From 113440fde52703e35e9c80e0c2229c91b02a3222 Mon Sep 17 00:00:00 2001 From: Jayanka Date: Sat, 19 May 2018 19:08:43 +0530 Subject: [PATCH 001/773] issue fixed #8258 - assign indices for all array inputs so that validation works properly --- lib/web/mage/validation.js | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/lib/web/mage/validation.js b/lib/web/mage/validation.js index 6258b3c627370..14be785714a7a 100644 --- a/lib/web/mage/validation.js +++ b/lib/web/mage/validation.js @@ -1865,6 +1865,7 @@ * @protected */ _create: function () { + this._workaroundForArrayInputs(); this.validate = this.element.validate(this.options); // ARIA (adding aria-required attribute) @@ -1877,6 +1878,27 @@ this._listenFormValidate(); }, + _workaroundForArrayInputs: function () { + /* Store original names for array inputs */ + var originalElements = []; + + /* For all array inputs, assign index so that validation is proper */ + this.element.find('[name$="[]"]').each(function (key, input) { + input = $(input); + var originalName = input.attr('name'); + var name = originalName.replace("[]", "["+key+"]"); + $(input).attr("name", name); + originalElements.push({element: $(input), name: originalName}); + }); + this.options.submitHandler = function (form) { + /* Before submitting the actual form, remove the previously assigned indices */ + originalElements.forEach(function (element) { + element.element.attr("name", element.name); + }); + form.submit(); + }; + }, + /** * Validation listening. * @protected From 874d77083329e66ea574ad32dc1d98184e45e71a Mon Sep 17 00:00:00 2001 From: Volodymyr Zaets Date: Tue, 12 Jun 2018 14:33:00 +0300 Subject: [PATCH 002/773] Update validation.js --- lib/web/mage/validation.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/lib/web/mage/validation.js b/lib/web/mage/validation.js index 14be785714a7a..5a5548e573482 100644 --- a/lib/web/mage/validation.js +++ b/lib/web/mage/validation.js @@ -1865,7 +1865,7 @@ * @protected */ _create: function () { - this._workaroundForArrayInputs(); + this.prepareArrayInputs(); this.validate = this.element.validate(this.options); // ARIA (adding aria-required attribute) @@ -1878,15 +1878,18 @@ this._listenFormValidate(); }, - _workaroundForArrayInputs: function () { + prepareArrayInputs: function () { /* Store original names for array inputs */ var originalElements = []; /* For all array inputs, assign index so that validation is proper */ this.element.find('[name$="[]"]').each(function (key, input) { + var originalName, + name; + input = $(input); - var originalName = input.attr('name'); - var name = originalName.replace("[]", "["+key+"]"); + originalName = input.attr('name'); + name = originalName.replace("[]", "["+key+"]"); $(input).attr("name", name); originalElements.push({element: $(input), name: originalName}); }); From 41e17938b6b3b6ea94e0cb0552727eb596341782 Mon Sep 17 00:00:00 2001 From: Bunyamin Date: Sun, 16 Sep 2018 09:43:41 -0300 Subject: [PATCH 003/773] Convert a PR for 2.2-develop into 2.3-develop --- .../Config/ConfigOptionsListConstants.php | 15 ++++ .../Setup/Controller/DatabaseCheck.php | 34 +++++++- .../Magento/Setup/Model/ConfigGenerator.php | 13 ++- .../Magento/Setup/Model/ConfigOptionsList.php | 50 ++++++++++- .../Model/ConfigOptionsList/DriverOptions.php | 38 ++++++++ setup/src/Magento/Setup/Model/Installer.php | 30 ++++++- .../Setup/Model/RequestDataConverter.php | 8 ++ .../Test/Unit/Model/ConfigGeneratorTest.php | 12 +++ .../Test/Unit/Model/ConfigOptionsListTest.php | 13 ++- .../Test/Unit/Module/ConfigGeneratorTest.php | 7 ++ .../Validator/AdminCredentialsValidator.php | 15 +++- .../Magento/Setup/Validator/DbValidator.php | 23 +++++ setup/view/magento/setup/add-database.phtml | 87 +++++++++++++++++++ 13 files changed, 333 insertions(+), 12 deletions(-) create mode 100644 setup/src/Magento/Setup/Model/ConfigOptionsList/DriverOptions.php diff --git a/lib/internal/Magento/Framework/Config/ConfigOptionsListConstants.php b/lib/internal/Magento/Framework/Config/ConfigOptionsListConstants.php index 52e7137fa3ddf..ee222e93f45cf 100644 --- a/lib/internal/Magento/Framework/Config/ConfigOptionsListConstants.php +++ b/lib/internal/Magento/Framework/Config/ConfigOptionsListConstants.php @@ -19,6 +19,7 @@ class ConfigOptionsListConstants const CONFIG_PATH_CRYPT_KEY = 'crypt/key'; const CONFIG_PATH_SESSION_SAVE = 'session/save'; const CONFIG_PATH_RESOURCE_DEFAULT_SETUP = 'resource/default_setup/connection'; + const CONFIG_PATH_DB_CONNECTION_DEFAULT_DRIVER_OPTIONS = 'db/connection/default/driver_options'; const CONFIG_PATH_DB_CONNECTION_DEFAULT = 'db/connection/default'; const CONFIG_PATH_DB_CONNECTIONS = 'db/connection'; const CONFIG_PATH_DB_PREFIX = 'db/table_prefix'; @@ -62,6 +63,10 @@ class ConfigOptionsListConstants const INPUT_KEY_DB_MODEL = 'db-model'; const INPUT_KEY_DB_INIT_STATEMENTS = 'db-init-statements'; const INPUT_KEY_DB_ENGINE = 'db-engine'; + const INPUT_KEY_DB_SSL_KEY = 'db-ssl-key'; + const INPUT_KEY_DB_SSL_CERT = 'db-ssl-cert'; + const INPUT_KEY_DB_SSL_CA = 'db-ssl-ca'; + const INPUT_KEY_DB_SSL_VERIFY = 'db-ssl-verify'; const INPUT_KEY_RESOURCE = 'resource'; const INPUT_KEY_SKIP_DB_VALIDATION = 'skip-db-validation'; const INPUT_KEY_CACHE_HOSTS = 'http-cache-hosts'; @@ -102,6 +107,16 @@ class ConfigOptionsListConstants const KEY_MODEL = 'model'; const KEY_INIT_STATEMENTS = 'initStatements'; const KEY_ACTIVE = 'active'; + const KEY_DRIVER_OPTIONS = 'driver_options'; + /**#@-*/ + + /**#@+ + * Array keys for database driver options configurations + */ + const KEY_MYSQL_SSL_KEY = \PDO::MYSQL_ATTR_SSL_KEY; + const KEY_MYSQL_SSL_CERT = \PDO::MYSQL_ATTR_SSL_CERT; + const KEY_MYSQL_SSL_CA = \PDO::MYSQL_ATTR_SSL_CA; + const KEY_MYSQL_SSL_VERIFY = \PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT; /**#@-*/ /** diff --git a/setup/src/Magento/Setup/Controller/DatabaseCheck.php b/setup/src/Magento/Setup/Controller/DatabaseCheck.php index ace9ef3294eab..d1978e536dfcb 100644 --- a/setup/src/Magento/Setup/Controller/DatabaseCheck.php +++ b/setup/src/Magento/Setup/Controller/DatabaseCheck.php @@ -5,6 +5,7 @@ */ namespace Magento\Setup\Controller; +use Magento\Framework\Config\ConfigOptionsListConstants; use Magento\Setup\Validator\DbValidator; use Zend\Json\Json; use Zend\Mvc\Controller\AbstractActionController; @@ -37,7 +38,25 @@ public function indexAction() try { $params = Json::decode($this->getRequest()->getContent(), Json::TYPE_ARRAY); $password = isset($params['password']) ? $params['password'] : ''; - $this->dbValidator->checkDatabaseConnection($params['name'], $params['host'], $params['user'], $password); + $driverOptions = []; + if ($this->isDriverOptionsGiven($params)) { + if (empty($params['driverOptionsSslVerify'])) { + $params['driverOptionsSslVerify'] = 0; + } + $driverOptions = [ + ConfigOptionsListConstants::KEY_MYSQL_SSL_KEY => $params['driverOptionsSslKey'], + ConfigOptionsListConstants::KEY_MYSQL_SSL_CERT => $params['driverOptionsSslCert'], + ConfigOptionsListConstants::KEY_MYSQL_SSL_CA => $params['driverOptionsSslCa'], + ConfigOptionsListConstants::KEY_MYSQL_SSL_VERIFY => (int) $params['driverOptionsSslVerify'], + ]; + } + $this->dbValidator->checkDatabaseConnectionWithDriverOptions( + $params['name'], + $params['host'], + $params['user'], + $password, + $driverOptions + ); $tablePrefix = isset($params['tablePrefix']) ? $params['tablePrefix'] : ''; $this->dbValidator->checkDatabaseTablePrefix($tablePrefix); return new JsonModel(['success' => true]); @@ -45,4 +64,17 @@ public function indexAction() return new JsonModel(['success' => false, 'error' => $e->getMessage()]); } } + + /** + * @param array $params + * @return boolean + */ + private function isDriverOptionsGiven($params) + { + return !( + empty($params['driverOptionsSslKey']) || + empty($params['driverOptionsSslCert']) || + empty($params['driverOptionsSslCa']) + ); + } } diff --git a/setup/src/Magento/Setup/Model/ConfigGenerator.php b/setup/src/Magento/Setup/Model/ConfigGenerator.php index 7e5b0c162a393..88468c20c5a70 100644 --- a/setup/src/Magento/Setup/Model/ConfigGenerator.php +++ b/setup/src/Magento/Setup/Model/ConfigGenerator.php @@ -14,6 +14,7 @@ use Magento\Framework\Config\ConfigOptionsListConstants; use Magento\Framework\App\State; use Magento\Framework\Math\Random; +use Magento\Setup\Model\ConfigOptionsList\DriverOptions; /** * Creates deployment config data based on user input array @@ -61,6 +62,11 @@ class ConfigGenerator */ private $cryptKeyGenerator; + /** + * @var DriverOptions + */ + private $driverOptions; + /** * Constructor * @@ -73,12 +79,14 @@ public function __construct( Random $random, DeploymentConfig $deploymentConfig, ConfigDataFactory $configDataFactory = null, - CryptKeyGeneratorInterface $cryptKeyGenerator = null + CryptKeyGeneratorInterface $cryptKeyGenerator = null, + DriverOptions $driverOptions = null ) { $this->random = $random; $this->deploymentConfig = $deploymentConfig; $this->configDataFactory = $configDataFactory ?? ObjectManager::getInstance()->get(ConfigDataFactory::class); $this->cryptKeyGenerator = $cryptKeyGenerator ?? ObjectManager::getInstance()->get(CryptKeyGenerator::class); + $this->driverOptions = $driverOptions ?? ObjectManager::getInstance()->get(DriverOptions::class); } /** @@ -179,6 +187,9 @@ public function createDbConfig(array $data) $configData->set($dbConnectionPrefix . ConfigOptionsListConstants::KEY_ACTIVE, '1'); } + $driverOptions = $this->driverOptions->getDriverOptions($data); + $configData->set($dbConnectionPrefix . ConfigOptionsListConstants::KEY_DRIVER_OPTIONS, $driverOptions); + return $configData; } diff --git a/setup/src/Magento/Setup/Model/ConfigOptionsList.php b/setup/src/Magento/Setup/Model/ConfigOptionsList.php index fa79139e73313..e92a71cdea2c8 100644 --- a/setup/src/Magento/Setup/Model/ConfigOptionsList.php +++ b/setup/src/Magento/Setup/Model/ConfigOptionsList.php @@ -12,6 +12,7 @@ use Magento\Framework\Setup\Option\FlagConfigOption; use Magento\Framework\Setup\Option\SelectConfigOption; use Magento\Framework\Setup\Option\TextConfigOption; +use Magento\Setup\Model\ConfigOptionsList\DriverOptions; use Magento\Setup\Validator\DbValidator; /** @@ -47,19 +48,28 @@ class ConfigOptionsList implements ConfigOptionsListInterface \Magento\Setup\Model\ConfigOptionsList\PageCache::class ]; + /** + * @var DriverOptions + */ + private $driverOptions; + /** * Constructor * * @param ConfigGenerator $configGenerator * @param DbValidator $dbValidator */ - public function __construct(ConfigGenerator $configGenerator, DbValidator $dbValidator) - { + public function __construct( + ConfigGenerator $configGenerator, + DbValidator $dbValidator, + DriverOptions $driverOptions = null + ) { $this->configGenerator = $configGenerator; $this->dbValidator = $dbValidator; foreach ($this->configOptionsListClasses as $className) { $this->configOptionsCollection[] = \Magento\Framework\App\ObjectManager::getInstance()->get($className); } + $this->driverOptions = $driverOptions ?? \Magento\Framework\App\ObjectManager::getInstance()->get(DriverOptions::class); } /** @@ -150,6 +160,36 @@ public function getOptions() ConfigOptionsListConstants::CONFIG_PATH_CACHE_HOSTS, 'http Cache hosts' ), + new TextConfigOption( + ConfigOptionsListConstants::INPUT_KEY_DB_SSL_KEY, + TextConfigOption::FRONTEND_WIZARD_TEXT, + ConfigOptionsListConstants::CONFIG_PATH_DB_CONNECTION_DEFAULT_DRIVER_OPTIONS . + '/' . ConfigOptionsListConstants::KEY_MYSQL_SSL_KEY, + 'Full path of client key file in order to establish db connection through SSL', + null + ), + new TextConfigOption( + ConfigOptionsListConstants::INPUT_KEY_DB_SSL_CERT, + TextConfigOption::FRONTEND_WIZARD_TEXT, + ConfigOptionsListConstants::CONFIG_PATH_DB_CONNECTION_DEFAULT_DRIVER_OPTIONS . + '/' . ConfigOptionsListConstants::KEY_MYSQL_SSL_CERT, + 'Full path of client certificate file in order to establish db connection through SSL', + null + ), + new TextConfigOption( + ConfigOptionsListConstants::INPUT_KEY_DB_SSL_CA, + TextConfigOption::FRONTEND_WIZARD_TEXT, + ConfigOptionsListConstants::CONFIG_PATH_DB_CONNECTION_DEFAULT_DRIVER_OPTIONS . + '/' . ConfigOptionsListConstants::KEY_MYSQL_SSL_CA, + 'Full path of server certificate file in order to establish db connection through SSL', + null + ), + new FlagConfigOption( + ConfigOptionsListConstants::INPUT_KEY_DB_SSL_VERIFY, + ConfigOptionsListConstants::CONFIG_PATH_DB_CONNECTION_DEFAULT_DRIVER_OPTIONS . + '/' . ConfigOptionsListConstants::KEY_MYSQL_SSL_VERIFY, + 'Verify server certification' + ), ]; foreach ($this->configOptionsCollection as $configOptionsList) { @@ -334,12 +374,14 @@ private function validateDbSettings(array $options, DeploymentConfig $deployment ) { try { $options = $this->getDbSettings($options, $deploymentConfig); + $driverOptions = $this->driverOptions->getDriverOptions($options); - $this->dbValidator->checkDatabaseConnection( + $this->dbValidator->checkDatabaseConnectionWithDriverOptions( $options[ConfigOptionsListConstants::INPUT_KEY_DB_NAME], $options[ConfigOptionsListConstants::INPUT_KEY_DB_HOST], $options[ConfigOptionsListConstants::INPUT_KEY_DB_USER], - $options[ConfigOptionsListConstants::INPUT_KEY_DB_PASSWORD] + $options[ConfigOptionsListConstants::INPUT_KEY_DB_PASSWORD], + $driverOptions ); } catch (\Exception $exception) { $errors[] = $exception->getMessage(); diff --git a/setup/src/Magento/Setup/Model/ConfigOptionsList/DriverOptions.php b/setup/src/Magento/Setup/Model/ConfigOptionsList/DriverOptions.php new file mode 100644 index 0000000000000..f9dfa5ea65c33 --- /dev/null +++ b/setup/src/Magento/Setup/Model/ConfigOptionsList/DriverOptions.php @@ -0,0 +1,38 @@ + ConfigOptionsListConstants::INPUT_KEY_DB_SSL_KEY, + ConfigOptionsListConstants::KEY_MYSQL_SSL_CERT => ConfigOptionsListConstants::INPUT_KEY_DB_SSL_CERT, + ConfigOptionsListConstants::KEY_MYSQL_SSL_CA => ConfigOptionsListConstants::INPUT_KEY_DB_SSL_CA, + ConfigOptionsListConstants::KEY_MYSQL_SSL_VERIFY => ConfigOptionsListConstants::INPUT_KEY_DB_SSL_VERIFY + ]; + $driverOptions = []; + foreach ($driverOptionKeys as $configKey => $driverOptionKey) { + if ($this->optionExists($options, $driverOptionKey)) { + $driverOptions[$configKey] = $options[$driverOptionKey]; + } + } + return $driverOptions; + } + + /** + * @param array $options + * @param string $driverOptionKey + * @return bool + */ + private function optionExists($options, $driverOptionKey) + { + return $options[$driverOptionKey] === false || !empty($options[$driverOptionKey]); + } +} diff --git a/setup/src/Magento/Setup/Model/Installer.php b/setup/src/Magento/Setup/Model/Installer.php index a7dc4dd1e6099..252f7ba95f18c 100644 --- a/setup/src/Magento/Setup/Model/Installer.php +++ b/setup/src/Magento/Setup/Model/Installer.php @@ -1334,7 +1334,32 @@ private function deleteDeploymentConfig() */ private function assertDbAccessible() { - $this->dbValidator->checkDatabaseConnection( + $driverOptionKeys = [ + ConfigOptionsListConstants::KEY_MYSQL_SSL_KEY => + ConfigOptionsListConstants::CONFIG_PATH_DB_CONNECTION_DEFAULT_DRIVER_OPTIONS . '/' . + ConfigOptionsListConstants::KEY_MYSQL_SSL_KEY, + + ConfigOptionsListConstants::KEY_MYSQL_SSL_CERT => + ConfigOptionsListConstants::CONFIG_PATH_DB_CONNECTION_DEFAULT_DRIVER_OPTIONS . '/' . + ConfigOptionsListConstants::KEY_MYSQL_SSL_CERT, + + ConfigOptionsListConstants::KEY_MYSQL_SSL_CA => + ConfigOptionsListConstants::CONFIG_PATH_DB_CONNECTION_DEFAULT_DRIVER_OPTIONS . '/' . + ConfigOptionsListConstants::KEY_MYSQL_SSL_CA, + + ConfigOptionsListConstants::KEY_MYSQL_SSL_VERIFY => + ConfigOptionsListConstants::CONFIG_PATH_DB_CONNECTION_DEFAULT_DRIVER_OPTIONS . '/' . + ConfigOptionsListConstants::KEY_MYSQL_SSL_VERIFY + ]; + $driverOptions = []; + foreach ($driverOptionKeys as $driverOptionKey => $driverOptionConfig) { + $config = $this->deploymentConfig->get($driverOptionConfig); + if ($config !== null) { + $driverOptions[$driverOptionKey] = $config; + } + } + + $this->dbValidator->checkDatabaseConnectionWithDriverOptions( $this->deploymentConfig->get( ConfigOptionsListConstants::CONFIG_PATH_DB_CONNECTION_DEFAULT . '/' . ConfigOptionsListConstants::KEY_NAME @@ -1350,7 +1375,8 @@ private function assertDbAccessible() $this->deploymentConfig->get( ConfigOptionsListConstants::CONFIG_PATH_DB_CONNECTION_DEFAULT . '/' . ConfigOptionsListConstants::KEY_PASSWORD - ) + ), + $driverOptions ); $prefix = $this->deploymentConfig->get( ConfigOptionsListConstants::CONFIG_PATH_DB_CONNECTION_DEFAULT . diff --git a/setup/src/Magento/Setup/Model/RequestDataConverter.php b/setup/src/Magento/Setup/Model/RequestDataConverter.php index 0ed5dc669c95f..4964dbe596d85 100644 --- a/setup/src/Magento/Setup/Model/RequestDataConverter.php +++ b/setup/src/Magento/Setup/Model/RequestDataConverter.php @@ -51,6 +51,14 @@ private function convertDeploymentConfigForm(array $source) isset($source['db']['tablePrefix']) ? $source['db']['tablePrefix'] : ''; $result[BackendConfigOptionsList::INPUT_KEY_BACKEND_FRONTNAME] = isset($source['config']['address']['admin']) ? $source['config']['address']['admin'] : ''; + $result[SetupConfigOptionsList::INPUT_KEY_DB_SSL_KEY] = isset($source['db']['driverOptionsSslKey']) + ? $source['db']['driverOptionsSslKey'] : ''; + $result[SetupConfigOptionsList::INPUT_KEY_DB_SSL_CERT] = isset($source['db']['driverOptionsSslCert']) + ? $source['db']['driverOptionsSslCert'] : ''; + $result[SetupConfigOptionsList::INPUT_KEY_DB_SSL_CA] = isset($source['db']['driverOptionsSslCa']) + ? $source['db']['driverOptionsSslCa'] : ''; + $result[SetupConfigOptionsList::INPUT_KEY_DB_SSL_VERIFY] = isset($source['db']['driverOptionsSslVerify']) + ? $source['db']['driverOptionsSslVerify'] : ''; $result[SetupConfigOptionsList::INPUT_KEY_ENCRYPTION_KEY] = isset($source['config']['encrypt']['key']) ? $source['config']['encrypt']['key'] : null; $result[SetupConfigOptionsList::INPUT_KEY_SESSION_SAVE] = isset($source['config']['sessionSave']['type']) diff --git a/setup/src/Magento/Setup/Test/Unit/Model/ConfigGeneratorTest.php b/setup/src/Magento/Setup/Test/Unit/Model/ConfigGeneratorTest.php index be68be8bd8c2d..22de958070b8f 100644 --- a/setup/src/Magento/Setup/Test/Unit/Model/ConfigGeneratorTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Model/ConfigGeneratorTest.php @@ -11,6 +11,7 @@ use Magento\Framework\Config\Data\ConfigData; use Magento\Framework\Config\Data\ConfigDataFactory; use Magento\Setup\Model\ConfigGenerator; +use Magento\Setup\Model\ConfigOptionsList\DriverOptions; class ConfigGeneratorTest extends \PHPUnit\Framework\TestCase { @@ -29,6 +30,11 @@ class ConfigGeneratorTest extends \PHPUnit\Framework\TestCase */ private $configDataMock; + /** + * @var DriverOptions + */ + private $driverOptionsMock; + public function setUp() { $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); @@ -50,11 +56,17 @@ public function setUp() $configDataFactoryMock->method('create') ->willReturn($this->configDataMock); + $this->driverOptionsMock = $this->getMockBuilder(DriverOptions::class) + ->disableOriginalConstructor() + ->setMethods(['getDriverOptions']) + ->getMock(); + $this->model = $objectManager->getObject( ConfigGenerator::class, [ 'deploymentConfig' => $this->deploymentConfigMock, 'configDataFactory' => $configDataFactoryMock, + 'driverOptions' => $this->driverOptionsMock, ] ); } diff --git a/setup/src/Magento/Setup/Test/Unit/Model/ConfigOptionsListTest.php b/setup/src/Magento/Setup/Test/Unit/Model/ConfigOptionsListTest.php index 1bb60517d5e67..27b7945410add 100644 --- a/setup/src/Magento/Setup/Test/Unit/Model/ConfigOptionsListTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Model/ConfigOptionsListTest.php @@ -33,12 +33,18 @@ class ConfigOptionsListTest extends \PHPUnit\Framework\TestCase */ private $dbValidator; + /** + * @var ConfigOptionsList\DriverOptions + */ + private $driverOptionsMock; + protected function setUp() { $this->generator = $this->createMock(\Magento\Setup\Model\ConfigGenerator::class); $this->deploymentConfig = $this->createMock(\Magento\Framework\App\DeploymentConfig::class); $this->dbValidator = $this->createMock(\Magento\Setup\Validator\DbValidator::class); - $this->object = new ConfigOptionsList($this->generator, $this->dbValidator); + $this->driverOptionsMock = $this->createMock(ConfigOptionsList\DriverOptions::class); + $this->object = new ConfigOptionsList($this->generator, $this->dbValidator, $this->driverOptionsMock); } public function testGetOptions() @@ -155,7 +161,10 @@ private function prepareValidationMocks() ->disableOriginalConstructor() ->getMock(); $this->dbValidator->expects($this->once())->method('checkDatabaseTablePrefix')->willReturn($configDataMock); - $this->dbValidator->expects($this->once())->method('checkDatabaseConnection')->willReturn($configDataMock); + $this->dbValidator + ->expects($this->once()) + ->method('checkDatabaseConnectionWithDriverOptions') + ->willReturn($configDataMock); } /** diff --git a/setup/src/Magento/Setup/Test/Unit/Module/ConfigGeneratorTest.php b/setup/src/Magento/Setup/Test/Unit/Module/ConfigGeneratorTest.php index 65fe4a5f47711..7e3bb535173b7 100644 --- a/setup/src/Magento/Setup/Test/Unit/Module/ConfigGeneratorTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Module/ConfigGeneratorTest.php @@ -15,6 +15,7 @@ use Magento\Framework\Config\ConfigOptionsListConstants; use Magento\Setup\Model\CryptKeyGenerator; use PHPUnit\Framework\TestCase; +use Magento\Setup\Model\ConfigOptionsList\DriverOptions; class ConfigGeneratorTest extends TestCase { @@ -44,9 +45,15 @@ protected function setUp() $configDataFactoryMock = (new ObjectManager($this)) ->getObject(ConfigDataFactory::class, ['objectManager' => $objectManagerMock]); + $driverOptions = $this->getMockBuilder(DriverOptions::class) + ->disableOriginalConstructor() + ->setMethods(['getDriverOptions']) + ->getMock(); + $this->configGeneratorObject = new ConfigGenerator( $randomMock, $deployConfig, + $driverOptions, $configDataFactoryMock, $cryptKeyGenerator ); diff --git a/setup/src/Magento/Setup/Validator/AdminCredentialsValidator.php b/setup/src/Magento/Setup/Validator/AdminCredentialsValidator.php index df061de2adb9a..90b4a4c219ada 100644 --- a/setup/src/Magento/Setup/Validator/AdminCredentialsValidator.php +++ b/setup/src/Magento/Setup/Validator/AdminCredentialsValidator.php @@ -8,6 +8,7 @@ use Magento\Framework\Config\ConfigOptionsListConstants as ConfigOption; use Magento\Setup\Model\AdminAccount; use Magento\Setup\Model\Installer; +use Magento\Setup\Model\ConfigOptionsList\DriverOptions; /** * Admin user credentials validator @@ -29,6 +30,11 @@ class AdminCredentialsValidator */ private $setupFactory; + /** + * @var DriverOptions + */ + private $driverOptions; + /** * Initialize dependencies. * @@ -39,11 +45,13 @@ class AdminCredentialsValidator public function __construct( \Magento\Setup\Model\AdminAccountFactory $adminAccountFactory, \Magento\Setup\Module\ConnectionFactory $connectionFactory, - \Magento\Setup\Module\SetupFactory $setupFactory + \Magento\Setup\Module\SetupFactory $setupFactory, + DriverOptions $driverOptions ) { $this->connectionFactory = $connectionFactory; $this->adminAccountFactory = $adminAccountFactory; $this->setupFactory = $setupFactory; + $this->driverOptions = $driverOptions; } /** @@ -55,12 +63,15 @@ public function __construct( */ public function validate(array $data) { + $driverOptions = $this->driverOptions->getDriverOptions($data); + $dbConnection = $this->connectionFactory->create([ ConfigOption::KEY_NAME => $data[ConfigOption::INPUT_KEY_DB_NAME], ConfigOption::KEY_HOST => $data[ConfigOption::INPUT_KEY_DB_HOST], ConfigOption::KEY_USER => $data[ConfigOption::INPUT_KEY_DB_USER], ConfigOption::KEY_PASSWORD => $data[ConfigOption::INPUT_KEY_DB_PASSWORD], - ConfigOption::KEY_PREFIX => $data[ConfigOption::INPUT_KEY_DB_PREFIX] + ConfigOption::KEY_PREFIX => $data[ConfigOption::INPUT_KEY_DB_PREFIX], + ConfigOption::KEY_DRIVER_OPTIONS => $driverOptions ]); $adminAccount = $this->adminAccountFactory->create( diff --git a/setup/src/Magento/Setup/Validator/DbValidator.php b/setup/src/Magento/Setup/Validator/DbValidator.php index 1eae39160ff8e..af0a9714f2204 100644 --- a/setup/src/Magento/Setup/Validator/DbValidator.php +++ b/setup/src/Magento/Setup/Validator/DbValidator.php @@ -74,9 +74,31 @@ public function checkDatabaseTablePrefix($prefix) * @param string $dbPass * @return boolean * @throws \Magento\Setup\Exception + * @deprecated */ public function checkDatabaseConnection($dbName, $dbHost, $dbUser, $dbPass = '') { + return $this->checkDatabaseConnectionWithDriverOptions($dbName, $dbHost, $dbUser, $dbPass, []); + } + + /** + * Checks Database Connection with Driver Options + * + * @param string $dbName + * @param string $dbHost + * @param string $dbUser + * @param string $dbPass + * @param array $driverOptions + * @return boolean + * @throws \Magento\Setup\Exception + */ + public function checkDatabaseConnectionWithDriverOptions( + $dbName, + $dbHost, + $dbUser, + $dbPass = '', + $driverOptions = [] + ) { // establish connection to information_schema view to retrieve information about user and table privileges $connection = $this->connectionFactory->create([ ConfigOptionsListConstants::KEY_NAME => 'information_schema', @@ -84,6 +106,7 @@ public function checkDatabaseConnection($dbName, $dbHost, $dbUser, $dbPass = '') ConfigOptionsListConstants::KEY_USER => $dbUser, ConfigOptionsListConstants::KEY_PASSWORD => $dbPass, ConfigOptionsListConstants::KEY_ACTIVE => true, + ConfigOptionsListConstants::KEY_DRIVER_OPTIONS => $driverOptions, ]); if (!$connection) { diff --git a/setup/view/magento/setup/add-database.phtml b/setup/view/magento/setup/add-database.phtml index 18259c65fcf88..c858d92cfef55 100644 --- a/setup/view/magento/setup/add-database.phtml +++ b/setup/view/magento/setup/add-database.phtml @@ -476,6 +476,93 @@ */ ?> +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+ + +
+
+
From def50d54c2246e3ae265554dc581e39ac8fcd004 Mon Sep 17 00:00:00 2001 From: Bunyamin Date: Sun, 16 Sep 2018 11:26:28 -0300 Subject: [PATCH 004/773] Fix failing unit test --- .../Magento/Setup/Test/Unit/Module/ConfigGeneratorTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup/src/Magento/Setup/Test/Unit/Module/ConfigGeneratorTest.php b/setup/src/Magento/Setup/Test/Unit/Module/ConfigGeneratorTest.php index 7e3bb535173b7..15e334909f50a 100644 --- a/setup/src/Magento/Setup/Test/Unit/Module/ConfigGeneratorTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Module/ConfigGeneratorTest.php @@ -53,9 +53,9 @@ protected function setUp() $this->configGeneratorObject = new ConfigGenerator( $randomMock, $deployConfig, - $driverOptions, $configDataFactoryMock, - $cryptKeyGenerator + $cryptKeyGenerator, + $driverOptions ); } From 7c7cc9bb16ecf5deaeec3b334f0443b058432133 Mon Sep 17 00:00:00 2001 From: Bunyamin Date: Sun, 16 Sep 2018 14:51:07 -0300 Subject: [PATCH 005/773] Convert boolean typehints into bool --- setup/src/Magento/Setup/Controller/DatabaseCheck.php | 2 +- setup/src/Magento/Setup/Validator/DbValidator.php | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/setup/src/Magento/Setup/Controller/DatabaseCheck.php b/setup/src/Magento/Setup/Controller/DatabaseCheck.php index d1978e536dfcb..1d83a13242762 100644 --- a/setup/src/Magento/Setup/Controller/DatabaseCheck.php +++ b/setup/src/Magento/Setup/Controller/DatabaseCheck.php @@ -67,7 +67,7 @@ public function indexAction() /** * @param array $params - * @return boolean + * @return bool */ private function isDriverOptionsGiven($params) { diff --git a/setup/src/Magento/Setup/Validator/DbValidator.php b/setup/src/Magento/Setup/Validator/DbValidator.php index af0a9714f2204..b42abb2b13f8a 100644 --- a/setup/src/Magento/Setup/Validator/DbValidator.php +++ b/setup/src/Magento/Setup/Validator/DbValidator.php @@ -42,7 +42,7 @@ public function __construct(ConnectionFactory $connectionFactory) * Check if database table prefix is valid * * @param string $prefix - * @return boolean + * @return bool * @throws \InvalidArgumentException */ public function checkDatabaseTablePrefix($prefix) @@ -72,7 +72,7 @@ public function checkDatabaseTablePrefix($prefix) * @param string $dbHost * @param string $dbUser * @param string $dbPass - * @return boolean + * @return bool * @throws \Magento\Setup\Exception * @deprecated */ @@ -89,7 +89,7 @@ public function checkDatabaseConnection($dbName, $dbHost, $dbUser, $dbPass = '') * @param string $dbUser * @param string $dbPass * @param array $driverOptions - * @return boolean + * @return bool * @throws \Magento\Setup\Exception */ public function checkDatabaseConnectionWithDriverOptions( From ddad680b699418ed9941359df7540eb8120abc79 Mon Sep 17 00:00:00 2001 From: Bunyamin Date: Mon, 17 Sep 2018 11:06:45 -0300 Subject: [PATCH 006/773] Annotation is fixed --- setup/src/Magento/Setup/Model/ConfigGenerator.php | 1 + 1 file changed, 1 insertion(+) diff --git a/setup/src/Magento/Setup/Model/ConfigGenerator.php b/setup/src/Magento/Setup/Model/ConfigGenerator.php index 88468c20c5a70..05947146ad97a 100644 --- a/setup/src/Magento/Setup/Model/ConfigGenerator.php +++ b/setup/src/Magento/Setup/Model/ConfigGenerator.php @@ -74,6 +74,7 @@ class ConfigGenerator * @param DeploymentConfig $deploymentConfig * @param ConfigDataFactory|null $configDataFactory * @param CryptKeyGeneratorInterface|null $cryptKeyGenerator + * @param DriverOptions|null $driverOptions */ public function __construct( Random $random, From fa659d20695b9cbfe7b4f4ab33d1ee35673baa55 Mon Sep 17 00:00:00 2001 From: Bunyamin Date: Mon, 17 Sep 2018 11:07:38 -0300 Subject: [PATCH 007/773] Annotation is fixed for ConfigOptionsList.php --- setup/src/Magento/Setup/Model/ConfigOptionsList.php | 1 + 1 file changed, 1 insertion(+) diff --git a/setup/src/Magento/Setup/Model/ConfigOptionsList.php b/setup/src/Magento/Setup/Model/ConfigOptionsList.php index e92a71cdea2c8..f184b86326282 100644 --- a/setup/src/Magento/Setup/Model/ConfigOptionsList.php +++ b/setup/src/Magento/Setup/Model/ConfigOptionsList.php @@ -58,6 +58,7 @@ class ConfigOptionsList implements ConfigOptionsListInterface * * @param ConfigGenerator $configGenerator * @param DbValidator $dbValidator + * @param DriverOptions|null $driverOptions */ public function __construct( ConfigGenerator $configGenerator, From 968a59ccf2a079d21b2c61fee008132cdc398b01 Mon Sep 17 00:00:00 2001 From: Bunyamin Date: Mon, 17 Sep 2018 11:10:38 -0300 Subject: [PATCH 008/773] Adding $driverOptions parameter into annotations --- setup/src/Magento/Setup/Validator/AdminCredentialsValidator.php | 1 + 1 file changed, 1 insertion(+) diff --git a/setup/src/Magento/Setup/Validator/AdminCredentialsValidator.php b/setup/src/Magento/Setup/Validator/AdminCredentialsValidator.php index 90b4a4c219ada..ced1ff395396c 100644 --- a/setup/src/Magento/Setup/Validator/AdminCredentialsValidator.php +++ b/setup/src/Magento/Setup/Validator/AdminCredentialsValidator.php @@ -41,6 +41,7 @@ class AdminCredentialsValidator * @param \Magento\Setup\Model\AdminAccountFactory $adminAccountFactory * @param \Magento\Setup\Module\ConnectionFactory $connectionFactory * @param \Magento\Setup\Module\SetupFactory $setupFactory + * @param DriverOptions|null $driverOptions */ public function __construct( \Magento\Setup\Model\AdminAccountFactory $adminAccountFactory, From 84355a34d260f5720af626221cbbac36a6533b73 Mon Sep 17 00:00:00 2001 From: Jayanka Date: Wed, 19 Sep 2018 12:45:58 +0530 Subject: [PATCH 009/773] invalid quotes and doc-block resolved --- lib/web/mage/validation.js | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/lib/web/mage/validation.js b/lib/web/mage/validation.js index 5a5548e573482..9f0ccc3f2eba5 100644 --- a/lib/web/mage/validation.js +++ b/lib/web/mage/validation.js @@ -1865,7 +1865,7 @@ * @protected */ _create: function () { - this.prepareArrayInputs(); + this._prepareArrayInputs(); this.validate = this.element.validate(this.options); // ARIA (adding aria-required attribute) @@ -1878,7 +1878,12 @@ this._listenFormValidate(); }, - prepareArrayInputs: function () { + /** + * Validation creation. + * + * @protected + */ + _prepareArrayInputs: function () { /* Store original names for array inputs */ var originalElements = []; @@ -1889,12 +1894,19 @@ input = $(input); originalName = input.attr('name'); - name = originalName.replace("[]", "["+key+"]"); - $(input).attr("name", name); - originalElements.push({element: $(input), name: originalName}); + name = originalName.replace('[]', '[' + key + ']'); + $(input).attr('name', name); + originalElements.push({ + element: $(input), + name: originalName + }); }); + + /** + * Before submitting the actual form, remove the previously assigned indices + * @param form + */ this.options.submitHandler = function (form) { - /* Before submitting the actual form, remove the previously assigned indices */ originalElements.forEach(function (element) { element.element.attr("name", element.name); }); From d5c41b643b3b8d92a66da633a0fdb8a2312cbd86 Mon Sep 17 00:00:00 2001 From: Jayanka Date: Thu, 20 Sep 2018 10:21:44 +0530 Subject: [PATCH 010/773] param type given in doc block --- lib/web/mage/validation.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/lib/web/mage/validation.js b/lib/web/mage/validation.js index 9f0ccc3f2eba5..1a321a77125f9 100644 --- a/lib/web/mage/validation.js +++ b/lib/web/mage/validation.js @@ -1889,9 +1889,7 @@ /* For all array inputs, assign index so that validation is proper */ this.element.find('[name$="[]"]').each(function (key, input) { - var originalName, - name; - + var originalName, name; input = $(input); originalName = input.attr('name'); name = originalName.replace('[]', '[' + key + ']'); @@ -1904,11 +1902,11 @@ /** * Before submitting the actual form, remove the previously assigned indices - * @param form + * @param {Object} form */ this.options.submitHandler = function (form) { originalElements.forEach(function (element) { - element.element.attr("name", element.name); + element.element.attr('name', element.name); }); form.submit(); }; From 156ac1654294f7b0e24057cf10ce2e098b354c7f Mon Sep 17 00:00:00 2001 From: Jayanka Date: Thu, 20 Sep 2018 12:22:10 +0530 Subject: [PATCH 011/773] newline after var declaration --- lib/web/mage/validation.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/web/mage/validation.js b/lib/web/mage/validation.js index 1a321a77125f9..8d825a9ef2226 100644 --- a/lib/web/mage/validation.js +++ b/lib/web/mage/validation.js @@ -1890,6 +1890,7 @@ /* For all array inputs, assign index so that validation is proper */ this.element.find('[name$="[]"]').each(function (key, input) { var originalName, name; + input = $(input); originalName = input.attr('name'); name = originalName.replace('[]', '[' + key + ']'); From 5cfad033e00338456f6eed9da68e3632dfaeaad9 Mon Sep 17 00:00:00 2001 From: Eugene Shakhsuvarov Date: Mon, 1 Oct 2018 15:35:08 +0300 Subject: [PATCH 012/773] Update doc blocks --- .../Model/ConfigOptionsList/DriverOptions.php | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/setup/src/Magento/Setup/Model/ConfigOptionsList/DriverOptions.php b/setup/src/Magento/Setup/Model/ConfigOptionsList/DriverOptions.php index f9dfa5ea65c33..cb21fa76817e6 100644 --- a/setup/src/Magento/Setup/Model/ConfigOptionsList/DriverOptions.php +++ b/setup/src/Magento/Setup/Model/ConfigOptionsList/DriverOptions.php @@ -1,15 +1,26 @@ - ConfigOptionsListConstants::INPUT_KEY_DB_SSL_KEY, @@ -27,11 +38,13 @@ public function getDriverOptions($options) } /** + * Check if provided option exists. + * * @param array $options * @param string $driverOptionKey * @return bool */ - private function optionExists($options, $driverOptionKey) + private function optionExists(array $options, string $driverOptionKey): bool { return $options[$driverOptionKey] === false || !empty($options[$driverOptionKey]); } From 7c7760ba30ac87eabceee22a13b40c11c4bb60a0 Mon Sep 17 00:00:00 2001 From: Bunyamin Date: Mon, 8 Oct 2018 09:06:50 -0300 Subject: [PATCH 013/773] Fix missing @param --- .../src/Magento/Setup/Model/ConfigOptionsList/DriverOptions.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup/src/Magento/Setup/Model/ConfigOptionsList/DriverOptions.php b/setup/src/Magento/Setup/Model/ConfigOptionsList/DriverOptions.php index cb21fa76817e6..8ef9592e423de 100644 --- a/setup/src/Magento/Setup/Model/ConfigOptionsList/DriverOptions.php +++ b/setup/src/Magento/Setup/Model/ConfigOptionsList/DriverOptions.php @@ -17,7 +17,7 @@ class DriverOptions /** * Get driver options. * - * @params array $options + * @param array $options * @return array */ public function getDriverOptions(array $options): array From 6f19bf097b321356ffec4798f42d457c5f743256 Mon Sep 17 00:00:00 2001 From: Bunyamin Date: Mon, 8 Oct 2018 09:10:34 -0300 Subject: [PATCH 014/773] Fix code smell --- setup/src/Magento/Setup/Controller/DatabaseCheck.php | 5 +++++ setup/src/Magento/Setup/Model/ConfigOptionsList.php | 11 ++++++----- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/setup/src/Magento/Setup/Controller/DatabaseCheck.php b/setup/src/Magento/Setup/Controller/DatabaseCheck.php index 1d83a13242762..e1647aa6822c0 100644 --- a/setup/src/Magento/Setup/Controller/DatabaseCheck.php +++ b/setup/src/Magento/Setup/Controller/DatabaseCheck.php @@ -11,6 +11,9 @@ use Zend\Mvc\Controller\AbstractActionController; use Zend\View\Model\JsonModel; +/** + * Class DatabaseCheck + */ class DatabaseCheck extends AbstractActionController { /** @@ -66,6 +69,8 @@ public function indexAction() } /** + * Is Driver Options Given + * * @param array $params * @return bool */ diff --git a/setup/src/Magento/Setup/Model/ConfigOptionsList.php b/setup/src/Magento/Setup/Model/ConfigOptionsList.php index f184b86326282..67d6da6dd0989 100644 --- a/setup/src/Magento/Setup/Model/ConfigOptionsList.php +++ b/setup/src/Magento/Setup/Model/ConfigOptionsList.php @@ -65,16 +65,17 @@ public function __construct( DbValidator $dbValidator, DriverOptions $driverOptions = null ) { + $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); $this->configGenerator = $configGenerator; $this->dbValidator = $dbValidator; foreach ($this->configOptionsListClasses as $className) { - $this->configOptionsCollection[] = \Magento\Framework\App\ObjectManager::getInstance()->get($className); + $this->configOptionsCollection[] = $objectManager->get($className); } - $this->driverOptions = $driverOptions ?? \Magento\Framework\App\ObjectManager::getInstance()->get(DriverOptions::class); + $this->driverOptions = $driverOptions ?? $objectManager->get(DriverOptions::class); } /** - * {@inheritdoc} + * @inheritdoc * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ public function getOptions() @@ -201,7 +202,7 @@ public function getOptions() } /** - * {@inheritdoc} + * @inheritdoc */ public function createConfig(array $data, DeploymentConfig $deploymentConfig) { @@ -225,7 +226,7 @@ public function createConfig(array $data, DeploymentConfig $deploymentConfig) } /** - * {@inheritdoc} + * @inheritdoc */ public function validate(array $options, DeploymentConfig $deploymentConfig) { From d97af677ad0b602aa5f1bb697ef5360c6d324406 Mon Sep 17 00:00:00 2001 From: Sviatoslav Mankivskyi Date: Tue, 23 Oct 2018 13:53:46 -0500 Subject: [PATCH 015/773] Fix dockblock --- setup/src/Magento/Setup/Controller/DatabaseCheck.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup/src/Magento/Setup/Controller/DatabaseCheck.php b/setup/src/Magento/Setup/Controller/DatabaseCheck.php index e1647aa6822c0..4b88a8732d2c7 100644 --- a/setup/src/Magento/Setup/Controller/DatabaseCheck.php +++ b/setup/src/Magento/Setup/Controller/DatabaseCheck.php @@ -70,7 +70,7 @@ public function indexAction() /** * Is Driver Options Given - * + * * @param array $params * @return bool */ From 6cd243d96bc1ea2116bd9cd28aae4c83f828480e Mon Sep 17 00:00:00 2001 From: Sviatoslav Mankivskyi Date: Tue, 23 Oct 2018 13:55:12 -0500 Subject: [PATCH 016/773] Fix docblock --- setup/src/Magento/Setup/Model/ConfigGenerator.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/setup/src/Magento/Setup/Model/ConfigGenerator.php b/setup/src/Magento/Setup/Model/ConfigGenerator.php index 05947146ad97a..88421797e59df 100644 --- a/setup/src/Magento/Setup/Model/ConfigGenerator.php +++ b/setup/src/Magento/Setup/Model/ConfigGenerator.php @@ -18,7 +18,8 @@ /** * Creates deployment config data based on user input array - * this class introduced to break down Magento\Setup\Model\ConfigOptionsList::createConfig + * + * This class introduced to break down {@see Magento\Setup\Model\ConfigOptionsList::createConfig} */ class ConfigGenerator { @@ -92,6 +93,7 @@ public function __construct( /** * Creates encryption key config data + * * @param array $data * @return ConfigData */ From 8fc5f7511b91af291d0294337378b02fbe6a00d2 Mon Sep 17 00:00:00 2001 From: roman Date: Mon, 31 Dec 2018 15:48:11 +0200 Subject: [PATCH 017/773] MC-5951: Incorrect rendering --- .../Customer/Ui/Component/Listing/Column/GroupActions.php | 7 +++++-- js.js | 0 2 files changed, 5 insertions(+), 2 deletions(-) create mode 100644 js.js diff --git a/app/code/Magento/Customer/Ui/Component/Listing/Column/GroupActions.php b/app/code/Magento/Customer/Ui/Component/Listing/Column/GroupActions.php index 00c5f99fab46c..6870bd1136d10 100644 --- a/app/code/Magento/Customer/Ui/Component/Listing/Column/GroupActions.php +++ b/app/code/Magento/Customer/Ui/Component/Listing/Column/GroupActions.php @@ -96,8 +96,11 @@ public function prepareDataSource(array $dataSource) ), 'label' => __('Delete'), 'confirm' => [ - 'title' => __('Delete %1', $title), - 'message' => __('Are you sure you want to delete a %1 record?', $title) + 'title' => __('Delete %1', $this->escaper->escapeJs($title)), + 'message' => __( + 'Are you sure you want to delete a %1 record?', + $this->escaper->escapeJs($title) + ) ], 'post' => true ]; diff --git a/js.js b/js.js new file mode 100644 index 0000000000000..e69de29bb2d1d From fced7ed5ffaa0cb25526d25eaae0d569ff18bd50 Mon Sep 17 00:00:00 2001 From: roman Date: Thu, 3 Jan 2019 11:00:20 +0200 Subject: [PATCH 018/773] MC-5951: Incorrect rendering --- js.js | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 js.js diff --git a/js.js b/js.js deleted file mode 100644 index e69de29bb2d1d..0000000000000 From e33bc20c5fd32294f700c9d359d469901b82ee33 Mon Sep 17 00:00:00 2001 From: roman Date: Tue, 15 Jan 2019 18:04:46 +0200 Subject: [PATCH 019/773] MC-5951: Incorrect rendering --- .../Block/Adminhtml/Group/Edit/Form.php | 2 +- .../Controller/Adminhtml/Group/Save.php | 23 ++++++++++++++++++- .../Model/ResourceModel/GroupRepository.php | 12 +++++++--- 3 files changed, 32 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/Customer/Block/Adminhtml/Group/Edit/Form.php b/app/code/Magento/Customer/Block/Adminhtml/Group/Edit/Form.php index 1a57ab7c7b6a5..e87a08ebc10c1 100644 --- a/app/code/Magento/Customer/Block/Adminhtml/Group/Edit/Form.php +++ b/app/code/Magento/Customer/Block/Adminhtml/Group/Edit/Form.php @@ -84,7 +84,7 @@ protected function _prepareLayout() $fieldset = $form->addFieldset('base_fieldset', ['legend' => __('Group Information')]); $validateClass = sprintf( - 'required-entry validate-length maximum-length-%d', + 'required-entry validate-data validate-length maximum-length-%d', \Magento\Customer\Model\GroupManagement::GROUP_CODE_MAX_LENGTH ); $name = $fieldset->addField( diff --git a/app/code/Magento/Customer/Controller/Adminhtml/Group/Save.php b/app/code/Magento/Customer/Controller/Adminhtml/Group/Save.php index 7549315f9ffcd..57e4f11ba280b 100644 --- a/app/code/Magento/Customer/Controller/Adminhtml/Group/Save.php +++ b/app/code/Magento/Customer/Controller/Adminhtml/Group/Save.php @@ -1,6 +1,5 @@ resultRedirectFactory->create(); try { $customerGroupCode = (string)$this->getRequest()->getParam('code'); + $this->validateGroupCode($customerGroupCode); + if ($id !== null) { $customerGroup = $this->groupRepository->getById((int)$id); $customerGroupCode = $customerGroupCode ?: $customerGroup->getCode(); @@ -109,4 +114,20 @@ public function execute() return $this->resultForwardFactory->create()->forward('new'); } } + + /** + * Validates group code given in POST param + * + * @param string $groupCode + * @return bool + * @throws LocalizedException + * @throws \Zend_Validate_Exception + */ + private function validateGroupCode(string $groupCode): bool + { + if (!\Zend_Validate::is($groupCode, 'Alnum')) { + throw new LocalizedException(__('Invalid group code provided.' . + ' Please use only letters (a-z or A-Z), numbers (0-9) or underscore (_) ')); + }; + } } diff --git a/app/code/Magento/Customer/Model/ResourceModel/GroupRepository.php b/app/code/Magento/Customer/Model/ResourceModel/GroupRepository.php index 31e0e2727436b..3faa768e87314 100644 --- a/app/code/Magento/Customer/Model/ResourceModel/GroupRepository.php +++ b/app/code/Magento/Customer/Model/ResourceModel/GroupRepository.php @@ -109,7 +109,7 @@ public function __construct( } /** - * {@inheritdoc} + * @inheritdoc */ public function save(\Magento\Customer\Api\Data\GroupInterface $group) { @@ -165,7 +165,7 @@ public function save(\Magento\Customer\Api\Data\GroupInterface $group) } /** - * {@inheritdoc} + * @inheritdoc */ public function getById($id) { @@ -179,7 +179,7 @@ public function getById($id) } /** - * {@inheritdoc} + * @inheritdoc */ public function getList(SearchCriteriaInterface $searchCriteria) { @@ -301,6 +301,7 @@ public function deleteById($id) * * @param \Magento\Customer\Api\Data\GroupInterface $group * @throws InputException + * @throws \Zend_Validate_Exception * @return void * * @SuppressWarnings(PHPMD.NPathComplexity) @@ -313,6 +314,11 @@ private function _validate($group) $exception->addError(__('"%fieldName" is required. Enter and try again.', ['fieldName' => 'code'])); } + if (!\Zend_Validate::is($group->getCode(), 'Alnum')) { + $exception->addError(__('Invalid group code provided.' . + ' Please use only letters (a-z or A-Z), numbers (0-9) or underscore (_) ')); + }; + if ($exception->wasErrorAdded()) { throw $exception; } From 9e74d8532fc972eaf01256c6b578c327cb297b70 Mon Sep 17 00:00:00 2001 From: roman Date: Thu, 17 Jan 2019 16:58:43 +0200 Subject: [PATCH 020/773] MC-5951: Incorrect rendering --- .../Controller/Adminhtml/Group/Save.php | 18 +----------------- .../Model/Customer/Attribute/Source/Group.php | 3 +++ .../Model/ResourceModel/GroupRepository.php | 5 ----- .../Customer/Ui/Component/ColumnFactory.php | 11 ++++++++++- .../Customer/Ui/Component/FilterFactory.php | 9 ++++++++- .../Component/Listing/AttributeRepository.php | 16 +++++++++++++++- .../Ui/Component/MassAction/Group/Options.php | 3 ++- .../adminhtml/web/js/grid/columns/actions.js | 7 ++++++- 8 files changed, 45 insertions(+), 27 deletions(-) diff --git a/app/code/Magento/Customer/Controller/Adminhtml/Group/Save.php b/app/code/Magento/Customer/Controller/Adminhtml/Group/Save.php index 57e4f11ba280b..c73379502e0e0 100644 --- a/app/code/Magento/Customer/Controller/Adminhtml/Group/Save.php +++ b/app/code/Magento/Customer/Controller/Adminhtml/Group/Save.php @@ -13,6 +13,7 @@ /** * Controller class Save. Performs save action of customers group + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class Save extends \Magento\Customer\Controller\Adminhtml\Group implements HttpPostActionInterface { @@ -82,7 +83,6 @@ public function execute() $resultRedirect = $this->resultRedirectFactory->create(); try { $customerGroupCode = (string)$this->getRequest()->getParam('code'); - $this->validateGroupCode($customerGroupCode); if ($id !== null) { $customerGroup = $this->groupRepository->getById((int)$id); @@ -114,20 +114,4 @@ public function execute() return $this->resultForwardFactory->create()->forward('new'); } } - - /** - * Validates group code given in POST param - * - * @param string $groupCode - * @return bool - * @throws LocalizedException - * @throws \Zend_Validate_Exception - */ - private function validateGroupCode(string $groupCode): bool - { - if (!\Zend_Validate::is($groupCode, 'Alnum')) { - throw new LocalizedException(__('Invalid group code provided.' . - ' Please use only letters (a-z or A-Z), numbers (0-9) or underscore (_) ')); - }; - } } diff --git a/app/code/Magento/Customer/Model/Customer/Attribute/Source/Group.php b/app/code/Magento/Customer/Model/Customer/Attribute/Source/Group.php index e590e5e213acd..63f36deaeac73 100644 --- a/app/code/Magento/Customer/Model/Customer/Attribute/Source/Group.php +++ b/app/code/Magento/Customer/Model/Customer/Attribute/Source/Group.php @@ -48,6 +48,9 @@ public function getAllOptions($withEmpty = true, $defaultValues = false) { if (!$this->_options) { $groups = $this->_groupManagement->getLoggedInGroups(); + array_walk($groups, function ($item) { + $item->setCode(str_replace('${', '', $item->getCode())); + }); $this->_options = $this->_converter->toOptionArray($groups, 'id', 'code'); } diff --git a/app/code/Magento/Customer/Model/ResourceModel/GroupRepository.php b/app/code/Magento/Customer/Model/ResourceModel/GroupRepository.php index 3faa768e87314..664f85f841e3f 100644 --- a/app/code/Magento/Customer/Model/ResourceModel/GroupRepository.php +++ b/app/code/Magento/Customer/Model/ResourceModel/GroupRepository.php @@ -314,11 +314,6 @@ private function _validate($group) $exception->addError(__('"%fieldName" is required. Enter and try again.', ['fieldName' => 'code'])); } - if (!\Zend_Validate::is($group->getCode(), 'Alnum')) { - $exception->addError(__('Invalid group code provided.' . - ' Please use only letters (a-z or A-Z), numbers (0-9) or underscore (_) ')); - }; - if ($exception->wasErrorAdded()) { throw $exception; } diff --git a/app/code/Magento/Customer/Ui/Component/ColumnFactory.php b/app/code/Magento/Customer/Ui/Component/ColumnFactory.php index 60bf3ea26b78c..1051f7827a67f 100644 --- a/app/code/Magento/Customer/Ui/Component/ColumnFactory.php +++ b/app/code/Magento/Customer/Ui/Component/ColumnFactory.php @@ -9,6 +9,9 @@ use Magento\Customer\Ui\Component\Listing\Column\InlineEditUpdater; use Magento\Customer\Api\CustomerMetadataInterface; +/** + * Class ColumnFactory. Responsible for the column object generation + */ class ColumnFactory { /** @@ -55,6 +58,8 @@ public function __construct( } /** + * Creates column object for grid ui component + * * @param array $attributeData * @param string $columnName * @param \Magento\Framework\View\Element\UiComponent\ContextInterface $context @@ -64,7 +69,7 @@ public function __construct( public function create(array $attributeData, $columnName, $context, array $config = []) { $config = array_merge([ - 'label' => __($attributeData[AttributeMetadata::FRONTEND_LABEL]), + 'label' => __(str_replace('${', '', $attributeData[AttributeMetadata::FRONTEND_LABEL])), 'dataType' => $this->getDataType($attributeData[AttributeMetadata::FRONTEND_INPUT]), 'align' => 'left', 'visible' => (bool)$attributeData[AttributeMetadata::IS_VISIBLE_IN_GRID], @@ -101,6 +106,8 @@ public function create(array $attributeData, $columnName, $context, array $confi } /** + * Returns component map + * * @param string $dataType * @return string */ @@ -110,6 +117,8 @@ protected function getJsComponent($dataType) } /** + * Returns component map depends on data type + * * @param string $frontendType * @return string */ diff --git a/app/code/Magento/Customer/Ui/Component/FilterFactory.php b/app/code/Magento/Customer/Ui/Component/FilterFactory.php index 9d8fcdb9715ca..eb0ff33836b15 100644 --- a/app/code/Magento/Customer/Ui/Component/FilterFactory.php +++ b/app/code/Magento/Customer/Ui/Component/FilterFactory.php @@ -7,6 +7,9 @@ use Magento\Customer\Api\Data\AttributeMetadataInterface as AttributeMetadata; +/** + * Class FilterFactory. Responsible for generation filter object + */ class FilterFactory { /** @@ -34,6 +37,8 @@ public function __construct(\Magento\Framework\View\Element\UiComponentFactory $ } /** + * Creates filter object + * * @param array $attributeData * @param \Magento\Framework\View\Element\UiComponent\ContextInterface $context * @return \Magento\Ui\Component\Listing\Columns\ColumnInterface @@ -42,7 +47,7 @@ public function create(array $attributeData, $context) { $config = [ 'dataScope' => $attributeData[AttributeMetadata::ATTRIBUTE_CODE], - 'label' => __($attributeData[AttributeMetadata::FRONTEND_LABEL]), + 'label' => str_replace('${', '', __($attributeData[AttributeMetadata::FRONTEND_LABEL])), ]; if ($attributeData[AttributeMetadata::OPTIONS]) { $config['options'] = $attributeData[AttributeMetadata::OPTIONS]; @@ -63,6 +68,8 @@ public function create(array $attributeData, $context) } /** + * Returns filter type + * * @param string $frontendInput * @return string */ diff --git a/app/code/Magento/Customer/Ui/Component/Listing/AttributeRepository.php b/app/code/Magento/Customer/Ui/Component/Listing/AttributeRepository.php index d0af1ec21467f..45da0972f7f6a 100644 --- a/app/code/Magento/Customer/Ui/Component/Listing/AttributeRepository.php +++ b/app/code/Magento/Customer/Ui/Component/Listing/AttributeRepository.php @@ -13,6 +13,9 @@ use Magento\Customer\Api\MetadataManagementInterface; use Magento\Customer\Model\Indexer\Attribute\Filter; +/** + * Class AttributeRepository + */ class AttributeRepository { const BILLING_ADDRESS_PREFIX = 'billing_'; @@ -69,6 +72,8 @@ public function __construct( } /** + * Returns attribute list for current customer + * * @return array */ public function getList() @@ -93,6 +98,8 @@ public function getList() } /** + * Returns attribute list for given entity type code + * * @param AttributeMetadataInterface[] $metadata * @param string $entityTypeCode * @param MetadataManagementInterface $management @@ -136,12 +143,19 @@ protected function getOptionArray(array $options) { /** @var \Magento\Customer\Api\Data\OptionInterface $option */ foreach ($options as &$option) { - $option = ['label' => (string)$option->getLabel(), 'value' => $option->getValue()]; + $option = ['label' => str_replace( + '${', + '', + (string)$option->getLabel() + ), + 'value' => $option->getValue()]; } return $options; } /** + * Return customer group's metadata by given group code + * * @param string $code * @return [] */ diff --git a/app/code/Magento/Customer/Ui/Component/MassAction/Group/Options.php b/app/code/Magento/Customer/Ui/Component/MassAction/Group/Options.php index 146adacac9553..0cc9afc6e1488 100644 --- a/app/code/Magento/Customer/Ui/Component/MassAction/Group/Options.php +++ b/app/code/Magento/Customer/Ui/Component/MassAction/Group/Options.php @@ -87,7 +87,8 @@ public function jsonSerialize() foreach ($options as $optionCode) { $this->options[$optionCode['value']] = [ 'type' => 'customer_group_' . $optionCode['value'], - 'label' => __($optionCode['label']), + 'label' => str_replace('${', '', __($optionCode['label'])), + ]; if ($this->urlPath && $this->paramName) { diff --git a/app/code/Magento/Customer/view/adminhtml/web/js/grid/columns/actions.js b/app/code/Magento/Customer/view/adminhtml/web/js/grid/columns/actions.js index 66ef89c9413c7..a0be009507915 100644 --- a/app/code/Magento/Customer/view/adminhtml/web/js/grid/columns/actions.js +++ b/app/code/Magento/Customer/view/adminhtml/web/js/grid/columns/actions.js @@ -20,7 +20,12 @@ define([ }, listens: { action: 'onAction' - } + }, + ignoreTmpls: { + fieldAction: true, + options: true, + action: true + }, }, /** From f2b2be695ca9b9ef27c99b0280647b154af23691 Mon Sep 17 00:00:00 2001 From: roman Date: Thu, 17 Jan 2019 17:06:04 +0200 Subject: [PATCH 021/773] MC-5951: Incorrect rendering --- app/code/Magento/Customer/Controller/Adminhtml/Group/Save.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/code/Magento/Customer/Controller/Adminhtml/Group/Save.php b/app/code/Magento/Customer/Controller/Adminhtml/Group/Save.php index c73379502e0e0..19ee080a18aa2 100644 --- a/app/code/Magento/Customer/Controller/Adminhtml/Group/Save.php +++ b/app/code/Magento/Customer/Controller/Adminhtml/Group/Save.php @@ -13,7 +13,6 @@ /** * Controller class Save. Performs save action of customers group - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class Save extends \Magento\Customer\Controller\Adminhtml\Group implements HttpPostActionInterface { From 652aa111bbb348595271c7a04df3e4ca9b29a41d Mon Sep 17 00:00:00 2001 From: roman Date: Thu, 17 Jan 2019 17:07:46 +0200 Subject: [PATCH 022/773] MC-5951: Incorrect rendering --- app/code/Magento/Customer/Controller/Adminhtml/Group/Save.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/code/Magento/Customer/Controller/Adminhtml/Group/Save.php b/app/code/Magento/Customer/Controller/Adminhtml/Group/Save.php index 19ee080a18aa2..5ffce4cbcd989 100644 --- a/app/code/Magento/Customer/Controller/Adminhtml/Group/Save.php +++ b/app/code/Magento/Customer/Controller/Adminhtml/Group/Save.php @@ -9,7 +9,6 @@ use Magento\Customer\Api\Data\GroupInterfaceFactory; use Magento\Customer\Api\Data\GroupInterface; use Magento\Customer\Api\GroupRepositoryInterface; -use Magento\Framework\Exception\LocalizedException; /** * Controller class Save. Performs save action of customers group From f5838452f3260e4e8ad14b043e072e5fa891b0be Mon Sep 17 00:00:00 2001 From: roman Date: Fri, 18 Jan 2019 15:14:58 +0200 Subject: [PATCH 023/773] MC-5951: Incorrect rendering --- .../Model/Customer/Attribute/Source/Group.php | 6 +-- .../Customer/Ui/Component/ColumnFactory.php | 3 +- .../Customer/Ui/Component/FilterFactory.php | 3 +- .../Component/Listing/AttributeRepository.php | 11 ++--- .../Ui/Component/MassAction/Group/Options.php | 4 +- lib/web/mage/utils/template.js | 46 +++++++++++++++++-- 6 files changed, 55 insertions(+), 18 deletions(-) diff --git a/app/code/Magento/Customer/Model/Customer/Attribute/Source/Group.php b/app/code/Magento/Customer/Model/Customer/Attribute/Source/Group.php index 63f36deaeac73..186990c181d07 100644 --- a/app/code/Magento/Customer/Model/Customer/Attribute/Source/Group.php +++ b/app/code/Magento/Customer/Model/Customer/Attribute/Source/Group.php @@ -48,9 +48,9 @@ public function getAllOptions($withEmpty = true, $defaultValues = false) { if (!$this->_options) { $groups = $this->_groupManagement->getLoggedInGroups(); - array_walk($groups, function ($item) { - $item->setCode(str_replace('${', '', $item->getCode())); - }); + foreach ($groups as $group) { + $group['__ignore'] = true; + } $this->_options = $this->_converter->toOptionArray($groups, 'id', 'code'); } diff --git a/app/code/Magento/Customer/Ui/Component/ColumnFactory.php b/app/code/Magento/Customer/Ui/Component/ColumnFactory.php index 1051f7827a67f..d92818b903acd 100644 --- a/app/code/Magento/Customer/Ui/Component/ColumnFactory.php +++ b/app/code/Magento/Customer/Ui/Component/ColumnFactory.php @@ -69,11 +69,12 @@ public function __construct( public function create(array $attributeData, $columnName, $context, array $config = []) { $config = array_merge([ - 'label' => __(str_replace('${', '', $attributeData[AttributeMetadata::FRONTEND_LABEL])), + 'label' => __($attributeData[AttributeMetadata::FRONTEND_LABEL]), 'dataType' => $this->getDataType($attributeData[AttributeMetadata::FRONTEND_INPUT]), 'align' => 'left', 'visible' => (bool)$attributeData[AttributeMetadata::IS_VISIBLE_IN_GRID], 'component' => $this->getJsComponent($this->getDataType($attributeData[AttributeMetadata::FRONTEND_INPUT])), + '__ignore' => 'true' ], $config); if ($attributeData[AttributeMetadata::FRONTEND_INPUT] == 'date') { $config['dateFormat'] = 'MMM d, y'; diff --git a/app/code/Magento/Customer/Ui/Component/FilterFactory.php b/app/code/Magento/Customer/Ui/Component/FilterFactory.php index eb0ff33836b15..fea822f76fb70 100644 --- a/app/code/Magento/Customer/Ui/Component/FilterFactory.php +++ b/app/code/Magento/Customer/Ui/Component/FilterFactory.php @@ -47,7 +47,8 @@ public function create(array $attributeData, $context) { $config = [ 'dataScope' => $attributeData[AttributeMetadata::ATTRIBUTE_CODE], - 'label' => str_replace('${', '', __($attributeData[AttributeMetadata::FRONTEND_LABEL])), + 'label' => __($attributeData[AttributeMetadata::FRONTEND_LABEL]), + '__ignore' => 'true' ]; if ($attributeData[AttributeMetadata::OPTIONS]) { $config['options'] = $attributeData[AttributeMetadata::OPTIONS]; diff --git a/app/code/Magento/Customer/Ui/Component/Listing/AttributeRepository.php b/app/code/Magento/Customer/Ui/Component/Listing/AttributeRepository.php index 45da0972f7f6a..7e261cba903d6 100644 --- a/app/code/Magento/Customer/Ui/Component/Listing/AttributeRepository.php +++ b/app/code/Magento/Customer/Ui/Component/Listing/AttributeRepository.php @@ -143,12 +143,11 @@ protected function getOptionArray(array $options) { /** @var \Magento\Customer\Api\Data\OptionInterface $option */ foreach ($options as &$option) { - $option = ['label' => str_replace( - '${', - '', - (string)$option->getLabel() - ), - 'value' => $option->getValue()]; + $option = [ + 'label' => (string)$option->getLabel(), + 'value' => $option->getValue(), + '__ignore' => true + ]; } return $options; } diff --git a/app/code/Magento/Customer/Ui/Component/MassAction/Group/Options.php b/app/code/Magento/Customer/Ui/Component/MassAction/Group/Options.php index 0cc9afc6e1488..366e24682534c 100644 --- a/app/code/Magento/Customer/Ui/Component/MassAction/Group/Options.php +++ b/app/code/Magento/Customer/Ui/Component/MassAction/Group/Options.php @@ -87,8 +87,8 @@ public function jsonSerialize() foreach ($options as $optionCode) { $this->options[$optionCode['value']] = [ 'type' => 'customer_group_' . $optionCode['value'], - 'label' => str_replace('${', '', __($optionCode['label'])), - + 'label' => __($optionCode['label']), + '__ignore' => true ]; if ($this->urlPath && $this->paramName) { diff --git a/lib/web/mage/utils/template.js b/lib/web/mage/utils/template.js index 7c50226d6aa3a..ae80cc9dc87a0 100644 --- a/lib/web/mage/utils/template.js +++ b/lib/web/mage/utils/template.js @@ -32,6 +32,35 @@ define([ } })(); + /** + * Validates template + * + * @param {String} tmpl + * @param {Object} target + * @returns {*} + */ + function validateTemplate(tmpl, target) { + var parsedTmpl; + + try { + parsedTmpl = JSON.parse(tmpl); + + if (typeof parsedTmpl === 'object') { + return tmpl.includes('__ignore'); + } + } catch (e) { + } + + if (typeof target !== 'undefined') { + if (typeof target === 'object' && target.hasOwnProperty('__ignore')) { + return true; + } + } + + return false; + + } + if (hasStringTmpls) { /*eslint-disable no-unused-vars, no-eval*/ @@ -40,10 +69,17 @@ define([ * * @param {String} tmpl - Template string. * @param {Object} $ - Data object used in a template. + * @param {Object} target * @returns {String} Compiled template. */ - template = function (tmpl, $) { - return eval('`' + tmpl + '`'); + template = function (tmpl, $, target) { + var ignoreTmpl = validateTemplate(tmpl, target); + + if (!ignoreTmpl) { + return eval('`' + tmpl + '`'); + } + + return tmpl; }; /*eslint-enable no-unused-vars, no-eval*/ @@ -97,11 +133,11 @@ define([ * that it should be leaved as a string. * @returns {*} Compiled template. */ - function render(tmpl, data, castString) { + function render(tmpl, data, castString, target) { var last = tmpl; while (~tmpl.indexOf(opener)) { - tmpl = template(tmpl, data); + tmpl = template(tmpl, data, target); if (tmpl === last) { break; @@ -178,7 +214,7 @@ define([ } if (isTemplate(value)) { - list[key] = render(value, tmpl, castString); + list[key] = render(value, tmpl, castString, list); } else if ($.isPlainObject(value) || Array.isArray(value)) { _.each(value, iterate); } From f82876c9069cbadf026b16c92b6718e9df57bfbd Mon Sep 17 00:00:00 2001 From: roman Date: Mon, 21 Jan 2019 16:34:24 +0200 Subject: [PATCH 024/773] MC-5951: Incorrect rendering --- .../Model/Customer/Attribute/Source/Group.php | 11 ++++++++--- .../Magento/Customer/Ui/Component/ColumnFactory.php | 2 +- .../Magento/Customer/Ui/Component/FilterFactory.php | 2 +- .../Ui/Component/Listing/AttributeRepository.php | 2 +- .../Ui/Component/MassAction/Group/Options.php | 2 +- lib/web/mage/utils/template.js | 11 +++++------ 6 files changed, 17 insertions(+), 13 deletions(-) diff --git a/app/code/Magento/Customer/Model/Customer/Attribute/Source/Group.php b/app/code/Magento/Customer/Model/Customer/Attribute/Source/Group.php index 186990c181d07..296d2877df8ea 100644 --- a/app/code/Magento/Customer/Model/Customer/Attribute/Source/Group.php +++ b/app/code/Magento/Customer/Model/Customer/Attribute/Source/Group.php @@ -48,10 +48,15 @@ public function getAllOptions($withEmpty = true, $defaultValues = false) { if (!$this->_options) { $groups = $this->_groupManagement->getLoggedInGroups(); - foreach ($groups as $group) { - $group['__ignore'] = true; - } + $this->_options = $this->_converter->toOptionArray($groups, 'id', 'code'); + + array_walk( + $this->_options, + function (&$item) { + $item['__disableTmpl'] = true; + } + ); } return $this->_options; diff --git a/app/code/Magento/Customer/Ui/Component/ColumnFactory.php b/app/code/Magento/Customer/Ui/Component/ColumnFactory.php index d92818b903acd..8cdf53f35387e 100644 --- a/app/code/Magento/Customer/Ui/Component/ColumnFactory.php +++ b/app/code/Magento/Customer/Ui/Component/ColumnFactory.php @@ -74,7 +74,7 @@ public function create(array $attributeData, $columnName, $context, array $confi 'align' => 'left', 'visible' => (bool)$attributeData[AttributeMetadata::IS_VISIBLE_IN_GRID], 'component' => $this->getJsComponent($this->getDataType($attributeData[AttributeMetadata::FRONTEND_INPUT])), - '__ignore' => 'true' + '__disableTmpl' => 'true' ], $config); if ($attributeData[AttributeMetadata::FRONTEND_INPUT] == 'date') { $config['dateFormat'] = 'MMM d, y'; diff --git a/app/code/Magento/Customer/Ui/Component/FilterFactory.php b/app/code/Magento/Customer/Ui/Component/FilterFactory.php index fea822f76fb70..9bf07b877cc07 100644 --- a/app/code/Magento/Customer/Ui/Component/FilterFactory.php +++ b/app/code/Magento/Customer/Ui/Component/FilterFactory.php @@ -48,7 +48,7 @@ public function create(array $attributeData, $context) $config = [ 'dataScope' => $attributeData[AttributeMetadata::ATTRIBUTE_CODE], 'label' => __($attributeData[AttributeMetadata::FRONTEND_LABEL]), - '__ignore' => 'true' + '__disableTmpl' => 'true' ]; if ($attributeData[AttributeMetadata::OPTIONS]) { $config['options'] = $attributeData[AttributeMetadata::OPTIONS]; diff --git a/app/code/Magento/Customer/Ui/Component/Listing/AttributeRepository.php b/app/code/Magento/Customer/Ui/Component/Listing/AttributeRepository.php index 7e261cba903d6..eb8359de93f32 100644 --- a/app/code/Magento/Customer/Ui/Component/Listing/AttributeRepository.php +++ b/app/code/Magento/Customer/Ui/Component/Listing/AttributeRepository.php @@ -146,7 +146,7 @@ protected function getOptionArray(array $options) $option = [ 'label' => (string)$option->getLabel(), 'value' => $option->getValue(), - '__ignore' => true + '__disableTmpl' => true ]; } return $options; diff --git a/app/code/Magento/Customer/Ui/Component/MassAction/Group/Options.php b/app/code/Magento/Customer/Ui/Component/MassAction/Group/Options.php index 366e24682534c..e5739317bca8d 100644 --- a/app/code/Magento/Customer/Ui/Component/MassAction/Group/Options.php +++ b/app/code/Magento/Customer/Ui/Component/MassAction/Group/Options.php @@ -88,7 +88,7 @@ public function jsonSerialize() $this->options[$optionCode['value']] = [ 'type' => 'customer_group_' . $optionCode['value'], 'label' => __($optionCode['label']), - '__ignore' => true + '__disableTmpl' => true ]; if ($this->urlPath && $this->paramName) { diff --git a/lib/web/mage/utils/template.js b/lib/web/mage/utils/template.js index ae80cc9dc87a0..7aa695023cb56 100644 --- a/lib/web/mage/utils/template.js +++ b/lib/web/mage/utils/template.js @@ -37,22 +37,22 @@ define([ * * @param {String} tmpl * @param {Object} target - * @returns {*} + * @returns {Boolean} */ - function validateTemplate(tmpl, target) { + function isTmplIgnored(tmpl, target) { var parsedTmpl; try { parsedTmpl = JSON.parse(tmpl); if (typeof parsedTmpl === 'object') { - return tmpl.includes('__ignore'); + return tmpl.includes('__disableTmpl'); } } catch (e) { } if (typeof target !== 'undefined') { - if (typeof target === 'object' && target.hasOwnProperty('__ignore')) { + if (typeof target === 'object' && target.hasOwnProperty('__disableTmpl')) { return true; } } @@ -73,9 +73,8 @@ define([ * @returns {String} Compiled template. */ template = function (tmpl, $, target) { - var ignoreTmpl = validateTemplate(tmpl, target); - if (!ignoreTmpl) { + if (!isTmplIgnored(tmpl, target)) { return eval('`' + tmpl + '`'); } From a7cca24ad88e50916ede03b5015722d65a162add Mon Sep 17 00:00:00 2001 From: roman Date: Tue, 22 Jan 2019 17:54:02 +0200 Subject: [PATCH 025/773] MC-5968: Fixed incorrect config override behavior --- app/code/Magento/Config/Model/Config.php | 32 ++++++++++++++++++- app/code/Magento/Store/etc/config.xml | 2 +- .../App/Config/Initial/Converter.php | 9 ++++++ .../Config/MetadataConfigTypeProcessor.php | 11 ++++--- 4 files changed, 48 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/Config/Model/Config.php b/app/code/Magento/Config/Model/Config.php index b1074e92cc949..3249bd53ecb96 100644 --- a/app/code/Magento/Config/Model/Config.php +++ b/app/code/Magento/Config/Model/Config.php @@ -6,6 +6,7 @@ namespace Magento\Config\Model; use Magento\Config\Model\Config\Reader\Source\Deployed\SettingChecker; +use Magento\Framework\App\Config\Initial as Reader; use Magento\Config\Model\Config\Structure\Element\Group; use Magento\Config\Model\Config\Structure\Element\Field; use Magento\Framework\App\ObjectManager; @@ -114,6 +115,11 @@ class Config extends \Magento\Framework\DataObject */ private $scopeTypeNormalizer; + /** + * @var Reader + */ + private $initialConfigReader; + /** * @param \Magento\Framework\App\Config\ReinitableConfigInterface $config * @param \Magento\Framework\Event\ManagerInterface $eventManager @@ -126,6 +132,7 @@ class Config extends \Magento\Framework\DataObject * @param array $data * @param ScopeResolverPool|null $scopeResolverPool * @param ScopeTypeNormalizer|null $scopeTypeNormalizer + * @param Reader|null $initialConfigReader * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -139,7 +146,8 @@ public function __construct( SettingChecker $settingChecker = null, array $data = [], ScopeResolverPool $scopeResolverPool = null, - ScopeTypeNormalizer $scopeTypeNormalizer = null + ScopeTypeNormalizer $scopeTypeNormalizer = null, + ?Reader $initialConfigReader = null ) { parent::__construct($data); $this->_eventManager = $eventManager; @@ -155,6 +163,8 @@ public function __construct( ?? ObjectManager::getInstance()->get(ScopeResolverPool::class); $this->scopeTypeNormalizer = $scopeTypeNormalizer ?? ObjectManager::getInstance()->get(ScopeTypeNormalizer::class); + $this->initialConfigReader = $initialConfigReader ?: + ObjectManager::getInstance()->get(Reader::class); } /** @@ -415,6 +425,10 @@ protected function _processGroup( continue; } + if ($this->isProtectedNode($groupPath . '/' . $fieldId)) { + continue; + } + $field = $this->getField($sectionPath, $groupId, $fieldId); /** @var \Magento\Framework\App\Config\ValueInterface $backendModel */ $backendModel = $field->hasBackendModel() @@ -678,4 +692,20 @@ public function getConfigDataValue($path, &$inherit = null, $configData = null) return $data; } + + /** + * Checks if node has 'protected' attribute by given path + * + * @param string $path + * @return bool + */ + private function isProtectedNode(string $path): bool + { + $currentConfigMetaData = $this->initialConfigReader->getMetadata()[$path] ?? + false; + + if ($currentConfigMetaData && isset($currentConfigMetaData['protected'])) { + return false; + } + } } diff --git a/app/code/Magento/Store/etc/config.xml b/app/code/Magento/Store/etc/config.xml index b9e7ac1c6aca0..7a7d4d0a436f8 100644 --- a/app/code/Magento/Store/etc/config.xml +++ b/app/code/Magento/Store/etc/config.xml @@ -113,7 +113,7 @@ 0,6 - + php php3 php4 diff --git a/lib/internal/Magento/Framework/App/Config/Initial/Converter.php b/lib/internal/Magento/Framework/App/Config/Initial/Converter.php index 8f1a8e9f298e7..491805dbdac96 100644 --- a/lib/internal/Magento/Framework/App/Config/Initial/Converter.php +++ b/lib/internal/Magento/Framework/App/Config/Initial/Converter.php @@ -7,6 +7,9 @@ */ namespace Magento\Framework\App\Config\Initial; +/** + * Class Converter. Responsible for transform dom documents into an array + */ class Converter implements \Magento\Framework\Config\ConverterInterface { /** @@ -66,6 +69,12 @@ protected function _convertNode(\DOMNode $node, $path = '') if ($backendModel) { $this->_metadata[$path] = ['backendModel' => $backendModel->nodeValue]; } + + if ($node->getAttribute('protected')) { + $this->_metadata[$path] = [ + 'protected' => $node->attributes->getNamedItem('protected')->nodeValue + ]; + } } $nodeData = []; /** @var $childNode \DOMNode */ diff --git a/lib/internal/Magento/Framework/App/Config/MetadataConfigTypeProcessor.php b/lib/internal/Magento/Framework/App/Config/MetadataConfigTypeProcessor.php index bc23032903d23..56fc064255015 100644 --- a/lib/internal/Magento/Framework/App/Config/MetadataConfigTypeProcessor.php +++ b/lib/internal/Magento/Framework/App/Config/MetadataConfigTypeProcessor.php @@ -126,10 +126,13 @@ private function processScopeData( //Failed to load scopes or config source, perhaps config data received is outdated. return $data; } - /** @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); + + if (isset($metadata['backendModel'])) { + /** @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; From 757856f3c6b6feccb8205950ece8fdedb7cc54a9 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky Date: Thu, 24 Jan 2019 15:09:18 +0200 Subject: [PATCH 026/773] magento/magento2#12817: [Forwardport] Coupon code with canceled order. --- .../Model/Coupon/UpdateCouponUsages.php | 153 +++++++++++++++ .../Model/ResourceModel/Coupon/Usage.php | 9 +- .../Observer/SalesOrderAfterPlaceObserver.php | 110 ----------- .../Plugin/CouponUsagesDecrement.php | 49 +++++ .../Plugin/CouponUsagesIncrement.php | 46 +++++ .../SalesOrderAfterPlaceObserverTest.php | 183 ------------------ app/code/Magento/SalesRule/etc/di.xml | 4 + app/code/Magento/SalesRule/etc/events.xml | 3 - .../Model/ResourceModel/Coupon/UsageTest.php | 81 ++++++++ .../SalesRule/Plugin/CouponUsagesTest.php | 101 ++++++++++ .../SalesRule/_files/coupons_limited.php | 29 +++ .../_files/coupons_limited_order.php | 26 +++ .../_files/coupons_limited_order_rollback.php | 8 + .../_files/coupons_limited_rollback.php | 21 ++ 14 files changed, 523 insertions(+), 300 deletions(-) create mode 100644 app/code/Magento/SalesRule/Model/Coupon/UpdateCouponUsages.php delete mode 100644 app/code/Magento/SalesRule/Observer/SalesOrderAfterPlaceObserver.php create mode 100644 app/code/Magento/SalesRule/Plugin/CouponUsagesDecrement.php create mode 100644 app/code/Magento/SalesRule/Plugin/CouponUsagesIncrement.php delete mode 100644 app/code/Magento/SalesRule/Test/Unit/Observer/SalesOrderAfterPlaceObserverTest.php create mode 100644 dev/tests/integration/testsuite/Magento/SalesRule/Model/ResourceModel/Coupon/UsageTest.php create mode 100644 dev/tests/integration/testsuite/Magento/SalesRule/Plugin/CouponUsagesTest.php create mode 100644 dev/tests/integration/testsuite/Magento/SalesRule/_files/coupons_limited.php create mode 100644 dev/tests/integration/testsuite/Magento/SalesRule/_files/coupons_limited_order.php create mode 100644 dev/tests/integration/testsuite/Magento/SalesRule/_files/coupons_limited_order_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/SalesRule/_files/coupons_limited_rollback.php diff --git a/app/code/Magento/SalesRule/Model/Coupon/UpdateCouponUsages.php b/app/code/Magento/SalesRule/Model/Coupon/UpdateCouponUsages.php new file mode 100644 index 0000000000000..ae1866d8fda48 --- /dev/null +++ b/app/code/Magento/SalesRule/Model/Coupon/UpdateCouponUsages.php @@ -0,0 +1,153 @@ +ruleFactory = $ruleFactory; + $this->ruleCustomerFactory = $ruleCustomerFactory; + $this->coupon = $coupon; + $this->couponUsage = $couponUsage; + } + + /** + * Executes the current command. + * + * @param Order $subject + * @param bool $increment + * @return Order + */ + public function execute(Order $subject, bool $increment) + { + if (!$subject || !$subject->getAppliedRuleIds()) { + return $subject; + } + // lookup rule ids + $ruleIds = explode(',', $subject->getAppliedRuleIds()); + $ruleIds = array_unique($ruleIds); + $customerId = (int)$subject->getCustomerId(); + // use each rule (and apply to customer, if applicable) + foreach ($ruleIds as $ruleId) { + if (!$ruleId) { + continue; + } + $this->updateRuleUsages($increment, (int)$ruleId, $customerId); + } + $this->updateCouponUsages($subject, $increment, $customerId); + + return $subject; + } + + /** + * Update the number of rule usages. + * + * @param bool $increment + * @param int $ruleId + * @param int $customerId + */ + private function updateRuleUsages(bool $increment, int $ruleId, int $customerId) + { + /** @var \Magento\SalesRule\Model\Rule $rule */ + $rule = $this->ruleFactory->create(); + $rule->load($ruleId); + if ($rule->getId()) { + $rule->loadCouponCode(); + if ($increment || $rule->getTimesUsed() > 0) { + $rule->setTimesUsed($rule->getTimesUsed() + ($increment ? 1 : -1)); + $rule->save(); + } + if ($customerId) { + $this->updateCustomerRuleUsages($increment, $ruleId, $customerId); + } + } + } + + /** + * Update the number of rule usages per customer. + * + * @param bool $increment + * @param int $ruleId + * @param int $customerId + */ + private function updateCustomerRuleUsages(bool $increment, int $ruleId, int $customerId) + { + /** @var \Magento\SalesRule\Model\Rule\Customer $ruleCustomer */ + $ruleCustomer = $this->ruleCustomerFactory->create(); + $ruleCustomer->loadByCustomerRule($customerId, $ruleId); + if ($ruleCustomer->getId()) { + if ($increment || $ruleCustomer->getTimesUsed() > 0) { + $ruleCustomer->setTimesUsed($ruleCustomer->getTimesUsed() + ($increment ? 1 : -1)); + } + } elseif ($increment) { + $ruleCustomer->setCustomerId($customerId)->setRuleId($ruleId)->setTimesUsed(1); + } + $ruleCustomer->save(); + } + + /** + * Update the number of coupon usages. + * + * @param Order $subject + * @param bool $increment + * @param int $customerId + */ + private function updateCouponUsages(Order $subject, bool $increment, int $customerId) + { + $this->coupon->load($subject->getCouponCode(), 'code'); + if ($this->coupon->getId()) { + if ($increment || $this->coupon->getTimesUsed() > 0) { + $this->coupon->setTimesUsed($this->coupon->getTimesUsed() + ($increment ? 1 : -1)); + $this->coupon->save(); + } + if ($customerId) { + $this->couponUsage->updateCustomerCouponTimesUsed($customerId, $this->coupon->getId(), $increment); + } + } + } +} diff --git a/app/code/Magento/SalesRule/Model/ResourceModel/Coupon/Usage.php b/app/code/Magento/SalesRule/Model/ResourceModel/Coupon/Usage.php index db32bdbe1e908..8680a91a9acc4 100644 --- a/app/code/Magento/SalesRule/Model/ResourceModel/Coupon/Usage.php +++ b/app/code/Magento/SalesRule/Model/ResourceModel/Coupon/Usage.php @@ -27,9 +27,10 @@ protected function _construct() * * @param int $customerId * @param mixed $couponId + * @param bool $increment * @return void */ - public function updateCustomerCouponTimesUsed($customerId, $couponId) + public function updateCustomerCouponTimesUsed($customerId, $couponId, $increment = true) { $connection = $this->getConnection(); $select = $connection->select(); @@ -44,13 +45,13 @@ public function updateCustomerCouponTimesUsed($customerId, $couponId) $timesUsed = $connection->fetchOne($select, [':coupon_id' => $couponId, ':customer_id' => $customerId]); - if ($timesUsed > 0) { + if ($timesUsed !== false) { $this->getConnection()->update( $this->getMainTable(), - ['times_used' => $timesUsed + 1], + ['times_used' => $timesUsed + ($increment ? 1 : -1)], ['coupon_id = ?' => $couponId, 'customer_id = ?' => $customerId] ); - } else { + } elseif ($increment) { $this->getConnection()->insert( $this->getMainTable(), ['coupon_id' => $couponId, 'customer_id' => $customerId, 'times_used' => 1] diff --git a/app/code/Magento/SalesRule/Observer/SalesOrderAfterPlaceObserver.php b/app/code/Magento/SalesRule/Observer/SalesOrderAfterPlaceObserver.php deleted file mode 100644 index a49802d4c304a..0000000000000 --- a/app/code/Magento/SalesRule/Observer/SalesOrderAfterPlaceObserver.php +++ /dev/null @@ -1,110 +0,0 @@ -_ruleFactory = $ruleFactory; - $this->_ruleCustomerFactory = $ruleCustomerFactory; - $this->_coupon = $coupon; - $this->_couponUsage = $couponUsage; - } - - /** - * @param EventObserver $observer - * @return $this - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - */ - public function execute(EventObserver $observer) - { - $order = $observer->getEvent()->getOrder(); - - if (!$order || !$order->getAppliedRuleIds()) { - return $this; - } - - // lookup rule ids - $ruleIds = explode(',', $order->getAppliedRuleIds()); - $ruleIds = array_unique($ruleIds); - - $ruleCustomer = null; - $customerId = $order->getCustomerId(); - - // use each rule (and apply to customer, if applicable) - foreach ($ruleIds as $ruleId) { - if (!$ruleId) { - continue; - } - /** @var \Magento\SalesRule\Model\Rule $rule */ - $rule = $this->_ruleFactory->create(); - $rule->load($ruleId); - if ($rule->getId()) { - $rule->loadCouponCode(); - $rule->setTimesUsed($rule->getTimesUsed() + 1); - $rule->save(); - - if ($customerId) { - /** @var \Magento\SalesRule\Model\Rule\Customer $ruleCustomer */ - $ruleCustomer = $this->_ruleCustomerFactory->create(); - $ruleCustomer->loadByCustomerRule($customerId, $ruleId); - - if ($ruleCustomer->getId()) { - $ruleCustomer->setTimesUsed($ruleCustomer->getTimesUsed() + 1); - } else { - $ruleCustomer->setCustomerId($customerId)->setRuleId($ruleId)->setTimesUsed(1); - } - $ruleCustomer->save(); - } - } - } - - $this->_coupon->load($order->getCouponCode(), 'code'); - if ($this->_coupon->getId()) { - $this->_coupon->setTimesUsed($this->_coupon->getTimesUsed() + 1); - $this->_coupon->save(); - if ($customerId) { - $this->_couponUsage->updateCustomerCouponTimesUsed($customerId, $this->_coupon->getId()); - } - } - - return $this; - } -} diff --git a/app/code/Magento/SalesRule/Plugin/CouponUsagesDecrement.php b/app/code/Magento/SalesRule/Plugin/CouponUsagesDecrement.php new file mode 100644 index 0000000000000..5f28632a54cea --- /dev/null +++ b/app/code/Magento/SalesRule/Plugin/CouponUsagesDecrement.php @@ -0,0 +1,49 @@ +updateCouponUsages = $updateCouponUsages; + } + + /** + * Decrements number of coupon usages after cancelling order. + * + * @param Order $subject + * @param callable $proceed + * @return Order + */ + public function aroundCancel(Order $subject, callable $proceed): Order + { + $canCancel = $subject->canCancel(); + $returnValue = $proceed(); + if ($canCancel) { + $returnValue = $this->updateCouponUsages->execute($returnValue, false); + } + + return $returnValue; + } +} diff --git a/app/code/Magento/SalesRule/Plugin/CouponUsagesIncrement.php b/app/code/Magento/SalesRule/Plugin/CouponUsagesIncrement.php new file mode 100644 index 0000000000000..473a368afb25a --- /dev/null +++ b/app/code/Magento/SalesRule/Plugin/CouponUsagesIncrement.php @@ -0,0 +1,46 @@ +updateCouponUsages = $updateCouponUsages; + } + + /** + * Increments number of coupon usages after placing order. + * + * @param Order $subject + * @param Order $result + * @return Order + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function afterPlace(Order $subject, Order $result): Order + { + $this->updateCouponUsages->execute($subject, true); + + return $subject; + } +} diff --git a/app/code/Magento/SalesRule/Test/Unit/Observer/SalesOrderAfterPlaceObserverTest.php b/app/code/Magento/SalesRule/Test/Unit/Observer/SalesOrderAfterPlaceObserverTest.php deleted file mode 100644 index 32bf2201665ef..0000000000000 --- a/app/code/Magento/SalesRule/Test/Unit/Observer/SalesOrderAfterPlaceObserverTest.php +++ /dev/null @@ -1,183 +0,0 @@ -initMocks(); - - $this->model = $helper->getObject( - \Magento\SalesRule\Observer\SalesOrderAfterPlaceObserver::class, - [ - 'ruleFactory' => $this->ruleFactory, - 'ruleCustomerFactory' => $this->ruleCustomerFactory, - 'coupon' => $this->couponMock, - 'couponUsage' => $this->couponUsage, - ] - ); - } - - protected function initMocks() - { - $this->couponMock = $this->createPartialMock(\Magento\SalesRule\Model\Coupon::class, [ - '__wakeup', - 'save', - 'load', - 'getId', - 'setTimesUsed', - 'getTimesUsed', - 'getRuleId', - 'loadByCode', - 'updateCustomerCouponTimesUsed' - ]); - $this->ruleFactory = $this->createPartialMock(\Magento\SalesRule\Model\RuleFactory::class, ['create']); - $this->ruleCustomerFactory = $this->createPartialMock( - \Magento\SalesRule\Model\Rule\CustomerFactory::class, - ['create'] - ); - $this->couponUsage = $this->createMock(\Magento\SalesRule\Model\ResourceModel\Coupon\Usage::class); - } - - /** - * @param \\PHPUnit_Framework_MockObject_MockObject $observer - * @return \PHPUnit_Framework_MockObject_MockObject $order - */ - protected function initOrderFromEvent($observer) - { - $event = $this->createPartialMock(\Magento\Framework\Event::class, ['getOrder']); - $order = $this->createPartialMock( - \Magento\Sales\Model\Order::class, - ['getAppliedRuleIds', 'getCustomerId', 'getDiscountAmount', 'getCouponCode', '__wakeup'] - ); - - $observer->expects($this->any()) - ->method('getEvent') - ->will($this->returnValue($event)); - $event->expects($this->any()) - ->method('getOrder') - ->will($this->returnValue($order)); - - return $order; - } - - public function testSalesOrderAfterPlaceWithoutOrder() - { - $observer = $this->createMock(\Magento\Framework\Event\Observer::class); - $this->initOrderFromEvent($observer); - - $this->assertEquals($this->model, $this->model->execute($observer)); - } - - public function testSalesOrderAfterPlaceWithoutRuleId() - { - $observer = $this->createMock(\Magento\Framework\Event\Observer::class); - $order = $this->initOrderFromEvent($observer); - $ruleIds = null; - $order->expects($this->once()) - ->method('getAppliedRuleIds') - ->will($this->returnValue($ruleIds)); - - $this->ruleFactory->expects($this->never()) - ->method('create'); - $this->assertEquals($this->model, $this->model->execute($observer)); - } - - /** - * @param int|bool $ruleCustomerId - * @dataProvider salesOrderAfterPlaceDataProvider - */ - public function testSalesOrderAfterPlace($ruleCustomerId) - { - $observer = $this->createMock(\Magento\Framework\Event\Observer::class); - $rule = $this->createMock(\Magento\SalesRule\Model\Rule::class); - $ruleCustomer = $this->createPartialMock(\Magento\SalesRule\Model\Rule\Customer::class, [ - 'setCustomerId', - 'loadByCustomerRule', - 'getId', - 'setTimesUsed', - 'setRuleId', - 'save', - '__wakeup' - ]); - $order = $this->initOrderFromEvent($observer); - $ruleId = 1; - $couponId = 1; - $customerId = 1; - - $order->expects($this->exactly(2)) - ->method('getAppliedRuleIds') - ->will($this->returnValue($ruleId)); - $order->expects($this->once()) - ->method('getCustomerId') - ->will($this->returnValue($customerId)); - $this->ruleFactory->expects($this->once()) - ->method('create') - ->will($this->returnValue($rule)); - $rule->expects($this->once()) - ->method('getId') - ->will($this->returnValue($ruleId)); - $this->ruleCustomerFactory->expects($this->once()) - ->method('create') - ->will($this->returnValue($ruleCustomer)); - $ruleCustomer->expects($this->once()) - ->method('getId') - ->will($this->returnValue($ruleCustomerId)); - $ruleCustomer->expects($this->any()) - ->method('setCustomerId') - ->will($this->returnSelf()); - $ruleCustomer->expects($this->any()) - ->method('setRuleId') - ->will($this->returnSelf()); - $this->couponMock->expects($this->any()) - ->method('getId') - ->will($this->returnValue($couponId)); - - $this->couponUsage->expects($this->once()) - ->method('updateCustomerCouponTimesUsed') - ->with($customerId, $couponId); - - $this->assertEquals($this->model, $this->model->execute($observer)); - } - - /** - * @return array - */ - public function salesOrderAfterPlaceDataProvider() - { - return [ - 'With customer rule id' => [1], - 'Without customer rule id' => [null] - ]; - } -} diff --git a/app/code/Magento/SalesRule/etc/di.xml b/app/code/Magento/SalesRule/etc/di.xml index 27c9a41503b22..94ca778cc7c31 100644 --- a/app/code/Magento/SalesRule/etc/di.xml +++ b/app/code/Magento/SalesRule/etc/di.xml @@ -182,4 +182,8 @@ + + + + diff --git a/app/code/Magento/SalesRule/etc/events.xml b/app/code/Magento/SalesRule/etc/events.xml index 43babc40a2ab5..8261860bbb7ce 100644 --- a/app/code/Magento/SalesRule/etc/events.xml +++ b/app/code/Magento/SalesRule/etc/events.xml @@ -6,9 +6,6 @@ */ --> - - - diff --git a/dev/tests/integration/testsuite/Magento/SalesRule/Model/ResourceModel/Coupon/UsageTest.php b/dev/tests/integration/testsuite/Magento/SalesRule/Model/ResourceModel/Coupon/UsageTest.php new file mode 100644 index 0000000000000..9bb263b225d96 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/SalesRule/Model/ResourceModel/Coupon/UsageTest.php @@ -0,0 +1,81 @@ +coupon->loadByCode($couponCode); + + $testCases = [ + ['increment' => true, 'expected' => 1], + ['increment' => false, 'expected' => 0], + ['increment' => false, 'expected' => 0], + ['increment' => true, 'expected' => 1], + ['increment' => true, 'expected' => 2], + ]; + + foreach ($testCases as $testCase) { + $this->usage->updateCustomerCouponTimesUsed($customerId, $this->coupon->getId(), $testCase['increment']); + $this->usage->loadByCustomerCoupon($this->couponUsage, $customerId, $this->coupon->getId()); + + self::assertEquals( + $testCase['expected'], + $this->couponUsage->getTimesUsed() + ); + } + } + + protected function setUp() + { + $this->objectManager = Bootstrap::getObjectManager(); + $this->coupon = $this->objectManager->get(Coupon::class); + $this->usage = $this->objectManager->get(Usage::class); + $this->couponUsage = $this->objectManager->get(DataObject::class); + } +} diff --git a/dev/tests/integration/testsuite/Magento/SalesRule/Plugin/CouponUsagesTest.php b/dev/tests/integration/testsuite/Magento/SalesRule/Plugin/CouponUsagesTest.php new file mode 100644 index 0000000000000..e0477993eea52 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/SalesRule/Plugin/CouponUsagesTest.php @@ -0,0 +1,101 @@ +coupon->loadByCode($couponCode); + $this->order->loadByIncrementId($orderId); + + // Make sure coupon usages value is incremented then order is placed. + $this->order->place(); + $this->usage->loadByCustomerCoupon($this->couponUsage, $customerId, $this->coupon->getId()); + $this->coupon->loadByCode($couponCode); + + self::assertEquals( + 1, + $this->coupon->getTimesUsed() + ); + self::assertEquals( + 1, + $this->couponUsage->getTimesUsed() + ); + + // Make sure order coupon usages value is decremented then order is cancelled. + $this->order->cancel(); + $this->usage->loadByCustomerCoupon($this->couponUsage, $customerId, $this->coupon->getId()); + $this->coupon->loadByCode($couponCode); + + self::assertEquals( + 0, + $this->coupon->getTimesUsed() + ); + self::assertEquals( + 0, + $this->couponUsage->getTimesUsed() + ); + } + + protected function setUp() + { + $this->objectManager = Bootstrap::getObjectManager(); + $this->coupon = $this->objectManager->get(Coupon::class); + $this->usage = $this->objectManager->get(Usage::class); + $this->couponUsage = $this->objectManager->get(DataObject::class); + $this->order = $this->objectManager->get(Order::class); + } +} diff --git a/dev/tests/integration/testsuite/Magento/SalesRule/_files/coupons_limited.php b/dev/tests/integration/testsuite/Magento/SalesRule/_files/coupons_limited.php new file mode 100644 index 0000000000000..2f298ad34b935 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/SalesRule/_files/coupons_limited.php @@ -0,0 +1,29 @@ +create( + \Magento\SalesRule\Model\ResourceModel\Rule\Collection::class +); +$items = array_values($collection->getItems()); + +/** @var Coupon $coupon */ +$coupon = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(Coupon::class); +$coupon->setRuleId($items[0]->getId()) + ->setCode('one_usage') + ->setType(0) + ->setUsageLimit(1) + ->save(); + +$coupon = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(Coupon::class); +$coupon->setRuleId($items[1]->getId()) + ->setCode('one_usage_per_customer') + ->setType(0) + ->setUsagePerCustomer(1) + ->save(); diff --git a/dev/tests/integration/testsuite/Magento/SalesRule/_files/coupons_limited_order.php b/dev/tests/integration/testsuite/Magento/SalesRule/_files/coupons_limited_order.php new file mode 100644 index 0000000000000..9980970ff0f24 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/SalesRule/_files/coupons_limited_order.php @@ -0,0 +1,26 @@ +create( + \Magento\SalesRule\Model\ResourceModel\Rule\Collection::class +); +$items = array_values($collection->getItems()); + +/** @var Order $order */ +$order = Bootstrap::getObjectManager()->create(Order::class); + +$order->loadByIncrementId('100000001') + ->setCouponCode('one_usage') + ->setAppliedRuleIds("{$items[0]->getId()}") + ->setCreatedAt('2014-10-25 10:10:10') + ->setCustomerId(1) + ->save(); diff --git a/dev/tests/integration/testsuite/Magento/SalesRule/_files/coupons_limited_order_rollback.php b/dev/tests/integration/testsuite/Magento/SalesRule/_files/coupons_limited_order_rollback.php new file mode 100644 index 0000000000000..73a919ac3362f --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/SalesRule/_files/coupons_limited_order_rollback.php @@ -0,0 +1,8 @@ +create(Coupon::class); + +foreach ($couponCodes as $couponCode) { + $coupon->loadByCode($couponCode); + $coupon->delete(); +} + +require 'rules_rollback.php'; From 8e8c2ca544acc5dc10b9863c6546492e6d16e0ee Mon Sep 17 00:00:00 2001 From: roman Date: Tue, 29 Jan 2019 14:06:25 +0200 Subject: [PATCH 027/773] MC-5968: Fixed incorrect config override behavior --- app/code/Magento/Config/Model/Config.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Config/Model/Config.php b/app/code/Magento/Config/Model/Config.php index 3249bd53ecb96..14997fb69b333 100644 --- a/app/code/Magento/Config/Model/Config.php +++ b/app/code/Magento/Config/Model/Config.php @@ -705,7 +705,9 @@ private function isProtectedNode(string $path): bool false; if ($currentConfigMetaData && isset($currentConfigMetaData['protected'])) { - return false; + return true; } + + return false; } } From 8089bd741cd3521943c1b33b6d80c74df8a49667 Mon Sep 17 00:00:00 2001 From: roman Date: Wed, 30 Jan 2019 14:44:20 +0200 Subject: [PATCH 028/773] MC-5968: Fixed incorrect config override behavior --- .../Adminhtml/System/Config/Save.php | 33 +++++++++++++++++- app/code/Magento/Config/Model/Config.php | 34 +------------------ app/code/Magento/Store/etc/config.xml | 2 +- .../App/Config/Initial/Converter.php | 8 +---- 4 files changed, 35 insertions(+), 42 deletions(-) diff --git a/app/code/Magento/Config/Controller/Adminhtml/System/Config/Save.php b/app/code/Magento/Config/Controller/Adminhtml/System/Config/Save.php index 2d4b20033806e..d67c973162991 100644 --- a/app/code/Magento/Config/Controller/Adminhtml/System/Config/Save.php +++ b/app/code/Magento/Config/Controller/Adminhtml/System/Config/Save.php @@ -3,10 +3,12 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Config\Controller\Adminhtml\System\Config; use Magento\Framework\App\Action\HttpPostActionInterface as HttpPostActionInterface; use Magento\Config\Controller\Adminhtml\System\AbstractConfig; +use Magento\Config\Model\Config\Structure; /** * System Configuration Save Controller @@ -157,7 +159,10 @@ public function execute() 'store' => $store, 'groups' => $this->_getGroupsForSave(), ]; - /** @var \Magento\Config\Model\Config $configModel */ + + $configData = $this->filterNodes($configData); + + /** @var \Magento\Config\Model\Config $configModel */ $configModel = $this->_configFactory->create(['data' => $configData]); $configModel->save(); $this->_eventManager->dispatch('admin_system_config_save', [ @@ -188,4 +193,30 @@ public function execute() ] ); } + + /** + * Filters nodes by checking exist in system.xml + * + * @param array $configData + * @return array + */ + private function filterNodes(array $configData): array + { + $systemXmlConfig = $this->_configStructure->getFieldPaths(); + + foreach ($configData['groups'] as $configKey => $configFields) { + foreach (array_keys($configFields['fields']) as $configFieldName) { + $systemConfigArrayKey = $configData['section'] . '/' . + $configKey . '/' . + $configFieldName; + if (array_key_exists($systemConfigArrayKey, $systemXmlConfig)) { + continue; + } + + unset($configData['groups'][$configKey]['fields'][$configFieldName]); + } + } + + return $configData; + } } diff --git a/app/code/Magento/Config/Model/Config.php b/app/code/Magento/Config/Model/Config.php index 14997fb69b333..b1074e92cc949 100644 --- a/app/code/Magento/Config/Model/Config.php +++ b/app/code/Magento/Config/Model/Config.php @@ -6,7 +6,6 @@ namespace Magento\Config\Model; use Magento\Config\Model\Config\Reader\Source\Deployed\SettingChecker; -use Magento\Framework\App\Config\Initial as Reader; use Magento\Config\Model\Config\Structure\Element\Group; use Magento\Config\Model\Config\Structure\Element\Field; use Magento\Framework\App\ObjectManager; @@ -115,11 +114,6 @@ class Config extends \Magento\Framework\DataObject */ private $scopeTypeNormalizer; - /** - * @var Reader - */ - private $initialConfigReader; - /** * @param \Magento\Framework\App\Config\ReinitableConfigInterface $config * @param \Magento\Framework\Event\ManagerInterface $eventManager @@ -132,7 +126,6 @@ class Config extends \Magento\Framework\DataObject * @param array $data * @param ScopeResolverPool|null $scopeResolverPool * @param ScopeTypeNormalizer|null $scopeTypeNormalizer - * @param Reader|null $initialConfigReader * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -146,8 +139,7 @@ public function __construct( SettingChecker $settingChecker = null, array $data = [], ScopeResolverPool $scopeResolverPool = null, - ScopeTypeNormalizer $scopeTypeNormalizer = null, - ?Reader $initialConfigReader = null + ScopeTypeNormalizer $scopeTypeNormalizer = null ) { parent::__construct($data); $this->_eventManager = $eventManager; @@ -163,8 +155,6 @@ public function __construct( ?? ObjectManager::getInstance()->get(ScopeResolverPool::class); $this->scopeTypeNormalizer = $scopeTypeNormalizer ?? ObjectManager::getInstance()->get(ScopeTypeNormalizer::class); - $this->initialConfigReader = $initialConfigReader ?: - ObjectManager::getInstance()->get(Reader::class); } /** @@ -425,10 +415,6 @@ protected function _processGroup( continue; } - if ($this->isProtectedNode($groupPath . '/' . $fieldId)) { - continue; - } - $field = $this->getField($sectionPath, $groupId, $fieldId); /** @var \Magento\Framework\App\Config\ValueInterface $backendModel */ $backendModel = $field->hasBackendModel() @@ -692,22 +678,4 @@ public function getConfigDataValue($path, &$inherit = null, $configData = null) return $data; } - - /** - * Checks if node has 'protected' attribute by given path - * - * @param string $path - * @return bool - */ - private function isProtectedNode(string $path): bool - { - $currentConfigMetaData = $this->initialConfigReader->getMetadata()[$path] ?? - false; - - if ($currentConfigMetaData && isset($currentConfigMetaData['protected'])) { - return true; - } - - return false; - } } diff --git a/app/code/Magento/Store/etc/config.xml b/app/code/Magento/Store/etc/config.xml index 7a7d4d0a436f8..b9e7ac1c6aca0 100644 --- a/app/code/Magento/Store/etc/config.xml +++ b/app/code/Magento/Store/etc/config.xml @@ -113,7 +113,7 @@ 0,6 - + php php3 php4 diff --git a/lib/internal/Magento/Framework/App/Config/Initial/Converter.php b/lib/internal/Magento/Framework/App/Config/Initial/Converter.php index 491805dbdac96..67b671a7b1a31 100644 --- a/lib/internal/Magento/Framework/App/Config/Initial/Converter.php +++ b/lib/internal/Magento/Framework/App/Config/Initial/Converter.php @@ -8,7 +8,7 @@ namespace Magento\Framework\App\Config\Initial; /** - * Class Converter. Responsible for transform dom documents into an array + * Class Converter */ class Converter implements \Magento\Framework\Config\ConverterInterface { @@ -69,12 +69,6 @@ protected function _convertNode(\DOMNode $node, $path = '') if ($backendModel) { $this->_metadata[$path] = ['backendModel' => $backendModel->nodeValue]; } - - if ($node->getAttribute('protected')) { - $this->_metadata[$path] = [ - 'protected' => $node->attributes->getNamedItem('protected')->nodeValue - ]; - } } $nodeData = []; /** @var $childNode \DOMNode */ From 640cff8527d808c4388f2c09c5547e330b1cec61 Mon Sep 17 00:00:00 2001 From: roman Date: Wed, 30 Jan 2019 18:04:32 +0200 Subject: [PATCH 029/773] MC-5968: Fixed incorrect config override behavior --- .../Adminhtml/System/Config/SaveTest.php | 292 ------------------ .../System/Config/_files/expected_array.php | 35 --- .../System/Config/_files/files_array.php | 37 --- .../System/Config/_files/groups_array.php | 7 - 4 files changed, 371 deletions(-) delete mode 100644 app/code/Magento/Config/Test/Unit/Controller/Adminhtml/System/Config/SaveTest.php delete mode 100644 app/code/Magento/Config/Test/Unit/Controller/Adminhtml/System/Config/_files/expected_array.php delete mode 100644 app/code/Magento/Config/Test/Unit/Controller/Adminhtml/System/Config/_files/files_array.php delete mode 100644 app/code/Magento/Config/Test/Unit/Controller/Adminhtml/System/Config/_files/groups_array.php diff --git a/app/code/Magento/Config/Test/Unit/Controller/Adminhtml/System/Config/SaveTest.php b/app/code/Magento/Config/Test/Unit/Controller/Adminhtml/System/Config/SaveTest.php deleted file mode 100644 index 069a1c20b2966..0000000000000 --- a/app/code/Magento/Config/Test/Unit/Controller/Adminhtml/System/Config/SaveTest.php +++ /dev/null @@ -1,292 +0,0 @@ -_requestMock = $this->createMock(\Magento\Framework\App\Request\Http::class); - $this->_responseMock = $this->createMock(\Magento\Framework\App\Response\Http::class); - - $configStructureMock = $this->createMock(\Magento\Config\Model\Config\Structure::class); - $this->_configFactoryMock = $this->createMock(\Magento\Config\Model\Config\Factory::class); - $this->_eventManagerMock = $this->createMock(\Magento\Framework\Event\ManagerInterface::class); - - $helperMock = $this->createMock(\Magento\Backend\Helper\Data::class); - - $this->messageManagerMock = $this->createPartialMock( - \Magento\Framework\Message\Manager::class, - ['addSuccess', 'addException'] - ); - - $this->_authMock = $this->createPartialMock(\Magento\Backend\Model\Auth::class, ['getUser']); - - $this->_sectionMock = $this->createMock(\Magento\Config\Model\Config\Structure\Element\Section::class); - - $this->_cacheMock = $this->createMock(\Magento\Framework\App\Cache\Type\Layout::class); - - $configStructureMock->expects($this->any())->method('getElement')->willReturn($this->_sectionMock); - $configStructureMock->expects($this->any())->method('getSectionList')->willReturn( - [ - 'some_key_0' => '0', - 'some_key_1' => '1' - ] - ); - - $helperMock->expects($this->any())->method('getUrl')->willReturnArgument(0); - - $helper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); - - $this->resultRedirect = $this->getMockBuilder(\Magento\Backend\Model\View\Result\Redirect::class) - ->disableOriginalConstructor() - ->getMock(); - $this->resultRedirect->expects($this->atLeastOnce()) - ->method('setPath') - ->with('adminhtml/system_config/edit') - ->willReturnSelf(); - $resultRedirectFactory = $this->getMockBuilder(\Magento\Backend\Model\View\Result\RedirectFactory::class) - ->disableOriginalConstructor() - ->setMethods(['create']) - ->getMock(); - $resultRedirectFactory->expects($this->atLeastOnce()) - ->method('create') - ->willReturn($this->resultRedirect); - - $arguments = [ - 'request' => $this->_requestMock, - 'response' => $this->_responseMock, - 'helper' => $helperMock, - 'eventManager' => $this->_eventManagerMock, - 'auth' => $this->_authMock, - 'messageManager' => $this->messageManagerMock, - 'resultRedirectFactory' => $resultRedirectFactory - ]; - - $this->_sectionCheckerMock = $this->createMock( - \Magento\Config\Controller\Adminhtml\System\ConfigSectionChecker::class - ); - - $context = $helper->getObject(\Magento\Backend\App\Action\Context::class, $arguments); - $this->_controller = $this->getMockBuilder(\Magento\Config\Controller\Adminhtml\System\Config\Save::class) - ->setMethods(['deniedAction']) - ->setConstructorArgs( - [ - $context, - $configStructureMock, - $this->_sectionCheckerMock, - $this->_configFactoryMock, - $this->_cacheMock, - new \Magento\Framework\Stdlib\StringUtils(), - ] - ) - ->getMock(); - } - - public function testIndexActionWithAllowedSection() - { - $this->_sectionCheckerMock->expects($this->any())->method('isSectionAllowed')->will($this->returnValue(true)); - $this->messageManagerMock->expects($this->once())->method('addSuccess')->with('You saved the configuration.'); - - $groups = ['some_key' => 'some_value']; - $requestParamMap = [ - ['section', null, 'test_section'], - ['website', null, 'test_website'], - ['store', null, 'test_store'], - ]; - - $requestPostMap = [['groups', null, $groups], ['config_state', null, 'test_config_state']]; - - $this->_requestMock->expects($this->any())->method('getPost')->will($this->returnValueMap($requestPostMap)); - $this->_requestMock->expects($this->any())->method('getParam')->will($this->returnValueMap($requestParamMap)); - - $backendConfigMock = $this->createMock(\Magento\Config\Model\Config::class); - $backendConfigMock->expects($this->once())->method('save'); - - $params = [ - 'section' => 'test_section', - 'website' => 'test_website', - 'store' => 'test_store', - 'groups' => $groups, - ]; - $this->_configFactoryMock->expects( - $this->once() - )->method( - 'create' - )->with( - ['data' => $params] - )->will( - $this->returnValue($backendConfigMock) - ); - - $this->assertEquals($this->resultRedirect, $this->_controller->execute()); - } - - public function testIndexActionSaveState() - { - $this->_sectionCheckerMock->expects($this->any())->method('isSectionAllowed')->will($this->returnValue(false)); - $inputData = [ - 'some_key' => 'some_value', - 'some_key_0' => '0', - 'some_key_1' => 'some_value_1', - ]; - $extraData = [ - 'some_key_0' => '0', - 'some_key_1' => '1', - ]; - - $userMock = $this->createMock(\Magento\User\Model\User::class); - $userMock->expects($this->once())->method('saveExtra')->with(['configState' => $extraData]); - $this->_authMock->expects($this->once())->method('getUser')->will($this->returnValue($userMock)); - $this->_requestMock->expects( - $this->any() - )->method( - 'getPost' - )->with( - 'config_state' - )->will( - $this->returnValue($inputData) - ); - - $this->assertEquals($this->resultRedirect, $this->_controller->execute()); - } - - public function testIndexActionGetGroupForSave() - { - $this->_sectionCheckerMock->expects($this->any())->method('isSectionAllowed')->will($this->returnValue(true)); - - $fixturePath = __DIR__ . '/_files/'; - $groups = require_once $fixturePath . 'groups_array.php'; - $requestParamMap = [ - ['section', null, 'test_section'], - ['website', null, 'test_website'], - ['store', null, 'test_store'], - ]; - - $requestPostMap = [['groups', null, $groups], ['config_state', null, 'test_config_state']]; - - $files = require_once $fixturePath . 'files_array.php'; - - $this->_requestMock->expects($this->any())->method('getPost')->will($this->returnValueMap($requestPostMap)); - $this->_requestMock->expects($this->any())->method('getParam')->will($this->returnValueMap($requestParamMap)); - $this->_requestMock->expects( - $this->once() - )->method( - 'getFiles' - )->with( - 'groups' - )->will( - $this->returnValue($files) - ); - - $groupToSave = require_once $fixturePath . 'expected_array.php'; - - $params = [ - 'section' => 'test_section', - 'website' => 'test_website', - 'store' => 'test_store', - 'groups' => $groupToSave, - ]; - $backendConfigMock = $this->createMock(\Magento\Config\Model\Config::class); - $this->_configFactoryMock->expects( - $this->once() - )->method( - 'create' - )->with( - ['data' => $params] - )->will( - $this->returnValue($backendConfigMock) - ); - $backendConfigMock->expects($this->once())->method('save'); - - $this->assertEquals($this->resultRedirect, $this->_controller->execute()); - } - - public function testIndexActionSaveAdvanced() - { - $this->_sectionCheckerMock->expects($this->any())->method('isSectionAllowed')->will($this->returnValue(true)); - - $requestParamMap = [ - ['section', null, 'advanced'], - ['website', null, 'test_website'], - ['store', null, 'test_store'], - ]; - - $this->_requestMock->expects($this->any())->method('getParam')->will($this->returnValueMap($requestParamMap)); - - $backendConfigMock = $this->createMock(\Magento\Config\Model\Config::class); - $this->_configFactoryMock->expects( - $this->once() - )->method( - 'create' - )->will( - $this->returnValue($backendConfigMock) - ); - $backendConfigMock->expects($this->once())->method('save'); - - $this->_cacheMock->expects($this->once())->method('clean')->with(\Zend_Cache::CLEANING_MODE_ALL); - $this->assertEquals($this->resultRedirect, $this->_controller->execute()); - } -} diff --git a/app/code/Magento/Config/Test/Unit/Controller/Adminhtml/System/Config/_files/expected_array.php b/app/code/Magento/Config/Test/Unit/Controller/Adminhtml/System/Config/_files/expected_array.php deleted file mode 100644 index a74fd9ef1eedf..0000000000000 --- a/app/code/Magento/Config/Test/Unit/Controller/Adminhtml/System/Config/_files/expected_array.php +++ /dev/null @@ -1,35 +0,0 @@ - 'some.val', - 'group.1' => [ - 'fields' => [ - 'f1.1' => ['value' => 'f1.1.val'], - 'f1.2' => ['value' => 'f1.2.val'], - 'g1.1' => ['value' => 'g1.1.val'], - ], - ], - 'group.2' => [ - 'fields' => ['f2.1' => ['value' => 'f2.1.val'], 'f2.2' => ['value' => 'f2.2.val']], - 'groups' => [ - 'group.2.1' => [ - 'fields' => [ - 'f2.1.1' => ['value' => 'f2.1.1.val'], - 'f2.1.2' => ['value' => 'f2.1.2.val'], - ], - 'groups' => [ - 'group.2.1.1' => [ - 'fields' => [ - 'f2.1.1.1' => ['value' => 'f2.1.1.1.val'], - 'f2.1.1.2' => ['value' => 'f2.1.1.2.val'], - ], - ], - ], - ], - ], - ] -]; diff --git a/app/code/Magento/Config/Test/Unit/Controller/Adminhtml/System/Config/_files/files_array.php b/app/code/Magento/Config/Test/Unit/Controller/Adminhtml/System/Config/_files/files_array.php deleted file mode 100644 index 3bc0f7a466733..0000000000000 --- a/app/code/Magento/Config/Test/Unit/Controller/Adminhtml/System/Config/_files/files_array.php +++ /dev/null @@ -1,37 +0,0 @@ - [ - 'fields' => ['f1.1' => ['value' => 'f1.1.val'], 'f1.2' => ['value' => 'f1.2.val']], - ], - 'group.2' => [ - 'fields' => [ - 'f2.1' => ['value' => 'f2.1.val'], - 'f2.2' => ['value' => 'f2.2.val'], - 'f2.3' => ['value' => ''], - ], - 'groups' => [ - 'group.2.1' => [ - 'fields' => [ - 'f2.1.1' => ['value' => 'f2.1.1.val'], - 'f2.1.2' => ['value' => 'f2.1.2.val'], - 'f2.1.3' => ['value' => ''], - ], - 'groups' => [ - 'group.2.1.1' => [ - 'fields' => [ - 'f2.1.1.1' => ['value' => 'f2.1.1.1.val'], - 'f2.1.1.2' => ['value' => 'f2.1.1.2.val'], - 'f2.1.1.3' => ['value' => ''], - ], - ], - ], - ], - ], - ], - 'group.3' => 'some.data', -]; diff --git a/app/code/Magento/Config/Test/Unit/Controller/Adminhtml/System/Config/_files/groups_array.php b/app/code/Magento/Config/Test/Unit/Controller/Adminhtml/System/Config/_files/groups_array.php deleted file mode 100644 index dde65986e8a3e..0000000000000 --- a/app/code/Magento/Config/Test/Unit/Controller/Adminhtml/System/Config/_files/groups_array.php +++ /dev/null @@ -1,7 +0,0 @@ - 'some.val', 'group.1' => ['fields' => ['g1.1' => ['value' => 'g1.1.val']]]]; From c834a1198ac0f41a14c2f7856171744644b7c4a9 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun Date: Wed, 30 Jan 2019 10:33:35 -0600 Subject: [PATCH 030/773] MC-13650: SOAP gateway ignores enforced parameters --- app/code/Magento/Customer/etc/webapi.xml | 8 +-- .../Controller/Soap/Request/Handler.php | 49 +++++++++++-- .../Webapi/Model/Config/ClassReflector.php | 4 +- .../Magento/Webapi/Model/Config/Converter.php | 23 ++++-- .../Magento/Webapi/Model/ServiceMetadata.php | 22 ++++-- app/code/Magento/Webapi/Model/Soap/Config.php | 7 +- app/code/Magento/Webapi/etc/webapi.xsd | 1 + .../TestCase/Webapi/Adapter/Soap.php | 28 ++++++-- .../Customer/Api/AccountManagementMeTest.php | 71 +++++++++++++++---- .../Customer/Api/CustomerRepositoryTest.php | 10 ++- 10 files changed, 175 insertions(+), 48 deletions(-) diff --git a/app/code/Magento/Customer/etc/webapi.xml b/app/code/Magento/Customer/etc/webapi.xml index c536e26bcc82a..38717619406aa 100644 --- a/app/code/Magento/Customer/etc/webapi.xml +++ b/app/code/Magento/Customer/etc/webapi.xml @@ -134,7 +134,7 @@ - + @@ -143,7 +143,7 @@ %customer_id% - + @@ -244,7 +244,7 @@ - + @@ -259,7 +259,7 @@ - + diff --git a/app/code/Magento/Webapi/Controller/Soap/Request/Handler.php b/app/code/Magento/Webapi/Controller/Soap/Request/Handler.php index 486275ac69dc5..5e50cdee794ce 100644 --- a/app/code/Magento/Webapi/Controller/Soap/Request/Handler.php +++ b/app/code/Magento/Webapi/Controller/Soap/Request/Handler.php @@ -9,12 +9,14 @@ use Magento\Framework\Api\ExtensibleDataInterface; use Magento\Framework\Api\MetadataObjectInterface; use Magento\Framework\Api\SimpleDataObjectConverter; +use Magento\Framework\App\ObjectManager; use Magento\Framework\Webapi\Authorization; use Magento\Framework\Exception\AuthorizationException; use Magento\Framework\Reflection\DataObjectProcessor; use Magento\Framework\Webapi\ServiceInputProcessor; use Magento\Framework\Webapi\Request as SoapRequest; use Magento\Framework\Webapi\Exception as WebapiException; +use Magento\Webapi\Controller\Rest\ParamsOverrider; use Magento\Webapi\Model\Soap\Config as SoapConfig; use Magento\Framework\Reflection\MethodsMap; use Magento\Webapi\Model\ServiceMetadata; @@ -70,6 +72,11 @@ class Handler */ protected $methodsMapProcessor; + /** + * @var ParamsOverrider + */ + private $paramsOverrider; + /** * Initialize dependencies. * @@ -81,6 +88,7 @@ class Handler * @param ServiceInputProcessor $serviceInputProcessor * @param DataObjectProcessor $dataObjectProcessor * @param MethodsMap $methodsMapProcessor + * @param ParamsOverrider|null $paramsOverrider */ public function __construct( SoapRequest $request, @@ -90,7 +98,8 @@ public function __construct( SimpleDataObjectConverter $dataObjectConverter, ServiceInputProcessor $serviceInputProcessor, DataObjectProcessor $dataObjectProcessor, - MethodsMap $methodsMapProcessor + MethodsMap $methodsMapProcessor, + ?ParamsOverrider $paramsOverrider = null ) { $this->_request = $request; $this->_objectManager = $objectManager; @@ -100,6 +109,7 @@ public function __construct( $this->serviceInputProcessor = $serviceInputProcessor; $this->_dataObjectProcessor = $dataObjectProcessor; $this->methodsMapProcessor = $methodsMapProcessor; + $this->paramsOverrider = $paramsOverrider ?? ObjectManager::getInstance()->get(ParamsOverrider::class); } /** @@ -133,25 +143,52 @@ public function __call($operation, $arguments) ); } $service = $this->_objectManager->get($serviceClass); - $inputData = $this->_prepareRequestData($serviceClass, $serviceMethod, $arguments); + $inputData = $this->prepareOperationInput($serviceClass, $serviceMethodInfo, $arguments); $outputData = call_user_func_array([$service, $serviceMethod], $inputData); return $this->_prepareResponseData($outputData, $serviceClass, $serviceMethod); } /** - * Convert SOAP operation arguments into format acceptable by service method. + * Convert arguments received from SOAP server to arguments to pass to a service. * * @param string $serviceClass - * @param string $serviceMethod + * @param array $methodMetadata * @param array $arguments * @return array + * @throws WebapiException + * @throws \Magento\Framework\Exception\InputException */ - protected function _prepareRequestData($serviceClass, $serviceMethod, $arguments) + private function prepareOperationInput(string $serviceClass, array $methodMetadata, array $arguments): array { /** SoapServer wraps parameters into array. Thus this wrapping should be removed to get access to parameters. */ $arguments = reset($arguments); $arguments = $this->_dataObjectConverter->convertStdObjectToArray($arguments, true); - return $this->serviceInputProcessor->process($serviceClass, $serviceMethod, $arguments); + $arguments = $this->paramsOverrider->override($arguments, $methodMetadata[ServiceMetadata::KEY_ROUTE_PARAMS]); + + return $this->serviceInputProcessor->process( + $serviceClass, + $methodMetadata[ServiceMetadata::KEY_METHOD], + $arguments + ); + } + + /** + * Convert SOAP operation arguments into format acceptable by service method. + * + * @param string $serviceClass + * @param string $serviceMethod + * @param array $arguments + * @return array + * @deprecated + * @see Handler::prepareOperationInput() + */ + protected function _prepareRequestData($serviceClass, $serviceMethod, $arguments) + { + return $this->prepareOperationInput( + $serviceClass, + [ServiceMetadata::KEY_METHOD => $serviceMethod, ServiceMetadata::KEY_ROUTE_PARAMS => []], + $arguments + ); } /** diff --git a/app/code/Magento/Webapi/Model/Config/ClassReflector.php b/app/code/Magento/Webapi/Model/Config/ClassReflector.php index 7ce94c9bc6eeb..f4390a5a97b1e 100644 --- a/app/code/Magento/Webapi/Model/Config/ClassReflector.php +++ b/app/code/Magento/Webapi/Model/Config/ClassReflector.php @@ -31,7 +31,7 @@ public function __construct(\Magento\Framework\Reflection\TypeProcessor $typePro * Reflect methods in given class and set retrieved data into reader. * * @param string $className - * @param array $methods + * @param string[]|array $methods List of methods of methods' metadata. * @return array
array(
      *     $firstMethod => array(
      *         'documentation' => $methodDocumentation,
@@ -68,7 +68,7 @@ public function reflectClassMethods($className, $methods)
         /** @var \Zend\Code\Reflection\MethodReflection $methodReflection */
         foreach ($classReflection->getMethods() as $methodReflection) {
             $methodName = $methodReflection->getName();
-            if (array_key_exists($methodName, $methods)) {
+            if (in_array($methodName, $methods) || array_key_exists($methodName, $methods)) {
                 $data[$methodName] = $this->extractMethodData($methodReflection);
             }
         }
diff --git a/app/code/Magento/Webapi/Model/Config/Converter.php b/app/code/Magento/Webapi/Model/Config/Converter.php
index a85fcbb15329f..41b7e16056340 100644
--- a/app/code/Magento/Webapi/Model/Config/Converter.php
+++ b/app/code/Magento/Webapi/Model/Config/Converter.php
@@ -28,6 +28,7 @@ class Converter implements \Magento\Framework\Config\ConverterInterface
     const KEY_METHOD = 'method';
     const KEY_METHODS = 'methods';
     const KEY_DESCRIPTION = 'description';
+    const KEY_REAL_SERVICE_METHOD = 'realMethod';
     /**#@-*/
 
     /**
@@ -49,6 +50,10 @@ public function convert($source)
             $service = $route->getElementsByTagName('service')->item(0);
             $serviceClass = $service->attributes->getNamedItem('class')->nodeValue;
             $serviceMethod = $service->attributes->getNamedItem('method')->nodeValue;
+            $soapMethod = $serviceMethod;
+            if ($soapOperationNode = $route->attributes->getNamedItem('soapOperation')) {
+                $soapMethod = trim($soapOperationNode->nodeValue);
+            }
             $url = trim($route->attributes->getNamedItem('url')->nodeValue);
             $version = $this->convertVersion($url);
 
@@ -71,13 +76,13 @@ public function convert($source)
                 $resourcePermissionSet[] = $ref;
             }
 
-            if (!isset($serviceClassData[self::KEY_METHODS][$serviceMethod])) {
-                $serviceClassData[self::KEY_METHODS][$serviceMethod][self::KEY_ACL_RESOURCES] = $resourcePermissionSet;
+            if (!isset($serviceClassData[self::KEY_METHODS][$soapMethod])) {
+                $serviceClassData[self::KEY_METHODS][$soapMethod][self::KEY_ACL_RESOURCES] = $resourcePermissionSet;
             } else {
-                $serviceClassData[self::KEY_METHODS][$serviceMethod][self::KEY_ACL_RESOURCES] =
+                $serviceClassData[self::KEY_METHODS][$soapMethod][self::KEY_ACL_RESOURCES] =
                     array_unique(
                         array_merge(
-                            $serviceClassData[self::KEY_METHODS][$serviceMethod][self::KEY_ACL_RESOURCES],
+                            $serviceClassData[self::KEY_METHODS][$soapMethod][self::KEY_ACL_RESOURCES],
                             $resourcePermissionSet
                         )
                     );
@@ -100,10 +105,14 @@ public function convert($source)
             ];
 
             $serviceSecure = false;
-            if (isset($serviceClassData[self::KEY_METHODS][$serviceMethod][self::KEY_SECURE])) {
-                $serviceSecure = $serviceClassData[self::KEY_METHODS][$serviceMethod][self::KEY_SECURE];
+            if (isset($serviceClassData[self::KEY_METHODS][$soapMethod][self::KEY_SECURE])) {
+                $serviceSecure = $serviceClassData[self::KEY_METHODS][$soapMethod][self::KEY_SECURE];
+            }
+            if (!isset($serviceClassData[self::KEY_METHODS][$soapMethod][self::KEY_REAL_SERVICE_METHOD])) {
+                $serviceClassData[self::KEY_METHODS][$soapMethod][self::KEY_REAL_SERVICE_METHOD] = $serviceMethod;
             }
-            $serviceClassData[self::KEY_METHODS][$serviceMethod][self::KEY_SECURE] = $serviceSecure || $secure;
+            $serviceClassData[self::KEY_METHODS][$soapMethod][self::KEY_SECURE] = $serviceSecure || $secure;
+            $serviceClassData[self::KEY_METHODS][$soapMethod][self::KEY_DATA_PARAMETERS] = $data;
 
             $result[self::KEY_SERVICES][$serviceClass][$version] = $serviceClassData;
         }
diff --git a/app/code/Magento/Webapi/Model/ServiceMetadata.php b/app/code/Magento/Webapi/Model/ServiceMetadata.php
index b56aa84b94651..36f5819b03c98 100644
--- a/app/code/Magento/Webapi/Model/ServiceMetadata.php
+++ b/app/code/Magento/Webapi/Model/ServiceMetadata.php
@@ -36,6 +36,8 @@ class ServiceMetadata
 
     const KEY_ROUTE_PARAMS = 'parameters';
 
+    const KEY_METHOD_ALIAS = 'methodAlias';
+
     const SERVICES_CONFIG_CACHE_ID = 'services-services-config';
 
     const ROUTES_CONFIG_CACHE_ID = 'routes-services-config';
@@ -113,23 +115,31 @@ protected function initServicesMetadata()
         foreach ($this->config->getServices()[Converter::KEY_SERVICES] as $serviceClass => $serviceVersionData) {
             foreach ($serviceVersionData as $version => $serviceData) {
                 $serviceName = $this->getServiceName($serviceClass, $version);
+                $methods = [];
                 foreach ($serviceData[Converter::KEY_METHODS] as $methodName => $methodMetadata) {
                     $services[$serviceName][self::KEY_SERVICE_METHODS][$methodName] = [
-                        self::KEY_METHOD => $methodName,
+                        self::KEY_METHOD => $methodMetadata[Converter::KEY_REAL_SERVICE_METHOD],
                         self::KEY_IS_REQUIRED => (bool)$methodMetadata[Converter::KEY_SECURE],
                         self::KEY_IS_SECURE => $methodMetadata[Converter::KEY_SECURE],
                         self::KEY_ACL_RESOURCES => $methodMetadata[Converter::KEY_ACL_RESOURCES],
+                        self::KEY_METHOD_ALIAS => $methodName,
+                        self::KEY_ROUTE_PARAMS => $methodMetadata[Converter::KEY_DATA_PARAMETERS]
                     ];
                     $services[$serviceName][self::KEY_CLASS] = $serviceClass;
+                    $methods[] = $methodMetadata[Converter::KEY_REAL_SERVICE_METHOD];
                 }
+                unset($methodName, $methodMetadata);
                 $reflectedMethodsMetadata = $this->classReflector->reflectClassMethods(
                     $serviceClass,
-                    $services[$serviceName][self::KEY_SERVICE_METHODS]
-                );
-                $services[$serviceName][self::KEY_SERVICE_METHODS] = array_merge_recursive(
-                    $services[$serviceName][self::KEY_SERVICE_METHODS],
-                    $reflectedMethodsMetadata
+                    $methods
                 );
+                foreach ($services[$serviceName][self::KEY_SERVICE_METHODS] as $methodName => &$methodMetadata) {
+                    $methodMetadata = array_merge(
+                        $methodMetadata,
+                        $reflectedMethodsMetadata[$methodMetadata[self::KEY_METHOD]]
+                    );
+                }
+                unset($methodName, $methodMetadata);
                 $services[$serviceName][Converter::KEY_DESCRIPTION] = $this->classReflector->extractClassDescription(
                     $serviceClass
                 );
diff --git a/app/code/Magento/Webapi/Model/Soap/Config.php b/app/code/Magento/Webapi/Model/Soap/Config.php
index ea269d8703a47..190280ff8f004 100644
--- a/app/code/Magento/Webapi/Model/Soap/Config.php
+++ b/app/code/Magento/Webapi/Model/Soap/Config.php
@@ -75,12 +75,14 @@ protected function getSoapOperations($requestedServices)
                 foreach ($serviceData[ServiceMetadata::KEY_SERVICE_METHODS] as $methodData) {
                     $method = $methodData[ServiceMetadata::KEY_METHOD];
                     $class = $serviceData[ServiceMetadata::KEY_CLASS];
-                    $operationName = $serviceName . ucfirst($method);
+                    $operation = $methodData[ServiceMetadata::KEY_METHOD_ALIAS];
+                    $operationName = $serviceName . ucfirst($operation);
                     $this->soapOperations[$operationName] = [
                         ServiceMetadata::KEY_CLASS => $class,
                         ServiceMetadata::KEY_METHOD => $method,
                         ServiceMetadata::KEY_IS_SECURE => $methodData[ServiceMetadata::KEY_IS_SECURE],
                         ServiceMetadata::KEY_ACL_RESOURCES => $methodData[ServiceMetadata::KEY_ACL_RESOURCES],
+                        ServiceMetadata::KEY_ROUTE_PARAMS => $methodData[ServiceMetadata::KEY_ROUTE_PARAMS]
                     ];
                 }
             }
@@ -110,7 +112,8 @@ public function getServiceMethodInfo($soapOperation, $requestedServices)
             ServiceMetadata::KEY_CLASS => $soapOperations[$soapOperation][ServiceMetadata::KEY_CLASS],
             ServiceMetadata::KEY_METHOD => $soapOperations[$soapOperation][ServiceMetadata::KEY_METHOD],
             ServiceMetadata::KEY_IS_SECURE => $soapOperations[$soapOperation][ServiceMetadata::KEY_IS_SECURE],
-            ServiceMetadata::KEY_ACL_RESOURCES => $soapOperations[$soapOperation][ServiceMetadata::KEY_ACL_RESOURCES]
+            ServiceMetadata::KEY_ACL_RESOURCES => $soapOperations[$soapOperation][ServiceMetadata::KEY_ACL_RESOURCES],
+            ServiceMetadata::KEY_ROUTE_PARAMS => $soapOperations[$soapOperation][ServiceMetadata::KEY_ROUTE_PARAMS]
         ];
     }
 
diff --git a/app/code/Magento/Webapi/etc/webapi.xsd b/app/code/Magento/Webapi/etc/webapi.xsd
index 7a237cba2cfd2..e3b90bd5d5ad1 100644
--- a/app/code/Magento/Webapi/etc/webapi.xsd
+++ b/app/code/Magento/Webapi/etc/webapi.xsd
@@ -34,6 +34,7 @@
         
         
         
+        
     
 
     
diff --git a/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/Webapi/Adapter/Soap.php b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/Webapi/Adapter/Soap.php
index e2e32c119af21..caba692fc0633 100644
--- a/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/Webapi/Adapter/Soap.php
+++ b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/Webapi/Adapter/Soap.php
@@ -21,7 +21,7 @@ class Soap implements \Magento\TestFramework\TestCase\Webapi\AdapterInterface
      *
      * @var \Zend\Soap\Client[]
      */
-    protected $_soapClients = [];
+    protected $_soapClients = ['custom' => [], 'default' => []];
 
     /**
      * @var \Magento\Webapi\Model\Soap\Config
@@ -75,12 +75,28 @@ protected function _getSoapClient($serviceInfo, $storeCode = null)
             [$this->_getSoapServiceName($serviceInfo) . $this->_getSoapServiceVersion($serviceInfo)],
             $storeCode
         );
-        /** Check if there is SOAP client initialized with requested WSDL available */
-        if (!isset($this->_soapClients[$wsdlUrl])) {
-            $token = isset($serviceInfo['soap']['token']) ? $serviceInfo['soap']['token'] : null;
-            $this->_soapClients[$wsdlUrl] = $this->instantiateSoapClient($wsdlUrl, $token);
+        /** @var \Zend\Soap\Client $soapClient */
+        $soapClient = null;
+        if (isset($serviceInfo['soap']['token'])) {
+            $token = $serviceInfo['soap']['token'];
+            if (array_key_exists($token, $this->_soapClients['custom'])
+                && array_key_exists($wsdlUrl, $this->_soapClients['custom'][$token])
+            ) {
+                $soapClient = $this->_soapClients['custom'][$token][$wsdlUrl];
+            } else {
+                if (!array_key_exists($token, $this->_soapClients['custom'])) {
+                    $this->_soapClients['custom'][$token] = [];
+                }
+                $soapClient = $this->_soapClients['custom'][$token][$wsdlUrl]
+                    = $this->instantiateSoapClient($wsdlUrl, $token);
+            }
+        } else {
+            if (!isset($this->_soapClients[$wsdlUrl])) {
+                $this->_soapClients['default'][$wsdlUrl] = $this->instantiateSoapClient($wsdlUrl, null);
+            }
+            $soapClient = $this->_soapClients['default'][$wsdlUrl];
         }
-        return $this->_soapClients[$wsdlUrl];
+        return $soapClient;
     }
 
     /**
diff --git a/dev/tests/api-functional/testsuite/Magento/Customer/Api/AccountManagementMeTest.php b/dev/tests/api-functional/testsuite/Magento/Customer/Api/AccountManagementMeTest.php
index e85523cf40ea6..31894c1332ad5 100644
--- a/dev/tests/api-functional/testsuite/Magento/Customer/Api/AccountManagementMeTest.php
+++ b/dev/tests/api-functional/testsuite/Magento/Customer/Api/AccountManagementMeTest.php
@@ -8,6 +8,7 @@
 
 use Magento\Customer\Api\Data\CustomerInterface;
 use Magento\Customer\Model\CustomerRegistry;
+use Magento\Integration\Api\CustomerTokenServiceInterface;
 use Magento\Integration\Model\Oauth\Token as TokenModel;
 use Magento\TestFramework\Helper\Bootstrap;
 use Magento\TestFramework\Helper\Customer as CustomerHelper;
@@ -23,6 +24,9 @@ class AccountManagementMeTest extends \Magento\TestFramework\TestCase\WebapiAbst
 {
     const RESOURCE_PATH = '/V1/customers/me';
     const RESOURCE_PATH_CUSTOMER_TOKEN = "/V1/integration/customer/token";
+    const REPO_SERVICE = 'customerCustomerRepositoryV1';
+    const ACCOUNT_SERVICE = 'customerAccountManagementV1';
+    const SERVICE_VERSION = 'V1';
 
     /**
      * @var CustomerRepositoryInterface
@@ -59,13 +63,16 @@ class AccountManagementMeTest extends \Magento\TestFramework\TestCase\WebapiAbst
      */
     private $dataObjectProcessor;
 
+    /**
+     * @var CustomerTokenServiceInterface
+     */
+    private $tokenService;
+
     /**
      * Execute per test initialization.
      */
     public function setUp()
     {
-        $this->_markTestAsRestOnly();
-
         $this->customerRegistry = Bootstrap::getObjectManager()->get(
             \Magento\Customer\Model\CustomerRegistry::class
         );
@@ -80,6 +87,7 @@ public function setUp()
 
         $this->customerHelper = new CustomerHelper();
         $this->customerData = $this->customerHelper->createSampleCustomer();
+        $this->tokenService = Bootstrap::getObjectManager()->get(CustomerTokenServiceInterface::class);
 
         // get token
         $this->resetTokenForCustomerSampleData();
@@ -114,8 +122,17 @@ public function testChangePassword()
                 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_PUT,
                 'token' => $this->token,
             ],
+            'soap' => [
+                'service' => self::ACCOUNT_SERVICE,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::ACCOUNT_SERVICE .'ChangePasswordById',
+                'token' => $this->token
+            ]
         ];
         $requestData = ['currentPassword' => 'test@123', 'newPassword' => '123@test'];
+        if (TESTS_WEB_API_ADAPTER === 'soap') {
+            $requestData['customerId'] = 0;
+        }
         $this->assertTrue($this->_webApiCall($serviceInfo, $requestData));
 
         $customerResponseData = $this->customerAccountManagement
@@ -141,6 +158,12 @@ public function testUpdateCustomer()
                 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_PUT,
                 'token' => $this->token,
             ],
+            'soap' => [
+                'service' => self::REPO_SERVICE,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::REPO_SERVICE .'SaveSelf',
+                'token' => $this->token
+            ]
         ];
         $requestData = ['customer' => $updatedCustomerData];
 
@@ -171,8 +194,18 @@ public function testGetCustomerData()
                 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET,
                 'token' => $this->token,
             ],
+            'soap' => [
+                'service' => self::REPO_SERVICE,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::REPO_SERVICE .'GetSelf',
+                'token' => $this->token
+            ]
         ];
-        $customerDetailsResponse = $this->_webApiCall($serviceInfo);
+        $arguments = [];
+        if (TESTS_WEB_API_ADAPTER === 'soap') {
+            $arguments['customerId'] = 0;
+        }
+        $customerDetailsResponse = $this->_webApiCall($serviceInfo, $arguments);
 
         unset($expectedCustomerDetails['custom_attributes']);
         unset($customerDetailsResponse['custom_attributes']); //for REST
@@ -188,8 +221,17 @@ public function testGetCustomerActivateCustomer()
                 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_PUT,
                 'token' => $this->token,
             ],
+            'soap' => [
+                'service' => self::ACCOUNT_SERVICE,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::ACCOUNT_SERVICE .'ActivateById',
+                'token' => $this->token
+            ]
         ];
         $requestData = ['confirmationKey' => $this->customerData[CustomerInterface::CONFIRMATION]];
+        if (TESTS_WEB_API_ADAPTER === 'soap') {
+            $requestData['customerId'] = 0;
+        }
         $customerResponseData = $this->_webApiCall($serviceInfo, $requestData);
         $this->assertEquals($this->customerData[CustomerInterface::ID], $customerResponseData[CustomerInterface::ID]);
         // Confirmation key is removed after confirmation
@@ -220,6 +262,12 @@ public function testGetDefaultBillingAddress()
                 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET,
                 'token' => $this->token,
             ],
+            'soap' => [
+                'service' => self::ACCOUNT_SERVICE,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::ACCOUNT_SERVICE .'GetMyDefaultBillingAddress',
+                'token' => $this->token
+            ]
         ];
         $requestData = ['customerId' => $fixtureCustomerId];
         $addressData = $this->_webApiCall($serviceInfo, $requestData);
@@ -241,6 +289,12 @@ public function testGetDefaultShippingAddress()
                 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET,
                 'token' => $this->token,
             ],
+            'soap' => [
+                'service' => self::ACCOUNT_SERVICE,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::ACCOUNT_SERVICE .'GetMyDefaultShippingAddress',
+                'token' => $this->token
+            ]
         ];
         $requestData = ['customerId' => $fixtureCustomerId];
         $addressData = $this->_webApiCall($serviceInfo, $requestData);
@@ -324,14 +378,7 @@ protected function resetTokenForCustomerSampleData()
      */
     protected function resetTokenForCustomer($username, $password)
     {
-        // get customer ID token
-        $serviceInfo = [
-            'rest' => [
-                'resourcePath' => self::RESOURCE_PATH_CUSTOMER_TOKEN,
-                'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST,
-            ],
-        ];
-        $requestData = ['username' => $username, 'password' => $password];
-        $this->token = $this->_webApiCall($serviceInfo, $requestData);
+        $this->token = $this->tokenService->createCustomerAccessToken($username, $password);
+        $this->customerRegistry->remove($this->customerRepository->get($username)->getId());
     }
 }
diff --git a/dev/tests/api-functional/testsuite/Magento/Customer/Api/CustomerRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Customer/Api/CustomerRepositoryTest.php
index 8f84f485fc2ae..b4f8304dd4873 100644
--- a/dev/tests/api-functional/testsuite/Magento/Customer/Api/CustomerRepositoryTest.php
+++ b/dev/tests/api-functional/testsuite/Magento/Customer/Api/CustomerRepositoryTest.php
@@ -147,12 +147,10 @@ public function tearDown()
      * Validate update by invalid customer.
      *
      * @expectedException \Exception
-     * @expectedExceptionMessage The consumer isn't authorized to access %resources.
+     * @expectedExceptionMessageRegExp  /The consumer isn't authorized to access \%resources.|Function \("customerCustomerRepositoryV1Save"\) is not a valid method for this service/
      */
     public function testInvalidCustomerUpdate()
     {
-        $this->_markTestAsRestOnly();
-
         //Create first customer and retrieve customer token.
         $firstCustomerData = $this->_createCustomer();
 
@@ -181,6 +179,12 @@ public function testInvalidCustomerUpdate()
                 'resourcePath' => self::RESOURCE_PATH . "/{$customerData[Customer::ID]}",
                 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_PUT,
                 'token' => $token,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Save',
+                'token' => $token
             ]
         ];
 

From e277a722f0b538d1fd0cbd27d62661f7fda688e7 Mon Sep 17 00:00:00 2001
From: Oleksandr Gorkun 
Date: Wed, 30 Jan 2019 13:04:36 -0600
Subject: [PATCH 031/773] MC-13650: SOAP gateway ignores enforced parameters

---
 .../Magento/Webapi/Model/Config/Converter.php |  11 +-
 .../Controller/Soap/Request/HandlerTest.php   | 127 -----
 .../Test/Unit/Model/Config/_files/webapi.php  |  20 +-
 .../Test/Unit/Model/Config/_files/webapi.xml  |   2 +-
 .../Test/Unit/Model/ServiceMetadataTest.php   | 469 ------------------
 .../TestCase/Webapi/Adapter/Soap.php          |   2 +-
 .../Webapi/Model/Config/_files/webapi.php     |  91 +++-
 .../Webapi/Model/Config/_files/webapiA.xml    |   9 +
 .../Magento/Webapi/Model/Soap/ConfigTest.php  |   5 +-
 9 files changed, 114 insertions(+), 622 deletions(-)
 delete mode 100644 app/code/Magento/Webapi/Test/Unit/Controller/Soap/Request/HandlerTest.php
 delete mode 100644 app/code/Magento/Webapi/Test/Unit/Model/ServiceMetadataTest.php

diff --git a/app/code/Magento/Webapi/Model/Config/Converter.php b/app/code/Magento/Webapi/Model/Config/Converter.php
index 41b7e16056340..837a0f84423ad 100644
--- a/app/code/Magento/Webapi/Model/Config/Converter.php
+++ b/app/code/Magento/Webapi/Model/Config/Converter.php
@@ -32,7 +32,7 @@ class Converter implements \Magento\Framework\Config\ConverterInterface
     /**#@-*/
 
     /**
-     * {@inheritdoc}
+     * @inheritdoc
      * @SuppressWarnings(PHPMD.CyclomaticComplexity)
      * @SuppressWarnings(PHPMD.NPathComplexity)
      */
@@ -75,6 +75,8 @@ public function convert($source)
                 // For SOAP
                 $resourcePermissionSet[] = $ref;
             }
+            $data = $this->convertMethodParameters($route->getElementsByTagName('parameter'));
+            $serviceData = $data;
 
             if (!isset($serviceClassData[self::KEY_METHODS][$soapMethod])) {
                 $serviceClassData[self::KEY_METHODS][$soapMethod][self::KEY_ACL_RESOURCES] = $resourcePermissionSet;
@@ -86,12 +88,12 @@ public function convert($source)
                             $resourcePermissionSet
                         )
                     );
+                $serviceData = [];
             }
 
             $method = $route->attributes->getNamedItem('method')->nodeValue;
             $secureNode = $route->attributes->getNamedItem('secure');
             $secure = $secureNode ? (bool)trim($secureNode->nodeValue) : false;
-            $data = $this->convertMethodParameters($route->getElementsByTagName('parameter'));
 
             // We could handle merging here by checking if the route already exists
             $result[self::KEY_ROUTES][$url][$method] = [
@@ -112,7 +114,7 @@ public function convert($source)
                 $serviceClassData[self::KEY_METHODS][$soapMethod][self::KEY_REAL_SERVICE_METHOD] = $serviceMethod;
             }
             $serviceClassData[self::KEY_METHODS][$soapMethod][self::KEY_SECURE] = $serviceSecure || $secure;
-            $serviceClassData[self::KEY_METHODS][$soapMethod][self::KEY_DATA_PARAMETERS] = $data;
+            $serviceClassData[self::KEY_METHODS][$soapMethod][self::KEY_DATA_PARAMETERS] = $serviceData;
 
             $result[self::KEY_SERVICES][$serviceClass][$version] = $serviceClassData;
         }
@@ -156,7 +158,8 @@ protected function convertMethodParameters($parameters)
 
     /**
      * Derive the version from the provided URL.
-     * Assumes the version is the first portion of the URL. For example, '/V1/customers'
+     *
+     * Assumes the version is the first portion of the URL. For example, '/V1/customers'.
      *
      * @param string $url
      * @return string
diff --git a/app/code/Magento/Webapi/Test/Unit/Controller/Soap/Request/HandlerTest.php b/app/code/Magento/Webapi/Test/Unit/Controller/Soap/Request/HandlerTest.php
deleted file mode 100644
index 4094811b1386e..0000000000000
--- a/app/code/Magento/Webapi/Test/Unit/Controller/Soap/Request/HandlerTest.php
+++ /dev/null
@@ -1,127 +0,0 @@
-_apiConfigMock = $this->getMockBuilder(\Magento\Webapi\Model\Soap\Config::class)
-            ->setMethods(['getServiceMethodInfo'])->disableOriginalConstructor()->getMock();
-        $this->_requestMock = $this->createMock(\Magento\Framework\Webapi\Request::class);
-        $this->_objectManagerMock = $this->createMock(\Magento\Framework\ObjectManagerInterface::class);
-        $this->_authorizationMock = $this->createMock(\Magento\Framework\Webapi\Authorization::class);
-        $this->_dataObjectConverter = $this->createPartialMock(
-            \Magento\Framework\Api\SimpleDataObjectConverter::class,
-            ['convertStdObjectToArray']
-        );
-        $this->_serviceInputProcessorMock = $this->createMock(\Magento\Framework\Webapi\ServiceInputProcessor::class);
-        $this->_dataObjectProcessorMock = $this->createMock(\Magento\Framework\Reflection\DataObjectProcessor::class);
-        $this->_methodsMapProcessorMock = $this->createMock(\Magento\Framework\Reflection\MethodsMap::class);
-
-        /** Initialize SUT. */
-        $this->_handler = new \Magento\Webapi\Controller\Soap\Request\Handler(
-            $this->_requestMock,
-            $this->_objectManagerMock,
-            $this->_apiConfigMock,
-            $this->_authorizationMock,
-            $this->_dataObjectConverter,
-            $this->_serviceInputProcessorMock,
-            $this->_dataObjectProcessorMock,
-            $this->_methodsMapProcessorMock
-        );
-        parent::setUp();
-    }
-
-    public function testCall()
-    {
-        $requestedServices = ['requestedServices'];
-        $this->_requestMock->expects($this->once())
-            ->method('getRequestedServices')
-            ->will($this->returnValue($requestedServices));
-        $this->_dataObjectConverter->expects($this->once())
-            ->method('convertStdObjectToArray')
-            ->will($this->returnValue(['field' => 1]));
-        $this->_methodsMapProcessorMock->method('getMethodReturnType')->willReturn('string');
-        $operationName = 'soapOperation';
-        $className = \Magento\Framework\DataObject::class;
-        $methodName = 'testMethod';
-        $isSecure = false;
-        $aclResources = [['Magento_TestModule::resourceA']];
-        $this->_apiConfigMock->expects($this->once())
-            ->method('getServiceMethodInfo')
-            ->with($operationName, $requestedServices)
-            ->will(
-                $this->returnValue(
-                    [
-                        ServiceMetadata::KEY_CLASS => $className,
-                        ServiceMetadata::KEY_METHOD => $methodName,
-                        ServiceMetadata::KEY_IS_SECURE => $isSecure,
-                        ServiceMetadata::KEY_ACL_RESOURCES => $aclResources,
-                    ]
-                )
-            );
-
-        $this->_authorizationMock->expects($this->once())->method('isAllowed')->will($this->returnValue(true));
-        $serviceMock = $this->getMockBuilder($className)
-            ->disableOriginalConstructor()
-            ->setMethods([$methodName])
-            ->getMock();
-
-        $serviceResponse = ['foo' => 'bar'];
-        $serviceMock->expects($this->once())->method($methodName)->will($this->returnValue($serviceResponse));
-        $this->_objectManagerMock->expects($this->once())->method('get')->with($className)
-            ->will($this->returnValue($serviceMock));
-        $this->_serviceInputProcessorMock
-            ->expects($this->once())
-            ->method('process')
-            ->will($this->returnArgument(2));
-
-        /** Execute SUT. */
-        $this->assertEquals(
-            ['result' => $serviceResponse],
-            $this->_handler->__call($operationName, [(object)['field' => 1]])
-        );
-    }
-}
diff --git a/app/code/Magento/Webapi/Test/Unit/Model/Config/_files/webapi.php b/app/code/Magento/Webapi/Test/Unit/Model/Config/_files/webapi.php
index 2df8697b19857..49c794bf773b9 100644
--- a/app/code/Magento/Webapi/Test/Unit/Model/Config/_files/webapi.php
+++ b/app/code/Magento/Webapi/Test/Unit/Model/Config/_files/webapi.php
@@ -13,13 +13,29 @@
                             'Magento_Customer::read',
                         ],
                         'secure' => false,
+                        'realMethod' => 'getById',
+                        'parameters' => []
                     ],
                     'save' => [
                         'resources' => [
-                            'Magento_Customer::customer_self',
                             'Magento_Customer::manage'
                         ],
+                        'secure' => false,
+                        'realMethod' => 'save',
+                        'parameters' => []
+                    ],
+                    'saveSelf' => [
+                        'resources' => [
+                            'Magento_Customer::customer_self'
+                        ],
                         'secure' => true,
+                        'realMethod' => 'save',
+                        'parameters' => [
+                            'id' => [
+                                'force' => false,
+                                'value' => null,
+                            ],
+                        ],
                     ],
                     'deleteById' => [
                         'resources' => [
@@ -27,6 +43,8 @@
                             'Magento_Customer::delete',
                         ],
                         'secure' => false,
+                        'realMethod' => 'deleteById',
+                        'parameters' => []
                     ],
                 ],
             ],
diff --git a/app/code/Magento/Webapi/Test/Unit/Model/Config/_files/webapi.xml b/app/code/Magento/Webapi/Test/Unit/Model/Config/_files/webapi.xml
index b08b3087bfc1f..50b9abb8f17ae 100644
--- a/app/code/Magento/Webapi/Test/Unit/Model/Config/_files/webapi.xml
+++ b/app/code/Magento/Webapi/Test/Unit/Model/Config/_files/webapi.xml
@@ -25,7 +25,7 @@
             %customer_id%
         
     
-    
+    
         
         
             
diff --git a/app/code/Magento/Webapi/Test/Unit/Model/ServiceMetadataTest.php b/app/code/Magento/Webapi/Test/Unit/Model/ServiceMetadataTest.php
deleted file mode 100644
index a24878c408e13..0000000000000
--- a/app/code/Magento/Webapi/Test/Unit/Model/ServiceMetadataTest.php
+++ /dev/null
@@ -1,469 +0,0 @@
-configMock = $this->createMock(Config::class);
-        $this->cacheMock = $this->createMock(Webapi::class);
-        $this->classReflectorMock = $this->createMock(ClassReflector::class);
-        $this->typeProcessorMock = $this->createMock(TypeProcessor::class);
-        $this->serializerMock = $this->createMock(SerializerInterface::class);
-
-        $this->serviceMetadata = $objectManager->getObject(
-            ServiceMetadata::class,
-            [
-                'config' => $this->configMock,
-                'cache' => $this->cacheMock,
-                'classReflector' => $this->classReflectorMock,
-                'typeProcessor' => $this->typeProcessorMock,
-                'serializer' => $this->serializerMock
-            ]
-        );
-    }
-
-    public function testGetServicesConfig()
-    {
-        $servicesConfig = ['foo' => 'bar'];
-        $typeData = ['bar' => 'foo'];
-        $serializedServicesConfig = 'serialized services config';
-        $serializedTypeData = 'serialized type data';
-        $this->cacheMock->expects($this->at(0))
-            ->method('load')
-            ->with(ServiceMetadata::SERVICES_CONFIG_CACHE_ID)
-            ->willReturn($serializedServicesConfig);
-        $this->cacheMock->expects($this->at(1))
-            ->method('load')
-            ->with(ServiceMetadata::REFLECTED_TYPES_CACHE_ID)
-            ->willReturn($serializedTypeData);
-        $this->serializerMock->expects($this->at(0))
-            ->method('unserialize')
-            ->with($serializedServicesConfig)
-            ->willReturn($servicesConfig);
-        $this->serializerMock->expects($this->at(1))
-            ->method('unserialize')
-            ->with($serializedTypeData)
-            ->willReturn($typeData);
-        $this->typeProcessorMock->expects($this->once())
-            ->method('setTypesData')
-            ->with($typeData);
-        $this->serviceMetadata->getServicesConfig();
-        $this->assertEquals($servicesConfig, $this->serviceMetadata->getServicesConfig());
-    }
-
-    /**
-     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
-     */
-    public function testGetServicesConfigNoCache()
-    {
-        $servicesConfig = [
-            'services' => [
-                CustomerRepositoryInterface::class => [
-                    'V1' => [
-                        'methods' => [
-                            'getById' => [
-                                'resources' => [
-                                    [
-                                        'Magento_Customer::customer',
-                                    ]
-                                ],
-                                'secure' => false
-                            ]
-                        ]
-                    ]
-                ]
-            ]
-        ];
-        $methodsReflectionData = [
-            'getById' => [
-                'documentation' => 'Get customer by customer ID.',
-                'interface' => [
-                    'in' => [
-                        'parameters' => [
-                            'customerId' => [
-                                'type' => 'int',
-                                'required' => true,
-                                'documentation' => null
-                            ]
-                        ]
-                    ],
-                    'out' => [
-                        'parameters' => [
-                            'result' => [
-                                'type' => 'CustomerDataCustomerInterface',
-                                'required' => true,
-                                'documentation' => null
-                            ]
-                        ]
-                    ]
-                ]
-            ]
-        ];
-        $servicesMetadata = [
-            'customerCustomerRepositoryV1' => [
-                'methods' => array_merge_recursive(
-                    [
-                        'getById' => [
-                            'resources' => [
-                                [
-                                    'Magento_Customer::customer',
-                                ],
-                            ],
-                            'method' => 'getById',
-                            'inputRequired' => false,
-                            'isSecure' => false,
-                        ]
-                    ],
-                    $methodsReflectionData
-                ),
-                'class' => CustomerRepositoryInterface::class,
-                'description' => 'Customer CRUD interface.'
-            ]
-        ];
-        $typeData = [
-            'CustomerDataCustomerInterface' => [
-                'documentation' => 'Customer interface.',
-                'parameters' => [
-                    'id' => [
-                        'type' => 'int',
-                        'required' => false,
-                        'documentation' => 'Customer id'
-                    ]
-                ]
-            ]
-        ];
-        $serializedServicesConfig = 'serialized services config';
-        $serializedTypeData = 'serialized type data';
-        $this->cacheMock->expects($this->at(0))
-            ->method('load')
-            ->with(ServiceMetadata::SERVICES_CONFIG_CACHE_ID)
-            ->willReturn(false);
-        $this->cacheMock->expects($this->at(1))
-            ->method('load')
-            ->with(ServiceMetadata::REFLECTED_TYPES_CACHE_ID)
-            ->willReturn(false);
-        $this->serializerMock->expects($this->never())
-            ->method('unserialize');
-        $this->configMock->expects($this->once())
-            ->method('getServices')
-            ->willReturn($servicesConfig);
-        $this->classReflectorMock->expects($this->once())
-            ->method('reflectClassMethods')
-            ->willReturn($methodsReflectionData);
-        $this->classReflectorMock->expects($this->once())
-            ->method('extractClassDescription')
-            ->with(CustomerRepositoryInterface::class)
-            ->willReturn('Customer CRUD interface.');
-        $this->typeProcessorMock->expects($this->once())
-            ->method('getTypesData')
-            ->willReturn($typeData);
-        $this->serializerMock->expects($this->at(0))
-            ->method('serialize')
-            ->with($servicesMetadata)
-            ->willReturn($serializedServicesConfig);
-        $this->serializerMock->expects($this->at(1))
-            ->method('serialize')
-            ->with($typeData)
-            ->willReturn($serializedTypeData);
-        $this->cacheMock->expects($this->at(2))
-            ->method('save')
-            ->with(
-                $serializedServicesConfig,
-                ServiceMetadata::SERVICES_CONFIG_CACHE_ID
-            );
-        $this->cacheMock->expects($this->at(3))
-            ->method('save')
-            ->with(
-                $serializedTypeData,
-                ServiceMetadata::REFLECTED_TYPES_CACHE_ID
-            );
-        $this->serviceMetadata->getServicesConfig();
-        $this->assertEquals($servicesMetadata, $this->serviceMetadata->getServicesConfig());
-    }
-
-    public function testGetRoutesConfig()
-    {
-        $routesConfig = ['foo' => 'bar'];
-        $typeData = ['bar' => 'foo'];
-        $serializedRoutesConfig = 'serialized routes config';
-        $serializedTypeData = 'serialized type data';
-        $this->cacheMock->expects($this->at(0))
-            ->method('load')
-            ->with(ServiceMetadata::ROUTES_CONFIG_CACHE_ID)
-            ->willReturn($serializedRoutesConfig);
-        $this->cacheMock->expects($this->at(1))
-            ->method('load')
-            ->with(ServiceMetadata::REFLECTED_TYPES_CACHE_ID)
-            ->willReturn($serializedTypeData);
-        $this->serializerMock->expects($this->at(0))
-            ->method('unserialize')
-            ->with($serializedRoutesConfig)
-            ->willReturn($routesConfig);
-        $this->serializerMock->expects($this->at(1))
-            ->method('unserialize')
-            ->with($serializedTypeData)
-            ->willReturn($typeData);
-        $this->typeProcessorMock->expects($this->once())
-            ->method('setTypesData')
-            ->with($typeData);
-        $this->serviceMetadata->getRoutesConfig();
-        $this->assertEquals($routesConfig, $this->serviceMetadata->getRoutesConfig());
-    }
-
-    /**
-     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
-     */
-    public function testGetRoutesConfigNoCache()
-    {
-        $servicesConfig = [
-            'services' => [
-                CustomerRepositoryInterface::class => [
-                    'V1' => [
-                        'methods' => [
-                            'getById' => [
-                                'resources' => [
-                                    [
-                                        'Magento_Customer::customer',
-                                    ]
-                                ],
-                                'secure' => false
-                            ]
-                        ]
-                    ]
-                ]
-            ],
-            'routes' => [
-                '/V1/customers/:customerId' => [
-                    'GET' => [
-                        'secure' => false,
-                        'service' => [
-                            'class' => CustomerRepositoryInterface::class,
-                            'method' => 'getById'
-                        ],
-                        'resources' => [
-                            'Magento_Customer::customer' => true
-                        ],
-                        'parameters' => []
-                    ]
-                ]
-            ],
-            'class' => CustomerRepositoryInterface::class,
-            'description' => 'Customer CRUD interface.',
-        ];
-        $methodsReflectionData = [
-            'getById' => [
-                'documentation' => 'Get customer by customer ID.',
-                'interface' => [
-                    'in' => [
-                        'parameters' => [
-                            'customerId' => [
-                                'type' => 'int',
-                                'required' => true,
-                                'documentation' => null
-                            ]
-                        ]
-                    ],
-                    'out' => [
-                        'parameters' => [
-                            'result' => [
-                                'type' => 'CustomerDataCustomerInterface',
-                                'required' => true,
-                                'documentation' => null
-                            ]
-                        ]
-                    ]
-                ]
-            ]
-        ];
-        $routesMetadata = [
-            'customerCustomerRepositoryV1' => [
-                'methods' => array_merge_recursive(
-                    [
-                        'getById' => [
-                            'resources' => [
-                                [
-                                    'Magento_Customer::customer',
-                                ]
-                            ],
-                            'method' => 'getById',
-                            'inputRequired' => false,
-                            'isSecure' => false,
-                        ]
-                    ],
-                    $methodsReflectionData
-                ),
-                'routes' => [
-                    '/V1/customers/:customerId' => [
-                        'GET' => [
-                            'method' => 'getById',
-                            'parameters' => []
-                        ]
-                    ]
-                ],
-                'class' => CustomerRepositoryInterface::class,
-                'description' => 'Customer CRUD interface.'
-            ]
-        ];
-        $typeData = [
-            'CustomerDataCustomerInterface' => [
-                'documentation' => 'Customer interface.',
-                'parameters' => [
-                    'id' => [
-                        'type' => 'int',
-                        'required' => false,
-                        'documentation' => 'Customer id'
-                    ]
-                ]
-            ]
-        ];
-        $serializedRoutesConfig = 'serialized routes config';
-        $serializedTypeData = 'serialized type data';
-        $this->cacheMock->expects($this->at(0))
-            ->method('load')
-            ->with(ServiceMetadata::ROUTES_CONFIG_CACHE_ID)
-            ->willReturn(false);
-        $this->cacheMock->expects($this->at(1))
-            ->method('load')
-            ->with(ServiceMetadata::REFLECTED_TYPES_CACHE_ID)
-            ->willReturn(false);
-        $this->serializerMock->expects($this->never())
-            ->method('unserialize');
-        $this->configMock->expects($this->exactly(2))
-            ->method('getServices')
-            ->willReturn($servicesConfig);
-        $this->classReflectorMock->expects($this->once())
-            ->method('reflectClassMethods')
-            ->willReturn($methodsReflectionData);
-        $this->classReflectorMock->expects($this->once())
-            ->method('extractClassDescription')
-            ->with(CustomerRepositoryInterface::class)
-            ->willReturn('Customer CRUD interface.');
-        $this->typeProcessorMock->expects($this->exactly(2))
-            ->method('getTypesData')
-            ->willReturn($typeData);
-        $this->serializerMock->expects($this->at(2))
-            ->method('serialize')
-            ->with($routesMetadata)
-            ->willReturn($serializedRoutesConfig);
-        $this->serializerMock->expects($this->at(3))
-            ->method('serialize')
-            ->with($typeData)
-            ->willReturn($serializedTypeData);
-        $this->cacheMock->expects($this->at(6))
-            ->method('save')
-            ->with(
-                $serializedRoutesConfig,
-                ServiceMetadata::ROUTES_CONFIG_CACHE_ID
-            );
-        $this->cacheMock->expects($this->at(7))
-            ->method('save')
-            ->with(
-                $serializedTypeData,
-                ServiceMetadata::REFLECTED_TYPES_CACHE_ID
-            );
-        $this->serviceMetadata->getRoutesConfig();
-        $this->assertEquals($routesMetadata, $this->serviceMetadata->getRoutesConfig());
-    }
-
-    /**
-     * @dataProvider getServiceNameDataProvider
-     */
-    public function testGetServiceName($className, $version, $preserveVersion, $expected)
-    {
-        $this->assertEquals(
-            $expected,
-            $this->serviceMetadata->getServiceName($className, $version, $preserveVersion)
-        );
-    }
-
-    /**
-     * @return string
-     */
-    public function getServiceNameDataProvider()
-    {
-        return [
-            [
-                \Magento\Customer\Api\AccountManagementInterface::class,
-                'V1',
-                false,
-                'customerAccountManagement'
-            ],
-            [
-                \Magento\Customer\Api\AddressRepositoryInterface::class,
-                'V1',
-                true,
-                'customerAddressRepositoryV1'
-            ],
-        ];
-    }
-
-    /**
-     * @expectedException \InvalidArgumentException
-     * @dataProvider getServiceNameInvalidNameDataProvider
-     */
-    public function testGetServiceNameInvalidName($interfaceClassName, $version)
-    {
-        $this->serviceMetadata->getServiceName($interfaceClassName, $version);
-    }
-
-    /**
-     * @return string
-     */
-    public function getServiceNameInvalidNameDataProvider()
-    {
-        return [
-            ['BarV1Interface', 'V1'], // Missed vendor, module and Service
-            ['Service\\V1Interface', 'V1'], // Missed vendor and module
-            ['Magento\\Foo\\Service\\BarVxInterface', 'V1'], // Version number should be a number
-            ['Magento\\Foo\\Service\\BarInterface', 'V1'], // Missed version
-            ['Magento\\Foo\\Service\\BarV1', 'V1'], // Missed Interface
-            ['Foo\\Service\\BarV1Interface', 'V1'], // Missed module
-            ['Foo\\BarV1Interface', 'V1'] // Missed module and Service
-        ];
-    }
-}
diff --git a/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/Webapi/Adapter/Soap.php b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/Webapi/Adapter/Soap.php
index caba692fc0633..8453edb071b3e 100644
--- a/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/Webapi/Adapter/Soap.php
+++ b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/Webapi/Adapter/Soap.php
@@ -46,7 +46,7 @@ public function __construct()
     }
 
     /**
-     * {@inheritdoc}
+     * @inheritdoc
      */
     public function call($serviceInfo, $arguments = [], $storeCode = null, $integration = null)
     {
diff --git a/dev/tests/integration/testsuite/Magento/Webapi/Model/Config/_files/webapi.php b/dev/tests/integration/testsuite/Magento/Webapi/Model/Config/_files/webapi.php
index 1e5b338e0a7ef..57c8fbf45c63c 100644
--- a/dev/tests/integration/testsuite/Magento/Webapi/Model/Config/_files/webapi.php
+++ b/dev/tests/integration/testsuite/Magento/Webapi/Model/Config/_files/webapi.php
@@ -12,12 +12,16 @@
                             'Magento_TestModuleMSC::resource1',
                         ],
                         'secure' => false,
+                        'realMethod' => 'item',
+                        'parameters' => []
                     ],
                     'create' => [
                         'resources' => [
                             'Magento_TestModuleMSC::resource3',
                         ],
                         'secure' => false,
+                        'realMethod' => 'create',
+                        'parameters' => []
                     ],
                 ],
             ],
@@ -29,6 +33,8 @@
                             'Magento_TestModuleMSC::resource2',
                         ],
                         'secure' => false,
+                        'realMethod' => 'getPreconfiguredItem',
+                        'parameters' => []
                     ],
                 ],
             ],
@@ -40,12 +46,34 @@
                             'Magento_Test1::resource1',
                         ],
                         'secure' => false,
+                        'realMethod' => 'item',
+                        'parameters' => []
+                    ],
+                    'itemDefault' => [
+                        'resources' => [
+                            'Magento_Test1::default',
+                        ],
+                        'secure' => false,
+                        'realMethod' => 'item',
+                        'parameters' => [
+                            'id' => [
+                                'force' => true,
+                                'value' => null,
+                            ],
+                        ]
                     ],
                     'create' => [
                         'resources' => [
                             'Magento_Test1::resource1',
                         ],
                         'secure' => false,
+                        'realMethod' => 'create',
+                        'parameters' => [
+                            'id' => [
+                                'force' => true,
+                                'value' => null,
+                            ],
+                        ]
                     ],
                 ],
             ],
@@ -58,6 +86,8 @@
                             'Magento_Test1::resource2',
                         ],
                         'secure' => false,
+                        'realMethod' => 'item',
+                        'parameters' => []
                     ],
                     'create' => [
                         'resources' => [
@@ -65,6 +95,13 @@
                             'Magento_Test1::resource2',
                         ],
                         'secure' => false,
+                        'realMethod' => 'create',
+                        'parameters' => [
+                            'id' => [
+                                'force' => true,
+                                'value' => null,
+                            ],
+                        ]
                     ],
                     'delete' => [
                         'resources' => [
@@ -72,6 +109,8 @@
                             'Magento_Test1::resource2',
                         ],
                         'secure' => false,
+                        'realMethod' => 'delete',
+                        'parameters' => []
                     ],
                     'update' => [
                         'resources' => [
@@ -79,6 +118,8 @@
                             'Magento_Test1::resource2',
                         ],
                         'secure' => false,
+                        'realMethod' => 'update',
+                        'parameters' => []
                     ],
                 ],
             ],
@@ -127,25 +168,46 @@
                 ],
             ],
         ],
-        '/V2/testmodule1/:id' => [
+        '/V1/testmodule1' => [
             'GET' => [
                 'secure' => false,
                 'service' => [
-                    'class' => \Magento\TestModule1\Service\V2\AllSoapAndRestInterface::class,
+                    'class' => \Magento\TestModule1\Service\V1\AllSoapAndRestInterface::class,
                     'method' => 'item',
                 ],
+                'resources' => [
+                    'Magento_Test1::default' => true,
+                ],
+                'parameters' => [
+                    'id' => [
+                        'force' => true,
+                        'value' => null,
+                    ],
+                ],
+            ],
+            'POST' => [
+                'secure' => false,
+                'service' => [
+                    'class' => \Magento\TestModule1\Service\V1\AllSoapAndRestInterface::class,
+                    'method' => 'create',
+                ],
                 'resources' => [
                     'Magento_Test1::resource1' => true,
-                    'Magento_Test1::resource2' => true,
                 ],
                 'parameters' => [
+                    'id' => [
+                        'force' => true,
+                        'value' => null,
+                    ],
                 ],
             ],
-            'DELETE' => [
+        ],
+        '/V2/testmodule1/:id' => [
+            'GET' => [
                 'secure' => false,
                 'service' => [
                     'class' => \Magento\TestModule1\Service\V2\AllSoapAndRestInterface::class,
-                    'method' => 'delete',
+                    'method' => 'item',
                 ],
                 'resources' => [
                     'Magento_Test1::resource1' => true,
@@ -154,11 +216,11 @@
                 'parameters' => [
                 ],
             ],
-            'PUT' => [
+            'DELETE' => [
                 'secure' => false,
                 'service' => [
                     'class' => \Magento\TestModule1\Service\V2\AllSoapAndRestInterface::class,
-                    'method' => 'update',
+                    'method' => 'delete',
                 ],
                 'resources' => [
                     'Magento_Test1::resource1' => true,
@@ -167,35 +229,30 @@
                 'parameters' => [
                 ],
             ],
-        ],
-        '/V2/testmodule1' => [
-            'POST' => [
+            'PUT' => [
                 'secure' => false,
                 'service' => [
                     'class' => \Magento\TestModule1\Service\V2\AllSoapAndRestInterface::class,
-                    'method' => 'create',
+                    'method' => 'update',
                 ],
                 'resources' => [
                     'Magento_Test1::resource1' => true,
                     'Magento_Test1::resource2' => true,
                 ],
                 'parameters' => [
-                    'id' => [
-                        'force' => true,
-                        'value' => null,
-                    ],
                 ],
             ],
         ],
-        '/V1/testmodule1' => [
+        '/V2/testmodule1' => [
             'POST' => [
                 'secure' => false,
                 'service' => [
-                    'class' => \Magento\TestModule1\Service\V1\AllSoapAndRestInterface::class,
+                    'class' => \Magento\TestModule1\Service\V2\AllSoapAndRestInterface::class,
                     'method' => 'create',
                 ],
                 'resources' => [
                     'Magento_Test1::resource1' => true,
+                    'Magento_Test1::resource2' => true,
                 ],
                 'parameters' => [
                     'id' => [
diff --git a/dev/tests/integration/testsuite/Magento/Webapi/Model/Config/_files/webapiA.xml b/dev/tests/integration/testsuite/Magento/Webapi/Model/Config/_files/webapiA.xml
index c814b1039b04b..389908309b2a2 100644
--- a/dev/tests/integration/testsuite/Magento/Webapi/Model/Config/_files/webapiA.xml
+++ b/dev/tests/integration/testsuite/Magento/Webapi/Model/Config/_files/webapiA.xml
@@ -13,6 +13,15 @@
             
         
     
+    
+        
+        
+            
+        
+        
+            null
+        
+    
     
         
         
diff --git a/dev/tests/integration/testsuite/Magento/Webapi/Model/Soap/ConfigTest.php b/dev/tests/integration/testsuite/Magento/Webapi/Model/Soap/ConfigTest.php
index 1236ad20c3486..8a9184f5d5e4c 100644
--- a/dev/tests/integration/testsuite/Magento/Webapi/Model/Soap/ConfigTest.php
+++ b/dev/tests/integration/testsuite/Magento/Webapi/Model/Soap/ConfigTest.php
@@ -64,7 +64,8 @@ public function testGetRequestedSoapServices()
                                     '\\' . LocalizedException::class
                                 ]
                             ]
-                        ]
+                        ],
+                        'parameters' => []
                     ]
                 ],
                 'class' => AccountManagementInterface::class,
@@ -88,8 +89,8 @@ public function testGetServiceMethodInfo()
             'isSecure' => false,
             'resources' => [
                 'Magento_Customer::customer',
-                'self'
             ],
+            'parameters' => []
         ];
         $actual = $this->soapConfig->getServiceMethodInfo(
             'customerCustomerRepositoryV1GetById',

From 9e4d32d58267eb22f417238dea4fd8ef69c21545 Mon Sep 17 00:00:00 2001
From: Oleksandr Gorkun 
Date: Wed, 30 Jan 2019 13:58:12 -0600
Subject: [PATCH 032/773] MC-10870: Invalid company ID in web API

---
 app/code/Magento/Webapi/Model/Config/Reader.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/app/code/Magento/Webapi/Model/Config/Reader.php b/app/code/Magento/Webapi/Model/Config/Reader.php
index 15eb1c0fb8e39..59e183092cbd6 100644
--- a/app/code/Magento/Webapi/Model/Config/Reader.php
+++ b/app/code/Magento/Webapi/Model/Config/Reader.php
@@ -18,7 +18,7 @@ class Reader extends \Magento\Framework\Config\Reader\Filesystem
     protected $_idAttributes = [
         '/routes/route' => ['url', 'method'],
         '/routes/route/resources/resource' => 'ref',
-        '/routes/route/data' => 'name',
+        '/routes/route/data/parameter' => 'name',
     ];
 
     /**

From 031df48b3548a75cd95511f47e4768732bd58009 Mon Sep 17 00:00:00 2001
From: Oleksandr Gorkun 
Date: Wed, 30 Jan 2019 16:04:50 -0600
Subject: [PATCH 033/773] MC-13650: SOAP gateway ignores enforced parameters

---
 .../testsuite/Magento/Customer/Api/CustomerRepositoryTest.php    | 1 -
 1 file changed, 1 deletion(-)

diff --git a/dev/tests/api-functional/testsuite/Magento/Customer/Api/CustomerRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Customer/Api/CustomerRepositoryTest.php
index b4f8304dd4873..709abbbb8fbf9 100644
--- a/dev/tests/api-functional/testsuite/Magento/Customer/Api/CustomerRepositoryTest.php
+++ b/dev/tests/api-functional/testsuite/Magento/Customer/Api/CustomerRepositoryTest.php
@@ -147,7 +147,6 @@ public function tearDown()
      * Validate update by invalid customer.
      *
      * @expectedException \Exception
-     * @expectedExceptionMessageRegExp  /The consumer isn't authorized to access \%resources.|Function \("customerCustomerRepositoryV1Save"\) is not a valid method for this service/
      */
     public function testInvalidCustomerUpdate()
     {

From 7191377e0817f335b1588fabcd724cb4ba3c7f23 Mon Sep 17 00:00:00 2001
From: roman 
Date: Thu, 31 Jan 2019 17:20:07 +0200
Subject: [PATCH 034/773] MC-5968: Fixed incorrect config override behavior

---
 .../Controller/Adminhtml/System/Config/Save.php       | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/app/code/Magento/Config/Controller/Adminhtml/System/Config/Save.php b/app/code/Magento/Config/Controller/Adminhtml/System/Config/Save.php
index d67c973162991..e6b6fd5ce1b1a 100644
--- a/app/code/Magento/Config/Controller/Adminhtml/System/Config/Save.php
+++ b/app/code/Magento/Config/Controller/Adminhtml/System/Config/Save.php
@@ -202,14 +202,21 @@ public function execute()
      */
     private function filterNodes(array $configData): array
     {
-        $systemXmlConfig = $this->_configStructure->getFieldPaths();
+        $systemXmlConfig = array_merge(
+            array_keys($this->_configStructure->getFieldPaths()),
+            array_reduce(
+                array_values($this->_configStructure->getFieldPaths()),
+                'array_merge',
+                array()
+            )
+        );
 
         foreach ($configData['groups'] as $configKey => $configFields) {
             foreach (array_keys($configFields['fields']) as $configFieldName) {
                 $systemConfigArrayKey = $configData['section'] . '/' .
                     $configKey . '/' .
                     $configFieldName;
-                if (array_key_exists($systemConfigArrayKey, $systemXmlConfig)) {
+                if (in_array($systemConfigArrayKey, $systemXmlConfig)) {
                     continue;
                 }
 

From 5590834f8c587f756304489674131ba09f5ce6cd Mon Sep 17 00:00:00 2001
From: roman 
Date: Fri, 1 Feb 2019 14:17:43 +0200
Subject: [PATCH 035/773] MC-5968: Fixed incorrect config override behavior

---
 .../Controller/Adminhtml/System/Config/Save.php   | 15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/app/code/Magento/Config/Controller/Adminhtml/System/Config/Save.php b/app/code/Magento/Config/Controller/Adminhtml/System/Config/Save.php
index e6b6fd5ce1b1a..57b29748a9c59 100644
--- a/app/code/Magento/Config/Controller/Adminhtml/System/Config/Save.php
+++ b/app/code/Magento/Config/Controller/Adminhtml/System/Config/Save.php
@@ -202,15 +202,16 @@ public function execute()
      */
     private function filterNodes(array $configData): array
     {
-        $systemXmlConfig = array_merge(
-            array_keys($this->_configStructure->getFieldPaths()),
-            array_reduce(
-                array_values($this->_configStructure->getFieldPaths()),
-                'array_merge',
-                array()
-            )
+        $systemXmlPathsFromKeys = array_keys($this->_configStructure->getFieldPaths());
+
+        $systemXmlPathsFromValues = array_reduce(
+            array_values($this->_configStructure->getFieldPaths()),
+            'array_merge',
+            []
         );
 
+        $systemXmlConfig = array_merge($systemXmlPathsFromKeys, $systemXmlPathsFromValues);
+
         foreach ($configData['groups'] as $configKey => $configFields) {
             foreach (array_keys($configFields['fields']) as $configFieldName) {
                 $systemConfigArrayKey = $configData['section'] . '/' .

From e062906ed76ffbc3e2226d42c43c9be023391f8d Mon Sep 17 00:00:00 2001
From: "Rav [RedChamps]" 
Date: Sun, 3 Feb 2019 14:11:53 +0530
Subject: [PATCH 036/773] Enabled 'Shopping Cart' tab for customer edit
 interface in admin

---
 .../Block/Adminhtml/Edit/Tab/Carts.php        | 55 +++++++++++++++++++
 .../adminhtml/layout/customer_index_edit.xml  |  3 +
 .../view/base/ui_component/customer_form.xml  |  3 +
 3 files changed, 61 insertions(+)

diff --git a/app/code/Magento/Customer/Block/Adminhtml/Edit/Tab/Carts.php b/app/code/Magento/Customer/Block/Adminhtml/Edit/Tab/Carts.php
index 5601cf3728349..2fc43fc7ce3bf 100644
--- a/app/code/Magento/Customer/Block/Adminhtml/Edit/Tab/Carts.php
+++ b/app/code/Magento/Customer/Block/Adminhtml/Edit/Tab/Carts.php
@@ -97,4 +97,59 @@ protected function _getCustomer()
         );
         return $customerDataObject;
     }
+
+    /**
+     * @return bool
+     */
+    public function canShowTab()
+    {
+        if ($this->_getCustomer()->getId()) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * @return \Magento\Framework\Phrase
+     */
+    public function getTabLabel()
+    {
+        return __('Shopping cart');
+    }
+
+    /**
+     * @return \Magento\Framework\Phrase
+     */
+    public function getTabTitle()
+    {
+        return __('Shopping cart');
+    }
+
+    /**
+     * Return URL link to Tab content, used with isAjaxLoaded to true
+     *
+     * @return string
+     */
+    public function getTabUrl()
+    {
+        return $this->getUrl('customer/*/cart', ['_current' => true]);
+    }
+
+    /**
+     * Tab should be loaded trough Ajax call
+     *
+     * @return bool
+     */
+    public function isAjaxLoaded()
+    {
+        return true;
+    }
+
+    /**
+     * @return bool
+     */
+    public function canDisplayContainer()
+    {
+        return true;
+    }
 }
diff --git a/app/code/Magento/Customer/view/adminhtml/layout/customer_index_edit.xml b/app/code/Magento/Customer/view/adminhtml/layout/customer_index_edit.xml
index 23b5718870229..e982d8bb0960e 100644
--- a/app/code/Magento/Customer/view/adminhtml/layout/customer_index_edit.xml
+++ b/app/code/Magento/Customer/view/adminhtml/layout/customer_index_edit.xml
@@ -15,5 +15,8 @@
         
             
         
+        
+            
+        
     
 
diff --git a/app/code/Magento/Sales/view/base/ui_component/customer_form.xml b/app/code/Magento/Sales/view/base/ui_component/customer_form.xml
index 2c6dda05c80f6..f03338da261f3 100644
--- a/app/code/Magento/Sales/view/base/ui_component/customer_form.xml
+++ b/app/code/Magento/Sales/view/base/ui_component/customer_form.xml
@@ -6,6 +6,9 @@
  */
 -->
 
+ + + From d4db84ce0e6db5299de5b438e8e160b00700c2d2 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun Date: Mon, 4 Feb 2019 17:14:36 -0600 Subject: [PATCH 037/773] MC-13812: Error when using Test Connection --- app/code/Magento/Elasticsearch/Model/Config.php | 9 ++++++++- .../Magento/Elasticsearch/Test/Unit/Model/ConfigTest.php | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Elasticsearch/Model/Config.php b/app/code/Magento/Elasticsearch/Model/Config.php index dc08a72a9feb3..c5aec625d36a1 100644 --- a/app/code/Magento/Elasticsearch/Model/Config.php +++ b/app/code/Magento/Elasticsearch/Model/Config.php @@ -100,7 +100,14 @@ public function prepareClientOptions($options = []) 'timeout' => $this->getElasticsearchConfigData('server_timeout') ? : self::ELASTICSEARCH_DEFAULT_TIMEOUT, ]; $options = array_merge($defaultOptions, $options); - return $options; + + return array_filter( + $options, + function (string $key) use ($defaultOptions) { + return array_key_exists($key, $defaultOptions); + }, + ARRAY_FILTER_USE_KEY + ); } /** diff --git a/app/code/Magento/Elasticsearch/Test/Unit/Model/ConfigTest.php b/app/code/Magento/Elasticsearch/Test/Unit/Model/ConfigTest.php index 3829a2f9280c1..dfe6deb23c22f 100644 --- a/app/code/Magento/Elasticsearch/Test/Unit/Model/ConfigTest.php +++ b/app/code/Magento/Elasticsearch/Test/Unit/Model/ConfigTest.php @@ -61,7 +61,7 @@ public function testPrepareClientOptions() 'password' => 'pass', 'timeout' => 1, ]; - $this->assertEquals($options, $this->model->prepareClientOptions($options)); + $this->assertEquals($options, $this->model->prepareClientOptions(array_merge($options, ['test' => 'test']))); } /** From e5a223c0a1e7864abd036ea94804137b2f010494 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun Date: Thu, 7 Feb 2019 11:40:34 -0600 Subject: [PATCH 038/773] MC-13799: Misuse of HTTP client --- .../Magento/Framework/HTTP/Client/Curl.php | 1 + .../HTTP/Test/Unit/Client/CurlTest.php | 30 +++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 lib/internal/Magento/Framework/HTTP/Test/Unit/Client/CurlTest.php diff --git a/lib/internal/Magento/Framework/HTTP/Client/Curl.php b/lib/internal/Magento/Framework/HTTP/Client/Curl.php index 0ac65a420ddcf..8b90897481259 100644 --- a/lib/internal/Magento/Framework/HTTP/Client/Curl.php +++ b/lib/internal/Magento/Framework/HTTP/Client/Curl.php @@ -357,6 +357,7 @@ public function getStatus() protected function makeRequest($method, $uri, $params = []) { $this->_ch = curl_init(); + $this->curlOption(CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS | CURLPROTO_FTP | CURLPROTO_FTPS); $this->curlOption(CURLOPT_URL, $uri); if ($method == 'POST') { $this->curlOption(CURLOPT_POST, 1); diff --git a/lib/internal/Magento/Framework/HTTP/Test/Unit/Client/CurlTest.php b/lib/internal/Magento/Framework/HTTP/Test/Unit/Client/CurlTest.php new file mode 100644 index 0000000000000..40683206dd28e --- /dev/null +++ b/lib/internal/Magento/Framework/HTTP/Test/Unit/Client/CurlTest.php @@ -0,0 +1,30 @@ +get('telnet://127.0.0.1/test'); + } +} From 042b64b9194ffd802183cd89e2eff50356128156 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun Date: Thu, 7 Feb 2019 17:30:05 -0600 Subject: [PATCH 039/773] MC-13799: Misuse of HTTP client --- .../Magento/Framework/HTTP/Test/Unit/Client/CurlTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/HTTP/Test/Unit/Client/CurlTest.php b/lib/internal/Magento/Framework/HTTP/Test/Unit/Client/CurlTest.php index 40683206dd28e..128c4440063ec 100644 --- a/lib/internal/Magento/Framework/HTTP/Test/Unit/Client/CurlTest.php +++ b/lib/internal/Magento/Framework/HTTP/Test/Unit/Client/CurlTest.php @@ -20,7 +20,7 @@ class CurlTest extends TestCase * Check that HTTP client can be used only for HTTP. * * @expectedException \Exception - * @expectedExceptionMessage Protocol "telnet" not supported or disabled in libcurl + * @expectedExceptionMessageRegExp /Protocol .?telnet.? not supported or disabled in libcurl/ */ public function testInvalidProtocol() { From c9c55bc34d3067745b1585489445145c91773548 Mon Sep 17 00:00:00 2001 From: roman Date: Fri, 8 Feb 2019 16:10:17 +0200 Subject: [PATCH 040/773] MC-5888: Fixed incorrect wysiwyg behavior --- .../Magento/Cms/Model/Template/Filter.php | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/app/code/Magento/Cms/Model/Template/Filter.php b/app/code/Magento/Cms/Model/Template/Filter.php index f93972bade2af..f56bab49e75d6 100644 --- a/app/code/Magento/Cms/Model/Template/Filter.php +++ b/app/code/Magento/Cms/Model/Template/Filter.php @@ -5,6 +5,8 @@ */ namespace Magento\Cms\Model\Template; +use Magento\Framework\Exception\LocalizedException; + /** * Cms Template Filter Model */ @@ -40,4 +42,23 @@ public function mediaDirective($construction) $params = $this->getParameters(html_entity_decode($construction[2], ENT_QUOTES)); return $this->_storeManager->getStore()->getBaseMediaDir() . '/' . $params['url']; } + + /** + * Validates directive param for traversal path + * + * @param string $directive + * @return string + */ + public function filter($directive) + { + if (preg_match('#\.\.[\\\/]#', $directive)) { + throw new LocalizedException( + __( + 'Requested file should not include parent directory traversal ("../", "..\\" notation)' + ) + ); + } + + return parent::filter($directive); + } } From fd03c265729729b7b2624f5a089f1add21593ac6 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun Date: Wed, 13 Feb 2019 18:57:07 -0600 Subject: [PATCH 041/773] MC-13958: Additional Permissions for Design settings --- .../Catalog/Model/ProductRepository.php | 40 +++++++-- .../Product/Form/Modifier/Eav.php | 39 +++++++-- app/code/Magento/Catalog/etc/acl.xml | 4 +- app/code/Magento/Catalog/i18n/en_US.csv | 3 +- .../Catalog/Model/ProductRepositoryTest.php | 82 +++++++++++++++++-- 5 files changed, 147 insertions(+), 21 deletions(-) diff --git a/app/code/Magento/Catalog/Model/ProductRepository.php b/app/code/Magento/Catalog/Model/ProductRepository.php index d124bf5e42639..5b044245886d4 100644 --- a/app/code/Magento/Catalog/Model/ProductRepository.php +++ b/app/code/Magento/Catalog/Model/ProductRepository.php @@ -17,6 +17,7 @@ use Magento\Framework\Api\ImageContentValidatorInterface; use Magento\Framework\Api\ImageProcessorInterface; use Magento\Framework\Api\SearchCriteria\CollectionProcessorInterface; +use Magento\Framework\App\ObjectManager; use Magento\Framework\DB\Adapter\ConnectionException; use Magento\Framework\DB\Adapter\DeadlockException; use Magento\Framework\DB\Adapter\LockWaitException; @@ -28,6 +29,8 @@ use Magento\Framework\Exception\TemporaryState\CouldNotSaveException as TemporaryCouldNotSaveException; use Magento\Framework\Exception\StateException; use Magento\Framework\Exception\ValidatorException; +use Magento\Authorization\Model\UserContextInterface; +use Magento\Framework\AuthorizationInterface; /** * Product Repository. @@ -161,6 +164,16 @@ class ProductRepository implements \Magento\Catalog\Api\ProductRepositoryInterfa */ private $readExtensions; + /** + * @var UserContextInterface + */ + private $userContext; + + /** + * @var AuthorizationInterface + */ + private $authorization; + /** * ProductRepository constructor. * @param ProductFactory $productFactory @@ -187,6 +200,8 @@ class ProductRepository implements \Magento\Catalog\Api\ProductRepositoryInterfa * @param \Magento\Framework\Serialize\Serializer\Json|null $serializer * @param int $cacheLimit [optional] * @param ReadExtensions|null $readExtensions + * @param UserContextInterface|null $userContext + * @param AuthorizationInterface|null $authorization * @SuppressWarnings(PHPMD.ExcessiveParameterList) * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ @@ -214,7 +229,9 @@ public function __construct( CollectionProcessorInterface $collectionProcessor = null, \Magento\Framework\Serialize\Serializer\Json $serializer = null, $cacheLimit = 1000, - ReadExtensions $readExtensions = null + ReadExtensions $readExtensions = null, + ?UserContextInterface $userContext = null, + ?AuthorizationInterface $authorization = null ) { $this->productFactory = $productFactory; $this->collectionFactory = $collectionFactory; @@ -234,11 +251,12 @@ public function __construct( $this->imageProcessor = $imageProcessor; $this->extensionAttributesJoinProcessor = $extensionAttributesJoinProcessor; $this->collectionProcessor = $collectionProcessor ?: $this->getCollectionProcessor(); - $this->serializer = $serializer ?: \Magento\Framework\App\ObjectManager::getInstance() - ->get(\Magento\Framework\Serialize\Serializer\Json::class); + $this->serializer = $serializer + ?: ObjectManager::getInstance()->get(\Magento\Framework\Serialize\Serializer\Json::class); $this->cacheLimit = (int)$cacheLimit; - $this->readExtensions = $readExtensions ?: \Magento\Framework\App\ObjectManager::getInstance() - ->get(ReadExtensions::class); + $this->readExtensions = $readExtensions ?: ObjectManager::getInstance()->get(ReadExtensions::class); + $this->userContext = $userContext ?? ObjectManager::getInstance()->get(UserContextInterface::class); + $this->authorization = $authorization ?? ObjectManager::getInstance()->get(AuthorizationInterface::class); } /** @@ -354,6 +372,18 @@ protected function initializeProductData(array $productData, $createNew) $product = $this->get($productData['sku']); } + $userType = $this->userContext->getUserType(); + if ($userType === UserContextInterface::USER_TYPE_ADMIN + || $userType === UserContextInterface::USER_TYPE_INTEGRATION + ) { + if (!$this->authorization->isAllowed('Magento_Catalog::edit_product_design')) { + $product->lockAttribute('custom_design'); + $product->lockAttribute('page_layout'); + $product->lockAttribute('options_container'); + $product->lockAttribute('custom_layout_update'); + } + } + foreach ($productData as $key => $value) { $product->setData($key, $value); } diff --git a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php index 99f7122efa0a8..9e3e0a54e8444 100755 --- a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php +++ b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php @@ -21,8 +21,10 @@ use Magento\Eav\Model\ResourceModel\Entity\Attribute\Group\CollectionFactory as GroupCollectionFactory; use Magento\Framework\Api\SearchCriteriaBuilder; use Magento\Framework\Api\SortOrderBuilder; +use Magento\Framework\App\ObjectManager; use Magento\Framework\App\Request\DataPersistorInterface; use Magento\Framework\App\RequestInterface; +use Magento\Framework\AuthorizationInterface; use Magento\Framework\Filter\Translit; use Magento\Framework\Locale\CurrencyInterface; use Magento\Framework\Stdlib\ArrayManager; @@ -213,6 +215,11 @@ class Eav extends AbstractModifier */ private $scopeConfig; + /** + * @var AuthorizationInterface + */ + private $auth; + /** * Eav constructor. * @param LocatorInterface $locator @@ -261,7 +268,8 @@ public function __construct( $attributesToEliminate = [], CompositeConfigProcessor $wysiwygConfigProcessor = null, ScopeConfigInterface $scopeConfig = null, - AttributeCollectionFactory $attributeCollectionFactory = null + AttributeCollectionFactory $attributeCollectionFactory = null, + ?AuthorizationInterface $auth = null ) { $this->locator = $locator; $this->catalogEavValidationRules = $catalogEavValidationRules; @@ -282,12 +290,12 @@ public function __construct( $this->dataPersistor = $dataPersistor; $this->attributesToDisable = $attributesToDisable; $this->attributesToEliminate = $attributesToEliminate; - $this->wysiwygConfigProcessor = $wysiwygConfigProcessor ?: \Magento\Framework\App\ObjectManager::getInstance() - ->get(CompositeConfigProcessor::class); - $this->scopeConfig = $scopeConfig ?: \Magento\Framework\App\ObjectManager::getInstance() - ->get(ScopeConfigInterface::class); + $this->wysiwygConfigProcessor = $wysiwygConfigProcessor + ?: ObjectManager::getInstance()->get(CompositeConfigProcessor::class); + $this->scopeConfig = $scopeConfig ?: ObjectManager::getInstance()->get(ScopeConfigInterface::class); $this->attributeCollectionFactory = $attributeCollectionFactory - ?: \Magento\Framework\App\ObjectManager::getInstance()->get(AttributeCollectionFactory::class); + ?: ObjectManager::getInstance()->get(AttributeCollectionFactory::class); + $this->auth = $auth ?? ObjectManager::getInstance()->get(AuthorizationInterface::class); } /** @@ -730,6 +738,25 @@ public function setupAttributeMeta(ProductAttributeInterface $attribute, $groupC break; } + //Checking access to design config. + if (in_array( + $attribute->getAttributeCode(), + ['custom_design', 'page_layout', 'options_container', 'custom_layout_update'], + true + )) { + if (!$this->auth->isAllowed('Magento_Catalog::edit_product_design')) { + $meta = $this->arrayManager->merge( + $configPath, + $meta, + [ + 'disabled' => true, + 'validation' => ['required' => false], + 'required' => false, + ] + ); + } + } + return $meta; } diff --git a/app/code/Magento/Catalog/etc/acl.xml b/app/code/Magento/Catalog/etc/acl.xml index 358a798fc7579..79b1e3426b2f1 100644 --- a/app/code/Magento/Catalog/etc/acl.xml +++ b/app/code/Magento/Catalog/etc/acl.xml @@ -11,7 +11,9 @@ - + + + diff --git a/app/code/Magento/Catalog/i18n/en_US.csv b/app/code/Magento/Catalog/i18n/en_US.csv index ed27dfd646cb2..27b9e43658901 100644 --- a/app/code/Magento/Catalog/i18n/en_US.csv +++ b/app/code/Magento/Catalog/i18n/en_US.csv @@ -808,4 +808,5 @@ Details,Details "Start typing to find products", "Start typing to find products" "Product with ID: (%1) doesn't exist", "Product with ID: (%1) doesn't exist" "Category with ID: (%1) doesn't exist", "Category with ID: (%1) doesn't exist" -"You added product %1 to the comparison list.","You added product %1 to the comparison list." \ No newline at end of file +"You added product %1 to the comparison list.","You added product %1 to the comparison list." +"Edit Product Design","Edit Product Design" \ No newline at end of file diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductRepositoryTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductRepositoryTest.php index d4016b2bfa8d4..71b4455f3a1fa 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductRepositoryTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductRepositoryTest.php @@ -7,8 +7,16 @@ namespace Magento\Catalog\Model; +use Magento\Authorization\Model\Role; +use Magento\Authorization\Model\RoleFactory; use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Framework\Api\SearchCriteriaBuilder; use Magento\TestFramework\Helper\Bootstrap; +use Magento\Authorization\Model\Rules; +use Magento\Authorization\Model\RulesFactory; +use Magento\TestFramework\Bootstrap as TestBootstrap; +use Magento\User\Model\User; +use Magento\User\Model\UserFactory; /** * Provide tests for ProductRepository model. @@ -26,22 +34,35 @@ class ProductRepositoryTest extends \PHPUnit\Framework\TestCase private $productRepository; /** - * @var \Magento\Framework\Api\SearchCriteriaBuilder + * @var SearchCriteriaBuilder */ private $searchCriteriaBuilder; + /** + * @var RulesFactory + */ + private $rulesFactory; + + /** + * @var RoleFactory + */ + private $roleFactory; + + /** + * @var UserFactory + */ + private $userFactory; + /** * Sets up common objects */ protected function setUp() { - $this->productRepository = \Magento\Framework\App\ObjectManager::getInstance()->create( - \Magento\Catalog\Api\ProductRepositoryInterface::class - ); - - $this->searchCriteriaBuilder = \Magento\Framework\App\ObjectManager::getInstance()->create( - \Magento\Framework\Api\SearchCriteriaBuilder::class - ); + $this->productRepository = Bootstrap::getObjectManager()->create(ProductRepositoryInterface::class); + $this->searchCriteriaBuilder = Bootstrap::getObjectManager()->get(SearchCriteriaBuilder::class); + $this->rulesFactory = Bootstrap::getObjectManager()->get(RulesFactory::class); + $this->roleFactory = Bootstrap::getObjectManager()->get(RoleFactory::class); + $this->userFactory = Bootstrap::getObjectManager()->get(UserFactory::class); } /** @@ -138,4 +159,49 @@ public function testSaveProductWithGalleryImage(): void $this->assertStringStartsWith('/m/a/magento_image', $product->getData('image')); $this->assertStringStartsWith('/m/a/magento_image', $product->getData('small_image')); } + + /** + * Test authorization when saving product's design settings. + * + * @magentoDataFixture Magento/Catalog/_files/product_simple.php + */ + public function testSaveDesign() + { + $product = $this->productRepository->get('simple'); + /** @var Role $role */ + $role = $this->roleFactory->create(); + $role->load(TestBootstrap::ADMIN_ROLE_NAME, 'role_name'); + /** @var User $user */ + $user = $this->userFactory->create(); + + //Admin doesn't have access to product's design. + /** @var Rules $rules */ + $rules = $this->rulesFactory->create(); + $rules->setRoleId($role->getId()); + $rules->setResources(['Magento_Catalog::products']); + $rules->saveRel(); + $user->login( + TestBootstrap::ADMIN_NAME, + TestBootstrap::ADMIN_PASSWORD + )->reload(); + + $product->setCustomAttribute('custom_design', 2); + $product = $this->productRepository->save($product); + $this->assertEmpty($product->getCustomAttribute('custom_design')); + + //Admin has access to products' design. + /** @var Rules $rules */ + $rules = $this->rulesFactory->create(); + $rules->setRoleId($role->getId()); + $rules->setResources(['Magento_Catalog::products', 'Magento_Catalog::edit_product_design']); + $rules->saveRel(); + $user->login( + TestBootstrap::ADMIN_NAME, + TestBootstrap::ADMIN_PASSWORD + )->reload(); + + $product->setCustomAttribute('custom_design', 2); + $product = $this->productRepository->save($product); + $this->assertEquals(2, $product->getCustomAttribute('custom_design')); + } } From 65a2c17418755355bc50dd7aded5a6bd617c97dc Mon Sep 17 00:00:00 2001 From: Jayanka Date: Thu, 14 Feb 2019 18:27:15 +0530 Subject: [PATCH 042/773] add orig-name to elements when _prepareArrayInputs and use it for name validation if it exists --- lib/web/mage/validation.js | 9 +++++++-- lib/web/mage/validation/validation.js | 5 ++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/lib/web/mage/validation.js b/lib/web/mage/validation.js index 8d825a9ef2226..ad74b2e6fb81e 100644 --- a/lib/web/mage/validation.js +++ b/lib/web/mage/validation.js @@ -1885,7 +1885,8 @@ */ _prepareArrayInputs: function () { /* Store original names for array inputs */ - var originalElements = []; + var originalElements = [], + originalSubmitHandler = this.options.submitHandler; /* For all array inputs, assign index so that validation is proper */ this.element.find('[name$="[]"]').each(function (key, input) { @@ -1895,6 +1896,7 @@ originalName = input.attr('name'); name = originalName.replace('[]', '[' + key + ']'); $(input).attr('name', name); + $(input).attr('orig-name', originalName); originalElements.push({ element: $(input), name: originalName @@ -1908,8 +1910,11 @@ this.options.submitHandler = function (form) { originalElements.forEach(function (element) { element.element.attr('name', element.name); + element.element.removeAttr('orig-name'); }); - form.submit(); + + /* Call the originalSubmitHandler if it's a function */ + typeof originalSubmitHandler === 'function' && originalSubmitHandler(form); }; }, diff --git a/lib/web/mage/validation/validation.js b/lib/web/mage/validation/validation.js index f3b36fa153c32..a22245236f372 100644 --- a/lib/web/mage/validation/validation.js +++ b/lib/web/mage/validation/validation.js @@ -49,10 +49,13 @@ 'validate-one-checkbox-required-by-name': [ function (value, element, params) { var checkedCount = 0, + selector, container; if (element.type === 'checkbox') { - $('[name="' + element.name + '"]').each(function () { + /* If orig-name attribute is present, use it for validation. Else use name */ + selector = = element.getAttribute('orig-name') ? '[orig-name="' + element.getAttribute('orig-name') + '"]' : '[name="' + element.name + '"]'; + $(selector).each(function () { if ($(this).is(':checked')) { checkedCount += 1; From 97c03f5deb4ee53a1a597610509f9ecf91c029ff Mon Sep 17 00:00:00 2001 From: Jayanka Date: Thu, 14 Feb 2019 18:32:00 +0530 Subject: [PATCH 043/773] call form submit if originalSubmitHandler not present --- lib/web/mage/validation.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/web/mage/validation.js b/lib/web/mage/validation.js index ad74b2e6fb81e..ba187766e236a 100644 --- a/lib/web/mage/validation.js +++ b/lib/web/mage/validation.js @@ -1912,9 +1912,9 @@ element.element.attr('name', element.name); element.element.removeAttr('orig-name'); }); - + /* Call the originalSubmitHandler if it's a function */ - typeof originalSubmitHandler === 'function' && originalSubmitHandler(form); + typeof originalSubmitHandler === 'function' ? originalSubmitHandler(form) : form.submit(); }; }, From 224f73768ea425fcd8128f921682a5aa894e5992 Mon Sep 17 00:00:00 2001 From: Jayanka Date: Thu, 14 Feb 2019 18:35:02 +0530 Subject: [PATCH 044/773] call form submit if originalSubmitHandler not present --- lib/web/mage/validation/validation.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/web/mage/validation/validation.js b/lib/web/mage/validation/validation.js index a22245236f372..437c753d78c8b 100644 --- a/lib/web/mage/validation/validation.js +++ b/lib/web/mage/validation/validation.js @@ -54,7 +54,7 @@ if (element.type === 'checkbox') { /* If orig-name attribute is present, use it for validation. Else use name */ - selector = = element.getAttribute('orig-name') ? '[orig-name="' + element.getAttribute('orig-name') + '"]' : '[name="' + element.name + '"]'; + selector = element.getAttribute('orig-name') ? '[orig-name="' + element.getAttribute('orig-name') + '"]' : '[name="' + element.name + '"]'; $(selector).each(function () { if ($(this).is(':checked')) { checkedCount += 1; From 908100bdc9974d3754ad3291763705ee3ff321c1 Mon Sep 17 00:00:00 2001 From: Jayanka Date: Thu, 14 Feb 2019 18:43:06 +0530 Subject: [PATCH 045/773] code quality improved --- lib/web/mage/validation.js | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/web/mage/validation.js b/lib/web/mage/validation.js index ba187766e236a..256922378a4c8 100644 --- a/lib/web/mage/validation.js +++ b/lib/web/mage/validation.js @@ -1912,7 +1912,6 @@ element.element.attr('name', element.name); element.element.removeAttr('orig-name'); }); - /* Call the originalSubmitHandler if it's a function */ typeof originalSubmitHandler === 'function' ? originalSubmitHandler(form) : form.submit(); }; From 469abb5c89e8c910fa529a92f1bfe4db7d97ecc5 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun Date: Thu, 14 Feb 2019 14:31:15 -0600 Subject: [PATCH 046/773] MC-13958: Additional Permissions for Design settings --- .../Catalog/Model/ProductRepository.php | 17 +++++---- .../Product/Form/Modifier/Eav.php | 1 + app/code/Magento/Catalog/composer.json | 3 +- .../Catalog/Model/ProductRepositoryTest.php | 36 ++++++++++--------- 4 files changed, 33 insertions(+), 24 deletions(-) diff --git a/app/code/Magento/Catalog/Model/ProductRepository.php b/app/code/Magento/Catalog/Model/ProductRepository.php index 5b044245886d4..6b0f76b206781 100644 --- a/app/code/Magento/Catalog/Model/ProductRepository.php +++ b/app/code/Magento/Catalog/Model/ProductRepository.php @@ -34,8 +34,10 @@ /** * Product Repository. + * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) * @SuppressWarnings(PHPMD.TooManyFields) + * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) */ class ProductRepository implements \Magento\Catalog\Api\ProductRepositoryInterface { @@ -373,15 +375,16 @@ protected function initializeProductData(array $productData, $createNew) } $userType = $this->userContext->getUserType(); - if ($userType === UserContextInterface::USER_TYPE_ADMIN + if (( + $userType === UserContextInterface::USER_TYPE_ADMIN || $userType === UserContextInterface::USER_TYPE_INTEGRATION + ) + && !$this->authorization->isAllowed('Magento_Catalog::edit_product_design') ) { - if (!$this->authorization->isAllowed('Magento_Catalog::edit_product_design')) { - $product->lockAttribute('custom_design'); - $product->lockAttribute('page_layout'); - $product->lockAttribute('options_container'); - $product->lockAttribute('custom_layout_update'); - } + $product->lockAttribute('custom_design'); + $product->lockAttribute('page_layout'); + $product->lockAttribute('options_container'); + $product->lockAttribute('custom_layout_update'); } foreach ($productData as $key => $value) { diff --git a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php index 9e3e0a54e8444..ba6dd623405a2 100755 --- a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php +++ b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php @@ -244,6 +244,7 @@ class Eav extends AbstractModifier * @param CompositeConfigProcessor|null $wysiwygConfigProcessor * @param ScopeConfigInterface|null $scopeConfig * @param AttributeCollectionFactory $attributeCollectionFactory + * @param AuthorizationInterface|null $auth * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( diff --git a/app/code/Magento/Catalog/composer.json b/app/code/Magento/Catalog/composer.json index 44d051933909b..3dfae99575c35 100644 --- a/app/code/Magento/Catalog/composer.json +++ b/app/code/Magento/Catalog/composer.json @@ -29,7 +29,8 @@ "magento/module-ui": "*", "magento/module-url-rewrite": "*", "magento/module-widget": "*", - "magento/module-wishlist": "*" + "magento/module-wishlist": "*", + "magento/module-authorization": "*" }, "suggest": { "magento/module-cookie": "*", diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductRepositoryTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductRepositoryTest.php index 71b4455f3a1fa..2a4a8bf9de2a2 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductRepositoryTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductRepositoryTest.php @@ -9,20 +9,22 @@ use Magento\Authorization\Model\Role; use Magento\Authorization\Model\RoleFactory; +use Magento\Backend\Model\Auth; use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Framework\Acl\RootResource; use Magento\Framework\Api\SearchCriteriaBuilder; use Magento\TestFramework\Helper\Bootstrap; use Magento\Authorization\Model\Rules; use Magento\Authorization\Model\RulesFactory; use Magento\TestFramework\Bootstrap as TestBootstrap; -use Magento\User\Model\User; -use Magento\User\Model\UserFactory; /** * Provide tests for ProductRepository model. * * @magentoDbIsolation enabled * @magentoAppIsolation enabled + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class ProductRepositoryTest extends \PHPUnit\Framework\TestCase { @@ -49,9 +51,9 @@ class ProductRepositoryTest extends \PHPUnit\Framework\TestCase private $roleFactory; /** - * @var UserFactory + * @var Auth */ - private $userFactory; + private $auth; /** * Sets up common objects @@ -62,7 +64,7 @@ protected function setUp() $this->searchCriteriaBuilder = Bootstrap::getObjectManager()->get(SearchCriteriaBuilder::class); $this->rulesFactory = Bootstrap::getObjectManager()->get(RulesFactory::class); $this->roleFactory = Bootstrap::getObjectManager()->get(RoleFactory::class); - $this->userFactory = Bootstrap::getObjectManager()->get(UserFactory::class); + $this->auth = Bootstrap::getObjectManager()->get(Auth::class); } /** @@ -164,6 +166,7 @@ public function testSaveProductWithGalleryImage(): void * Test authorization when saving product's design settings. * * @magentoDataFixture Magento/Catalog/_files/product_simple.php + * @magentoAppArea adminhtml */ public function testSaveDesign() { @@ -171,8 +174,7 @@ public function testSaveDesign() /** @var Role $role */ $role = $this->roleFactory->create(); $role->load(TestBootstrap::ADMIN_ROLE_NAME, 'role_name'); - /** @var User $user */ - $user = $this->userFactory->create(); + $this->auth->login(TestBootstrap::ADMIN_NAME, TestBootstrap::ADMIN_PASSWORD); //Admin doesn't have access to product's design. /** @var Rules $rules */ @@ -180,10 +182,6 @@ public function testSaveDesign() $rules->setRoleId($role->getId()); $rules->setResources(['Magento_Catalog::products']); $rules->saveRel(); - $user->login( - TestBootstrap::ADMIN_NAME, - TestBootstrap::ADMIN_PASSWORD - )->reload(); $product->setCustomAttribute('custom_design', 2); $product = $this->productRepository->save($product); @@ -195,13 +193,19 @@ public function testSaveDesign() $rules->setRoleId($role->getId()); $rules->setResources(['Magento_Catalog::products', 'Magento_Catalog::edit_product_design']); $rules->saveRel(); - $user->login( - TestBootstrap::ADMIN_NAME, - TestBootstrap::ADMIN_PASSWORD - )->reload(); $product->setCustomAttribute('custom_design', 2); $product = $this->productRepository->save($product); - $this->assertEquals(2, $product->getCustomAttribute('custom_design')); + $this->assertNotEmpty($product->getCustomAttribute('custom_design')); + $this->assertEquals(2, $product->getCustomAttribute('custom_design')->getValue()); + + //Restoring the role + /** @var RootResource $rootResource */ + $rootResource = Bootstrap::getObjectManager()->get(\Magento\Framework\Acl\RootResource::class); + /** @var Rules $rules */ + $rules = $this->rulesFactory->create(); + $rules->setRoleId($role->getId()); + $rules->setResources([$rootResource->getId()]); + $rules->saveRel(); } } From f4174f8a22b91c502c8f11571a86046979e727e8 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun Date: Thu, 14 Feb 2019 18:19:22 -0600 Subject: [PATCH 047/773] MC-13958: Additional Permissions for Design settings --- .../Catalog/Model/Category/DataProvider.php | 21 +++- .../Catalog/Model/ProductRepository.php | 43 +------ .../Catalog/Model/ResourceModel/Category.php | 54 ++++++++- .../Catalog/Model/ResourceModel/Product.php | 38 +++++- app/code/Magento/Catalog/etc/acl.xml | 4 +- app/code/Magento/Catalog/i18n/en_US.csv | 3 +- .../Magento/Cms/Model/Page/DataProvider.php | 59 +++++++++- app/code/Magento/Cms/Model/PageRepository.php | 48 +++++++- app/code/Magento/Cms/etc/acl.xml | 4 +- app/code/Magento/Cms/i18n/en_US.csv | 1 + .../Catalog/Model/CategoryRepositoryTest.php | 110 ++++++++++++++++++ .../Catalog/Model/ProductRepositoryTest.php | 3 +- 12 files changed, 337 insertions(+), 51 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/Model/CategoryRepositoryTest.php diff --git a/app/code/Magento/Catalog/Model/Category/DataProvider.php b/app/code/Magento/Catalog/Model/Category/DataProvider.php index a4127c9a97ffd..22ee8baff4823 100644 --- a/app/code/Magento/Catalog/Model/Category/DataProvider.php +++ b/app/code/Magento/Catalog/Model/Category/DataProvider.php @@ -25,6 +25,7 @@ use Magento\Ui\Component\Form\Field; use Magento\Ui\DataProvider\EavValidationRules; use Magento\Ui\DataProvider\Modifier\PoolInterface; +use Magento\Framework\AuthorizationInterface; /** * Class DataProvider @@ -146,6 +147,11 @@ class DataProvider extends \Magento\Ui\DataProvider\ModifierPoolDataProvider */ private $fileInfo; + /** + * @var AuthorizationInterface + */ + private $auth; + /** * DataProvider constructor * @@ -162,6 +168,7 @@ class DataProvider extends \Magento\Ui\DataProvider\ModifierPoolDataProvider * @param array $meta * @param array $data * @param PoolInterface|null $pool + * @param AuthorizationInterface|null $auth * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -177,7 +184,8 @@ public function __construct( CategoryFactory $categoryFactory, array $meta = [], array $data = [], - PoolInterface $pool = null + PoolInterface $pool = null, + ?AuthorizationInterface $auth = null ) { $this->eavValidationRules = $eavValidationRules; $this->collection = $categoryCollectionFactory->create(); @@ -187,6 +195,7 @@ public function __construct( $this->storeManager = $storeManager; $this->request = $request; $this->categoryFactory = $categoryFactory; + $this->auth = $auth ?? ObjectManager::getInstance()->get(AuthorizationInterface::class); parent::__construct($name, $primaryFieldName, $requestFieldName, $meta, $data, $pool); } @@ -277,11 +286,19 @@ public function prepareMeta($meta) */ private function prepareFieldsMeta($fieldsMap, $fieldsMeta) { + $canEditDesign = $this->auth->isAllowed('Magento_Catalog::edit_category_design'); + $result = []; foreach ($fieldsMap as $fieldSet => $fields) { foreach ($fields as $field) { if (isset($fieldsMeta[$field])) { - $result[$fieldSet]['children'][$field]['arguments']['data']['config'] = $fieldsMeta[$field]; + $config = $fieldsMeta[$field]; + if (($fieldSet === 'design' || $fieldSet === 'schedule_design_update') && !$canEditDesign) { + $config['required'] = 1; + $config['disabled'] = 1; + } + + $result[$fieldSet]['children'][$field]['arguments']['data']['config'] = $config; } } } diff --git a/app/code/Magento/Catalog/Model/ProductRepository.php b/app/code/Magento/Catalog/Model/ProductRepository.php index 6b0f76b206781..d124bf5e42639 100644 --- a/app/code/Magento/Catalog/Model/ProductRepository.php +++ b/app/code/Magento/Catalog/Model/ProductRepository.php @@ -17,7 +17,6 @@ use Magento\Framework\Api\ImageContentValidatorInterface; use Magento\Framework\Api\ImageProcessorInterface; use Magento\Framework\Api\SearchCriteria\CollectionProcessorInterface; -use Magento\Framework\App\ObjectManager; use Magento\Framework\DB\Adapter\ConnectionException; use Magento\Framework\DB\Adapter\DeadlockException; use Magento\Framework\DB\Adapter\LockWaitException; @@ -29,15 +28,11 @@ use Magento\Framework\Exception\TemporaryState\CouldNotSaveException as TemporaryCouldNotSaveException; use Magento\Framework\Exception\StateException; use Magento\Framework\Exception\ValidatorException; -use Magento\Authorization\Model\UserContextInterface; -use Magento\Framework\AuthorizationInterface; /** * Product Repository. - * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) * @SuppressWarnings(PHPMD.TooManyFields) - * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) */ class ProductRepository implements \Magento\Catalog\Api\ProductRepositoryInterface { @@ -166,16 +161,6 @@ class ProductRepository implements \Magento\Catalog\Api\ProductRepositoryInterfa */ private $readExtensions; - /** - * @var UserContextInterface - */ - private $userContext; - - /** - * @var AuthorizationInterface - */ - private $authorization; - /** * ProductRepository constructor. * @param ProductFactory $productFactory @@ -202,8 +187,6 @@ class ProductRepository implements \Magento\Catalog\Api\ProductRepositoryInterfa * @param \Magento\Framework\Serialize\Serializer\Json|null $serializer * @param int $cacheLimit [optional] * @param ReadExtensions|null $readExtensions - * @param UserContextInterface|null $userContext - * @param AuthorizationInterface|null $authorization * @SuppressWarnings(PHPMD.ExcessiveParameterList) * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ @@ -231,9 +214,7 @@ public function __construct( CollectionProcessorInterface $collectionProcessor = null, \Magento\Framework\Serialize\Serializer\Json $serializer = null, $cacheLimit = 1000, - ReadExtensions $readExtensions = null, - ?UserContextInterface $userContext = null, - ?AuthorizationInterface $authorization = null + ReadExtensions $readExtensions = null ) { $this->productFactory = $productFactory; $this->collectionFactory = $collectionFactory; @@ -253,12 +234,11 @@ public function __construct( $this->imageProcessor = $imageProcessor; $this->extensionAttributesJoinProcessor = $extensionAttributesJoinProcessor; $this->collectionProcessor = $collectionProcessor ?: $this->getCollectionProcessor(); - $this->serializer = $serializer - ?: ObjectManager::getInstance()->get(\Magento\Framework\Serialize\Serializer\Json::class); + $this->serializer = $serializer ?: \Magento\Framework\App\ObjectManager::getInstance() + ->get(\Magento\Framework\Serialize\Serializer\Json::class); $this->cacheLimit = (int)$cacheLimit; - $this->readExtensions = $readExtensions ?: ObjectManager::getInstance()->get(ReadExtensions::class); - $this->userContext = $userContext ?? ObjectManager::getInstance()->get(UserContextInterface::class); - $this->authorization = $authorization ?? ObjectManager::getInstance()->get(AuthorizationInterface::class); + $this->readExtensions = $readExtensions ?: \Magento\Framework\App\ObjectManager::getInstance() + ->get(ReadExtensions::class); } /** @@ -374,19 +354,6 @@ protected function initializeProductData(array $productData, $createNew) $product = $this->get($productData['sku']); } - $userType = $this->userContext->getUserType(); - if (( - $userType === UserContextInterface::USER_TYPE_ADMIN - || $userType === UserContextInterface::USER_TYPE_INTEGRATION - ) - && !$this->authorization->isAllowed('Magento_Catalog::edit_product_design') - ) { - $product->lockAttribute('custom_design'); - $product->lockAttribute('page_layout'); - $product->lockAttribute('options_container'); - $product->lockAttribute('custom_layout_update'); - } - foreach ($productData as $key => $value) { $product->setData($key, $value); } diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Category.php b/app/code/Magento/Catalog/Model/ResourceModel/Category.php index 536fda7e093d3..69c6bb302257f 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Category.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Category.php @@ -12,8 +12,12 @@ namespace Magento\Catalog\Model\ResourceModel; use Magento\Catalog\Model\Indexer\Category\Product\Processor; +use Magento\Framework\App\ObjectManager; use Magento\Framework\DataObject; use Magento\Framework\EntityManager\EntityManager; +use Magento\Framework\AuthorizationInterface; +use Magento\Authorization\Model\UserContextInterface; +use Magento\Catalog\Model\Category as CategoryEntity; /** * Resource model for category entity @@ -91,6 +95,16 @@ class Category extends AbstractResource */ private $indexerProcessor; + /** + * @var UserContextInterface + */ + private $userContext; + + /** + * @var AuthorizationInterface + */ + private $authorization; + /** * Category constructor. * @param \Magento\Eav\Model\Entity\Context $context @@ -102,6 +116,8 @@ class Category extends AbstractResource * @param Processor $indexerProcessor * @param array $data * @param \Magento\Framework\Serialize\Serializer\Json|null $serializer + * @param UserContextInterface|null $userContext + * @param AuthorizationInterface|null $authorization */ public function __construct( \Magento\Eav\Model\Entity\Context $context, @@ -112,7 +128,9 @@ public function __construct( \Magento\Catalog\Model\ResourceModel\Category\CollectionFactory $categoryCollectionFactory, Processor $indexerProcessor, $data = [], - \Magento\Framework\Serialize\Serializer\Json $serializer = null + \Magento\Framework\Serialize\Serializer\Json $serializer = null, + ?UserContextInterface $userContext = null, + ?AuthorizationInterface $authorization = null ) { parent::__construct( $context, @@ -125,8 +143,10 @@ public function __construct( $this->_eventManager = $eventManager; $this->connectionName = 'catalog'; $this->indexerProcessor = $indexerProcessor; - $this->serializer = $serializer ?: \Magento\Framework\App\ObjectManager::getInstance() + $this->serializer = $serializer ?: ObjectManager::getInstance() ->get(\Magento\Framework\Serialize\Serializer\Json::class); + $this->userContext = $userContext ?? ObjectManager::getInstance()->get(UserContextInterface::class); + $this->authorization = $authorization ?? ObjectManager::getInstance()->get(AuthorizationInterface::class); } /** @@ -1132,4 +1152,34 @@ private function getAggregateCount() } return $this->aggregateCount; } + + /** + * @inheritDoc + * @param CategoryEntity|object $object + */ + public function validate($object) + { + $isValid = parent::validate($object); + if ($isValid !== true) { + return $isValid; + } + + //Validate changing of design. + $userType = $this->userContext->getUserType(); + if (( + $userType === UserContextInterface::USER_TYPE_ADMIN + || $userType === UserContextInterface::USER_TYPE_INTEGRATION + ) + && !$this->authorization->isAllowed('Magento_Catalog::edit_category_design') + ) { + $object->setData('custom_design', $object->getOrigData('custom_design')); + $object->setData('custom_design_from', $object->getOrigData('custom_design_from')); + $object->setData('custom_design_to', $object->getOrigData('custom_design_to')); + $object->setData('page_layout', $object->getOrigData('page_layout')); + $object->setData('custom_layout_update', $object->getOrigData('custom_layout_update')); + $object->setData('custom_apply_to_products', $object->getOrigData('custom_apply_to_products')); + } + + return true; + } } diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product.php b/app/code/Magento/Catalog/Model/ResourceModel/Product.php index d71ec23881982..0d0dfe7b60dc9 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product.php @@ -5,9 +5,12 @@ */ namespace Magento\Catalog\Model\ResourceModel; +use Magento\Authorization\Model\UserContextInterface; use Magento\Catalog\Model\ResourceModel\Product\Website\Link as ProductWebsiteLink; use Magento\Framework\App\ObjectManager; use Magento\Catalog\Model\Indexer\Category\Product\TableMaintainer; +use Magento\Framework\AuthorizationInterface; +use Magento\Catalog\Model\Product as ProductEntity; /** * Product entity resource model @@ -89,6 +92,16 @@ class Product extends AbstractResource */ private $tableMaintainer; + /** + * @var UserContextInterface + */ + private $userContext; + + /** + * @var AuthorizationInterface + */ + private $authorization; + /** * @param \Magento\Eav\Model\Entity\Context $context * @param \Magento\Store\Model\StoreManagerInterface $storeManager @@ -101,6 +114,8 @@ class Product extends AbstractResource * @param \Magento\Catalog\Model\Product\Attribute\DefaultAttributes $defaultAttributes * @param array $data * @param TableMaintainer|null $tableMaintainer + * @param UserContextInterface|null $userContext + * @param AuthorizationInterface|null $authorization * * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -115,7 +130,9 @@ public function __construct( \Magento\Eav\Model\Entity\TypeFactory $typeFactory, \Magento\Catalog\Model\Product\Attribute\DefaultAttributes $defaultAttributes, $data = [], - TableMaintainer $tableMaintainer = null + TableMaintainer $tableMaintainer = null, + ?UserContextInterface $userContext = null, + ?AuthorizationInterface $authorization = null ) { $this->_categoryCollectionFactory = $categoryCollectionFactory; $this->_catalogCategory = $catalogCategory; @@ -123,6 +140,8 @@ public function __construct( $this->setFactory = $setFactory; $this->typeFactory = $typeFactory; $this->defaultAttributes = $defaultAttributes; + $this->userContext = $userContext ?? ObjectManager::getInstance()->get(UserContextInterface::class); + $this->authorization = $authorization ?? ObjectManager::getInstance()->get(AuthorizationInterface::class); parent::__construct( $context, $storeManager, @@ -593,10 +612,25 @@ public function countAll() } /** - * {@inheritdoc} + * @inheritDoc + * @param ProductEntity|object $object */ public function validate($object) { + //Validate changing of design. + $userType = $this->userContext->getUserType(); + if (( + $userType === UserContextInterface::USER_TYPE_ADMIN + || $userType === UserContextInterface::USER_TYPE_INTEGRATION + ) + && !$this->authorization->isAllowed('Magento_Catalog::edit_product_design') + ) { + $object->setData('custom_design', $object->getOrigData('custom_design')); + $object->setData('page_layout', $object->getOrigData('page_layout')); + $object->setData('options_container', $object->getOrigData('options_container')); + $object->setData('custom_layout_update', $object->getOrigData('custom_layout_update')); + } + //validate attribute set entity type $entityType = $this->typeFactory->create()->loadByCode(\Magento\Catalog\Model\Product::ENTITY); $attributeSet = $this->setFactory->create()->load($object->getAttributeSetId()); diff --git a/app/code/Magento/Catalog/etc/acl.xml b/app/code/Magento/Catalog/etc/acl.xml index 79b1e3426b2f1..fbc61141258a0 100644 --- a/app/code/Magento/Catalog/etc/acl.xml +++ b/app/code/Magento/Catalog/etc/acl.xml @@ -14,7 +14,9 @@ - + + + diff --git a/app/code/Magento/Catalog/i18n/en_US.csv b/app/code/Magento/Catalog/i18n/en_US.csv index 27b9e43658901..c35ffbce1a125 100644 --- a/app/code/Magento/Catalog/i18n/en_US.csv +++ b/app/code/Magento/Catalog/i18n/en_US.csv @@ -809,4 +809,5 @@ Details,Details "Product with ID: (%1) doesn't exist", "Product with ID: (%1) doesn't exist" "Category with ID: (%1) doesn't exist", "Category with ID: (%1) doesn't exist" "You added product %1 to the comparison list.","You added product %1 to the comparison list." -"Edit Product Design","Edit Product Design" \ No newline at end of file +"Edit Product Design","Edit Product Design" +"Edit Category Design","Edit Category Design" \ No newline at end of file diff --git a/app/code/Magento/Cms/Model/Page/DataProvider.php b/app/code/Magento/Cms/Model/Page/DataProvider.php index abbe9254a68d4..0f0edf878c7b8 100644 --- a/app/code/Magento/Cms/Model/Page/DataProvider.php +++ b/app/code/Magento/Cms/Model/Page/DataProvider.php @@ -6,8 +6,10 @@ namespace Magento\Cms\Model\Page; use Magento\Cms\Model\ResourceModel\Page\CollectionFactory; +use Magento\Framework\App\ObjectManager; use Magento\Framework\App\Request\DataPersistorInterface; use Magento\Ui\DataProvider\Modifier\PoolInterface; +use Magento\Framework\AuthorizationInterface; /** * Class DataProvider @@ -29,6 +31,11 @@ class DataProvider extends \Magento\Ui\DataProvider\ModifierPoolDataProvider */ protected $loadedData; + /** + * @var AuthorizationInterface + */ + private $auth; + /** * @param string $name * @param string $primaryFieldName @@ -38,6 +45,7 @@ class DataProvider extends \Magento\Ui\DataProvider\ModifierPoolDataProvider * @param array $meta * @param array $data * @param PoolInterface|null $pool + * @param AuthorizationInterface|null $auth */ public function __construct( $name, @@ -47,11 +55,13 @@ public function __construct( DataPersistorInterface $dataPersistor, array $meta = [], array $data = [], - PoolInterface $pool = null + PoolInterface $pool = null, + ?AuthorizationInterface $auth = null ) { $this->collection = $pageCollectionFactory->create(); $this->dataPersistor = $dataPersistor; parent::__construct($name, $primaryFieldName, $requestFieldName, $meta, $data, $pool); + $this->auth = $auth ?? ObjectManager::getInstance()->get(AuthorizationInterface::class); $this->meta = $this->prepareMeta($this->meta); } @@ -92,4 +102,51 @@ public function getData() return $this->loadedData; } + + /** + * @inheritDoc + */ + public function getMeta() + { + $meta = parent::getMeta(); + + if (!$this->auth->isAllowed('Magento_Cms::save_design')) { + $designMeta = [ + 'design' => [ + 'children' => [ + 'page_layout' => [ + 'arguments' => [ + 'data' => [ + 'config' => [ + 'disabled' => true, + ] + ] + ] + ], + 'layout_update_xml' => [ + 'arguments' => [ + 'data' => [ + 'config' => [ + 'disabled' => true, + ] + ] + ] + ], + 'custom_theme' => [ + 'arguments' => [ + 'data' => [ + 'config' => [ + 'disabled' => true, + ] + ] + ] + ] + ] + ] + ]; + $meta = array_merge_recursive($meta, $designMeta); + } + + return $meta; + } } diff --git a/app/code/Magento/Cms/Model/PageRepository.php b/app/code/Magento/Cms/Model/PageRepository.php index 5578ae49f586d..d3626691d933d 100644 --- a/app/code/Magento/Cms/Model/PageRepository.php +++ b/app/code/Magento/Cms/Model/PageRepository.php @@ -10,6 +10,7 @@ use Magento\Cms\Api\PageRepositoryInterface; use Magento\Framework\Api\DataObjectHelper; use Magento\Framework\Api\SearchCriteria\CollectionProcessorInterface; +use Magento\Framework\App\ObjectManager; use Magento\Framework\Exception\CouldNotDeleteException; use Magento\Framework\Exception\CouldNotSaveException; use Magento\Framework\Exception\NoSuchEntityException; @@ -17,6 +18,8 @@ use Magento\Cms\Model\ResourceModel\Page as ResourcePage; use Magento\Cms\Model\ResourceModel\Page\CollectionFactory as PageCollectionFactory; use Magento\Store\Model\StoreManagerInterface; +use Magento\Framework\AuthorizationInterface; +use Magento\Authorization\Model\UserContextInterface; /** * Class PageRepository @@ -69,6 +72,16 @@ class PageRepository implements PageRepositoryInterface */ private $collectionProcessor; + /** + * @var UserContextInterface + */ + private $userContext; + + /** + * @var AuthorizationInterface + */ + private $authorization; + /** * @param ResourcePage $resource * @param PageFactory $pageFactory @@ -79,6 +92,8 @@ class PageRepository implements PageRepositoryInterface * @param DataObjectProcessor $dataObjectProcessor * @param StoreManagerInterface $storeManager * @param CollectionProcessorInterface $collectionProcessor + * @param UserContextInterface|null $userContext + * @param AuthorizationInterface|null $authorization */ public function __construct( ResourcePage $resource, @@ -89,7 +104,9 @@ public function __construct( DataObjectHelper $dataObjectHelper, DataObjectProcessor $dataObjectProcessor, StoreManagerInterface $storeManager, - CollectionProcessorInterface $collectionProcessor = null + CollectionProcessorInterface $collectionProcessor = null, + ?UserContextInterface $userContext = null, + ?AuthorizationInterface $authorization = null ) { $this->resource = $resource; $this->pageFactory = $pageFactory; @@ -100,12 +117,14 @@ public function __construct( $this->dataObjectProcessor = $dataObjectProcessor; $this->storeManager = $storeManager; $this->collectionProcessor = $collectionProcessor ?: $this->getCollectionProcessor(); + $this->userContext = $userContext ?? ObjectManager::getInstance()->get(UserContextInterface::class); + $this->authorization = $authorization ?? ObjectManager::getInstance()->get(AuthorizationInterface::class); } /** * Save Page data * - * @param \Magento\Cms\Api\Data\PageInterface $page + * @param \Magento\Cms\Api\Data\PageInterface|Page $page * @return Page * @throws CouldNotSaveException */ @@ -116,6 +135,31 @@ public function save(\Magento\Cms\Api\Data\PageInterface $page) $page->setStoreId($storeId); } try { + //Validate changing of design. + $userType = $this->userContext->getUserType(); + if (( + $userType === UserContextInterface::USER_TYPE_ADMIN + || $userType === UserContextInterface::USER_TYPE_INTEGRATION + ) + && !$this->authorization->isAllowed('Magento_Cms::save_design') + ) { + if (!$page->getId()) { + $page->setLayoutUpdateXml(null); + $page->setPageLayout(null); + $page->setCustomTheme(null); + $page->setCustomLayoutUpdateXml(null); + } else { + $savedPage = $this->getById($page->getId()); + $page->setLayoutUpdateXml($savedPage->getLayoutUpdateXml()); + $page->setPageLayout($savedPage->getPageLayout()); + $page->setCustomTheme($savedPage->getCustomTheme()); + $page->setCustomLayoutUpdateXml($savedPage->getCustomLayoutUpdateXml()); + } + $page->setData('layout_update_xml', $page->getOrigData('layout_update_xml')); + $page->setData('page_layout', $page->getOrigData('page_layout')); + $page->setData('custom_theme', $page->getOrigData('custom_theme')); + } + $this->resource->save($page); } catch (\Exception $exception) { throw new CouldNotSaveException( diff --git a/app/code/Magento/Cms/etc/acl.xml b/app/code/Magento/Cms/etc/acl.xml index b13b58b101f90..3df31923d1eb6 100644 --- a/app/code/Magento/Cms/etc/acl.xml +++ b/app/code/Magento/Cms/etc/acl.xml @@ -12,7 +12,9 @@ - + + + diff --git a/app/code/Magento/Cms/i18n/en_US.csv b/app/code/Magento/Cms/i18n/en_US.csv index b34793c35d659..2947c567d75ff 100644 --- a/app/code/Magento/Cms/i18n/en_US.csv +++ b/app/code/Magento/Cms/i18n/en_US.csv @@ -155,3 +155,4 @@ Enable,Enable "Custom design to","Custom design to" "Custom Theme","Custom Theme" "Custom Layout","Custom Layout" +"Edit Page Design","Edit Page Design" diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/CategoryRepositoryTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/CategoryRepositoryTest.php new file mode 100644 index 0000000000000..0403c1ee74c4e --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/CategoryRepositoryTest.php @@ -0,0 +1,110 @@ +repo = Bootstrap::getObjectManager()->create(CategoryRepositoryInterface::class); + $this->rulesFactory = Bootstrap::getObjectManager()->get(RulesFactory::class); + $this->roleFactory = Bootstrap::getObjectManager()->get(RoleFactory::class); + $this->auth = Bootstrap::getObjectManager()->get(Auth::class); + } + + /** + * Test authorization when saving product's design settings. + * + * @magentoDataFixture Magento/Catalog/_files/category.php + * @magentoAppArea adminhtml + * @magentoDbIsolation enabled + * @magentoAppIsolation enabled + */ + public function testSaveDesign() + { + $category = $this->repo->get(333); + /** @var Role $role */ + $role = $this->roleFactory->create(); + $role->load(TestBootstrap::ADMIN_ROLE_NAME, 'role_name'); + $this->auth->login(TestBootstrap::ADMIN_NAME, TestBootstrap::ADMIN_PASSWORD); + + //Admin doesn't have access to product's design. + /** @var Rules $rules */ + $rules = $this->rulesFactory->create(); + $rules->setRoleId($role->getId()); + $rules->setResources(['Magento_Catalog::products']); + $rules->saveRel(); + + $category->setCustomAttribute('custom_design', 2); + $category = $this->repo->save($category); + $this->assertEmpty($category->getCustomAttribute('custom_design')); + + //Admin has access to products' design. + /** @var Rules $rules */ + $rules = $this->rulesFactory->create(); + $rules->setRoleId($role->getId()); + $rules->setResources(['Magento_Catalog::products', 'Magento_Catalog::edit_category_design']); + $rules->saveRel(); + + $category->setCustomAttribute('custom_design', 2); + $category = $this->repo->save($category); + $this->assertNotEmpty($category->getCustomAttribute('custom_design')); + $this->assertEquals(2, $category->getCustomAttribute('custom_design')->getValue()); + + //Restoring the role + /** @var RootResource $rootResource */ + $rootResource = Bootstrap::getObjectManager()->get(RootResource::class); + /** @var Rules $rules */ + $rules = $this->rulesFactory->create(); + $rules->setRoleId($role->getId()); + $rules->setResources([$rootResource->getId()]); + $rules->saveRel(); + $this->auth->logout(); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductRepositoryTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductRepositoryTest.php index 2a4a8bf9de2a2..1a6c16dd32d10 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductRepositoryTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductRepositoryTest.php @@ -201,11 +201,12 @@ public function testSaveDesign() //Restoring the role /** @var RootResource $rootResource */ - $rootResource = Bootstrap::getObjectManager()->get(\Magento\Framework\Acl\RootResource::class); + $rootResource = Bootstrap::getObjectManager()->get(RootResource::class); /** @var Rules $rules */ $rules = $this->rulesFactory->create(); $rules->setRoleId($role->getId()); $rules->setResources([$rootResource->getId()]); $rules->saveRel(); + $this->auth->logout(); } } From ec707c7e8e010c3bc2321d8f43ab872de64509f5 Mon Sep 17 00:00:00 2001 From: roman Date: Fri, 15 Feb 2019 13:25:55 +0200 Subject: [PATCH 048/773] MC-14893: Fixed incorrect behavior of email templates --- lib/internal/Magento/Framework/Filter/Template.php | 6 +++++- .../Magento/Framework/Filter/Test/Unit/TemplateTest.php | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/Filter/Template.php b/lib/internal/Magento/Framework/Filter/Template.php index d3a8d5334ab9d..480a883143256 100644 --- a/lib/internal/Magento/Framework/Filter/Template.php +++ b/lib/internal/Magento/Framework/Filter/Template.php @@ -75,7 +75,11 @@ class Template implements \Zend_Filter_Interface 'load', 'save', 'getcollection', - 'getresource' + 'getresource', + 'setvariables', + 'settemplateprocessor', + 'gettemplateprocessor', + 'vardirective' ]; /** diff --git a/lib/internal/Magento/Framework/Filter/Test/Unit/TemplateTest.php b/lib/internal/Magento/Framework/Filter/Test/Unit/TemplateTest.php index e4a2dc48d11dd..0a5ff8639afca 100644 --- a/lib/internal/Magento/Framework/Filter/Test/Unit/TemplateTest.php +++ b/lib/internal/Magento/Framework/Filter/Test/Unit/TemplateTest.php @@ -437,6 +437,10 @@ public function disallowedMethods() ['save'], ['getCollection'], ['getResource'], + ['setVariables'], + ['setTemplateProcessor'], + ['getTemplateProcessor'], + ['varDirective'] ]; } } From b2f9d903d3781681ed7b4f947eb225ae1cbd0f72 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun Date: Fri, 15 Feb 2019 12:01:53 -0600 Subject: [PATCH 049/773] MC-13958: Additional Permissions for Design settings --- app/code/Magento/Cms/Model/PageRepository.php | 3 - .../Catalog/Model/CategoryRepositoryTest.php | 39 +++--- .../Catalog/Model/ProductRepositoryTest.php | 27 ++--- .../Magento/Cms/Model/PageRepositoryTest.php | 113 ++++++++++++++++++ .../User/_files/user_with_new_role.php | 33 +++++ .../_files/user_with_new_role_rollback.php | 21 ++++ 6 files changed, 198 insertions(+), 38 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/Cms/Model/PageRepositoryTest.php create mode 100644 dev/tests/integration/testsuite/Magento/User/_files/user_with_new_role.php create mode 100644 dev/tests/integration/testsuite/Magento/User/_files/user_with_new_role_rollback.php diff --git a/app/code/Magento/Cms/Model/PageRepository.php b/app/code/Magento/Cms/Model/PageRepository.php index d3626691d933d..b0d1af87d6a9c 100644 --- a/app/code/Magento/Cms/Model/PageRepository.php +++ b/app/code/Magento/Cms/Model/PageRepository.php @@ -155,9 +155,6 @@ public function save(\Magento\Cms\Api\Data\PageInterface $page) $page->setCustomTheme($savedPage->getCustomTheme()); $page->setCustomLayoutUpdateXml($savedPage->getCustomLayoutUpdateXml()); } - $page->setData('layout_update_xml', $page->getOrigData('layout_update_xml')); - $page->setData('page_layout', $page->getOrigData('page_layout')); - $page->setData('custom_theme', $page->getOrigData('custom_theme')); } $this->resource->save($page); diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/CategoryRepositoryTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/CategoryRepositoryTest.php index 0403c1ee74c4e..dbc70b89d3697 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Model/CategoryRepositoryTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/CategoryRepositoryTest.php @@ -11,11 +11,9 @@ use Magento\Authorization\Model\RoleFactory; use Magento\Backend\Model\Auth; use Magento\Catalog\Api\CategoryRepositoryInterface; -use Magento\Framework\Acl\RootResource; use Magento\TestFramework\Helper\Bootstrap; use Magento\Authorization\Model\Rules; use Magento\Authorization\Model\RulesFactory; -use Magento\TestFramework\Bootstrap as TestBootstrap; use PHPUnit\Framework\TestCase; /** @@ -59,52 +57,51 @@ protected function setUp() } /** - * Test authorization when saving product's design settings. + * @inheritDoc + */ + protected function tearDown() + { + parent::tearDown(); + + $this->auth->logout(); + } + + /** + * Test authorization when saving category's design settings. * * @magentoDataFixture Magento/Catalog/_files/category.php + * @magentoDataFixture Magento/User/_files/user_with_new_role.php * @magentoAppArea adminhtml - * @magentoDbIsolation enabled - * @magentoAppIsolation enabled */ public function testSaveDesign() { $category = $this->repo->get(333); /** @var Role $role */ $role = $this->roleFactory->create(); - $role->load(TestBootstrap::ADMIN_ROLE_NAME, 'role_name'); - $this->auth->login(TestBootstrap::ADMIN_NAME, TestBootstrap::ADMIN_PASSWORD); + $role->load('new_role', 'role_name'); + $this->auth->login('admin_with_role', '12345abc'); - //Admin doesn't have access to product's design. + //Admin doesn't have access to category's design. /** @var Rules $rules */ $rules = $this->rulesFactory->create(); $rules->setRoleId($role->getId()); - $rules->setResources(['Magento_Catalog::products']); + $rules->setResources(['Magento_Catalog::categories']); $rules->saveRel(); $category->setCustomAttribute('custom_design', 2); $category = $this->repo->save($category); $this->assertEmpty($category->getCustomAttribute('custom_design')); - //Admin has access to products' design. + //Admin has access to category' design. /** @var Rules $rules */ $rules = $this->rulesFactory->create(); $rules->setRoleId($role->getId()); - $rules->setResources(['Magento_Catalog::products', 'Magento_Catalog::edit_category_design']); + $rules->setResources(['Magento_Catalog::categories', 'Magento_Catalog::edit_category_design']); $rules->saveRel(); $category->setCustomAttribute('custom_design', 2); $category = $this->repo->save($category); $this->assertNotEmpty($category->getCustomAttribute('custom_design')); $this->assertEquals(2, $category->getCustomAttribute('custom_design')->getValue()); - - //Restoring the role - /** @var RootResource $rootResource */ - $rootResource = Bootstrap::getObjectManager()->get(RootResource::class); - /** @var Rules $rules */ - $rules = $this->rulesFactory->create(); - $rules->setRoleId($role->getId()); - $rules->setResources([$rootResource->getId()]); - $rules->saveRel(); - $this->auth->logout(); } } diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductRepositoryTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductRepositoryTest.php index 1a6c16dd32d10..283b0713e9763 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductRepositoryTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductRepositoryTest.php @@ -11,12 +11,10 @@ use Magento\Authorization\Model\RoleFactory; use Magento\Backend\Model\Auth; use Magento\Catalog\Api\ProductRepositoryInterface; -use Magento\Framework\Acl\RootResource; use Magento\Framework\Api\SearchCriteriaBuilder; use Magento\TestFramework\Helper\Bootstrap; use Magento\Authorization\Model\Rules; use Magento\Authorization\Model\RulesFactory; -use Magento\TestFramework\Bootstrap as TestBootstrap; /** * Provide tests for ProductRepository model. @@ -67,6 +65,16 @@ protected function setUp() $this->auth = Bootstrap::getObjectManager()->get(Auth::class); } + /** + * @inheritDoc + */ + protected function tearDown() + { + parent::tearDown(); + + $this->auth->logout(); + } + /** * Checks filtering by store_id * @@ -166,6 +174,7 @@ public function testSaveProductWithGalleryImage(): void * Test authorization when saving product's design settings. * * @magentoDataFixture Magento/Catalog/_files/product_simple.php + * @magentoDataFixture Magento/User/_files/user_with_new_role.php * @magentoAppArea adminhtml */ public function testSaveDesign() @@ -173,8 +182,8 @@ public function testSaveDesign() $product = $this->productRepository->get('simple'); /** @var Role $role */ $role = $this->roleFactory->create(); - $role->load(TestBootstrap::ADMIN_ROLE_NAME, 'role_name'); - $this->auth->login(TestBootstrap::ADMIN_NAME, TestBootstrap::ADMIN_PASSWORD); + $role->load('new_role', 'role_name'); + $this->auth->login('admin_with_role', '12345abc'); //Admin doesn't have access to product's design. /** @var Rules $rules */ @@ -198,15 +207,5 @@ public function testSaveDesign() $product = $this->productRepository->save($product); $this->assertNotEmpty($product->getCustomAttribute('custom_design')); $this->assertEquals(2, $product->getCustomAttribute('custom_design')->getValue()); - - //Restoring the role - /** @var RootResource $rootResource */ - $rootResource = Bootstrap::getObjectManager()->get(RootResource::class); - /** @var Rules $rules */ - $rules = $this->rulesFactory->create(); - $rules->setRoleId($role->getId()); - $rules->setResources([$rootResource->getId()]); - $rules->saveRel(); - $this->auth->logout(); } } diff --git a/dev/tests/integration/testsuite/Magento/Cms/Model/PageRepositoryTest.php b/dev/tests/integration/testsuite/Magento/Cms/Model/PageRepositoryTest.php new file mode 100644 index 0000000000000..2661099d6fe59 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Cms/Model/PageRepositoryTest.php @@ -0,0 +1,113 @@ +repo = Bootstrap::getObjectManager()->create(PageRepositoryInterface::class); + $this->rulesFactory = Bootstrap::getObjectManager()->get(RulesFactory::class); + $this->roleFactory = Bootstrap::getObjectManager()->get(RoleFactory::class); + $this->auth = Bootstrap::getObjectManager()->get(Auth::class); + $this->criteriaBuilder = Bootstrap::getObjectManager()->get(SearchCriteriaBuilder::class); + } + + /** + * @inheritDoc + */ + protected function tearDown() + { + parent::tearDown(); + + $this->auth->logout(); + } + + /** + * Test authorization when saving page's design settings. + * + * @magentoDataFixture Magento/Cms/_files/pages.php + * @magentoDataFixture Magento/User/_files/user_with_new_role.php + * @magentoAppArea adminhtml + */ + public function testSaveDesign() + { + $pages = $this->repo->getList( + $this->criteriaBuilder->addFilter('identifier', 'page_design_blank')->create() + )->getItems(); + $page = array_pop($pages); + /** @var Role $role */ + $role = $this->roleFactory->create(); + $role->load('new_role', 'role_name'); + $this->auth->login('admin_with_role', '12345abc'); + + //Admin doesn't have access to page's design. + /** @var Rules $rules */ + $rules = $this->rulesFactory->create(); + $rules->setRoleId($role->getId()); + $rules->setResources(['Magento_Cms::save']); + $rules->saveRel(); + + $page->setCustomTheme('test'); + $page = $this->repo->save($page); + $this->assertNotEquals('test', $page->getCustomTheme()); + + //Admin has access to page' design. + /** @var Rules $rules */ + $rules = $this->rulesFactory->create(); + $rules->setRoleId($role->getId()); + $rules->setResources(['Magento_Cms::save', 'Magento_Cms::save_design']); + $rules->saveRel(); + + $page->setCustomTheme('test'); + $page = $this->repo->save($page); + $this->assertEquals('test', $page->getCustomTheme()); + } +} \ No newline at end of file diff --git a/dev/tests/integration/testsuite/Magento/User/_files/user_with_new_role.php b/dev/tests/integration/testsuite/Magento/User/_files/user_with_new_role.php new file mode 100644 index 0000000000000..18087593448f8 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/User/_files/user_with_new_role.php @@ -0,0 +1,33 @@ +create(Role::class); +$role->setRoleName('new_role'); +$role->setRoleType('G'); +$role->save(); + +/** @var User $model */ +$model = $objectManager->create(User::class); +$model->setFirstname("John") + ->setLastname("Doe") + ->setUsername('admin_with_role') + ->setPassword('12345abc') + ->setEmail('admin_with_role@example.com') + ->setRoleType('G') + ->setResourceId('Magento_Backend::all') + ->setPrivileges("") + ->setAssertId(0) + ->setRoleId($role->getId()) + ->setPermission('allow'); +$model->save(); diff --git a/dev/tests/integration/testsuite/Magento/User/_files/user_with_new_role_rollback.php b/dev/tests/integration/testsuite/Magento/User/_files/user_with_new_role_rollback.php new file mode 100644 index 0000000000000..fa9f11b616583 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/User/_files/user_with_new_role_rollback.php @@ -0,0 +1,21 @@ +create(User::class); +$user->load('admin_with_role', 'username'); +$user->delete(); +/** @var Role $role */ +$role = $objectManager->create(Role::class); +$role->load('new_role', 'role_name'); +$role->delete(); \ No newline at end of file From 5da3c9f1b509a7ba8a3cbf1659e92fd67b218944 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun Date: Fri, 15 Feb 2019 12:11:00 -0600 Subject: [PATCH 050/773] MC-13958: Additional Permissions for Design settings --- .../Magento/Catalog/Model/Category/DataProvider.php | 5 +++++ .../Catalog/Model/ResourceModel/Category.php | 2 ++ .../Magento/Catalog/Model/ResourceModel/Product.php | 13 ++++++++++--- app/code/Magento/Cms/Model/PageRepository.php | 1 + app/code/Magento/Cms/composer.json | 3 ++- 5 files changed, 20 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Category/DataProvider.php b/app/code/Magento/Catalog/Model/Category/DataProvider.php index 22ee8baff4823..d30656c3b8df2 100644 --- a/app/code/Magento/Catalog/Model/Category/DataProvider.php +++ b/app/code/Magento/Catalog/Model/Category/DataProvider.php @@ -33,6 +33,7 @@ * @api * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * @SuppressWarnings(PHPMD.TooManyFields) * @since 101.0.0 */ class DataProvider extends \Magento\Ui\DataProvider\ModifierPoolDataProvider @@ -219,6 +220,8 @@ public function getMeta() } /** + * Disable fields if they are using default values. + * * @param Category $category * @param array $meta * @return array @@ -550,6 +553,8 @@ public function getDefaultMetaData($result) } /** + * List of fields groups and fields. + * * @return array * @since 101.0.0 */ diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Category.php b/app/code/Magento/Catalog/Model/ResourceModel/Category.php index 69c6bb302257f..b04190f74e804 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Category.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Category.php @@ -118,6 +118,7 @@ class Category extends AbstractResource * @param \Magento\Framework\Serialize\Serializer\Json|null $serializer * @param UserContextInterface|null $userContext * @param AuthorizationInterface|null $authorization + * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( \Magento\Eav\Model\Entity\Context $context, @@ -1155,6 +1156,7 @@ private function getAggregateCount() /** * @inheritDoc + * * @param CategoryEntity|object $object */ public function validate($object) diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product.php b/app/code/Magento/Catalog/Model/ResourceModel/Product.php index 0d0dfe7b60dc9..9256078cfdd42 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product.php @@ -308,7 +308,7 @@ protected function _afterSave(\Magento\Framework\DataObject $product) } /** - * {@inheritdoc} + * @inheritdoc */ public function delete($object) { @@ -613,6 +613,7 @@ public function countAll() /** * @inheritDoc + * * @param ProductEntity|object $object */ public function validate($object) @@ -667,7 +668,7 @@ public function load($object, $entityId, $attributes = []) } /** - * {@inheritdoc} + * @inheritdoc * @SuppressWarnings(PHPMD.UnusedLocalVariable) * @since 101.0.0 */ @@ -709,6 +710,8 @@ public function save(\Magento\Framework\Model\AbstractModel $object) } /** + * Retrieve entity manager. + * * @return \Magento\Framework\EntityManager\EntityManager */ private function getEntityManager() @@ -721,6 +724,8 @@ private function getEntityManager() } /** + * Retrieve ProductWebsiteLink instance. + * * @deprecated 101.1.0 * @return ProductWebsiteLink */ @@ -730,6 +735,8 @@ private function getProductWebsiteLink() } /** + * Retrieve CategoryLink instance. + * * @deprecated 101.1.0 * @return \Magento\Catalog\Model\ResourceModel\Product\CategoryLink */ @@ -746,7 +753,7 @@ private function getProductCategoryLink() * Extends parent method to be appropriate for product. * Store id is required to correctly identify attribute value we are working with. * - * {@inheritdoc} + * @inheritdoc * @since 101.1.0 */ protected function getAttributeRow($entity, $object, $attribute) diff --git a/app/code/Magento/Cms/Model/PageRepository.php b/app/code/Magento/Cms/Model/PageRepository.php index b0d1af87d6a9c..4366eef4cbe67 100644 --- a/app/code/Magento/Cms/Model/PageRepository.php +++ b/app/code/Magento/Cms/Model/PageRepository.php @@ -94,6 +94,7 @@ class PageRepository implements PageRepositoryInterface * @param CollectionProcessorInterface $collectionProcessor * @param UserContextInterface|null $userContext * @param AuthorizationInterface|null $authorization + * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( ResourcePage $resource, diff --git a/app/code/Magento/Cms/composer.json b/app/code/Magento/Cms/composer.json index f051271c05051..b80ab60a7ec64 100644 --- a/app/code/Magento/Cms/composer.json +++ b/app/code/Magento/Cms/composer.json @@ -15,7 +15,8 @@ "magento/module-theme": "*", "magento/module-ui": "*", "magento/module-variable": "*", - "magento/module-widget": "*" + "magento/module-widget": "*", + "magento/module-authorization": "*" }, "suggest": { "magento/module-cms-sample-data": "*" From 7cc339603ed8892a110c0bcbd499ab6828a5b1d6 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun Date: Fri, 15 Feb 2019 14:30:22 -0600 Subject: [PATCH 051/773] MC-13958: Additional Permissions for Design settings --- app/code/Magento/Catalog/Model/ResourceModel/Product.php | 1 + .../Magento/Catalog/Model/CategoryRepositoryTest.php | 2 ++ .../testsuite/Magento/Cms/Model/PageRepositoryTest.php | 4 +++- .../testsuite/Magento/User/_files/user_with_new_role.php | 1 + .../Magento/User/_files/user_with_new_role_rollback.php | 4 ---- 5 files changed, 7 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product.php b/app/code/Magento/Catalog/Model/ResourceModel/Product.php index 9256078cfdd42..0a947491ada01 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product.php @@ -751,6 +751,7 @@ private function getProductCategoryLink() /** * Extends parent method to be appropriate for product. + * * Store id is required to correctly identify attribute value we are working with. * * @inheritdoc diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/CategoryRepositoryTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/CategoryRepositoryTest.php index dbc70b89d3697..9343563353adf 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Model/CategoryRepositoryTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/CategoryRepositoryTest.php @@ -72,6 +72,8 @@ protected function tearDown() * @magentoDataFixture Magento/Catalog/_files/category.php * @magentoDataFixture Magento/User/_files/user_with_new_role.php * @magentoAppArea adminhtml + * @magentoDbIsolation enabled + * @magentoAppIsolation enabled */ public function testSaveDesign() { diff --git a/dev/tests/integration/testsuite/Magento/Cms/Model/PageRepositoryTest.php b/dev/tests/integration/testsuite/Magento/Cms/Model/PageRepositoryTest.php index 2661099d6fe59..89d99d2c62aea 100644 --- a/dev/tests/integration/testsuite/Magento/Cms/Model/PageRepositoryTest.php +++ b/dev/tests/integration/testsuite/Magento/Cms/Model/PageRepositoryTest.php @@ -76,6 +76,8 @@ protected function tearDown() * @magentoDataFixture Magento/Cms/_files/pages.php * @magentoDataFixture Magento/User/_files/user_with_new_role.php * @magentoAppArea adminhtml + * @magentoDbIsolation enabled + * @magentoAppIsolation enabled */ public function testSaveDesign() { @@ -110,4 +112,4 @@ public function testSaveDesign() $page = $this->repo->save($page); $this->assertEquals('test', $page->getCustomTheme()); } -} \ No newline at end of file +} diff --git a/dev/tests/integration/testsuite/Magento/User/_files/user_with_new_role.php b/dev/tests/integration/testsuite/Magento/User/_files/user_with_new_role.php index 18087593448f8..b592933593f19 100644 --- a/dev/tests/integration/testsuite/Magento/User/_files/user_with_new_role.php +++ b/dev/tests/integration/testsuite/Magento/User/_files/user_with_new_role.php @@ -15,6 +15,7 @@ $role = $objectManager->create(Role::class); $role->setRoleName('new_role'); $role->setRoleType('G'); +$role->setParentId(1); $role->save(); /** @var User $model */ diff --git a/dev/tests/integration/testsuite/Magento/User/_files/user_with_new_role_rollback.php b/dev/tests/integration/testsuite/Magento/User/_files/user_with_new_role_rollback.php index fa9f11b616583..3a687686555b6 100644 --- a/dev/tests/integration/testsuite/Magento/User/_files/user_with_new_role_rollback.php +++ b/dev/tests/integration/testsuite/Magento/User/_files/user_with_new_role_rollback.php @@ -15,7 +15,3 @@ $user = $objectManager->create(User::class); $user->load('admin_with_role', 'username'); $user->delete(); -/** @var Role $role */ -$role = $objectManager->create(Role::class); -$role->load('new_role', 'role_name'); -$role->delete(); \ No newline at end of file From c0fdb46166287a66468927d10f2599a44f63978a Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun Date: Fri, 15 Feb 2019 16:41:15 -0600 Subject: [PATCH 052/773] MC-13958: Additional Permissions for Design settings --- .../Magento/User/_files/user_with_new_role.php | 1 - .../User/_files/user_with_new_role_rollback.php | 17 ----------------- 2 files changed, 18 deletions(-) delete mode 100644 dev/tests/integration/testsuite/Magento/User/_files/user_with_new_role_rollback.php diff --git a/dev/tests/integration/testsuite/Magento/User/_files/user_with_new_role.php b/dev/tests/integration/testsuite/Magento/User/_files/user_with_new_role.php index b592933593f19..18087593448f8 100644 --- a/dev/tests/integration/testsuite/Magento/User/_files/user_with_new_role.php +++ b/dev/tests/integration/testsuite/Magento/User/_files/user_with_new_role.php @@ -15,7 +15,6 @@ $role = $objectManager->create(Role::class); $role->setRoleName('new_role'); $role->setRoleType('G'); -$role->setParentId(1); $role->save(); /** @var User $model */ diff --git a/dev/tests/integration/testsuite/Magento/User/_files/user_with_new_role_rollback.php b/dev/tests/integration/testsuite/Magento/User/_files/user_with_new_role_rollback.php deleted file mode 100644 index 3a687686555b6..0000000000000 --- a/dev/tests/integration/testsuite/Magento/User/_files/user_with_new_role_rollback.php +++ /dev/null @@ -1,17 +0,0 @@ -create(User::class); -$user->load('admin_with_role', 'username'); -$user->delete(); From 58a82c592fa5d1c8b9a53a4e38279840d043a630 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun Date: Fri, 15 Feb 2019 17:40:17 -0600 Subject: [PATCH 053/773] MC-5844: Coupon Requests Limiter --- .../Observer/CaptchaStringResolver.php | 18 +- .../Magento/Checkout/Block/Cart/Coupon.php | 28 ++ .../Unit/Controller/Cart/CouponPostTest.php | 398 ------------------ app/code/Magento/Checkout/composer.json | 3 +- app/code/Magento/Checkout/etc/config.xml | 16 + .../view/frontend/templates/cart/coupon.phtml | 6 + .../Magento/Quote/Model/CouponManagement.php | 12 +- .../Api/CouponManagementInterface.php | 1 + .../Exception/CodeRequestLimitException.php | 19 + .../Model/Coupon/AdminCodeLimitManager.php | 26 ++ .../Model/Coupon/CaptchaConfigProvider.php | 84 ++++ .../Model/Coupon/CodeLimitManager.php | 171 ++++++++ .../Model/Service/CouponManagementService.php | 44 +- .../Model/Spi/CodeLimitManagerInterface.php | 26 ++ .../Observer/CouponCodeValidation.php | 79 ++++ .../Service/CouponManagementServiceTest.php | 353 ---------------- app/code/Magento/SalesRule/composer.json | 4 +- .../Magento/SalesRule/etc/adminhtml/di.xml | 4 + app/code/Magento/SalesRule/etc/di.xml | 4 + app/code/Magento/SalesRule/etc/events.xml | 3 + .../Magento/SalesRule/etc/frontend/di.xml | 7 + .../frontend/layout/checkout_index_index.xml | 6 + .../frontend/web/js/action/cancel-coupon.js | 34 +- .../frontend/web/js/action/set-coupon-code.js | 65 ++- .../frontend/web/js/view/payment/captcha.js | 68 +++ .../web/template/payment/discount.html | 3 + .../Model/Coupon/CodeLimitManagerTest.php | 220 ++++++++++ .../Model/Coupon/QuoteRepositoryTest.php | 137 ++++++ lib/web/mage/storage.js | 21 +- 29 files changed, 1075 insertions(+), 785 deletions(-) delete mode 100644 app/code/Magento/Checkout/Test/Unit/Controller/Cart/CouponPostTest.php create mode 100644 app/code/Magento/SalesRule/Api/Exception/CodeRequestLimitException.php create mode 100644 app/code/Magento/SalesRule/Model/Coupon/AdminCodeLimitManager.php create mode 100644 app/code/Magento/SalesRule/Model/Coupon/CaptchaConfigProvider.php create mode 100644 app/code/Magento/SalesRule/Model/Coupon/CodeLimitManager.php create mode 100644 app/code/Magento/SalesRule/Model/Spi/CodeLimitManagerInterface.php create mode 100644 app/code/Magento/SalesRule/Observer/CouponCodeValidation.php delete mode 100644 app/code/Magento/SalesRule/Test/Unit/Model/Service/CouponManagementServiceTest.php create mode 100644 app/code/Magento/SalesRule/view/frontend/web/js/view/payment/captcha.js create mode 100644 dev/tests/integration/testsuite/Magento/SalesRule/Model/Coupon/CodeLimitManagerTest.php create mode 100644 dev/tests/integration/testsuite/Magento/SalesRule/Model/Coupon/QuoteRepositoryTest.php diff --git a/app/code/Magento/Captcha/Observer/CaptchaStringResolver.php b/app/code/Magento/Captcha/Observer/CaptchaStringResolver.php index 39579616fa928..d83abc7a6c7d1 100644 --- a/app/code/Magento/Captcha/Observer/CaptchaStringResolver.php +++ b/app/code/Magento/Captcha/Observer/CaptchaStringResolver.php @@ -5,19 +5,31 @@ */ namespace Magento\Captcha\Observer; +use Magento\Framework\App\RequestInterface; +use Magento\Framework\App\Request\Http as HttpRequest; + +/** + * Extract given captcha word. + */ class CaptchaStringResolver { /** * Get Captcha String * - * @param \Magento\Framework\App\RequestInterface $request + * @param \Magento\Framework\App\RequestInterface|HttpRequest $request * @param string $formId * @return string */ - public function resolve(\Magento\Framework\App\RequestInterface $request, $formId) + public function resolve(RequestInterface $request, $formId) { $captchaParams = $request->getPost(\Magento\Captcha\Helper\Data::INPUT_NAME_FIELD_VALUE); + if (!empty($captchaParams) && !empty($captchaParams[$formId])) { + $value = $captchaParams[$formId]; + } else { + //For Web APIs + $value = $request->getHeader('X-Captcha'); + } - return $captchaParams[$formId] ?? ''; + return $value; } } diff --git a/app/code/Magento/Checkout/Block/Cart/Coupon.php b/app/code/Magento/Checkout/Block/Cart/Coupon.php index e485eaf64c832..acf3c0922f3c9 100644 --- a/app/code/Magento/Checkout/Block/Cart/Coupon.php +++ b/app/code/Magento/Checkout/Block/Cart/Coupon.php @@ -5,7 +5,11 @@ */ namespace Magento\Checkout\Block\Cart; +use Magento\Captcha\Block\Captcha; + /** + * Block with apply-coupon form. + * * @api */ class Coupon extends \Magento\Checkout\Block\Cart\AbstractCart @@ -28,6 +32,8 @@ public function __construct( } /** + * Applied code. + * * @return string * @codeCoverageIgnore */ @@ -35,4 +41,26 @@ public function getCouponCode() { return $this->getQuote()->getCouponCode(); } + + /** + * @inheritDoc + */ + protected function _prepareLayout() + { + if (!$this->getChildBlock('captcha')) { + $this->addChild( + 'captcha', + Captcha::class, + [ + 'cacheable' => false, + 'after' => '-', + 'form_id' => 'sales_rule_coupon_request', + 'image_width' => 230, + 'image_height' => 230 + ] + ); + } + + return parent::_prepareLayout(); + } } diff --git a/app/code/Magento/Checkout/Test/Unit/Controller/Cart/CouponPostTest.php b/app/code/Magento/Checkout/Test/Unit/Controller/Cart/CouponPostTest.php deleted file mode 100644 index 1cf5006c20f73..0000000000000 --- a/app/code/Magento/Checkout/Test/Unit/Controller/Cart/CouponPostTest.php +++ /dev/null @@ -1,398 +0,0 @@ -request = $this->createMock(\Magento\Framework\App\Request\Http::class); - $this->response = $this->createMock(\Magento\Framework\App\Response\Http::class); - $this->quote = $this->createPartialMock(\Magento\Quote\Model\Quote::class, [ - 'setCouponCode', - 'getItemsCount', - 'getShippingAddress', - 'setCollectShippingRates', - 'getCouponCode', - 'collectTotals', - 'save' - ]); - $this->eventManager = $this->createMock(\Magento\Framework\Event\Manager::class); - $this->checkoutSession = $this->createMock(\Magento\Checkout\Model\Session::class); - - $this->objectManagerMock = $this->createPartialMock(\Magento\Framework\ObjectManager\ObjectManager::class, [ - 'get', 'escapeHtml' - ]); - - $this->messageManager = $this->getMockBuilder(\Magento\Framework\Message\ManagerInterface::class) - ->disableOriginalConstructor() - ->getMock(); - - $context = $this->createMock(\Magento\Framework\App\Action\Context::class); - $context->expects($this->once()) - ->method('getObjectManager') - ->willReturn($this->objectManagerMock); - $context->expects($this->once()) - ->method('getRequest') - ->willReturn($this->request); - $context->expects($this->once()) - ->method('getResponse') - ->willReturn($this->response); - $context->expects($this->once()) - ->method('getEventManager') - ->willReturn($this->eventManager); - $context->expects($this->once()) - ->method('getMessageManager') - ->willReturn($this->messageManager); - - $this->redirectFactory = - $this->createMock(\Magento\Framework\Controller\Result\RedirectFactory::class); - $this->redirect = $this->createMock(\Magento\Store\App\Response\Redirect::class); - - $this->redirect->expects($this->any()) - ->method('getRefererUrl') - ->willReturn(null); - - $context->expects($this->once()) - ->method('getRedirect') - ->willReturn($this->redirect); - - $context->expects($this->once()) - ->method('getResultRedirectFactory') - ->willReturn($this->redirectFactory); - - $this->cart = $this->getMockBuilder(\Magento\Checkout\Model\Cart::class) - ->disableOriginalConstructor() - ->getMock(); - - $this->couponFactory = $this->getMockBuilder(\Magento\SalesRule\Model\CouponFactory::class) - ->disableOriginalConstructor() - ->setMethods(['create']) - ->getMock(); - $this->quoteRepository = $this->createMock(\Magento\Quote\Api\CartRepositoryInterface::class); - - $objectManagerHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); - - $this->controller = $objectManagerHelper->getObject( - \Magento\Checkout\Controller\Cart\CouponPost::class, - [ - 'context' => $context, - 'checkoutSession' => $this->checkoutSession, - 'cart' => $this->cart, - 'couponFactory' => $this->couponFactory, - 'quoteRepository' => $this->quoteRepository - ] - ); - } - - public function testExecuteWithEmptyCoupon() - { - $this->request->expects($this->at(0)) - ->method('getParam') - ->with('remove') - ->willReturn(0); - - $this->request->expects($this->at(1)) - ->method('getParam') - ->with('coupon_code') - ->willReturn(''); - - $this->cart->expects($this->once()) - ->method('getQuote') - ->willReturn($this->quote); - - $this->controller->execute(); - } - - public function testExecuteWithGoodCouponAndItems() - { - $this->request->expects($this->at(0)) - ->method('getParam') - ->with('remove') - ->willReturn(0); - - $this->request->expects($this->at(1)) - ->method('getParam') - ->with('coupon_code') - ->willReturn('CODE'); - - $this->cart->expects($this->any()) - ->method('getQuote') - ->willReturn($this->quote); - - $this->quote->expects($this->at(0)) - ->method('getCouponCode') - ->willReturn('OLDCODE'); - - $coupon = $this->createMock(\Magento\SalesRule\Model\Coupon::class); - $this->couponFactory->expects($this->once()) - ->method('create') - ->willReturn($coupon); - $coupon->expects($this->once())->method('load')->willReturnSelf(); - $coupon->expects($this->once())->method('getId')->willReturn(1); - $this->quote->expects($this->any()) - ->method('getItemsCount') - ->willReturn(1); - - $shippingAddress = $this->createMock(\Magento\Quote\Model\Quote\Address::class); - - $this->quote->expects($this->any()) - ->method('setCollectShippingRates') - ->with(true); - - $this->quote->expects($this->any()) - ->method('getShippingAddress') - ->willReturn($shippingAddress); - - $this->quote->expects($this->any()) - ->method('collectTotals') - ->willReturn($this->quote); - - $this->quote->expects($this->any()) - ->method('setCouponCode') - ->with('CODE') - ->willReturnSelf(); - - $this->quote->expects($this->any()) - ->method('getCouponCode') - ->willReturn('CODE'); - - $this->messageManager->expects($this->once()) - ->method('addSuccessMessage') - ->willReturnSelf(); - - $this->objectManagerMock->expects($this->once()) - ->method('get') - ->willReturnSelf(); - - $this->controller->execute(); - } - - public function testExecuteWithGoodCouponAndNoItems() - { - $this->request->expects($this->at(0)) - ->method('getParam') - ->with('remove') - ->willReturn(0); - - $this->request->expects($this->at(1)) - ->method('getParam') - ->with('coupon_code') - ->willReturn('CODE'); - - $this->cart->expects($this->any()) - ->method('getQuote') - ->willReturn($this->quote); - - $this->quote->expects($this->at(0)) - ->method('getCouponCode') - ->willReturn('OLDCODE'); - - $this->quote->expects($this->any()) - ->method('getItemsCount') - ->willReturn(0); - - $coupon = $this->createMock(\Magento\Quote\Model\Quote\Address::class); - - $coupon->expects($this->once()) - ->method('getId') - ->willReturn(1); - - $this->couponFactory->expects($this->once()) - ->method('create') - ->willReturn($coupon); - - $this->checkoutSession->expects($this->once()) - ->method('getQuote') - ->willReturn($this->quote); - - $this->quote->expects($this->any()) - ->method('setCouponCode') - ->with('CODE') - ->willReturnSelf(); - - $this->messageManager->expects($this->once()) - ->method('addSuccessMessage') - ->willReturnSelf(); - - $this->objectManagerMock->expects($this->once()) - ->method('get') - ->willReturnSelf(); - - $this->controller->execute(); - } - - public function testExecuteWithBadCouponAndItems() - { - $this->request->expects($this->at(0)) - ->method('getParam') - ->with('remove') - ->willReturn(0); - - $this->request->expects($this->at(1)) - ->method('getParam') - ->with('coupon_code') - ->willReturn(''); - - $this->cart->expects($this->any()) - ->method('getQuote') - ->willReturn($this->quote); - - $this->quote->expects($this->at(0)) - ->method('getCouponCode') - ->willReturn('OLDCODE'); - - $this->quote->expects($this->any()) - ->method('getItemsCount') - ->willReturn(1); - - $shippingAddress = $this->createMock(\Magento\Quote\Model\Quote\Address::class); - - $this->quote->expects($this->any()) - ->method('setCollectShippingRates') - ->with(true); - - $this->quote->expects($this->any()) - ->method('getShippingAddress') - ->willReturn($shippingAddress); - - $this->quote->expects($this->any()) - ->method('collectTotals') - ->willReturn($this->quote); - - $this->quote->expects($this->any()) - ->method('setCouponCode') - ->with('') - ->willReturnSelf(); - - $this->messageManager->expects($this->once()) - ->method('addSuccessMessage') - ->with('You canceled the coupon code.') - ->willReturnSelf(); - - $this->controller->execute(); - } - - public function testExecuteWithBadCouponAndNoItems() - { - $this->request->expects($this->at(0)) - ->method('getParam') - ->with('remove') - ->willReturn(0); - - $this->request->expects($this->at(1)) - ->method('getParam') - ->with('coupon_code') - ->willReturn('CODE'); - - $this->cart->expects($this->any()) - ->method('getQuote') - ->willReturn($this->quote); - - $this->quote->expects($this->at(0)) - ->method('getCouponCode') - ->willReturn('OLDCODE'); - - $this->quote->expects($this->any()) - ->method('getItemsCount') - ->willReturn(0); - - $coupon = $this->createMock(\Magento\Quote\Model\Quote\Address::class); - - $coupon->expects($this->once()) - ->method('getId') - ->willReturn(0); - - $this->couponFactory->expects($this->once()) - ->method('create') - ->willReturn($coupon); - - $this->messageManager->expects($this->once()) - ->method('addErrorMessage') - ->willReturnSelf(); - - $this->objectManagerMock->expects($this->once()) - ->method('get') - ->willReturnSelf(); - - $this->controller->execute(); - } -} diff --git a/app/code/Magento/Checkout/composer.json b/app/code/Magento/Checkout/composer.json index 540565345bd9b..4051a9cc512ff 100644 --- a/app/code/Magento/Checkout/composer.json +++ b/app/code/Magento/Checkout/composer.json @@ -23,7 +23,8 @@ "magento/module-store": "*", "magento/module-tax": "*", "magento/module-theme": "*", - "magento/module-ui": "*" + "magento/module-ui": "*", + "magento/module-captcha": "*" }, "suggest": { "magento/module-cookie": "*" diff --git a/app/code/Magento/Checkout/etc/config.xml b/app/code/Magento/Checkout/etc/config.xml index e1ba4381f2230..f8c2e7ebcb503 100644 --- a/app/code/Magento/Checkout/etc/config.xml +++ b/app/code/Magento/Checkout/etc/config.xml @@ -33,5 +33,21 @@ + + + + + + + + + + + + + 1 + + + diff --git a/app/code/Magento/Checkout/view/frontend/templates/cart/coupon.phtml b/app/code/Magento/Checkout/view/frontend/templates/cart/coupon.phtml index 1d67b325e01c5..7c6a56ec8c699 100644 --- a/app/code/Magento/Checkout/view/frontend/templates/cart/coupon.phtml +++ b/app/code/Magento/Checkout/view/frontend/templates/cart/coupon.phtml @@ -6,6 +6,9 @@ // @codingStandardsIgnoreFile +/** + * @var \Magento\Framework\View\Element\AbstractBlock $block + */ ?>
@@ -41,6 +44,9 @@
+ getCouponCode())): ?> + getChildHtml('captcha') ?> + diff --git a/app/code/Magento/Quote/Model/CouponManagement.php b/app/code/Magento/Quote/Model/CouponManagement.php index 55c21c974d6dd..0c93724ae12bc 100644 --- a/app/code/Magento/Quote/Model/CouponManagement.php +++ b/app/code/Magento/Quote/Model/CouponManagement.php @@ -7,6 +7,7 @@ namespace Magento\Quote\Model; +use Magento\Framework\Exception\LocalizedException; use \Magento\Quote\Api\CouponManagementInterface; use Magento\Framework\Exception\CouldNotDeleteException; use Magento\Framework\Exception\CouldNotSaveException; @@ -36,7 +37,7 @@ public function __construct( } /** - * {@inheritdoc} + * @inheritDoc */ public function get($cartId) { @@ -46,7 +47,7 @@ public function get($cartId) } /** - * {@inheritdoc} + * @inheritDoc */ public function set($cartId, $couponCode) { @@ -63,9 +64,12 @@ public function set($cartId, $couponCode) try { $quote->setCouponCode($couponCode); $this->quoteRepository->save($quote->collectTotals()); + } catch (LocalizedException $e) { + throw new CouldNotSaveException(__('The coupon code couldn\'t be applied: ' .$e->getMessage()), $e); } catch (\Exception $e) { throw new CouldNotSaveException( - __("The coupon code couldn't be applied. Verify the coupon code and try again.") + __("The coupon code couldn't be applied. Verify the coupon code and try again."), + $e ); } if ($quote->getCouponCode() != $couponCode) { @@ -75,7 +79,7 @@ public function set($cartId, $couponCode) } /** - * {@inheritdoc} + * @inheritDoc */ public function remove($cartId) { diff --git a/app/code/Magento/SalesRule/Api/CouponManagementInterface.php b/app/code/Magento/SalesRule/Api/CouponManagementInterface.php index dc1c1de81965e..defa800bc1798 100644 --- a/app/code/Magento/SalesRule/Api/CouponManagementInterface.php +++ b/app/code/Magento/SalesRule/Api/CouponManagementInterface.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\SalesRule\Api; /** diff --git a/app/code/Magento/SalesRule/Api/Exception/CodeRequestLimitException.php b/app/code/Magento/SalesRule/Api/Exception/CodeRequestLimitException.php new file mode 100644 index 0000000000000..dfa1c9c1f6a53 --- /dev/null +++ b/app/code/Magento/SalesRule/Api/Exception/CodeRequestLimitException.php @@ -0,0 +1,19 @@ +storeManager = $storeManager; + $this->captchaData = $captchaData; + $this->customerSession = $session; + } + + /** + * @inheritDoc + */ + public function getConfig() + { + $formId = 'sales_rule_coupon_request'; + /** @var Store $store */ + $store = $this->storeManager->getStore(); + /** @var DefaultModel $captchaModel */ + $captchaModel = $this->captchaData->getCaptcha($formId); + $login = ''; + if ($this->customerSession->isLoggedIn()) { + $login = $this->customerSession->getCustomerData()->getEmail(); + } + $required = $captchaModel->isRequired($login); + if ($required) { + $captchaModel->generate(); + $imageSrc = $captchaModel->getImgSrc(); + } else { + $imageSrc = ''; + } + + return [ + 'captcha' => [ + $formId => [ + 'isCaseSensitive' => $captchaModel->isCaseSensitive(), + 'imageHeight' => $captchaModel->getHeight(), + 'imageSrc' => $imageSrc, + 'refreshUrl' => $store->getUrl('captcha/refresh', ['_secure' => $store->isCurrentlySecure()]), + 'isRequired' => $required + ] + ] + ]; + } +} diff --git a/app/code/Magento/SalesRule/Model/Coupon/CodeLimitManager.php b/app/code/Magento/SalesRule/Model/Coupon/CodeLimitManager.php new file mode 100644 index 0000000000000..030ffca363cf4 --- /dev/null +++ b/app/code/Magento/SalesRule/Model/Coupon/CodeLimitManager.php @@ -0,0 +1,171 @@ +repository = $repository; + $this->criteriaBuilder = $criteriaBuilder; + $this->captchaHelper = $captchaHelper; + $this->captchaResolver = $captchaResolver; + $this->request = $request; + $this->customerSession = $customerSession; + } + + /** + * Check whether a valid code was requested. + * + * @param string $code + * @return bool + */ + private function checkCode(string $code): bool + { + $list = $this->repository->getList($this->criteriaBuilder->addFilter('code', $code)->create()); + + return (bool)$list->getTotalCount(); + } + + /** + * Get user's identifier. + * + * @return null|string + */ + private function getLogin(): ?string + { + $login = null; + if ($this->customerSession->isLoggedIn()) { + $login = $this->customerSession->getCustomerData()->getEmail(); + } + + return $login; + } + + /** + * @inheritDoc + */ + public function checkRequest(string $code): void + { + $formId = 'sales_rule_coupon_request'; + $login = $this->getLogin(); + /** @var Captcha $captcha */ + $captcha = $this->captchaHelper->getCaptcha($formId); + //Avoid logging multiple times or recalculating $required when the same codes are checked. + if (array_key_exists($code, $this->loggedFor)) { + $required = $this->loggedFor[$code]; + } else { + $required = $captcha->isRequired($login); + if (!$this->checkCode($code)) { + $captcha->logAttempt($login); + } + $this->loggedFor[$code] = $required; + } + + $value = null; + if ($required) { + $valid = false; + $value = $this->captchaResolver->resolve($this->request, $formId); + if ($value) { + if (array_key_exists($code, $this->checked) && array_key_exists($value, $this->checked[$code])) { + $valid = $this->checked[$code][$value]; + } else { + $valid = $captcha->isCorrect($value); + $this->checked[$code][$value] = $valid; + } + } + } else { + $valid = true; + } + + if (!$valid) { + if ($value) { + $message = __('Incorrect CAPTCHA'); + } else { + $message = __('Too many coupon code requests, please try again later.'); + } + throw new CodeRequestLimitException($message); + } + } +} diff --git a/app/code/Magento/SalesRule/Model/Service/CouponManagementService.php b/app/code/Magento/SalesRule/Model/Service/CouponManagementService.php index bff74740aa241..b698190997d7e 100644 --- a/app/code/Magento/SalesRule/Model/Service/CouponManagementService.php +++ b/app/code/Magento/SalesRule/Model/Service/CouponManagementService.php @@ -5,6 +5,11 @@ */ namespace Magento\SalesRule\Model\Service; +use Magento\Framework\Api\SearchCriteriaBuilder; +use Magento\Framework\App\ObjectManager; +use Magento\Framework\Exception\NoSuchEntityException; +use Magento\SalesRule\Api\CouponRepositoryInterface; + /** * Coupon management service class * @@ -14,6 +19,7 @@ class CouponManagementService implements \Magento\SalesRule\Api\CouponManagement { /** * @var \Magento\SalesRule\Model\CouponFactory + * @deprecated */ protected $couponFactory; @@ -24,6 +30,7 @@ class CouponManagementService implements \Magento\SalesRule\Api\CouponManagement /** * @var \Magento\SalesRule\Model\ResourceModel\Coupon\CollectionFactory + * @deprecated */ protected $collectionFactory; @@ -34,6 +41,7 @@ class CouponManagementService implements \Magento\SalesRule\Api\CouponManagement /** * @var \Magento\SalesRule\Model\Spi\CouponResourceInterface + * @deprecated */ protected $resourceModel; @@ -42,6 +50,16 @@ class CouponManagementService implements \Magento\SalesRule\Api\CouponManagement */ protected $couponMassDeleteResultFactory; + /** + * @var SearchCriteriaBuilder + */ + private $criteriaBuilder; + + /** + * @var CouponRepositoryInterface + */ + private $repository; + /** * @param \Magento\SalesRule\Model\CouponFactory $couponFactory * @param \Magento\SalesRule\Model\RuleFactory $ruleFactory @@ -49,6 +67,8 @@ class CouponManagementService implements \Magento\SalesRule\Api\CouponManagement * @param \Magento\SalesRule\Model\Coupon\Massgenerator $couponGenerator * @param \Magento\SalesRule\Model\Spi\CouponResourceInterface $resourceModel * @param \Magento\SalesRule\Api\Data\CouponMassDeleteResultInterfaceFactory $couponMassDeleteResultFactory + * @param SearchCriteriaBuilder|null $criteriaBuilder + * @param CouponRepositoryInterface|null $repository */ public function __construct( \Magento\SalesRule\Model\CouponFactory $couponFactory, @@ -56,7 +76,9 @@ public function __construct( \Magento\SalesRule\Model\ResourceModel\Coupon\CollectionFactory $collectionFactory, \Magento\SalesRule\Model\Coupon\Massgenerator $couponGenerator, \Magento\SalesRule\Model\Spi\CouponResourceInterface $resourceModel, - \Magento\SalesRule\Api\Data\CouponMassDeleteResultInterfaceFactory $couponMassDeleteResultFactory + \Magento\SalesRule\Api\Data\CouponMassDeleteResultInterfaceFactory $couponMassDeleteResultFactory, + ?SearchCriteriaBuilder $criteriaBuilder = null, + ?CouponRepositoryInterface $repository = null ) { $this->couponFactory = $couponFactory; $this->ruleFactory = $ruleFactory; @@ -64,6 +86,8 @@ public function __construct( $this->couponGenerator = $couponGenerator; $this->resourceModel = $resourceModel; $this->couponMassDeleteResultFactory = $couponMassDeleteResultFactory; + $this->criteriaBuilder = $criteriaBuilder ?? ObjectManager::getInstance()->get(SearchCriteriaBuilder::class); + $this->repository = $repository ?? ObjectManager::getInstance()->get(CouponRepositoryInterface::class); } /** @@ -84,7 +108,7 @@ public function generate(\Magento\SalesRule\Api\Data\CouponGenerationSpecInterfa try { $rule = $this->ruleFactory->create()->load($couponSpec->getRuleId()); if (!$rule->getRuleId()) { - throw \Magento\Framework\Exception\NoSuchEntityException::singleField( + throw NoSuchEntityException::singleField( \Magento\SalesRule\Model\Coupon::KEY_RULE_ID, $couponSpec->getRuleId() ); @@ -156,7 +180,7 @@ public function deleteByIds(array $ids, $ignoreInvalidCoupons = true) /** * Delete coupon by coupon codes. * - * @param string[] codes + * @param string[] $codes * @param bool $ignoreInvalidCoupons * @return \Magento\SalesRule\Api\Data\CouponMassDeleteResultInterface * @throws \Magento\Framework\Exception\LocalizedException @@ -170,21 +194,18 @@ public function deleteByCodes(array $codes, $ignoreInvalidCoupons = true) * Delete coupons by filter * * @param string $fieldName - * @param string[] fieldValues + * @param string[] $fieldValues * @param bool $ignoreInvalid * @return \Magento\SalesRule\Api\Data\CouponMassDeleteResultInterface * @throws \Magento\Framework\Exception\LocalizedException */ protected function massDelete($fieldName, array $fieldValues, $ignoreInvalid) { - $couponsCollection = $this->collectionFactory->create() - ->addFieldToFilter( - $fieldName, - ['in' => $fieldValues] - ); + $this->criteriaBuilder->addFilter($fieldName, $fieldValues, 'in'); + $couponsCollection = $this->repository->getList($this->criteriaBuilder->create()); if (!$ignoreInvalid) { - if ($couponsCollection->getSize() != count($fieldValues)) { + if ($couponsCollection->getTotalCount() != count($fieldValues)) { throw new \Magento\Framework\Exception\LocalizedException(__('Some coupons are invalid.')); } } @@ -192,11 +213,10 @@ protected function massDelete($fieldName, array $fieldValues, $ignoreInvalid) $results = $this->couponMassDeleteResultFactory->create(); $failedItems = []; $fieldValues = array_flip($fieldValues); - /** @var \Magento\SalesRule\Model\Coupon $coupon */ foreach ($couponsCollection->getItems() as $coupon) { $couponValue = ($fieldName == 'code') ? $coupon->getCode() : $coupon->getCouponId(); try { - $coupon->delete(); + $this->repository->deleteById($coupon->getCouponId()); } catch (\Exception $e) { $failedItems[] = $couponValue; } diff --git a/app/code/Magento/SalesRule/Model/Spi/CodeLimitManagerInterface.php b/app/code/Magento/SalesRule/Model/Spi/CodeLimitManagerInterface.php new file mode 100644 index 0000000000000..dfee9e24a83fe --- /dev/null +++ b/app/code/Magento/SalesRule/Model/Spi/CodeLimitManagerInterface.php @@ -0,0 +1,26 @@ +codeLimitManager = $codeLimitManager; + $this->cartRepository = $cartRepository; + $this->criteriaBuilder = $criteriaBuilder; + } + + /** + * @inheritDoc + */ + public function execute(EventObserver $observer) + { + /** @var Quote $quote */ + $quote = $observer->getData('quote'); + $code = $quote->getCouponCode(); + if ($code) { + //Only validating the code if it's a new code. + /** @var Quote[] $found */ + $found = $this->cartRepository->getList( + $this->criteriaBuilder->addFilter(CartInterface::KEY_ENTITY_ID, $quote->getId())->create() + )->getItems(); + if (!$found || ((string)array_shift($found)->getCouponCode()) !== (string)$code) { + try { + $this->codeLimitManager->checkRequest($code); + } catch (CodeRequestLimitException $exception) { + $quote->setCouponCode(''); + throw $exception; + } + } + } + } +} diff --git a/app/code/Magento/SalesRule/Test/Unit/Model/Service/CouponManagementServiceTest.php b/app/code/Magento/SalesRule/Test/Unit/Model/Service/CouponManagementServiceTest.php deleted file mode 100644 index d68df19e466e2..0000000000000 --- a/app/code/Magento/SalesRule/Test/Unit/Model/Service/CouponManagementServiceTest.php +++ /dev/null @@ -1,353 +0,0 @@ -objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); - - $className = \Magento\SalesRule\Model\CouponFactory::class; - $this->couponFactory = $this->createMock($className); - - $className = \Magento\SalesRule\Model\RuleFactory::class; - $this->ruleFactory = $this->createPartialMock($className, ['create']); - - $className = \Magento\SalesRule\Model\ResourceModel\Coupon\CollectionFactory::class; - $this->collectionFactory = $this->createPartialMock($className, ['create']); - - $className = \Magento\SalesRule\Model\Coupon\Massgenerator::class; - $this->couponGenerator = $this->createMock($className); - - $className = \Magento\SalesRule\Model\Spi\CouponResourceInterface::class; - $this->resourceModel = $this->createMock($className); - - $className = \Magento\SalesRule\Api\Data\CouponMassDeleteResultInterface::class; - $this->couponMassDeleteResult = $this->createMock($className); - - $className = \Magento\SalesRule\Api\Data\CouponMassDeleteResultInterfaceFactory::class; - $this->couponMassDeleteResultFactory = $this->createPartialMock($className, ['create']); - $this->couponMassDeleteResultFactory - ->expects($this->any()) - ->method('create') - ->willReturn($this->couponMassDeleteResult); - - $this->model = $this->objectManager->getObject( - \Magento\SalesRule\Model\Service\CouponManagementService::class, - [ - 'couponFactory' => $this->couponFactory, - 'ruleFactory' => $this->ruleFactory, - 'collectionFactory' => $this->collectionFactory, - 'couponGenerator' => $this->couponGenerator, - 'resourceModel' => $this->resourceModel, - 'couponMassDeleteResultFactory' => $this->couponMassDeleteResultFactory, - ] - ); - } - - /** - * test Generate - */ - public function testGenerate() - { - $className = \Magento\SalesRule\Model\Data\CouponGenerationSpec::class; - /** - * @var \Magento\SalesRule\Api\Data\CouponGenerationSpecInterface $couponSpec - */ - $couponSpec = $this->createPartialMock( - $className, - ['getRuleId', 'getQuantity', 'getFormat', 'getLength', 'setData'] - ); - - $couponSpec->expects($this->atLeastOnce())->method('getRuleId')->willReturn(1); - $couponSpec->expects($this->once())->method('getQuantity')->willReturn(1); - $couponSpec->expects($this->once())->method('getFormat')->willReturn('num'); - $couponSpec->expects($this->once())->method('getLength')->willReturn(1); - - $this->couponGenerator->expects($this->atLeastOnce())->method('setData'); - $this->couponGenerator->expects($this->once())->method('validateData')->willReturn(true); - $this->couponGenerator->expects($this->once())->method('generatePool'); - $this->couponGenerator->expects($this->once())->method('getGeneratedCodes')->willReturn([]); - - /** - * @var \Magento\SalesRule\Model\Rule $rule - */ - $rule = $this->createPartialMock( - \Magento\SalesRule\Model\Rule::class, - ['load', 'getRuleId', 'getToDate', 'getUsesPerCoupon', 'getUsesPerCustomer', 'getUseAutoGeneration'] - ); - - $rule->expects($this->any())->method('load')->willReturnSelf(); - $rule->expects($this->any())->method('getRuleId')->willReturn(1); - $rule->expects($this->any())->method('getToDate')->willReturn('2015-07-31 00:00:00'); - $rule->expects($this->any())->method('getUsesPerCoupon')->willReturn(20); - $rule->expects($this->any())->method('getUsesPerCustomer')->willReturn(5); - $rule->expects($this->any())->method('getUseAutoGeneration')->willReturn(true); - - $this->ruleFactory->expects($this->any())->method('create')->willReturn($rule); - - $result = $this->model->generate($couponSpec); - $this->assertEquals([], $result); - } - - /** - * test Generate with validation Exception - * @throws \Magento\Framework\Exception\InputException - */ - public function testGenerateValidationException() - { - $className = \Magento\SalesRule\Api\Data\CouponGenerationSpecInterface::class; - /** - * @var \Magento\SalesRule\Api\Data\CouponGenerationSpecInterface $couponSpec - */ - $couponSpec = $this->createMock($className); - - /** - * @var \Magento\SalesRule\Model\Rule $rule - */ - $rule = $this->createPartialMock(\Magento\SalesRule\Model\Rule::class, ['load', 'getRuleId']); - - $rule->expects($this->any())->method('load')->willReturnSelf(); - $rule->expects($this->any())->method('getRuleId')->willReturn(1); - - $this->ruleFactory->expects($this->any())->method('create')->willReturn($rule); - - $this->couponGenerator->expects($this->once())->method('validateData') - ->willThrowException(new \Magento\Framework\Exception\InputException()); - $this->expectException(\Magento\Framework\Exception\InputException::class); - - $this->model->generate($couponSpec); - } - - /** - * test Generate with localized Exception - * @throws \Magento\Framework\Exception\LocalizedException - */ - public function testGenerateLocalizedException() - { - $className = \Magento\SalesRule\Api\Data\CouponGenerationSpecInterface::class; - /** - * @var \Magento\SalesRule\Api\Data\CouponGenerationSpecInterface $couponSpec - */ - $couponSpec = $this->createMock($className); - - /** - * @var \Magento\SalesRule\Model\Rule $rule - */ - $rule = $this->createPartialMock( - \Magento\SalesRule\Model\Rule::class, - ['load', 'getRuleId', 'getUseAutoGeneration'] - ); - $rule->expects($this->any())->method('load')->willReturnSelf(); - $rule->expects($this->any())->method('getRuleId')->willReturn(1); - $rule->expects($this->once())->method('getUseAutoGeneration') - ->willThrowException( - new \Magento\Framework\Exception\LocalizedException( - __('Error occurred when generating coupons: %1', '1') - ) - ); - $this->ruleFactory->expects($this->any())->method('create')->willReturn($rule); - - $this->couponGenerator->expects($this->once())->method('validateData')->willReturn(true); - - $this->expectException(\Magento\Framework\Exception\LocalizedException::class); - - $this->model->generate($couponSpec); - } - - /** - * test Generate with localized Exception - * @throws \Magento\Framework\Exception\LocalizedException - */ - public function testGenerateNoSuchEntity() - { - $className = \Magento\SalesRule\Api\Data\CouponGenerationSpecInterface::class; - /** - * @var \Magento\SalesRule\Api\Data\CouponGenerationSpecInterface $couponSpec - */ - $couponSpec = $this->createMock($className); - - /** - * @var \Magento\SalesRule\Model\Rule $rule - */ - $rule = $this->createPartialMock(\Magento\SalesRule\Model\Rule::class, ['load', 'getRuleId']); - - $rule->expects($this->any())->method('load')->willReturnSelf(); - $rule->expects($this->any())->method('getRuleId')->willReturn(false); - - $this->ruleFactory->expects($this->any())->method('create')->willReturn($rule); - - $this->couponGenerator->expects($this->once())->method('validateData')->willReturn(true); - - $this->expectException(\Magento\Framework\Exception\LocalizedException::class); - - $this->model->generate($couponSpec); - } - - /** - * test DeleteByIds with Ignore non existing - */ - public function testDeleteByIdsIgnore() - { - $ids = [1, 2, 3]; - - $className = \Magento\SalesRule\Model\Coupon::class; - /** - * @var \Magento\SalesRule\Model\Coupon $coupon - */ - $coupon = $this->createMock($className); - $coupon->expects($this->exactly(3))->method('delete'); - - $className = \Magento\SalesRule\Model\ResourceModel\Coupon\Collection::class; - /** - * @var \Magento\SalesRule\Model\ResourceModel\Coupon\Collection $couponCollection - */ - $couponCollection = $this->createMock($className); - - $couponCollection->expects($this->once())->method('addFieldToFilter')->willReturnSelf(); - $couponCollection->expects($this->once())->method('getItems')->willReturn([$coupon, $coupon, $coupon]); - $this->collectionFactory->expects($this->once())->method('create')->willReturn($couponCollection); - - $this->couponMassDeleteResult->expects($this->once())->method('setFailedItems')->willReturnSelf(); - $this->couponMassDeleteResult->expects($this->once())->method('setMissingItems')->willReturnSelf(); - - $this->model->deleteByIds($ids, true); - } - - /** - * test DeleteByIds with not Ignore non existing - * @throws \Magento\Framework\Exception\LocalizedException - */ - public function testDeleteByAnyNoIgnore() - { - $ids = [1, 2, 3]; - - $className = \Magento\SalesRule\Model\ResourceModel\Coupon\Collection::class; - /** - * @var \Magento\SalesRule\Model\ResourceModel\Coupon\Collection $couponCollection - */ - $couponCollection = $this->createMock($className); - $couponCollection->expects($this->once())->method('addFieldToFilter')->willReturnSelf(); - $this->collectionFactory->expects($this->once())->method('create')->willReturn($couponCollection); - - $this->expectException(\Magento\Framework\Exception\LocalizedException::class); - - $this->model->deleteByIds($ids, false); - } - - /** - * test DeleteByIds with not Ignore non existing - */ - public function testDeleteByAnyExceptionOnDelete() - { - $ids = [1, 2, 3]; - - /** - * @var \Magento\SalesRule\Model\Coupon $coupon - */ - $className = \Magento\SalesRule\Model\Coupon::class; - $coupon = $this->createMock($className); - $coupon->expects($this->any())->method('delete')->willThrowException(new \Exception()); - - /** - * @var \Magento\SalesRule\Model\ResourceModel\Coupon\Collection $couponCollection - */ - $className = \Magento\SalesRule\Model\ResourceModel\Coupon\Collection::class; - $couponCollection = $this->createMock($className); - $couponCollection->expects($this->once())->method('addFieldToFilter')->willReturnSelf(); - $couponCollection->expects($this->once())->method('getItems')->willReturn([$coupon, $coupon, $coupon]); - $this->collectionFactory->expects($this->once())->method('create')->willReturn($couponCollection); - - $this->couponMassDeleteResult->expects($this->once())->method('setFailedItems')->willReturnSelf(); - $this->couponMassDeleteResult->expects($this->once())->method('setMissingItems')->willReturnSelf(); - - $this->model->deleteByIds($ids, true); - } - - /** - * test DeleteByCodes - */ - public function testDeleteByCodes() - { - $ids = [1, 2, 3]; - - $className = \Magento\SalesRule\Model\Coupon::class; - /** - * @var \Magento\SalesRule\Model\Coupon $coupon - */ - $coupon = $this->createMock($className); - $coupon->expects($this->exactly(3))->method('delete'); - - $className = \Magento\SalesRule\Model\ResourceModel\Coupon\Collection::class; - /** - * @var \Magento\SalesRule\Model\ResourceModel\Coupon\Collection $couponCollection - */ - $couponCollection = $this->createMock($className); - - $couponCollection->expects($this->once())->method('addFieldToFilter')->willReturnSelf(); - $couponCollection->expects($this->once())->method('getItems')->willReturn([$coupon, $coupon, $coupon]); - $this->collectionFactory->expects($this->once())->method('create')->willReturn($couponCollection); - - $this->couponMassDeleteResult->expects($this->once())->method('setFailedItems')->willReturnSelf(); - $this->couponMassDeleteResult->expects($this->once())->method('setMissingItems')->willReturnSelf(); - - $this->model->deleteByCodes($ids, true); - } -} diff --git a/app/code/Magento/SalesRule/composer.json b/app/code/Magento/SalesRule/composer.json index a2e7dc8835ae7..3d54595a16d78 100644 --- a/app/code/Magento/SalesRule/composer.json +++ b/app/code/Magento/SalesRule/composer.json @@ -22,7 +22,9 @@ "magento/module-shipping": "*", "magento/module-store": "*", "magento/module-ui": "*", - "magento/module-widget": "*" + "magento/module-widget": "*", + "magento/module-captcha": "*", + "magento/module-checkout": "*" }, "suggest": { "magento/module-sales-rule-sample-data": "*" diff --git a/app/code/Magento/SalesRule/etc/adminhtml/di.xml b/app/code/Magento/SalesRule/etc/adminhtml/di.xml index bd0fb8ac1b14e..3b8fae469ffa9 100644 --- a/app/code/Magento/SalesRule/etc/adminhtml/di.xml +++ b/app/code/Magento/SalesRule/etc/adminhtml/di.xml @@ -18,4 +18,8 @@ + + diff --git a/app/code/Magento/SalesRule/etc/di.xml b/app/code/Magento/SalesRule/etc/di.xml index 27c9a41503b22..475d5472abcda 100644 --- a/app/code/Magento/SalesRule/etc/di.xml +++ b/app/code/Magento/SalesRule/etc/di.xml @@ -182,4 +182,8 @@ + + diff --git a/app/code/Magento/SalesRule/etc/events.xml b/app/code/Magento/SalesRule/etc/events.xml index 43babc40a2ab5..e6b84502552e0 100644 --- a/app/code/Magento/SalesRule/etc/events.xml +++ b/app/code/Magento/SalesRule/etc/events.xml @@ -27,4 +27,7 @@ + + + diff --git a/app/code/Magento/SalesRule/etc/frontend/di.xml b/app/code/Magento/SalesRule/etc/frontend/di.xml index bd0fb8ac1b14e..e38f43eac2194 100644 --- a/app/code/Magento/SalesRule/etc/frontend/di.xml +++ b/app/code/Magento/SalesRule/etc/frontend/di.xml @@ -18,4 +18,11 @@ + + + + Magento\SalesRule\Model\Coupon\CaptchaConfigProvider + + + diff --git a/app/code/Magento/SalesRule/view/frontend/layout/checkout_index_index.xml b/app/code/Magento/SalesRule/view/frontend/layout/checkout_index_index.xml index f75525576f16b..b6b87682d9653 100644 --- a/app/code/Magento/SalesRule/view/frontend/layout/checkout_index_index.xml +++ b/app/code/Magento/SalesRule/view/frontend/layout/checkout_index_index.xml @@ -30,6 +30,12 @@ Magento_SalesRule/js/view/payment/discount-messages messages + + Magento_SalesRule/js/view/payment/captcha + captcha + sales_rule_coupon_request + checkoutConfig + diff --git a/app/code/Magento/SalesRule/view/frontend/web/js/action/cancel-coupon.js b/app/code/Magento/SalesRule/view/frontend/web/js/action/cancel-coupon.js index ed77cf188413c..72eec1be0766c 100644 --- a/app/code/Magento/SalesRule/view/frontend/web/js/action/cancel-coupon.js +++ b/app/code/Magento/SalesRule/view/frontend/web/js/action/cancel-coupon.js @@ -22,7 +22,26 @@ define([ ) { 'use strict'; - return function (isApplied) { + var successCallbacks = [], + action, + callSuccessCallbacks; + + /** + * Execute callbacks when a coupon is successfully canceled. + */ + callSuccessCallbacks = function () { + successCallbacks.forEach(function (callback) { + callback(); + }); + }; + + /** + * Cancel applied coupon. + * + * @param {Boolean} isApplied + * @returns {Deferred} + */ + action = function (isApplied) { var quoteId = quote.getQuoteId(), url = urlManager.getCancelCouponUrl(quoteId), message = $t('Your coupon was successfully removed.'); @@ -42,6 +61,8 @@ define([ isApplied(false); totals.isLoading(false); fullScreenLoader.stopLoader(); + //Allowing to tap into coupon-cancel process. + callSuccessCallbacks(); }); messageContainer.addSuccessMessage({ 'message': message @@ -52,4 +73,15 @@ define([ errorProcessor.process(response, messageContainer); }); }; + + /** + * Callback for when the cancel-coupon process is finished. + * + * @param {Function} callback + */ + action.registerSuccessCallback = function (callback) { + successCallbacks.push(callback); + }; + + return action; }); diff --git a/app/code/Magento/SalesRule/view/frontend/web/js/action/set-coupon-code.js b/app/code/Magento/SalesRule/view/frontend/web/js/action/set-coupon-code.js index 4d29d95e6777c..994ccf2b395d2 100644 --- a/app/code/Magento/SalesRule/view/frontend/web/js/action/set-coupon-code.js +++ b/app/code/Magento/SalesRule/view/frontend/web/js/action/set-coupon-code.js @@ -23,17 +23,37 @@ define([ ) { 'use strict'; - return function (couponCode, isApplied) { + var dataModifiers = [], + successCallbacks = [], + failCallbacks = [], + action; + + /** + * Apply provided coupon. + * + * @param {String} couponCode + * @param {Boolean}isApplied + * @returns {Deferred} + */ + action = function (couponCode, isApplied) { var quoteId = quote.getQuoteId(), url = urlManager.getApplyCouponUrl(couponCode, quoteId), - message = $t('Your coupon was successfully applied.'); + message = $t('Your coupon was successfully applied.'), + data = {}, + headers = {}; + //Allowing to modify coupon-apply request + dataModifiers.forEach(function (modifier) { + modifier(headers, data); + }); fullScreenLoader.startLoader(); return storage.put( url, - {}, - false + data, + false, + null, + headers ).done(function (response) { var deferred; @@ -50,11 +70,48 @@ define([ messageContainer.addSuccessMessage({ 'message': message }); + //Allowing to tap into apply-coupon process. + successCallbacks.forEach(function (callback) { + callback(response); + }); } }).fail(function (response) { fullScreenLoader.stopLoader(); totals.isLoading(false); errorProcessor.process(response, messageContainer); + //Allowing to tap into apply-coupon process. + failCallbacks.forEach(function (callback) { + callback(response); + }); }); }; + + /** + * Modifying data to be sent. + * + * @param {Function} modifier + */ + action.registerDataModifier = function (modifier) { + dataModifiers.push(modifier); + }; + + /** + * When successfully added a coupon. + * + * @param {Function} callback + */ + action.registerSuccessCallback = function (callback) { + successCallbacks.push(callback); + }; + + /** + * When failed to add a coupon. + * + * @param {Function} callback + */ + action.registerFailCallback = function (callback) { + failCallbacks.push(callback); + }; + + return action; }); diff --git a/app/code/Magento/SalesRule/view/frontend/web/js/view/payment/captcha.js b/app/code/Magento/SalesRule/view/frontend/web/js/view/payment/captcha.js new file mode 100644 index 0000000000000..f289377e48294 --- /dev/null +++ b/app/code/Magento/SalesRule/view/frontend/web/js/view/payment/captcha.js @@ -0,0 +1,68 @@ +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +define([ + 'Magento_Captcha/js/view/checkout/defaultCaptcha', + 'Magento_Captcha/js/model/captchaList', + 'Magento_SalesRule/js/action/set-coupon-code', + 'Magento_SalesRule/js/action/cancel-coupon', + 'Magento_Checkout/js/model/quote', + 'ko' + ], + function (defaultCaptcha, captchaList, setCouponCodeAction, cancelCouponAction, quote, ko) { + 'use strict'; + + var totals = quote.getTotals(), + couponCode = ko.observable(null), + isApplied; + + if (totals()) { + couponCode(totals()['coupon_code']); + } + //Captcha can only be required for adding a coupon so we need to know if one was added already. + isApplied = ko.observable(couponCode() != null); + + return defaultCaptcha.extend({ + /** @inheritdoc */ + initialize: function () { + var self = this, + currentCaptcha; + + this._super(); + //Getting coupon captcha model. + currentCaptcha = captchaList.getCaptchaByFormId(this.formId); + + if (currentCaptcha != null) { + if (!isApplied()) { + //Show captcha if we don't have a coupon applied. + currentCaptcha.setIsVisible(true); + } + this.setCurrentCaptcha(currentCaptcha); + //Add captcha code to coupon-apply request. + setCouponCodeAction.registerDataModifier(function (headers) { + if (self.isRequired()) { + headers['X-Captcha'] = self.captchaValue()(); + } + }); + //Refresh captcha after failed request. + setCouponCodeAction.registerFailCallback(function () { + if (self.isRequired()) { + self.refresh(); + } + }); + //Hide captcha when a coupon has been applied. + setCouponCodeAction.registerSuccessCallback(function () { + self.setIsVisible(false); + }); + //Show captcha again if it was canceled. + cancelCouponAction.registerSuccessCallback(function () { + if (self.isRequired()) { + self.setIsVisible(true); + } + }); + } + } + }); + }); diff --git a/app/code/Magento/SalesRule/view/frontend/web/template/payment/discount.html b/app/code/Magento/SalesRule/view/frontend/web/template/payment/discount.html index d622b5ea5762d..649c1ba4bfe59 100644 --- a/app/code/Magento/SalesRule/view/frontend/web/template/payment/discount.html +++ b/app/code/Magento/SalesRule/view/frontend/web/template/payment/discount.html @@ -45,6 +45,9 @@ + + + diff --git a/dev/tests/integration/testsuite/Magento/SalesRule/Model/Coupon/CodeLimitManagerTest.php b/dev/tests/integration/testsuite/Magento/SalesRule/Model/Coupon/CodeLimitManagerTest.php new file mode 100644 index 0000000000000..7208147054ec2 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/SalesRule/Model/Coupon/CodeLimitManagerTest.php @@ -0,0 +1,220 @@ +manager = $objectManager->get(CodeLimitManager::class); + $this->customerSession = $objectManager->get(CustomerSession::class); + /** @var Http $request */ + $request = $objectManager->get(RequestInterface::class); + $request->getServer()->set('REMOTE_ADDR', '127.0.0.1'); + $objectManager->removeSharedInstance(RemoteAddress::class); + } + + /** + * @inheritDoc + */ + protected function tearDown() + { + $this->customerSession->logout(); + $this->customerSession->clearStorage(); + } + + /** + * Log in customer by ID. + * + * @param int $id + * @return void + */ + private function loginCustomer(int $id): void + { + if (!$this->customerSession->loginById($id)) { + throw new \RuntimeException('Failed to log in customer'); + } + } + + /** + * @magentoDbIsolation enabled + * @magentoAppIsolation enabled + * + * @magentoDataFixture Magento/Customer/_files/customer.php + * + * @magentoConfigFixture default_store customer/captcha/enable 1 + */ + public function testCounterDisabled() + { + $this->manager->checkRequest('fakeCode1'); + $this->loginCustomer(1); + $this->manager->checkRequest('fakeCode2'); + } + + /** + * @magentoDbIsolation enabled + * @magentoAppIsolation enabled + * + * @magentoConfigFixture default_store customer/captcha/enable 1 + * @magentoConfigFixture default_store customer/captcha/forms sales_rule_coupon_request + * @magentoConfigFixture default_store customer/captcha/failed_attempts_login 3 + * @magentoConfigFixture default_store customer/captcha/failed_attempts_ip 5 + * + * @magentoDataFixture Magento/Customer/_files/customer.php + */ + public function testUnderLimit() + { + $this->manager->checkRequest('fakeCode3'); + $this->manager->checkRequest('fakeCode4'); + + $this->loginCustomer(1); + $this->manager->checkRequest('fakeCode5'); + $this->manager->checkRequest('fakeCode6'); + } + + /** + * @magentoDbIsolation enabled + * @magentoAppIsolation enabled + * + * @magentoConfigFixture default_store customer/captcha/enable 1 + * @magentoConfigFixture default_store customer/captcha/forms sales_rule_coupon_request + * @magentoConfigFixture default_store customer/captcha/failed_attempts_login 10 + * @magentoConfigFixture default_store customer/captcha/failed_attempts_ip 2 + * + * @expectedException \Magento\SalesRule\Api\Exception\CodeRequestLimitException + */ + public function testAboveLimitNotLoggedIn() + { + try { + $this->manager->checkRequest('fakeCode7'); + $this->manager->checkRequest('fakeCode8'); + } catch (CodeRequestLimitException $exception) { + $this->fail('Attempt denied before reaching the limit'); + } + $this->manager->checkRequest('fakeCode9'); + } + + /** + * @magentoDbIsolation enabled + * @magentoAppIsolation enabled + * + * @magentoConfigFixture default_store customer/captcha/enable 1 + * @magentoConfigFixture default_store customer/captcha/forms sales_rule_coupon_request + * @magentoConfigFixture default_store customer/captcha/failed_attempts_login 2 + * @magentoConfigFixture default_store customer/captcha/failed_attempts_ip 10 + * + * @magentoDataFixture Magento/Customer/_files/customer.php + * + * @expectedException \Magento\SalesRule\Api\Exception\CodeRequestLimitException + */ + public function testAboveLimitLoggedIn() + { + try { + $this->loginCustomer(1); + $this->manager->checkRequest('fakeCode10'); + $this->manager->checkRequest('fakeCode11'); + } catch (CodeRequestLimitException $exception) { + $this->fail('Attempt denied before reaching the limit'); + } + $this->manager->checkRequest('fakeCode12'); + } + + /** + * @magentoDbIsolation enabled + * @magentoAppIsolation enabled + * + * @magentoConfigFixture default_store customer/captcha/enable 1 + * @magentoConfigFixture default_store customer/captcha/forms sales_rule_coupon_request + * @magentoConfigFixture default_store customer/captcha/failed_attempts_login 10 + * @magentoConfigFixture default_store customer/captcha/failed_attempts_ip 10 + * @magentoConfigFixture default_store customer/captcha/mode always + * + * @magentoDataFixture Magento/Customer/_files/customer.php + * + * @expectedException \Magento\SalesRule\Api\Exception\CodeRequestLimitException + */ + public function testCustomerNotAllowedWithoutCode() + { + $this->loginCustomer(1); + $this->manager->checkRequest('fakeCode13'); + } + + /** + * @magentoDbIsolation enabled + * @magentoAppIsolation enabled + * + * @magentoConfigFixture default_store customer/captcha/enable 1 + * @magentoConfigFixture default_store customer/captcha/forms sales_rule_coupon_request + * @magentoConfigFixture default_store customer/captcha/failed_attempts_login 10 + * @magentoConfigFixture default_store customer/captcha/failed_attempts_ip 10 + * @magentoConfigFixture default_store customer/captcha/mode always + * + * @expectedException \Magento\SalesRule\Api\Exception\CodeRequestLimitException + */ + public function testGuestNotAllowedWithoutCode() + { + $this->manager->checkRequest('fakeCode14'); + } + + /** + * @magentoDbIsolation enabled + * @magentoAppIsolation enabled + * + * @magentoConfigFixture default_store customer/captcha/enable 1 + * @magentoConfigFixture default_store customer/captcha/forms sales_rule_coupon_request + * @magentoConfigFixture default_store customer/captcha/failed_attempts_login 2 + * @magentoConfigFixture default_store customer/captcha/failed_attempts_ip 10 + * + * @magentoDataFixture Magento/SalesRule/_files/rules.php + * @magentoDataFixture Magento/SalesRule/_files/coupons.php + * @magentoDataFixture Magento/Customer/_files/customer.php + * + * @expectedException \Magento\SalesRule\Api\Exception\CodeRequestLimitException + */ + public function testLoggingOnlyInvalidCodes() + { + try { + $this->loginCustomer(1); + $this->manager->checkRequest('coupon_code'); + $this->manager->checkRequest('coupon_code'); + $this->manager->checkRequest('fakeCode15'); + $this->manager->checkRequest('fakeCode16'); + } catch (CodeRequestLimitException $exception) { + $this->fail('Attempts are logged for existing codes'); + } + $this->manager->checkRequest('fakeCode17'); + } +} diff --git a/dev/tests/integration/testsuite/Magento/SalesRule/Model/Coupon/QuoteRepositoryTest.php b/dev/tests/integration/testsuite/Magento/SalesRule/Model/Coupon/QuoteRepositoryTest.php new file mode 100644 index 0000000000000..0b17a3b5522b9 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/SalesRule/Model/Coupon/QuoteRepositoryTest.php @@ -0,0 +1,137 @@ +get(RequestInterface::class); + $request->getServer()->set('REMOTE_ADDR', '127.0.0.1'); + $this->request = $request; + $objectManager->removeSharedInstance(RemoteAddress::class); + $this->repo = $objectManager->get(CartRepositoryInterface::class); + $this->criteriaBuilder = $objectManager->get(SearchCriteriaBuilder::class); + $this->captchaHelper = $objectManager->get(CaptchaHelper::class); + } + + /** + * Load cart from fixture. + * + * @return CartInterface + */ + private function getCart(): CartInterface + { + $carts = $this->repo->getList( + $this->criteriaBuilder->addFilter('reserved_order_id', 'test01')->create() + )->getItems(); + if (!$carts) { + throw new \RuntimeException('Cart from fixture not found'); + } + + return array_shift($carts); + } + + /** + * Case when coupon requests limit is reached. + * + * @magentoDbIsolation enabled + * @magentoAppIsolation enabled + * + * @magentoConfigFixture default_store customer/captcha/enable 1 + * @magentoConfigFixture default_store customer/captcha/forms sales_rule_coupon_request + * @magentoConfigFixture default_store customer/captcha/failed_attempts_login 10 + * @magentoConfigFixture default_store customer/captcha/failed_attempts_ip 2 + * + * @magentoDataFixture Magento/Sales/_files/quote.php + * @magentoDataFixture Magento/SalesRule/_files/coupon_cart_fixed_discount.php + * + * @expectedException \Magento\SalesRule\Api\Exception\CodeRequestLimitException + */ + public function testAboveLimitFail() + { + //Making number of requests above limit. + try { + $this->repo->save($this->getCart()->setCouponCode('fake20')); + $this->repo->save($this->getCart()->setCouponCode('fake21')); + } catch (CodeRequestLimitException $exception) { + $this->fail('Denied access before the limit is reached.'); + } + $this->repo->save($this->getCart()->setCouponCode('fake22')); + } + + /** + * Case when coupon requests limit reached but genuine request provided. + * + * @magentoDbIsolation enabled + * @magentoAppIsolation enabled + * + * @magentoConfigFixture default_store customer/captcha/enable 1 + * @magentoConfigFixture default_store customer/captcha/forms sales_rule_coupon_request + * @magentoConfigFixture default_store customer/captcha/failed_attempts_login 10 + * @magentoConfigFixture default_store customer/captcha/failed_attempts_ip 2 + * + * @magentoDataFixture Magento/Sales/_files/quote.php + * @magentoDataFixture Magento/SalesRule/_files/coupon_cart_fixed_discount.php + */ + public function testAboveLimitSuccess() + { + $this->repo->save($this->getCart()->setCouponCode('fake24')); + $this->repo->save($this->getCart()->setCouponCode('fake25')); + + //Providing genuine proof. + /** @var DefaultModel $captcha */ + $captcha = $this->captchaHelper->getCaptcha('sales_rule_coupon_request'); + $captcha->generate(); + $this->request->setPostValue('captcha', ['sales_rule_coupon_request' => $captcha->getWord()]); + $this->repo->save($this->getCart()->setCouponCode('fake26')); + } +} diff --git a/lib/web/mage/storage.js b/lib/web/mage/storage.js index 4df3ae755ec16..1e136aa78477b 100644 --- a/lib/web/mage/storage.js +++ b/lib/web/mage/storage.js @@ -55,17 +55,22 @@ define(['jquery', 'mage/url'], function ($, urlBuilder) { * @param {String} contentType * @returns {Deferred} */ - put: function (url, data, global, contentType) { + put: function (url, data, global, contentType, headers) { + var ajaxSettings = {}; + global = global === undefined ? true : global; contentType = contentType || 'application/json'; + ajaxSettings.url = urlBuilder.build(url); + ajaxSettings.type = 'PUT'; + ajaxSettings.data = data; + ajaxSettings.global = global; + ajaxSettings.contentType = contentType; - return $.ajax({ - url: urlBuilder.build(url), - type: 'PUT', - data: data, - global: global, - contentType: contentType - }); + if (headers) { + ajaxSettings.headers = headers; + } + + return $.ajax(ajaxSettings); }, /** From eebd15faf5392ba40879c3a3813f7cb7c6fea60b Mon Sep 17 00:00:00 2001 From: Kajal Solanki Date: Wed, 20 Feb 2019 17:45:32 +0530 Subject: [PATCH 054/773] Resolved import design break issue resolved --- .../backend/web/css/source/forms/_fields.less | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/app/design/adminhtml/Magento/backend/web/css/source/forms/_fields.less b/app/design/adminhtml/Magento/backend/web/css/source/forms/_fields.less index f47ddcece1c79..e23f362863c1c 100644 --- a/app/design/adminhtml/Magento/backend/web/css/source/forms/_fields.less +++ b/app/design/adminhtml/Magento/backend/web/css/source/forms/_fields.less @@ -32,6 +32,20 @@ width: @field-size__l; } +.admin__field { + &.field { + &.field-basic_behavior.with-addon { + .admin__field-control { + position: relative; + .mage-error { + position: absolute; + width: 100%; + } + } + } + } +} + .abs-field-sizes { &.admin__field-x-small { > .admin__field-control { From bcb6f4964813f07a9c62b480c0a3720f876c8be7 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun Date: Wed, 20 Feb 2019 14:19:27 -0600 Subject: [PATCH 055/773] MC-13958: Additional Permissions for Design settings --- .../Catalog/Api/CategoryRepositoryTest.php | 131 +++++++++++++++--- .../Api/ProductRepositoryInterfaceTest.php | 95 ++++++++++++- .../Magento/Cms/Api/PageRepositoryTest.php | 119 ++++++++++++++++ .../Catalog/Model/CategoryRepositoryTest.php | 109 --------------- .../Catalog/Model/ProductRepositoryTest.php | 84 +---------- .../Magento/Cms/Model/PageRepositoryTest.php | 115 --------------- .../User/_files/user_with_new_role.php | 36 +++-- 7 files changed, 352 insertions(+), 337 deletions(-) delete mode 100644 dev/tests/integration/testsuite/Magento/Catalog/Model/CategoryRepositoryTest.php delete mode 100644 dev/tests/integration/testsuite/Magento/Cms/Model/PageRepositoryTest.php diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CategoryRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CategoryRepositoryTest.php index 332e509d550ac..463a167c59c98 100644 --- a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CategoryRepositoryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CategoryRepositoryTest.php @@ -6,10 +6,15 @@ */ namespace Magento\Catalog\Api; +use Magento\Authorization\Model\Role; +use Magento\Integration\Model\AdminTokenService; use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\WebapiAbstract; use Magento\UrlRewrite\Service\V1\Data\UrlRewrite; use Magento\CatalogUrlRewrite\Model\CategoryUrlRewriteGenerator; +use Magento\Authorization\Model\Rules; +use Magento\Authorization\Model\RulesFactory; +use Magento\Authorization\Model\RoleFactory; class CategoryRepositoryTest extends WebapiAbstract { @@ -18,6 +23,33 @@ class CategoryRepositoryTest extends WebapiAbstract private $modelId = 333; + /** + * @var RulesFactory + */ + private $rulesFactory; + + /** + * @var RoleFactory + */ + private $roleFactory; + + /** + * @var AdminTokenService + */ + private $adminTokenService; + + /** + * Sets up common objects. + * + * @inheritDoc + */ + protected function setUp() + { + $this->rulesFactory = Bootstrap::getObjectManager()->get(RulesFactory::class); + $this->roleFactory = Bootstrap::getObjectManager()->get(RoleFactory::class); + $this->adminTokenService = Bootstrap::getObjectManager()->get(AdminTokenService::class); + } + /** * @magentoApiDataFixture Magento/Catalog/_files/category_backend.php */ @@ -251,28 +283,87 @@ protected function deleteCategory($id) return $this->_webApiCall($serviceInfo, ['categoryId' => $id]); } - protected function updateCategory($id, $data) + /** + * Make category update request. + * + * @param string $id + * @param array $data + * @param string|null $token + * @return array|bool|float|int|string + */ + function updateCategory($id, $data, ?string $token = null) { - $serviceInfo = - [ - 'rest' => [ - 'resourcePath' => self::RESOURCE_PATH . '/' . $id, - 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_PUT, - ], - 'soap' => [ - 'service' => self::SERVICE_NAME, - 'serviceVersion' => 'V1', - 'operation' => self::SERVICE_NAME . 'Save', - ], - ]; + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => self::RESOURCE_PATH . '/' . $id, + 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_PUT, + ], + 'soap' => [ + 'service' => self::SERVICE_NAME, + 'serviceVersion' => 'V1', + 'operation' => self::SERVICE_NAME . 'Save', + ], + ]; + if ($token) { + $serviceInfo['rest']['token'] = $token; + $serviceInfo['soap']['token'] = $token; + } - if (TESTS_WEB_API_ADAPTER == self::ADAPTER_SOAP) { - $data['id'] = $id; - return $this->_webApiCall($serviceInfo, ['id' => $id, 'category' => $data]); - } else { - $data['id'] = $id; - return $this->_webApiCall($serviceInfo, ['id' => $id, 'category' => $data]); - return $this->_webApiCall($serviceInfo, ['category' => $data]); + $data['id'] = $id; + return $this->_webApiCall($serviceInfo, ['id' => $id, 'category' => $data]); + } + + /** + * Test authorization when saving category's design settings. + * + * @magentoApiDataFixture Magento/Catalog/_files/category.php + * @magentoApiDataFixture Magento/User/_files/user_with_new_role.php + */ + public function testSaveDesign() + { + /** @var array $category */ + $category = $this->getInfoCategory(333); + /** @var Role $role */ + $role = $this->roleFactory->create(); + $role->load('new_role', 'role_name'); + $token = $this->adminTokenService->createAdminAccessToken('admin_with_role', '12345abc'); + + //Admin doesn't have access to category's design. + /** @var Rules $rules */ + $rules = $this->rulesFactory->create(); + $rules->setRoleId($role->getId()); + $rules->setResources(['Magento_Catalog::categories']); + $rules->saveRel(); + + $category['custom_attributes'] = [['attribute_code' => 'custom_design', 'value' => 2]]; + $category = $this->updateCategory($category['id'], $category, $token); + foreach ($category['custom_attributes'] as $attribute) { + if ($attribute['attribute_code'] === 'custom_design') { + if ($attribute['value']) { + $this->fail('Design attribute changed without proper access rights'); + } + } + } + + //Admin has access to category' design. + /** @var Rules $rules */ + $rules = $this->rulesFactory->create(); + $rules->setRoleId($role->getId()); + $rules->setResources(['Magento_Catalog::categories', 'Magento_Catalog::edit_category_design']); + $rules->saveRel(); + + $changed = false; + $category['custom_attributes'] = [['attribute_code' => 'custom_design', 'value' => 2]]; + $category = $this->updateCategory($category['id'], $category, $token); + foreach ($category['custom_attributes'] as $attribute) { + if ($attribute['attribute_code'] === 'custom_design') { + if ($attribute['value'] == 2) { + $changed = true; + } + } + } + if (!$changed) { + $this->fail('Failed to change a design attribute with proper access rights'); } } } diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductRepositoryInterfaceTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductRepositoryInterfaceTest.php index 3e935e1d7ae9b..57aadcfaead5a 100644 --- a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductRepositoryInterfaceTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductRepositoryInterfaceTest.php @@ -7,6 +7,7 @@ namespace Magento\Catalog\Api; +use Magento\Authorization\Model\Role; use Magento\Catalog\Api\Data\ProductInterface; use Magento\CatalogInventory\Api\Data\StockItemInterface; use Magento\Downloadable\Model\Link; @@ -22,6 +23,10 @@ use Magento\Framework\Api\SortOrderBuilder; use Magento\Framework\Exception\NoSuchEntityException; use Magento\Framework\Webapi\Exception as HTTPExceptionCodes; +use Magento\Authorization\Model\Rules; +use Magento\Authorization\Model\RulesFactory; +use Magento\Authorization\Model\RoleFactory; +use Magento\Integration\Model\AdminTokenService; /** * @magentoAppIsolation enabled @@ -37,6 +42,21 @@ class ProductRepositoryInterfaceTest extends WebapiAbstract const KEY_SPECIAL_PRICE = 'special_price'; const KEY_CATEGORY_LINKS = 'category_links'; + /** + * @var RulesFactory + */ + private $rulesFactory; + + /** + * @var RoleFactory + */ + private $roleFactory; + + /** + * @var AdminTokenService + */ + private $adminTokenService; + /** * @var array */ @@ -55,6 +75,18 @@ class ProductRepositoryInterfaceTest extends WebapiAbstract ], ]; + /** + * Sets up common objects. + * + * @inheritDoc + */ + protected function setUp() + { + $this->rulesFactory = Bootstrap::getObjectManager()->get(RulesFactory::class); + $this->roleFactory = Bootstrap::getObjectManager()->get(RoleFactory::class); + $this->adminTokenService = Bootstrap::getObjectManager()->get(AdminTokenService::class); + } + /** * @magentoApiDataFixture Magento/Catalog/_files/products_related.php */ @@ -725,10 +757,13 @@ public function testUpdateWithExtensionAttributes(): void } /** + * Update given product. + * * @param array $product + * @param string|null $token * @return array|bool|float|int|string */ - protected function updateProduct($product) + protected function updateProduct($product, ?string $token = null) { if (isset($product['custom_attributes'])) { for ($i=0; $i self::SERVICE_NAME . 'Save', ], ]; + if ($token) { + $serviceInfo['rest']['token'] = $token; + $serviceInfo['soap']['token'] = $token; + } $requestData = ['product' => $product]; $response = $this->_webApiCall($serviceInfo, $requestData); return $response; @@ -1582,4 +1621,58 @@ private function assertMultiselectValue($productSku, $multiselectAttributeCode, } $this->assertEquals($expectedMultiselectValue, $multiselectValue); } + + /** + * Test authorization when saving a product's design settings. + * + * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/User/_files/user_with_new_role.php + */ + public function testSaveDesign() + { + /** @var array $product */ + $product = $this->getProduct('simple'); + /** @var Role $role */ + $role = $this->roleFactory->create(); + $role->load('new_role', 'role_name'); + $token = $this->adminTokenService->createAdminAccessToken('admin_with_role', '12345abc'); + + //Admin doesn't have access to product's design. + /** @var Rules $rules */ + $rules = $this->rulesFactory->create(); + $rules->setRoleId($role->getId()); + $rules->setResources(['Magento_Catalog::products']); + $rules->saveRel(); + + $product['custom_attributes'] = [['attribute_code' => 'custom_design', 'value' => 2]]; + $product = $this->updateProduct($product, $token); + foreach ($product['custom_attributes'] as $attribute) { + if ($attribute['attribute_code'] === 'custom_design') { + if ($attribute['value']) { + $this->fail('Design attribute changed without proper access rights'); + } + } + } + + //Admin has access to product's design. + /** @var Rules $rules */ + $rules = $this->rulesFactory->create(); + $rules->setRoleId($role->getId()); + $rules->setResources(['Magento_Catalog::products', 'Magento_Catalog::edit_product_design']); + $rules->saveRel(); + + $changed = false; + $product['custom_attributes'] = [['attribute_code' => 'custom_design', 'value' => 2]]; + $product = $this->updateProduct($product, $token); + foreach ($product['custom_attributes'] as $attribute) { + if ($attribute['attribute_code'] === 'custom_design') { + if ($attribute['value'] == 2) { + $changed = true; + } + } + } + if (!$changed) { + $this->fail('Failed to change a design attribute with proper access rights'); + } + } } diff --git a/dev/tests/api-functional/testsuite/Magento/Cms/Api/PageRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Cms/Api/PageRepositoryTest.php index c40d1918cca67..261ee036face1 100644 --- a/dev/tests/api-functional/testsuite/Magento/Cms/Api/PageRepositoryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Cms/Api/PageRepositoryTest.php @@ -12,6 +12,11 @@ use Magento\Framework\Api\SortOrderBuilder; use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\WebapiAbstract; +use Magento\Authorization\Model\Rules; +use Magento\Authorization\Model\RulesFactory; +use Magento\Authorization\Model\RoleFactory; +use Magento\Authorization\Model\Role; +use Magento\Integration\Model\AdminTokenService; /** * Tests for cms page service. @@ -47,6 +52,21 @@ class PageRepositoryTest extends WebapiAbstract */ protected $currentPage; + /** + * @var RulesFactory + */ + private $rulesFactory; + + /** + * @var RoleFactory + */ + private $roleFactory; + + /** + * @var AdminTokenService + */ + private $adminTokenService; + /** * Execute per test initialization. */ @@ -57,6 +77,9 @@ public function setUp() $this->dataObjectHelper = Bootstrap::getObjectManager()->create(\Magento\Framework\Api\DataObjectHelper::class); $this->dataObjectProcessor = Bootstrap::getObjectManager() ->create(\Magento\Framework\Reflection\DataObjectProcessor::class); + $this->rulesFactory = Bootstrap::getObjectManager()->get(RulesFactory::class); + $this->roleFactory = Bootstrap::getObjectManager()->get(RoleFactory::class); + $this->adminTokenService = Bootstrap::getObjectManager()->get(AdminTokenService::class); } /** @@ -379,4 +402,100 @@ private function deletePageByIdentifier($pageId) $this->_webApiCall($serviceInfo, [PageInterface::PAGE_ID => $pageId]); } + + /** + * Load page data. + * + * @param string $id + * @return array + */ + private function getPageData(string $id): array + { + /** @var SearchCriteriaBuilder $searchCriteriaBuilder */ + $searchCriteriaBuilder = Bootstrap::getObjectManager() + ->create(SearchCriteriaBuilder::class); + $searchCriteriaBuilder->addFilter(PageInterface::IDENTIFIER, $id); + $searchData = $searchCriteriaBuilder->create()->__toArray(); + $requestData = ['searchCriteria' => $searchData]; + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => self::RESOURCE_PATH . "/search" . '?' . http_build_query($requestData), + 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET, + ], + 'soap' => [ + 'service' => self::SERVICE_NAME, + 'serviceVersion' => self::SERVICE_VERSION, + 'operation' => self::SERVICE_NAME . 'GetList', + ], + ]; + + $searchResult = $this->_webApiCall($serviceInfo, $requestData); + + return $searchResult['items'][0]; + } + + /** + * Update a page. + * + * @param array $pageData + * @return array + */ + private function updatePage(array $pageData, ?string $token = null): array + { + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => self::RESOURCE_PATH, + 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST, + ], + 'soap' => [ + 'service' => self::SERVICE_NAME, + 'serviceVersion' => self::SERVICE_VERSION, + 'operation' => self::SERVICE_NAME . 'Save', + ], + ]; + if ($token) { + $serviceInfo['rest']['token'] = $token; + $serviceInfo['soap']['token'] = $token; + } + + return $this->_webApiCall($serviceInfo, ['page' => $pageData]); + } + + /** + * Test authorization when saving page's design settings. + * + * @magentoApiDataFixture Magento/Cms/_files/pages.php + * @magentoApiDataFixture Magento/User/_files/user_with_new_role.php + */ + public function testSaveDesign() + { + /** @var array $page */ + $page = $this->getPageData('page_design_blank'); + /** @var Role $role */ + $role = $this->roleFactory->create(); + $role->load('new_role', 'role_name'); + $token = $this->adminTokenService->createAdminAccessToken('admin_with_role', '12345abc'); + + //Admin doesn't have access to category's design. + /** @var Rules $rules */ + $rules = $this->rulesFactory->create(); + $rules->setRoleId($role->getId()); + $rules->setResources(['Magento_Cms::page', 'Magento_Cms::save']); + $rules->saveRel(); + + $page[PageInterface::CUSTOM_THEME] = 'test'; + $page = $this->updatePage($page, $token); + $this->assertNotEquals('test', $page[PageInterface::CUSTOM_THEME]); + + //Admin has access to category' design. + /** @var Rules $rules */ + $rules = $this->rulesFactory->create(); + $rules->setRoleId($role->getId()); + $rules->setResources(['Magento_Cms::page', 'Magento_Cms::save', 'Magento_Cms::save_design']); + $rules->saveRel(); + + $page[PageInterface::CUSTOM_THEME] = 'test'; + $page = $this->updatePage($page, $token); + $this->assertEquals('test', $page[PageInterface::CUSTOM_THEME]); + } } diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/CategoryRepositoryTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/CategoryRepositoryTest.php deleted file mode 100644 index 9343563353adf..0000000000000 --- a/dev/tests/integration/testsuite/Magento/Catalog/Model/CategoryRepositoryTest.php +++ /dev/null @@ -1,109 +0,0 @@ -repo = Bootstrap::getObjectManager()->create(CategoryRepositoryInterface::class); - $this->rulesFactory = Bootstrap::getObjectManager()->get(RulesFactory::class); - $this->roleFactory = Bootstrap::getObjectManager()->get(RoleFactory::class); - $this->auth = Bootstrap::getObjectManager()->get(Auth::class); - } - - /** - * @inheritDoc - */ - protected function tearDown() - { - parent::tearDown(); - - $this->auth->logout(); - } - - /** - * Test authorization when saving category's design settings. - * - * @magentoDataFixture Magento/Catalog/_files/category.php - * @magentoDataFixture Magento/User/_files/user_with_new_role.php - * @magentoAppArea adminhtml - * @magentoDbIsolation enabled - * @magentoAppIsolation enabled - */ - public function testSaveDesign() - { - $category = $this->repo->get(333); - /** @var Role $role */ - $role = $this->roleFactory->create(); - $role->load('new_role', 'role_name'); - $this->auth->login('admin_with_role', '12345abc'); - - //Admin doesn't have access to category's design. - /** @var Rules $rules */ - $rules = $this->rulesFactory->create(); - $rules->setRoleId($role->getId()); - $rules->setResources(['Magento_Catalog::categories']); - $rules->saveRel(); - - $category->setCustomAttribute('custom_design', 2); - $category = $this->repo->save($category); - $this->assertEmpty($category->getCustomAttribute('custom_design')); - - //Admin has access to category' design. - /** @var Rules $rules */ - $rules = $this->rulesFactory->create(); - $rules->setRoleId($role->getId()); - $rules->setResources(['Magento_Catalog::categories', 'Magento_Catalog::edit_category_design']); - $rules->saveRel(); - - $category->setCustomAttribute('custom_design', 2); - $category = $this->repo->save($category); - $this->assertNotEmpty($category->getCustomAttribute('custom_design')); - $this->assertEquals(2, $category->getCustomAttribute('custom_design')->getValue()); - } -} diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductRepositoryTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductRepositoryTest.php index 283b0713e9763..d4016b2bfa8d4 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductRepositoryTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductRepositoryTest.php @@ -7,22 +7,14 @@ namespace Magento\Catalog\Model; -use Magento\Authorization\Model\Role; -use Magento\Authorization\Model\RoleFactory; -use Magento\Backend\Model\Auth; use Magento\Catalog\Api\ProductRepositoryInterface; -use Magento\Framework\Api\SearchCriteriaBuilder; use Magento\TestFramework\Helper\Bootstrap; -use Magento\Authorization\Model\Rules; -use Magento\Authorization\Model\RulesFactory; /** * Provide tests for ProductRepository model. * * @magentoDbIsolation enabled * @magentoAppIsolation enabled - * - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class ProductRepositoryTest extends \PHPUnit\Framework\TestCase { @@ -34,45 +26,22 @@ class ProductRepositoryTest extends \PHPUnit\Framework\TestCase private $productRepository; /** - * @var SearchCriteriaBuilder + * @var \Magento\Framework\Api\SearchCriteriaBuilder */ private $searchCriteriaBuilder; - /** - * @var RulesFactory - */ - private $rulesFactory; - - /** - * @var RoleFactory - */ - private $roleFactory; - - /** - * @var Auth - */ - private $auth; - /** * Sets up common objects */ protected function setUp() { - $this->productRepository = Bootstrap::getObjectManager()->create(ProductRepositoryInterface::class); - $this->searchCriteriaBuilder = Bootstrap::getObjectManager()->get(SearchCriteriaBuilder::class); - $this->rulesFactory = Bootstrap::getObjectManager()->get(RulesFactory::class); - $this->roleFactory = Bootstrap::getObjectManager()->get(RoleFactory::class); - $this->auth = Bootstrap::getObjectManager()->get(Auth::class); - } - - /** - * @inheritDoc - */ - protected function tearDown() - { - parent::tearDown(); + $this->productRepository = \Magento\Framework\App\ObjectManager::getInstance()->create( + \Magento\Catalog\Api\ProductRepositoryInterface::class + ); - $this->auth->logout(); + $this->searchCriteriaBuilder = \Magento\Framework\App\ObjectManager::getInstance()->create( + \Magento\Framework\Api\SearchCriteriaBuilder::class + ); } /** @@ -169,43 +138,4 @@ public function testSaveProductWithGalleryImage(): void $this->assertStringStartsWith('/m/a/magento_image', $product->getData('image')); $this->assertStringStartsWith('/m/a/magento_image', $product->getData('small_image')); } - - /** - * Test authorization when saving product's design settings. - * - * @magentoDataFixture Magento/Catalog/_files/product_simple.php - * @magentoDataFixture Magento/User/_files/user_with_new_role.php - * @magentoAppArea adminhtml - */ - public function testSaveDesign() - { - $product = $this->productRepository->get('simple'); - /** @var Role $role */ - $role = $this->roleFactory->create(); - $role->load('new_role', 'role_name'); - $this->auth->login('admin_with_role', '12345abc'); - - //Admin doesn't have access to product's design. - /** @var Rules $rules */ - $rules = $this->rulesFactory->create(); - $rules->setRoleId($role->getId()); - $rules->setResources(['Magento_Catalog::products']); - $rules->saveRel(); - - $product->setCustomAttribute('custom_design', 2); - $product = $this->productRepository->save($product); - $this->assertEmpty($product->getCustomAttribute('custom_design')); - - //Admin has access to products' design. - /** @var Rules $rules */ - $rules = $this->rulesFactory->create(); - $rules->setRoleId($role->getId()); - $rules->setResources(['Magento_Catalog::products', 'Magento_Catalog::edit_product_design']); - $rules->saveRel(); - - $product->setCustomAttribute('custom_design', 2); - $product = $this->productRepository->save($product); - $this->assertNotEmpty($product->getCustomAttribute('custom_design')); - $this->assertEquals(2, $product->getCustomAttribute('custom_design')->getValue()); - } } diff --git a/dev/tests/integration/testsuite/Magento/Cms/Model/PageRepositoryTest.php b/dev/tests/integration/testsuite/Magento/Cms/Model/PageRepositoryTest.php deleted file mode 100644 index 89d99d2c62aea..0000000000000 --- a/dev/tests/integration/testsuite/Magento/Cms/Model/PageRepositoryTest.php +++ /dev/null @@ -1,115 +0,0 @@ -repo = Bootstrap::getObjectManager()->create(PageRepositoryInterface::class); - $this->rulesFactory = Bootstrap::getObjectManager()->get(RulesFactory::class); - $this->roleFactory = Bootstrap::getObjectManager()->get(RoleFactory::class); - $this->auth = Bootstrap::getObjectManager()->get(Auth::class); - $this->criteriaBuilder = Bootstrap::getObjectManager()->get(SearchCriteriaBuilder::class); - } - - /** - * @inheritDoc - */ - protected function tearDown() - { - parent::tearDown(); - - $this->auth->logout(); - } - - /** - * Test authorization when saving page's design settings. - * - * @magentoDataFixture Magento/Cms/_files/pages.php - * @magentoDataFixture Magento/User/_files/user_with_new_role.php - * @magentoAppArea adminhtml - * @magentoDbIsolation enabled - * @magentoAppIsolation enabled - */ - public function testSaveDesign() - { - $pages = $this->repo->getList( - $this->criteriaBuilder->addFilter('identifier', 'page_design_blank')->create() - )->getItems(); - $page = array_pop($pages); - /** @var Role $role */ - $role = $this->roleFactory->create(); - $role->load('new_role', 'role_name'); - $this->auth->login('admin_with_role', '12345abc'); - - //Admin doesn't have access to page's design. - /** @var Rules $rules */ - $rules = $this->rulesFactory->create(); - $rules->setRoleId($role->getId()); - $rules->setResources(['Magento_Cms::save']); - $rules->saveRel(); - - $page->setCustomTheme('test'); - $page = $this->repo->save($page); - $this->assertNotEquals('test', $page->getCustomTheme()); - - //Admin has access to page' design. - /** @var Rules $rules */ - $rules = $this->rulesFactory->create(); - $rules->setRoleId($role->getId()); - $rules->setResources(['Magento_Cms::save', 'Magento_Cms::save_design']); - $rules->saveRel(); - - $page->setCustomTheme('test'); - $page = $this->repo->save($page); - $this->assertEquals('test', $page->getCustomTheme()); - } -} diff --git a/dev/tests/integration/testsuite/Magento/User/_files/user_with_new_role.php b/dev/tests/integration/testsuite/Magento/User/_files/user_with_new_role.php index 18087593448f8..142a13b6027d0 100644 --- a/dev/tests/integration/testsuite/Magento/User/_files/user_with_new_role.php +++ b/dev/tests/integration/testsuite/Magento/User/_files/user_with_new_role.php @@ -13,21 +13,27 @@ $objectManager = Bootstrap::getObjectManager(); /** @var Role $role */ $role = $objectManager->create(Role::class); -$role->setRoleName('new_role'); -$role->setRoleType('G'); -$role->save(); +$role->load('new_role', 'role_name'); +if (!$role->getId()) { + $role->setRoleName('new_role'); + $role->setRoleType('G'); + $role->save(); +} /** @var User $model */ $model = $objectManager->create(User::class); -$model->setFirstname("John") - ->setLastname("Doe") - ->setUsername('admin_with_role') - ->setPassword('12345abc') - ->setEmail('admin_with_role@example.com') - ->setRoleType('G') - ->setResourceId('Magento_Backend::all') - ->setPrivileges("") - ->setAssertId(0) - ->setRoleId($role->getId()) - ->setPermission('allow'); -$model->save(); +$model->load('admin_with_role', 'username'); +if (!$model->getId()) { + $model->setFirstname("John") + ->setLastname("Doe") + ->setUsername('admin_with_role') + ->setPassword('12345abc') + ->setEmail('admin_with_role@example.com') + ->setRoleType('G') + ->setResourceId('Magento_Backend::all') + ->setPrivileges("") + ->setAssertId(0) + ->setRoleId($role->getId()) + ->setPermission('allow'); + $model->save(); +} From 750749c954061791880e7a391e042585f9e7f1d1 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun Date: Wed, 20 Feb 2019 18:28:38 -0600 Subject: [PATCH 056/773] MC-13958: Additional Permissions for Design settings --- .../Catalog/Api/CategoryRepositoryTest.php | 131 +++--------------- .../Api/ProductRepositoryInterfaceTest.php | 95 +------------ .../Magento/Cms/Api/PageRepositoryTest.php | 119 ---------------- .../Catalog/Model/CategoryRepositoryTest.php | 109 +++++++++++++++ .../Catalog/Model/ProductRepositoryTest.php | 84 ++++++++++- .../Magento/Cms/Model/PageRepositoryTest.php | 115 +++++++++++++++ .../User/_files/user_with_new_role.php | 36 ++--- 7 files changed, 337 insertions(+), 352 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/Model/CategoryRepositoryTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Cms/Model/PageRepositoryTest.php diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CategoryRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CategoryRepositoryTest.php index 463a167c59c98..332e509d550ac 100644 --- a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CategoryRepositoryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CategoryRepositoryTest.php @@ -6,15 +6,10 @@ */ namespace Magento\Catalog\Api; -use Magento\Authorization\Model\Role; -use Magento\Integration\Model\AdminTokenService; use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\WebapiAbstract; use Magento\UrlRewrite\Service\V1\Data\UrlRewrite; use Magento\CatalogUrlRewrite\Model\CategoryUrlRewriteGenerator; -use Magento\Authorization\Model\Rules; -use Magento\Authorization\Model\RulesFactory; -use Magento\Authorization\Model\RoleFactory; class CategoryRepositoryTest extends WebapiAbstract { @@ -23,33 +18,6 @@ class CategoryRepositoryTest extends WebapiAbstract private $modelId = 333; - /** - * @var RulesFactory - */ - private $rulesFactory; - - /** - * @var RoleFactory - */ - private $roleFactory; - - /** - * @var AdminTokenService - */ - private $adminTokenService; - - /** - * Sets up common objects. - * - * @inheritDoc - */ - protected function setUp() - { - $this->rulesFactory = Bootstrap::getObjectManager()->get(RulesFactory::class); - $this->roleFactory = Bootstrap::getObjectManager()->get(RoleFactory::class); - $this->adminTokenService = Bootstrap::getObjectManager()->get(AdminTokenService::class); - } - /** * @magentoApiDataFixture Magento/Catalog/_files/category_backend.php */ @@ -283,87 +251,28 @@ protected function deleteCategory($id) return $this->_webApiCall($serviceInfo, ['categoryId' => $id]); } - /** - * Make category update request. - * - * @param string $id - * @param array $data - * @param string|null $token - * @return array|bool|float|int|string - */ - function updateCategory($id, $data, ?string $token = null) - { - $serviceInfo = [ - 'rest' => [ - 'resourcePath' => self::RESOURCE_PATH . '/' . $id, - 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_PUT, - ], - 'soap' => [ - 'service' => self::SERVICE_NAME, - 'serviceVersion' => 'V1', - 'operation' => self::SERVICE_NAME . 'Save', - ], - ]; - if ($token) { - $serviceInfo['rest']['token'] = $token; - $serviceInfo['soap']['token'] = $token; - } - - $data['id'] = $id; - return $this->_webApiCall($serviceInfo, ['id' => $id, 'category' => $data]); - } - - /** - * Test authorization when saving category's design settings. - * - * @magentoApiDataFixture Magento/Catalog/_files/category.php - * @magentoApiDataFixture Magento/User/_files/user_with_new_role.php - */ - public function testSaveDesign() + protected function updateCategory($id, $data) { - /** @var array $category */ - $category = $this->getInfoCategory(333); - /** @var Role $role */ - $role = $this->roleFactory->create(); - $role->load('new_role', 'role_name'); - $token = $this->adminTokenService->createAdminAccessToken('admin_with_role', '12345abc'); - - //Admin doesn't have access to category's design. - /** @var Rules $rules */ - $rules = $this->rulesFactory->create(); - $rules->setRoleId($role->getId()); - $rules->setResources(['Magento_Catalog::categories']); - $rules->saveRel(); - - $category['custom_attributes'] = [['attribute_code' => 'custom_design', 'value' => 2]]; - $category = $this->updateCategory($category['id'], $category, $token); - foreach ($category['custom_attributes'] as $attribute) { - if ($attribute['attribute_code'] === 'custom_design') { - if ($attribute['value']) { - $this->fail('Design attribute changed without proper access rights'); - } - } - } - - //Admin has access to category' design. - /** @var Rules $rules */ - $rules = $this->rulesFactory->create(); - $rules->setRoleId($role->getId()); - $rules->setResources(['Magento_Catalog::categories', 'Magento_Catalog::edit_category_design']); - $rules->saveRel(); + $serviceInfo = + [ + 'rest' => [ + 'resourcePath' => self::RESOURCE_PATH . '/' . $id, + 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_PUT, + ], + 'soap' => [ + 'service' => self::SERVICE_NAME, + 'serviceVersion' => 'V1', + 'operation' => self::SERVICE_NAME . 'Save', + ], + ]; - $changed = false; - $category['custom_attributes'] = [['attribute_code' => 'custom_design', 'value' => 2]]; - $category = $this->updateCategory($category['id'], $category, $token); - foreach ($category['custom_attributes'] as $attribute) { - if ($attribute['attribute_code'] === 'custom_design') { - if ($attribute['value'] == 2) { - $changed = true; - } - } - } - if (!$changed) { - $this->fail('Failed to change a design attribute with proper access rights'); + if (TESTS_WEB_API_ADAPTER == self::ADAPTER_SOAP) { + $data['id'] = $id; + return $this->_webApiCall($serviceInfo, ['id' => $id, 'category' => $data]); + } else { + $data['id'] = $id; + return $this->_webApiCall($serviceInfo, ['id' => $id, 'category' => $data]); + return $this->_webApiCall($serviceInfo, ['category' => $data]); } } } diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductRepositoryInterfaceTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductRepositoryInterfaceTest.php index 57aadcfaead5a..3e935e1d7ae9b 100644 --- a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductRepositoryInterfaceTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductRepositoryInterfaceTest.php @@ -7,7 +7,6 @@ namespace Magento\Catalog\Api; -use Magento\Authorization\Model\Role; use Magento\Catalog\Api\Data\ProductInterface; use Magento\CatalogInventory\Api\Data\StockItemInterface; use Magento\Downloadable\Model\Link; @@ -23,10 +22,6 @@ use Magento\Framework\Api\SortOrderBuilder; use Magento\Framework\Exception\NoSuchEntityException; use Magento\Framework\Webapi\Exception as HTTPExceptionCodes; -use Magento\Authorization\Model\Rules; -use Magento\Authorization\Model\RulesFactory; -use Magento\Authorization\Model\RoleFactory; -use Magento\Integration\Model\AdminTokenService; /** * @magentoAppIsolation enabled @@ -42,21 +37,6 @@ class ProductRepositoryInterfaceTest extends WebapiAbstract const KEY_SPECIAL_PRICE = 'special_price'; const KEY_CATEGORY_LINKS = 'category_links'; - /** - * @var RulesFactory - */ - private $rulesFactory; - - /** - * @var RoleFactory - */ - private $roleFactory; - - /** - * @var AdminTokenService - */ - private $adminTokenService; - /** * @var array */ @@ -75,18 +55,6 @@ class ProductRepositoryInterfaceTest extends WebapiAbstract ], ]; - /** - * Sets up common objects. - * - * @inheritDoc - */ - protected function setUp() - { - $this->rulesFactory = Bootstrap::getObjectManager()->get(RulesFactory::class); - $this->roleFactory = Bootstrap::getObjectManager()->get(RoleFactory::class); - $this->adminTokenService = Bootstrap::getObjectManager()->get(AdminTokenService::class); - } - /** * @magentoApiDataFixture Magento/Catalog/_files/products_related.php */ @@ -757,13 +725,10 @@ public function testUpdateWithExtensionAttributes(): void } /** - * Update given product. - * * @param array $product - * @param string|null $token * @return array|bool|float|int|string */ - protected function updateProduct($product, ?string $token = null) + protected function updateProduct($product) { if (isset($product['custom_attributes'])) { for ($i=0; $i self::SERVICE_NAME . 'Save', ], ]; - if ($token) { - $serviceInfo['rest']['token'] = $token; - $serviceInfo['soap']['token'] = $token; - } $requestData = ['product' => $product]; $response = $this->_webApiCall($serviceInfo, $requestData); return $response; @@ -1621,58 +1582,4 @@ private function assertMultiselectValue($productSku, $multiselectAttributeCode, } $this->assertEquals($expectedMultiselectValue, $multiselectValue); } - - /** - * Test authorization when saving a product's design settings. - * - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php - * @magentoApiDataFixture Magento/User/_files/user_with_new_role.php - */ - public function testSaveDesign() - { - /** @var array $product */ - $product = $this->getProduct('simple'); - /** @var Role $role */ - $role = $this->roleFactory->create(); - $role->load('new_role', 'role_name'); - $token = $this->adminTokenService->createAdminAccessToken('admin_with_role', '12345abc'); - - //Admin doesn't have access to product's design. - /** @var Rules $rules */ - $rules = $this->rulesFactory->create(); - $rules->setRoleId($role->getId()); - $rules->setResources(['Magento_Catalog::products']); - $rules->saveRel(); - - $product['custom_attributes'] = [['attribute_code' => 'custom_design', 'value' => 2]]; - $product = $this->updateProduct($product, $token); - foreach ($product['custom_attributes'] as $attribute) { - if ($attribute['attribute_code'] === 'custom_design') { - if ($attribute['value']) { - $this->fail('Design attribute changed without proper access rights'); - } - } - } - - //Admin has access to product's design. - /** @var Rules $rules */ - $rules = $this->rulesFactory->create(); - $rules->setRoleId($role->getId()); - $rules->setResources(['Magento_Catalog::products', 'Magento_Catalog::edit_product_design']); - $rules->saveRel(); - - $changed = false; - $product['custom_attributes'] = [['attribute_code' => 'custom_design', 'value' => 2]]; - $product = $this->updateProduct($product, $token); - foreach ($product['custom_attributes'] as $attribute) { - if ($attribute['attribute_code'] === 'custom_design') { - if ($attribute['value'] == 2) { - $changed = true; - } - } - } - if (!$changed) { - $this->fail('Failed to change a design attribute with proper access rights'); - } - } } diff --git a/dev/tests/api-functional/testsuite/Magento/Cms/Api/PageRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Cms/Api/PageRepositoryTest.php index 261ee036face1..c40d1918cca67 100644 --- a/dev/tests/api-functional/testsuite/Magento/Cms/Api/PageRepositoryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Cms/Api/PageRepositoryTest.php @@ -12,11 +12,6 @@ use Magento\Framework\Api\SortOrderBuilder; use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\WebapiAbstract; -use Magento\Authorization\Model\Rules; -use Magento\Authorization\Model\RulesFactory; -use Magento\Authorization\Model\RoleFactory; -use Magento\Authorization\Model\Role; -use Magento\Integration\Model\AdminTokenService; /** * Tests for cms page service. @@ -52,21 +47,6 @@ class PageRepositoryTest extends WebapiAbstract */ protected $currentPage; - /** - * @var RulesFactory - */ - private $rulesFactory; - - /** - * @var RoleFactory - */ - private $roleFactory; - - /** - * @var AdminTokenService - */ - private $adminTokenService; - /** * Execute per test initialization. */ @@ -77,9 +57,6 @@ public function setUp() $this->dataObjectHelper = Bootstrap::getObjectManager()->create(\Magento\Framework\Api\DataObjectHelper::class); $this->dataObjectProcessor = Bootstrap::getObjectManager() ->create(\Magento\Framework\Reflection\DataObjectProcessor::class); - $this->rulesFactory = Bootstrap::getObjectManager()->get(RulesFactory::class); - $this->roleFactory = Bootstrap::getObjectManager()->get(RoleFactory::class); - $this->adminTokenService = Bootstrap::getObjectManager()->get(AdminTokenService::class); } /** @@ -402,100 +379,4 @@ private function deletePageByIdentifier($pageId) $this->_webApiCall($serviceInfo, [PageInterface::PAGE_ID => $pageId]); } - - /** - * Load page data. - * - * @param string $id - * @return array - */ - private function getPageData(string $id): array - { - /** @var SearchCriteriaBuilder $searchCriteriaBuilder */ - $searchCriteriaBuilder = Bootstrap::getObjectManager() - ->create(SearchCriteriaBuilder::class); - $searchCriteriaBuilder->addFilter(PageInterface::IDENTIFIER, $id); - $searchData = $searchCriteriaBuilder->create()->__toArray(); - $requestData = ['searchCriteria' => $searchData]; - $serviceInfo = [ - 'rest' => [ - 'resourcePath' => self::RESOURCE_PATH . "/search" . '?' . http_build_query($requestData), - 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET, - ], - 'soap' => [ - 'service' => self::SERVICE_NAME, - 'serviceVersion' => self::SERVICE_VERSION, - 'operation' => self::SERVICE_NAME . 'GetList', - ], - ]; - - $searchResult = $this->_webApiCall($serviceInfo, $requestData); - - return $searchResult['items'][0]; - } - - /** - * Update a page. - * - * @param array $pageData - * @return array - */ - private function updatePage(array $pageData, ?string $token = null): array - { - $serviceInfo = [ - 'rest' => [ - 'resourcePath' => self::RESOURCE_PATH, - 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST, - ], - 'soap' => [ - 'service' => self::SERVICE_NAME, - 'serviceVersion' => self::SERVICE_VERSION, - 'operation' => self::SERVICE_NAME . 'Save', - ], - ]; - if ($token) { - $serviceInfo['rest']['token'] = $token; - $serviceInfo['soap']['token'] = $token; - } - - return $this->_webApiCall($serviceInfo, ['page' => $pageData]); - } - - /** - * Test authorization when saving page's design settings. - * - * @magentoApiDataFixture Magento/Cms/_files/pages.php - * @magentoApiDataFixture Magento/User/_files/user_with_new_role.php - */ - public function testSaveDesign() - { - /** @var array $page */ - $page = $this->getPageData('page_design_blank'); - /** @var Role $role */ - $role = $this->roleFactory->create(); - $role->load('new_role', 'role_name'); - $token = $this->adminTokenService->createAdminAccessToken('admin_with_role', '12345abc'); - - //Admin doesn't have access to category's design. - /** @var Rules $rules */ - $rules = $this->rulesFactory->create(); - $rules->setRoleId($role->getId()); - $rules->setResources(['Magento_Cms::page', 'Magento_Cms::save']); - $rules->saveRel(); - - $page[PageInterface::CUSTOM_THEME] = 'test'; - $page = $this->updatePage($page, $token); - $this->assertNotEquals('test', $page[PageInterface::CUSTOM_THEME]); - - //Admin has access to category' design. - /** @var Rules $rules */ - $rules = $this->rulesFactory->create(); - $rules->setRoleId($role->getId()); - $rules->setResources(['Magento_Cms::page', 'Magento_Cms::save', 'Magento_Cms::save_design']); - $rules->saveRel(); - - $page[PageInterface::CUSTOM_THEME] = 'test'; - $page = $this->updatePage($page, $token); - $this->assertEquals('test', $page[PageInterface::CUSTOM_THEME]); - } } diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/CategoryRepositoryTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/CategoryRepositoryTest.php new file mode 100644 index 0000000000000..9343563353adf --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/CategoryRepositoryTest.php @@ -0,0 +1,109 @@ +repo = Bootstrap::getObjectManager()->create(CategoryRepositoryInterface::class); + $this->rulesFactory = Bootstrap::getObjectManager()->get(RulesFactory::class); + $this->roleFactory = Bootstrap::getObjectManager()->get(RoleFactory::class); + $this->auth = Bootstrap::getObjectManager()->get(Auth::class); + } + + /** + * @inheritDoc + */ + protected function tearDown() + { + parent::tearDown(); + + $this->auth->logout(); + } + + /** + * Test authorization when saving category's design settings. + * + * @magentoDataFixture Magento/Catalog/_files/category.php + * @magentoDataFixture Magento/User/_files/user_with_new_role.php + * @magentoAppArea adminhtml + * @magentoDbIsolation enabled + * @magentoAppIsolation enabled + */ + public function testSaveDesign() + { + $category = $this->repo->get(333); + /** @var Role $role */ + $role = $this->roleFactory->create(); + $role->load('new_role', 'role_name'); + $this->auth->login('admin_with_role', '12345abc'); + + //Admin doesn't have access to category's design. + /** @var Rules $rules */ + $rules = $this->rulesFactory->create(); + $rules->setRoleId($role->getId()); + $rules->setResources(['Magento_Catalog::categories']); + $rules->saveRel(); + + $category->setCustomAttribute('custom_design', 2); + $category = $this->repo->save($category); + $this->assertEmpty($category->getCustomAttribute('custom_design')); + + //Admin has access to category' design. + /** @var Rules $rules */ + $rules = $this->rulesFactory->create(); + $rules->setRoleId($role->getId()); + $rules->setResources(['Magento_Catalog::categories', 'Magento_Catalog::edit_category_design']); + $rules->saveRel(); + + $category->setCustomAttribute('custom_design', 2); + $category = $this->repo->save($category); + $this->assertNotEmpty($category->getCustomAttribute('custom_design')); + $this->assertEquals(2, $category->getCustomAttribute('custom_design')->getValue()); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductRepositoryTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductRepositoryTest.php index d4016b2bfa8d4..283b0713e9763 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductRepositoryTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductRepositoryTest.php @@ -7,14 +7,22 @@ namespace Magento\Catalog\Model; +use Magento\Authorization\Model\Role; +use Magento\Authorization\Model\RoleFactory; +use Magento\Backend\Model\Auth; use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Framework\Api\SearchCriteriaBuilder; use Magento\TestFramework\Helper\Bootstrap; +use Magento\Authorization\Model\Rules; +use Magento\Authorization\Model\RulesFactory; /** * Provide tests for ProductRepository model. * * @magentoDbIsolation enabled * @magentoAppIsolation enabled + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class ProductRepositoryTest extends \PHPUnit\Framework\TestCase { @@ -26,22 +34,45 @@ class ProductRepositoryTest extends \PHPUnit\Framework\TestCase private $productRepository; /** - * @var \Magento\Framework\Api\SearchCriteriaBuilder + * @var SearchCriteriaBuilder */ private $searchCriteriaBuilder; + /** + * @var RulesFactory + */ + private $rulesFactory; + + /** + * @var RoleFactory + */ + private $roleFactory; + + /** + * @var Auth + */ + private $auth; + /** * Sets up common objects */ protected function setUp() { - $this->productRepository = \Magento\Framework\App\ObjectManager::getInstance()->create( - \Magento\Catalog\Api\ProductRepositoryInterface::class - ); + $this->productRepository = Bootstrap::getObjectManager()->create(ProductRepositoryInterface::class); + $this->searchCriteriaBuilder = Bootstrap::getObjectManager()->get(SearchCriteriaBuilder::class); + $this->rulesFactory = Bootstrap::getObjectManager()->get(RulesFactory::class); + $this->roleFactory = Bootstrap::getObjectManager()->get(RoleFactory::class); + $this->auth = Bootstrap::getObjectManager()->get(Auth::class); + } + + /** + * @inheritDoc + */ + protected function tearDown() + { + parent::tearDown(); - $this->searchCriteriaBuilder = \Magento\Framework\App\ObjectManager::getInstance()->create( - \Magento\Framework\Api\SearchCriteriaBuilder::class - ); + $this->auth->logout(); } /** @@ -138,4 +169,43 @@ public function testSaveProductWithGalleryImage(): void $this->assertStringStartsWith('/m/a/magento_image', $product->getData('image')); $this->assertStringStartsWith('/m/a/magento_image', $product->getData('small_image')); } + + /** + * Test authorization when saving product's design settings. + * + * @magentoDataFixture Magento/Catalog/_files/product_simple.php + * @magentoDataFixture Magento/User/_files/user_with_new_role.php + * @magentoAppArea adminhtml + */ + public function testSaveDesign() + { + $product = $this->productRepository->get('simple'); + /** @var Role $role */ + $role = $this->roleFactory->create(); + $role->load('new_role', 'role_name'); + $this->auth->login('admin_with_role', '12345abc'); + + //Admin doesn't have access to product's design. + /** @var Rules $rules */ + $rules = $this->rulesFactory->create(); + $rules->setRoleId($role->getId()); + $rules->setResources(['Magento_Catalog::products']); + $rules->saveRel(); + + $product->setCustomAttribute('custom_design', 2); + $product = $this->productRepository->save($product); + $this->assertEmpty($product->getCustomAttribute('custom_design')); + + //Admin has access to products' design. + /** @var Rules $rules */ + $rules = $this->rulesFactory->create(); + $rules->setRoleId($role->getId()); + $rules->setResources(['Magento_Catalog::products', 'Magento_Catalog::edit_product_design']); + $rules->saveRel(); + + $product->setCustomAttribute('custom_design', 2); + $product = $this->productRepository->save($product); + $this->assertNotEmpty($product->getCustomAttribute('custom_design')); + $this->assertEquals(2, $product->getCustomAttribute('custom_design')->getValue()); + } } diff --git a/dev/tests/integration/testsuite/Magento/Cms/Model/PageRepositoryTest.php b/dev/tests/integration/testsuite/Magento/Cms/Model/PageRepositoryTest.php new file mode 100644 index 0000000000000..89d99d2c62aea --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Cms/Model/PageRepositoryTest.php @@ -0,0 +1,115 @@ +repo = Bootstrap::getObjectManager()->create(PageRepositoryInterface::class); + $this->rulesFactory = Bootstrap::getObjectManager()->get(RulesFactory::class); + $this->roleFactory = Bootstrap::getObjectManager()->get(RoleFactory::class); + $this->auth = Bootstrap::getObjectManager()->get(Auth::class); + $this->criteriaBuilder = Bootstrap::getObjectManager()->get(SearchCriteriaBuilder::class); + } + + /** + * @inheritDoc + */ + protected function tearDown() + { + parent::tearDown(); + + $this->auth->logout(); + } + + /** + * Test authorization when saving page's design settings. + * + * @magentoDataFixture Magento/Cms/_files/pages.php + * @magentoDataFixture Magento/User/_files/user_with_new_role.php + * @magentoAppArea adminhtml + * @magentoDbIsolation enabled + * @magentoAppIsolation enabled + */ + public function testSaveDesign() + { + $pages = $this->repo->getList( + $this->criteriaBuilder->addFilter('identifier', 'page_design_blank')->create() + )->getItems(); + $page = array_pop($pages); + /** @var Role $role */ + $role = $this->roleFactory->create(); + $role->load('new_role', 'role_name'); + $this->auth->login('admin_with_role', '12345abc'); + + //Admin doesn't have access to page's design. + /** @var Rules $rules */ + $rules = $this->rulesFactory->create(); + $rules->setRoleId($role->getId()); + $rules->setResources(['Magento_Cms::save']); + $rules->saveRel(); + + $page->setCustomTheme('test'); + $page = $this->repo->save($page); + $this->assertNotEquals('test', $page->getCustomTheme()); + + //Admin has access to page' design. + /** @var Rules $rules */ + $rules = $this->rulesFactory->create(); + $rules->setRoleId($role->getId()); + $rules->setResources(['Magento_Cms::save', 'Magento_Cms::save_design']); + $rules->saveRel(); + + $page->setCustomTheme('test'); + $page = $this->repo->save($page); + $this->assertEquals('test', $page->getCustomTheme()); + } +} diff --git a/dev/tests/integration/testsuite/Magento/User/_files/user_with_new_role.php b/dev/tests/integration/testsuite/Magento/User/_files/user_with_new_role.php index 142a13b6027d0..18087593448f8 100644 --- a/dev/tests/integration/testsuite/Magento/User/_files/user_with_new_role.php +++ b/dev/tests/integration/testsuite/Magento/User/_files/user_with_new_role.php @@ -13,27 +13,21 @@ $objectManager = Bootstrap::getObjectManager(); /** @var Role $role */ $role = $objectManager->create(Role::class); -$role->load('new_role', 'role_name'); -if (!$role->getId()) { - $role->setRoleName('new_role'); - $role->setRoleType('G'); - $role->save(); -} +$role->setRoleName('new_role'); +$role->setRoleType('G'); +$role->save(); /** @var User $model */ $model = $objectManager->create(User::class); -$model->load('admin_with_role', 'username'); -if (!$model->getId()) { - $model->setFirstname("John") - ->setLastname("Doe") - ->setUsername('admin_with_role') - ->setPassword('12345abc') - ->setEmail('admin_with_role@example.com') - ->setRoleType('G') - ->setResourceId('Magento_Backend::all') - ->setPrivileges("") - ->setAssertId(0) - ->setRoleId($role->getId()) - ->setPermission('allow'); - $model->save(); -} +$model->setFirstname("John") + ->setLastname("Doe") + ->setUsername('admin_with_role') + ->setPassword('12345abc') + ->setEmail('admin_with_role@example.com') + ->setRoleType('G') + ->setResourceId('Magento_Backend::all') + ->setPrivileges("") + ->setAssertId(0) + ->setRoleId($role->getId()) + ->setPermission('allow'); +$model->save(); From ddfcdc841d0ef47fc41a50e0ae4928efe611bb8b Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun Date: Wed, 20 Feb 2019 18:52:39 -0600 Subject: [PATCH 057/773] MC-5844: Coupon Requests Limiter --- .../Model/Coupon/CaptchaConfigProvider.php | 5 +++- .../Model/Coupon/CodeLimitManager.php | 25 +++++++++++++------ 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/app/code/Magento/SalesRule/Model/Coupon/CaptchaConfigProvider.php b/app/code/Magento/SalesRule/Model/Coupon/CaptchaConfigProvider.php index 23fc21923357a..82ada4662a01d 100644 --- a/app/code/Magento/SalesRule/Model/Coupon/CaptchaConfigProvider.php +++ b/app/code/Magento/SalesRule/Model/Coupon/CaptchaConfigProvider.php @@ -17,6 +17,8 @@ /** * Adds captcha data related to coupons. + * + * @SuppressWarnings(PHPMD.CookieAndSessionMisuse) */ class CaptchaConfigProvider implements ConfigProviderInterface { @@ -76,7 +78,8 @@ public function getConfig() 'imageHeight' => $captchaModel->getHeight(), 'imageSrc' => $imageSrc, 'refreshUrl' => $store->getUrl('captcha/refresh', ['_secure' => $store->isCurrentlySecure()]), - 'isRequired' => $required + 'isRequired' => $required, + 'timestamp' => time() ] ] ]; diff --git a/app/code/Magento/SalesRule/Model/Coupon/CodeLimitManager.php b/app/code/Magento/SalesRule/Model/Coupon/CodeLimitManager.php index 030ffca363cf4..0a4ca20268e86 100644 --- a/app/code/Magento/SalesRule/Model/Coupon/CodeLimitManager.php +++ b/app/code/Magento/SalesRule/Model/Coupon/CodeLimitManager.php @@ -8,6 +8,7 @@ namespace Magento\SalesRule\Model\Coupon; +use Magento\Customer\Api\CustomerRepositoryInterface; use Magento\Framework\Api\SearchCriteriaBuilder; use Magento\Framework\App\RequestInterface; use Magento\SalesRule\Api\CouponRepositoryInterface; @@ -16,7 +17,7 @@ use Magento\Captcha\Helper\Data as CaptchaHelper; use Magento\Captcha\Observer\CaptchaStringResolver as CaptchaResolver; use Magento\Captcha\Model\DefaultModel as Captcha; -use Magento\Customer\Model\Session as CustomerSession; +use Magento\Authorization\Model\UserContextInterface; /** * @inheritDoc @@ -51,9 +52,14 @@ class CodeLimitManager implements CodeLimitManagerInterface private $request; /** - * @var CustomerSession + * @var UserContextInterface */ - private $customerSession; + private $userContext; + + /** + * @var CustomerRepositoryInterface + */ + private $customerRepository; /** * Needed to avoid confusion in case of duplicate checks. @@ -77,7 +83,8 @@ class CodeLimitManager implements CodeLimitManagerInterface * @param CaptchaHelper $captchaHelper * @param CaptchaResolver $captchaResolver * @param RequestInterface $request - * @param CustomerSession $customerSession + * @param UserContextInterface $userContext + * @param CustomerRepositoryInterface $customerRepository */ public function __construct( CouponRepositoryInterface $repository, @@ -85,14 +92,16 @@ public function __construct( CaptchaHelper $captchaHelper, CaptchaResolver $captchaResolver, RequestInterface $request, - CustomerSession $customerSession + UserContextInterface $userContext, + CustomerRepositoryInterface $customerRepository ) { $this->repository = $repository; $this->criteriaBuilder = $criteriaBuilder; $this->captchaHelper = $captchaHelper; $this->captchaResolver = $captchaResolver; $this->request = $request; - $this->customerSession = $customerSession; + $this->userContext = $userContext; + $this->customerRepository = $customerRepository; } /** @@ -116,8 +125,8 @@ private function checkCode(string $code): bool private function getLogin(): ?string { $login = null; - if ($this->customerSession->isLoggedIn()) { - $login = $this->customerSession->getCustomerData()->getEmail(); + if ($this->userContext->getUserType() === UserContextInterface::USER_TYPE_CUSTOMER) { + $login = $this->customerRepository->getById($this->userContext->getUserId())->getEmail(); } return $login; From 6e9d1f2fc3cde7045c581e700c986abccf159345 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun Date: Thu, 21 Feb 2019 20:27:12 -0600 Subject: [PATCH 058/773] MC-5844: Coupon Requests Limiter --- .../Magento/Captcha/CustomerData/Captcha.php | 35 +++++++++++++------ .../Model/Coupon/CaptchaConfigProvider.php | 2 +- app/code/Magento/SalesRule/composer.json | 3 +- .../Magento/SalesRule/etc/frontend/di.xml | 7 ++++ 4 files changed, 35 insertions(+), 12 deletions(-) diff --git a/app/code/Magento/Captcha/CustomerData/Captcha.php b/app/code/Magento/Captcha/CustomerData/Captcha.php index a744daacdc673..0797eea68a134 100644 --- a/app/code/Magento/Captcha/CustomerData/Captcha.php +++ b/app/code/Magento/Captcha/CustomerData/Captcha.php @@ -9,11 +9,16 @@ namespace Magento\Captcha\CustomerData; use Magento\Customer\CustomerData\SectionSourceInterface; +use Magento\Customer\Model\Session as CustomerSession; +use Magento\Captcha\Model\DefaultModel; +use Magento\Captcha\Helper\Data as CaptchaHelper; /** - * Captcha section + * Captcha section. + * + * @SuppressWarnings(PHPMD.CookieAndSessionMisuse) */ -class Captcha extends \Magento\Framework\DataObject implements SectionSourceInterface +class Captcha implements SectionSourceInterface { /** * @var array @@ -21,24 +26,28 @@ class Captcha extends \Magento\Framework\DataObject implements SectionSourceInte private $formIds; /** - * @var \Magento\Captcha\Helper\Data + * @var CaptchaHelper */ private $helper; /** - * @param \Magento\Captcha\Helper\Data $helper + * @var CustomerSession + */ + private $customerSession; + + /** + * @param CaptchaHelper $helper * @param array $formIds - * @param array $data - * @codeCoverageIgnore + * @param CustomerSession $customerSession */ public function __construct( - \Magento\Captcha\Helper\Data $helper, + CaptchaHelper $helper, array $formIds, - array $data = [] + CustomerSession $customerSession ) { - parent::__construct($data); $this->helper = $helper; $this->formIds = $formIds; + $this->customerSession = $customerSession; } /** @@ -49,9 +58,15 @@ public function getSectionData() :array $data = []; foreach ($this->formIds as $formId) { + /** @var DefaultModel $captchaModel */ $captchaModel = $this->helper->getCaptcha($formId); + $login = ''; + if ($this->customerSession->isLoggedIn()) { + $login = $this->customerSession->getCustomerData()->getEmail(); + } + $required = $captchaModel->isRequired($login); $data[$formId] = [ - 'isRequired' => $captchaModel->isRequired(), + 'isRequired' => $required, 'timestamp' => time() ]; } diff --git a/app/code/Magento/SalesRule/Model/Coupon/CaptchaConfigProvider.php b/app/code/Magento/SalesRule/Model/Coupon/CaptchaConfigProvider.php index 82ada4662a01d..0f4e008e672ce 100644 --- a/app/code/Magento/SalesRule/Model/Coupon/CaptchaConfigProvider.php +++ b/app/code/Magento/SalesRule/Model/Coupon/CaptchaConfigProvider.php @@ -74,7 +74,7 @@ public function getConfig() return [ 'captcha' => [ $formId => [ - 'isCaseSensitive' => $captchaModel->isCaseSensitive(), + 'isCaseSensitive' => (bool)$captchaModel->isCaseSensitive(), 'imageHeight' => $captchaModel->getHeight(), 'imageSrc' => $imageSrc, 'refreshUrl' => $store->getUrl('captcha/refresh', ['_secure' => $store->isCurrentlySecure()]), diff --git a/app/code/Magento/SalesRule/composer.json b/app/code/Magento/SalesRule/composer.json index 3d54595a16d78..bb51ef8dca685 100644 --- a/app/code/Magento/SalesRule/composer.json +++ b/app/code/Magento/SalesRule/composer.json @@ -24,7 +24,8 @@ "magento/module-ui": "*", "magento/module-widget": "*", "magento/module-captcha": "*", - "magento/module-checkout": "*" + "magento/module-checkout": "*", + "magento/module-authorization": "*" }, "suggest": { "magento/module-sales-rule-sample-data": "*" diff --git a/app/code/Magento/SalesRule/etc/frontend/di.xml b/app/code/Magento/SalesRule/etc/frontend/di.xml index e38f43eac2194..0b51ac2b566d9 100644 --- a/app/code/Magento/SalesRule/etc/frontend/di.xml +++ b/app/code/Magento/SalesRule/etc/frontend/di.xml @@ -25,4 +25,11 @@ + + + + sales_rule_coupon_request + + + From d9c68e04f77b9bfedfcdc3240a9e58a19e529ac9 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun Date: Thu, 21 Feb 2019 20:32:33 -0600 Subject: [PATCH 059/773] MC-5844: Coupon Requests Limiter --- .../Magento/SalesRule/Model/Coupon/CodeLimitManagerTest.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dev/tests/integration/testsuite/Magento/SalesRule/Model/Coupon/CodeLimitManagerTest.php b/dev/tests/integration/testsuite/Magento/SalesRule/Model/Coupon/CodeLimitManagerTest.php index 7208147054ec2..df32e4ffc057e 100644 --- a/dev/tests/integration/testsuite/Magento/SalesRule/Model/Coupon/CodeLimitManagerTest.php +++ b/dev/tests/integration/testsuite/Magento/SalesRule/Model/Coupon/CodeLimitManagerTest.php @@ -19,6 +19,8 @@ /** * Test for captcha based implementation. + * + * @magentoAppArea frontend */ class CodeLimitManagerTest extends TestCase { From a96f107e51e32599fee5559d170b6f1a39e3a2f8 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun Date: Fri, 22 Feb 2019 12:44:18 -0600 Subject: [PATCH 060/773] MC-13958: Additional Permissions for Design settings --- .../Catalog/Model/CategoryRepositoryTest.php | 42 +++++------------ .../Catalog/Model/ProductRepositoryTest.php | 42 +++++------------ .../Adminhtml/FulltextGridSearchTest.php | 3 ++ .../Magento/Cms/Model/PageRepositoryTest.php | 45 ++++++------------- .../System/Config/OauthSectionTest.php | 5 +++ .../Controller/Adminhtml/Locks/GridTest.php | 5 +++ .../Adminhtml/Locks/MassUnlockTest.php | 5 +++ .../Adminhtml/User/InvalidateTokenTest.php | 2 + .../User/_files/user_with_new_role.php | 33 -------------- 9 files changed, 58 insertions(+), 124 deletions(-) delete mode 100644 dev/tests/integration/testsuite/Magento/User/_files/user_with_new_role.php diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/CategoryRepositoryTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/CategoryRepositoryTest.php index 9343563353adf..df9774ceddba2 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Model/CategoryRepositoryTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/CategoryRepositoryTest.php @@ -7,14 +7,12 @@ namespace Magento\Catalog\Model; -use Magento\Authorization\Model\Role; -use Magento\Authorization\Model\RoleFactory; use Magento\Backend\Model\Auth; use Magento\Catalog\Api\CategoryRepositoryInterface; +use Magento\Framework\Acl\Builder; use Magento\TestFramework\Helper\Bootstrap; -use Magento\Authorization\Model\Rules; -use Magento\Authorization\Model\RulesFactory; use PHPUnit\Framework\TestCase; +use Magento\TestFramework\Bootstrap as TestBootstrap; /** * Provide tests for CategoryRepository model. @@ -29,19 +27,14 @@ class CategoryRepositoryTest extends TestCase private $repo; /** - * @var RulesFactory - */ - private $rulesFactory; - - /** - * @var RoleFactory + * @var Auth */ - private $roleFactory; + private $auth; /** - * @var Auth + * @var Builder */ - private $auth; + private $aclBuilder; /** * Sets up common objects. @@ -51,9 +44,8 @@ class CategoryRepositoryTest extends TestCase protected function setUp() { $this->repo = Bootstrap::getObjectManager()->create(CategoryRepositoryInterface::class); - $this->rulesFactory = Bootstrap::getObjectManager()->get(RulesFactory::class); - $this->roleFactory = Bootstrap::getObjectManager()->get(RoleFactory::class); $this->auth = Bootstrap::getObjectManager()->get(Auth::class); + $this->aclBuilder = Bootstrap::getObjectManager()->get(Builder::class); } /** @@ -64,13 +56,13 @@ protected function tearDown() parent::tearDown(); $this->auth->logout(); + $this->aclBuilder->resetRuntimeAcl(); } /** * Test authorization when saving category's design settings. * * @magentoDataFixture Magento/Catalog/_files/category.php - * @magentoDataFixture Magento/User/_files/user_with_new_role.php * @magentoAppArea adminhtml * @magentoDbIsolation enabled * @magentoAppIsolation enabled @@ -78,28 +70,18 @@ protected function tearDown() public function testSaveDesign() { $category = $this->repo->get(333); - /** @var Role $role */ - $role = $this->roleFactory->create(); - $role->load('new_role', 'role_name'); - $this->auth->login('admin_with_role', '12345abc'); + $this->auth->login(TestBootstrap::ADMIN_NAME, TestBootstrap::ADMIN_PASSWORD); //Admin doesn't have access to category's design. - /** @var Rules $rules */ - $rules = $this->rulesFactory->create(); - $rules->setRoleId($role->getId()); - $rules->setResources(['Magento_Catalog::categories']); - $rules->saveRel(); + $this->aclBuilder->getAcl()->deny(null, 'Magento_Catalog::edit_category_design'); $category->setCustomAttribute('custom_design', 2); $category = $this->repo->save($category); $this->assertEmpty($category->getCustomAttribute('custom_design')); //Admin has access to category' design. - /** @var Rules $rules */ - $rules = $this->rulesFactory->create(); - $rules->setRoleId($role->getId()); - $rules->setResources(['Magento_Catalog::categories', 'Magento_Catalog::edit_category_design']); - $rules->saveRel(); + $this->aclBuilder->getAcl() + ->allow(null, ['Magento_Catalog::categories', 'Magento_Catalog::edit_category_design']); $category->setCustomAttribute('custom_design', 2); $category = $this->repo->save($category); diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductRepositoryTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductRepositoryTest.php index 283b0713e9763..64a6e423d5e93 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductRepositoryTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductRepositoryTest.php @@ -7,14 +7,12 @@ namespace Magento\Catalog\Model; -use Magento\Authorization\Model\Role; -use Magento\Authorization\Model\RoleFactory; use Magento\Backend\Model\Auth; use Magento\Catalog\Api\ProductRepositoryInterface; use Magento\Framework\Api\SearchCriteriaBuilder; use Magento\TestFramework\Helper\Bootstrap; -use Magento\Authorization\Model\Rules; -use Magento\Authorization\Model\RulesFactory; +use Magento\TestFramework\Bootstrap as TestBootstrap; +use Magento\Framework\Acl\Builder; /** * Provide tests for ProductRepository model. @@ -39,19 +37,14 @@ class ProductRepositoryTest extends \PHPUnit\Framework\TestCase private $searchCriteriaBuilder; /** - * @var RulesFactory - */ - private $rulesFactory; - - /** - * @var RoleFactory + * @var Auth */ - private $roleFactory; + private $auth; /** - * @var Auth + * @var Builder */ - private $auth; + private $aclBuilder; /** * Sets up common objects @@ -60,9 +53,8 @@ protected function setUp() { $this->productRepository = Bootstrap::getObjectManager()->create(ProductRepositoryInterface::class); $this->searchCriteriaBuilder = Bootstrap::getObjectManager()->get(SearchCriteriaBuilder::class); - $this->rulesFactory = Bootstrap::getObjectManager()->get(RulesFactory::class); - $this->roleFactory = Bootstrap::getObjectManager()->get(RoleFactory::class); $this->auth = Bootstrap::getObjectManager()->get(Auth::class); + $this->aclBuilder = Bootstrap::getObjectManager()->get(Builder::class); } /** @@ -73,6 +65,7 @@ protected function tearDown() parent::tearDown(); $this->auth->logout(); + $this->aclBuilder->resetRuntimeAcl(); } /** @@ -174,34 +167,23 @@ public function testSaveProductWithGalleryImage(): void * Test authorization when saving product's design settings. * * @magentoDataFixture Magento/Catalog/_files/product_simple.php - * @magentoDataFixture Magento/User/_files/user_with_new_role.php * @magentoAppArea adminhtml */ public function testSaveDesign() { $product = $this->productRepository->get('simple'); - /** @var Role $role */ - $role = $this->roleFactory->create(); - $role->load('new_role', 'role_name'); - $this->auth->login('admin_with_role', '12345abc'); + $this->auth->login(TestBootstrap::ADMIN_NAME, TestBootstrap::ADMIN_PASSWORD); //Admin doesn't have access to product's design. - /** @var Rules $rules */ - $rules = $this->rulesFactory->create(); - $rules->setRoleId($role->getId()); - $rules->setResources(['Magento_Catalog::products']); - $rules->saveRel(); + $this->aclBuilder->getAcl()->deny(null, 'Magento_Catalog::edit_product_design'); $product->setCustomAttribute('custom_design', 2); $product = $this->productRepository->save($product); $this->assertEmpty($product->getCustomAttribute('custom_design')); //Admin has access to products' design. - /** @var Rules $rules */ - $rules = $this->rulesFactory->create(); - $rules->setRoleId($role->getId()); - $rules->setResources(['Magento_Catalog::products', 'Magento_Catalog::edit_product_design']); - $rules->saveRel(); + $this->aclBuilder->getAcl() + ->allow(null, ['Magento_Catalog::products','Magento_Catalog::edit_product_design']); $product->setCustomAttribute('custom_design', 2); $product = $this->productRepository->save($product); diff --git a/dev/tests/integration/testsuite/Magento/Cms/Controller/Adminhtml/FulltextGridSearchTest.php b/dev/tests/integration/testsuite/Magento/Cms/Controller/Adminhtml/FulltextGridSearchTest.php index c740609773b90..24ad1cd809ff2 100644 --- a/dev/tests/integration/testsuite/Magento/Cms/Controller/Adminhtml/FulltextGridSearchTest.php +++ b/dev/tests/integration/testsuite/Magento/Cms/Controller/Adminhtml/FulltextGridSearchTest.php @@ -10,6 +10,9 @@ use Magento\TestFramework\TestCase\AbstractBackendController; /** + * Testing seach in grid. + * + * @magentoAppArea adminhtml * @magentoDataFixture Magento/Cms/Fixtures/page_list.php */ class FulltextGridSearchTest extends AbstractBackendController diff --git a/dev/tests/integration/testsuite/Magento/Cms/Model/PageRepositoryTest.php b/dev/tests/integration/testsuite/Magento/Cms/Model/PageRepositoryTest.php index 89d99d2c62aea..cd4674f95d722 100644 --- a/dev/tests/integration/testsuite/Magento/Cms/Model/PageRepositoryTest.php +++ b/dev/tests/integration/testsuite/Magento/Cms/Model/PageRepositoryTest.php @@ -7,16 +7,17 @@ namespace Magento\Cms\Model; -use Magento\Authorization\Model\Role; -use Magento\Authorization\Model\RoleFactory; use Magento\Backend\Model\Auth; use Magento\Cms\Api\PageRepositoryInterface; use Magento\Framework\Api\SearchCriteriaBuilder; use Magento\TestFramework\Helper\Bootstrap; -use Magento\Authorization\Model\Rules; -use Magento\Authorization\Model\RulesFactory; use PHPUnit\Framework\TestCase; +use Magento\TestFramework\Bootstrap as TestBootstrap; +use Magento\Framework\Acl\Builder; +/** + * Test class for page repository. + */ class PageRepositoryTest extends TestCase { /** @@ -26,16 +27,6 @@ class PageRepositoryTest extends TestCase */ private $repo; - /** - * @var RulesFactory - */ - private $rulesFactory; - - /** - * @var RoleFactory - */ - private $roleFactory; - /** * @var Auth */ @@ -46,6 +37,11 @@ class PageRepositoryTest extends TestCase */ private $criteriaBuilder; + /** + * @var Builder + */ + private $aclBuilder; + /** * Sets up common objects. * @@ -54,10 +50,9 @@ class PageRepositoryTest extends TestCase protected function setUp() { $this->repo = Bootstrap::getObjectManager()->create(PageRepositoryInterface::class); - $this->rulesFactory = Bootstrap::getObjectManager()->get(RulesFactory::class); - $this->roleFactory = Bootstrap::getObjectManager()->get(RoleFactory::class); $this->auth = Bootstrap::getObjectManager()->get(Auth::class); $this->criteriaBuilder = Bootstrap::getObjectManager()->get(SearchCriteriaBuilder::class); + $this->aclBuilder = Bootstrap::getObjectManager()->get(Builder::class); } /** @@ -74,7 +69,6 @@ protected function tearDown() * Test authorization when saving page's design settings. * * @magentoDataFixture Magento/Cms/_files/pages.php - * @magentoDataFixture Magento/User/_files/user_with_new_role.php * @magentoAppArea adminhtml * @magentoDbIsolation enabled * @magentoAppIsolation enabled @@ -85,28 +79,17 @@ public function testSaveDesign() $this->criteriaBuilder->addFilter('identifier', 'page_design_blank')->create() )->getItems(); $page = array_pop($pages); - /** @var Role $role */ - $role = $this->roleFactory->create(); - $role->load('new_role', 'role_name'); - $this->auth->login('admin_with_role', '12345abc'); + $this->auth->login(TestBootstrap::ADMIN_NAME, TestBootstrap::ADMIN_PASSWORD); //Admin doesn't have access to page's design. - /** @var Rules $rules */ - $rules = $this->rulesFactory->create(); - $rules->setRoleId($role->getId()); - $rules->setResources(['Magento_Cms::save']); - $rules->saveRel(); + $this->aclBuilder->getAcl()->deny(null, 'Magento_Cms::save_design'); $page->setCustomTheme('test'); $page = $this->repo->save($page); $this->assertNotEquals('test', $page->getCustomTheme()); //Admin has access to page' design. - /** @var Rules $rules */ - $rules = $this->rulesFactory->create(); - $rules->setRoleId($role->getId()); - $rules->setResources(['Magento_Cms::save', 'Magento_Cms::save_design']); - $rules->saveRel(); + $this->aclBuilder->getAcl()->allow(null, ['Magento_Cms::save', 'Magento_Cms::save_design']); $page->setCustomTheme('test'); $page = $this->repo->save($page); diff --git a/dev/tests/integration/testsuite/Magento/Integration/Block/Adminhtml/System/Config/OauthSectionTest.php b/dev/tests/integration/testsuite/Magento/Integration/Block/Adminhtml/System/Config/OauthSectionTest.php index ac5d8005180b4..b163830c72b18 100644 --- a/dev/tests/integration/testsuite/Magento/Integration/Block/Adminhtml/System/Config/OauthSectionTest.php +++ b/dev/tests/integration/testsuite/Magento/Integration/Block/Adminhtml/System/Config/OauthSectionTest.php @@ -8,6 +8,11 @@ namespace Magento\Integration\Block\Adminhtml\System\Config; +/** + * Testing Oauth section in configs. + * + * @magentoAppArea adminhtml + */ class OauthSectionTest extends \Magento\TestFramework\TestCase\AbstractBackendController { /** diff --git a/dev/tests/integration/testsuite/Magento/User/Controller/Adminhtml/Locks/GridTest.php b/dev/tests/integration/testsuite/Magento/User/Controller/Adminhtml/Locks/GridTest.php index 4a1c8c722b18d..f3e67ac22ecd1 100644 --- a/dev/tests/integration/testsuite/Magento/User/Controller/Adminhtml/Locks/GridTest.php +++ b/dev/tests/integration/testsuite/Magento/User/Controller/Adminhtml/Locks/GridTest.php @@ -5,6 +5,11 @@ */ namespace Magento\User\Controller\Adminhtml\Locks; +/** + * Testing users grid. + * + * @magentoAppArea adminhtml + */ class GridTest extends \Magento\TestFramework\TestCase\AbstractBackendController { /** diff --git a/dev/tests/integration/testsuite/Magento/User/Controller/Adminhtml/Locks/MassUnlockTest.php b/dev/tests/integration/testsuite/Magento/User/Controller/Adminhtml/Locks/MassUnlockTest.php index bd83f202d6942..723a4c481b864 100644 --- a/dev/tests/integration/testsuite/Magento/User/Controller/Adminhtml/Locks/MassUnlockTest.php +++ b/dev/tests/integration/testsuite/Magento/User/Controller/Adminhtml/Locks/MassUnlockTest.php @@ -5,6 +5,11 @@ */ namespace Magento\User\Controller\Adminhtml\Locks; +/** + * Testing unlock controller. + * + * @magentoAppArea adminhtml + */ class MassUnlockTest extends \Magento\TestFramework\TestCase\AbstractBackendController { /** diff --git a/dev/tests/integration/testsuite/Magento/User/Controller/Adminhtml/User/InvalidateTokenTest.php b/dev/tests/integration/testsuite/Magento/User/Controller/Adminhtml/User/InvalidateTokenTest.php index 672cbd7a586ec..77c5507d4d119 100644 --- a/dev/tests/integration/testsuite/Magento/User/Controller/Adminhtml/User/InvalidateTokenTest.php +++ b/dev/tests/integration/testsuite/Magento/User/Controller/Adminhtml/User/InvalidateTokenTest.php @@ -11,6 +11,8 @@ /** * Test class for Magento\User\Controller\Adminhtml\User\InvalidateToken. + * + * @magentoAppArea adminhtml */ class InvalidateTokenTest extends \Magento\TestFramework\TestCase\AbstractBackendController { diff --git a/dev/tests/integration/testsuite/Magento/User/_files/user_with_new_role.php b/dev/tests/integration/testsuite/Magento/User/_files/user_with_new_role.php deleted file mode 100644 index 18087593448f8..0000000000000 --- a/dev/tests/integration/testsuite/Magento/User/_files/user_with_new_role.php +++ /dev/null @@ -1,33 +0,0 @@ -create(Role::class); -$role->setRoleName('new_role'); -$role->setRoleType('G'); -$role->save(); - -/** @var User $model */ -$model = $objectManager->create(User::class); -$model->setFirstname("John") - ->setLastname("Doe") - ->setUsername('admin_with_role') - ->setPassword('12345abc') - ->setEmail('admin_with_role@example.com') - ->setRoleType('G') - ->setResourceId('Magento_Backend::all') - ->setPrivileges("") - ->setAssertId(0) - ->setRoleId($role->getId()) - ->setPermission('allow'); -$model->save(); From fea0463475dc14ebc56219f2da4bb1cd67e24425 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun Date: Fri, 22 Feb 2019 13:55:15 -0600 Subject: [PATCH 061/773] MC-5844: Coupon Requests Limiter --- app/code/Magento/Captcha/CustomerData/Captcha.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Captcha/CustomerData/Captcha.php b/app/code/Magento/Captcha/CustomerData/Captcha.php index 0797eea68a134..86456f9ab27a4 100644 --- a/app/code/Magento/Captcha/CustomerData/Captcha.php +++ b/app/code/Magento/Captcha/CustomerData/Captcha.php @@ -12,13 +12,14 @@ use Magento\Customer\Model\Session as CustomerSession; use Magento\Captcha\Model\DefaultModel; use Magento\Captcha\Helper\Data as CaptchaHelper; +use Magento\Framework\DataObject; /** * Captcha section. * * @SuppressWarnings(PHPMD.CookieAndSessionMisuse) */ -class Captcha implements SectionSourceInterface +class Captcha extends DataObject implements SectionSourceInterface { /** * @var array @@ -38,11 +39,13 @@ class Captcha implements SectionSourceInterface /** * @param CaptchaHelper $helper * @param array $formIds + * @param array $data * @param CustomerSession $customerSession */ public function __construct( CaptchaHelper $helper, array $formIds, + array $data =[], CustomerSession $customerSession ) { $this->helper = $helper; From 21b70c60f160f9a3dcab2c965f4f36b083d725cb Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun Date: Fri, 22 Feb 2019 13:57:38 -0600 Subject: [PATCH 062/773] MC-5844: Coupon Requests Limiter --- app/code/Magento/Captcha/CustomerData/Captcha.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Captcha/CustomerData/Captcha.php b/app/code/Magento/Captcha/CustomerData/Captcha.php index 86456f9ab27a4..f914832ea09f4 100644 --- a/app/code/Magento/Captcha/CustomerData/Captcha.php +++ b/app/code/Magento/Captcha/CustomerData/Captcha.php @@ -40,13 +40,13 @@ class Captcha extends DataObject implements SectionSourceInterface * @param CaptchaHelper $helper * @param array $formIds * @param array $data - * @param CustomerSession $customerSession + * @param CustomerSession|null $customerSession */ public function __construct( CaptchaHelper $helper, array $formIds, array $data =[], - CustomerSession $customerSession + ?CustomerSession $customerSession = null ) { $this->helper = $helper; $this->formIds = $formIds; From 0db8331d40242036be92b8c7b8966a1adfa704c0 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun Date: Fri, 22 Feb 2019 14:59:15 -0600 Subject: [PATCH 063/773] MC-13958: Additional Permissions for Design settings --- app/code/Magento/Catalog/Model/ResourceModel/Product.php | 2 +- .../Magento/User/Controller/Adminhtml/Locks/IndexTest.php | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product.php b/app/code/Magento/Catalog/Model/ResourceModel/Product.php index 36f183832ac9b..8c69175de887b 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product.php @@ -114,9 +114,9 @@ class Product extends AbstractResource * @param \Magento\Eav\Model\Entity\TypeFactory $typeFactory * @param \Magento\Catalog\Model\Product\Attribute\DefaultAttributes $defaultAttributes * @param array $data - * @param TableMaintainer|null $tableMaintainer * @param UserContextInterface|null $userContext * @param AuthorizationInterface|null $authorization + * @param TableMaintainer|null $tableMaintainer * @param UniqueValidationInterface|null $uniqueValidator * * @SuppressWarnings(PHPMD.ExcessiveParameterList) diff --git a/dev/tests/integration/testsuite/Magento/User/Controller/Adminhtml/Locks/IndexTest.php b/dev/tests/integration/testsuite/Magento/User/Controller/Adminhtml/Locks/IndexTest.php index c43bd1ef3f7f8..196627694d19c 100644 --- a/dev/tests/integration/testsuite/Magento/User/Controller/Adminhtml/Locks/IndexTest.php +++ b/dev/tests/integration/testsuite/Magento/User/Controller/Adminhtml/Locks/IndexTest.php @@ -3,8 +3,14 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\User\Controller\Adminhtml\Locks; +/** + * Locked users page test. + * + * @magentoAppArea adminhtml + */ class IndexTest extends \Magento\TestFramework\TestCase\AbstractBackendController { /** From 1ae409cce72d06e7f8a5801cc81e56059cd83d8c Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun Date: Fri, 22 Feb 2019 15:01:08 -0600 Subject: [PATCH 064/773] MC-5844: Coupon Requests Limiter --- app/code/Magento/Captcha/CustomerData/Captcha.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Captcha/CustomerData/Captcha.php b/app/code/Magento/Captcha/CustomerData/Captcha.php index f914832ea09f4..e9e332f8b146f 100644 --- a/app/code/Magento/Captcha/CustomerData/Captcha.php +++ b/app/code/Magento/Captcha/CustomerData/Captcha.php @@ -12,6 +12,7 @@ use Magento\Customer\Model\Session as CustomerSession; use Magento\Captcha\Model\DefaultModel; use Magento\Captcha\Helper\Data as CaptchaHelper; +use Magento\Framework\App\ObjectManager; use Magento\Framework\DataObject; /** @@ -50,7 +51,8 @@ public function __construct( ) { $this->helper = $helper; $this->formIds = $formIds; - $this->customerSession = $customerSession; + parent::__construct($data); + $this->customerSession = $customerSession ?? ObjectManager::getInstance()->get(CustomerSession::class); } /** From 4a8fa2542c52a399b85dbed935e4453b04e02e46 Mon Sep 17 00:00:00 2001 From: roman Date: Mon, 25 Feb 2019 15:21:10 +0200 Subject: [PATCH 065/773] MC-5951: Incorrect rendering --- .../Customer/Ui/Component/Listing/Column/Group/Options.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/code/Magento/Customer/Ui/Component/Listing/Column/Group/Options.php b/app/code/Magento/Customer/Ui/Component/Listing/Column/Group/Options.php index f521a95e1e616..615ad2243a467 100644 --- a/app/code/Magento/Customer/Ui/Component/Listing/Column/Group/Options.php +++ b/app/code/Magento/Customer/Ui/Component/Listing/Column/Group/Options.php @@ -43,6 +43,11 @@ public function toOptionArray() if ($this->options === null) { $this->options = $this->collectionFactory->create()->toOptionArray(); } + + array_walk($this->options, function (&$item) { + $item['__disableTmpl'] = true; + }); + return $this->options; } } From ce2c82ba2f0e624f64bf34c86b3fc4daee4da80b Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun Date: Tue, 26 Feb 2019 18:51:48 -0600 Subject: [PATCH 066/773] MC-5865: Same Content Type for Components on Storefront --- .../Magento/Ui/Controller/Index/Render.php | 23 ++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Ui/Controller/Index/Render.php b/app/code/Magento/Ui/Controller/Index/Render.php index 6dc7e8b12db21..eec044912ac92 100644 --- a/app/code/Magento/Ui/Controller/Index/Render.php +++ b/app/code/Magento/Ui/Controller/Index/Render.php @@ -6,8 +6,11 @@ namespace Magento\Ui\Controller\Index; use Magento\Backend\App\Action\Context; +use Magento\Framework\App\ObjectManager; +use Magento\Framework\App\Response\Http as HttpResponse; use Magento\Framework\View\Element\UiComponentFactory; use Magento\Framework\View\Element\UiComponentInterface; +use Magento\Ui\Model\UiComponentTypeResolver; /** * Is responsible for providing ui components information on store front @@ -24,16 +27,27 @@ class Render extends \Magento\Framework\App\Action\Action */ private $uiComponentFactory; + /** + * @var UiComponentTypeResolver + */ + private $contentTypeResolver; + /** * Render constructor. * @param Context $context * @param UiComponentFactory $uiComponentFactory + * @param UiComponentTypeResolver|null $contentTypeResolver */ - public function __construct(Context $context, UiComponentFactory $uiComponentFactory) - { + public function __construct( + Context $context, + UiComponentFactory $uiComponentFactory, + ?UiComponentTypeResolver $contentTypeResolver = null + ) { parent::__construct($context); $this->context = $context; $this->uiComponentFactory = $uiComponentFactory; + $this->contentTypeResolver = $contentTypeResolver + ?? ObjectManager::getInstance()->get(UiComponentTypeResolver::class); } /** @@ -50,7 +64,10 @@ public function execute() $component = $this->uiComponentFactory->create($this->_request->getParam('namespace')); $this->prepareComponent($component); - $this->_response->appendBody((string) $component->render()); + /** @var HttpResponse $response */ + $response = $this->getResponse(); + $response->appendBody((string) $component->render()); + $response->setHeader('Content-Type', $this->contentTypeResolver->resolve($component->getContext()), true); } /** From 78e2404207d254855eb9f0443a397bf58a0a6ab2 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun Date: Wed, 27 Feb 2019 10:21:24 -0600 Subject: [PATCH 067/773] MC-5865: Same Content Type for Components on Storefront --- .../Magento/Ui/Controller/Index/Render.php | 4 ++- .../Ui/Controller/Index/RenderTest.php | 31 +++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 dev/tests/integration/testsuite/Magento/Ui/Controller/Index/RenderTest.php diff --git a/app/code/Magento/Ui/Controller/Index/Render.php b/app/code/Magento/Ui/Controller/Index/Render.php index eec044912ac92..910885b67c948 100644 --- a/app/code/Magento/Ui/Controller/Index/Render.php +++ b/app/code/Magento/Ui/Controller/Index/Render.php @@ -13,7 +13,9 @@ use Magento\Ui\Model\UiComponentTypeResolver; /** - * Is responsible for providing ui components information on store front + * Is responsible for providing ui components information on store front. + * + * @SuppressWarnings(PHPMD.AllPurposeAction) */ class Render extends \Magento\Framework\App\Action\Action { diff --git a/dev/tests/integration/testsuite/Magento/Ui/Controller/Index/RenderTest.php b/dev/tests/integration/testsuite/Magento/Ui/Controller/Index/RenderTest.php new file mode 100644 index 0000000000000..c63a6fe75f5fc --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Ui/Controller/Index/RenderTest.php @@ -0,0 +1,31 @@ +getRequest()->setParam('namespace', 'widget_recently_viewed'); + $this->getRequest()->setHeaders(Headers::fromString('Accept: application/json')); + $this->dispatch('mui/index/render'); + $this->assertNotEmpty($contentType = $this->getResponse()->getHeader('Content-Type')); + $this->assertEquals('application/json', $contentType->getFieldValue()); + } +} From bdba212759ca755359b69465399b5ca8e5257f18 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun Date: Thu, 28 Feb 2019 10:43:46 -0600 Subject: [PATCH 068/773] MC-5888: Fixed incorrect wysiwyg behavior --- .../Adminhtml/Wysiwyg/Directive.php | 25 ++++++++++------- .../Magento/Cms/Model/Template/Filter.php | 21 +++------------ .../Test/Unit/Model/Template/FilterTest.php | 27 +++++++++++++++++++ 3 files changed, 46 insertions(+), 27 deletions(-) diff --git a/app/code/Magento/Cms/Controller/Adminhtml/Wysiwyg/Directive.php b/app/code/Magento/Cms/Controller/Adminhtml/Wysiwyg/Directive.php index 807bdcb015ad6..ac6bfdb91b4e1 100644 --- a/app/code/Magento/Cms/Controller/Adminhtml/Wysiwyg/Directive.php +++ b/app/code/Magento/Cms/Controller/Adminhtml/Wysiwyg/Directive.php @@ -7,8 +7,13 @@ namespace Magento\Cms\Controller\Adminhtml\Wysiwyg; use Magento\Backend\App\Action; +use Magento\Cms\Model\Template\Filter; +use Magento\Cms\Model\Wysiwyg\Config; -class Directive extends \Magento\Backend\App\Action +/** + * Process template text for wysiwyg editor. + */ +class Directive extends Action { /** @@ -52,19 +57,21 @@ public function execute() { $directive = $this->getRequest()->getParam('___directive'); $directive = $this->urlDecoder->decode($directive); - $imagePath = $this->_objectManager->create(\Magento\Cms\Model\Template\Filter::class)->filter($directive); - /** @var \Magento\Framework\Image\Adapter\AdapterInterface $image */ - $image = $this->_objectManager->get(\Magento\Framework\Image\AdapterFactory::class)->create(); - /** @var \Magento\Framework\Controller\Result\Raw $resultRaw */ - $resultRaw = $this->resultRawFactory->create(); try { + /** @var Filter $filter */ + $filter = $this->_objectManager->create(Filter::class); + $imagePath = $filter->filter($directive); + /** @var \Magento\Framework\Image\Adapter\AdapterInterface $image */ + $image = $this->_objectManager->get(\Magento\Framework\Image\AdapterFactory::class)->create(); + /** @var \Magento\Framework\Controller\Result\Raw $resultRaw */ + $resultRaw = $this->resultRawFactory->create(); $image->open($imagePath); $resultRaw->setHeader('Content-Type', $image->getMimeType()); $resultRaw->setContents($image->getImage()); } catch (\Exception $e) { - $imagePath = $this->_objectManager->get( - \Magento\Cms\Model\Wysiwyg\Config::class - )->getSkinImagePlaceholderPath(); + /** @var Config $config */ + $config = $this->_objectManager->get(Config::class); + $imagePath = $config->getSkinImagePlaceholderPath(); $image->open($imagePath); $resultRaw->setHeader('Content-Type', $image->getMimeType()); $resultRaw->setContents($image->getImage()); diff --git a/app/code/Magento/Cms/Model/Template/Filter.php b/app/code/Magento/Cms/Model/Template/Filter.php index f56bab49e75d6..4f86dfe07dee2 100644 --- a/app/code/Magento/Cms/Model/Template/Filter.php +++ b/app/code/Magento/Cms/Model/Template/Filter.php @@ -40,25 +40,10 @@ public function setUseSessionInUrl($flag) public function mediaDirective($construction) { $params = $this->getParameters(html_entity_decode($construction[2], ENT_QUOTES)); - return $this->_storeManager->getStore()->getBaseMediaDir() . '/' . $params['url']; - } - - /** - * Validates directive param for traversal path - * - * @param string $directive - * @return string - */ - public function filter($directive) - { - if (preg_match('#\.\.[\\\/]#', $directive)) { - throw new LocalizedException( - __( - 'Requested file should not include parent directory traversal ("../", "..\\" notation)' - ) - ); + if (preg_match('/\.\.(\\\|\/)/', $params['url'])) { + throw new \InvalidArgumentException('Image path must be absolute'); } - return parent::filter($directive); + return $this->_storeManager->getStore()->getBaseMediaDir() . '/' . $params['url']; } } 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 09476f291fb06..b6b802a8a4e6d 100644 --- a/app/code/Magento/Cms/Test/Unit/Model/Template/FilterTest.php +++ b/app/code/Magento/Cms/Test/Unit/Model/Template/FilterTest.php @@ -46,6 +46,8 @@ protected function setUp() } /** + * Test processing media directives. + * * @covers \Magento\Cms\Model\Template\Filter::mediaDirective */ public function testMediaDirective() @@ -63,6 +65,11 @@ public function testMediaDirective() $this->assertEquals($expectedResult, $this->filter->mediaDirective($construction)); } + /** + * Test the directive when HTML quotes used. + * + * @covers \Magento\Cms\Model\Template\Filter::mediaDirective + */ public function testMediaDirectiveWithEncodedQuotes() { $baseMediaDir = 'pub/media'; @@ -78,4 +85,24 @@ public function testMediaDirectiveWithEncodedQuotes() ->willReturn($baseMediaDir); $this->assertEquals($expectedResult, $this->filter->mediaDirective($construction)); } + + /** + * Test using media directive with relative path to image. + * + * @covers \Magento\Cms\Model\Template\Filter::mediaDirective + * @expectedException \InvalidArgumentException + */ + public function testMediaDirectiveRelativePath() + { + $baseMediaDir = 'pub/media'; + $construction = [ + '{{media url="wysiwyg/images/../image.jpg"}}', + 'media', + ' url="wysiwyg/images/../image.jpg"' + ]; + $this->storeMock->expects($this->any()) + ->method('getBaseMediaDir') + ->willReturn($baseMediaDir); + $this->filter->mediaDirective($construction); + } } From ab5598a444bfbd0760aabe4d02a947592db0beaf Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun Date: Thu, 28 Feb 2019 12:37:34 -0600 Subject: [PATCH 069/773] MC-5888: Fixed incorrect wysiwyg behavior --- .../Magento/Cms/Controller/Adminhtml/Wysiwyg/Directive.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Cms/Controller/Adminhtml/Wysiwyg/Directive.php b/app/code/Magento/Cms/Controller/Adminhtml/Wysiwyg/Directive.php index ac6bfdb91b4e1..b21ea9fd7ef7b 100644 --- a/app/code/Magento/Cms/Controller/Adminhtml/Wysiwyg/Directive.php +++ b/app/code/Magento/Cms/Controller/Adminhtml/Wysiwyg/Directive.php @@ -9,11 +9,12 @@ use Magento\Backend\App\Action; use Magento\Cms\Model\Template\Filter; use Magento\Cms\Model\Wysiwyg\Config; +use Magento\Framework\App\Action\HttpGetActionInterface; /** * Process template text for wysiwyg editor. */ -class Directive extends Action +class Directive extends Action implements HttpGetActionInterface { /** From 8874f5828bc676faf67879106690e246127d2381 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun Date: Thu, 28 Feb 2019 12:51:22 -0600 Subject: [PATCH 070/773] MC-14893: Fixed incorrect behavior of email templates --- .../Magento/Framework/Filter/Test/Unit/TemplateTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/internal/Magento/Framework/Filter/Test/Unit/TemplateTest.php b/lib/internal/Magento/Framework/Filter/Test/Unit/TemplateTest.php index 0a5ff8639afca..b4fb0295fa98b 100644 --- a/lib/internal/Magento/Framework/Filter/Test/Unit/TemplateTest.php +++ b/lib/internal/Magento/Framework/Filter/Test/Unit/TemplateTest.php @@ -420,8 +420,8 @@ public function testInappropriateCallbacks() */ public function testDisallowedMethods($method) { - $this->templateFilter->setVariables(['store' => $this->store]); - $this->templateFilter->filter('{{var store.'.$method.'()}}'); + $this->templateFilter->setVariables(['store' => $this->store, 'filter' => $this->templateFilter]); + $this->templateFilter->filter('{{var store.'.$method.'()}} {{var filter.' .$method .'()}}'); } /** From c291f84f08877f536a4262bbfda033d1e763f591 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun Date: Fri, 1 Mar 2019 12:00:49 -0600 Subject: [PATCH 071/773] MC-5968: Fixed incorrect config override behavior --- .../Adminhtml/System/Config/Save.php | 59 +++++++++++++------ .../Adminhtml/System/ConfigTest.php | 32 ++++++++++ 2 files changed, 74 insertions(+), 17 deletions(-) diff --git a/app/code/Magento/Config/Controller/Adminhtml/System/Config/Save.php b/app/code/Magento/Config/Controller/Adminhtml/System/Config/Save.php index 57b29748a9c59..288b95fdda9be 100644 --- a/app/code/Magento/Config/Controller/Adminhtml/System/Config/Save.php +++ b/app/code/Magento/Config/Controller/Adminhtml/System/Config/Save.php @@ -152,14 +152,12 @@ public function execute() $section = $this->getRequest()->getParam('section'); $website = $this->getRequest()->getParam('website'); $store = $this->getRequest()->getParam('store'); - $configData = [ 'section' => $section, 'website' => $website, 'store' => $store, 'groups' => $this->_getGroupsForSave(), ]; - $configData = $this->filterNodes($configData); /** @var \Magento\Config\Model\Config $configModel */ @@ -195,7 +193,7 @@ public function execute() } /** - * Filters nodes by checking exist in system.xml + * Filters nodes by checking whether they exist in system.xml. * * @param array $configData * @return array @@ -203,27 +201,54 @@ public function execute() private function filterNodes(array $configData): array { $systemXmlPathsFromKeys = array_keys($this->_configStructure->getFieldPaths()); - $systemXmlPathsFromValues = array_reduce( array_values($this->_configStructure->getFieldPaths()), 'array_merge', [] ); - - $systemXmlConfig = array_merge($systemXmlPathsFromKeys, $systemXmlPathsFromValues); - - foreach ($configData['groups'] as $configKey => $configFields) { - foreach (array_keys($configFields['fields']) as $configFieldName) { - $systemConfigArrayKey = $configData['section'] . '/' . - $configKey . '/' . - $configFieldName; - if (in_array($systemConfigArrayKey, $systemXmlConfig)) { - continue; + //Full list of paths defined in system.xml + $systemXmlConfig = array_flip(array_merge($systemXmlPathsFromKeys, $systemXmlPathsFromValues)); + //Recursive filtering function. + $filterPaths = function (string $prefix, array $groups) use (&$filterPaths, $systemXmlConfig): array { + $filtered = []; + foreach ($groups as $groupName => $childPaths) { + //Processing fields + if (array_key_exists('fields', $childPaths)) { + foreach ($childPaths['fields'] as $field => $fieldData) { + //Constructing config path for the $field + $path = $prefix .'/' .$groupName .'/' .$field; + $element = $this->_configStructure->getElement($path); + if ($element + && ($elementData = $element->getData()) + && array_key_exists('config_path', $elementData) + ) { + $path = $elementData['config_path']; + } + //Checking whether it exists in system.xml + if (array_key_exists($path, $systemXmlConfig)) { + if (!array_key_exists($groupName, $filtered)) { + $filtered[$groupName] = ['fields' => []]; + } + $filtered[$groupName]['fields'][$field] = $fieldData; + } + } + } + //Recursively filtering this group's groups. + if (array_key_exists('groups', $childPaths)) { + $filteredGroups = $filterPaths($prefix .'/' .$groupName, $childPaths['groups']); + if ($filteredGroups) { + if (!array_key_exists($groupName, $filtered)) { + $filtered[$groupName] = []; + } + $filtered[$groupName]['groups'] = $filteredGroups; + } } - - unset($configData['groups'][$configKey]['fields'][$configFieldName]); } - } + + return $filtered; + }; + + $configData['groups'] = $filterPaths($configData['section'], $configData['groups']); return $configData; } diff --git a/dev/tests/integration/testsuite/Magento/Config/Controller/Adminhtml/System/ConfigTest.php b/dev/tests/integration/testsuite/Magento/Config/Controller/Adminhtml/System/ConfigTest.php index 24b68e804cd57..0a55c7866fccf 100644 --- a/dev/tests/integration/testsuite/Magento/Config/Controller/Adminhtml/System/ConfigTest.php +++ b/dev/tests/integration/testsuite/Magento/Config/Controller/Adminhtml/System/ConfigTest.php @@ -6,6 +6,7 @@ namespace Magento\Config\Controller\Adminhtml\System; +use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\TestFramework\Helper\Bootstrap; use Magento\Framework\App\Request\Http as HttpRequest; @@ -67,6 +68,37 @@ public function testChangeBaseUrl() $this->resetBaseUrl($defaultHost); } + /** + * Test saving undeclared configs. + * + * @magentoAppIsolation enabled + * @magentoDbIsolation enabled + */ + public function testSavingUndeclared() + { + $request = $this->getRequest(); + $request->setPostValue([ + 'groups' => [ + 'non_existing' => [ + 'fields' => [ + 'non_existing_field' => [ + 'value' => 'some_value' + ] + ] + ] + ] + ]); + $request->setParam('section', 'web'); + $request->setMethod(HttpRequest::METHOD_POST); + + $this->dispatch('backend/admin/system_config/save'); + + $this->assertSessionMessages($this->equalTo(['You saved the configuration.'])); + /** @var ScopeConfigInterface $scopeConfig */ + $scopeConfig = Bootstrap::getObjectManager()->get(ScopeConfigInterface::class); + $this->assertNull($scopeConfig->getValue('web/non_existing/non_existing_field')); + } + /** * Reset test framework default base url. * From 548b48d8ed36288f6e16c762ea987d4dfcb2f718 Mon Sep 17 00:00:00 2001 From: Dmytro Voskoboinikov Date: Fri, 1 Mar 2019 15:07:14 -0600 Subject: [PATCH 072/773] MC-5951: Incorrect rendering --- .../Customer/Test/Unit/Ui/Component/ColumnFactoryTest.php | 1 + .../Customer/Test/Unit/Ui/Component/FilterFactoryTest.php | 1 + .../Test/Unit/Ui/Component/Listing/AttributeRepositoryTest.php | 3 ++- .../Customer/view/adminhtml/web/js/grid/columns/actions.js | 2 +- .../Customer/Model/Config/Source/Group/MultiselectTest.php | 2 +- 5 files changed, 6 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Customer/Test/Unit/Ui/Component/ColumnFactoryTest.php b/app/code/Magento/Customer/Test/Unit/Ui/Component/ColumnFactoryTest.php index 131b1ee94cc14..dfc9af2a35498 100644 --- a/app/code/Magento/Customer/Test/Unit/Ui/Component/ColumnFactoryTest.php +++ b/app/code/Magento/Customer/Test/Unit/Ui/Component/ColumnFactoryTest.php @@ -90,6 +90,7 @@ public function testCreate() ] ], 'component' => 'Magento_Ui/js/grid/columns/column', + '__disableTmpl' => 'true' ], ], 'context' => $this->context, diff --git a/app/code/Magento/Customer/Test/Unit/Ui/Component/FilterFactoryTest.php b/app/code/Magento/Customer/Test/Unit/Ui/Component/FilterFactoryTest.php index 7fbf9d2a2a10a..a0681ce6e94a5 100644 --- a/app/code/Magento/Customer/Test/Unit/Ui/Component/FilterFactoryTest.php +++ b/app/code/Magento/Customer/Test/Unit/Ui/Component/FilterFactoryTest.php @@ -69,6 +69,7 @@ public function testCreate() 'config' => [ 'dataScope' => $filterName, 'label' => __('Label'), + '__disableTmpl' => 'true', 'options' => [['value' => 'Value', 'label' => 'Label']], 'caption' => __('Select...'), ], diff --git a/app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/AttributeRepositoryTest.php b/app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/AttributeRepositoryTest.php index 0662235c0d5ac..187f385bc9107 100644 --- a/app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/AttributeRepositoryTest.php +++ b/app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/AttributeRepositoryTest.php @@ -144,7 +144,8 @@ public function testGetList() 'options' => [ [ 'label' => 'Label', - 'value' => 'Value' + 'value' => 'Value', + '__disableTmpl' => true ] ], 'is_used_in_grid' => true, diff --git a/app/code/Magento/Customer/view/adminhtml/web/js/grid/columns/actions.js b/app/code/Magento/Customer/view/adminhtml/web/js/grid/columns/actions.js index a0be009507915..42f427cf8a094 100644 --- a/app/code/Magento/Customer/view/adminhtml/web/js/grid/columns/actions.js +++ b/app/code/Magento/Customer/view/adminhtml/web/js/grid/columns/actions.js @@ -25,7 +25,7 @@ define([ fieldAction: true, options: true, action: true - }, + } }, /** diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/Config/Source/Group/MultiselectTest.php b/dev/tests/integration/testsuite/Magento/Customer/Model/Config/Source/Group/MultiselectTest.php index a0b8c076d5059..4ee23846ae27c 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Model/Config/Source/Group/MultiselectTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Model/Config/Source/Group/MultiselectTest.php @@ -34,7 +34,7 @@ public function testToOptionArray() $item, [ ['value' => 1, 'label' => 'Default (General)'], - ['value' => 1, 'label' => 'General'], + ['value' => 1, 'label' => 'General', '__disableTmpl' => true], ['value' => 2, 'label' => 'Wholesale'], ['value' => 3, 'label' => 'Retailer'], ] From dd24e3fa3d79ec4c380ba7f0533319467e01efdd Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun Date: Fri, 1 Mar 2019 16:05:45 -0600 Subject: [PATCH 073/773] MC-5968: Fixed incorrect config override behavior --- .../Adminhtml/System/Config/Save.php | 96 +++++++++++-------- 1 file changed, 55 insertions(+), 41 deletions(-) diff --git a/app/code/Magento/Config/Controller/Adminhtml/System/Config/Save.php b/app/code/Magento/Config/Controller/Adminhtml/System/Config/Save.php index 288b95fdda9be..a3f9974872a79 100644 --- a/app/code/Magento/Config/Controller/Adminhtml/System/Config/Save.php +++ b/app/code/Magento/Config/Controller/Adminhtml/System/Config/Save.php @@ -192,6 +192,59 @@ public function execute() ); } + /** + * Filter paths that are not defined. + * + * @param string $prefix Path prefix + * @param array $groups Groups data. + * @param string[] $systemXmlConfig Defined paths. + * @return array Filtered groups. + */ + private function filterPaths(string $prefix, array $groups, array $systemXmlConfig): array + { + $flippedXmlConfig = array_flip($systemXmlConfig); + $filtered = []; + foreach ($groups as $groupName => $childPaths) { + //Processing fields + if (array_key_exists('fields', $childPaths)) { + foreach ($childPaths['fields'] as $field => $fieldData) { + //Constructing config path for the $field + $path = $prefix .'/' .$groupName .'/' .$field; + $element = $this->_configStructure->getElement($path); + if ($element + && ($elementData = $element->getData()) + && array_key_exists('config_path', $elementData) + ) { + $path = $elementData['config_path']; + } + //Checking whether it exists in system.xml + if (array_key_exists($path, $flippedXmlConfig)) { + if (!array_key_exists($groupName, $filtered)) { + $filtered[$groupName] = ['fields' => []]; + } + $filtered[$groupName]['fields'][$field] = $fieldData; + } + } + } + //Recursively filtering this group's groups. + if (array_key_exists('groups', $childPaths)) { + $filteredGroups = $this->filterPaths( + $prefix .'/' .$groupName, + $childPaths['groups'], + $systemXmlConfig + ); + if ($filteredGroups) { + if (!array_key_exists($groupName, $filtered)) { + $filtered[$groupName] = []; + } + $filtered[$groupName]['groups'] = $filteredGroups; + } + } + } + + return $filtered; + } + /** * Filters nodes by checking whether they exist in system.xml. * @@ -207,48 +260,9 @@ private function filterNodes(array $configData): array [] ); //Full list of paths defined in system.xml - $systemXmlConfig = array_flip(array_merge($systemXmlPathsFromKeys, $systemXmlPathsFromValues)); - //Recursive filtering function. - $filterPaths = function (string $prefix, array $groups) use (&$filterPaths, $systemXmlConfig): array { - $filtered = []; - foreach ($groups as $groupName => $childPaths) { - //Processing fields - if (array_key_exists('fields', $childPaths)) { - foreach ($childPaths['fields'] as $field => $fieldData) { - //Constructing config path for the $field - $path = $prefix .'/' .$groupName .'/' .$field; - $element = $this->_configStructure->getElement($path); - if ($element - && ($elementData = $element->getData()) - && array_key_exists('config_path', $elementData) - ) { - $path = $elementData['config_path']; - } - //Checking whether it exists in system.xml - if (array_key_exists($path, $systemXmlConfig)) { - if (!array_key_exists($groupName, $filtered)) { - $filtered[$groupName] = ['fields' => []]; - } - $filtered[$groupName]['fields'][$field] = $fieldData; - } - } - } - //Recursively filtering this group's groups. - if (array_key_exists('groups', $childPaths)) { - $filteredGroups = $filterPaths($prefix .'/' .$groupName, $childPaths['groups']); - if ($filteredGroups) { - if (!array_key_exists($groupName, $filtered)) { - $filtered[$groupName] = []; - } - $filtered[$groupName]['groups'] = $filteredGroups; - } - } - } - - return $filtered; - }; + $systemXmlConfig = array_merge($systemXmlPathsFromKeys, $systemXmlPathsFromValues); - $configData['groups'] = $filterPaths($configData['section'], $configData['groups']); + $configData['groups'] = $this->filterPaths($configData['section'], $configData['groups'], $systemXmlConfig); return $configData; } From 1ac1b070840ff5746daab207f1695d09fc16ba5c Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun Date: Fri, 1 Mar 2019 17:25:33 -0600 Subject: [PATCH 074/773] MC-5968: Fixed incorrect config override behavior --- .../Controller/Adminhtml/System/Config/Save.php | 17 +++++++++++++++-- .../Controller/Adminhtml/System/ConfigTest.php | 11 +++++++++-- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Config/Controller/Adminhtml/System/Config/Save.php b/app/code/Magento/Config/Controller/Adminhtml/System/Config/Save.php index a3f9974872a79..54590b86712a4 100644 --- a/app/code/Magento/Config/Controller/Adminhtml/System/Config/Save.php +++ b/app/code/Magento/Config/Controller/Adminhtml/System/Config/Save.php @@ -8,7 +8,8 @@ use Magento\Framework\App\Action\HttpPostActionInterface as HttpPostActionInterface; use Magento\Config\Controller\Adminhtml\System\AbstractConfig; -use Magento\Config\Model\Config\Structure; +use Magento\Framework\App\ObjectManager; +use Magento\Framework\App\State; /** * System Configuration Save Controller @@ -35,6 +36,11 @@ class Save extends AbstractConfig implements HttpPostActionInterface */ protected $string; + /** + * @var State + */ + private $appState; + /** * @param \Magento\Backend\App\Action\Context $context * @param \Magento\Config\Model\Config\Structure $configStructure @@ -42,6 +48,7 @@ class Save extends AbstractConfig implements HttpPostActionInterface * @param \Magento\Config\Model\Config\Factory $configFactory * @param \Magento\Framework\Cache\FrontendInterface $cache * @param \Magento\Framework\Stdlib\StringUtils $string + * @param State|null $appState */ public function __construct( \Magento\Backend\App\Action\Context $context, @@ -49,12 +56,14 @@ public function __construct( \Magento\Config\Controller\Adminhtml\System\ConfigSectionChecker $sectionChecker, \Magento\Config\Model\Config\Factory $configFactory, \Magento\Framework\Cache\FrontendInterface $cache, - \Magento\Framework\Stdlib\StringUtils $string + \Magento\Framework\Stdlib\StringUtils $string, + ?State $appState = null ) { parent::__construct($context, $configStructure, $sectionChecker); $this->_configFactory = $configFactory; $this->_cache = $cache; $this->string = $string; + $this->appState = $appState ?? ObjectManager::getInstance()->get(State::class); } /** @@ -253,6 +262,10 @@ private function filterPaths(string $prefix, array $groups, array $systemXmlConf */ private function filterNodes(array $configData): array { + if ($this->appState->getMode() !== State::MODE_PRODUCTION) { + return $configData; + } + $systemXmlPathsFromKeys = array_keys($this->_configStructure->getFieldPaths()); $systemXmlPathsFromValues = array_reduce( array_values($this->_configStructure->getFieldPaths()), diff --git a/dev/tests/integration/testsuite/Magento/Config/Controller/Adminhtml/System/ConfigTest.php b/dev/tests/integration/testsuite/Magento/Config/Controller/Adminhtml/System/ConfigTest.php index 0a55c7866fccf..d7746286f797a 100644 --- a/dev/tests/integration/testsuite/Magento/Config/Controller/Adminhtml/System/ConfigTest.php +++ b/dev/tests/integration/testsuite/Magento/Config/Controller/Adminhtml/System/ConfigTest.php @@ -6,9 +6,12 @@ namespace Magento\Config\Controller\Adminhtml\System; +use Magento\Config\Controller\Adminhtml\System\Config\Save; use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Framework\App\State; use Magento\TestFramework\Helper\Bootstrap; use Magento\Framework\App\Request\Http as HttpRequest; +use Magento\TestFramework\ObjectManager; /** * @magentoAppArea adminhtml @@ -90,8 +93,12 @@ public function testSavingUndeclared() ]); $request->setParam('section', 'web'); $request->setMethod(HttpRequest::METHOD_POST); - - $this->dispatch('backend/admin/system_config/save'); + /** @var ObjectManager $objectManager */ + $objectManager = Bootstrap::getObjectManager(); + $appState = $objectManager->create(State::class, ['mode' => State::MODE_PRODUCTION]); + /** @var Save $controller */ + $controller = $objectManager->create(Save::class, ['appState' => $appState]); + $controller->execute(); $this->assertSessionMessages($this->equalTo(['You saved the configuration.'])); /** @var ScopeConfigInterface $scopeConfig */ From d5475ffe8c2882a4ad76d66f911b32f44abba133 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun Date: Sun, 3 Mar 2019 19:21:17 -0600 Subject: [PATCH 075/773] MC-5968: Fixed incorrect config override behavior --- .../Controller/Adminhtml/System/Config/Save.php | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/app/code/Magento/Config/Controller/Adminhtml/System/Config/Save.php b/app/code/Magento/Config/Controller/Adminhtml/System/Config/Save.php index 54590b86712a4..d64c48982c094 100644 --- a/app/code/Magento/Config/Controller/Adminhtml/System/Config/Save.php +++ b/app/code/Magento/Config/Controller/Adminhtml/System/Config/Save.php @@ -214,6 +214,7 @@ private function filterPaths(string $prefix, array $groups, array $systemXmlConf $flippedXmlConfig = array_flip($systemXmlConfig); $filtered = []; foreach ($groups as $groupName => $childPaths) { + $filtered[$groupName] = ['fields' => [], 'groups' => []]; //Processing fields if (array_key_exists('fields', $childPaths)) { foreach ($childPaths['fields'] as $field => $fieldData) { @@ -228,9 +229,6 @@ private function filterPaths(string $prefix, array $groups, array $systemXmlConf } //Checking whether it exists in system.xml if (array_key_exists($path, $flippedXmlConfig)) { - if (!array_key_exists($groupName, $filtered)) { - $filtered[$groupName] = ['fields' => []]; - } $filtered[$groupName]['fields'][$field] = $fieldData; } } @@ -243,15 +241,14 @@ private function filterPaths(string $prefix, array $groups, array $systemXmlConf $systemXmlConfig ); if ($filteredGroups) { - if (!array_key_exists($groupName, $filtered)) { - $filtered[$groupName] = []; - } $filtered[$groupName]['groups'] = $filteredGroups; } } + + $filtered[$groupName] = array_filter($filtered[$groupName]); } - return $filtered; + return array_filter($filtered); } /** From 9bb139d12fb60e06c73b0f80483600527921e0c1 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun Date: Sun, 3 Mar 2019 20:00:05 -0600 Subject: [PATCH 076/773] MC-5949: Calculated Labels in Columns Widget --- app/code/Magento/Catalog/Ui/Component/ColumnFactory.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Catalog/Ui/Component/ColumnFactory.php b/app/code/Magento/Catalog/Ui/Component/ColumnFactory.php index 1903bcd144831..364d922460d98 100644 --- a/app/code/Magento/Catalog/Ui/Component/ColumnFactory.php +++ b/app/code/Magento/Catalog/Ui/Component/ColumnFactory.php @@ -76,6 +76,7 @@ public function create($attribute, $context, array $config = []) } $config['component'] = $this->getJsComponent($config['dataType']); + $config['__disableTmpl'] = true; $arguments = [ 'data' => [ From 810dcb8472bd3b1fdd8053d41ba144179e285dfd Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun Date: Sun, 3 Mar 2019 22:44:10 -0600 Subject: [PATCH 077/773] MC-5968: Fixed incorrect config override behavior --- .../Controller/Adminhtml/System/Config/Save.php | 16 +--------------- .../Controller/Adminhtml/System/ConfigTest.php | 7 +------ 2 files changed, 2 insertions(+), 21 deletions(-) diff --git a/app/code/Magento/Config/Controller/Adminhtml/System/Config/Save.php b/app/code/Magento/Config/Controller/Adminhtml/System/Config/Save.php index d64c48982c094..7f0d24f609613 100644 --- a/app/code/Magento/Config/Controller/Adminhtml/System/Config/Save.php +++ b/app/code/Magento/Config/Controller/Adminhtml/System/Config/Save.php @@ -8,8 +8,6 @@ use Magento\Framework\App\Action\HttpPostActionInterface as HttpPostActionInterface; use Magento\Config\Controller\Adminhtml\System\AbstractConfig; -use Magento\Framework\App\ObjectManager; -use Magento\Framework\App\State; /** * System Configuration Save Controller @@ -36,11 +34,6 @@ class Save extends AbstractConfig implements HttpPostActionInterface */ protected $string; - /** - * @var State - */ - private $appState; - /** * @param \Magento\Backend\App\Action\Context $context * @param \Magento\Config\Model\Config\Structure $configStructure @@ -48,7 +41,6 @@ class Save extends AbstractConfig implements HttpPostActionInterface * @param \Magento\Config\Model\Config\Factory $configFactory * @param \Magento\Framework\Cache\FrontendInterface $cache * @param \Magento\Framework\Stdlib\StringUtils $string - * @param State|null $appState */ public function __construct( \Magento\Backend\App\Action\Context $context, @@ -56,14 +48,12 @@ public function __construct( \Magento\Config\Controller\Adminhtml\System\ConfigSectionChecker $sectionChecker, \Magento\Config\Model\Config\Factory $configFactory, \Magento\Framework\Cache\FrontendInterface $cache, - \Magento\Framework\Stdlib\StringUtils $string, - ?State $appState = null + \Magento\Framework\Stdlib\StringUtils $string ) { parent::__construct($context, $configStructure, $sectionChecker); $this->_configFactory = $configFactory; $this->_cache = $cache; $this->string = $string; - $this->appState = $appState ?? ObjectManager::getInstance()->get(State::class); } /** @@ -259,10 +249,6 @@ private function filterPaths(string $prefix, array $groups, array $systemXmlConf */ private function filterNodes(array $configData): array { - if ($this->appState->getMode() !== State::MODE_PRODUCTION) { - return $configData; - } - $systemXmlPathsFromKeys = array_keys($this->_configStructure->getFieldPaths()); $systemXmlPathsFromValues = array_reduce( array_values($this->_configStructure->getFieldPaths()), diff --git a/dev/tests/integration/testsuite/Magento/Config/Controller/Adminhtml/System/ConfigTest.php b/dev/tests/integration/testsuite/Magento/Config/Controller/Adminhtml/System/ConfigTest.php index d7746286f797a..f5dbeb2ed12e4 100644 --- a/dev/tests/integration/testsuite/Magento/Config/Controller/Adminhtml/System/ConfigTest.php +++ b/dev/tests/integration/testsuite/Magento/Config/Controller/Adminhtml/System/ConfigTest.php @@ -8,10 +8,8 @@ use Magento\Config\Controller\Adminhtml\System\Config\Save; use Magento\Framework\App\Config\ScopeConfigInterface; -use Magento\Framework\App\State; use Magento\TestFramework\Helper\Bootstrap; use Magento\Framework\App\Request\Http as HttpRequest; -use Magento\TestFramework\ObjectManager; /** * @magentoAppArea adminhtml @@ -93,11 +91,8 @@ public function testSavingUndeclared() ]); $request->setParam('section', 'web'); $request->setMethod(HttpRequest::METHOD_POST); - /** @var ObjectManager $objectManager */ - $objectManager = Bootstrap::getObjectManager(); - $appState = $objectManager->create(State::class, ['mode' => State::MODE_PRODUCTION]); /** @var Save $controller */ - $controller = $objectManager->create(Save::class, ['appState' => $appState]); + $controller = Bootstrap::getObjectManager()->create(Save::class); $controller->execute(); $this->assertSessionMessages($this->equalTo(['You saved the configuration.'])); From 0b91ef9b399fb7baa519aaf3e7a3f89fad65556e Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun Date: Mon, 4 Mar 2019 18:03:06 -0600 Subject: [PATCH 078/773] MC-5968: Fixed incorrect config override behavior --- .../Adminhtml/System/Config/Save.php | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/app/code/Magento/Config/Controller/Adminhtml/System/Config/Save.php b/app/code/Magento/Config/Controller/Adminhtml/System/Config/Save.php index 7f0d24f609613..9f94f8e711c15 100644 --- a/app/code/Magento/Config/Controller/Adminhtml/System/Config/Save.php +++ b/app/code/Magento/Config/Controller/Adminhtml/System/Config/Save.php @@ -224,7 +224,7 @@ private function filterPaths(string $prefix, array $groups, array $systemXmlConf } } //Recursively filtering this group's groups. - if (array_key_exists('groups', $childPaths)) { + if (array_key_exists('groups', $childPaths) && $childPaths['groups']) { $filteredGroups = $this->filterPaths( $prefix .'/' .$groupName, $childPaths['groups'], @@ -249,16 +249,18 @@ private function filterPaths(string $prefix, array $groups, array $systemXmlConf */ private function filterNodes(array $configData): array { - $systemXmlPathsFromKeys = array_keys($this->_configStructure->getFieldPaths()); - $systemXmlPathsFromValues = array_reduce( - array_values($this->_configStructure->getFieldPaths()), - 'array_merge', - [] - ); - //Full list of paths defined in system.xml - $systemXmlConfig = array_merge($systemXmlPathsFromKeys, $systemXmlPathsFromValues); + if (!empty($configData['groups'])) { + $systemXmlPathsFromKeys = array_keys($this->_configStructure->getFieldPaths()); + $systemXmlPathsFromValues = array_reduce( + array_values($this->_configStructure->getFieldPaths()), + 'array_merge', + [] + ); + //Full list of paths defined in system.xml + $systemXmlConfig = array_merge($systemXmlPathsFromKeys, $systemXmlPathsFromValues); - $configData['groups'] = $this->filterPaths($configData['section'], $configData['groups'], $systemXmlConfig); + $configData['groups'] = $this->filterPaths($configData['section'], $configData['groups'], $systemXmlConfig); + } return $configData; } From f645b686ac1755a583afdcd09d8fe457cb5a3b17 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun Date: Tue, 5 Mar 2019 12:12:12 -0600 Subject: [PATCH 079/773] MC-5968: Fixed incorrect config override behavior --- .../Config/Controller/Adminhtml/System/Config/Save.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/app/code/Magento/Config/Controller/Adminhtml/System/Config/Save.php b/app/code/Magento/Config/Controller/Adminhtml/System/Config/Save.php index 9f94f8e711c15..bea080d366f4a 100644 --- a/app/code/Magento/Config/Controller/Adminhtml/System/Config/Save.php +++ b/app/code/Magento/Config/Controller/Adminhtml/System/Config/Save.php @@ -198,12 +198,20 @@ public function execute() * @param array $groups Groups data. * @param string[] $systemXmlConfig Defined paths. * @return array Filtered groups. + * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ private function filterPaths(string $prefix, array $groups, array $systemXmlConfig): array { $flippedXmlConfig = array_flip($systemXmlConfig); $filtered = []; foreach ($groups as $groupName => $childPaths) { + //When group accepts arbitrary fields and clones them we allow it + $group = $this->_configStructure->getElement($prefix .'/' .$groupName); + if (array_key_exists('clone_fields', $group->getData()) && $group->getData()['clone_fields']) { + $filtered[$groupName] = $childPaths; + continue; + } + $filtered[$groupName] = ['fields' => [], 'groups' => []]; //Processing fields if (array_key_exists('fields', $childPaths)) { From 7c0bc1aaf3199f08763d15b904a16caa9470e1b5 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun Date: Tue, 5 Mar 2019 16:21:34 -0600 Subject: [PATCH 080/773] MC-5951: Incorrect rendering --- app/code/Magento/Customer/Block/Adminhtml/Group/Edit/Form.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Customer/Block/Adminhtml/Group/Edit/Form.php b/app/code/Magento/Customer/Block/Adminhtml/Group/Edit/Form.php index e87a08ebc10c1..1a57ab7c7b6a5 100644 --- a/app/code/Magento/Customer/Block/Adminhtml/Group/Edit/Form.php +++ b/app/code/Magento/Customer/Block/Adminhtml/Group/Edit/Form.php @@ -84,7 +84,7 @@ protected function _prepareLayout() $fieldset = $form->addFieldset('base_fieldset', ['legend' => __('Group Information')]); $validateClass = sprintf( - 'required-entry validate-data validate-length maximum-length-%d', + 'required-entry validate-length maximum-length-%d', \Magento\Customer\Model\GroupManagement::GROUP_CODE_MAX_LENGTH ); $name = $fieldset->addField( From 7259fe7a1ef45e7016ecbdaa0ab4fc887848a705 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun Date: Wed, 6 Mar 2019 10:43:34 -0600 Subject: [PATCH 081/773] MC-13958: Additional Permissions for Design settings --- .../Magento/Catalog/Model/ResourceModel/Product.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product.php b/app/code/Magento/Catalog/Model/ResourceModel/Product.php index 8c69175de887b..e48f3ae4bf09d 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product.php @@ -114,10 +114,10 @@ class Product extends AbstractResource * @param \Magento\Eav\Model\Entity\TypeFactory $typeFactory * @param \Magento\Catalog\Model\Product\Attribute\DefaultAttributes $defaultAttributes * @param array $data - * @param UserContextInterface|null $userContext - * @param AuthorizationInterface|null $authorization * @param TableMaintainer|null $tableMaintainer * @param UniqueValidationInterface|null $uniqueValidator + * @param UserContextInterface|null $userContext + * @param AuthorizationInterface|null $authorization * * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -132,10 +132,10 @@ public function __construct( \Magento\Eav\Model\Entity\TypeFactory $typeFactory, \Magento\Catalog\Model\Product\Attribute\DefaultAttributes $defaultAttributes, $data = [], - ?UserContextInterface $userContext = null, - ?AuthorizationInterface $authorization = null, TableMaintainer $tableMaintainer = null, - UniqueValidationInterface $uniqueValidator = null + UniqueValidationInterface $uniqueValidator = null, + ?UserContextInterface $userContext = null, + ?AuthorizationInterface $authorization = null ) { $this->_categoryCollectionFactory = $categoryCollectionFactory; $this->_catalogCategory = $catalogCategory; From f48cdb75129c33735094a66156ba355fad410e35 Mon Sep 17 00:00:00 2001 From: Dmytro Voskoboinikov Date: Wed, 6 Mar 2019 13:59:52 -0600 Subject: [PATCH 082/773] MC-13743: Fixed incorrect email template rendering --- lib/internal/Magento/Framework/Filter/Template.php | 3 ++- .../Magento/Framework/Filter/Test/Unit/TemplateTest.php | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/Filter/Template.php b/lib/internal/Magento/Framework/Filter/Template.php index d3a8d5334ab9d..5d26447be6750 100644 --- a/lib/internal/Magento/Framework/Filter/Template.php +++ b/lib/internal/Magento/Framework/Filter/Template.php @@ -75,7 +75,8 @@ class Template implements \Zend_Filter_Interface 'load', 'save', 'getcollection', - 'getresource' + 'getresource', + 'getconfig' ]; /** diff --git a/lib/internal/Magento/Framework/Filter/Test/Unit/TemplateTest.php b/lib/internal/Magento/Framework/Filter/Test/Unit/TemplateTest.php index e4a2dc48d11dd..605504d6e5ba4 100644 --- a/lib/internal/Magento/Framework/Filter/Test/Unit/TemplateTest.php +++ b/lib/internal/Magento/Framework/Filter/Test/Unit/TemplateTest.php @@ -437,6 +437,7 @@ public function disallowedMethods() ['save'], ['getCollection'], ['getResource'], + ['getConfig'], ]; } } From 5bf761384013fd1f8907fc10291dea155644fc75 Mon Sep 17 00:00:00 2001 From: Dmytro Voskoboinikov Date: Wed, 6 Mar 2019 14:10:08 -0600 Subject: [PATCH 083/773] MC-5841: Fixed incorrect order's status displaying --- .../Listing/Column/Status/OptionsTest.php | 27 +++++++++++++++---- .../Listing/Column/Status/Options.php | 8 +++++- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/Sales/Test/Unit/Ui/Component/Listing/Column/Status/OptionsTest.php b/app/code/Magento/Sales/Test/Unit/Ui/Component/Listing/Column/Status/OptionsTest.php index c0eba0b14138a..fe285d29d703b 100644 --- a/app/code/Magento/Sales/Test/Unit/Ui/Component/Listing/Column/Status/OptionsTest.php +++ b/app/code/Magento/Sales/Test/Unit/Ui/Component/Listing/Column/Status/OptionsTest.php @@ -39,17 +39,34 @@ protected function setUp() public function testToOptionArray() { - $collectionMock = - $this->createMock(\Magento\Sales\Model\ResourceModel\Order\Status\Collection::class); - $options = ['options']; + $collectionMock = $this->createMock( + \Magento\Sales\Model\ResourceModel\Order\Status\Collection::class + ); + + $options = [ + [ + 'value' => '1', + 'label' => 'Label' + ] + ]; + + $expectedOptions = [ + [ + 'value' => '1', + 'label' => 'Label', + '__disableTmpl' => true + ] + ]; $this->collectionFactoryMock->expects($this->once()) ->method('create') ->willReturn($collectionMock); + $collectionMock->expects($this->once()) ->method('toOptionArray') ->willReturn($options); - $this->assertEquals($options, $this->model->toOptionArray()); - $this->assertEquals($options, $this->model->toOptionArray()); + + $this->assertEquals($expectedOptions, $this->model->toOptionArray()); + $this->assertEquals($expectedOptions, $this->model->toOptionArray()); } } diff --git a/app/code/Magento/Sales/Ui/Component/Listing/Column/Status/Options.php b/app/code/Magento/Sales/Ui/Component/Listing/Column/Status/Options.php index e091d4966282a..4a597b1f42540 100644 --- a/app/code/Magento/Sales/Ui/Component/Listing/Column/Status/Options.php +++ b/app/code/Magento/Sales/Ui/Component/Listing/Column/Status/Options.php @@ -41,7 +41,13 @@ public function __construct(CollectionFactory $collectionFactory) public function toOptionArray() { if ($this->options === null) { - $this->options = $this->collectionFactory->create()->toOptionArray(); + $options = $this->collectionFactory->create()->toOptionArray(); + + array_walk($options, function (&$option) { + $option['__disableTmpl'] = true; + }); + + $this->options = $options; } return $this->options; } From 65f6635028e596c169a19ee65e5ad84e3a16fd2e Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun Date: Wed, 6 Mar 2019 15:57:07 -0600 Subject: [PATCH 084/773] MC-13812: Error when using Test Connection --- app/code/Magento/Elasticsearch/Model/Config.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Elasticsearch/Model/Config.php b/app/code/Magento/Elasticsearch/Model/Config.php index c5aec625d36a1..0de0c1fde859c 100644 --- a/app/code/Magento/Elasticsearch/Model/Config.php +++ b/app/code/Magento/Elasticsearch/Model/Config.php @@ -100,11 +100,12 @@ public function prepareClientOptions($options = []) 'timeout' => $this->getElasticsearchConfigData('server_timeout') ? : self::ELASTICSEARCH_DEFAULT_TIMEOUT, ]; $options = array_merge($defaultOptions, $options); + $allowedOptions = array_merge(array_keys($defaultOptions), ['engine']); return array_filter( $options, - function (string $key) use ($defaultOptions) { - return array_key_exists($key, $defaultOptions); + function (string $key) use ($allowedOptions) { + return in_array($key, $allowedOptions); }, ARRAY_FILTER_USE_KEY ); From 1a73182ab6010d6ed6dc2b0583dc0dbce2119562 Mon Sep 17 00:00:00 2001 From: "Rav [RedChamps]" Date: Thu, 7 Mar 2019 12:50:37 +0530 Subject: [PATCH 085/773] Created separate block class inheriting TabWrapper and removed public methods from API block class --- .../Block/Adminhtml/Edit/Tab/Carts.php | 55 -------------- .../Block/Adminhtml/ShoppingCartsTab.php | 74 +++++++++++++++++++ .../view/base/ui_component/customer_form.xml | 6 +- 3 files changed, 77 insertions(+), 58 deletions(-) create mode 100644 app/code/Magento/Sales/Block/Adminhtml/ShoppingCartsTab.php diff --git a/app/code/Magento/Customer/Block/Adminhtml/Edit/Tab/Carts.php b/app/code/Magento/Customer/Block/Adminhtml/Edit/Tab/Carts.php index 2fc43fc7ce3bf..5601cf3728349 100644 --- a/app/code/Magento/Customer/Block/Adminhtml/Edit/Tab/Carts.php +++ b/app/code/Magento/Customer/Block/Adminhtml/Edit/Tab/Carts.php @@ -97,59 +97,4 @@ protected function _getCustomer() ); return $customerDataObject; } - - /** - * @return bool - */ - public function canShowTab() - { - if ($this->_getCustomer()->getId()) { - return true; - } - return false; - } - - /** - * @return \Magento\Framework\Phrase - */ - public function getTabLabel() - { - return __('Shopping cart'); - } - - /** - * @return \Magento\Framework\Phrase - */ - public function getTabTitle() - { - return __('Shopping cart'); - } - - /** - * Return URL link to Tab content, used with isAjaxLoaded to true - * - * @return string - */ - public function getTabUrl() - { - return $this->getUrl('customer/*/cart', ['_current' => true]); - } - - /** - * Tab should be loaded trough Ajax call - * - * @return bool - */ - public function isAjaxLoaded() - { - return true; - } - - /** - * @return bool - */ - public function canDisplayContainer() - { - return true; - } } diff --git a/app/code/Magento/Sales/Block/Adminhtml/ShoppingCartsTab.php b/app/code/Magento/Sales/Block/Adminhtml/ShoppingCartsTab.php new file mode 100644 index 0000000000000..371f109bb0493 --- /dev/null +++ b/app/code/Magento/Sales/Block/Adminhtml/ShoppingCartsTab.php @@ -0,0 +1,74 @@ +coreRegistry = $registry; + parent::__construct($context, $data); + } + + /** + * @inheritdoc + */ + public function canShowTab() + { + return $this->coreRegistry->registry(RegistryConstants::CURRENT_CUSTOMER_ID); + } + + /** + * Return Tab label + * + * @codeCoverageIgnore + * + * @return \Magento\Framework\Phrase + */ + public function getTabLabel() + { + return __('Shopping cart'); + } + + /** + * Return URL link to Tab content + * + * @return string + */ + public function getTabUrl() + { + return $this->getUrl('customer/*/cart', ['_current' => true]); + } +} diff --git a/app/code/Magento/Sales/view/base/ui_component/customer_form.xml b/app/code/Magento/Sales/view/base/ui_component/customer_form.xml index f03338da261f3..ae965bb010c0b 100644 --- a/app/code/Magento/Sales/view/base/ui_component/customer_form.xml +++ b/app/code/Magento/Sales/view/base/ui_component/customer_form.xml @@ -6,10 +6,10 @@ */ -->
- - - + + +
From 9e12510d1f4de6c16afa173eb4d1442dc63d70ee Mon Sep 17 00:00:00 2001 From: OlgaVasyltsun Date: Thu, 7 Mar 2019 14:59:23 +0200 Subject: [PATCH 086/773] MC-14891: Changes in config save controller --- .../Config/Controller/Adminhtml/System/AbstractConfig.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Config/Controller/Adminhtml/System/AbstractConfig.php b/app/code/Magento/Config/Controller/Adminhtml/System/AbstractConfig.php index 36e4603cba577..126fea54312d7 100644 --- a/app/code/Magento/Config/Controller/Adminhtml/System/AbstractConfig.php +++ b/app/code/Magento/Config/Controller/Adminhtml/System/AbstractConfig.php @@ -75,7 +75,7 @@ protected function _isAllowed() { $sectionId = $this->_request->getParam('section'); return parent::_isAllowed() - || $this->_configStructure->getElement($sectionId)->isAllowed(); + && $this->_configStructure->getElement($sectionId)->isAllowed(); } /** From a6ad257ddcecd51b4474eaca50544c8ac4ffc624 Mon Sep 17 00:00:00 2001 From: OlgaVasyltsun Date: Thu, 7 Mar 2019 16:33:59 +0200 Subject: [PATCH 087/773] MC-14891: Changes in config save controller --- .../Config/Controller/Adminhtml/System/AbstractConfig.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/code/Magento/Config/Controller/Adminhtml/System/AbstractConfig.php b/app/code/Magento/Config/Controller/Adminhtml/System/AbstractConfig.php index 126fea54312d7..cb3069f14349a 100644 --- a/app/code/Magento/Config/Controller/Adminhtml/System/AbstractConfig.php +++ b/app/code/Magento/Config/Controller/Adminhtml/System/AbstractConfig.php @@ -12,6 +12,8 @@ * System Configuration Abstract Controller * @api * @since 100.0.2 + * + * @SuppressWarnings(PHPMD.AllPurposeAction) */ abstract class AbstractConfig extends \Magento\Backend\App\AbstractAction { From 593a8b4736ea3c3935b6784eb06201b6ddf8d147 Mon Sep 17 00:00:00 2001 From: Dmytro Voskoboinikov Date: Thu, 7 Mar 2019 11:01:46 -0600 Subject: [PATCH 088/773] MC-5951: Incorrect rendering --- .../Config/Source/Group/MultiselectTest.php | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/Config/Source/Group/MultiselectTest.php b/dev/tests/integration/testsuite/Magento/Customer/Model/Config/Source/Group/MultiselectTest.php index 4ee23846ae27c..e7bb82af8edc5 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Model/Config/Source/Group/MultiselectTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Model/Config/Source/Group/MultiselectTest.php @@ -33,10 +33,26 @@ public function testToOptionArray() $this->assertContains( $item, [ - ['value' => 1, 'label' => 'Default (General)'], - ['value' => 1, 'label' => 'General', '__disableTmpl' => true], - ['value' => 2, 'label' => 'Wholesale'], - ['value' => 3, 'label' => 'Retailer'], + [ + 'value' => 1, + 'label' => 'Default (General)', + '__disableTmpl' => true + ], + [ + 'value' => 1, + 'label' => 'General', + '__disableTmpl' => true + ], + [ + 'value' => 2, + 'label' => 'Wholesale', + '__disableTmpl' => true + ], + [ + 'value' => 3, + 'label' => 'Retailer', + '__disableTmpl' => true + ], ] ); } From 1048f9c08996c2cb5f3fbb1ba827b8c80baa5861 Mon Sep 17 00:00:00 2001 From: Dmytro Voskoboinikov Date: Thu, 7 Mar 2019 12:41:01 -0600 Subject: [PATCH 089/773] MC-5951: Incorrect rendering --- .../Customer/Model/Config/Source/Group/MultiselectTest.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/Config/Source/Group/MultiselectTest.php b/dev/tests/integration/testsuite/Magento/Customer/Model/Config/Source/Group/MultiselectTest.php index e7bb82af8edc5..918b085580420 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Model/Config/Source/Group/MultiselectTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Model/Config/Source/Group/MultiselectTest.php @@ -35,8 +35,7 @@ public function testToOptionArray() [ [ 'value' => 1, - 'label' => 'Default (General)', - '__disableTmpl' => true + 'label' => 'Default (General)' ], [ 'value' => 1, From efb02d6dc1caa37e64fda30ddc0b99f2f2dfb8a1 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun Date: Thu, 7 Mar 2019 16:26:23 -0600 Subject: [PATCH 090/773] MC-5949: Calculated Labels in Columns Widget --- app/code/Magento/Catalog/Ui/Component/ColumnFactory.php | 4 +++- .../Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php | 3 +++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Ui/Component/ColumnFactory.php b/app/code/Magento/Catalog/Ui/Component/ColumnFactory.php index e362d7d10e329..f7554219c6c31 100644 --- a/app/code/Magento/Catalog/Ui/Component/ColumnFactory.php +++ b/app/code/Magento/Catalog/Ui/Component/ColumnFactory.php @@ -77,10 +77,12 @@ public function create($attribute, $context, array $config = []) if ($attribute->usesSource()) { $config['options'] = $attribute->getSource()->getAllOptions(); + foreach ($config['options'] as &$optionData) { + $optionData['__disableTmpl'] = true; + } } $config['component'] = $this->getJsComponent($config['dataType']); - $config['__disableTmpl'] = true; $arguments = [ 'data' => [ diff --git a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php index 99f7122efa0a8..61320313eef3f 100755 --- a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php +++ b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php @@ -677,6 +677,9 @@ public function setupAttributeMeta(ProductAttributeInterface $attribute, $groupC $attributeModel = $this->getAttributeModel($attribute); if ($attributeModel->usesSource()) { $options = $attributeModel->getSource()->getAllOptions(); + foreach ($options as &$option) { + $option['__disableTmpl'] = true; + } $meta = $this->arrayManager->merge($configPath, $meta, [ 'options' => $this->convertOptionsValueToString($options), ]); From ececfc07d391f9a5062b51444a604ef5fd3ebb63 Mon Sep 17 00:00:00 2001 From: OlgaVasyltsun Date: Tue, 12 Mar 2019 10:07:28 +0200 Subject: [PATCH 091/773] MC-15050: New review form changes --- app/code/Magento/Review/Block/Adminhtml/Add.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Review/Block/Adminhtml/Add.php b/app/code/Magento/Review/Block/Adminhtml/Add.php index c5600fe061003..260685395e106 100644 --- a/app/code/Magento/Review/Block/Adminhtml/Add.php +++ b/app/code/Magento/Review/Block/Adminhtml/Add.php @@ -93,13 +93,14 @@ protected function _construct() if( response.error ) { alert(response.message); } else if( response.id ){ + var productName = response.name; $("product_id").value = response.id; $("product_name").innerHTML = \'\' + response.name + \'\'; + 'id/\' + response.id + \'" target="_blank">\' + productName.escapeHTML() + \'\'; } else if ( response.message ) { alert(response.message); } From 4a9becceba22c1054243aee9d6f8d7564704e4a7 Mon Sep 17 00:00:00 2001 From: Andrii Meysar Date: Tue, 12 Mar 2019 14:01:12 +0200 Subject: [PATCH 092/773] MC-13894: Fixed incorrect email template rendering --- lib/internal/Magento/Framework/Filter/Template.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/Filter/Template.php b/lib/internal/Magento/Framework/Filter/Template.php index 5d26447be6750..d5285f22ac479 100644 --- a/lib/internal/Magento/Framework/Filter/Template.php +++ b/lib/internal/Magento/Framework/Filter/Template.php @@ -76,7 +76,8 @@ class Template implements \Zend_Filter_Interface 'save', 'getcollection', 'getresource', - 'getconfig' + 'getconfig', + 'delete', ]; /** From f250993430971a588b20fc55deb31f4488eb3dc6 Mon Sep 17 00:00:00 2001 From: Andrii Meysar Date: Tue, 12 Mar 2019 14:05:52 +0200 Subject: [PATCH 093/773] MC-13894: Fixed incorrect email template rendering --- lib/internal/Magento/Framework/Filter/Test/Unit/TemplateTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/internal/Magento/Framework/Filter/Test/Unit/TemplateTest.php b/lib/internal/Magento/Framework/Filter/Test/Unit/TemplateTest.php index 605504d6e5ba4..cf1cf2958a648 100644 --- a/lib/internal/Magento/Framework/Filter/Test/Unit/TemplateTest.php +++ b/lib/internal/Magento/Framework/Filter/Test/Unit/TemplateTest.php @@ -438,6 +438,7 @@ public function disallowedMethods() ['getCollection'], ['getResource'], ['getConfig'], + ['delete'], ]; } } From 57e754d849a9640c8364bd32bd6cb14ec24accf8 Mon Sep 17 00:00:00 2001 From: Viktor Petryk Date: Wed, 13 Mar 2019 16:45:19 +0200 Subject: [PATCH 094/773] MC-6006: Invalid action behaviour --- .../Backend/Controller/Adminhtml/System/Design/Delete.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Backend/Controller/Adminhtml/System/Design/Delete.php b/app/code/Magento/Backend/Controller/Adminhtml/System/Design/Delete.php index 21f28188cf874..a669915bb7cd6 100644 --- a/app/code/Magento/Backend/Controller/Adminhtml/System/Design/Delete.php +++ b/app/code/Magento/Backend/Controller/Adminhtml/System/Design/Delete.php @@ -6,7 +6,9 @@ */ namespace Magento\Backend\Controller\Adminhtml\System\Design; -class Delete extends \Magento\Backend\Controller\Adminhtml\System\Design +use Magento\Framework\App\Action\HttpPostActionInterface; + +class Delete extends \Magento\Backend\Controller\Adminhtml\System\Design implements HttpPostActionInterface { /** * @return \Magento\Backend\Model\View\Result\Redirect From 25fd60e1339aebde35cc5a7e0a150354ff57ac4e Mon Sep 17 00:00:00 2001 From: Viktor Petryk Date: Fri, 15 Mar 2019 08:47:03 +0200 Subject: [PATCH 095/773] MC-6006: Invalid action behaviour --- app/code/Magento/Backend/Block/System/Design/Edit.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Backend/Block/System/Design/Edit.php b/app/code/Magento/Backend/Block/System/Design/Edit.php index 4d6c26e4cfe4b..d2d3035f62e3d 100644 --- a/app/code/Magento/Backend/Block/System/Design/Edit.php +++ b/app/code/Magento/Backend/Block/System/Design/Edit.php @@ -66,7 +66,7 @@ protected function _prepareLayout() 'label' => __('Delete'), 'onclick' => 'deleteConfirm(\'' . __( 'Are you sure?' - ) . '\', \'' . $this->getDeleteUrl() . '\')', + ) . '\', \'' . $this->getDeleteUrl() . '\', {data: {}})', 'class' => 'delete' ] ); From 1c3d10e05a3264c6f08575822d466e96e0d06a52 Mon Sep 17 00:00:00 2001 From: "Rav [RedChamps]" Date: Fri, 15 Mar 2019 16:01:50 +0530 Subject: [PATCH 096/773] added acl node --- app/code/Magento/Sales/view/base/ui_component/customer_form.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Sales/view/base/ui_component/customer_form.xml b/app/code/Magento/Sales/view/base/ui_component/customer_form.xml index ae965bb010c0b..788403f15570f 100644 --- a/app/code/Magento/Sales/view/base/ui_component/customer_form.xml +++ b/app/code/Magento/Sales/view/base/ui_component/customer_form.xml @@ -10,6 +10,6 @@ - + From 94510ed2654ab44909b906e446c3ace22d27f619 Mon Sep 17 00:00:00 2001 From: Yaroslav Rogoza Date: Sat, 16 Mar 2019 16:55:49 +0200 Subject: [PATCH 097/773] Added store id to the resolver context --- .../Model/Resolver/Category/SortFields.php | 30 ++++++++----------- .../Model/Resolver/Product/Price.php | 27 ++++++++++++----- .../Resolver/Product/ProductImage/Label.php | 23 +++++--------- .../GraphQl/Model/Query/Resolver/Context.php | 29 ++++++++++++++++++ .../Query/Resolver/ContextInterface.php | 15 ++++++++++ 5 files changed, 83 insertions(+), 41 deletions(-) diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Category/SortFields.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Category/SortFields.php index cb5553bb03701..fc8f6accbb226 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Resolver/Category/SortFields.php +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Category/SortFields.php @@ -7,6 +7,8 @@ namespace Magento\CatalogGraphQl\Model\Resolver\Category; +use Magento\Catalog\Model\Category\Attribute\Source\Sortby; +use Magento\Catalog\Model\Config; use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; use Magento\Framework\GraphQl\Config\Element\Field; use Magento\Framework\GraphQl\Query\ResolverInterface; @@ -17,32 +19,24 @@ class SortFields implements ResolverInterface { /** - * @var \Magento\Catalog\Model\Config + * @var Config */ private $catalogConfig; - - /** - * @var \Magento\Store\Model\StoreManagerInterface - */ - private $storeManager; - + /** - * @var \Magento\Catalog\Model\Category\Attribute\Source\Sortby + * @var Sortby */ private $sortbyAttributeSource; /** - * @param \Magento\Catalog\Model\Config $catalogConfig - * @param \Magento\Store\Model\StoreManagerInterface $storeManager - * @oaram \Magento\Catalog\Model\Category\Attribute\Source\Sortby $sortbyAttributeSource + * @param Config $catalogConfig + * @param Sortby $sortbyAttributeSource */ public function __construct( - \Magento\Catalog\Model\Config $catalogConfig, - \Magento\Store\Model\StoreManagerInterface $storeManager, - \Magento\Catalog\Model\Category\Attribute\Source\Sortby $sortbyAttributeSource + Config $catalogConfig, + Sortby $sortbyAttributeSource ) { $this->catalogConfig = $catalogConfig; - $this->storeManager = $storeManager; $this->sortbyAttributeSource = $sortbyAttributeSource; } @@ -52,6 +46,8 @@ public function __construct( public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null) { $sortFieldsOptions = $this->sortbyAttributeSource->getAllOptions(); + $storeId = $context->getStoreId(); + array_walk( $sortFieldsOptions, function (&$option) { @@ -59,10 +55,10 @@ function (&$option) { } ); $data = [ - 'default' => $this->catalogConfig->getProductListDefaultSortBy($this->storeManager->getStore()->getId()), + 'default' => $this->catalogConfig->getProductListDefaultSortBy($storeId), 'options' => $sortFieldsOptions, ]; - + return $data; } } diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/Price.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/Price.php index 55d930101fb60..4eb85fced8ab6 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/Price.php +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/Price.php @@ -7,14 +7,14 @@ namespace Magento\CatalogGraphQl\Model\Resolver\Product; -use Magento\Framework\Exception\LocalizedException; -use Magento\Framework\GraphQl\Query\Resolver\ContextInterface; -use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; use Magento\Catalog\Model\Product; use Magento\Catalog\Pricing\Price\FinalPrice; use Magento\Catalog\Pricing\Price\RegularPrice; +use Magento\Framework\Exception\LocalizedException; use Magento\Framework\GraphQl\Config\Element\Field; +use Magento\Framework\GraphQl\Query\Resolver\ContextInterface; use Magento\Framework\GraphQl\Query\ResolverInterface; +use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; use Magento\Framework\Pricing\Adjustment\AdjustmentInterface; use Magento\Framework\Pricing\Amount\AmountInterface; use Magento\Framework\Pricing\PriceInfo\Factory as PriceInfoFactory; @@ -80,11 +80,20 @@ public function resolve( $minimalPriceAmount = $finalPrice->getMinimalPrice(); $maximalPriceAmount = $finalPrice->getMaximalPrice(); $regularPriceAmount = $priceInfo->getPrice(RegularPrice::PRICE_CODE)->getAmount(); + $storeId = $context->getStoreId(); $prices = [ - 'minimalPrice' => $this->createAdjustmentsArray($priceInfo->getAdjustments(), $minimalPriceAmount), - 'regularPrice' => $this->createAdjustmentsArray($priceInfo->getAdjustments(), $regularPriceAmount), - 'maximalPrice' => $this->createAdjustmentsArray($priceInfo->getAdjustments(), $maximalPriceAmount) + 'minimalPrice' => $this->createAdjustmentsArray( + $priceInfo->getAdjustments(), + $minimalPriceAmount, + $storeId + ), + 'regularPrice' => $this->createAdjustmentsArray( + $priceInfo->getAdjustments(), + $regularPriceAmount, + $storeId + ), + 'maximalPrice' => $this->createAdjustmentsArray($priceInfo->getAdjustments(), $maximalPriceAmount, $storeId) ]; return $prices; @@ -95,12 +104,14 @@ public function resolve( * * @param AdjustmentInterface[] $adjustments * @param AmountInterface $amount + * @param int $storeId * @return array + * @throws \Magento\Framework\Exception\NoSuchEntityException */ - private function createAdjustmentsArray(array $adjustments, AmountInterface $amount) : array + private function createAdjustmentsArray(array $adjustments, AmountInterface $amount, int $storeId) : array { /** @var \Magento\Store\Model\Store $store */ - $store = $this->storeManager->getStore(); + $store = $this->storeManager->getStore($storeId); $priceArray = [ 'amount' => [ diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/ProductImage/Label.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/ProductImage/Label.php index f971e35742628..30de2f33c7da7 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/ProductImage/Label.php +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/ProductImage/Label.php @@ -13,7 +13,6 @@ use Magento\Framework\GraphQl\Config\Element\Field; use Magento\Framework\GraphQl\Query\ResolverInterface; use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; -use Magento\Store\Model\StoreManagerInterface; /** * Returns product's image label @@ -25,21 +24,13 @@ class Label implements ResolverInterface */ private $productResource; - /** - * @var StoreManagerInterface - */ - private $storeManager; - /** * @param ProductResourceModel $productResource - * @param StoreManagerInterface $storeManager */ public function __construct( - ProductResourceModel $productResource, - StoreManagerInterface $storeManager + ProductResourceModel $productResource ) { $this->productResource = $productResource; - $this->storeManager = $storeManager; } /** @@ -65,15 +56,16 @@ public function resolve( $imageType = $value['image_type']; $imagePath = $product->getData($imageType); $productId = (int)$product->getEntityId(); + $storeId = $context->getStoreId(); // null if image is not set if (null === $imagePath) { - return $this->getAttributeValue($productId, 'name'); + return $this->getAttributeValue($productId, 'name', $storeId); } - $imageLabel = $this->getAttributeValue($productId, $imageType . '_label'); + $imageLabel = $this->getAttributeValue($productId, $imageType . '_label', $storeId); if (null === $imageLabel) { - $imageLabel = $this->getAttributeValue($productId, 'name'); + $imageLabel = $this->getAttributeValue($productId, 'name', $storeId); } return $imageLabel; @@ -84,12 +76,11 @@ public function resolve( * * @param int $productId * @param string $attributeCode + * @param int $storeId * @return null|string Null if attribute value is not exists */ - private function getAttributeValue(int $productId, string $attributeCode): ?string + private function getAttributeValue(int $productId, string $attributeCode, int $storeId): ?string { - $storeId = $this->storeManager->getStore()->getId(); - $value = $this->productResource->getAttributeRawValue($productId, $attributeCode, $storeId); return is_array($value) && empty($value) ? null : $value; } diff --git a/app/code/Magento/GraphQl/Model/Query/Resolver/Context.php b/app/code/Magento/GraphQl/Model/Query/Resolver/Context.php index 1eae619967ef5..b222689ed6b96 100644 --- a/app/code/Magento/GraphQl/Model/Query/Resolver/Context.php +++ b/app/code/Magento/GraphQl/Model/Query/Resolver/Context.php @@ -11,6 +11,7 @@ use Magento\Framework\Api\AttributeValueFactory; use Magento\Framework\Api\ExtensionAttributesFactory; use Magento\Framework\GraphQl\Query\Resolver\ContextInterface; +use Magento\Store\Model\StoreManagerInterface; /** * Concrete implementation for @see ContextInterface @@ -25,8 +26,14 @@ class Context extends \Magento\Framework\Model\AbstractExtensibleModel implement */ const USER_TYPE_ID = 'user_type'; const USER_ID = 'user_id'; + const STORE_ID = 'store_id'; /**#@-*/ + /** + * @var StoreManagerInterface + */ + private $storeManager; + /** * @var UserContextInterface */ @@ -38,6 +45,7 @@ class Context extends \Magento\Framework\Model\AbstractExtensibleModel implement * @param ExtensionAttributesFactory $extensionFactory * @param AttributeValueFactory $customAttributeFactory * @param UserContextInterface|null $userContext + * @param StoreManagerInterface $storeManager * @param array $data */ public function __construct( @@ -46,6 +54,7 @@ public function __construct( ExtensionAttributesFactory $extensionFactory, AttributeValueFactory $customAttributeFactory, UserContextInterface $userContext, + StoreManagerInterface $storeManager, array $data = [] ) { parent::__construct( @@ -61,6 +70,7 @@ public function __construct( $this->setId($data['type']); } $this->userContext = $userContext; + $this->storeManager = $storeManager; } /** @@ -122,4 +132,23 @@ public function setUserType(int $typeId) : ContextInterface { return $this->setData(self::USER_TYPE_ID, $typeId); } + + /** + * @inheritDoc + */ + public function getStoreId(): int + { + if (!$this->getData(self::STORE_ID)) { + $this->setStoreId($this->storeManager->getStore()->getId()); + } + return (int) $this->getData(self::STORE_ID); + } + + /** + * @inheritDoc + */ + public function setStoreId(int $storeId) : ContextInterface + { + return $this->setData(self::STORE_ID, $storeId); + } } diff --git a/lib/internal/Magento/Framework/GraphQl/Query/Resolver/ContextInterface.php b/lib/internal/Magento/Framework/GraphQl/Query/Resolver/ContextInterface.php index 9bf708539ef07..92726033a14c6 100644 --- a/lib/internal/Magento/Framework/GraphQl/Query/Resolver/ContextInterface.php +++ b/lib/internal/Magento/Framework/GraphQl/Query/Resolver/ContextInterface.php @@ -52,6 +52,21 @@ public function getUserId() : int; */ public function setUserId(int $userId) : ContextInterface; + /** + * Get current store id + * + * @return int + */ + public function getStoreId() : int; + + /** + * Set current store id + * + * @param int $storeId + * @return ContextInterface + */ + public function setStoreId(int $storeId) : ContextInterface; + /** * Retrieve existing extension attributes object or create a new one. * From 1f744db6808886384d4f8233447c0c63baba285b Mon Sep 17 00:00:00 2001 From: Stas Kozar Date: Mon, 18 Mar 2019 10:26:10 +0200 Subject: [PATCH 098/773] MC-5859: Fix action behavior --- app/code/Magento/Sales/Controller/Guest/View.php | 8 ++++++-- .../testsuite/Magento/Sales/Controller/Guest/FormTest.php | 1 + 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Sales/Controller/Guest/View.php b/app/code/Magento/Sales/Controller/Guest/View.php index 9e96a15ed2c12..185369dd6ed80 100644 --- a/app/code/Magento/Sales/Controller/Guest/View.php +++ b/app/code/Magento/Sales/Controller/Guest/View.php @@ -9,8 +9,12 @@ use Magento\Sales\Helper\Guest as GuestHelper; use Magento\Framework\View\Result\PageFactory; use Magento\Framework\Controller\ResultInterface; +use Magento\Framework\App\Action\HttpPostActionInterface as HttpPostActionInterface; -class View extends Action\Action +/** + * Guest order view action. + */ +class View extends Action\Action implements HttpPostActionInterface { /** * @var \Magento\Sales\Helper\Guest @@ -38,7 +42,7 @@ public function __construct( } /** - * @return \Magento\Framework\Controller\ResultInterface + * @inheritdoc */ public function execute() { diff --git a/dev/tests/integration/testsuite/Magento/Sales/Controller/Guest/FormTest.php b/dev/tests/integration/testsuite/Magento/Sales/Controller/Guest/FormTest.php index 1067a474e19aa..80dfc17f522f1 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/Controller/Guest/FormTest.php +++ b/dev/tests/integration/testsuite/Magento/Sales/Controller/Guest/FormTest.php @@ -40,6 +40,7 @@ public function testViewOrderAsGuest() public function testViewOrderAsLoggedIn() { $this->login(1); + $this->getRequest()->setMethod(Request::METHOD_POST); $this->dispatch('sales/guest/view/'); $this->assertRedirect($this->stringContains('sales/order/history/')); } From 53b6b79cfec57341e2bad7d01970a6b157a9cd0d Mon Sep 17 00:00:00 2001 From: Viktor Petryk Date: Mon, 18 Mar 2019 11:28:33 +0200 Subject: [PATCH 099/773] MC-14816: Invalid action behaviour --- app/code/Magento/Review/Block/Adminhtml/Edit.php | 2 +- .../Magento/Review/Controller/Adminhtml/Product/Delete.php | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Review/Block/Adminhtml/Edit.php b/app/code/Magento/Review/Block/Adminhtml/Edit.php index f6f0ccef9b4e7..c75d4612f3d9f 100644 --- a/app/code/Magento/Review/Block/Adminhtml/Edit.php +++ b/app/code/Magento/Review/Block/Adminhtml/Edit.php @@ -168,7 +168,7 @@ protected function _construct() ) . '\', ' . '\'' . $this->getUrl( '*/*/delete', [$this->_objectId => $this->getRequest()->getParam($this->_objectId), 'ret' => 'pending'] - ) . '\'' . ')' + ) . '\', {data: {}})' ); $this->_coreRegistry->register('ret', 'pending'); } diff --git a/app/code/Magento/Review/Controller/Adminhtml/Product/Delete.php b/app/code/Magento/Review/Controller/Adminhtml/Product/Delete.php index 75015d65e1a18..c35a30bd92b11 100644 --- a/app/code/Magento/Review/Controller/Adminhtml/Product/Delete.php +++ b/app/code/Magento/Review/Controller/Adminhtml/Product/Delete.php @@ -7,8 +7,9 @@ use Magento\Review\Controller\Adminhtml\Product as ProductController; use Magento\Framework\Controller\ResultFactory; +use Magento\Framework\App\Action\HttpPostActionInterface; -class Delete extends ProductController +class Delete extends ProductController implements HttpPostActionInterface { /** * @return \Magento\Backend\Model\View\Result\Redirect From e34ea9586c34b76da37a7a669ff7b5a8c9b121d3 Mon Sep 17 00:00:00 2001 From: Serhii Voloshkov Date: Mon, 18 Mar 2019 12:41:59 +0200 Subject: [PATCH 100/773] MC-5870: Product Widget Chooser minor changes --- .../Adminhtml/Product/Widget/Chooser.php | 32 +++++++++++++------ 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Widget/Chooser.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Widget/Chooser.php index 933b5eaafbb39..113b048f7c98b 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Widget/Chooser.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Widget/Chooser.php @@ -1,12 +1,17 @@ resultRawFactory = $resultRawFactory; $this->layoutFactory = $layoutFactory; + $this->escaper = $escaper ?: ObjectManager::getInstance()->get(\Magento\Framework\Escaper::class); } /** - * Chooser Source action + * Chooser Source action. * * @return \Magento\Framework\Controller\Result\Raw */ @@ -55,11 +68,11 @@ public function execute() '', [ 'data' => [ - 'id' => $uniqId, + 'id' => $this->escaper->escapeHtml($uniqId), 'use_massaction' => $massAction, 'product_type_id' => $productTypeId, - 'category_id' => $this->getRequest()->getParam('category_id'), - ] + 'category_id' => (int)$this->getRequest()->getParam('category_id'), + ], ] ); @@ -71,10 +84,10 @@ public function execute() '', [ 'data' => [ - 'id' => $uniqId . 'Tree', + 'id' => $this->escaper->escapeHtml($uniqId) . 'Tree', 'node_click_listener' => $productsGrid->getCategoryClickListenerJs(), 'with_empty_node' => true, - ] + ], ] ); @@ -86,6 +99,7 @@ public function execute() /** @var \Magento\Framework\Controller\Result\Raw $resultRaw */ $resultRaw = $this->resultRawFactory->create(); + return $resultRaw->setContents($html); } } From e71c2a8014ca338e204419f08aafd493312d7d34 Mon Sep 17 00:00:00 2001 From: Viktor Petryk Date: Mon, 18 Mar 2019 14:23:14 +0200 Subject: [PATCH 101/773] MC-14816: Invalid action behaviour --- .../Magento/Review/Controller/Adminhtml/Product/Delete.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/code/Magento/Review/Controller/Adminhtml/Product/Delete.php b/app/code/Magento/Review/Controller/Adminhtml/Product/Delete.php index c35a30bd92b11..955706e124c15 100644 --- a/app/code/Magento/Review/Controller/Adminhtml/Product/Delete.php +++ b/app/code/Magento/Review/Controller/Adminhtml/Product/Delete.php @@ -9,9 +9,14 @@ use Magento\Framework\Controller\ResultFactory; use Magento\Framework\App\Action\HttpPostActionInterface; +/** + * Delete review action. + */ class Delete extends ProductController implements HttpPostActionInterface { /** + * Execute action. + * * @return \Magento\Backend\Model\View\Result\Redirect */ public function execute() From 8f18707bacc825da2759670a58924ca707945efc Mon Sep 17 00:00:00 2001 From: Serhii Voloshkov Date: Mon, 18 Mar 2019 14:31:32 +0200 Subject: [PATCH 102/773] MC-6009: User Role minor changes --- app/code/Magento/User/Block/Buttons.php | 2 +- .../Controller/Adminhtml/User/Role/Delete.php | 19 +- .../Adminhtml/User/Role/DeleteTest.php | 314 ++++++++++++++++++ 3 files changed, 329 insertions(+), 6 deletions(-) create mode 100644 app/code/Magento/User/Test/Unit/Controller/Adminhtml/User/Role/DeleteTest.php diff --git a/app/code/Magento/User/Block/Buttons.php b/app/code/Magento/User/Block/Buttons.php index f580c5cd72b9b..f39aadd41686e 100644 --- a/app/code/Magento/User/Block/Buttons.php +++ b/app/code/Magento/User/Block/Buttons.php @@ -68,7 +68,7 @@ protected function _prepareLayout() ) . '\', \'' . $this->getUrl( '*/*/delete', ['rid' => $this->getRequest()->getParam('rid')] - ) . '\')', + ) . '\', {data: {}})', 'class' => 'delete' ] ); diff --git a/app/code/Magento/User/Controller/Adminhtml/User/Role/Delete.php b/app/code/Magento/User/Controller/Adminhtml/User/Role/Delete.php index 194e730aedfa7..b1064efc7a324 100644 --- a/app/code/Magento/User/Controller/Adminhtml/User/Role/Delete.php +++ b/app/code/Magento/User/Controller/Adminhtml/User/Role/Delete.php @@ -6,30 +6,39 @@ */ namespace Magento\User\Controller\Adminhtml\User\Role; +use Magento\Framework\App\Action\HttpPostActionInterface; use Magento\Framework\Controller\ResultFactory; -class Delete extends \Magento\User\Controller\Adminhtml\User\Role +/** + * User roles delete action. + */ +class Delete extends \Magento\User\Controller\Adminhtml\User\Role implements HttpPostActionInterface { /** - * Remove role action + * Remove role action. * - * @return \Magento\Backend\Model\View\Result\Redirect|void + * @return \Magento\Backend\Model\View\Result\Redirect */ public function execute() { /** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */ $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT); - $rid = $this->getRequest()->getParam('rid', false); + $rid = (int)$this->getRequest()->getParam('rid', false); /** @var \Magento\User\Model\User $currentUser */ $currentUser = $this->_userFactory->create()->setId($this->_authSession->getUser()->getId()); if (in_array($rid, $currentUser->getRoles())) { $this->messageManager->addError(__('You cannot delete self-assigned roles.')); + return $resultRedirect->setPath('adminhtml/*/editrole', ['rid' => $rid]); } try { - $this->_initRole()->delete(); + $role = $this->_initRole(); + if (!$role->getId()) { + throw new \Exception(); + } + $role->delete(); $this->messageManager->addSuccess(__('You deleted the role.')); } catch (\Exception $e) { $this->messageManager->addError(__('An error occurred while deleting this role.')); diff --git a/app/code/Magento/User/Test/Unit/Controller/Adminhtml/User/Role/DeleteTest.php b/app/code/Magento/User/Test/Unit/Controller/Adminhtml/User/Role/DeleteTest.php new file mode 100644 index 0000000000000..33702068d3448 --- /dev/null +++ b/app/code/Magento/User/Test/Unit/Controller/Adminhtml/User/Role/DeleteTest.php @@ -0,0 +1,314 @@ +contextMock = $this->createMock(\Magento\Backend\App\Action\Context::class); + $this->coreRegistryMock = $this->createPartialMock(\Magento\Framework\Registry::class, ['getId']); + $this->roleFactoryMock = $this->createMock(\Magento\Authorization\Model\RoleFactory::class); + $this->userFactoryMock = $this->createPartialMock( + \Magento\User\Model\UserFactory::class, + ['create'] + ); + $this->rulesFactoryMock = $this->createMock(\Magento\Authorization\Model\RulesFactory::class); + $this->authSessionMock = $this->createPartialMock( + \Magento\Backend\Model\Auth\Session::class, + ['getUser'] + ); + $this->filterManagerMock = $this->createMock(\Magento\Framework\Filter\FilterManager::class); + $this->resultRedirectMock = $this->createPartialMock( + \Magento\Backend\Model\View\Result\Redirect::class, + ['setPath'] + ); + $this->resultFactoryMock = $this->createPartialMock( + \Magento\Framework\Controller\ResultFactory::class, + ['create'] + ); + + $this->resultFactoryMock->expects($this->atLeastOnce()) + ->method('create') + ->willReturn($this->resultRedirectMock); + $this->requestMock = $this->getMockForAbstractClass( + \Magento\Framework\App\RequestInterface::class, + [], + '', + false, + true, + true, + ['getParam'] + ); + $this->contextMock->expects($this->once()) + ->method('getResultFactory') + ->willReturn($this->resultFactoryMock); + $this->resultFactoryMock->expects($this->once()) + ->method('create') + ->with(\Magento\Framework\Controller\ResultFactory::TYPE_REDIRECT, []) + ->willReturn($this->resultRedirectMock); + + $this->messageManagerMock = $this->createMock(\Magento\Framework\Message\Manager::class); + $this->contextMock->expects($this->once()) + ->method('getMessageManager') + ->willReturn($this->messageManagerMock); + + $this->contextMock->expects($this->once())->method('getRequest')->willReturn($this->requestMock); + + $this->roleModelMock = $this->createPartialMock( + \Magento\Authorization\Model\Role::class, + ['load', 'getId', 'getRoleType', 'delete'] + ); + + $this->controller = $objectManagerHelper->getObject( + \Magento\User\Controller\Adminhtml\User\Role\Delete::class, + [ + 'context' => $this->contextMock, + 'coreRegistry' => $this->coreRegistryMock, + 'roleFactory' => $this->roleFactoryMock, + 'userFactory' => $this->userFactoryMock, + 'rulesFactory' => $this->rulesFactoryMock, + 'authSession' => $this->authSessionMock, + 'filterManager' => $this->filterManagerMock, + ] + ); + } + + /** + * Unit test which trying to delete role which assigned on current user. + * + * @return void + */ + public function testExecuteDeleteSelfAssignedRole() + { + $idUser = 1; + $idUserRole = 3; + $idDeleteRole = 3; + + $this->checkUserAndRoleIds($idDeleteRole, $idUser, $idUserRole); + + $this->messageManagerMock->expects($this->once()) + ->method('addError') + ->with(__('You cannot delete self-assigned roles.')) + ->willReturnSelf(); + + $this->resultRedirectMock->expects($this->once()) + ->method('setPath') + ->with('adminhtml/*/editrole', ['rid' => $idDeleteRole]) + ->willReturnSelf(); + + $this->controller->execute(); + } + + /** + * Unit test which trying to delete role. + * + * @return void + */ + public function testExecuteDeleteWithNormalScenario() + { + $idUser = 1; + $idUserRole = 3; + $idDeleteRole = 5; + $roleType = 'G'; + + $this->checkUserAndRoleIds($idDeleteRole, $idUser, $idUserRole); + + $this->initRoleExecute($roleType); + $this->roleModelMock->expects($this->exactly(2))->method('getId')->willReturn($idDeleteRole); + + $this->roleModelMock->expects($this->once())->method('delete')->willReturnSelf(); + + $this->messageManagerMock->expects($this->once()) + ->method('addSuccess') + ->with(__('You deleted the role.')) + ->willReturnSelf(); + + $this->resultRedirectMock->expects($this->once()) + ->method('setPath') + ->with('*/*/') + ->willReturnSelf(); + + $this->controller->execute(); + } + + /** + * Unit test which failed on delete role. + * + * @return void + */ + public function testExecuteDeleteWithError() + { + $idUser = 1; + $idUserRole = 3; + $idDeleteRole = 5; + $roleType = 'G'; + + $this->checkUserAndRoleIds($idDeleteRole, $idUser, $idUserRole); + + $this->initRoleExecute($roleType); + $this->roleModelMock->expects($this->exactly(2))->method('getId')->willReturn($idDeleteRole); + + $this->roleModelMock->expects($this->once())->method('delete')->willThrowException(new \Exception); + + $this->messageManagerMock->expects($this->once()) + ->method('addError') + ->with(__('An error occurred while deleting this role.')) + ->willReturnSelf(); + + $this->resultRedirectMock->expects($this->once()) + ->method('setPath') + ->with('*/*/') + ->willReturnSelf(); + + $this->controller->execute(); + } + + /** + * Unit test which trying to delete nonexistent role. + * + * @return void + */ + public function testExecuteWithoutRole() + { + $idUser = 1; + $idUserRole = 3; + $idDeleteRole = 100; + $roleType = null; + + $this->checkUserAndRoleIds($idDeleteRole, $idUser, $idUserRole); + + $this->initRoleExecute($roleType); + $this->roleModelMock->expects($this->at(1))->method('getId')->willReturn($idDeleteRole); + $this->roleModelMock->expects($this->at(2))->method('getId')->willReturn(null); + + $this->messageManagerMock->expects($this->once()) + ->method('addError') + ->with(__('An error occurred while deleting this role.')) + ->willReturnSelf(); + + $this->resultRedirectMock->expects($this->once()) + ->method('setPath') + ->with('*/*/') + ->willReturnSelf(); + + $this->controller->execute(); + } + + /** + * Method which takes Id from request and check with User Role Id. + * + * @param int $id + * @param int $userId + * @param int $userRoleId + * @return void + */ + private function checkUserAndRoleIds(int $id, int $userId, int $userRoleId) + { + $this->requestMock->expects($this->atLeastOnce())->method('getParam')->with('rid')->willReturn($id); + + $userModelMock = $this->createPartialMock(\Magento\User\Model\User::class, ['getId', 'setId', 'getRoles']); + $this->authSessionMock->expects($this->once())->method('getUser')->willReturn($userModelMock); + $userModelMock->expects($this->once())->method('getId')->willReturn($userId); + + $this->userFactoryMock->expects($this->once())->method('create')->willReturn($userModelMock); + $userModelMock->expects($this->once())->method('setId')->with($userId)->willReturnSelf(); + + $userModelMock->expects($this->once())->method('getRoles')->willReturn(['id' => $userRoleId]); + } + + /** + * Execute initialization Role. + * + * @param string|null $roleType + * @return void + */ + private function initRoleExecute($roleType) + { + $this->roleFactoryMock->expects($this->once())->method('create')->willReturn($this->roleModelMock); + $this->roleModelMock->expects($this->once())->method('load')->willReturnSelf(); + $this->roleModelMock->expects($this->once())->method('getRoleType')->willReturn($roleType); + } +} From 92d9a70f145cc9d4c2c599de0468fd8e619dced6 Mon Sep 17 00:00:00 2001 From: Viktor Petryk Date: Mon, 18 Mar 2019 15:18:51 +0200 Subject: [PATCH 103/773] MC-6006: Invalid action behaviour --- .../Backend/Block/System/Design/Edit.php | 19 ++++++++++++++++++- .../Adminhtml/System/Design/Delete.php | 6 +++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Backend/Block/System/Design/Edit.php b/app/code/Magento/Backend/Block/System/Design/Edit.php index d2d3035f62e3d..a0cbe4b640d97 100644 --- a/app/code/Magento/Backend/Block/System/Design/Edit.php +++ b/app/code/Magento/Backend/Block/System/Design/Edit.php @@ -5,6 +5,9 @@ */ namespace Magento\Backend\Block\System\Design; +/** + * Edit store design schedule block. + */ class Edit extends \Magento\Backend\Block\Widget { /** @@ -20,6 +23,8 @@ class Edit extends \Magento\Backend\Block\Widget protected $_coreRegistry = null; /** + * @inheritdoc + * * @param \Magento\Backend\Block\Template\Context $context * @param \Magento\Framework\Registry $registry * @param array $data @@ -34,6 +39,8 @@ public function __construct( } /** + * @inheritdoc + * * @return void */ protected function _construct() @@ -44,7 +51,7 @@ protected function _construct() } /** - * {@inheritdoc} + * @inheritdoc */ protected function _prepareLayout() { @@ -88,6 +95,8 @@ protected function _prepareLayout() } /** + * Return design change Id. + * * @return string */ public function getDesignChangeId() @@ -96,6 +105,8 @@ public function getDesignChangeId() } /** + * Return delete url. + * * @return string */ public function getDeleteUrl() @@ -104,6 +115,8 @@ public function getDeleteUrl() } /** + * Return save url for edit form. + * * @return string */ public function getSaveUrl() @@ -112,6 +125,8 @@ public function getSaveUrl() } /** + * Return validation url for edit form. + * * @return string */ public function getValidationUrl() @@ -120,6 +135,8 @@ public function getValidationUrl() } /** + * Return page header. + * * @return string */ public function getHeader() diff --git a/app/code/Magento/Backend/Controller/Adminhtml/System/Design/Delete.php b/app/code/Magento/Backend/Controller/Adminhtml/System/Design/Delete.php index a669915bb7cd6..335ff3bf85e7a 100644 --- a/app/code/Magento/Backend/Controller/Adminhtml/System/Design/Delete.php +++ b/app/code/Magento/Backend/Controller/Adminhtml/System/Design/Delete.php @@ -1,6 +1,5 @@ Date: Mon, 18 Mar 2019 15:04:45 -0500 Subject: [PATCH 104/773] MC-5844: Coupon Requests Limiter --- app/code/Magento/Captcha/CustomerData/Captcha.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Captcha/CustomerData/Captcha.php b/app/code/Magento/Captcha/CustomerData/Captcha.php index e9e332f8b146f..e07bf953abaa3 100644 --- a/app/code/Magento/Captcha/CustomerData/Captcha.php +++ b/app/code/Magento/Captcha/CustomerData/Captcha.php @@ -46,7 +46,7 @@ class Captcha extends DataObject implements SectionSourceInterface public function __construct( CaptchaHelper $helper, array $formIds, - array $data =[], + array $data = [], ?CustomerSession $customerSession = null ) { $this->helper = $helper; From 7f200632fe1826d550cc4bd6cf93a1b64bcbbcb5 Mon Sep 17 00:00:00 2001 From: Serhii Voloshkov Date: Tue, 19 Mar 2019 13:56:02 +0200 Subject: [PATCH 105/773] MC-6009: User Role minor changes --- .../User/Controller/Adminhtml/User/Role/Delete.php | 10 ++++++---- .../Unit/Controller/Adminhtml/User/Role/DeleteTest.php | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/User/Controller/Adminhtml/User/Role/Delete.php b/app/code/Magento/User/Controller/Adminhtml/User/Role/Delete.php index b1064efc7a324..7997d96945784 100644 --- a/app/code/Magento/User/Controller/Adminhtml/User/Role/Delete.php +++ b/app/code/Magento/User/Controller/Adminhtml/User/Role/Delete.php @@ -32,12 +32,14 @@ public function execute() return $resultRedirect->setPath('adminhtml/*/editrole', ['rid' => $rid]); } + $role = $this->_initRole(); + if (!$role->getId()) { + $this->messageManager->addError(__('We can\'t find a role to delete.')); + + return $resultRedirect->setPath("*/*/"); + } try { - $role = $this->_initRole(); - if (!$role->getId()) { - throw new \Exception(); - } $role->delete(); $this->messageManager->addSuccess(__('You deleted the role.')); } catch (\Exception $e) { diff --git a/app/code/Magento/User/Test/Unit/Controller/Adminhtml/User/Role/DeleteTest.php b/app/code/Magento/User/Test/Unit/Controller/Adminhtml/User/Role/DeleteTest.php index 33702068d3448..7780c43ecaf16 100644 --- a/app/code/Magento/User/Test/Unit/Controller/Adminhtml/User/Role/DeleteTest.php +++ b/app/code/Magento/User/Test/Unit/Controller/Adminhtml/User/Role/DeleteTest.php @@ -266,7 +266,7 @@ public function testExecuteWithoutRole() $this->messageManagerMock->expects($this->once()) ->method('addError') - ->with(__('An error occurred while deleting this role.')) + ->with(__('We can\'t find a role to delete.')) ->willReturnSelf(); $this->resultRedirectMock->expects($this->once()) From e3e65a43c721767993cd5214445150badef57a9f Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky Date: Tue, 19 Mar 2019 14:15:15 +0200 Subject: [PATCH 106/773] ENGCOM-4126: Health index fix. --- app/code/Magento/Sales/Block/Adminhtml/ShoppingCartsTab.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Sales/Block/Adminhtml/ShoppingCartsTab.php b/app/code/Magento/Sales/Block/Adminhtml/ShoppingCartsTab.php index 371f109bb0493..d0d2fef1f1d42 100644 --- a/app/code/Magento/Sales/Block/Adminhtml/ShoppingCartsTab.php +++ b/app/code/Magento/Sales/Block/Adminhtml/ShoppingCartsTab.php @@ -22,7 +22,7 @@ class ShoppingCartsTab extends TabWrapper * * @var Registry */ - protected $coreRegistry = null; + private $coreRegistry; /** * @var bool From 3d2654e4d13b68ffbb7c70266a12412344020edb Mon Sep 17 00:00:00 2001 From: Yaroslav Rogoza Date: Wed, 20 Mar 2019 11:17:03 +0100 Subject: [PATCH 107/773] Further refactoring --- .../Model/Customer/CreateCustomerAccount.php | 11 ++++-- .../Model/Customer/UpdateCustomerAccount.php | 15 ++------ .../Model/Resolver/CreateCustomer.php | 2 +- .../Model/Resolver/UpdateCustomer.php | 2 +- .../Store/StoreConfigDataProvider.php | 20 ++++++---- .../Model/Resolver/StoreConfigResolver.php | 2 +- .../Model/Resolver/EntityUrl.php | 37 ++++++++----------- 7 files changed, 42 insertions(+), 47 deletions(-) diff --git a/app/code/Magento/CustomerGraphQl/Model/Customer/CreateCustomerAccount.php b/app/code/Magento/CustomerGraphQl/Model/Customer/CreateCustomerAccount.php index b7b66df042467..285c76874cad4 100644 --- a/app/code/Magento/CustomerGraphQl/Model/Customer/CreateCustomerAccount.php +++ b/app/code/Magento/CustomerGraphQl/Model/Customer/CreateCustomerAccount.php @@ -70,13 +70,14 @@ public function __construct( * Creates new customer account * * @param array $data + * @param int $storeId * @return CustomerInterface * @throws GraphQlInputException */ - public function execute(array $data): CustomerInterface + public function execute(array $data, int $storeId): CustomerInterface { try { - $customer = $this->createAccount($data); + $customer = $this->createAccount($data, $storeId); } catch (LocalizedException $e) { throw new GraphQlInputException(__($e->getMessage())); } @@ -91,10 +92,12 @@ public function execute(array $data): CustomerInterface * Create account * * @param array $data + * @param int $storeId * @return CustomerInterface * @throws LocalizedException + * @throws \Magento\Framework\Exception\NoSuchEntityException */ - private function createAccount(array $data): CustomerInterface + private function createAccount(array $data, int $storeId): CustomerInterface { $customerDataObject = $this->customerFactory->create(); $this->dataObjectHelper->populateWithArray( @@ -102,7 +105,7 @@ private function createAccount(array $data): CustomerInterface $data, CustomerInterface::class ); - $store = $this->storeManager->getStore(); + $store = $this->storeManager->getStore($storeId); $customerDataObject->setWebsiteId($store->getWebsiteId()); $customerDataObject->setStoreId($store->getId()); diff --git a/app/code/Magento/CustomerGraphQl/Model/Customer/UpdateCustomerAccount.php b/app/code/Magento/CustomerGraphQl/Model/Customer/UpdateCustomerAccount.php index 8601d586b3c95..236320b9390de 100644 --- a/app/code/Magento/CustomerGraphQl/Model/Customer/UpdateCustomerAccount.php +++ b/app/code/Magento/CustomerGraphQl/Model/Customer/UpdateCustomerAccount.php @@ -10,7 +10,6 @@ use Magento\Framework\GraphQl\Exception\GraphQlAlreadyExistsException; use Magento\Framework\GraphQl\Exception\GraphQlAuthenticationException; use Magento\Framework\GraphQl\Exception\GraphQlInputException; -use Magento\Store\Model\StoreManagerInterface; use Magento\Customer\Api\Data\CustomerInterface; use Magento\Framework\Api\DataObjectHelper; @@ -24,11 +23,6 @@ class UpdateCustomerAccount */ private $saveCustomer; - /** - * @var StoreManagerInterface - */ - private $storeManager; - /** * @var CheckCustomerPassword */ @@ -51,7 +45,6 @@ class UpdateCustomerAccount /** * @param SaveCustomer $saveCustomer - * @param StoreManagerInterface $storeManager * @param CheckCustomerPassword $checkCustomerPassword * @param DataObjectHelper $dataObjectHelper * @param ChangeSubscriptionStatus $changeSubscriptionStatus @@ -59,14 +52,12 @@ class UpdateCustomerAccount */ public function __construct( SaveCustomer $saveCustomer, - StoreManagerInterface $storeManager, CheckCustomerPassword $checkCustomerPassword, DataObjectHelper $dataObjectHelper, ChangeSubscriptionStatus $changeSubscriptionStatus, array $restrictedKeys = [] ) { $this->saveCustomer = $saveCustomer; - $this->storeManager = $storeManager; $this->checkCustomerPassword = $checkCustomerPassword; $this->dataObjectHelper = $dataObjectHelper; $this->restrictedKeys = $restrictedKeys; @@ -78,12 +69,14 @@ public function __construct( * * @param CustomerInterface $customer * @param array $data + * @param int $storeId * @return void * @throws GraphQlAlreadyExistsException * @throws GraphQlAuthenticationException * @throws GraphQlInputException + * @throws \Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException */ - public function execute(CustomerInterface $customer, array $data): void + public function execute(CustomerInterface $customer, array $data, int $storeId): void { if (isset($data['email']) && $customer->getEmail() !== $data['email']) { if (!isset($data['password']) || empty($data['password'])) { @@ -97,7 +90,7 @@ public function execute(CustomerInterface $customer, array $data): void $filteredData = array_diff_key($data, array_flip($this->restrictedKeys)); $this->dataObjectHelper->populateWithArray($customer, $filteredData, CustomerInterface::class); - $customer->setStoreId($this->storeManager->getStore()->getId()); + $customer->setStoreId($storeId); $this->saveCustomer->execute($customer); diff --git a/app/code/Magento/CustomerGraphQl/Model/Resolver/CreateCustomer.php b/app/code/Magento/CustomerGraphQl/Model/Resolver/CreateCustomer.php index 1ae22bcc12792..ca82d7062b0f8 100644 --- a/app/code/Magento/CustomerGraphQl/Model/Resolver/CreateCustomer.php +++ b/app/code/Magento/CustomerGraphQl/Model/Resolver/CreateCustomer.php @@ -56,7 +56,7 @@ public function resolve( throw new GraphQlInputException(__('"input" value should be specified')); } - $customer = $this->createCustomerAccount->execute($args['input']); + $customer = $this->createCustomerAccount->execute($args['input'], $context->getStoreId()); $context->setUserId((int)$customer->getId()); $context->setUserType(UserContextInterface::USER_TYPE_CUSTOMER); diff --git a/app/code/Magento/CustomerGraphQl/Model/Resolver/UpdateCustomer.php b/app/code/Magento/CustomerGraphQl/Model/Resolver/UpdateCustomer.php index 7e06a2a063b4b..bf13f95e10e0d 100644 --- a/app/code/Magento/CustomerGraphQl/Model/Resolver/UpdateCustomer.php +++ b/app/code/Magento/CustomerGraphQl/Model/Resolver/UpdateCustomer.php @@ -65,7 +65,7 @@ public function resolve( } $customer = $this->getCustomer->execute($context); - $this->updateCustomerAccount->execute($customer, $args['input']); + $this->updateCustomerAccount->execute($customer, $args['input'], $context->getStoreId()); $data = $this->extractCustomerData->execute($customer); return ['customer' => $data]; diff --git a/app/code/Magento/StoreGraphQl/Model/Resolver/Store/StoreConfigDataProvider.php b/app/code/Magento/StoreGraphQl/Model/Resolver/Store/StoreConfigDataProvider.php index 8c2d6c36591d5..c101a33adfdbc 100644 --- a/app/code/Magento/StoreGraphQl/Model/Resolver/Store/StoreConfigDataProvider.php +++ b/app/code/Magento/StoreGraphQl/Model/Resolver/Store/StoreConfigDataProvider.php @@ -58,13 +58,15 @@ public function __construct( /** * Get store config data * + * @param int $storeId * @return array + * @throws \Magento\Framework\Exception\NoSuchEntityException */ - public function getStoreConfigData(): array + public function getStoreConfigData(int $storeId): array { $storeConfigData = array_merge( - $this->getBaseConfigData(), - $this->getExtendedConfigData() + $this->getBaseConfigData($storeId), + $this->getExtendedConfigData($storeId) ); return $storeConfigData; } @@ -72,11 +74,13 @@ public function getStoreConfigData(): array /** * Get base config data * + * @param int $storeId * @return array + * @throws \Magento\Framework\Exception\NoSuchEntityException */ - private function getBaseConfigData() : array + private function getBaseConfigData(int $storeId) : array { - $store = $this->storeManager->getStore(); + $store = $this->storeManager->getStore($storeId); $storeConfig = current($this->storeConfigManager->getStoreConfigs([$store->getCode()])); $storeConfigData = [ @@ -103,17 +107,17 @@ private function getBaseConfigData() : array /** * Get extended config data * + * @param int $storeId * @return array */ - private function getExtendedConfigData() + private function getExtendedConfigData(int $storeId) { - $store = $this->storeManager->getStore(); $extendedConfigData = []; foreach ($this->extendedConfigData as $key => $path) { $extendedConfigData[$key] = $this->scopeConfig->getValue( $path, ScopeInterface::SCOPE_STORE, - $store->getId() + $storeId ); } return $extendedConfigData; diff --git a/app/code/Magento/StoreGraphQl/Model/Resolver/StoreConfigResolver.php b/app/code/Magento/StoreGraphQl/Model/Resolver/StoreConfigResolver.php index 9c426172de85d..da183a30e015c 100644 --- a/app/code/Magento/StoreGraphQl/Model/Resolver/StoreConfigResolver.php +++ b/app/code/Magento/StoreGraphQl/Model/Resolver/StoreConfigResolver.php @@ -41,6 +41,6 @@ public function resolve( array $value = null, array $args = null ) { - return $this->storeConfigDataProvider->getStoreConfigData(); + return $this->storeConfigDataProvider->getStoreConfigData($context->getStoreId()); } } diff --git a/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/EntityUrl.php b/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/EntityUrl.php index c842d660a6176..89be1e6d67cc8 100644 --- a/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/EntityUrl.php +++ b/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/EntityUrl.php @@ -11,8 +11,8 @@ use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; use Magento\Framework\GraphQl\Config\Element\Field; use Magento\Framework\GraphQl\Query\ResolverInterface; -use Magento\Store\Model\StoreManagerInterface; use Magento\UrlRewrite\Model\UrlFinderInterface; +use Magento\UrlRewrite\Service\V1\Data\UrlRewrite; use Magento\UrlRewriteGraphQl\Model\Resolver\UrlRewrite\CustomUrlLocatorInterface; /** @@ -25,11 +25,6 @@ class EntityUrl implements ResolverInterface */ private $urlFinder; - /** - * @var StoreManagerInterface - */ - private $storeManager; - /** * @var CustomUrlLocatorInterface */ @@ -37,16 +32,13 @@ class EntityUrl implements ResolverInterface /** * @param UrlFinderInterface $urlFinder - * @param StoreManagerInterface $storeManager * @param CustomUrlLocatorInterface $customUrlLocator */ public function __construct( UrlFinderInterface $urlFinder, - StoreManagerInterface $storeManager, CustomUrlLocatorInterface $customUrlLocator ) { $this->urlFinder = $urlFinder; - $this->storeManager = $storeManager; $this->customUrlLocator = $customUrlLocator; } @@ -71,7 +63,7 @@ public function resolve( } $customUrl = $this->customUrlLocator->locateUrl($url); $url = $customUrl ?: $url; - $urlRewrite = $this->findCanonicalUrl($url); + $urlRewrite = $this->findCanonicalUrl($url, $context->getStoreId()); if ($urlRewrite) { $result = [ 'id' => $urlRewrite->getEntityId(), @@ -87,18 +79,19 @@ public function resolve( * Find the canonical url passing through all redirects if any * * @param string $requestPath - * @return \Magento\UrlRewrite\Service\V1\Data\UrlRewrite|null + * @param int $storeId + * @return UrlRewrite|null */ - private function findCanonicalUrl(string $requestPath) : ?\Magento\UrlRewrite\Service\V1\Data\UrlRewrite + private function findCanonicalUrl(string $requestPath, int $storeId) : ?UrlRewrite { - $urlRewrite = $this->findUrlFromRequestPath($requestPath); + $urlRewrite = $this->findUrlFromRequestPath($requestPath, $storeId); if ($urlRewrite && $urlRewrite->getRedirectType() > 0) { while ($urlRewrite && $urlRewrite->getRedirectType() > 0) { - $urlRewrite = $this->findUrlFromRequestPath($urlRewrite->getTargetPath()); + $urlRewrite = $this->findUrlFromRequestPath($urlRewrite->getTargetPath(), $storeId); } } if (!$urlRewrite) { - $urlRewrite = $this->findUrlFromTargetPath($requestPath); + $urlRewrite = $this->findUrlFromTargetPath($requestPath, $storeId); } return $urlRewrite; @@ -108,14 +101,15 @@ private function findCanonicalUrl(string $requestPath) : ?\Magento\UrlRewrite\Se * Find a url from a request url on the current store * * @param string $requestPath - * @return \Magento\UrlRewrite\Service\V1\Data\UrlRewrite|null + * @param int $storeId + * @return UrlRewrite|null */ - private function findUrlFromRequestPath(string $requestPath) : ?\Magento\UrlRewrite\Service\V1\Data\UrlRewrite + private function findUrlFromRequestPath(string $requestPath, int $storeId) : ?UrlRewrite { return $this->urlFinder->findOneByData( [ 'request_path' => $requestPath, - 'store_id' => $this->storeManager->getStore()->getId() + 'store_id' => $storeId ] ); } @@ -124,14 +118,15 @@ private function findUrlFromRequestPath(string $requestPath) : ?\Magento\UrlRewr * Find a url from a target url on the current store * * @param string $targetPath - * @return \Magento\UrlRewrite\Service\V1\Data\UrlRewrite|null + * @param int $storeId + * @return UrlRewrite|null */ - private function findUrlFromTargetPath(string $targetPath) : ?\Magento\UrlRewrite\Service\V1\Data\UrlRewrite + private function findUrlFromTargetPath(string $targetPath, int $storeId) : ?UrlRewrite { return $this->urlFinder->findOneByData( [ 'target_path' => $targetPath, - 'store_id' => $this->storeManager->getStore()->getId() + 'store_id' => $storeId ] ); } From c6a56f6d4befd1b971e7414bdc389bf6959c60de Mon Sep 17 00:00:00 2001 From: Stas Kozar Date: Wed, 20 Mar 2019 13:22:54 +0200 Subject: [PATCH 108/773] MC-5859: Fix action behavior --- .../Sales/Controller/Guest/ViewTest.php | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 dev/tests/integration/testsuite/Magento/Sales/Controller/Guest/ViewTest.php diff --git a/dev/tests/integration/testsuite/Magento/Sales/Controller/Guest/ViewTest.php b/dev/tests/integration/testsuite/Magento/Sales/Controller/Guest/ViewTest.php new file mode 100644 index 0000000000000..dad0018a37eb5 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Sales/Controller/Guest/ViewTest.php @@ -0,0 +1,26 @@ +getRequest()->setMethod(Request::METHOD_GET); + $this->dispatch('sales/guest/view/'); + + $this->assert404NotFound(); + } +} From d5c7c6d34070cc0a105cc57a1a8307f0de1ed535 Mon Sep 17 00:00:00 2001 From: Serhii Voloshkov Date: Wed, 20 Mar 2019 12:40:20 +0200 Subject: [PATCH 109/773] MC-5883: Notification minor changes --- .../Model/System/Message/Notifications.php | 20 +++++++-- .../System/Message/NotificationsTest.php | 42 +++++++++++++++++-- 2 files changed, 54 insertions(+), 8 deletions(-) diff --git a/app/code/Magento/Tax/Model/System/Message/Notifications.php b/app/code/Magento/Tax/Model/System/Message/Notifications.php index 5d274f0d2b1c9..b90b8c3af3c58 100644 --- a/app/code/Magento/Tax/Model/System/Message/Notifications.php +++ b/app/code/Magento/Tax/Model/System/Message/Notifications.php @@ -5,6 +5,8 @@ */ namespace Magento\Tax\Model\System\Message; +use Magento\Framework\App\ObjectManager; + /** * Notifications class */ @@ -53,22 +55,30 @@ class Notifications implements \Magento\Framework\Notification\MessageInterface */ private $notifications = []; + /** + * @var \Magento\Framework\Escaper + */ + private $escaper; + /** * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\Framework\UrlInterface $urlBuilder * @param \Magento\Tax\Model\Config $taxConfig * @param NotificationInterface[] $notifications + * @param \Magento\Framework\Escaper|null $escaper */ public function __construct( \Magento\Store\Model\StoreManagerInterface $storeManager, \Magento\Framework\UrlInterface $urlBuilder, \Magento\Tax\Model\Config $taxConfig, - $notifications = [] + $notifications = [], + \Magento\Framework\Escaper $escaper = null ) { $this->storeManager = $storeManager; $this->urlBuilder = $urlBuilder; $this->taxConfig = $taxConfig; $this->notifications = $notifications; + $this->escaper = $escaper ?: ObjectManager::getInstance()->get(\Magento\Framework\Escaper::class); } /** @@ -83,7 +93,7 @@ public function getIdentity() } /** - * {@inheritdoc} + * @inheritdoc */ public function isDisplayed() { @@ -96,7 +106,7 @@ public function isDisplayed() } /** - * {@inheritdoc} + * @inheritdoc */ public function getText() { @@ -135,7 +145,7 @@ public function getSeverity() */ public function getInfoUrl() { - return $this->taxConfig->getInfoUrl(); + return $this->escaper->escapeUrl($this->taxConfig->getInfoUrl()); } /** @@ -206,6 +216,7 @@ public function getIgnoreTaxNotificationUrl($section) /** * Return list of store names which have not compatible tax calculation type and price display settings. + * * Return true if settings are wrong for default store. * * @return array @@ -227,6 +238,7 @@ public function getStoresWithWrongDisplaySettings() /** * Return list of store names where tax discount settings are compatible. + * * Return true if settings are wrong for default store. * * @return array diff --git a/app/code/Magento/Tax/Test/Unit/Model/System/Message/NotificationsTest.php b/app/code/Magento/Tax/Test/Unit/Model/System/Message/NotificationsTest.php index 3fda67669fe86..5e2cb3dbeacbd 100644 --- a/app/code/Magento/Tax/Test/Unit/Model/System/Message/NotificationsTest.php +++ b/app/code/Magento/Tax/Test/Unit/Model/System/Message/NotificationsTest.php @@ -6,6 +6,7 @@ namespace Magento\Tax\Test\Unit\Model\System\Message; +use Magento\Framework\Escaper; use Magento\Tax\Model\Config as TaxConfig; use Magento\Tax\Model\System\Message\Notifications; use Magento\Store\Model\StoreManagerInterface; @@ -14,7 +15,7 @@ use Magento\Tax\Model\System\Message\NotificationInterface; /** - * Test class for @see \Magento\Tax\Model\System\Message\Notifications + * Test class for @see \Magento\Tax\Model\System\Message\Notifications. */ class NotificationsTest extends \PHPUnit\Framework\TestCase { @@ -43,21 +44,29 @@ class NotificationsTest extends \PHPUnit\Framework\TestCase */ private $notificationMock; + /** + * @var Escaper|\PHPUnit_Framework_MockObject_MockObject + */ + private $escaperMock; + + /** + * @inheritdoc + */ protected function setUp() { - parent::setUp(); - $this->storeManagerMock = $this->createMock(StoreManagerInterface::class); $this->urlBuilderMock = $this->createMock(UrlInterface::class); $this->taxConfigMock = $this->createMock(TaxConfig::class); $this->notificationMock = $this->createMock(NotificationInterface::class); + $this->escaperMock = $this->createMock(Escaper::class); $this->notifications = (new ObjectManager($this))->getObject( Notifications::class, [ 'storeManager' => $this->storeManagerMock, 'urlBuilder' => $this->urlBuilderMock, 'taxConfig' => $this->taxConfigMock, - 'notifications' => [$this->notificationMock] + 'notifications' => [$this->notificationMock], + 'escaper' => $this->escaperMock, ] ); } @@ -84,12 +93,21 @@ public function dataProviderIsDisplayed() ]; } + /** + * Unit test for getText method. + * + * @return void + */ public function testGetText() { $this->notificationMock->expects($this->once())->method('getText')->willReturn('Notification Text.'); $this->taxConfigMock->expects($this->once())->method('getInfoUrl')->willReturn('http://info-url'); $this->urlBuilderMock->expects($this->once())->method('getUrl') ->with('adminhtml/system_config/edit/section/tax')->willReturn('http://tax-config-url'); + $this->escaperMock->expects($this->once()) + ->method('escapeUrl') + ->with('http://info-url') + ->willReturn('http://info-url'); $this->assertEquals( 'Notification Text.

Please see documentation for more details. ' @@ -97,4 +115,20 @@ public function testGetText() $this->notifications->getText() ); } + + /** + * Unit test for getInfoUrl method. + * + * @return void + */ + public function testGetInfoUrl() + { + $this->taxConfigMock->expects($this->once())->method('getInfoUrl')->willReturn('http://info-url'); + $this->escaperMock->expects($this->once()) + ->method('escapeUrl') + ->with('http://info-url') + ->willReturn('http://info-url'); + + $this->notifications->getInfoUrl(); + } } From 9ab08c0ad626b3451775c05038d9189f5638b8d7 Mon Sep 17 00:00:00 2001 From: Stas Kozar Date: Wed, 20 Mar 2019 15:08:48 +0200 Subject: [PATCH 110/773] MC-5859: Fix action behavior --- .../testsuite/Magento/Sales/Controller/Guest/ViewTest.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dev/tests/integration/testsuite/Magento/Sales/Controller/Guest/ViewTest.php b/dev/tests/integration/testsuite/Magento/Sales/Controller/Guest/ViewTest.php index dad0018a37eb5..a984887bdb1b0 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/Controller/Guest/ViewTest.php +++ b/dev/tests/integration/testsuite/Magento/Sales/Controller/Guest/ViewTest.php @@ -5,6 +5,8 @@ */ declare(strict_types=1); +namespace Magento\Sales\Controller\Guest; + use Magento\TestFramework\Request; use Magento\TestFramework\TestCase\AbstractController; From d08c6dab696c911b6bb398df231f4af1fe1f1549 Mon Sep 17 00:00:00 2001 From: Serhii Voloshkov Date: Wed, 20 Mar 2019 15:43:20 +0200 Subject: [PATCH 111/773] MC-5883: Notification minor changes --- .../Model/System/Message/NotificationsTest.php | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/app/code/Magento/Tax/Test/Unit/Model/System/Message/NotificationsTest.php b/app/code/Magento/Tax/Test/Unit/Model/System/Message/NotificationsTest.php index 5e2cb3dbeacbd..a9fa12311803e 100644 --- a/app/code/Magento/Tax/Test/Unit/Model/System/Message/NotificationsTest.php +++ b/app/code/Magento/Tax/Test/Unit/Model/System/Message/NotificationsTest.php @@ -100,14 +100,15 @@ public function dataProviderIsDisplayed() */ public function testGetText() { + $url = 'http://info-url'; $this->notificationMock->expects($this->once())->method('getText')->willReturn('Notification Text.'); - $this->taxConfigMock->expects($this->once())->method('getInfoUrl')->willReturn('http://info-url'); + $this->taxConfigMock->expects($this->once())->method('getInfoUrl')->willReturn($url); $this->urlBuilderMock->expects($this->once())->method('getUrl') ->with('adminhtml/system_config/edit/section/tax')->willReturn('http://tax-config-url'); $this->escaperMock->expects($this->once()) ->method('escapeUrl') - ->with('http://info-url') - ->willReturn('http://info-url'); + ->with($url) + ->willReturn($url); $this->assertEquals( 'Notification Text.

Please see documentation for more details. ' @@ -123,12 +124,13 @@ public function testGetText() */ public function testGetInfoUrl() { - $this->taxConfigMock->expects($this->once())->method('getInfoUrl')->willReturn('http://info-url'); + $url = 'http://info-url'; + $this->taxConfigMock->expects($this->once())->method('getInfoUrl')->willReturn($url); $this->escaperMock->expects($this->once()) ->method('escapeUrl') - ->with('http://info-url') - ->willReturn('http://info-url'); + ->with($url) + ->willReturn($url); - $this->notifications->getInfoUrl(); + $this->assertEquals($url, $this->notifications->getInfoUrl()); } } From aeb8c3dccc8457cee523487b5601412b4de3a4d7 Mon Sep 17 00:00:00 2001 From: Serhii Voloshkov Date: Thu, 21 Mar 2019 16:26:42 +0200 Subject: [PATCH 112/773] MC-15476: Block Action minor changes --- .../Listing/Column/BlockActionsTest.php | 40 +++++++++++-------- .../Component/Listing/Column/BlockActions.php | 18 ++++----- 2 files changed, 31 insertions(+), 27 deletions(-) diff --git a/app/code/Magento/Cms/Test/Unit/Ui/Component/Listing/Column/BlockActionsTest.php b/app/code/Magento/Cms/Test/Unit/Ui/Component/Listing/Column/BlockActionsTest.php index 3095abef7bbe3..6981a7983049e 100644 --- a/app/code/Magento/Cms/Test/Unit/Ui/Component/Listing/Column/BlockActionsTest.php +++ b/app/code/Magento/Cms/Test/Unit/Ui/Component/Listing/Column/BlockActionsTest.php @@ -14,7 +14,7 @@ use PHPUnit_Framework_MockObject_MockObject as MockObject; /** - * BlockActionsTest contains unit tests for \Magento\Cms\Ui\Component\Listing\Column\BlockActions class + * BlockActionsTest contains unit tests for \Magento\Cms\Ui\Component\Listing\Column\BlockActions class. */ class BlockActionsTest extends \PHPUnit\Framework\TestCase { @@ -33,6 +33,9 @@ class BlockActionsTest extends \PHPUnit\Framework\TestCase */ private $urlBuilder; + /** + * @inheritdoc + */ protected function setUp() { $objectManager = new ObjectManager($this); @@ -42,7 +45,7 @@ protected function setUp() $processor = $this->getMockBuilder(Processor::class) ->disableOriginalConstructor() ->getMock(); - $context->expects(static::never()) + $context->expects($this->never()) ->method('getProcessor') ->willReturn($processor); @@ -50,7 +53,7 @@ protected function setUp() $this->escaper = $this->getMockBuilder(Escaper::class) ->disableOriginalConstructor() - ->setMethods(['escapeHtml']) + ->setMethods(['escapeHtmlAttr']) ->getMock(); $this->blockActions = $objectManager->getObject(BlockActions::class, [ @@ -62,7 +65,10 @@ protected function setUp() } /** + * Unit test for prepareDataSource method. + * * @covers \Magento\Cms\Ui\Component\Listing\Column\BlockActions::prepareDataSource + * @return void */ public function testPrepareDataSource() { @@ -73,10 +79,10 @@ public function testPrepareDataSource() 'items' => [ [ 'block_id' => $blockId, - 'title' => $title - ] - ] - ] + 'title' => $title, + ], + ], + ], ]; $name = 'item_name'; $expectedItems = [ @@ -93,34 +99,34 @@ public function testPrepareDataSource() 'label' => __('Delete'), 'confirm' => [ 'title' => __('Delete %1', $title), - 'message' => __('Are you sure you want to delete a %1 record?', $title) + 'message' => __('Are you sure you want to delete a %1 record?', $title), ], - 'post' => true - ] + 'post' => true, + ], ], - ] + ], ]; - $this->escaper->expects(static::once()) - ->method('escapeHtml') + $this->escaper->expects($this->once()) + ->method('escapeHtmlAttr') ->with($title) ->willReturn($title); - $this->urlBuilder->expects(static::exactly(2)) + $this->urlBuilder->expects($this->exactly(2)) ->method('getUrl') ->willReturnMap( [ [ BlockActions::URL_PATH_EDIT, [ - 'block_id' => $blockId + 'block_id' => $blockId, ], 'test/url/edit', ], [ BlockActions::URL_PATH_DELETE, [ - 'block_id' => $blockId + 'block_id' => $blockId, ], 'test/url/delete', ], @@ -130,6 +136,6 @@ public function testPrepareDataSource() $this->blockActions->setData('name', $name); $actual = $this->blockActions->prepareDataSource($items); - static::assertEquals($expectedItems, $actual['data']['items']); + $this->assertEquals($expectedItems, $actual['data']['items']); } } diff --git a/app/code/Magento/Cms/Ui/Component/Listing/Column/BlockActions.php b/app/code/Magento/Cms/Ui/Component/Listing/Column/BlockActions.php index f68ef35e534f3..6e9eef47281c0 100644 --- a/app/code/Magento/Cms/Ui/Component/Listing/Column/BlockActions.php +++ b/app/code/Magento/Cms/Ui/Component/Listing/Column/BlockActions.php @@ -13,7 +13,7 @@ use Magento\Framework\Escaper; /** - * Class BlockActions + * Class to build edit and delete link for each item. */ class BlockActions extends Column { @@ -35,8 +35,6 @@ class BlockActions extends Column private $escaper; /** - * Constructor - * * @param ContextInterface $context * @param UiComponentFactory $uiComponentFactory * @param UrlInterface $urlBuilder @@ -62,31 +60,31 @@ public function prepareDataSource(array $dataSource) if (isset($dataSource['data']['items'])) { foreach ($dataSource['data']['items'] as & $item) { if (isset($item['block_id'])) { - $title = $this->getEscaper()->escapeHtml($item['title']); + $title = $this->getEscaper()->escapeHtmlAttr($item['title']); $item[$this->getData('name')] = [ 'edit' => [ 'href' => $this->urlBuilder->getUrl( static::URL_PATH_EDIT, [ - 'block_id' => $item['block_id'] + 'block_id' => $item['block_id'], ] ), - 'label' => __('Edit') + 'label' => __('Edit'), ], 'delete' => [ 'href' => $this->urlBuilder->getUrl( static::URL_PATH_DELETE, [ - 'block_id' => $item['block_id'] + 'block_id' => $item['block_id'], ] ), 'label' => __('Delete'), 'confirm' => [ 'title' => __('Delete %1', $title), - 'message' => __('Are you sure you want to delete a %1 record?', $title) + 'message' => __('Are you sure you want to delete a %1 record?', $title), ], - 'post' => true - ] + 'post' => true, + ], ]; } } From 9b62b1c4bf9fbb553dd78c7f45375d0c4b9849c7 Mon Sep 17 00:00:00 2001 From: Hwashiang Yu Date: Thu, 21 Mar 2019 10:47:09 -0500 Subject: [PATCH 113/773] MC-15048: Update transaction email variable dialog - Resolved incorrect recusive array merge - Updated variable dialog values --- app/code/Magento/Email/Model/Template.php | 2 +- app/code/Magento/Email/view/adminhtml/web/js/variables.js | 8 +++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/Email/Model/Template.php b/app/code/Magento/Email/Model/Template.php index 8724b725ae489..3ee87cb81dfc4 100644 --- a/app/code/Magento/Email/Model/Template.php +++ b/app/code/Magento/Email/Model/Template.php @@ -326,7 +326,7 @@ public function getVariablesOptionArray($withGroup = false) $optionArray[] = ['value' => '{{' . $value . '}}', 'label' => __('%1', $label)]; } if ($withGroup) { - $optionArray = ['label' => __('Template Variables'), 'value' => $optionArray]; + $optionArray = [['label' => __('Template Variables'), 'value' => $optionArray]]; } } return $optionArray; diff --git a/app/code/Magento/Email/view/adminhtml/web/js/variables.js b/app/code/Magento/Email/view/adminhtml/web/js/variables.js index d519053b5265a..252e21b631457 100644 --- a/app/code/Magento/Email/view/adminhtml/web/js/variables.js +++ b/app/code/Magento/Email/view/adminhtml/web/js/variables.js @@ -52,11 +52,11 @@ define([ this.variablesContent = '

    '; variables.each(function (variableGroup) { if (variableGroup.label && variableGroup.value) { - this.variablesContent += '
  • ' + variableGroup.label + '
  • '; + this.variablesContent += '
  • ' + variableGroup.label.escapeHTML() + '
  • '; variableGroup.value.each(function (variable) { if (variable.value && variable.label) { this.variablesContent += '
  • ' + - this.prepareVariableRow(variable.value, variable.label) + '
  • '; + this.prepareVariableRow(variable.value.escapeHTML(), variable.label.escapeHTML()) + ''; } }.bind(this)); } @@ -75,7 +75,7 @@ define([ openDialogWindow: function (variablesContent) { var windowId = this.dialogWindowId; - jQuery('
    ' + Variables.variablesContent + '
    ').modal({ + jQuery('
    ' + variablesContent + '
    ').modal({ title: $t('Insert Variable...'), type: 'slide', buttons: [], @@ -87,8 +87,6 @@ define([ }); jQuery('#' + windowId).modal('openModal'); - - variablesContent.evalScripts.bind(variablesContent).defer(); }, /** From 232248894da04f6012e02d47462bff87d6dbdcaf Mon Sep 17 00:00:00 2001 From: Nathan Smith Date: Thu, 21 Mar 2019 10:59:03 -0500 Subject: [PATCH 114/773] MC-15425: Incorrect ImportExport entity handling --- .../Magento/ImportExport/Model/Import.php | 244 ++++++++++-------- .../Test/Unit/Model/ImportTest.php | 84 +++++- .../Magento/ImportExport/Model/ImportTest.php | 13 +- 3 files changed, 223 insertions(+), 118 deletions(-) diff --git a/app/code/Magento/ImportExport/Model/Import.php b/app/code/Magento/ImportExport/Model/Import.php index d115aea7f2ff9..a074782b502f6 100644 --- a/app/code/Magento/ImportExport/Model/Import.php +++ b/app/code/Magento/ImportExport/Model/Import.php @@ -6,13 +6,35 @@ namespace Magento\ImportExport\Model; +use Magento\Eav\Model\Entity\Attribute; +use Magento\Eav\Model\Entity\Attribute\AbstractAttribute; +use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\App\Filesystem\DirectoryList; use Magento\Framework\App\ObjectManager; +use Magento\Framework\Exception\FileSystemException; +use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\Filesystem; use Magento\Framework\HTTP\Adapter\FileTransferFactory; +use Magento\Framework\Indexer\IndexerRegistry; +use Magento\Framework\Math\Random; use Magento\Framework\Stdlib\DateTime\DateTime; +use Magento\ImportExport\Helper\Data as DataHelper; +use Magento\ImportExport\Model\Export\Adapter\CsvFactory; +use Magento\ImportExport\Model\Import\AbstractEntity as ImportAbstractEntity; +use Magento\ImportExport\Model\Import\AbstractSource; +use Magento\ImportExport\Model\Import\Adapter; +use Magento\ImportExport\Model\Import\ConfigInterface; +use Magento\ImportExport\Model\Import\Entity\AbstractEntity; +use Magento\ImportExport\Model\Import\Entity\Factory; use Magento\ImportExport\Model\Import\ErrorProcessing\ProcessingError; use Magento\ImportExport\Model\Import\ErrorProcessing\ProcessingErrorAggregatorInterface; use Magento\Framework\Message\ManagerInterface; +use Magento\ImportExport\Model\ResourceModel\Import\Data; +use Magento\ImportExport\Model\Source\Import\AbstractBehavior; +use Magento\ImportExport\Model\Source\Import\Behavior\Factory as BehaviorFactory; +use Magento\MediaStorage\Model\File\Uploader; +use Magento\MediaStorage\Model\File\UploaderFactory; +use Psr\Log\LoggerInterface; /** * Import model @@ -20,32 +42,19 @@ * @api * * @method string getBehavior() getBehavior() - * @method \Magento\ImportExport\Model\Import setEntity() setEntity(string $value) + * @method self setEntity() setEntity(string $value) * @SuppressWarnings(PHPMD.CouplingBetweenObjects) * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) * @since 100.0.2 */ -class Import extends \Magento\ImportExport\Model\AbstractModel +class Import extends AbstractModel { - /**#@+ - * Import behaviors - */ const BEHAVIOR_APPEND = 'append'; - const BEHAVIOR_ADD_UPDATE = 'add_update'; - const BEHAVIOR_REPLACE = 'replace'; - const BEHAVIOR_DELETE = 'delete'; - const BEHAVIOR_CUSTOM = 'custom'; - /**#@-*/ - - /**#@+ - * Form field names (and IDs) - */ - /** * Import source file. */ @@ -91,8 +100,6 @@ class Import extends \Magento\ImportExport\Model\AbstractModel */ const FIELDS_ENCLOSURE = 'fields_enclosure'; - /**#@-*/ - /** * default delimiter for several values in one cell as default for FIELD_FIELD_MULTIPLE_VALUE_SEPARATOR */ @@ -102,72 +109,65 @@ class Import extends \Magento\ImportExport\Model\AbstractModel * default empty attribute value constant */ const DEFAULT_EMPTY_ATTRIBUTE_VALUE_CONSTANT = '__EMPTY__VALUE__'; - - /**#@+ - * Import constants - */ const DEFAULT_SIZE = 50; - const MAX_IMPORT_CHUNKS = 4; - const IMPORT_HISTORY_DIR = 'import_history/'; - const IMPORT_DIR = 'import/'; - /**#@-*/ - - /**#@-*/ + /** + * @var AbstractEntity|ImportAbstractEntity + */ protected $_entityAdapter; /** * Import export data * - * @var \Magento\ImportExport\Helper\Data + * @var DataHelper */ protected $_importExportData = null; /** - * @var \Magento\ImportExport\Model\Import\ConfigInterface + * @var ConfigInterface */ protected $_importConfig; /** - * @var \Magento\ImportExport\Model\Import\Entity\Factory + * @var Factory */ protected $_entityFactory; /** - * @var \Magento\ImportExport\Model\ResourceModel\Import\Data + * @var Data */ protected $_importData; /** - * @var \Magento\ImportExport\Model\Export\Adapter\CsvFactory + * @var CsvFactory */ protected $_csvFactory; /** - * @var \Magento\Framework\HTTP\Adapter\FileTransferFactory + * @var FileTransferFactory */ protected $_httpFactory; /** - * @var \Magento\MediaStorage\Model\File\UploaderFactory + * @var UploaderFactory */ protected $_uploaderFactory; /** - * @var \Magento\Framework\Indexer\IndexerRegistry + * @var IndexerRegistry */ protected $indexerRegistry; /** - * @var \Magento\ImportExport\Model\Source\Import\Behavior\Factory + * @var BehaviorFactory */ protected $_behaviorFactory; /** - * @var \Magento\Framework\Filesystem + * @var Filesystem */ protected $_filesystem; @@ -187,41 +187,48 @@ class Import extends \Magento\ImportExport\Model\AbstractModel private $messageManager; /** - * @param \Psr\Log\LoggerInterface $logger - * @param \Magento\Framework\Filesystem $filesystem - * @param \Magento\ImportExport\Helper\Data $importExportData - * @param \Magento\Framework\App\Config\ScopeConfigInterface $coreConfig + * @var Random + */ + private $random; + + /** + * @param LoggerInterface $logger + * @param Filesystem $filesystem + * @param DataHelper $importExportData + * @param ScopeConfigInterface $coreConfig * @param Import\ConfigInterface $importConfig * @param Import\Entity\Factory $entityFactory - * @param \Magento\ImportExport\Model\ResourceModel\Import\Data $importData + * @param Data $importData * @param Export\Adapter\CsvFactory $csvFactory * @param FileTransferFactory $httpFactory - * @param \Magento\MediaStorage\Model\File\UploaderFactory $uploaderFactory + * @param UploaderFactory $uploaderFactory * @param Source\Import\Behavior\Factory $behaviorFactory - * @param \Magento\Framework\Indexer\IndexerRegistry $indexerRegistry + * @param IndexerRegistry $indexerRegistry * @param History $importHistoryModel * @param DateTime $localeDate * @param array $data * @param ManagerInterface|null $messageManager + * @param Random|null $random * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( - \Psr\Log\LoggerInterface $logger, - \Magento\Framework\Filesystem $filesystem, - \Magento\ImportExport\Helper\Data $importExportData, - \Magento\Framework\App\Config\ScopeConfigInterface $coreConfig, - \Magento\ImportExport\Model\Import\ConfigInterface $importConfig, - \Magento\ImportExport\Model\Import\Entity\Factory $entityFactory, - \Magento\ImportExport\Model\ResourceModel\Import\Data $importData, - \Magento\ImportExport\Model\Export\Adapter\CsvFactory $csvFactory, - \Magento\Framework\HTTP\Adapter\FileTransferFactory $httpFactory, - \Magento\MediaStorage\Model\File\UploaderFactory $uploaderFactory, - \Magento\ImportExport\Model\Source\Import\Behavior\Factory $behaviorFactory, - \Magento\Framework\Indexer\IndexerRegistry $indexerRegistry, - \Magento\ImportExport\Model\History $importHistoryModel, + LoggerInterface $logger, + Filesystem $filesystem, + DataHelper $importExportData, + ScopeConfigInterface $coreConfig, + ConfigInterface $importConfig, + Factory $entityFactory, + Data $importData, + CsvFactory $csvFactory, + FileTransferFactory $httpFactory, + UploaderFactory $uploaderFactory, + BehaviorFactory $behaviorFactory, + IndexerRegistry $indexerRegistry, + History $importHistoryModel, DateTime $localeDate, array $data = [], - ManagerInterface $messageManager = null + ManagerInterface $messageManager = null, + Random $random = null ) { $this->_importExportData = $importExportData; $this->_coreConfig = $coreConfig; @@ -236,15 +243,18 @@ public function __construct( $this->_filesystem = $filesystem; $this->importHistoryModel = $importHistoryModel; $this->localeDate = $localeDate; - $this->messageManager = $messageManager ?: ObjectManager::getInstance()->get(ManagerInterface::class); + $this->messageManager = $messageManager ?: ObjectManager::getInstance() + ->get(ManagerInterface::class); + $this->random = $random ?: ObjectManager::getInstance() + ->get(Random::class); parent::__construct($logger, $filesystem, $data); } /** * Create instance of entity adapter and return it * - * @throws \Magento\Framework\Exception\LocalizedException - * @return \Magento\ImportExport\Model\Import\Entity\AbstractEntity|\Magento\ImportExport\Model\Import\AbstractEntity + * @throws LocalizedException + * @return AbstractEntity|ImportAbstractEntity */ protected function _getEntityAdapter() { @@ -255,30 +265,30 @@ protected function _getEntityAdapter() $this->_entityAdapter = $this->_entityFactory->create($entities[$this->getEntity()]['model']); } catch (\Exception $e) { $this->_logger->critical($e); - throw new \Magento\Framework\Exception\LocalizedException( + throw new LocalizedException( __('Please enter a correct entity model.') ); } - if (!$this->_entityAdapter instanceof \Magento\ImportExport\Model\Import\Entity\AbstractEntity && - !$this->_entityAdapter instanceof \Magento\ImportExport\Model\Import\AbstractEntity + if (!$this->_entityAdapter instanceof AbstractEntity && + !$this->_entityAdapter instanceof ImportAbstractEntity ) { - throw new \Magento\Framework\Exception\LocalizedException( + throw new LocalizedException( __( 'The entity adapter object must be an instance of %1 or %2.', - \Magento\ImportExport\Model\Import\Entity\AbstractEntity::class, - \Magento\ImportExport\Model\Import\AbstractEntity::class + AbstractEntity::class, + ImportAbstractEntity::class ) ); } // check for entity codes integrity if ($this->getEntity() != $this->_entityAdapter->getEntityTypeCode()) { - throw new \Magento\Framework\Exception\LocalizedException( + throw new LocalizedException( __('The input entity code is not equal to entity adapter code.') ); } } else { - throw new \Magento\Framework\Exception\LocalizedException(__('Please enter a correct entity.')); + throw new LocalizedException(__('Please enter a correct entity.')); } $this->_entityAdapter->setParameters($this->getData()); } @@ -289,12 +299,12 @@ protected function _getEntityAdapter() * Returns source adapter object. * * @param string $sourceFile Full path to source file - * @return \Magento\ImportExport\Model\Import\AbstractSource - * @throws \Magento\Framework\Exception\FileSystemException + * @return AbstractSource + * @throws FileSystemException */ protected function _getSourceAdapter($sourceFile) { - return \Magento\ImportExport\Model\Import\Adapter::findAdapterFor( + return Adapter::findAdapterFor( $sourceFile, $this->_filesystem->getDirectoryWrite(DirectoryList::ROOT), $this->getData(self::FIELD_FIELD_SEPARATOR) @@ -306,7 +316,7 @@ protected function _getSourceAdapter($sourceFile) * * @param ProcessingErrorAggregatorInterface $validationResult * @return string[] - * @throws \Magento\Framework\Exception\LocalizedException + * @throws LocalizedException */ public function getOperationResultMessages(ProcessingErrorAggregatorInterface $validationResult) { @@ -349,10 +359,10 @@ public function getOperationResultMessages(ProcessingErrorAggregatorInterface $v /** * Get attribute type for upcoming validation. * - * @param \Magento\Eav\Model\Entity\Attribute\AbstractAttribute|\Magento\Eav\Model\Entity\Attribute $attribute + * @param AbstractAttribute|Attribute $attribute * @return string */ - public static function getAttributeType(\Magento\Eav\Model\Entity\Attribute\AbstractAttribute $attribute) + public static function getAttributeType(AbstractAttribute $attribute) { $frontendInput = $attribute->getFrontendInput(); if ($attribute->usesSource() && in_array($frontendInput, ['select', 'multiselect', 'boolean'])) { @@ -367,7 +377,7 @@ public static function getAttributeType(\Magento\Eav\Model\Entity\Attribute\Abst /** * DB data source model getter. * - * @return \Magento\ImportExport\Model\ResourceModel\Import\Data + * @return Data */ public function getDataSourceModel() { @@ -388,14 +398,19 @@ public static function getDefaultBehavior() /** * Override standard entity getter. * - * @throws \Magento\Framework\Exception\LocalizedException + * @throws LocalizedException * @return string */ public function getEntity() { - if (empty($this->_data['entity'])) { - throw new \Magento\Framework\Exception\LocalizedException(__('Entity is unknown')); + $entities = $this->_importConfig->getEntities(); + + if (empty($this->_data['entity']) + || !empty($this->_data['entity']) && !isset($entities[$this->_data['entity']]) + ) { + throw new LocalizedException(__('Entity is unknown')); } + return $this->_data['entity']; } @@ -403,7 +418,7 @@ public function getEntity() * Returns number of checked entities. * * @return int - * @throws \Magento\Framework\Exception\LocalizedException + * @throws LocalizedException */ public function getProcessedEntitiesCount() { @@ -414,7 +429,7 @@ public function getProcessedEntitiesCount() * Returns number of checked rows. * * @return int - * @throws \Magento\Framework\Exception\LocalizedException + * @throws LocalizedException */ public function getProcessedRowsCount() { @@ -435,7 +450,7 @@ public function getWorkingDir() * Import source file structure to DB. * * @return bool - * @throws \Magento\Framework\Exception\LocalizedException + * @throws LocalizedException */ public function importSource() { @@ -472,7 +487,7 @@ public function importSource() * Process import. * * @return bool - * @throws \Magento\Framework\Exception\LocalizedException + * @throws LocalizedException */ protected function processImport() { @@ -483,7 +498,7 @@ protected function processImport() * Import possibility getter. * * @return bool - * @throws \Magento\Framework\Exception\LocalizedException + * @throws LocalizedException */ public function isImportAllowed() { @@ -494,7 +509,7 @@ public function isImportAllowed() * Get error aggregator instance. * * @return ProcessingErrorAggregatorInterface - * @throws \Magento\Framework\Exception\LocalizedException + * @throws LocalizedException */ public function getErrorAggregator() { @@ -504,7 +519,7 @@ public function getErrorAggregator() /** * Move uploaded file. * - * @throws \Magento\Framework\Exception\LocalizedException + * @throws LocalizedException * @return string Source file path */ public function uploadSource() @@ -518,20 +533,21 @@ public function uploadSource() } else { $errorMessage = __('The file was not uploaded.'); } - throw new \Magento\Framework\Exception\LocalizedException($errorMessage); + throw new LocalizedException($errorMessage); } $entity = $this->getEntity(); - /** @var $uploader \Magento\MediaStorage\Model\File\Uploader */ + /** @var $uploader Uploader */ $uploader = $this->_uploaderFactory->create(['fileId' => self::FIELD_NAME_SOURCE_FILE]); $uploader->skipDbProcessing(true); - $result = $uploader->save($this->getWorkingDir()); + $fileName = $this->random->getRandomString(32) . '.' . $uploader->getFileExtension(); + $result = $uploader->save($this->getWorkingDir(), $fileName); $extension = pathinfo($result['file'], PATHINFO_EXTENSION); $uploadedFile = $result['path'] . $result['file']; if (!$extension) { $this->_varDirectory->delete($uploadedFile); - throw new \Magento\Framework\Exception\LocalizedException(__('The file you uploaded has no extension.')); + throw new LocalizedException(__('The file you uploaded has no extension.')); } $sourceFile = $this->getWorkingDir() . $entity; @@ -548,8 +564,8 @@ public function uploadSource() $this->_varDirectory->getRelativePath($uploadedFile), $sourceFileRelative ); - } catch (\Magento\Framework\Exception\FileSystemException $e) { - throw new \Magento\Framework\Exception\LocalizedException(__('The source file moving process failed.')); + } catch (FileSystemException $e) { + throw new LocalizedException(__('The source file moving process failed.')); } } $this->_removeBom($sourceFile); @@ -561,8 +577,8 @@ public function uploadSource() * Move uploaded file and provide source instance. * * @return Import\AbstractSource - * @throws \Magento\Framework\Exception\FileSystemException - * @throws \Magento\Framework\Exception\LocalizedException + * @throws FileSystemException + * @throws LocalizedException */ public function uploadFileAndGetSource() { @@ -571,7 +587,7 @@ public function uploadFileAndGetSource() $source = $this->_getSourceAdapter($sourceFile); } catch (\Exception $e) { $this->_varDirectory->delete($this->_varDirectory->getRelativePath($sourceFile)); - throw new \Magento\Framework\Exception\LocalizedException(__($e->getMessage())); + throw new LocalizedException(__($e->getMessage())); } return $source; @@ -582,7 +598,7 @@ public function uploadFileAndGetSource() * * @param string $sourceFile * @return $this - * @throws \Magento\Framework\Exception\FileSystemException + * @throws FileSystemException */ protected function _removeBom($sourceFile) { @@ -600,11 +616,11 @@ protected function _removeBom($sourceFile) * Before validate data the method requires to initialize error aggregator (ProcessingErrorAggregatorInterface) * with 'validation strategy' and 'allowed error count' values to allow using this parameters in validation process. * - * @param \Magento\ImportExport\Model\Import\AbstractSource $source + * @param AbstractSource $source * @return bool - * @throws \Magento\Framework\Exception\LocalizedException + * @throws LocalizedException */ - public function validateSource(\Magento\ImportExport\Model\Import\AbstractSource $source) + public function validateSource(AbstractSource $source) { $this->addLogComment(__('Begin data validation')); @@ -619,7 +635,7 @@ public function validateSource(\Magento\ImportExport\Model\Import\AbstractSource $adapter->validateData(); } catch (\Exception $e) { $errorAggregator->addError( - \Magento\ImportExport\Model\Import\Entity\AbstractEntity::ERROR_CODE_SYSTEM_EXCEPTION, + AbstractEntity::ERROR_CODE_SYSTEM_EXCEPTION, ProcessingError::ERROR_LEVEL_CRITICAL, null, null, @@ -641,7 +657,7 @@ public function validateSource(\Magento\ImportExport\Model\Import\AbstractSource * Invalidate indexes by process codes. * * @return $this - * @throws \Magento\Framework\Exception\LocalizedException + * @throws LocalizedException */ public function invalidateIndex() { @@ -675,7 +691,7 @@ public function invalidateIndex() * ) * * @return array - * @throws \Magento\Framework\Exception\LocalizedException + * @throws LocalizedException */ public function getEntityBehaviors() { @@ -684,7 +700,7 @@ public function getEntityBehaviors() foreach ($entities as $entityCode => $entityData) { $behaviorClassName = isset($entityData['behaviorModel']) ? $entityData['behaviorModel'] : null; if ($behaviorClassName && class_exists($behaviorClassName)) { - /** @var $behavior \Magento\ImportExport\Model\Source\Import\AbstractBehavior */ + /** @var $behavior AbstractBehavior */ $behavior = $this->_behaviorFactory->create($behaviorClassName); $behaviourData[$entityCode] = [ 'token' => $behaviorClassName, @@ -692,7 +708,7 @@ public function getEntityBehaviors() 'notes' => $behavior->getNotes($entityCode), ]; } else { - throw new \Magento\Framework\Exception\LocalizedException( + throw new LocalizedException( __('The behavior token for %1 is invalid.', $entityCode) ); } @@ -708,7 +724,7 @@ public function getEntityBehaviors() * ) * * @return array - * @throws \Magento\Framework\Exception\LocalizedException + * @throws LocalizedException */ public function getUniqueEntityBehaviors() { @@ -728,7 +744,7 @@ public function getUniqueEntityBehaviors() * * @param string|null $entity * @return bool - * @throws \Magento\Framework\Exception\LocalizedException + * @throws LocalizedException */ public function isReportEntityType($entity = null) { @@ -742,12 +758,12 @@ public function isReportEntityType($entity = null) try { $result = $this->_getEntityAdapter()->isNeedToLogInHistory(); } catch (\Exception $e) { - throw new \Magento\Framework\Exception\LocalizedException( + throw new LocalizedException( __('Please enter a correct entity model') ); } } else { - throw new \Magento\Framework\Exception\LocalizedException(__('Please enter a correct entity model')); + throw new LocalizedException(__('Please enter a correct entity model')); } } else { $result = $this->_getEntityAdapter()->isNeedToLogInHistory(); @@ -763,7 +779,7 @@ public function isReportEntityType($entity = null) * @param string $extension * @param array $result * @return $this - * @throws \Magento\Framework\Exception\LocalizedException + * @throws LocalizedException */ protected function createHistoryReport($sourceFileRelative, $entity, $extension = null, $result = null) { @@ -787,8 +803,8 @@ protected function createHistoryReport($sourceFileRelative, $entity, $extension $content = $this->_varDirectory->getDriver()->fileGetContents($sourceFileRelative); $this->_varDirectory->writeFile($copyFile, $content); } - } catch (\Magento\Framework\Exception\FileSystemException $e) { - throw new \Magento\Framework\Exception\LocalizedException(__('Source file coping failed')); + } catch (FileSystemException $e) { + throw new LocalizedException(__('Source file coping failed')); } $this->importHistoryModel->addReport($copyName); } @@ -799,7 +815,7 @@ protected function createHistoryReport($sourceFileRelative, $entity, $extension * Get count of created items * * @return int - * @throws \Magento\Framework\Exception\LocalizedException + * @throws LocalizedException */ public function getCreatedItemsCount() { @@ -810,7 +826,7 @@ public function getCreatedItemsCount() * Get count of updated items * * @return int - * @throws \Magento\Framework\Exception\LocalizedException + * @throws LocalizedException */ public function getUpdatedItemsCount() { @@ -821,7 +837,7 @@ public function getUpdatedItemsCount() * Get count of deleted items * * @return int - * @throws \Magento\Framework\Exception\LocalizedException + * @throws LocalizedException */ public function getDeletedItemsCount() { diff --git a/app/code/Magento/ImportExport/Test/Unit/Model/ImportTest.php b/app/code/Magento/ImportExport/Test/Unit/Model/ImportTest.php index 823ec29d41760..6fdf9b04450c0 100644 --- a/app/code/Magento/ImportExport/Test/Unit/Model/ImportTest.php +++ b/app/code/Magento/ImportExport/Test/Unit/Model/ImportTest.php @@ -499,6 +499,10 @@ public function testInvalidateIndex() $this->_importConfig->expects($this->atLeastOnce()) ->method('getRelatedIndexers') ->willReturn($indexers); + $this->_importConfig->method('getEntities') + ->willReturn([ + 'test' => [] + ]); $this->indexerRegistry->expects($this->any()) ->method('get') ->willReturnMap([ @@ -532,6 +536,10 @@ public function testInvalidateIndexWithoutIndexers() $this->_importConfig->expects($this->once()) ->method('getRelatedIndexers') ->willReturn([]); + $this->_importConfig->method('getEntities') + ->willReturn([ + 'test' => [] + ]); $logger = $this->getMockBuilder(\Psr\Log\LoggerInterface::class) ->disableOriginalConstructor() @@ -558,12 +566,82 @@ public function testInvalidateIndexWithoutIndexers() $this->assertSame($import, $import->invalidateIndex()); } + public function testGetKnownEntity() + { + $this->_importConfig->method('getEntities') + ->willReturn([ + 'test' => [] + ]); + + $logger = $this->getMockBuilder(\Psr\Log\LoggerInterface::class) + ->disableOriginalConstructor() + ->getMock(); + + $import = new Import( + $logger, + $this->_filesystem, + $this->_importExportData, + $this->_coreConfig, + $this->_importConfig, + $this->_entityFactory, + $this->_importData, + $this->_csvFactory, + $this->_httpFactory, + $this->_uploaderFactory, + $this->_behaviorFactory, + $this->indexerRegistry, + $this->historyModel, + $this->dateTime + ); + + $import->setEntity('test'); + $entity = $import->getEntity(); + self::assertSame('test', $entity); + } + /** - * @todo to implement it. + * @expectedException \Magento\Framework\Exception\LocalizedException + * @expectedExceptionMessage Entity is unknown + * @dataProvider unknownEntitiesProvider */ - public function testGetEntityBehaviors() + public function testGetUnknownEntity($entity) { - $this->markTestIncomplete('This test has not been implemented yet.'); + $this->_importConfig->method('getEntities') + ->willReturn([ + 'test' => [] + ]); + + $logger = $this->getMockBuilder(\Psr\Log\LoggerInterface::class) + ->disableOriginalConstructor() + ->getMock(); + + $import = new Import( + $logger, + $this->_filesystem, + $this->_importExportData, + $this->_coreConfig, + $this->_importConfig, + $this->_entityFactory, + $this->_importData, + $this->_csvFactory, + $this->_httpFactory, + $this->_uploaderFactory, + $this->_behaviorFactory, + $this->indexerRegistry, + $this->historyModel, + $this->dateTime + ); + + $import->setEntity($entity); + $import->getEntity(); + } + + public function unknownEntitiesProvider() + { + return [ + [''], + ['foo'], + ]; } /** diff --git a/dev/tests/integration/testsuite/Magento/ImportExport/Model/ImportTest.php b/dev/tests/integration/testsuite/Magento/ImportExport/Model/ImportTest.php index 93fa04806d577..0c1f2d2fcc8d7 100644 --- a/dev/tests/integration/testsuite/Magento/ImportExport/Model/ImportTest.php +++ b/dev/tests/integration/testsuite/Magento/ImportExport/Model/ImportTest.php @@ -134,13 +134,24 @@ public function testValidateSourceException() $this->_model->validateSource($source); } - public function testGetEntity() + /** + * @expectedException \Magento\Framework\Exception\LocalizedException + * @expectedExceptionMessage Entity is unknown + */ + public function testGetUnknownEntity() { $entityName = 'entity_name'; $this->_model->setEntity($entityName); $this->assertSame($entityName, $this->_model->getEntity()); } + public function testGetEntity() + { + $entityName = 'catalog_product'; + $this->_model->setEntity($entityName); + $this->assertSame($entityName, $this->_model->getEntity()); + } + /** * @expectedException \Magento\Framework\Exception\LocalizedException * @expectedExceptionMessage Entity is unknown From 7d47720cca1f5353ab0da47872ed9c33174f342f Mon Sep 17 00:00:00 2001 From: Hwashiang Yu Date: Thu, 21 Mar 2019 15:06:42 -0500 Subject: [PATCH 115/773] MC-5867: TinyMCE editor JSOON attribute improvement - Added additional JSON check to TinyMCE3 --- .../base/web/tiny_mce/plugins/media/editor_plugin_src.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Tinymce3/view/base/web/tiny_mce/plugins/media/editor_plugin_src.js b/app/code/Magento/Tinymce3/view/base/web/tiny_mce/plugins/media/editor_plugin_src.js index a0d4ef2ae38b8..ea57141d65c6f 100644 --- a/app/code/Magento/Tinymce3/view/base/web/tiny_mce/plugins/media/editor_plugin_src.js +++ b/app/code/Magento/Tinymce3/view/base/web/tiny_mce/plugins/media/editor_plugin_src.js @@ -372,9 +372,15 @@ }; data = node.attr('data-mce-json'); - if (!data) + if (!data || !data.isJSON()) return; + try { + data.evalJSON(true); + } catch { + return; + } + data = JSON.parse(data); typeItem = this.getType(node.attr('class')); From dc479e16316377d727819f971ac2cbbb61c74227 Mon Sep 17 00:00:00 2001 From: Stas Kozar Date: Fri, 22 Mar 2019 13:53:24 +0200 Subject: [PATCH 116/773] MC-15477: Incorrect rendering --- .../Unit/Ui/Component/Listing/Column/PageActionsTest.php | 9 +++++---- .../Cms/Ui/Component/Listing/Column/PageActions.php | 5 +++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/Cms/Test/Unit/Ui/Component/Listing/Column/PageActionsTest.php b/app/code/Magento/Cms/Test/Unit/Ui/Component/Listing/Column/PageActionsTest.php index 9b3165a2c5517..9fe21256c4c4a 100644 --- a/app/code/Magento/Cms/Test/Unit/Ui/Component/Listing/Column/PageActionsTest.php +++ b/app/code/Magento/Cms/Test/Unit/Ui/Component/Listing/Column/PageActionsTest.php @@ -68,12 +68,13 @@ public function testPrepareItemsByPageId() 'label' => __('Delete'), 'confirm' => [ 'title' => __('Delete %1', $title), - 'message' => __('Are you sure you want to delete a %1 record?', $title) + 'message' => __('Are you sure you want to delete a %1 record?', $title), + '__disableTmpl' => true, ], - 'post' => true - ] + 'post' => true, + ], ], - ] + ], ]; $escaper->expects(static::once()) diff --git a/app/code/Magento/Cms/Ui/Component/Listing/Column/PageActions.php b/app/code/Magento/Cms/Ui/Component/Listing/Column/PageActions.php index 26d31456bf61d..cfac3bbf54956 100644 --- a/app/code/Magento/Cms/Ui/Component/Listing/Column/PageActions.php +++ b/app/code/Magento/Cms/Ui/Component/Listing/Column/PageActions.php @@ -85,9 +85,10 @@ public function prepareDataSource(array $dataSource) 'label' => __('Delete'), 'confirm' => [ 'title' => __('Delete %1', $title), - 'message' => __('Are you sure you want to delete a %1 record?', $title) + 'message' => __('Are you sure you want to delete a %1 record?', $title), + '__disableTmpl' => true, ], - 'post' => true + 'post' => true, ]; } if (isset($item['identifier'])) { From 27bfb80a2b764a493063e7e950267970d0e98848 Mon Sep 17 00:00:00 2001 From: Hwashiang Yu Date: Fri, 22 Mar 2019 11:15:31 -0500 Subject: [PATCH 117/773] MC-5867: TinyMCE editor JSON attribute improvement - Reverted JSON value changes - Updated all TinyMCE3 JSON utility method --- .../Tinymce3/view/base/web/tiny_mce/classes/util/JSON.js | 2 +- .../base/web/tiny_mce/plugins/media/editor_plugin_src.js | 8 +------- .../view/base/web/tiny_mce/tiny_mce_jquery_src.js | 2 +- .../view/base/web/tiny_mce/tiny_mce_prototype_src.js | 2 +- .../Tinymce3/view/base/web/tiny_mce/tiny_mce_src.js | 2 +- 5 files changed, 5 insertions(+), 11 deletions(-) diff --git a/app/code/Magento/Tinymce3/view/base/web/tiny_mce/classes/util/JSON.js b/app/code/Magento/Tinymce3/view/base/web/tiny_mce/classes/util/JSON.js index 56886fa50cca6..ccde4b8bc38e9 100644 --- a/app/code/Magento/Tinymce3/view/base/web/tiny_mce/classes/util/JSON.js +++ b/app/code/Magento/Tinymce3/view/base/web/tiny_mce/classes/util/JSON.js @@ -92,7 +92,7 @@ */ parse: function(s) { try { - return eval('(' + s + ')'); + return JSON.parse(s); } catch (ex) { // Ignore } diff --git a/app/code/Magento/Tinymce3/view/base/web/tiny_mce/plugins/media/editor_plugin_src.js b/app/code/Magento/Tinymce3/view/base/web/tiny_mce/plugins/media/editor_plugin_src.js index ea57141d65c6f..a0d4ef2ae38b8 100644 --- a/app/code/Magento/Tinymce3/view/base/web/tiny_mce/plugins/media/editor_plugin_src.js +++ b/app/code/Magento/Tinymce3/view/base/web/tiny_mce/plugins/media/editor_plugin_src.js @@ -372,15 +372,9 @@ }; data = node.attr('data-mce-json'); - if (!data || !data.isJSON()) + if (!data) return; - try { - data.evalJSON(true); - } catch { - return; - } - data = JSON.parse(data); typeItem = this.getType(node.attr('class')); diff --git a/app/code/Magento/Tinymce3/view/base/web/tiny_mce/tiny_mce_jquery_src.js b/app/code/Magento/Tinymce3/view/base/web/tiny_mce/tiny_mce_jquery_src.js index 60dd358414be1..9eddd0f0c3e68 100644 --- a/app/code/Magento/Tinymce3/view/base/web/tiny_mce/tiny_mce_jquery_src.js +++ b/app/code/Magento/Tinymce3/view/base/web/tiny_mce/tiny_mce_jquery_src.js @@ -1193,7 +1193,7 @@ tinymce.create('tinymce.util.Dispatcher', { parse: function(s) { try { - return eval('(' + s + ')'); + return JSON.parse(s); } catch (ex) { // Ignore } diff --git a/app/code/Magento/Tinymce3/view/base/web/tiny_mce/tiny_mce_prototype_src.js b/app/code/Magento/Tinymce3/view/base/web/tiny_mce/tiny_mce_prototype_src.js index ed0b7cb0e50a2..9230c2276c3e2 100644 --- a/app/code/Magento/Tinymce3/view/base/web/tiny_mce/tiny_mce_prototype_src.js +++ b/app/code/Magento/Tinymce3/view/base/web/tiny_mce/tiny_mce_prototype_src.js @@ -945,7 +945,7 @@ tinymce.create('tinymce.util.Dispatcher', { parse: function(s) { try { - return eval('(' + s + ')'); + return JSON.parse(s); } catch (ex) { // Ignore } diff --git a/app/code/Magento/Tinymce3/view/base/web/tiny_mce/tiny_mce_src.js b/app/code/Magento/Tinymce3/view/base/web/tiny_mce/tiny_mce_src.js index 1c53062dd9690..88b60001a88d3 100644 --- a/app/code/Magento/Tinymce3/view/base/web/tiny_mce/tiny_mce_src.js +++ b/app/code/Magento/Tinymce3/view/base/web/tiny_mce/tiny_mce_src.js @@ -918,7 +918,7 @@ tinymce.create('tinymce.util.Dispatcher', { parse: function(s) { try { - return eval('(' + s + ')'); + return JSON.parse(s); } catch (ex) { // Ignore } From 9cc18278b9dcae2dd20c8a9637b4e75ad6579152 Mon Sep 17 00:00:00 2001 From: Anthoula Wojczak Date: Fri, 22 Mar 2019 14:12:48 -0500 Subject: [PATCH 118/773] MC-5858: HTTPS redirecting problem on storefront - add urls to list --- app/code/Magento/Paypal/etc/frontend/di.xml | 1 + app/code/Magento/Vault/etc/frontend/di.xml | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/app/code/Magento/Paypal/etc/frontend/di.xml b/app/code/Magento/Paypal/etc/frontend/di.xml index 8c29ae1e2685f..f19b5dbffa208 100644 --- a/app/code/Magento/Paypal/etc/frontend/di.xml +++ b/app/code/Magento/Paypal/etc/frontend/di.xml @@ -40,6 +40,7 @@ /paypal/billing/ + /paypal/billing_agreement/ /paypal/bml/ /paypal/hostedpro/ /paypal/ipn/ diff --git a/app/code/Magento/Vault/etc/frontend/di.xml b/app/code/Magento/Vault/etc/frontend/di.xml index cb7ab4735d470..b25ac65aae5f1 100644 --- a/app/code/Magento/Vault/etc/frontend/di.xml +++ b/app/code/Magento/Vault/etc/frontend/di.xml @@ -23,4 +23,11 @@ + + + + /vault/ + + + From c2e810336ee97937038feabeec3d843108dddef2 Mon Sep 17 00:00:00 2001 From: Hwashiang Yu Date: Fri, 22 Mar 2019 14:28:14 -0500 Subject: [PATCH 119/773] MC-15048: Update transaction email variable dialog - Updated variable value storage --- .../Email/view/adminhtml/web/js/variables.js | 41 +++++++++---------- 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/app/code/Magento/Email/view/adminhtml/web/js/variables.js b/app/code/Magento/Email/view/adminhtml/web/js/variables.js index 252e21b631457..ea34373babbb3 100644 --- a/app/code/Magento/Email/view/adminhtml/web/js/variables.js +++ b/app/code/Magento/Email/view/adminhtml/web/js/variables.js @@ -21,6 +21,7 @@ define([ overlayShowEffectOptions: null, overlayHideEffectOptions: null, insertFunction: 'Variables.insertVariable', + variablesValue: [], /** * @param {*} textareaElementId @@ -55,8 +56,9 @@ define([ this.variablesContent += '
  • ' + variableGroup.label.escapeHTML() + '
  • '; variableGroup.value.each(function (variable) { if (variable.value && variable.label) { + this.variablesValue.push(variable.value); this.variablesContent += '
  • ' + - this.prepareVariableRow(variable.value.escapeHTML(), variable.label.escapeHTML()) + '
  • '; + this.prepareVariableRow(this.variablesValue.length, variable.label) + ''; } }.bind(this)); } @@ -97,27 +99,24 @@ define([ }, /** - * @param {String} varValue + * @param {Number} index * @param {*} varLabel * @return {String} */ - prepareVariableRow: function (varValue, varLabel) { - var value = varValue.replace(/"/g, '"').replace(/'/g, '\\''), - content = '' + - varLabel + - ''; - - return content; + prepareVariableRow: function (index, varLabel) { + return '' + + varLabel.escapeHTML() + + ''; }, /** - * @param {*} value + * @param {*} variable */ - insertVariable: function (value) { + insertVariable: function (variable) { var windowId = this.dialogWindowId, textareaElm, scrollPos; @@ -126,14 +125,16 @@ define([ if (textareaElm) { scrollPos = textareaElm.scrollTop; - updateElementAtCursor(textareaElm, value); + if (!isNaN(variable)) { + updateElementAtCursor(textareaElm, Variables.variablesValue[variable - 1]); + } else { + updateElementAtCursor(textareaElm, variable); + } textareaElm.focus(); textareaElm.scrollTop = scrollPos; jQuery(textareaElm).change(); textareaElm = null; } - - return; } }; @@ -170,8 +171,6 @@ define([ } else { this.openChooser(this.variables); } - - return; }, /** @@ -192,8 +191,6 @@ define([ Variables.closeDialogWindow(); this.editor.execCommand('mceInsertContent', false, value); } - - return; } }; }); From 4703c038e19474c7657a5ba4f617ee02ec31c66c Mon Sep 17 00:00:00 2001 From: Hwashiang Yu Date: Fri, 22 Mar 2019 16:18:57 -0500 Subject: [PATCH 120/773] MC-15048: Update transaction email variable dialog - Resolved static test failures --- app/code/Magento/Email/Model/Template.php | 2 ++ app/code/Magento/Email/view/adminhtml/web/js/variables.js | 1 + 2 files changed, 3 insertions(+) diff --git a/app/code/Magento/Email/Model/Template.php b/app/code/Magento/Email/Model/Template.php index 3ee87cb81dfc4..7672d900615ce 100644 --- a/app/code/Magento/Email/Model/Template.php +++ b/app/code/Magento/Email/Model/Template.php @@ -418,6 +418,8 @@ public function setOptions(array $options) } /** + * Get filter factory + * * @return \Magento\Email\Model\Template\FilterFactory */ protected function getFilterFactory() diff --git a/app/code/Magento/Email/view/adminhtml/web/js/variables.js b/app/code/Magento/Email/view/adminhtml/web/js/variables.js index ea34373babbb3..7a671823ace02 100644 --- a/app/code/Magento/Email/view/adminhtml/web/js/variables.js +++ b/app/code/Magento/Email/view/adminhtml/web/js/variables.js @@ -125,6 +125,7 @@ define([ if (textareaElm) { scrollPos = textareaElm.scrollTop; + if (!isNaN(variable)) { updateElementAtCursor(textareaElm, Variables.variablesValue[variable - 1]); } else { From 36f1b0531be862ffdd22417ec0c217f80b490d11 Mon Sep 17 00:00:00 2001 From: Hwashiang Yu Date: Fri, 22 Mar 2019 16:50:38 -0500 Subject: [PATCH 121/773] MC-15048: Update transaction email variable dialog - Resolved unit and integration test failures --- .../Email/Test/Unit/Model/TemplateTest.php | 28 ++++++++++--------- .../Magento/Email/Model/TemplateTest.php | 4 +-- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/app/code/Magento/Email/Test/Unit/Model/TemplateTest.php b/app/code/Magento/Email/Test/Unit/Model/TemplateTest.php index 5464ca51cbe35..5429530fd1f61 100644 --- a/app/code/Magento/Email/Test/Unit/Model/TemplateTest.php +++ b/app/code/Magento/Email/Test/Unit/Model/TemplateTest.php @@ -595,19 +595,21 @@ public function getVariablesOptionArrayDataProvider() 'templateVariables' => '{"store url=\"\"":"Store Url","var logo_url":"Email Logo Image Url",' . '"var customer.name":"Customer Name"}', 'expectedResult' => [ - 'label' => __('Template Variables'), - 'value' => [ - [ - 'value' => '{{store url=""}}', - 'label' => __('%1', 'Store Url'), - ], - [ - 'value' => '{{var logo_url}}', - 'label' => __('%1', 'Email Logo Image Url'), - ], - [ - 'value' => '{{var customer.name}}', - 'label' => __('%1', 'Customer Name'), + [ + 'label' => __('Template Variables'), + 'value' => [ + [ + 'value' => '{{store url=""}}', + 'label' => __('%1', 'Store Url'), + ], + [ + 'value' => '{{var logo_url}}', + 'label' => __('%1', 'Email Logo Image Url'), + ], + [ + 'value' => '{{var customer.name}}', + 'label' => __('%1', 'Customer Name'), + ], ], ], ], diff --git a/dev/tests/integration/testsuite/Magento/Email/Model/TemplateTest.php b/dev/tests/integration/testsuite/Magento/Email/Model/TemplateTest.php index 7789a79794f39..2d12eefc286c6 100644 --- a/dev/tests/integration/testsuite/Magento/Email/Model/TemplateTest.php +++ b/dev/tests/integration/testsuite/Magento/Email/Model/TemplateTest.php @@ -703,8 +703,8 @@ public function testGetVariablesOptionArrayInGroup() $testTemplateVariables = '{"var data.name":"Sender Name","var data.email":"Sender Email"}'; $this->model->setOrigTemplateVariables($testTemplateVariables); $variablesOptionArray = $this->model->getVariablesOptionArray(true); - $this->assertEquals('Template Variables', $variablesOptionArray['label']->getText()); - $this->assertEquals($this->model->getVariablesOptionArray(), $variablesOptionArray['value']); + $this->assertEquals('Template Variables', $variablesOptionArray[0]['label']->getText()); + $this->assertEquals($this->model->getVariablesOptionArray(), $variablesOptionArray[0]['value']); } /** From 5cfccc1e137a9c3bffbbab80fd3d2a50f35a9030 Mon Sep 17 00:00:00 2001 From: Dmytro Voskoboinikov Date: Mon, 25 Mar 2019 11:19:06 -0500 Subject: [PATCH 122/773] MC-5949: Calculated Labels in Columns Widget --- .../Ui/DataProvider/Product/Form/Modifier/EavTest.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/EavTest.php b/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/EavTest.php index 8cb59b1a2ccec..91a09c907de65 100755 --- a/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/EavTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/EavTest.php @@ -480,11 +480,11 @@ public function testSetupAttributeMetaDefaultAttribute( ['value' => ['test1', 'test2'], 'label' => 'Array label'], ]; $attributeOptionsExpected = [ - ['value' => '1', 'label' => 'Int label'], - ['value' => '1.5', 'label' => 'Float label'], - ['value' => '1', 'label' => 'Boolean label'], - ['value' => 'string', 'label' => 'String label'], - ['value' => ['test1', 'test2'], 'label' => 'Array label'], + ['value' => '1', 'label' => 'Int label', '__disableTmpl' => true], + ['value' => '1.5', 'label' => 'Float label', '__disableTmpl' => true], + ['value' => '1', 'label' => 'Boolean label', '__disableTmpl' => true], + ['value' => 'string', 'label' => 'String label', '__disableTmpl' => true], + ['value' => ['test1', 'test2'], 'label' => 'Array label', '__disableTmpl' => true], ]; $this->productMock->method('getId')->willReturn($productId); From be1c84186b22ba165386142b27544ef05c09b5d6 Mon Sep 17 00:00:00 2001 From: Cari Spruiell Date: Mon, 25 Mar 2019 12:56:07 -0500 Subject: [PATCH 123/773] MC-5894: Gift Card Account --- .../view/frontend/templates/paypal/button.phtml | 2 +- .../Customer/Test/Unit/Model/AccountManagementTest.php | 9 +++------ .../Catalog/Test/Fixture/Product/CustomOptions.php | 2 +- .../Test/TestCase/SearchTermsReportEntityTest.php | 2 +- .../Customer/Block/Adminhtml/Edit/Tab/View/SalesTest.php | 2 +- .../Sales/Block/Adminhtml/Order/Create/FormTest.php | 2 +- .../Sales/Block/Adminhtml/Order/View/InfoTest.php | 6 +++--- 7 files changed, 11 insertions(+), 14 deletions(-) diff --git a/app/code/Magento/Braintree/view/frontend/templates/paypal/button.phtml b/app/code/Magento/Braintree/view/frontend/templates/paypal/button.phtml index c1ef461ecae7c..98bba7d6044cb 100644 --- a/app/code/Magento/Braintree/view/frontend/templates/paypal/button.phtml +++ b/app/code/Magento/Braintree/view/frontend/templates/paypal/button.phtml @@ -8,7 +8,7 @@ * @var \Magento\Braintree\Block\Paypal\Button $block */ -$id = $block->getContainerId() . mt_rand(); +$id = $block->getContainerId() . random_int(0, PHP_INT_MAX); $config = [ 'Magento_Braintree/js/paypal/button' => [ diff --git a/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php b/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php index 22c9d90c086dc..a773fc2c10932 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php @@ -1238,8 +1238,7 @@ public function testInitiatePasswordResetEmailReminder() $storeId = 1; - mt_srand(mt_rand() + (100000000 * (float)microtime()) % PHP_INT_MAX); - $hash = md5(uniqid(microtime() . mt_rand(0, mt_getrandmax()), true)); + $hash = md5(uniqid(microtime() . random_int(0, PHP_INT_MAX), true)); $this->emailNotificationMock->expects($this->once()) ->method('passwordReminder') @@ -1263,8 +1262,7 @@ public function testInitiatePasswordResetEmailReset() $templateIdentifier = 'Template Identifier'; $sender = 'Sender'; - mt_srand(mt_rand() + (100000000 * (float)microtime()) % PHP_INT_MAX); - $hash = md5(uniqid(microtime() . mt_rand(0, mt_getrandmax()), true)); + $hash = md5(uniqid(microtime() . random_int(0, PHP_INT_MAX), true)); $this->emailNotificationMock->expects($this->once()) ->method('passwordResetConfirmation') @@ -1288,8 +1286,7 @@ public function testInitiatePasswordResetNoTemplate() $templateIdentifier = 'Template Identifier'; $sender = 'Sender'; - mt_srand(mt_rand() + (100000000 * (float)microtime()) % PHP_INT_MAX); - $hash = md5(uniqid(microtime() . mt_rand(0, mt_getrandmax()), true)); + $hash = md5(uniqid(microtime() . random_int(0, PHP_INT_MAX), true)); $this->prepareInitiatePasswordReset($email, $templateIdentifier, $sender, $storeId, $customerId, $hash); diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/Product/CustomOptions.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/Product/CustomOptions.php index 74452100b6955..0b18c3989e96b 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/Product/CustomOptions.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/Product/CustomOptions.php @@ -45,7 +45,7 @@ public function __construct( if (isset($data['dataset']) && isset($this->params['repository'])) { $this->data = $repositoryFactory->get($this->params['repository'])->get($data['dataset']); - $this->data = $this->replaceData($this->data, mt_rand()); + $this->data = $this->replaceData($this->data, random_int(0, PHP_INT_MAX)); $this->customOptions = $this->data; } if (isset($data['import_products'])) { diff --git a/dev/tests/functional/tests/app/Magento/Reports/Test/TestCase/SearchTermsReportEntityTest.php b/dev/tests/functional/tests/app/Magento/Reports/Test/TestCase/SearchTermsReportEntityTest.php index 108bbfcdf33ab..60be714e9dbbb 100644 --- a/dev/tests/functional/tests/app/Magento/Reports/Test/TestCase/SearchTermsReportEntityTest.php +++ b/dev/tests/functional/tests/app/Magento/Reports/Test/TestCase/SearchTermsReportEntityTest.php @@ -96,7 +96,7 @@ public function test($product, $countProducts, $countSearch) */ protected function createProducts($product, $countProduct) { - $name = 'simpleProductName' . mt_rand(); + $name = 'simpleProductName' . random_int(0, PHP_INT_MAX); for ($i = 0; $i < $countProduct; $i++) { $productFixture = $this->fixtureFactory->createByCode( 'catalogProductSimple', diff --git a/dev/tests/integration/testsuite/Magento/Customer/Block/Adminhtml/Edit/Tab/View/SalesTest.php b/dev/tests/integration/testsuite/Magento/Customer/Block/Adminhtml/Edit/Tab/View/SalesTest.php index c0772bc2be0e6..68410c44f29c3 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Block/Adminhtml/Edit/Tab/View/SalesTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Block/Adminhtml/Edit/Tab/View/SalesTest.php @@ -53,7 +53,7 @@ public function setUp() \Magento\Framework\View\LayoutInterface::class )->createBlock( \Magento\Customer\Block\Adminhtml\Edit\Tab\View\Sales::class, - 'sales_' . mt_rand(), + 'sales_' . random_int(0, PHP_INT_MAX), ['coreRegistry' => $this->coreRegistry] )->setTemplate( 'tab/view/sales.phtml' diff --git a/dev/tests/integration/testsuite/Magento/Sales/Block/Adminhtml/Order/Create/FormTest.php b/dev/tests/integration/testsuite/Magento/Sales/Block/Adminhtml/Order/Create/FormTest.php index abdbab2c24d16..952116784640d 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/Block/Adminhtml/Order/Create/FormTest.php +++ b/dev/tests/integration/testsuite/Magento/Sales/Block/Adminhtml/Order/Create/FormTest.php @@ -68,7 +68,7 @@ protected function setUp() $layout = $this->objectManager->get(LayoutInterface::class); $this->block = $layout->createBlock( Form::class, - 'order_create_block' . mt_rand(), + 'order_create_block' . random_int(0, PHP_INT_MAX), ['sessionQuote' => $this->session] ); parent::setUp(); diff --git a/dev/tests/integration/testsuite/Magento/Sales/Block/Adminhtml/Order/View/InfoTest.php b/dev/tests/integration/testsuite/Magento/Sales/Block/Adminhtml/Order/View/InfoTest.php index b3fee1124d15f..cede79b1687a1 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/Block/Adminhtml/Order/View/InfoTest.php +++ b/dev/tests/integration/testsuite/Magento/Sales/Block/Adminhtml/Order/View/InfoTest.php @@ -21,7 +21,7 @@ public function testCustomerGridAction() /** @var \Magento\Sales\Block\Adminhtml\Order\View\Info $infoBlock */ $infoBlock = $layout->createBlock( \Magento\Sales\Block\Adminhtml\Order\View\Info::class, - 'info_block' . mt_rand(), + 'info_block' . random_int(0, PHP_INT_MAX), [] ); @@ -38,7 +38,7 @@ public function testGetCustomerGroupName() /** @var \Magento\Sales\Block\Adminhtml\Order\View\Info $customerGroupBlock */ $customerGroupBlock = $layout->createBlock( \Magento\Sales\Block\Adminhtml\Order\View\Info::class, - 'info_block' . mt_rand(), + 'info_block' . random_int(0, PHP_INT_MAX), ['registry' => $this->_putOrderIntoRegistry()] ); @@ -60,7 +60,7 @@ public function testGetCustomerAccountData() /** @var \Magento\Sales\Block\Adminhtml\Order\View\Info $customerGroupBlock */ $customerGroupBlock = $layout->createBlock( \Magento\Sales\Block\Adminhtml\Order\View\Info::class, - 'info_block' . mt_rand(), + 'info_block' . random_int(0, PHP_INT_MAX), ['registry' => $this->_putOrderIntoRegistry($orderData)] ); From 8cdfb6af0e2884808f3fd2f91da86086bf4bfd7f Mon Sep 17 00:00:00 2001 From: Cari Spruiell Date: Mon, 25 Mar 2019 14:58:31 -0500 Subject: [PATCH 124/773] MC-5894: Gift Card Account --- .../Magento/Sales/Block/Adminhtml/Order/View/InfoTest.php | 2 ++ .../Test/Legacy/_files/security/unsecure_php_functions.php | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/dev/tests/integration/testsuite/Magento/Sales/Block/Adminhtml/Order/View/InfoTest.php b/dev/tests/integration/testsuite/Magento/Sales/Block/Adminhtml/Order/View/InfoTest.php index cede79b1687a1..b309fb788b213 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/Block/Adminhtml/Order/View/InfoTest.php +++ b/dev/tests/integration/testsuite/Magento/Sales/Block/Adminhtml/Order/View/InfoTest.php @@ -27,6 +27,8 @@ public function testCustomerGridAction() $result = $infoBlock->getCustomerAccountData(); $this->assertEquals([], $result, 'Customer has additional account data.'); + + $testStaticTest = mt_rand(); } /** 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 index 10c0da47cb2d2..f0a48207225e2 100644 --- 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 @@ -84,4 +84,8 @@ 'replacement' => '', 'exclude' => [] ], + 'mt_rand' => [ + 'replacement' => 'random_int', + 'exclude' => [] + ], ]; From d755a62bfe92438e1855a3b36769359cd91511fa Mon Sep 17 00:00:00 2001 From: Cari Spruiell Date: Mon, 25 Mar 2019 17:00:29 -0500 Subject: [PATCH 125/773] MC-5894: Gift Card Account --- .../Magento/Customer/Api/GroupRepositoryTest.php | 2 +- .../ConfigurableProduct/ConfigurableAttributesData.php | 4 ++-- .../Framework/Model/ResourceModel/Db/ProfilerTest.php | 2 +- .../Magento/Framework/Mview/View/ChangelogTest.php | 2 +- .../Magento/Sales/Block/Adminhtml/Order/View/InfoTest.php | 2 -- .../Controller/Adminhtml/Product/AttributeTest.php | 2 +- .../Legacy/_files/security/unsecure_php_functions.php | 5 +++++ .../Magento/Framework/DB/Test/Unit/Ddl/TriggerTest.php | 8 ++++---- .../Framework/Mview/Test/Unit/View/ChangelogTest.php | 4 ++-- .../src/Magento/Setup/Fixtures/BundleProductsFixture.php | 2 +- .../Setup/Fixtures/ConfigurableProductsFixture.php | 4 +--- .../Setup/Fixtures/ImagesGenerator/ImagesGenerator.php | 2 +- setup/src/Magento/Setup/Fixtures/OrdersFixture.php | 6 +++--- setup/src/Magento/Setup/Fixtures/PriceProvider.php | 5 ++--- setup/src/Magento/Setup/Fixtures/Quote/QuoteGenerator.php | 6 +++--- .../src/Magento/Setup/Fixtures/SimpleProductsFixture.php | 6 ++---- .../Model/FixtureGenerator/CustomerTemplateGenerator.php | 2 +- .../Magento/Setup/Test/Unit/Model/DataGeneratorTest.php | 2 +- 18 files changed, 32 insertions(+), 34 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/Customer/Api/GroupRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Customer/Api/GroupRepositoryTest.php index 999a2daa26065..4ed32258deecf 100644 --- a/dev/tests/api-functional/testsuite/Magento/Customer/Api/GroupRepositoryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Customer/Api/GroupRepositoryTest.php @@ -874,7 +874,7 @@ public function testSearchGroupsDataProvider() return [ ['tax_class_id', 3, []], ['tax_class_id', 0, null], - ['code', md5(mt_rand(0, 10000000000) . time()), null], + ['code', md5(random_int(0, 10000000000) . time()), null], [ 'id', 0, 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 ef86367a8079b..fdcf2d15d4288 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 @@ -360,7 +360,7 @@ protected function addVariationMatrix(array $variationsMatrix, array $attribute, /* If empty matrix add one empty row */ if (empty($variationsMatrix)) { - $variationIsolation = mt_rand(10000, 70000); + $variationIsolation = random_int(10000, 70000); $variationsMatrix = [ [ 'name' => "In configurable product {$variationIsolation}", @@ -370,7 +370,7 @@ protected function addVariationMatrix(array $variationsMatrix, array $attribute, } foreach ($variationsMatrix as $rowKey => $row) { - $randIsolation = mt_rand(1, 100); + $randIsolation = random_int(1, 100); $rowName = $row['name']; $rowSku = $row['sku']; $index = 1; diff --git a/dev/tests/integration/testsuite/Magento/Framework/Model/ResourceModel/Db/ProfilerTest.php b/dev/tests/integration/testsuite/Magento/Framework/Model/ResourceModel/Db/ProfilerTest.php index 7741f2a31fd90..5046c3328030c 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/Model/ResourceModel/Db/ProfilerTest.php +++ b/dev/tests/integration/testsuite/Magento/Framework/Model/ResourceModel/Db/ProfilerTest.php @@ -23,7 +23,7 @@ class ProfilerTest extends \PHPUnit\Framework\TestCase public static function setUpBeforeClass() { - self::$_testResourceName = 'testtest_' . mt_rand(1000, 9999) . '_setup'; + self::$_testResourceName = 'testtest_' . random_int(1000, 9999) . '_setup'; \Magento\Framework\Profiler::enable(); } diff --git a/dev/tests/integration/testsuite/Magento/Framework/Mview/View/ChangelogTest.php b/dev/tests/integration/testsuite/Magento/Framework/Mview/View/ChangelogTest.php index c047bd4fffd3d..700c45ffc1119 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/Mview/View/ChangelogTest.php +++ b/dev/tests/integration/testsuite/Magento/Framework/Mview/View/ChangelogTest.php @@ -95,7 +95,7 @@ public function testGetVersion() $model->create(); $this->assertEquals(0, $model->getVersion()); $changelogName = $this->resource->getTableName($model->getName()); - $this->connection->insert($changelogName, [$model->getColumnName() => mt_rand(1, 200)]); + $this->connection->insert($changelogName, [$model->getColumnName() => random_int(1, 200)]); $this->assertEquals($this->connection->lastInsertId($changelogName, 'version_id'), $model->getVersion()); $model->drop(); } diff --git a/dev/tests/integration/testsuite/Magento/Sales/Block/Adminhtml/Order/View/InfoTest.php b/dev/tests/integration/testsuite/Magento/Sales/Block/Adminhtml/Order/View/InfoTest.php index b309fb788b213..cede79b1687a1 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/Block/Adminhtml/Order/View/InfoTest.php +++ b/dev/tests/integration/testsuite/Magento/Sales/Block/Adminhtml/Order/View/InfoTest.php @@ -27,8 +27,6 @@ public function testCustomerGridAction() $result = $infoBlock->getCustomerAccountData(); $this->assertEquals([], $result, 'Customer has additional account data.'); - - $testStaticTest = mt_rand(); } /** diff --git a/dev/tests/integration/testsuite/Magento/Swatches/Controller/Adminhtml/Product/AttributeTest.php b/dev/tests/integration/testsuite/Magento/Swatches/Controller/Adminhtml/Product/AttributeTest.php index f806674d29705..758a8331cddcb 100644 --- a/dev/tests/integration/testsuite/Magento/Swatches/Controller/Adminhtml/Product/AttributeTest.php +++ b/dev/tests/integration/testsuite/Magento/Swatches/Controller/Adminhtml/Product/AttributeTest.php @@ -41,7 +41,7 @@ protected function setUp() */ private function getRandomColor() : string { - return '#' . str_pad(dechex(mt_rand(0, 0xFFFFFF)), 6, '0', STR_PAD_LEFT); + return '#' . str_pad(dechex(random_int(0, 0xFFFFFF)), 6, '0', STR_PAD_LEFT); } /** 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 index f0a48207225e2..598fb734b7738 100644 --- 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 @@ -73,6 +73,11 @@ 'type' => 'module', 'name' => 'Magento_Authorizenet', 'path' => 'Model/Directpost/Response.php' + ], + [ + 'type' => 'module', + 'name' => 'Magento_Support', + 'path' => 'Console/Command/AbstractBackupDumpCommand.php' ] ] ], diff --git a/lib/internal/Magento/Framework/DB/Test/Unit/Ddl/TriggerTest.php b/lib/internal/Magento/Framework/DB/Test/Unit/Ddl/TriggerTest.php index f3d84b83ce053..5e3840a0bc348 100644 --- a/lib/internal/Magento/Framework/DB/Test/Unit/Ddl/TriggerTest.php +++ b/lib/internal/Magento/Framework/DB/Test/Unit/Ddl/TriggerTest.php @@ -47,7 +47,7 @@ public function testGetListOfTimes() */ public function testGetNameWithSetName() { - $triggerName = 'TEST_TRIGGER_NAME' . mt_rand(100, 999); + $triggerName = 'TEST_TRIGGER_NAME' . random_int(100, 999); $this->_object->setName($triggerName); $this->assertEquals(strtolower($triggerName), $this->_object->getName()); @@ -101,7 +101,7 @@ public function testSetTableName() */ public function testGetNameWithException() { - $tableName = 'TEST_TABLE_NAME_' . mt_rand(100, 999); + $tableName = 'TEST_TABLE_NAME_' . random_int(100, 999); $event = \Magento\Framework\DB\Ddl\Trigger::EVENT_INSERT; $this->_object->setTable($tableName)->setTime(\Magento\Framework\DB\Ddl\Trigger::TIME_AFTER)->setEvent($event); @@ -117,7 +117,7 @@ public function testGetNameWithException() */ public function testGetTimeWithException() { - $tableName = 'TEST_TABLE_NAME_' . mt_rand(100, 999); + $tableName = 'TEST_TABLE_NAME_' . random_int(100, 999); $event = \Magento\Framework\DB\Ddl\Trigger::EVENT_INSERT; $this->_object->setTable($tableName)->setEvent($event); @@ -148,7 +148,7 @@ public function testGetTableWithException() */ public function testGetEventWithException() { - $tableName = 'TEST_TABLE_NAME_' . mt_rand(100, 999); + $tableName = 'TEST_TABLE_NAME_' . random_int(100, 999); $this->_object->setTable($tableName)->setTime(\Magento\Framework\DB\Ddl\Trigger::TIME_AFTER); diff --git a/lib/internal/Magento/Framework/Mview/Test/Unit/View/ChangelogTest.php b/lib/internal/Magento/Framework/Mview/Test/Unit/View/ChangelogTest.php index b16b7c87e87ac..ac88684842dc0 100644 --- a/lib/internal/Magento/Framework/Mview/Test/Unit/View/ChangelogTest.php +++ b/lib/internal/Magento/Framework/Mview/Test/Unit/View/ChangelogTest.php @@ -230,7 +230,7 @@ public function testGetListWithException() $this->expectException('Exception'); $this->expectExceptionMessage("Table {$changelogTableName} does not exist"); $this->model->setViewId('viewIdtest'); - $this->model->getList(mt_rand(1, 200), mt_rand(201, 400)); + $this->model->getList(random_int(1, 200), random_int(201, 400)); } public function testClearWithException() @@ -242,7 +242,7 @@ public function testClearWithException() $this->expectException('Exception'); $this->expectExceptionMessage("Table {$changelogTableName} does not exist"); $this->model->setViewId('viewIdtest'); - $this->model->clear(mt_rand(1, 200)); + $this->model->clear(random_int(1, 200)); } /** diff --git a/setup/src/Magento/Setup/Fixtures/BundleProductsFixture.php b/setup/src/Magento/Setup/Fixtures/BundleProductsFixture.php index 99c25089e68bb..d733389bf17cb 100644 --- a/setup/src/Magento/Setup/Fixtures/BundleProductsFixture.php +++ b/setup/src/Magento/Setup/Fixtures/BundleProductsFixture.php @@ -165,7 +165,7 @@ public function execute() 'meta_title' => $skuClosure, 'price' => function ($index) use ($priceTypeClosure) { return $priceTypeClosure($index) === LinkInterface::PRICE_TYPE_PERCENT - ? mt_rand(10, 90) + ? random_int(10, 90) : $this->priceProvider->getPrice($index); }, 'priceType' => $priceTypeClosure, diff --git a/setup/src/Magento/Setup/Fixtures/ConfigurableProductsFixture.php b/setup/src/Magento/Setup/Fixtures/ConfigurableProductsFixture.php index 00c60a2a8a6a5..a45261049567e 100644 --- a/setup/src/Magento/Setup/Fixtures/ConfigurableProductsFixture.php +++ b/setup/src/Magento/Setup/Fixtures/ConfigurableProductsFixture.php @@ -317,10 +317,9 @@ private function getDefaultAttributeSetsConfig(array $defaultAttributeSets, $con { $attributeSetClosure = function ($index) use ($defaultAttributeSets) { $attributeSetAmount = count(array_keys($defaultAttributeSets)); - mt_srand($index); return $attributeSetAmount > ($index - 1) % (int)$this->fixtureModel->getValue('categories', 30) - ? array_keys($defaultAttributeSets)[mt_rand(0, $attributeSetAmount - 1)] + ? array_keys($defaultAttributeSets)[random_int(0, $attributeSetAmount - 1)] : 'Default'; }; $productsPerSet = []; @@ -855,7 +854,6 @@ private function getDescriptionClosure( $configurableProductsCount / ($simpleProductsCount + $configurableProductsCount) ) ); - mt_srand($index); return $this->dataGenerator->generate( $minAmountOfWordsDescription, $maxAmountOfWordsDescription, diff --git a/setup/src/Magento/Setup/Fixtures/ImagesGenerator/ImagesGenerator.php b/setup/src/Magento/Setup/Fixtures/ImagesGenerator/ImagesGenerator.php index b5ea18f9cee2b..4bdb837a8aebe 100644 --- a/setup/src/Magento/Setup/Fixtures/ImagesGenerator/ImagesGenerator.php +++ b/setup/src/Magento/Setup/Fixtures/ImagesGenerator/ImagesGenerator.php @@ -51,7 +51,7 @@ public function generate($config) $image = imagecreate($config['image-width'], $config['image-height']); $bgColor = imagecolorallocate($image, 240, 240, 240); - $fgColor = imagecolorallocate($image, mt_rand(0, 230), mt_rand(0, 230), mt_rand(0, 230)); + $fgColor = imagecolorallocate($image, random_int(0, 230), random_int(0, 230), random_int(0, 230)); $colors = [$fgColor, $bgColor]; imagefilledrectangle($image, 0, 0, $config['image-width'], $config['image-height'], $bgColor); diff --git a/setup/src/Magento/Setup/Fixtures/OrdersFixture.php b/setup/src/Magento/Setup/Fixtures/OrdersFixture.php index 9fbec3b3741b2..82238650be740 100644 --- a/setup/src/Magento/Setup/Fixtures/OrdersFixture.php +++ b/setup/src/Magento/Setup/Fixtures/OrdersFixture.php @@ -324,9 +324,9 @@ public function execute() while ($entityId <= $requestedOrders) { $batchNumber++; $productCount = [ - Type::TYPE_SIMPLE => mt_rand($orderSimpleCountFrom, $orderSimpleCountTo), - Configurable::TYPE_CODE => mt_rand($orderConfigurableCountFrom, $orderConfigurableCountTo), - self::BIG_CONFIGURABLE_TYPE => mt_rand($orderBigConfigurableCountFrom, $orderBigConfigurableCountTo) + Type::TYPE_SIMPLE => random_int($orderSimpleCountFrom, $orderSimpleCountTo), + Configurable::TYPE_CODE => random_int($orderConfigurableCountFrom, $orderConfigurableCountTo), + self::BIG_CONFIGURABLE_TYPE => random_int($orderBigConfigurableCountFrom, $orderBigConfigurableCountTo) ]; $order = [ '%itemsPerOrder%' => array_sum($productCount), diff --git a/setup/src/Magento/Setup/Fixtures/PriceProvider.php b/setup/src/Magento/Setup/Fixtures/PriceProvider.php index c1cb68a4832e2..17bd2270a4fbe 100644 --- a/setup/src/Magento/Setup/Fixtures/PriceProvider.php +++ b/setup/src/Magento/Setup/Fixtures/PriceProvider.php @@ -19,8 +19,7 @@ class PriceProvider */ public function getPrice($productIndex) { - mt_srand($productIndex); - switch (mt_rand(0, 3)) { + switch (random_int(0, 3)) { case 0: return 9.99; case 1: @@ -28,7 +27,7 @@ public function getPrice($productIndex) case 2: return 1; case 3: - return mt_rand(1, 10000) / 10; + return random_int(1, 10000) / 10; } } } diff --git a/setup/src/Magento/Setup/Fixtures/Quote/QuoteGenerator.php b/setup/src/Magento/Setup/Fixtures/Quote/QuoteGenerator.php index 0a63fa5799715..6f67a2a63a2e0 100644 --- a/setup/src/Magento/Setup/Fixtures/Quote/QuoteGenerator.php +++ b/setup/src/Magento/Setup/Fixtures/Quote/QuoteGenerator.php @@ -179,15 +179,15 @@ public function generateQuotes() private function saveQuoteWithQuoteItems($entityId, \Generator $itemIdSequence) { $productCount = [ - Type::TYPE_SIMPLE => mt_rand( + Type::TYPE_SIMPLE => random_int( $this->config->getSimpleCountFrom(), $this->config->getSimpleCountTo() ), - Configurable::TYPE_CODE => mt_rand( + Configurable::TYPE_CODE => random_int( $this->config->getConfigurableCountFrom(), $this->config->getConfigurableCountTo() ), - QuoteConfiguration::BIG_CONFIGURABLE_TYPE => mt_rand( + QuoteConfiguration::BIG_CONFIGURABLE_TYPE => random_int( $this->config->getBigConfigurableCountFrom(), $this->config->getBigConfigurableCountTo() ) diff --git a/setup/src/Magento/Setup/Fixtures/SimpleProductsFixture.php b/setup/src/Magento/Setup/Fixtures/SimpleProductsFixture.php index 62c76d8a2fe11..ca20c5e5d1ca2 100644 --- a/setup/src/Magento/Setup/Fixtures/SimpleProductsFixture.php +++ b/setup/src/Magento/Setup/Fixtures/SimpleProductsFixture.php @@ -185,10 +185,9 @@ public function execute() $additionalAttributeSets = $this->getAdditionalAttributeSets(); $attributeSet = function ($index) use ($defaultAttributeSets, $additionalAttributeSets) { - mt_srand($index); $attributeSetCount = count(array_keys($defaultAttributeSets)); if ($attributeSetCount > (($index - 1) % (int)$this->fixtureModel->getValue('categories', 30))) { - return array_keys($defaultAttributeSets)[mt_rand(0, count(array_keys($defaultAttributeSets)) - 1)]; + return array_keys($defaultAttributeSets)[random_int(0, count(array_keys($defaultAttributeSets)) - 1)]; } else { $customSetsAmount = count($additionalAttributeSets); return $customSetsAmount @@ -205,10 +204,9 @@ public function execute() $additionalAttributeSets ) { $attributeValues = []; - mt_srand($index); if (isset($defaultAttributeSets[$attributeSetId])) { foreach ($defaultAttributeSets[$attributeSetId] as $attributeCode => $values) { - $attributeValues[$attributeCode] = $values[mt_rand(0, count($values) - 1)]; + $attributeValues[$attributeCode] = $values[random_int(0, count($values) - 1)]; } } diff --git a/setup/src/Magento/Setup/Model/FixtureGenerator/CustomerTemplateGenerator.php b/setup/src/Magento/Setup/Model/FixtureGenerator/CustomerTemplateGenerator.php index 5c43950d49bde..0c99c235d38c1 100644 --- a/setup/src/Magento/Setup/Model/FixtureGenerator/CustomerTemplateGenerator.php +++ b/setup/src/Magento/Setup/Model/FixtureGenerator/CustomerTemplateGenerator.php @@ -67,7 +67,7 @@ public function generateEntity() */ private function getCustomerTemplate() { - $customerRandomizerNumber = crc32(mt_rand(1, PHP_INT_MAX)); + $customerRandomizerNumber = crc32(random_int(1, PHP_INT_MAX)); $now = new \DateTime(); diff --git a/setup/src/Magento/Setup/Test/Unit/Model/DataGeneratorTest.php b/setup/src/Magento/Setup/Test/Unit/Model/DataGeneratorTest.php index 4e02fcea2d72a..ab6701bc345bf 100644 --- a/setup/src/Magento/Setup/Test/Unit/Model/DataGeneratorTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Model/DataGeneratorTest.php @@ -38,7 +38,7 @@ public function testGenerateWithKey() $key = 'generate-test'; $data = file(__DIR__ . self::PATH_TO_CSV_FILE); - $wordCount = mt_rand(1, count($data)); + $wordCount = random_int(1, count($data)); $model = new DataGenerator(__DIR__ . self::PATH_TO_CSV_FILE); $result = $model->generate($wordCount, $wordCount, $key); From 7539afebec222583db32eea1b86f2f362d0104ef Mon Sep 17 00:00:00 2001 From: Yaroslav Rogoza Date: Tue, 26 Mar 2019 09:36:01 +0100 Subject: [PATCH 126/773] Convert OnePageCheckoutJsValidationTest to MFTF --- ...refrontOnePageCheckoutJsValidationTest.xml | 37 +++++++++++++++++++ .../OnePageCheckoutJsValidationTest.xml | 1 + 2 files changed, 38 insertions(+) create mode 100644 app/code/Magento/Checkout/Test/Mftf/Test/StorefrontOnePageCheckoutJsValidationTest.xml diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontOnePageCheckoutJsValidationTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontOnePageCheckoutJsValidationTest.xml new file mode 100644 index 0000000000000..b699ecdc5a152 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontOnePageCheckoutJsValidationTest.xml @@ -0,0 +1,37 @@ + + + + + + + + + <description value="Js validation error messages must be absent for required fields after checkout start."/> + <group value="shoppingCart"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <createData entity="_defaultCategory" stepKey="createCategory"/> + <createData entity="ApiSimpleProduct" stepKey="createProduct"> + <requiredEntity createDataKey="createCategory"/> + </createData> + <actionGroup ref="AddSimpleProductToCart" stepKey="addToCartFromStorefrontProductPage"> + <argument name="product" value="$$createProduct$$"/> + </actionGroup> + <actionGroup ref="GoToCheckoutFromMinicartActionGroup" stepKey="guestGoToCheckoutFromMinicart"/> + <waitForPageLoad stepKey="waitForCheckoutPage"/> + </before> + <after> + <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> + </after> + + <dontSeeElement selector="div .field-error" stepKey="dontSeeValidationErrors"/> + </test> +</tests> 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 75603d12cbe32..65ae2dd442d73 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 @@ -12,6 +12,7 @@ <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> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <constraint name="Magento\Checkout\Test\Constraint\AssertShippingAddressJsValidationMessagesIsAbsent" /> </variation> </testCase> From 93931d2c8359c9da14babeb7d76593007127a7a2 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Tue, 26 Mar 2019 13:36:57 +0200 Subject: [PATCH 127/773] magento/magento2#18075: UI installation fix. --- .../Model/ConfigOptionsList/DriverOptions.php | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/setup/src/Magento/Setup/Model/ConfigOptionsList/DriverOptions.php b/setup/src/Magento/Setup/Model/ConfigOptionsList/DriverOptions.php index 8ef9592e423de..f77dbe74abd4f 100644 --- a/setup/src/Magento/Setup/Model/ConfigOptionsList/DriverOptions.php +++ b/setup/src/Magento/Setup/Model/ConfigOptionsList/DriverOptions.php @@ -26,7 +26,9 @@ public function getDriverOptions(array $options): array ConfigOptionsListConstants::KEY_MYSQL_SSL_KEY => ConfigOptionsListConstants::INPUT_KEY_DB_SSL_KEY, ConfigOptionsListConstants::KEY_MYSQL_SSL_CERT => ConfigOptionsListConstants::INPUT_KEY_DB_SSL_CERT, ConfigOptionsListConstants::KEY_MYSQL_SSL_CA => ConfigOptionsListConstants::INPUT_KEY_DB_SSL_CA, - ConfigOptionsListConstants::KEY_MYSQL_SSL_VERIFY => ConfigOptionsListConstants::INPUT_KEY_DB_SSL_VERIFY + ]; + $booleanDriverOptionKeys = [ + ConfigOptionsListConstants::KEY_MYSQL_SSL_VERIFY => ConfigOptionsListConstants::INPUT_KEY_DB_SSL_VERIFY, ]; $driverOptions = []; foreach ($driverOptionKeys as $configKey => $driverOptionKey) { @@ -34,6 +36,10 @@ public function getDriverOptions(array $options): array $driverOptions[$configKey] = $options[$driverOptionKey]; } } + foreach ($booleanDriverOptionKeys as $configKey => $driverOptionKey) { + $driverOptions[$configKey] = $this->getBooleanValue($options, $driverOptionKey); + } + return $driverOptions; } @@ -48,4 +54,18 @@ private function optionExists(array $options, string $driverOptionKey): bool { return $options[$driverOptionKey] === false || !empty($options[$driverOptionKey]); } + + /** + * Transforms checkbox flag value into boolean. + * + * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/checkbox#value + * + * @param array $options + * @param string $driverOptionKey + * @return bool + */ + private function getBooleanValue(array $options, string $driverOptionKey): bool + { + return isset($options[$driverOptionKey]) ? (bool)$options[$driverOptionKey] : false; + } } From bcd42e9b68da410f22c2fafe7620c0dc4346c860 Mon Sep 17 00:00:00 2001 From: Andrew Molina <amolina@adobe.com> Date: Tue, 26 Mar 2019 08:55:45 -0500 Subject: [PATCH 128/773] MC-13954: Update Product Import Temp Directory --- .../Model/Import/Uploader.php | 9 ++++----- .../Test/Unit/Model/Import/UploaderTest.php | 18 +++++++++++------- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Uploader.php b/app/code/Magento/CatalogImportExport/Model/Import/Uploader.php index 3ac7f98818d70..3ee35cc87b312 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Uploader.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Uploader.php @@ -52,6 +52,8 @@ class Uploader extends \Magento\MediaStorage\Model\File\Uploader const DEFAULT_FILE_TYPE = 'application/octet-stream'; + const DEFAULT_TMP_DIR = 'pub/media/import'; + /** * Image factory. * @@ -154,16 +156,13 @@ public function move($fileName, $renameFileOff = false) $this->setAllowRenameFiles(false); } - if ($this->getTmpDir()) { - $filePath = $this->getTmpDir() . '/'; - } else { - $filePath = ''; - } + $filePath = $this->getTmpDir() ? ($this->getTmpDir() . '/') : ''; if (preg_match('/\bhttps?:\/\//i', $fileName, $matches)) { $url = str_replace($matches[0], '', $fileName); $driver = $matches[0] === $this->httpScheme ? DriverPool::HTTP : DriverPool::HTTPS; $read = $this->_readFactory->create($url, $driver); + $filePath = self::DEFAULT_TMP_DIR . '/'; //only use filename (for URI with query parameters) $parsedUrlPath = parse_url($url, PHP_URL_PATH); diff --git a/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/UploaderTest.php b/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/UploaderTest.php index f734596de014b..5eec2c3414ce5 100644 --- a/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/UploaderTest.php +++ b/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/UploaderTest.php @@ -102,12 +102,15 @@ protected function setUp() */ public function testMoveFileUrl($fileUrl, $expectedHost, $expectedFileName, $checkAllowedExtension) { + $defaultTmpDir = 'pub/media/import'; $destDir = 'var/dest/dir'; - $expectedRelativeFilePath = $expectedFileName; + $expectedRelativeFilePath = $defaultTmpDir . '/' . $expectedFileName; + $this->directoryMock->expects($this->once())->method('isWritable')->with($destDir)->willReturn(true); $this->directoryMock->expects($this->any())->method('getRelativePath')->with($expectedRelativeFilePath); $this->directoryMock->expects($this->once())->method('getAbsolutePath')->with($destDir) ->willReturn($destDir . '/' . $expectedFileName); + // Check writeFile() method invoking. $this->directoryMock->expects($this->any())->method('writeFile')->will($this->returnValue($expectedFileName)); @@ -116,20 +119,21 @@ public function testMoveFileUrl($fileUrl, $expectedHost, $expectedFileName, $che ->disableOriginalConstructor() ->setMethods(['readAll']) ->getMock(); + // Check readAll() method invoking. $readMock->expects($this->once())->method('readAll')->will($this->returnValue(null)); // Check create() method invoking with expected argument. - $this->readFactory->expects($this->once()) - ->method('create') - ->will($this->returnValue($readMock))->with($expectedHost); + $this->readFactory->expects($this->once())->method('create') + ->will($this->returnValue($readMock))->with($expectedHost); + //Check invoking of getTmpDir(), _setUploadFile(), save() methods. $this->uploader->expects($this->any())->method('getTmpDir')->will($this->returnValue('')); $this->uploader->expects($this->once())->method('_setUploadFile')->will($this->returnSelf()); - $this->uploader->expects($this->once())->method('save')->with($destDir . '/' . $expectedFileName) + $this->uploader->expects($this->once())->method('save') + ->with($destDir . '/' . $expectedFileName) ->willReturn(['name' => $expectedFileName, 'path' => 'absPath']); - $this->uploader->expects($this->exactly($checkAllowedExtension)) - ->method('checkAllowedExtension') + $this->uploader->expects($this->exactly($checkAllowedExtension))->method('checkAllowedExtension') ->willReturn(true); $this->uploader->setDestDir($destDir); From 0236fffdd804726efbe7e4eefd4092f26065d1d8 Mon Sep 17 00:00:00 2001 From: Cari Spruiell <spruiell@adobe.com> Date: Tue, 26 Mar 2019 10:41:54 -0500 Subject: [PATCH 129/773] MC-5894: Gift Card Account --- .../Setup/Fixtures/BundleProductsFixture.php | 13 +++--- .../Fixtures/ConfigurableProductsFixture.php | 41 +++++++++++++++---- .../Magento/Setup/Fixtures/OrdersFixture.php | 8 ++-- .../Magento/Setup/Fixtures/PriceProvider.php | 3 +- .../Setup/Fixtures/Quote/QuoteGenerator.php | 5 ++- .../Setup/Fixtures/SimpleProductsFixture.php | 11 ++--- .../CustomerTemplateGenerator.php | 4 +- 7 files changed, 57 insertions(+), 28 deletions(-) diff --git a/setup/src/Magento/Setup/Fixtures/BundleProductsFixture.php b/setup/src/Magento/Setup/Fixtures/BundleProductsFixture.php index d733389bf17cb..1b6e66202297d 100644 --- a/setup/src/Magento/Setup/Fixtures/BundleProductsFixture.php +++ b/setup/src/Magento/Setup/Fixtures/BundleProductsFixture.php @@ -99,7 +99,8 @@ public function __construct( } /** - * {@inheritdoc} + * @inheritdoc + * * @SuppressWarnings(PHPMD.UnusedLocalVariable) */ public function execute() @@ -126,8 +127,8 @@ public function execute() $fixtureMap = [ 'name' => $variationSkuClosure, 'sku' => $variationSkuClosure, - 'price' => function ($index, $entityNumber) { - return $this->priceProvider->getPrice($entityNumber); + 'price' => function () { + return $this->priceProvider->getPrice(); }, 'website_ids' => function ($index, $entityNumber) use ($variationCount) { $configurableIndex = $this->getBundleProductIndex($entityNumber, $variationCount); @@ -166,7 +167,7 @@ public function execute() 'price' => function ($index) use ($priceTypeClosure) { return $priceTypeClosure($index) === LinkInterface::PRICE_TYPE_PERCENT ? random_int(10, 90) - : $this->priceProvider->getPrice($index); + : $this->priceProvider->getPrice(); }, 'priceType' => $priceTypeClosure, 'website_ids' => function ($index, $entityNumber) { @@ -242,7 +243,7 @@ private function getBundleVariationIndex($entityNumber, $variationCount) } /** - * {@inheritdoc} + * @inheritdoc */ public function getActionTitle() { @@ -250,7 +251,7 @@ public function getActionTitle() } /** - * {@inheritdoc} + * @inheritdoc */ public function introduceParamLabels() { diff --git a/setup/src/Magento/Setup/Fixtures/ConfigurableProductsFixture.php b/setup/src/Magento/Setup/Fixtures/ConfigurableProductsFixture.php index a45261049567e..1e76e31733d88 100644 --- a/setup/src/Magento/Setup/Fixtures/ConfigurableProductsFixture.php +++ b/setup/src/Magento/Setup/Fixtures/ConfigurableProductsFixture.php @@ -203,7 +203,8 @@ public function __construct( } /** - * {@inheritdoc} + * @inheritdoc + * * @SuppressWarnings(PHPMD) */ public function execute() @@ -254,8 +255,8 @@ public function execute() $fixture = [ 'name' => $variationSkuClosure, 'sku' => $variationSkuClosure, - 'price' => function ($index, $entityNumber) { - return $this->priceProvider->getPrice($entityNumber); + 'price' => function () { + return $this->priceProvider->getPrice(); }, 'website_ids' => function ($index, $entityNumber) use ($variationCount) { $configurableIndex = $this->getConfigurableProductIndex($entityNumber, $variationCount); @@ -296,6 +297,8 @@ public function execute() } /** + * Get the closure to return the website IDs. + * * @return \Closure * @SuppressWarnings(PHPMD.UnusedLocalVariable) */ @@ -398,7 +401,7 @@ private function getConfigurableVariationIndex($entityNumber, $variationCount) } /** - * {@inheritdoc} + * @inheritdoc */ public function getActionTitle() { @@ -406,7 +409,7 @@ public function getActionTitle() } /** - * {@inheritdoc} + * @inheritdoc */ public function introduceParamLabels() { @@ -414,7 +417,10 @@ public function introduceParamLabels() } /** - * {@inheritdoc} + * @inheritdoc + * + * @param OutputInterface $output + * @return void * @throws ValidatorException */ public function printInfo(OutputInterface $output) @@ -432,7 +438,8 @@ public function printInfo(OutputInterface $output) } /** - * Gen default attribute sets with attributes + * Get default attribute sets with attributes. + * * @see config/attributeSets.xml * * @return array @@ -559,8 +566,10 @@ private function getConfigurableProductConfig() } /** - * Prepare configuration. If amount of configurable products set in profile then return predefined attribute sets - * else return configuration from profile + * Prepare configuration. + * + * If amount of configurable products set in profile then return predefined attribute sets + * else return configuration from profile. * * @param array $defaultAttributeSets * @return array @@ -599,6 +608,8 @@ private function prepareConfigurableConfig($defaultAttributeSets) } /** + * Get closure to return configurable category. + * * @param array $config * @return \Closure */ @@ -622,6 +633,8 @@ private function getConfigurableCategory($config) } /** + * Get sku pattern. + * * @param array $config * @param string $attributeSetName * @return string @@ -692,6 +705,8 @@ function ($index, $attribute) use ($attributeSetName, $attributes, $attributeSet } /** + * Get search configuration. + * * @return array */ private function getSearchConfig() @@ -703,6 +718,8 @@ private function getSearchConfig() } /** + * Get value of search configuration property. + * * @param string $name * @return int|mixed */ @@ -713,6 +730,8 @@ private function getSearchConfigValue($name) } /** + * Get search terms. + * * @return array */ private function getSearchTerms() @@ -770,6 +789,7 @@ private function getAdditionalAttributesClosure(array $attributes, $variationCou /** * Generates matrix of all possible variations. + * * @param int $attributesPerSet * @param int $optionsPerAttribute * @return array @@ -785,6 +805,7 @@ private function generateVariationsMatrix($attributesPerSet, $optionsPerAttribut /** * Build all possible variations based on attributes and options count. + * * @param array|null $variationsMatrix * @return array */ @@ -817,6 +838,8 @@ private function getConfigurableOptionSkuPattern($skuPattern) } /** + * Get description closure. + * * @param array|null $searchTerms * @param int $simpleProductsCount * @param int $configurableProductsCount diff --git a/setup/src/Magento/Setup/Fixtures/OrdersFixture.php b/setup/src/Magento/Setup/Fixtures/OrdersFixture.php index 82238650be740..2c9b4569bbd7d 100644 --- a/setup/src/Magento/Setup/Fixtures/OrdersFixture.php +++ b/setup/src/Magento/Setup/Fixtures/OrdersFixture.php @@ -11,6 +11,7 @@ /** * Fixture generator for Order entities with configurable number of different types of order items. + * * Optionally generates inactive quotes for generated orders. * * Support the following format: @@ -523,7 +524,7 @@ private function prepareQueryTemplates() * DB connection (if setup). Additionally filters out quote-related queries, if appropriate flag is set. * * @param string $table - * @param array ...$replacements + * @param array $replacements * @return void */ protected function query($table, ... $replacements) @@ -718,7 +719,7 @@ private function commitBatch() } /** - * {@inheritdoc} + * @inheritdoc */ public function getActionTitle() { @@ -726,7 +727,7 @@ public function getActionTitle() } /** - * {@inheritdoc} + * @inheritdoc */ public function introduceParamLabels() { @@ -737,6 +738,7 @@ public function introduceParamLabels() /** * Get real table name for db table, validated by db adapter. + * * In case prefix or other features mutating default table names are used. * * @param string $tableName diff --git a/setup/src/Magento/Setup/Fixtures/PriceProvider.php b/setup/src/Magento/Setup/Fixtures/PriceProvider.php index 17bd2270a4fbe..c19ea4d683ca5 100644 --- a/setup/src/Magento/Setup/Fixtures/PriceProvider.php +++ b/setup/src/Magento/Setup/Fixtures/PriceProvider.php @@ -14,10 +14,9 @@ class PriceProvider /** * Get random price for product * - * @param int $productIndex * @return float */ - public function getPrice($productIndex) + public function getPrice() { switch (random_int(0, 3)) { case 0: diff --git a/setup/src/Magento/Setup/Fixtures/Quote/QuoteGenerator.php b/setup/src/Magento/Setup/Fixtures/Quote/QuoteGenerator.php index 6f67a2a63a2e0..f449f63f77ef0 100644 --- a/setup/src/Magento/Setup/Fixtures/Quote/QuoteGenerator.php +++ b/setup/src/Magento/Setup/Fixtures/Quote/QuoteGenerator.php @@ -85,8 +85,8 @@ class QuoteGenerator /** * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory $productCollectionFactory - * @param \Magento\ConfigurableProduct\Api\OptionRepositoryInterface $optionRepository * @param \Magento\Catalog\Api\ProductRepositoryInterface $productRepository + * @param \Magento\ConfigurableProduct\Api\OptionRepositoryInterface $optionRepository * @param \Magento\ConfigurableProduct\Api\LinkManagementInterface $linkManagement * @param \Magento\Framework\Serialize\SerializerInterface $serializer * @param QuoteConfiguration $config @@ -578,7 +578,7 @@ private function prepareQueryTemplates() * DB connection (if setup). Additionally filters out quote-related queries, if appropriate flag is set. * * @param string $table - * @param array ...$replacements + * @param array $replacements * @return void */ protected function query($table, ... $replacements) @@ -774,6 +774,7 @@ private function getItemIdSequence($maxItemId, $requestedOrders, $maxItemsPerOrd /** * Get real table name for db table, validated by db adapter. + * * In case prefix or other features mutating default table names are used. * * @param string $tableName diff --git a/setup/src/Magento/Setup/Fixtures/SimpleProductsFixture.php b/setup/src/Magento/Setup/Fixtures/SimpleProductsFixture.php index ca20c5e5d1ca2..ce3bc2c7cfcb3 100644 --- a/setup/src/Magento/Setup/Fixtures/SimpleProductsFixture.php +++ b/setup/src/Magento/Setup/Fixtures/SimpleProductsFixture.php @@ -132,7 +132,7 @@ public function __construct( } /** - * {@inheritdoc} + * @inheritdoc */ public function getActionTitle() { @@ -140,7 +140,7 @@ public function getActionTitle() } /** - * {@inheritdoc} + * @inheritdoc */ public function introduceParamLabels() { @@ -150,7 +150,8 @@ public function introduceParamLabels() } /** - * {@inheritdoc} + * @inheritdoc + * * @SuppressWarnings(PHPMD) */ public function execute() @@ -220,8 +221,8 @@ public function execute() 'sku' => function ($productId) { return sprintf($this->getSkuPattern(), $productId); }, - 'price' => function ($index, $entityNumber) { - return $this->priceProvider->getPrice($entityNumber); + 'price' => function () { + return $this->priceProvider->getPrice(); }, 'url_key' => function ($productId) { return sprintf('simple-product-%s', $productId); diff --git a/setup/src/Magento/Setup/Model/FixtureGenerator/CustomerTemplateGenerator.php b/setup/src/Magento/Setup/Model/FixtureGenerator/CustomerTemplateGenerator.php index 0c99c235d38c1..ba57c95999284 100644 --- a/setup/src/Magento/Setup/Model/FixtureGenerator/CustomerTemplateGenerator.php +++ b/setup/src/Magento/Setup/Model/FixtureGenerator/CustomerTemplateGenerator.php @@ -48,7 +48,7 @@ public function __construct( } /** - * {@inheritdoc} + * @inheritdoc */ public function generateEntity() { @@ -100,6 +100,8 @@ private function getCustomerTemplate() } /** + * Get address template. + * * @param int $customerId * @return Address */ From 55b0307042b816cde072f50b475777056f190bac Mon Sep 17 00:00:00 2001 From: Nathan Smith <nathsmit@adobe.com> Date: Tue, 26 Mar 2019 11:28:20 -0500 Subject: [PATCH 130/773] MC-15533: Product attribute template incorrectly handles data --- .../view/frontend/templates/product/view/attribute.phtml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/code/Magento/Catalog/view/frontend/templates/product/view/attribute.phtml b/app/code/Magento/Catalog/view/frontend/templates/product/view/attribute.phtml index 86f97cf6f6aaf..2435590786807 100644 --- a/app/code/Magento/Catalog/view/frontend/templates/product/view/attribute.phtml +++ b/app/code/Magento/Catalog/view/frontend/templates/product/view/attribute.phtml @@ -15,6 +15,11 @@ <?php $_helper = $this->helper('Magento\Catalog\Helper\Output'); $_product = $block->getProduct(); + +if (!$_product instanceof \Magento\Catalog\Model\Product) { + return; +} + $_call = $block->getAtCall(); $_code = $block->getAtCode(); $_className = $block->getCssClass(); From 52536250803b9f79852133181116682c98f0c5d9 Mon Sep 17 00:00:00 2001 From: Nathan Smith <nathsmit@adobe.com> Date: Tue, 26 Mar 2019 11:51:00 -0500 Subject: [PATCH 131/773] MC-15533: Product attribute template incorrectly handles data --- .../Block/Product/View/DescriptionTest.php | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/Block/Product/View/DescriptionTest.php diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/View/DescriptionTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/View/DescriptionTest.php new file mode 100644 index 0000000000000..8da04d82ac908 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/View/DescriptionTest.php @@ -0,0 +1,54 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Catalog\Block\Product; + +use Magento\Framework\Registry; +use Magento\TestFramework\Helper\Bootstrap; +use PHPUnit\Framework\TestCase; + +/** + * @magentoAppArea frontend + */ +class DescriptionTest extends TestCase +{ + /** + * @var View\Description + */ + private $block; + + /** + * @var Registry + */ + private $registry; + + protected function setUp() + { + $objectManager = Bootstrap::getObjectManager(); + $this->block = $objectManager->create(View\Description::class, [ + 'data' => [ + 'template' => 'Magento_Catalog::product/view/attribute.phtml' + ] + ]); + + $this->registry = $objectManager->get(Registry::class); + $this->registry->unregister('product'); + } + + public function testGetProductWhenNoProductIsRegistered() + { + $html = $this->block->toHtml(); + $this->assertEmpty($html); + } + + public function testGetProductWhenInvalidProductIsRegistered() + { + $this->registry->register('product', new \stdClass()); + $html = $this->block->toHtml(); + $this->assertEmpty($html); + } +} From 370b274731628fdcd45346c646d663b0c8bc8ab6 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun <ogorkun@magento.com> Date: Tue, 26 Mar 2019 15:31:31 -0500 Subject: [PATCH 132/773] MC-13958: Additional Permissions for Design settings --- app/code/Magento/Catalog/Model/Category/DataProvider.php | 1 + .../Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php | 1 + .../Catalog/view/adminhtml/ui_component/category_form.xml | 8 ++++---- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Category/DataProvider.php b/app/code/Magento/Catalog/Model/Category/DataProvider.php index d30656c3b8df2..2e0e71003beab 100644 --- a/app/code/Magento/Catalog/Model/Category/DataProvider.php +++ b/app/code/Magento/Catalog/Model/Category/DataProvider.php @@ -299,6 +299,7 @@ private function prepareFieldsMeta($fieldsMap, $fieldsMeta) if (($fieldSet === 'design' || $fieldSet === 'schedule_design_update') && !$canEditDesign) { $config['required'] = 1; $config['disabled'] = 1; + $config['serviceDisabled'] = true; } $result[$fieldSet]['children'][$field]['arguments']['data']['config'] = $config; diff --git a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php index ba6dd623405a2..e665d2e4fa45e 100755 --- a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php +++ b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php @@ -753,6 +753,7 @@ public function setupAttributeMeta(ProductAttributeInterface $attribute, $groupC 'disabled' => true, 'validation' => ['required' => false], 'required' => false, + 'serviceDisabled' => true, ] ); } diff --git a/app/code/Magento/Catalog/view/adminhtml/ui_component/category_form.xml b/app/code/Magento/Catalog/view/adminhtml/ui_component/category_form.xml index 90d6e0b48400e..84c3c35f1af18 100644 --- a/app/code/Magento/Catalog/view/adminhtml/ui_component/category_form.xml +++ b/app/code/Magento/Catalog/view/adminhtml/ui_component/category_form.xml @@ -466,7 +466,7 @@ <dataType>string</dataType> <label translate="true">Theme</label> <imports> - <link name="serviceDisabled">${ $.parentName }.custom_use_parent_settings:checked</link> + <link name="serviceDisabled">${ $.parentName }.custom_use_parent_settings:checked || $.data.serviceDisabled</link> </imports> </settings> </field> @@ -475,7 +475,7 @@ <dataType>string</dataType> <label translate="true">Layout</label> <imports> - <link name="serviceDisabled">${ $.parentName }.custom_use_parent_settings:checked</link> + <link name="serviceDisabled">${ $.parentName }.custom_use_parent_settings:checked || $.data.serviceDisabled</link> </imports> </settings> </field> @@ -484,7 +484,7 @@ <dataType>string</dataType> <label translate="true">Layout Update XML</label> <imports> - <link name="serviceDisabled">${ $.parentName }.custom_use_parent_settings:checked</link> + <link name="serviceDisabled">${ $.parentName }.custom_use_parent_settings:checked || $.data.serviceDisabled</link> </imports> </settings> </field> @@ -501,7 +501,7 @@ <dataType>boolean</dataType> <label translate="true">Apply Design to Products</label> <imports> - <link name="serviceDisabled">${ $.parentName }.custom_use_parent_settings:checked</link> + <link name="serviceDisabled">${ $.parentName }.custom_use_parent_settings:checked || $.data.serviceDisabled</link> </imports> </settings> <formElements> From d4f316d34d91c1602c61ba52c6998f92286443fa Mon Sep 17 00:00:00 2001 From: Hwashiang Yu <hwyu@adobe.com> Date: Tue, 26 Mar 2019 15:41:30 -0500 Subject: [PATCH 133/773] MC-13896: User Role Template Update - Updated the param request logic --- .../User/view/adminhtml/templates/role/users_grid_js.phtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/User/view/adminhtml/templates/role/users_grid_js.phtml b/app/code/Magento/User/view/adminhtml/templates/role/users_grid_js.phtml index 964d925a5f2fd..99f3c43354aa4 100644 --- a/app/code/Magento/User/view/adminhtml/templates/role/users_grid_js.phtml +++ b/app/code/Magento/User/view/adminhtml/templates/role/users_grid_js.phtml @@ -17,7 +17,7 @@ require([ <!-- <?php $myBlock = $block->getLayout()->getBlock('roleUsersGrid'); ?> <?php if (is_object($myBlock) && $myBlock->getJsObjectName()): ?> - var checkBoxes = $H(<?= /* @escapeNotVerified */ $myBlock->getUsers(true) ?>); + var checkBoxes = $H(<?= $block->escapeJs($block->escapeUrl($myBlock->getUsers(true))) ?>); var warning = false; if (checkBoxes.size() > 0) { warning = true; From 01cb52a6253f1c0a958347fba6066e410bbd2348 Mon Sep 17 00:00:00 2001 From: Dan Mooney <dmooney@adobe.com> Date: Mon, 25 Mar 2019 15:13:45 -0500 Subject: [PATCH 134/773] MC-15418: Elasticsearch configuration updates --- .../Model/ResourceModel/SynonymReader.php | 1 + .../Search/Model/SynonymReaderTest.php | 6 +++++ .../Framework/DB/Helper/Mysql/Fulltext.php | 26 +++++++++++++++++-- 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Search/Model/ResourceModel/SynonymReader.php b/app/code/Magento/Search/Model/ResourceModel/SynonymReader.php index 46e794a1954cf..6eb3737c813de 100644 --- a/app/code/Magento/Search/Model/ResourceModel/SynonymReader.php +++ b/app/code/Magento/Search/Model/ResourceModel/SynonymReader.php @@ -85,6 +85,7 @@ protected function _construct() */ private function queryByPhrase($phrase) { + $phrase = $this->fullTextSelect->removeSpecialCharacters($phrase); $matchQuery = $this->fullTextSelect->getMatchQuery( ['synonyms' => 'synonyms'], $phrase, diff --git a/dev/tests/integration/testsuite/Magento/Search/Model/SynonymReaderTest.php b/dev/tests/integration/testsuite/Magento/Search/Model/SynonymReaderTest.php index b9ba89ba53144..1ec76f6a3e7b2 100644 --- a/dev/tests/integration/testsuite/Magento/Search/Model/SynonymReaderTest.php +++ b/dev/tests/integration/testsuite/Magento/Search/Model/SynonymReaderTest.php @@ -31,6 +31,9 @@ public static function loadByPhraseDataProvider() [ 'ELIZABETH', [] ], + [ + '-+<(ELIZABETH)>*~', [] + ], [ 'ENGLISH', [['synonyms' => 'british,english', 'store_id' => 1, 'website_id' => 0]] ], @@ -43,6 +46,9 @@ public static function loadByPhraseDataProvider() [ 'Monarch', [['synonyms' => 'queen,monarch', 'store_id' => 1, 'website_id' => 0]] ], + [ + '-+<(Monarch)>*~', [['synonyms' => 'queen,monarch', 'store_id' => 1, 'website_id' => 0]] + ], [ 'MONARCH English', [ ['synonyms' => 'queen,monarch', 'store_id' => 1, 'website_id' => 0], diff --git a/lib/internal/Magento/Framework/DB/Helper/Mysql/Fulltext.php b/lib/internal/Magento/Framework/DB/Helper/Mysql/Fulltext.php index 8063c60143e00..5c50faf71a854 100644 --- a/lib/internal/Magento/Framework/DB/Helper/Mysql/Fulltext.php +++ b/lib/internal/Magento/Framework/DB/Helper/Mysql/Fulltext.php @@ -3,12 +3,24 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Framework\DB\Helper\Mysql; use Magento\Framework\App\ResourceConnection; +/** + * MySQL Fulltext Query Builder + */ class Fulltext { + /** + * Characters that have special meaning in fulltext match syntax + * + * @var string + */ + const SPECIAL_CHARACTERS = '-+<>*()~'; + /** * FULLTEXT search in MySQL search mode "natural language" */ @@ -73,8 +85,7 @@ public function getMatchQuery($columns, $expression, $mode = self::FULLTEXT_MODE } /** - * Method for FULLTEXT search in Mysql, will added generated - * MATCH ($columns) AGAINST ('$expression' $mode) to where clause + * Method for FULLTEXT search in Mysql; will add generated MATCH ($columns) AGAINST ('$expression' $mode) to $select * * @param \Magento\Framework\DB\Select $select * @param string|string[] $columns Columns which add to MATCH () @@ -95,4 +106,15 @@ public function match($select, $columns, $expression, $isCondition = true, $mode return $select; } + + /** + * Remove special characters from fulltext query expression + * + * @param string $expression + * @return string + */ + public function removeSpecialCharacters(string $expression): string + { + return str_replace(str_split(static::SPECIAL_CHARACTERS), '', $expression); + } } From 5f9f21331b27c9ffcd5fe9c700d6cdb0aec70d7e Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun <ogorkun@magento.com> Date: Tue, 26 Mar 2019 17:07:59 -0500 Subject: [PATCH 135/773] MC-13958: Additional Permissions for Design settings --- .../Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php index 0f5de0378b97a..7bba2367d7ec6 100755 --- a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php +++ b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php @@ -743,11 +743,8 @@ public function setupAttributeMeta(ProductAttributeInterface $attribute, $groupC } //Checking access to design config. - if (in_array( - $attribute->getAttributeCode(), - ['custom_design', 'page_layout', 'options_container', 'custom_layout_update'], - true - )) { + $designAttributeCodes = ['custom_design', 'page_layout', 'options_container', 'custom_layout_update']; + if (in_array($attributeCode, $designAttributeCodes, true)) { if (!$this->auth->isAllowed('Magento_Catalog::edit_product_design')) { $meta = $this->arrayManager->merge( $configPath, From a1d72908496a829d5f6c43766c4476c9a3c8d9ee Mon Sep 17 00:00:00 2001 From: Nathan Smith <nathsmit@adobe.com> Date: Tue, 26 Mar 2019 17:08:10 -0500 Subject: [PATCH 136/773] MC-15533: Product attribute template incorrectly handles data --- .../Magento/Catalog/Block/Product/View/DescriptionTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/View/DescriptionTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/View/DescriptionTest.php index 8da04d82ac908..11a34db152b4e 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/View/DescriptionTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/View/DescriptionTest.php @@ -5,7 +5,7 @@ */ declare(strict_types=1); -namespace Magento\Catalog\Block\Product; +namespace Magento\Catalog\Block\Product\View; use Magento\Framework\Registry; use Magento\TestFramework\Helper\Bootstrap; From 9fecc9ef0b895c17f66c1f8492c272500b0c4655 Mon Sep 17 00:00:00 2001 From: Nathan Smith <nathsmit@adobe.com> Date: Tue, 26 Mar 2019 18:11:45 -0500 Subject: [PATCH 137/773] MC-15533: Product attribute template incorrectly handles data --- .../Magento/Catalog/Block/Product/View/DescriptionTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/View/DescriptionTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/View/DescriptionTest.php index 11a34db152b4e..fc6628626285a 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/View/DescriptionTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/View/DescriptionTest.php @@ -29,7 +29,7 @@ class DescriptionTest extends TestCase protected function setUp() { $objectManager = Bootstrap::getObjectManager(); - $this->block = $objectManager->create(View\Description::class, [ + $this->block = $objectManager->create(Description::class, [ 'data' => [ 'template' => 'Magento_Catalog::product/view/attribute.phtml' ] From d661eea158e3e7a9de5d91a41647954b53ac46cf Mon Sep 17 00:00:00 2001 From: OlgaVasyltsun <olga.vasyltsun@gmail.com> Date: Wed, 27 Mar 2019 10:35:29 +0200 Subject: [PATCH 138/773] MC-11052: Escaper changes --- lib/internal/Magento/Framework/Escaper.php | 3 ++- .../Framework/Test/Unit/EscaperTest.php | 27 ++++++++++++++++--- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/lib/internal/Magento/Framework/Escaper.php b/lib/internal/Magento/Framework/Escaper.php index c4150851ec40d..997f9c5396670 100644 --- a/lib/internal/Magento/Framework/Escaper.php +++ b/lib/internal/Magento/Framework/Escaper.php @@ -328,7 +328,8 @@ public function escapeXssInUrl($data) */ private function escapeScriptIdentifiers(string $data): string { - $filteredData = preg_replace(self::$xssFiltrationPattern, ':', $data) ?: ''; + $filteredData = preg_replace('/[\x00-\x1F\x7F\xA0]/u', '', $data) ?: ''; + $filteredData = preg_replace(self::$xssFiltrationPattern, ':', $filteredData) ?: ''; if (preg_match(self::$xssFiltrationPattern, $filteredData)) { $filteredData = $this->escapeScriptIdentifiers($filteredData); } diff --git a/lib/internal/Magento/Framework/Test/Unit/EscaperTest.php b/lib/internal/Magento/Framework/Test/Unit/EscaperTest.php index e406994b54c17..17fcce92bc729 100644 --- a/lib/internal/Magento/Framework/Test/Unit/EscaperTest.php +++ b/lib/internal/Magento/Framework/Test/Unit/EscaperTest.php @@ -265,15 +265,36 @@ public function escapeHtmlInvalidDataProvider() /** * @covers \Magento\Framework\Escaper::escapeUrl + * + * @param string $data + * @param string $expected + * @return void + * + * @dataProvider escapeUrlDataProvider */ - public function testEscapeUrl() + public function testEscapeUrl(string $data, string $expected): void { - $data = 'http://example.com/search?term=this+%26+that&view=list'; - $expected = 'http://example.com/search?term=this+%26+that&view=list'; $this->assertEquals($expected, $this->escaper->escapeUrl($data)); $this->assertEquals($expected, $this->escaper->escapeUrl($expected)); } + /** + * @return array + */ + public function escapeUrlDataProvider(): array + { + return [ + [ + 'data' => "http://example.com/search?term=this+%26+that&view=list", + 'expected' => "http://example.com/search?term=this+%26+that&view=list", + ], + [ + 'data' => "http://exam\r\nple.com/search?term=this+%26+that&view=list", + 'expected' => "http://example.com/search?term=this+%26+that&view=list", + ], + ]; + } + /** * @covers \Magento\Framework\Escaper::escapeJsQuote */ From db60f716713815ae6265855647146027f4eef965 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Wed, 27 Mar 2019 12:20:55 +0200 Subject: [PATCH 139/773] magento/magento2#18075: Unit tests fix. --- .../Test/Unit/Model/ConfigOptionsListTest.php | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/setup/src/Magento/Setup/Test/Unit/Model/ConfigOptionsListTest.php b/setup/src/Magento/Setup/Test/Unit/Model/ConfigOptionsListTest.php index 188346182f5b2..435f03f9de60b 100644 --- a/setup/src/Magento/Setup/Test/Unit/Model/ConfigOptionsListTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Model/ConfigOptionsListTest.php @@ -7,11 +7,14 @@ namespace Magento\Setup\Test\Unit\Model; use Magento\Framework\Config\ConfigOptionsListConstants; -use Magento\Setup\Model\ConfigOptionsList\Lock; use Magento\Setup\Model\ConfigGenerator; use Magento\Setup\Model\ConfigOptionsList; +use Magento\Setup\Model\ConfigOptionsList\Lock; use Magento\Setup\Validator\DbValidator; +/** + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ class ConfigOptionsListTest extends \PHPUnit\Framework\TestCase { /** @@ -34,6 +37,11 @@ class ConfigOptionsListTest extends \PHPUnit\Framework\TestCase */ private $dbValidator; + /** + * @var \Magento\Framework\Encryption\KeyValidator|\PHPUnit_Framework_MockObject_MockObject + */ + private $encryptionKeyValidator; + /** * @var ConfigOptionsList\DriverOptions */ @@ -44,8 +52,14 @@ protected function setUp() $this->generator = $this->createMock(\Magento\Setup\Model\ConfigGenerator::class); $this->deploymentConfig = $this->createMock(\Magento\Framework\App\DeploymentConfig::class); $this->dbValidator = $this->createMock(\Magento\Setup\Validator\DbValidator::class); + $this->encryptionKeyValidator = $this->createMock(\Magento\Framework\Encryption\KeyValidator::class); $this->driverOptionsMock = $this->createMock(ConfigOptionsList\DriverOptions::class); - $this->object = new ConfigOptionsList($this->generator, $this->dbValidator, $this->driverOptionsMock); + $this->object = new ConfigOptionsList( + $this->generator, + $this->dbValidator, + $this->encryptionKeyValidator, + $this->driverOptionsMock + ); } public function testGetOptions() From d27e9a4e885b1480b6835d01f4e17fa0ef455cc9 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Wed, 27 Mar 2019 13:00:54 +0200 Subject: [PATCH 140/773] magento/magento2#18075: No param fix. --- .../Setup/Model/ConfigOptionsList/DriverOptions.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/setup/src/Magento/Setup/Model/ConfigOptionsList/DriverOptions.php b/setup/src/Magento/Setup/Model/ConfigOptionsList/DriverOptions.php index f77dbe74abd4f..5910899354911 100644 --- a/setup/src/Magento/Setup/Model/ConfigOptionsList/DriverOptions.php +++ b/setup/src/Magento/Setup/Model/ConfigOptionsList/DriverOptions.php @@ -37,7 +37,7 @@ public function getDriverOptions(array $options): array } } foreach ($booleanDriverOptionKeys as $configKey => $driverOptionKey) { - $driverOptions[$configKey] = $this->getBooleanValue($options, $driverOptionKey); + $driverOptions[$configKey] = $this->booleanValue($options, $driverOptionKey); } return $driverOptions; @@ -52,7 +52,8 @@ public function getDriverOptions(array $options): array */ private function optionExists(array $options, string $driverOptionKey): bool { - return $options[$driverOptionKey] === false || !empty($options[$driverOptionKey]); + return isset($options[$driverOptionKey]) + && ($options[$driverOptionKey] === false || !empty($options[$driverOptionKey])); } /** @@ -64,8 +65,8 @@ private function optionExists(array $options, string $driverOptionKey): bool * @param string $driverOptionKey * @return bool */ - private function getBooleanValue(array $options, string $driverOptionKey): bool + private function booleanValue(array $options, string $driverOptionKey): bool { - return isset($options[$driverOptionKey]) ? (bool)$options[$driverOptionKey] : false; + return isset($options[$driverOptionKey]) && (bool)$options[$driverOptionKey]; } } From de7f0a33ca2412b9764f4575394818c1e475fb08 Mon Sep 17 00:00:00 2001 From: Nathan Smith <nathsmit@adobe.com> Date: Wed, 27 Mar 2019 08:26:33 -0500 Subject: [PATCH 141/773] MC-15533: Product attribute template incorrectly handles data --- .../Magento/Catalog/Block/Product/View/DescriptionTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/View/DescriptionTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/View/DescriptionTest.php index fc6628626285a..e097109ff63bc 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/View/DescriptionTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/View/DescriptionTest.php @@ -17,7 +17,7 @@ class DescriptionTest extends TestCase { /** - * @var View\Description + * @var Description */ private $block; From ffae144c5de45db67ddc1451d45c9cf24e16a349 Mon Sep 17 00:00:00 2001 From: Andrew Molina <amolina@adobe.com> Date: Wed, 27 Mar 2019 08:57:10 -0500 Subject: [PATCH 142/773] MC-13954: Update Product Import Temp Directory --- .../Magento/CatalogImportExport/Model/Import/Uploader.php | 4 +--- .../Test/Unit/Model/Import/UploaderTest.php | 4 ++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Uploader.php b/app/code/Magento/CatalogImportExport/Model/Import/Uploader.php index 3ee35cc87b312..77e264b09a087 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Uploader.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Uploader.php @@ -52,8 +52,6 @@ class Uploader extends \Magento\MediaStorage\Model\File\Uploader const DEFAULT_FILE_TYPE = 'application/octet-stream'; - const DEFAULT_TMP_DIR = 'pub/media/import'; - /** * Image factory. * @@ -162,7 +160,7 @@ public function move($fileName, $renameFileOff = false) $url = str_replace($matches[0], '', $fileName); $driver = $matches[0] === $this->httpScheme ? DriverPool::HTTP : DriverPool::HTTPS; $read = $this->_readFactory->create($url, $driver); - $filePath = self::DEFAULT_TMP_DIR . '/'; + $filePath = DirectoryList::getDefaultConfig()[DirectoryList::TMP][DirectoryList::PATH] . '/'; //only use filename (for URI with query parameters) $parsedUrlPath = parse_url($url, PHP_URL_PATH); diff --git a/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/UploaderTest.php b/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/UploaderTest.php index 5eec2c3414ce5..03653398599b2 100644 --- a/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/UploaderTest.php +++ b/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/UploaderTest.php @@ -102,9 +102,9 @@ protected function setUp() */ public function testMoveFileUrl($fileUrl, $expectedHost, $expectedFileName, $checkAllowedExtension) { - $defaultTmpDir = 'pub/media/import'; $destDir = 'var/dest/dir'; - $expectedRelativeFilePath = $defaultTmpDir . '/' . $expectedFileName; + $expectedTmpDir = 'var/tmp'; + $expectedRelativeFilePath = $expectedTmpDir . '/' . $expectedFileName; $this->directoryMock->expects($this->once())->method('isWritable')->with($destDir)->willReturn(true); $this->directoryMock->expects($this->any())->method('getRelativePath')->with($expectedRelativeFilePath); From 17b7f4b78cbd978a1dacb178c6ae6f87192d3bed Mon Sep 17 00:00:00 2001 From: David Haecker <dhaecker@magento.com> Date: Wed, 27 Mar 2019 09:57:18 -0500 Subject: [PATCH 143/773] MC-5858: HTTPS redirecting problem on storefront - Adding MFTF tests --- ...ontVerifySecureURLRedirectCheckoutTest.xml | 39 +++++++++++++++++ ...rontVerifySecureURLRedirectContactTest.xml | 39 +++++++++++++++++ ...ontVerifySecureURLRedirectCustomerTest.xml | 43 +++++++++++++++++++ ...tVerifySecureURLRedirectNewsletterTest.xml | 43 +++++++++++++++++++ ...frontVerifySecureURLRedirectPaypalTest.xml | 43 +++++++++++++++++++ ...frontVerifySecureURLRedirectReviewTest.xml | 43 +++++++++++++++++++ ...ontVerifySecureURLRedirectWishlistTest.xml | 43 +++++++++++++++++++ 7 files changed, 293 insertions(+) create mode 100644 app/code/Magento/Checkout/Test/Mftf/Test/StorefrontVerifySecureURLRedirectCheckoutTest.xml create mode 100644 app/code/Magento/Contact/Test/Mftf/Test/StorefrontVerifySecureURLRedirectContactTest.xml create mode 100644 app/code/Magento/Customer/Test/Mftf/Test/StorefrontVerifySecureURLRedirectCustomerTest.xml create mode 100644 app/code/Magento/Newsletter/Test/Mftf/Test/StorefrontVerifySecureURLRedirectNewsletterTest.xml create mode 100644 app/code/Magento/Paypal/Test/Mftf/Test/StorefrontVerifySecureURLRedirectPaypalTest.xml create mode 100644 app/code/Magento/Review/Test/Mftf/Test/StorefrontVerifySecureURLRedirectReviewTest.xml create mode 100644 app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontVerifySecureURLRedirectWishlistTest.xml diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontVerifySecureURLRedirectCheckoutTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontVerifySecureURLRedirectCheckoutTest.xml new file mode 100644 index 0000000000000..0a3b627b3d267 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontVerifySecureURLRedirectCheckoutTest.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="StorefrontVerifySecureURLRedirectCheckout"> + <annotations> + <features value="Checkout"/> + <stories value="Storefront Secure URLs"/> + <title value="Verify Secure URLs For Storefront Checkout Pages"/> + <description value="Verify that the Secure URL configuration applies to the Checkout pages on the Storefront"/> + <severity value="MAJOR"/> + <testCaseId value="MC-15531"/> + <group value="checkout"/> + <group value="configuration"/> + </annotations> + <before> + <amOnPage url="/" stepKey="goToHomePage"/> + <executeJS function="return window.location.host" stepKey="baseURL"/> + <magentoCLI command="config:set web/secure/base_url https://{$baseURL}/" stepKey="setSecureBaseURL"/> + <magentoCLI command="config:set web/secure/use_in_frontend 1" stepKey="useSecureURLsOnStorefront"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> + </before> + <after> + <magentoCLI command="config:set web/secure/use_in_frontend 0" stepKey="dontUseSecureURLsOnStorefront"/> + <magentoCLI command="config:set web/secure/base_url {{_ENV.MAGENTO_BASE_URL}}" stepKey="setSecureBaseURL"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> + </after> + <!-- Go to Unsecure URL --> + <amOnPage url="/checkout" stepKey="goToCheckoutPage"/> + <!-- Verify Secure URL Redirect --> + <seeInCurrentUrl url="https://" stepKey="seeSecureURL"/> + </test> +</tests> diff --git a/app/code/Magento/Contact/Test/Mftf/Test/StorefrontVerifySecureURLRedirectContactTest.xml b/app/code/Magento/Contact/Test/Mftf/Test/StorefrontVerifySecureURLRedirectContactTest.xml new file mode 100644 index 0000000000000..7c95a181b74fc --- /dev/null +++ b/app/code/Magento/Contact/Test/Mftf/Test/StorefrontVerifySecureURLRedirectContactTest.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="StorefrontVerifySecureURLRedirectContact"> + <annotations> + <features value="Contact"/> + <stories value="Storefront Secure URLs"/> + <title value="Verify Secure URLs For Storefront Contact Pages"/> + <description value="Verify that the Secure URL configuration applies to the Contact pages on the Storefront"/> + <severity value="MAJOR"/> + <testCaseId value="MC-15539"/> + <group value="contact"/> + <group value="configuration"/> + </annotations> + <before> + <amOnPage url="/" stepKey="goToHomePage"/> + <executeJS function="return window.location.host" stepKey="baseURL"/> + <magentoCLI command="config:set web/secure/base_url https://{$baseURL}/" stepKey="setSecureBaseURL"/> + <magentoCLI command="config:set web/secure/use_in_frontend 1" stepKey="useSecureURLsOnStorefront"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> + </before> + <after> + <magentoCLI command="config:set web/secure/use_in_frontend 0" stepKey="dontUseSecureURLsOnStorefront"/> + <magentoCLI command="config:set web/secure/base_url {{_ENV.MAGENTO_BASE_URL}}" stepKey="setSecureBaseURL"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> + </after> + <!-- Go to Unsecure URL --> + <amOnPage url="/contact" stepKey="goToContactPage"/> + <!-- Verify Secure URL Redirect --> + <seeInCurrentUrl url="https://" stepKey="seeSecureURL"/> + </test> +</tests> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontVerifySecureURLRedirectCustomerTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontVerifySecureURLRedirectCustomerTest.xml new file mode 100644 index 0000000000000..770d47a683097 --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontVerifySecureURLRedirectCustomerTest.xml @@ -0,0 +1,43 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="StorefrontVerifySecureURLRedirectCustomer"> + <annotations> + <features value="Customer"/> + <stories value="Storefront Secure URLs"/> + <title value="Verify Secure URLs For Storefront Customer Pages"/> + <description value="Verify that the Secure URL configuration applies to the Customer pages on the Storefront"/> + <severity value="MAJOR"/> + <testCaseId value="MC-15540"/> + <group value="customer"/> + <group value="configuration"/> + </annotations> + <before> + <createData entity="Simple_US_Customer" stepKey="customer"/> + <actionGroup ref="LoginToStorefrontActionGroup" stepKey="signThirdSimpleUsCustomer"> + <argument name="Customer" value="$$customer$$"/> + </actionGroup> + <executeJS function="return window.location.host" stepKey="baseURL"/> + <magentoCLI command="config:set web/secure/base_url https://{$baseURL}/" stepKey="setSecureBaseURL"/> + <magentoCLI command="config:set web/secure/use_in_frontend 1" stepKey="useSecureURLsOnStorefront"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> + </before> + <after> + <magentoCLI command="config:set web/secure/use_in_frontend 0" stepKey="dontUseSecureURLsOnStorefront"/> + <magentoCLI command="config:set web/secure/base_url {{_ENV.MAGENTO_BASE_URL}}" stepKey="setSecureBaseURL"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> + <deleteData createDataKey="customer" stepKey="deleteCustomer"/> + </after> + <!-- Go to Unsecure URL --> + <amOnPage url="/storecredit/info/" stepKey="goToStoreCreditInfoPage"/> + <!-- Verify Secure URL Redirect --> + <seeInCurrentUrl url="https://" stepKey="seeSecureURL"/> + </test> +</tests> diff --git a/app/code/Magento/Newsletter/Test/Mftf/Test/StorefrontVerifySecureURLRedirectNewsletterTest.xml b/app/code/Magento/Newsletter/Test/Mftf/Test/StorefrontVerifySecureURLRedirectNewsletterTest.xml new file mode 100644 index 0000000000000..6b89f050ee538 --- /dev/null +++ b/app/code/Magento/Newsletter/Test/Mftf/Test/StorefrontVerifySecureURLRedirectNewsletterTest.xml @@ -0,0 +1,43 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="StorefrontVerifySecureURLRedirectNewsletter"> + <annotations> + <features value="Newsletter"/> + <stories value="Storefront Secure URLs"/> + <title value="Verify Secure URLs For Storefront Newsletter Pages"/> + <description value="Verify that the Secure URL configuration applies to the Newsletter pages on the Storefront"/> + <severity value="MAJOR"/> + <testCaseId value="MC-15530"/> + <group value="newsletter"/> + <group value="configuration"/> + </annotations> + <before> + <createData entity="Simple_US_Customer" stepKey="customer"/> + <actionGroup ref="LoginToStorefrontActionGroup" stepKey="signThirdSimpleUsCustomer"> + <argument name="Customer" value="$$customer$$"/> + </actionGroup> + <executeJS function="return window.location.host" stepKey="baseURL"/> + <magentoCLI command="config:set web/secure/base_url https://{$baseURL}/" stepKey="setSecureBaseURL"/> + <magentoCLI command="config:set web/secure/use_in_frontend 1" stepKey="useSecureURLsOnStorefront"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> + </before> + <after> + <magentoCLI command="config:set web/secure/use_in_frontend 0" stepKey="dontUseSecureURLsOnStorefront"/> + <magentoCLI command="config:set web/secure/base_url {{_ENV.MAGENTO_BASE_URL}}" stepKey="setSecureBaseURL"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> + <deleteData createDataKey="customer" stepKey="deleteCustomer"/> + </after> + <!-- Go to Unsecure URL --> + <amOnPage url="/newsletter/manage" stepKey="goToNewsletterPage"/> + <!-- Verify Secure URL Redirect --> + <seeInCurrentUrl url="https://" stepKey="seeSecureURL"/> + </test> +</tests> diff --git a/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontVerifySecureURLRedirectPaypalTest.xml b/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontVerifySecureURLRedirectPaypalTest.xml new file mode 100644 index 0000000000000..9fd7956b71466 --- /dev/null +++ b/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontVerifySecureURLRedirectPaypalTest.xml @@ -0,0 +1,43 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="StorefrontVerifySecureURLRedirectPaypal"> + <annotations> + <features value="Paypal"/> + <stories value="Storefront Secure URLs"/> + <title value="Verify Secure URLs For Storefront Paypal Pages"/> + <description value="Verify that the Secure URL configuration applies to the Paypal pages on the Storefront"/> + <severity value="MAJOR"/> + <testCaseId value="MC-15541"/> + <group value="paypal"/> + <group value="configuration"/> + </annotations> + <before> + <createData entity="Simple_US_Customer" stepKey="customer"/> + <actionGroup ref="LoginToStorefrontActionGroup" stepKey="signThirdSimpleUsCustomer"> + <argument name="Customer" value="$$customer$$"/> + </actionGroup> + <executeJS function="return window.location.host" stepKey="baseURL"/> + <magentoCLI command="config:set web/secure/base_url https://{$baseURL}/" stepKey="setSecureBaseURL"/> + <magentoCLI command="config:set web/secure/use_in_frontend 1" stepKey="useSecureURLsOnStorefront"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> + </before> + <after> + <magentoCLI command="config:set web/secure/use_in_frontend 0" stepKey="dontUseSecureURLsOnStorefront"/> + <magentoCLI command="config:set web/secure/base_url {{_ENV.MAGENTO_BASE_URL}}" stepKey="setSecureBaseURL"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> + <deleteData createDataKey="customer" stepKey="deleteCustomer"/> + </after> + <!-- Go to Unsecure URL --> + <amOnPage url="/paypal/billing_agreement" stepKey="goToPaypalPage"/> + <!-- Verify Secure URL Redirect --> + <seeInCurrentUrl url="https://" stepKey="seeSecureURL"/> + </test> +</tests> diff --git a/app/code/Magento/Review/Test/Mftf/Test/StorefrontVerifySecureURLRedirectReviewTest.xml b/app/code/Magento/Review/Test/Mftf/Test/StorefrontVerifySecureURLRedirectReviewTest.xml new file mode 100644 index 0000000000000..8700b14d8524b --- /dev/null +++ b/app/code/Magento/Review/Test/Mftf/Test/StorefrontVerifySecureURLRedirectReviewTest.xml @@ -0,0 +1,43 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="StorefrontVerifySecureURLRedirectReview"> + <annotations> + <features value="Review"/> + <stories value="Storefront Secure URLs"/> + <title value="Verify Secure URLs For Storefront Review Pages"/> + <description value="Verify that the Secure URL configuration applies to the Review pages on the Storefront"/> + <severity value="MAJOR"/> + <testCaseId value="MC-15542"/> + <group value="review"/> + <group value="configuration"/> + </annotations> + <before> + <createData entity="Simple_US_Customer" stepKey="customer"/> + <actionGroup ref="LoginToStorefrontActionGroup" stepKey="signThirdSimpleUsCustomer"> + <argument name="Customer" value="$$customer$$"/> + </actionGroup> + <executeJS function="return window.location.host" stepKey="baseURL"/> + <magentoCLI command="config:set web/secure/base_url https://{$baseURL}/" stepKey="setSecureBaseURL"/> + <magentoCLI command="config:set web/secure/use_in_frontend 1" stepKey="useSecureURLsOnStorefront"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> + </before> + <after> + <magentoCLI command="config:set web/secure/use_in_frontend 0" stepKey="dontUseSecureURLsOnStorefront"/> + <magentoCLI command="config:set web/secure/base_url {{_ENV.MAGENTO_BASE_URL}}" stepKey="setSecureBaseURL"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> + <deleteData createDataKey="customer" stepKey="deleteCustomer"/> + </after> + <!-- Go to Unsecure URL --> + <amOnPage url="/review/customer" stepKey="goToReviewPage"/> + <!-- Verify Secure URL Redirect --> + <seeInCurrentUrl url="https://" stepKey="seeSecureURL"/> + </test> +</tests> diff --git a/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontVerifySecureURLRedirectWishlistTest.xml b/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontVerifySecureURLRedirectWishlistTest.xml new file mode 100644 index 0000000000000..4fbfa3dda971d --- /dev/null +++ b/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontVerifySecureURLRedirectWishlistTest.xml @@ -0,0 +1,43 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="StorefrontVerifySecureURLRedirectWishlist"> + <annotations> + <features value="Wishlist"/> + <stories value="Storefront Secure URLs"/> + <title value="Verify Secure URLs For Storefront Wishlist Pages"/> + <description value="Verify that the Secure URL configuration applies to the Wishlist pages on the Storefront"/> + <severity value="MAJOR"/> + <testCaseId value="MC-15543"/> + <group value="wishlist"/> + <group value="configuration"/> + </annotations> + <before> + <createData entity="Simple_US_Customer" stepKey="customer"/> + <actionGroup ref="LoginToStorefrontActionGroup" stepKey="signThirdSimpleUsCustomer"> + <argument name="Customer" value="$$customer$$"/> + </actionGroup> + <executeJS function="return window.location.host" stepKey="baseURL"/> + <magentoCLI command="config:set web/secure/base_url https://{$baseURL}/" stepKey="setSecureBaseURL"/> + <magentoCLI command="config:set web/secure/use_in_frontend 1" stepKey="useSecureURLsOnStorefront"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> + </before> + <after> + <magentoCLI command="config:set web/secure/use_in_frontend 0" stepKey="dontUseSecureURLsOnStorefront"/> + <magentoCLI command="config:set web/secure/base_url {{_ENV.MAGENTO_BASE_URL}}" stepKey="setSecureBaseURL"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> + <deleteData createDataKey="customer" stepKey="deleteCustomer"/> + </after> + <!-- Go to Unsecure URL --> + <amOnPage url="/wishlist" stepKey="goToWishlistPage"/> + <!-- Verify Secure URL Redirect --> + <seeInCurrentUrl url="https://" stepKey="seeSecureURL"/> + </test> +</tests> From c91dfa93a329db744c6e24568b3def830ef3da9d Mon Sep 17 00:00:00 2001 From: Andrew Molina <amolina@adobe.com> Date: Wed, 27 Mar 2019 11:00:51 -0500 Subject: [PATCH 144/773] MC-13954: Update Product Import Temp Directory --- .../CatalogImportExport/Model/Import/Uploader.php | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Uploader.php b/app/code/Magento/CatalogImportExport/Model/Import/Uploader.php index 77e264b09a087..dd0fb52028ab3 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Uploader.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Uploader.php @@ -31,6 +31,13 @@ class Uploader extends \Magento\MediaStorage\Model\File\Uploader */ protected $_tmpDir = ''; + /** + * Download directory for url-based resources. + * + * @var string + */ + private $_downloadDir; + /** * Destination directory. * @@ -122,6 +129,7 @@ public function __construct( if ($filePath !== null) { $this->_setUploadFile($filePath); } + $this->_downloadDir = DirectoryList::getDefaultConfig()[DirectoryList::TMP][DirectoryList::PATH]; } /** @@ -160,7 +168,7 @@ public function move($fileName, $renameFileOff = false) $url = str_replace($matches[0], '', $fileName); $driver = $matches[0] === $this->httpScheme ? DriverPool::HTTP : DriverPool::HTTPS; $read = $this->_readFactory->create($url, $driver); - $filePath = DirectoryList::getDefaultConfig()[DirectoryList::TMP][DirectoryList::PATH] . '/'; + $filePath = $this->_downloadDir . '/'; //only use filename (for URI with query parameters) $parsedUrlPath = parse_url($url, PHP_URL_PATH); From 6bad12e869b8bc081ac0e9452a8c65a7612358b5 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun <ogorkun@magento.com> Date: Wed, 27 Mar 2019 16:18:06 -0500 Subject: [PATCH 145/773] MC-10870: Invalid company ID in web API --- .../Controller/Rest/ParamsOverrider.php | 30 ++++++++++++++++--- .../Controller/Rest/ParamsOverriderTest.php | 2 +- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/Webapi/Controller/Rest/ParamsOverrider.php b/app/code/Magento/Webapi/Controller/Rest/ParamsOverrider.php index d1a3c0c0f0864..be11ee5a11c76 100644 --- a/app/code/Magento/Webapi/Controller/Rest/ParamsOverrider.php +++ b/app/code/Magento/Webapi/Controller/Rest/ParamsOverrider.php @@ -6,6 +6,7 @@ namespace Magento\Webapi\Controller\Rest; +use Magento\Framework\App\ObjectManager; use Magento\Framework\Webapi\Rest\Request\ParamOverriderInterface; use Magento\Webapi\Model\Config\Converter; use Magento\Framework\Reflection\MethodsMap; @@ -26,15 +27,24 @@ class ParamsOverrider */ private $methodsMap; + /** + * @var SimpleDataObjectConverter + */ + private $dataObjectConverter; + /** * Initialize dependencies * * @param ParamOverriderInterface[] $paramOverriders + * @param SimpleDataObjectConverter|null $dataObjectConverter */ public function __construct( - array $paramOverriders = [] + array $paramOverriders = [], + SimpleDataObjectConverter $dataObjectConverter = null ) { $this->paramOverriders = $paramOverriders; + $this->dataObjectConverter = $dataObjectConverter + ?? ObjectManager::getInstance()->get(SimpleDataObjectConverter::class); } /** @@ -64,15 +74,17 @@ public function override(array $inputData, array $parameters) /** * Determine if a nested array value is set. * - * @param array &$nestedArray + * @param array $nestedArray * @param string[] $arrayKeys * @return bool true if array value is set */ - protected function isNestedArrayValueSet(&$nestedArray, $arrayKeys) + protected function isNestedArrayValueSet($nestedArray, $arrayKeys) { - $currentArray = &$nestedArray; + //Converting input data to camelCase in order to process both snake and camel style data equally. + $currentArray = $this->dataObjectConverter->convertKeysToCamelCase($nestedArray); foreach ($arrayKeys as $key) { + $key = SimpleDataObjectConverter::snakeCaseToCamelCase($key); if (!isset($currentArray[$key])) { return false; } @@ -95,12 +107,22 @@ protected function setNestedArrayValue(&$nestedArray, $arrayKeys, $valueToSet) $lastKey = array_pop($arrayKeys); foreach ($arrayKeys as $key) { + if (!array_key_exists($key, $currentArray)) { + //In case input data uses camelCase format + $key = SimpleDataObjectConverter::snakeCaseToCamelCase($key); + } if (!isset($currentArray[$key])) { $currentArray[$key] = []; } $currentArray = &$currentArray[$key]; } + //In case input data uses camelCase format + $camelCaseKey = SimpleDataObjectConverter::snakeCaseToCamelCase($lastKey); + if (array_key_exists($camelCaseKey, $currentArray)) { + $lastKey = $camelCaseKey; + } + $currentArray[$lastKey] = $valueToSet; } diff --git a/app/code/Magento/Webapi/Test/Unit/Controller/Rest/ParamsOverriderTest.php b/app/code/Magento/Webapi/Test/Unit/Controller/Rest/ParamsOverriderTest.php index 7f98f21d1e2bb..239430498a2b4 100644 --- a/app/code/Magento/Webapi/Test/Unit/Controller/Rest/ParamsOverriderTest.php +++ b/app/code/Magento/Webapi/Test/Unit/Controller/Rest/ParamsOverriderTest.php @@ -54,7 +54,7 @@ public function overrideParamsDataProvider() 'force false, value present' => [ ['Name1' => 'valueIn'], ['Name1' => ['force' => false, 'value' => 'valueOverride']], - ['Name1' => 'valueIn'], + ['Name1' => 'valueOverride'], 1, UserContextInterface::USER_TYPE_INTEGRATION, ], From 5240f20ce53360ba0b2215a239b3e8ee762ecda0 Mon Sep 17 00:00:00 2001 From: Anthoula Wojczak <awojczak@adobe.com> Date: Wed, 27 Mar 2019 17:06:52 -0500 Subject: [PATCH 146/773] MC-5858: HTTPS redirecting problem on storefront - add mftf test coverage --- ...ontVerifySecureURLRedirectCheckoutTest.xml | 1 - ...rontVerifySecureURLRedirectContactTest.xml | 1 - ...ontVerifySecureURLRedirectCustomerTest.xml | 1 - ...tVerifySecureURLRedirectNewsletterTest.xml | 1 - ...frontVerifySecureURLRedirectPaypalTest.xml | 1 - ...frontVerifySecureURLRedirectReviewTest.xml | 2 - ...efrontVerifySecureURLRedirectVaultTest.xml | 42 +++++++++++++++++++ 7 files changed, 42 insertions(+), 7 deletions(-) create mode 100644 app/code/Magento/Vault/Test/Mftf/Test/StorefrontVerifySecureURLRedirectVaultTest.xml diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontVerifySecureURLRedirectCheckoutTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontVerifySecureURLRedirectCheckoutTest.xml index 0a3b627b3d267..5bcadad4547f0 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontVerifySecureURLRedirectCheckoutTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontVerifySecureURLRedirectCheckoutTest.xml @@ -28,7 +28,6 @@ </before> <after> <magentoCLI command="config:set web/secure/use_in_frontend 0" stepKey="dontUseSecureURLsOnStorefront"/> - <magentoCLI command="config:set web/secure/base_url {{_ENV.MAGENTO_BASE_URL}}" stepKey="setSecureBaseURL"/> <magentoCLI command="cache:flush" stepKey="flushCache"/> </after> <!-- Go to Unsecure URL --> diff --git a/app/code/Magento/Contact/Test/Mftf/Test/StorefrontVerifySecureURLRedirectContactTest.xml b/app/code/Magento/Contact/Test/Mftf/Test/StorefrontVerifySecureURLRedirectContactTest.xml index 7c95a181b74fc..2987d8e18ae35 100644 --- a/app/code/Magento/Contact/Test/Mftf/Test/StorefrontVerifySecureURLRedirectContactTest.xml +++ b/app/code/Magento/Contact/Test/Mftf/Test/StorefrontVerifySecureURLRedirectContactTest.xml @@ -28,7 +28,6 @@ </before> <after> <magentoCLI command="config:set web/secure/use_in_frontend 0" stepKey="dontUseSecureURLsOnStorefront"/> - <magentoCLI command="config:set web/secure/base_url {{_ENV.MAGENTO_BASE_URL}}" stepKey="setSecureBaseURL"/> <magentoCLI command="cache:flush" stepKey="flushCache"/> </after> <!-- Go to Unsecure URL --> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontVerifySecureURLRedirectCustomerTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontVerifySecureURLRedirectCustomerTest.xml index 770d47a683097..4fdb3a791569e 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontVerifySecureURLRedirectCustomerTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontVerifySecureURLRedirectCustomerTest.xml @@ -31,7 +31,6 @@ </before> <after> <magentoCLI command="config:set web/secure/use_in_frontend 0" stepKey="dontUseSecureURLsOnStorefront"/> - <magentoCLI command="config:set web/secure/base_url {{_ENV.MAGENTO_BASE_URL}}" stepKey="setSecureBaseURL"/> <magentoCLI command="cache:flush" stepKey="flushCache"/> <deleteData createDataKey="customer" stepKey="deleteCustomer"/> </after> diff --git a/app/code/Magento/Newsletter/Test/Mftf/Test/StorefrontVerifySecureURLRedirectNewsletterTest.xml b/app/code/Magento/Newsletter/Test/Mftf/Test/StorefrontVerifySecureURLRedirectNewsletterTest.xml index 6b89f050ee538..df8a2690dc9a4 100644 --- a/app/code/Magento/Newsletter/Test/Mftf/Test/StorefrontVerifySecureURLRedirectNewsletterTest.xml +++ b/app/code/Magento/Newsletter/Test/Mftf/Test/StorefrontVerifySecureURLRedirectNewsletterTest.xml @@ -31,7 +31,6 @@ </before> <after> <magentoCLI command="config:set web/secure/use_in_frontend 0" stepKey="dontUseSecureURLsOnStorefront"/> - <magentoCLI command="config:set web/secure/base_url {{_ENV.MAGENTO_BASE_URL}}" stepKey="setSecureBaseURL"/> <magentoCLI command="cache:flush" stepKey="flushCache"/> <deleteData createDataKey="customer" stepKey="deleteCustomer"/> </after> diff --git a/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontVerifySecureURLRedirectPaypalTest.xml b/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontVerifySecureURLRedirectPaypalTest.xml index 9fd7956b71466..9360250710f40 100644 --- a/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontVerifySecureURLRedirectPaypalTest.xml +++ b/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontVerifySecureURLRedirectPaypalTest.xml @@ -31,7 +31,6 @@ </before> <after> <magentoCLI command="config:set web/secure/use_in_frontend 0" stepKey="dontUseSecureURLsOnStorefront"/> - <magentoCLI command="config:set web/secure/base_url {{_ENV.MAGENTO_BASE_URL}}" stepKey="setSecureBaseURL"/> <magentoCLI command="cache:flush" stepKey="flushCache"/> <deleteData createDataKey="customer" stepKey="deleteCustomer"/> </after> diff --git a/app/code/Magento/Review/Test/Mftf/Test/StorefrontVerifySecureURLRedirectReviewTest.xml b/app/code/Magento/Review/Test/Mftf/Test/StorefrontVerifySecureURLRedirectReviewTest.xml index 8700b14d8524b..8ae4478265b5c 100644 --- a/app/code/Magento/Review/Test/Mftf/Test/StorefrontVerifySecureURLRedirectReviewTest.xml +++ b/app/code/Magento/Review/Test/Mftf/Test/StorefrontVerifySecureURLRedirectReviewTest.xml @@ -17,7 +17,6 @@ <severity value="MAJOR"/> <testCaseId value="MC-15542"/> <group value="review"/> - <group value="configuration"/> </annotations> <before> <createData entity="Simple_US_Customer" stepKey="customer"/> @@ -31,7 +30,6 @@ </before> <after> <magentoCLI command="config:set web/secure/use_in_frontend 0" stepKey="dontUseSecureURLsOnStorefront"/> - <magentoCLI command="config:set web/secure/base_url {{_ENV.MAGENTO_BASE_URL}}" stepKey="setSecureBaseURL"/> <magentoCLI command="cache:flush" stepKey="flushCache"/> <deleteData createDataKey="customer" stepKey="deleteCustomer"/> </after> diff --git a/app/code/Magento/Vault/Test/Mftf/Test/StorefrontVerifySecureURLRedirectVaultTest.xml b/app/code/Magento/Vault/Test/Mftf/Test/StorefrontVerifySecureURLRedirectVaultTest.xml new file mode 100644 index 0000000000000..05d5ea992bfb9 --- /dev/null +++ b/app/code/Magento/Vault/Test/Mftf/Test/StorefrontVerifySecureURLRedirectVaultTest.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="StorefrontVerifySecureURLRedirectVault"> + <annotations> + <features value="Vault"/> + <stories value="Storefront Secure URLs"/> + <title value="Verify Secure URLs For Storefront Vault Pages"/> + <description value="Verify that the Secure URL configuration applies to the Vault pages on the Storefront"/> + <severity value="MAJOR"/> + <testCaseId value="MC-15562"/> + <group value="vault"/> + <group value="configuration"/> + </annotations> + <before> + <createData entity="Simple_US_Customer" stepKey="customer"/> + <actionGroup ref="LoginToStorefrontActionGroup" stepKey="signThirdSimpleUsCustomer"> + <argument name="Customer" value="$$customer$$"/> + </actionGroup> + <executeJS function="return window.location.host" stepKey="baseURL"/> + <magentoCLI command="config:set web/secure/base_url https://{$baseURL}/" stepKey="setSecureBaseURL"/> + <magentoCLI command="config:set web/secure/use_in_frontend 1" stepKey="useSecureURLsOnStorefront"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> + </before> + <after> + <magentoCLI command="config:set web/secure/use_in_frontend 0" stepKey="dontUseSecureURLsOnStorefront"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> + <deleteData createDataKey="customer" stepKey="deleteCustomer"/> + </after> + <!-- Go to Unsecure URL --> + <amOnPage url="/vault/cards/listaction/" stepKey="goToStoreVaultCardsListactionPage"/> + <!-- Verify Secure URL Redirect --> + <seeInCurrentUrl url="https://" stepKey="seeSecureURL"/> + </test> +</tests> From 8543fd9bee4562700abde914f64ba677ada43225 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun <ogorkun@magento.com> Date: Wed, 27 Mar 2019 17:24:15 -0500 Subject: [PATCH 147/773] MC-13958: Additional Permissions for Design settings --- .../Controller/Adminhtml/Notification/MarkAsReadTest.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/dev/tests/integration/testsuite/Magento/AdminNotification/Controller/Adminhtml/Notification/MarkAsReadTest.php b/dev/tests/integration/testsuite/Magento/AdminNotification/Controller/Adminhtml/Notification/MarkAsReadTest.php index 8195048b10af9..ab72a2e1b1dd2 100644 --- a/dev/tests/integration/testsuite/Magento/AdminNotification/Controller/Adminhtml/Notification/MarkAsReadTest.php +++ b/dev/tests/integration/testsuite/Magento/AdminNotification/Controller/Adminhtml/Notification/MarkAsReadTest.php @@ -5,8 +5,16 @@ */ namespace Magento\AdminNotification\Controller\Adminhtml\Notification; +/** + * Testing markAsRead controller. + * + * @magentoAppArea adminhtml + */ class MarkAsReadTest extends \Magento\TestFramework\TestCase\AbstractBackendController { + /** + * @inheritdoc + */ public function setUp() { $this->resource = 'Magento_AdminNotification::mark_as_read'; From c0768d1b21ff73d20289352cd5668076a20e25e0 Mon Sep 17 00:00:00 2001 From: Nathan Smith <nathsmit@adobe.com> Date: Thu, 28 Mar 2019 10:54:37 -0500 Subject: [PATCH 148/773] MC-15569: Incorrect currency symbol code formatting --- .../view/adminhtml/templates/grid.phtml | 43 ++++++------------- .../view/adminhtml/web/js/symbols-form.js | 39 +++++++++++++++++ 2 files changed, 52 insertions(+), 30 deletions(-) create mode 100644 app/code/Magento/CurrencySymbol/view/adminhtml/web/js/symbols-form.js diff --git a/app/code/Magento/CurrencySymbol/view/adminhtml/templates/grid.phtml b/app/code/Magento/CurrencySymbol/view/adminhtml/templates/grid.phtml index 6e9b9a396ec2f..c0170fb4be5f7 100644 --- a/app/code/Magento/CurrencySymbol/view/adminhtml/templates/grid.phtml +++ b/app/code/Magento/CurrencySymbol/view/adminhtml/templates/grid.phtml @@ -5,61 +5,44 @@ */ // @codingStandardsIgnoreFile - ?> <?php /** * @var $block \Magento\CurrencySymbol\Block\Adminhtml\System\Currencysymbol */ ?> - -<form id="currency-symbols-form" action="<?= /* @escapeNotVerified */ $block->getFormActionUrl() ?>" method="post"> - <input name="form_key" type="hidden" value="<?= /* @escapeNotVerified */ $block->getFormKey() ?>" /> +<form id="currency-symbols-form" action="<?= $block->escapeHtmlAttr($block->getFormActionUrl()) ?>" method="post"> + <input name="form_key" type="hidden" value="<?= $block->escapeHtmlAttr($block->getFormKey()) ?>" /> <fieldset class="admin__fieldset"> <?php foreach ($block->getCurrencySymbolsData() as $code => $data): ?> <div class="admin__field _required"> - <label class="admin__field-label" for="custom_currency_symbol<?= /* @escapeNotVerified */ $code ?>"> - <span><?= /* @escapeNotVerified */ $code ?> (<?= /* @escapeNotVerified */ $data['displayName'] ?>)</span> + <label class="admin__field-label" for="custom_currency_symbol<?= $block->escapeHtmlAttr($code) ?>"> + <span><?= $block->escapeHtml($code) ?> (<?= $block->escapeHtml($data['displayName']) ?>)</span> </label> <div class="admin__field-control"> - <input id="custom_currency_symbol<?= /* @escapeNotVerified */ $code ?>" + <input id="custom_currency_symbol<?= $block->escapeHtmlAttr($code) ?>" class="required-entry admin__control-text <?= $data['inherited'] ? 'disabled' : '' ?>" type="text" value="<?= $block->escapeHtmlAttr($data['displaySymbol']) ?>" - name="custom_currency_symbol[<?= /* @escapeNotVerified */ $code ?>]"> + name="custom_currency_symbol[<?= $block->escapeHtmlAttr($code) ?>]"> <div class="admin__field admin__field-option"> - <input id="custom_currency_symbol_inherit<?= /* @escapeNotVerified */ $code ?>" + <input id="custom_currency_symbol_inherit<?= $block->escapeHtmlAttr($code) ?>" class="admin__control-checkbox" type="checkbox" - onclick="toggleUseDefault(<?= /* @escapeNotVerified */ '\'' . $code . '\',\'' . $block->escapeJs($data['parentSymbol']) . '\'' ?>)" + onclick="toggleUseDefault(<?= '\'' . $block->escapeHtmlAttr($block->escapeJs($code)) . '\',\'' . $block->escapeJs($data['parentSymbol']) . '\'' ?>)" <?= $data['inherited'] ? ' checked="checked"' : '' ?> value="1" - name="inherit_custom_currency_symbol[<?= /* @escapeNotVerified */ $code ?>]"> - <label class="admin__field-label" for="custom_currency_symbol_inherit<?= /* @escapeNotVerified */ $code ?>"><span><?= /* @escapeNotVerified */ $block->getInheritText() ?></span></label> + name="inherit_custom_currency_symbol[<?= $block->escapeHtmlAttr($code) ?>]"> + <label class="admin__field-label" for="custom_currency_symbol_inherit<?= $block->escapeHtmlAttr($code) ?>"><span><?= $block->escapeHtml($block->getInheritText()) ?></span></label> </div> </div> </div> <?php endforeach; ?> </fieldset> </form> -<script> -require(['jquery', "mage/mage", 'prototype'], function(jQuery){ - - jQuery('#currency-symbols-form').mage('form').mage('validation'); - - function toggleUseDefault(code, value) +<script type="text/x-magento-init"> { - checkbox = jQuery('#custom_currency_symbol_inherit'+code); - input = jQuery('#custom_currency_symbol'+code); - - if (checkbox.is(':checked')) { - input.addClass('disabled'); - input.val(value); - input.prop('readonly', true); - } else { - input.removeClass('disabled'); - input.prop('readonly', false); + "#currency-symbols-form": { + "Magento_CurrencySymbol/js/symbols-form": {} } } - window.toggleUseDefault = toggleUseDefault; -}); </script> diff --git a/app/code/Magento/CurrencySymbol/view/adminhtml/web/js/symbols-form.js b/app/code/Magento/CurrencySymbol/view/adminhtml/web/js/symbols-form.js new file mode 100644 index 0000000000000..68f914ddb1b4d --- /dev/null +++ b/app/code/Magento/CurrencySymbol/view/adminhtml/web/js/symbols-form.js @@ -0,0 +1,39 @@ +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +define([ + 'jquery', + 'mage/mage' +], function ($) { + 'use strict'; + + return function (config, element) { + $(element) + .mage('form') + .mage('validation'); + + /** + * Toggle the field to use the default value + * + * @param {String} code + * @param {String} value + */ + function toggleUseDefault(code, value) { + var checkbox = $('#custom_currency_symbol_inherit' + code), + input = $('#custom_currency_symbol' + code); + + if (checkbox.is(':checked')) { + input.addClass('disabled'); + input.val(value); + input.prop('readonly', true); + } else { + input.removeClass('disabled'); + input.prop('readonly', false); + } + } + + window.toggleUseDefault = toggleUseDefault; + }; +}); From d74797c0b3341ae776008dcce4dbe57fd7479718 Mon Sep 17 00:00:00 2001 From: Hwashiang Yu <hwyu@adobe.com> Date: Thu, 28 Mar 2019 14:39:27 -0500 Subject: [PATCH 149/773] MC-13896: User Role Template Update - Updated the param request logic for roles and users - Added unit test coverage for invalid request params --- app/code/Magento/User/Block/Role/Grid/User.php | 14 ++++++++++++-- .../Magento/User/Block/User/Edit/Tab/Roles.php | 14 ++++++++++++-- .../Test/Unit/Block/Role/Grid/UserTest.php | 18 ++++++++++++++++++ .../templates/role/users_grid_js.phtml | 4 +--- 4 files changed, 43 insertions(+), 7 deletions(-) diff --git a/app/code/Magento/User/Block/Role/Grid/User.php b/app/code/Magento/User/Block/Role/Grid/User.php index 4c6b6378b4c4d..4c9810d20df9b 100644 --- a/app/code/Magento/User/Block/Role/Grid/User.php +++ b/app/code/Magento/User/Block/Role/Grid/User.php @@ -34,6 +34,11 @@ class User extends \Magento\Backend\Block\Widget\Grid\Extended */ protected $_jsonEncoder; + /** + * @var \Magento\Framework\Json\DecoderInterface + */ + protected $_jsonDecoder; + /** * @var \Magento\User\Model\ResourceModel\Role\User\CollectionFactory */ @@ -49,6 +54,7 @@ class User extends \Magento\Backend\Block\Widget\Grid\Extended * @param \Magento\Backend\Block\Template\Context $context * @param \Magento\Backend\Helper\Data $backendHelper * @param \Magento\Framework\Json\EncoderInterface $jsonEncoder + * @param \Magento\Framework\Json\DecoderInterface $jsonDecoder * @param \Magento\Framework\Registry $coreRegistry * @param \Magento\Authorization\Model\RoleFactory $roleFactory * @param \Magento\User\Model\ResourceModel\Role\User\CollectionFactory $userRolesFactory @@ -58,6 +64,7 @@ public function __construct( \Magento\Backend\Block\Template\Context $context, \Magento\Backend\Helper\Data $backendHelper, \Magento\Framework\Json\EncoderInterface $jsonEncoder, + \Magento\Framework\Json\DecoderInterface $jsonDecoder, \Magento\Framework\Registry $coreRegistry, \Magento\Authorization\Model\RoleFactory $roleFactory, \Magento\User\Model\ResourceModel\Role\User\CollectionFactory $userRolesFactory, @@ -65,6 +72,7 @@ public function __construct( ) { parent::__construct($context, $backendHelper, $data); $this->_jsonEncoder = $jsonEncoder; + $this->_jsonDecoder = $jsonDecoder; $this->_coreRegistry = $coreRegistry; $this->_roleFactory = $roleFactory; $this->_userRolesFactory = $userRolesFactory; @@ -191,8 +199,10 @@ public function getGridUrl() */ public function getUsers($json = false) { - if ($this->getRequest()->getParam('in_role_user') != "") { - return $this->getRequest()->getParam('in_role_user'); + $inRoleUser = $this->getRequest()->getParam('in_role_user'); + if ($inRoleUser && $json) { + $result = $this->_jsonDecoder->decode($inRoleUser); + return $result ? $result : '{}'; } $roleId = $this->getRequest()->getParam( 'rid' diff --git a/app/code/Magento/User/Block/User/Edit/Tab/Roles.php b/app/code/Magento/User/Block/User/Edit/Tab/Roles.php index 22f89b144587c..c35e889fa5d4e 100644 --- a/app/code/Magento/User/Block/User/Edit/Tab/Roles.php +++ b/app/code/Magento/User/Block/User/Edit/Tab/Roles.php @@ -30,10 +30,16 @@ class Roles extends \Magento\Backend\Block\Widget\Grid\Extended */ protected $_jsonEncoder; + /** + * @var \Magento\Framework\Json\DecoderInterface + */ + protected $_jsonDecoder; + /** * @param \Magento\Backend\Block\Template\Context $context * @param \Magento\Backend\Helper\Data $backendHelper * @param \Magento\Framework\Json\EncoderInterface $jsonEncoder + * @param \Magento\Framework\Json\DecoderInterface $jsonDecoder * @param \Magento\Authorization\Model\ResourceModel\Role\CollectionFactory $userRolesFactory * @param \Magento\Framework\Registry $coreRegistry * @param array $data @@ -42,11 +48,13 @@ public function __construct( \Magento\Backend\Block\Template\Context $context, \Magento\Backend\Helper\Data $backendHelper, \Magento\Framework\Json\EncoderInterface $jsonEncoder, + \Magento\Framework\Json\DecoderInterface $jsonDecoder, \Magento\Authorization\Model\ResourceModel\Role\CollectionFactory $userRolesFactory, \Magento\Framework\Registry $coreRegistry, array $data = [] ) { $this->_jsonEncoder = $jsonEncoder; + $this->_jsonDecoder = $jsonDecoder; $this->_userRolesFactory = $userRolesFactory; $this->_coreRegistry = $coreRegistry; parent::__construct($context, $backendHelper, $data); @@ -140,8 +148,10 @@ public function getGridUrl() */ public function getSelectedRoles($json = false) { - if ($this->getRequest()->getParam('user_roles') != "") { - return $this->getRequest()->getParam('user_roles'); + $userRoles = $this->getRequest()->getParam('user_roles'); + if ($userRoles && $json) { + $result = $this->_jsonDecoder->decode($userRoles); + return $result ? $result : '{}'; } /* @var $user \Magento\User\Model\User */ $user = $this->_coreRegistry->registry('permissions_user'); diff --git a/app/code/Magento/User/Test/Unit/Block/Role/Grid/UserTest.php b/app/code/Magento/User/Test/Unit/Block/Role/Grid/UserTest.php index 5b03f89cfa553..d9ec719e30193 100644 --- a/app/code/Magento/User/Test/Unit/Block/Role/Grid/UserTest.php +++ b/app/code/Magento/User/Test/Unit/Block/Role/Grid/UserTest.php @@ -22,6 +22,9 @@ class UserTest extends \PHPUnit\Framework\TestCase /** @var \Magento\Framework\Json\EncoderInterface|\PHPUnit_Framework_MockObject_MockObject */ protected $jsonEncoderMock; + /** @var \Magento\Framework\Json\DecoderInterface|\PHPUnit_Framework_MockObject_MockObject */ + protected $jsonDecoderMock; + /** @var \Magento\Framework\Registry|\PHPUnit_Framework_MockObject_MockObject */ protected $registryMock; @@ -55,6 +58,11 @@ protected function setUp() ->setMethods([]) ->getMock(); + $this->jsonDecoderMock = $this->getMockBuilder(\Magento\Framework\Json\DecoderInterface::class) + ->disableOriginalConstructor() + ->setMethods([]) + ->getMock(); + $this->registryMock = $this->getMockBuilder(\Magento\Framework\Registry::class) ->disableOriginalConstructor() ->setMethods([]) @@ -97,6 +105,7 @@ protected function setUp() [ 'backendHelper' => $this->backendHelperMock, 'jsonEncoder' => $this->jsonEncoderMock, + 'jsonDecoder' => $this->jsonDecoderMock, 'coreRegistry' => $this->registryMock, 'roleFactory' => $this->roleFactoryMock, 'userRolesFactory' => $this->userRolesFactoryMock, @@ -239,4 +248,13 @@ public function testPrepareColumns() $this->model->toHtml(); } + + public function testGetUsersIncorrectInRoleUser() + { + $param = 'in_role_user'; + $paramValue = 'not_JSON'; + $this->requestInterfaceMock->expects($this->once())->method('getParam')->with($param)->willReturn($paramValue); + $this->jsonDecoderMock->expects($this->once())->method('decode')->with($paramValue)->willReturn(null); + $this->assertEquals('{}', $this->model->getUsers(true)); + } } diff --git a/app/code/Magento/User/view/adminhtml/templates/role/users_grid_js.phtml b/app/code/Magento/User/view/adminhtml/templates/role/users_grid_js.phtml index 99f3c43354aa4..16e5ff3d4bd2f 100644 --- a/app/code/Magento/User/view/adminhtml/templates/role/users_grid_js.phtml +++ b/app/code/Magento/User/view/adminhtml/templates/role/users_grid_js.phtml @@ -14,10 +14,9 @@ require([ 'mage/adminhtml/grid', 'prototype' ], function(jQuery, confirm, _){ -<!-- <?php $myBlock = $block->getLayout()->getBlock('roleUsersGrid'); ?> <?php if (is_object($myBlock) && $myBlock->getJsObjectName()): ?> - var checkBoxes = $H(<?= $block->escapeJs($block->escapeUrl($myBlock->getUsers(true))) ?>); + var checkBoxes = $H(<?= /* @escapeNotVerified */ $myBlock->getUsers(true) ?>); var warning = false; if (checkBoxes.size() > 0) { warning = true; @@ -135,7 +134,6 @@ require([ } onLoad(); <?php endif; ?> -//--> }); </script> From 7d48018e92e3fc46e0a9477bd47b742407ce04b9 Mon Sep 17 00:00:00 2001 From: Hwashiang Yu <hwyu@adobe.com> Date: Thu, 28 Mar 2019 14:46:22 -0500 Subject: [PATCH 150/773] MC-13896: User Role Template Update - Added unit test coverage for invalid user role request params --- .../Unit/Block/User/Edit/Tab/RolesTest.php | 128 ++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 app/code/Magento/User/Test/Unit/Block/User/Edit/Tab/RolesTest.php diff --git a/app/code/Magento/User/Test/Unit/Block/User/Edit/Tab/RolesTest.php b/app/code/Magento/User/Test/Unit/Block/User/Edit/Tab/RolesTest.php new file mode 100644 index 0000000000000..d1a7fcaaa4540 --- /dev/null +++ b/app/code/Magento/User/Test/Unit/Block/User/Edit/Tab/RolesTest.php @@ -0,0 +1,128 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\User\Test\Unit\Block\User\Edit\Tab; + +/** + * Class UserTest to cover Magento\User\Block\Role\Grid\User + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class RolesTest extends \PHPUnit\Framework\TestCase +{ + /** @var \Magento\User\Block\Role\Grid\User */ + protected $model; + + /** @var \Magento\Backend\Helper\Data|\PHPUnit_Framework_MockObject_MockObject */ + protected $backendHelperMock; + + /** @var \Magento\Framework\Json\EncoderInterface|\PHPUnit_Framework_MockObject_MockObject */ + protected $jsonEncoderMock; + + /** @var \Magento\Framework\Json\DecoderInterface|\PHPUnit_Framework_MockObject_MockObject */ + protected $jsonDecoderMock; + + /** @var \Magento\Framework\Registry|\PHPUnit_Framework_MockObject_MockObject */ + protected $registryMock; + + /** @var \Magento\Authorization\Model\RoleFactory|\PHPUnit_Framework_MockObject_MockObject */ + protected $roleFactoryMock; + + /** @var \Magento\User\Model\ResourceModel\Role\User\CollectionFactory|\PHPUnit_Framework_MockObject_MockObject */ + protected $userRolesFactoryMock; + + /** @var \Magento\Framework\App\RequestInterface|\PHPUnit_Framework_MockObject_MockObject */ + protected $requestInterfaceMock; + + /** @var \Magento\Framework\UrlInterface|\PHPUnit_Framework_MockObject_MockObject */ + protected $urlInterfaceMock; + + /** @var \Magento\Framework\View\LayoutInterface|\PHPUnit_Framework_MockObject_MockObject */ + protected $layoutMock; + + /** @var \Magento\Framework\Filesystem|\PHPUnit_Framework_MockObject_MockObject */ + protected $filesystemMock; + + protected function setUp() + { + $this->backendHelperMock = $this->getMockBuilder(\Magento\Backend\Helper\Data::class) + ->disableOriginalConstructor() + ->setMethods([]) + ->getMock(); + + $this->jsonEncoderMock = $this->getMockBuilder(\Magento\Framework\Json\EncoderInterface::class) + ->disableOriginalConstructor() + ->setMethods([]) + ->getMock(); + + $this->jsonDecoderMock = $this->getMockBuilder(\Magento\Framework\Json\DecoderInterface::class) + ->disableOriginalConstructor() + ->setMethods([]) + ->getMock(); + + $this->registryMock = $this->getMockBuilder(\Magento\Framework\Registry::class) + ->disableOriginalConstructor() + ->setMethods([]) + ->getMock(); + + $this->roleFactoryMock = $this->getMockBuilder(\Magento\Authorization\Model\RoleFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + + $this->userRolesFactoryMock = $this + ->getMockBuilder(\Magento\User\Model\ResourceModel\Role\User\CollectionFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + + $this->requestInterfaceMock = $this->getMockBuilder(\Magento\Framework\App\RequestInterface::class) + ->disableOriginalConstructor() + ->setMethods([]) + ->getMock(); + + $this->urlInterfaceMock = $this->getMockBuilder(\Magento\Framework\UrlInterface::class) + ->disableOriginalConstructor() + ->setMethods([]) + ->getMock(); + + $this->layoutMock = $this->getMockBuilder(\Magento\Framework\View\LayoutInterface::class) + ->disableOriginalConstructor() + ->setMethods([]) + ->getMock(); + + $this->filesystemMock = $this->getMockBuilder(\Magento\Framework\Filesystem::class) + ->disableOriginalConstructor() + ->setMethods([]) + ->getMock(); + + $objectManagerHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $this->model = $objectManagerHelper->getObject( + \Magento\User\Block\User\Edit\Tab\Roles::class, + [ + 'backendHelper' => $this->backendHelperMock, + 'jsonEncoder' => $this->jsonEncoderMock, + 'jsonDecoder' => $this->jsonDecoderMock, + 'coreRegistry' => $this->registryMock, + 'roleFactory' => $this->roleFactoryMock, + 'userRolesFactory' => $this->userRolesFactoryMock, + 'request' => $this->requestInterfaceMock, + 'urlBuilder' => $this->urlInterfaceMock, + 'layout' => $this->layoutMock, + 'filesystem' => $this->filesystemMock + ] + ); + } + + public function testSelectedRolesIncorrectUserRoles() + { + $param = 'user_roles'; + $paramValue = 'not_JSON'; + $this->requestInterfaceMock->expects($this->once())->method('getParam')->with($param)->willReturn($paramValue); + $this->jsonDecoderMock->expects($this->once())->method('decode')->with($paramValue)->willReturn(null); + $this->assertEquals('{}', $this->model->getUsers(true)); + } +} From 99597cce61e7b27f2b95017a4ab71e7bb6dbe281 Mon Sep 17 00:00:00 2001 From: David Haecker <dhaecker@magento.com> Date: Thu, 28 Mar 2019 15:20:15 -0500 Subject: [PATCH 151/773] MC-5858: HTTPS redirecting problem on storefront - Adding MFTF tests --- ...erifySecureURLRedirectAuthorizenetTest.xml | 43 ++++++++++++++++ .../Mftf/Suite/SecureStorefrontURLSuite.xml | 14 ++++++ ...ontVerifySecureURLRedirectCheckoutTest.xml | 15 +++--- ...rontVerifySecureURLRedirectContactTest.xml | 13 ++--- ...ontVerifySecureURLRedirectCustomerTest.xml | 23 +++++---- ...erifySecureURLRedirectDownloadableTest.xml | 49 +++++++++++++++++++ ...rifySecureURLRedirectMultishippingTest.xml | 43 ++++++++++++++++ ...tVerifySecureURLRedirectNewsletterTest.xml | 15 +++--- ...frontVerifySecureURLRedirectPaypalTest.xml | 33 ++++++++++--- ...tVerifySecureURLRedirectPersistentTest.xml | 47 ++++++++++++++++++ ...frontVerifySecureURLRedirectReviewTest.xml | 14 +++--- ...efrontVerifySecureURLRedirectSalesTest.xml | 43 ++++++++++++++++ ...efrontVerifySecureURLRedirectVaultTest.xml | 13 ++--- ...ontVerifySecureURLRedirectWishlistTest.xml | 12 ++--- 14 files changed, 322 insertions(+), 55 deletions(-) create mode 100644 app/code/Magento/Authorizenet/Test/Mftf/Test/StorefrontVerifySecureURLRedirectAuthorizenetTest.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/Suite/SecureStorefrontURLSuite.xml create mode 100644 app/code/Magento/Downloadable/Test/Mftf/Test/StorefrontVerifySecureURLRedirectDownloadableTest.xml create mode 100644 app/code/Magento/Multishipping/Test/Mftf/Test/StorefrontVerifySecureURLRedirectMultishippingTest.xml create mode 100644 app/code/Magento/Persistent/Test/Mftf/Test/StorefrontVerifySecureURLRedirectPersistentTest.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/Test/StorefrontVerifySecureURLRedirectSalesTest.xml diff --git a/app/code/Magento/Authorizenet/Test/Mftf/Test/StorefrontVerifySecureURLRedirectAuthorizenetTest.xml b/app/code/Magento/Authorizenet/Test/Mftf/Test/StorefrontVerifySecureURLRedirectAuthorizenetTest.xml new file mode 100644 index 0000000000000..532b99aa78503 --- /dev/null +++ b/app/code/Magento/Authorizenet/Test/Mftf/Test/StorefrontVerifySecureURLRedirectAuthorizenetTest.xml @@ -0,0 +1,43 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="StorefrontVerifySecureURLRedirectAuthorizenet"> + <annotations> + <features value="Authorizenet"/> + <stories value="Storefront Secure URLs"/> + <title value="Verify Secure URLs For Storefront Authorizenet Pages"/> + <description value="Verify that the Secure URL configuration applies to the Authorizenet pages on the Storefront"/> + <severity value="MAJOR"/> + <testCaseId value="MC-15610"/> + <group value="authorizenet"/> + <group value="configuration"/> + <group value="secure_storefront_url"/> + </annotations> + <before> + <createData entity="Simple_US_Customer" stepKey="customer"/> + <actionGroup ref="LoginToStorefrontActionGroup" stepKey="signThirdSimpleUsCustomer"> + <argument name="Customer" value="$$customer$$"/> + </actionGroup> + <executeJS function="return window.location.host" stepKey="hostname"/> + <magentoCLI command="config:set web/secure/base_url https://{$hostname}/" stepKey="setSecureBaseURL"/> + <magentoCLI command="config:set web/secure/use_in_frontend 1" stepKey="useSecureURLsOnStorefront"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> + </before> + <after> + <magentoCLI command="config:set web/secure/use_in_frontend 0" stepKey="dontUseSecureURLsOnStorefront"/> + <magentoCLI command="config:set web/secure/base_url {{_ENV.MAGENTO_BASE_URL}}" stepKey="setSecureBaseURL"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> + <deleteData createDataKey="customer" stepKey="deleteCustomer"/> + </after> + <executeJS function="return window.location.host" stepKey="hostname"/> + <amOnUrl url="http://{$hostname}/authorizenet" stepKey="goToUnsecureAuthorizenetURL"/> + <seeCurrentUrlEquals url="https://{$hostname}/authorizenet" stepKey="seeSecureAuthorizenetURL"/> + </test> +</tests> diff --git a/app/code/Magento/Checkout/Test/Mftf/Suite/SecureStorefrontURLSuite.xml b/app/code/Magento/Checkout/Test/Mftf/Suite/SecureStorefrontURLSuite.xml new file mode 100644 index 0000000000000..798bdb1c12686 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/Suite/SecureStorefrontURLSuite.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<suites xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Suite/etc/suiteSchema.xsd"> + <suite name="SecureStorefrontURLSuite"> + <include> + <group name="secure_storefront_url"/> + </include> + </suite> +</suites> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontVerifySecureURLRedirectCheckoutTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontVerifySecureURLRedirectCheckoutTest.xml index 5bcadad4547f0..89685ad3abd6e 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontVerifySecureURLRedirectCheckoutTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontVerifySecureURLRedirectCheckoutTest.xml @@ -18,21 +18,24 @@ <testCaseId value="MC-15531"/> <group value="checkout"/> <group value="configuration"/> + <group value="secure_storefront_url"/> </annotations> <before> <amOnPage url="/" stepKey="goToHomePage"/> - <executeJS function="return window.location.host" stepKey="baseURL"/> - <magentoCLI command="config:set web/secure/base_url https://{$baseURL}/" stepKey="setSecureBaseURL"/> + <executeJS function="return window.location.host" stepKey="hostname"/> + <magentoCLI command="config:set web/secure/base_url https://{$hostname}/" stepKey="setSecureBaseURL"/> <magentoCLI command="config:set web/secure/use_in_frontend 1" stepKey="useSecureURLsOnStorefront"/> <magentoCLI command="cache:flush" stepKey="flushCache"/> </before> <after> <magentoCLI command="config:set web/secure/use_in_frontend 0" stepKey="dontUseSecureURLsOnStorefront"/> + <magentoCLI command="config:set web/secure/base_url {{_ENV.MAGENTO_BASE_URL}}" stepKey="setSecureBaseURL"/> <magentoCLI command="cache:flush" stepKey="flushCache"/> </after> - <!-- Go to Unsecure URL --> - <amOnPage url="/checkout" stepKey="goToCheckoutPage"/> - <!-- Verify Secure URL Redirect --> - <seeInCurrentUrl url="https://" stepKey="seeSecureURL"/> + <executeJS function="return window.location.host" stepKey="hostname"/> + <amOnUrl url="http://{$hostname}/checkout" stepKey="goToUnsecureCheckoutURL"/> + <seeCurrentUrlEquals url="https://{$hostname}/checkout" stepKey="seeSecureCheckoutURL"/> + <amOnUrl url="http://{$hostname}/checkout/sidebar" stepKey="goToUnsecureCheckoutSidebarURL"/> + <seeCurrentUrlEquals url="http://{$hostname}/checkout/sidebar" stepKey="seeUnsecureCheckoutSidebarURL"/> </test> </tests> diff --git a/app/code/Magento/Contact/Test/Mftf/Test/StorefrontVerifySecureURLRedirectContactTest.xml b/app/code/Magento/Contact/Test/Mftf/Test/StorefrontVerifySecureURLRedirectContactTest.xml index 2987d8e18ae35..70bb6fa7b9fa7 100644 --- a/app/code/Magento/Contact/Test/Mftf/Test/StorefrontVerifySecureURLRedirectContactTest.xml +++ b/app/code/Magento/Contact/Test/Mftf/Test/StorefrontVerifySecureURLRedirectContactTest.xml @@ -18,21 +18,22 @@ <testCaseId value="MC-15539"/> <group value="contact"/> <group value="configuration"/> + <group value="secure_storefront_url"/> </annotations> <before> <amOnPage url="/" stepKey="goToHomePage"/> - <executeJS function="return window.location.host" stepKey="baseURL"/> - <magentoCLI command="config:set web/secure/base_url https://{$baseURL}/" stepKey="setSecureBaseURL"/> + <executeJS function="return window.location.host" stepKey="hostname"/> + <magentoCLI command="config:set web/secure/base_url https://{$hostname}/" stepKey="setSecureBaseURL"/> <magentoCLI command="config:set web/secure/use_in_frontend 1" stepKey="useSecureURLsOnStorefront"/> <magentoCLI command="cache:flush" stepKey="flushCache"/> </before> <after> <magentoCLI command="config:set web/secure/use_in_frontend 0" stepKey="dontUseSecureURLsOnStorefront"/> + <magentoCLI command="config:set web/secure/base_url {{_ENV.MAGENTO_BASE_URL}}" stepKey="setSecureBaseURL"/> <magentoCLI command="cache:flush" stepKey="flushCache"/> </after> - <!-- Go to Unsecure URL --> - <amOnPage url="/contact" stepKey="goToContactPage"/> - <!-- Verify Secure URL Redirect --> - <seeInCurrentUrl url="https://" stepKey="seeSecureURL"/> + <executeJS function="return window.location.host" stepKey="hostname"/> + <amOnUrl url="http://{$hostname}/contact" stepKey="goToUnsecureContactURL"/> + <seeCurrentUrlEquals url="https://{$hostname}/contact" stepKey="seeSecureContactURL"/> </test> </tests> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontVerifySecureURLRedirectCustomerTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontVerifySecureURLRedirectCustomerTest.xml index 4fdb3a791569e..0159879b81d46 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontVerifySecureURLRedirectCustomerTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontVerifySecureURLRedirectCustomerTest.xml @@ -15,28 +15,27 @@ <title value="Verify Secure URLs For Storefront Customer Pages"/> <description value="Verify that the Secure URL configuration applies to the Customer pages on the Storefront"/> <severity value="MAJOR"/> - <testCaseId value="MC-15540"/> + <testCaseId value="MC-15618"/> <group value="customer"/> <group value="configuration"/> + <group value="secure_storefront_url"/> </annotations> <before> - <createData entity="Simple_US_Customer" stepKey="customer"/> - <actionGroup ref="LoginToStorefrontActionGroup" stepKey="signThirdSimpleUsCustomer"> - <argument name="Customer" value="$$customer$$"/> - </actionGroup> - <executeJS function="return window.location.host" stepKey="baseURL"/> - <magentoCLI command="config:set web/secure/base_url https://{$baseURL}/" stepKey="setSecureBaseURL"/> + <amOnPage url="/" stepKey="goToHomePage"/> + <executeJS function="return window.location.host" stepKey="hostname"/> + <magentoCLI command="config:set web/secure/base_url https://{$hostname}/" stepKey="setSecureBaseURL"/> <magentoCLI command="config:set web/secure/use_in_frontend 1" stepKey="useSecureURLsOnStorefront"/> <magentoCLI command="cache:flush" stepKey="flushCache"/> </before> <after> <magentoCLI command="config:set web/secure/use_in_frontend 0" stepKey="dontUseSecureURLsOnStorefront"/> + <magentoCLI command="config:set web/secure/base_url {{_ENV.MAGENTO_BASE_URL}}" stepKey="setSecureBaseURL"/> <magentoCLI command="cache:flush" stepKey="flushCache"/> - <deleteData createDataKey="customer" stepKey="deleteCustomer"/> </after> - <!-- Go to Unsecure URL --> - <amOnPage url="/storecredit/info/" stepKey="goToStoreCreditInfoPage"/> - <!-- Verify Secure URL Redirect --> - <seeInCurrentUrl url="https://" stepKey="seeSecureURL"/> + <executeJS function="return window.location.host" stepKey="hostname"/> + <amOnUrl url="http://{$hostname}/customer" stepKey="goToUnsecureCustomerURL"/> + <seeCurrentUrlEquals url="https://{$hostname}/customer" stepKey="seeSecureCustomerURL"/> + <amOnUrl url="http://{$hostname}/customer/section/load" stepKey="goToUnsecureCustomerSectionLoadURL"/> + <seeCurrentUrlEquals url="http://{$hostname}/customer/section/load" stepKey="seeUnsecureCustomerSectionLoadURL"/> </test> </tests> diff --git a/app/code/Magento/Downloadable/Test/Mftf/Test/StorefrontVerifySecureURLRedirectDownloadableTest.xml b/app/code/Magento/Downloadable/Test/Mftf/Test/StorefrontVerifySecureURLRedirectDownloadableTest.xml new file mode 100644 index 0000000000000..3e561d4a4ed5d --- /dev/null +++ b/app/code/Magento/Downloadable/Test/Mftf/Test/StorefrontVerifySecureURLRedirectDownloadableTest.xml @@ -0,0 +1,49 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="StorefrontVerifySecureURLRedirectDownloadable"> + <annotations> + <features value="Downloadable"/> + <stories value="Storefront Secure URLs"/> + <title value="Verify Secure URLs For Storefront Downloadable Pages"/> + <description value="Verify that the Secure URL configuration applies to the Downloadable pages on the Storefront"/> + <severity value="MAJOR"/> + <testCaseId value="MC-15616"/> + <group value="downloadable"/> + <group value="configuration"/> + <group value="secure_storefront_url"/> + </annotations> + <before> + <createData entity="Simple_US_Customer" stepKey="customer"/> + <createData entity="Default_Company" stepKey="company"> + <requiredEntity createDataKey="customer"/> + </createData> + <actionGroup ref="LoginToStorefrontActionGroup" stepKey="signThirdSimpleUsCustomer"> + <argument name="Customer" value="$$customer$$"/> + </actionGroup> + <executeJS function="return window.location.host" stepKey="hostname"/> + <magentoCLI command="config:set web/secure/base_url https://{$hostname}/" stepKey="setSecureBaseURL"/> + <magentoCLI command="config:set web/secure/use_in_frontend 1" stepKey="useSecureURLsOnStorefront"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> + </before> + <after> + <magentoCLI command="config:set web/secure/use_in_frontend 0" stepKey="dontUseSecureURLsOnStorefront"/> + <magentoCLI command="config:set web/secure/base_url {{_ENV.MAGENTO_BASE_URL}}" stepKey="setSecureBaseURL"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> + <deleteData createDataKey="company" stepKey="deleteCompany"/> + <deleteData createDataKey="customer" stepKey="deleteCompanyAdmin"/> + </after> + <executeJS function="return window.location.host" stepKey="hostname"/> + <amOnUrl url="http://{$hostname}/downloadable/customer" stepKey="goToUnsecureDownloadableCustomerURL"/> + <seeCurrentUrlEquals url="https://{$hostname}/downloadable/customer" stepKey="seeSecureDownloadableCustomerURL"/> + <amOnUrl url="http://{$hostname}/downloadable/download" stepKey="goToUnsecureDownloadableDownloadURL"/> + <seeCurrentUrlEquals url="https://{$hostname}/downloadable/download" stepKey="seeSecureDownloadableDownloadURL"/> + </test> +</tests> diff --git a/app/code/Magento/Multishipping/Test/Mftf/Test/StorefrontVerifySecureURLRedirectMultishippingTest.xml b/app/code/Magento/Multishipping/Test/Mftf/Test/StorefrontVerifySecureURLRedirectMultishippingTest.xml new file mode 100644 index 0000000000000..5198a02a867e7 --- /dev/null +++ b/app/code/Magento/Multishipping/Test/Mftf/Test/StorefrontVerifySecureURLRedirectMultishippingTest.xml @@ -0,0 +1,43 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="StorefrontVerifySecureURLRedirectMultishipping"> + <annotations> + <features value="Multishipping"/> + <stories value="Storefront Secure URLs"/> + <title value="Verify Secure URLs For Storefront Multishipping Pages"/> + <description value="Verify that the Secure URL configuration applies to the Multishipping pages on the Storefront"/> + <severity value="MAJOR"/> + <testCaseId value="MC-15611"/> + <group value="multishipping"/> + <group value="configuration"/> + <group value="secure_storefront_url"/> + </annotations> + <before> + <createData entity="Simple_US_Customer" stepKey="customer"/> + <actionGroup ref="LoginToStorefrontActionGroup" stepKey="signThirdSimpleUsCustomer"> + <argument name="Customer" value="$$customer$$"/> + </actionGroup> + <executeJS function="return window.location.host" stepKey="hostname"/> + <magentoCLI command="config:set web/secure/base_url https://{$hostname}/" stepKey="setSecureBaseURL"/> + <magentoCLI command="config:set web/secure/use_in_frontend 1" stepKey="useSecureURLsOnStorefront"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> + </before> + <after> + <magentoCLI command="config:set web/secure/use_in_frontend 0" stepKey="dontUseSecureURLsOnStorefront"/> + <magentoCLI command="config:set web/secure/base_url {{_ENV.MAGENTO_BASE_URL}}" stepKey="setSecureBaseURL"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> + <deleteData createDataKey="customer" stepKey="deleteCustomer"/> + </after> + <executeJS function="return window.location.host" stepKey="hostname"/> + <amOnUrl url="http://{$hostname}/multishipping/checkout" stepKey="goToUnsecureMultishippingCheckoutURL"/> + <seeCurrentUrlEquals url="https://{$hostname}/multishipping/checkout" stepKey="seeSecureMultishippingCheckoutURL"/> + </test> +</tests> diff --git a/app/code/Magento/Newsletter/Test/Mftf/Test/StorefrontVerifySecureURLRedirectNewsletterTest.xml b/app/code/Magento/Newsletter/Test/Mftf/Test/StorefrontVerifySecureURLRedirectNewsletterTest.xml index df8a2690dc9a4..c3a475ab3d56f 100644 --- a/app/code/Magento/Newsletter/Test/Mftf/Test/StorefrontVerifySecureURLRedirectNewsletterTest.xml +++ b/app/code/Magento/Newsletter/Test/Mftf/Test/StorefrontVerifySecureURLRedirectNewsletterTest.xml @@ -15,28 +15,29 @@ <title value="Verify Secure URLs For Storefront Newsletter Pages"/> <description value="Verify that the Secure URL configuration applies to the Newsletter pages on the Storefront"/> <severity value="MAJOR"/> - <testCaseId value="MC-15530"/> + <testCaseId value="MC-15584"/> <group value="newsletter"/> <group value="configuration"/> + <group value="secure_storefront_url"/> </annotations> <before> <createData entity="Simple_US_Customer" stepKey="customer"/> <actionGroup ref="LoginToStorefrontActionGroup" stepKey="signThirdSimpleUsCustomer"> <argument name="Customer" value="$$customer$$"/> </actionGroup> - <executeJS function="return window.location.host" stepKey="baseURL"/> - <magentoCLI command="config:set web/secure/base_url https://{$baseURL}/" stepKey="setSecureBaseURL"/> + <executeJS function="return window.location.host" stepKey="hostname"/> + <magentoCLI command="config:set web/secure/base_url https://{$hostname}/" stepKey="setSecureBaseURL"/> <magentoCLI command="config:set web/secure/use_in_frontend 1" stepKey="useSecureURLsOnStorefront"/> <magentoCLI command="cache:flush" stepKey="flushCache"/> </before> <after> <magentoCLI command="config:set web/secure/use_in_frontend 0" stepKey="dontUseSecureURLsOnStorefront"/> + <magentoCLI command="config:set web/secure/base_url {{_ENV.MAGENTO_BASE_URL}}" stepKey="setSecureBaseURL"/> <magentoCLI command="cache:flush" stepKey="flushCache"/> <deleteData createDataKey="customer" stepKey="deleteCustomer"/> </after> - <!-- Go to Unsecure URL --> - <amOnPage url="/newsletter/manage" stepKey="goToNewsletterPage"/> - <!-- Verify Secure URL Redirect --> - <seeInCurrentUrl url="https://" stepKey="seeSecureURL"/> + <executeJS function="return window.location.host" stepKey="hostname"/> + <amOnUrl url="http://{$hostname}/newsletter/manage" stepKey="goToUnsecureNewsletterManageURL"/> + <seeCurrentUrlEquals url="https://{$hostname}/newsletter/manage" stepKey="seeSecureNewsletterManageURL"/> </test> </tests> diff --git a/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontVerifySecureURLRedirectPaypalTest.xml b/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontVerifySecureURLRedirectPaypalTest.xml index 9360250710f40..8de3ad034d632 100644 --- a/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontVerifySecureURLRedirectPaypalTest.xml +++ b/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontVerifySecureURLRedirectPaypalTest.xml @@ -18,25 +18,46 @@ <testCaseId value="MC-15541"/> <group value="paypal"/> <group value="configuration"/> + <group value="secure_storefront_url"/> </annotations> <before> <createData entity="Simple_US_Customer" stepKey="customer"/> <actionGroup ref="LoginToStorefrontActionGroup" stepKey="signThirdSimpleUsCustomer"> <argument name="Customer" value="$$customer$$"/> </actionGroup> - <executeJS function="return window.location.host" stepKey="baseURL"/> - <magentoCLI command="config:set web/secure/base_url https://{$baseURL}/" stepKey="setSecureBaseURL"/> + <executeJS function="return window.location.host" stepKey="hostname"/> + <magentoCLI command="config:set web/secure/base_url https://{$hostname}/" stepKey="setSecureBaseURL"/> <magentoCLI command="config:set web/secure/use_in_frontend 1" stepKey="useSecureURLsOnStorefront"/> <magentoCLI command="cache:flush" stepKey="flushCache"/> </before> <after> <magentoCLI command="config:set web/secure/use_in_frontend 0" stepKey="dontUseSecureURLsOnStorefront"/> + <magentoCLI command="config:set web/secure/base_url {{_ENV.MAGENTO_BASE_URL}}" stepKey="setSecureBaseURL"/> <magentoCLI command="cache:flush" stepKey="flushCache"/> <deleteData createDataKey="customer" stepKey="deleteCustomer"/> </after> - <!-- Go to Unsecure URL --> - <amOnPage url="/paypal/billing_agreement" stepKey="goToPaypalPage"/> - <!-- Verify Secure URL Redirect --> - <seeInCurrentUrl url="https://" stepKey="seeSecureURL"/> + <executeJS function="return window.location.host" stepKey="hostname"/> + <amOnUrl url="http://{$hostname}/paypal/billing" stepKey="goToUnsecurePaypalBillingURL"/> + <seeCurrentUrlEquals url="https://{$hostname}/paypal/billing" stepKey="seeSecurePaypalBillingURL"/> + <amOnUrl url="http://{$hostname}/paypal/billing_agreement" stepKey="goToUnsecurePaypalBillingAgreementURL"/> + <seeCurrentUrlEquals url="https://{$hostname}/paypal/billing_agreement" stepKey="seeSecurePaypalBillingAgreementURL"/> + <amOnUrl url="http://{$hostname}/paypal/bml" stepKey="goToUnsecurePaypalBmlURL"/> + <seeCurrentUrlEquals url="https://{$hostname}/paypal/bml" stepKey="seeSecurePaypalBmlURL"/> + <amOnUrl url="http://{$hostname}/paypal/hostedpro" stepKey="goToUnsecurePaypalHostedProURL"/> + <seeCurrentUrlEquals url="https://{$hostname}/paypal/hostedpro" stepKey="seeSecurePaypalHostedProURL"/> + <amOnUrl url="http://{$hostname}/paypal/ipn" stepKey="goToUnsecurePaypalIpnURL"/> + <seeCurrentUrlEquals url="https://{$hostname}/paypal/ipn" stepKey="seeSecurePaypalIpnURL"/> + <amOnUrl url="http://{$hostname}/paypal/payflow" stepKey="goToUnsecurePaypalPayflowUL"/> + <seeCurrentUrlEquals url="https://{$hostname}/paypal/payflow" stepKey="seeSecurePaypalPayflowURL"/> + <amOnUrl url="http://{$hostname}/paypal/payflowadvanced" stepKey="goToUnsecurePaypalPayflowAdvancedURL"/> + <seeCurrentUrlEquals url="https://{$hostname}/paypal/payflowadvanced" stepKey="seeSecurePaypalPayflowAdvancedURL"/> + <amOnUrl url="http://{$hostname}/paypal/payflowbml" stepKey="goToUnsecurePaypalPayflowBmlURL"/> + <seeCurrentUrlEquals url="https://{$hostname}/paypal/payflowbml" stepKey="seeSecurePaypalPayflowBmlURL"/> + <amOnUrl url="http://{$hostname}/paypal/payflowexpress" stepKey="goToUnsecurePaypalPayflowExpressURL"/> + <seeCurrentUrlEquals url="https://{$hostname}/paypal/payflowexpress" stepKey="seeSecurePaypalPayflowExpressURL"/> + <amOnUrl url="http://{$hostname}/paypal/transparent" stepKey="goToUnsecurePaypalTransparentURL"/> + <seeCurrentUrlEquals url="https://{$hostname}/paypal/transparent" stepKey="seeSecurePaypalTransparentURL"/> + <amOnUrl url="http://{$hostname}/paypal/express" stepKey="goToUnsecurePaypalExpressURL"/> + <seeCurrentUrlEquals url="https://{$hostname}/paypal/express" stepKey="seeSecurePaypalExpressURL"/> </test> </tests> diff --git a/app/code/Magento/Persistent/Test/Mftf/Test/StorefrontVerifySecureURLRedirectPersistentTest.xml b/app/code/Magento/Persistent/Test/Mftf/Test/StorefrontVerifySecureURLRedirectPersistentTest.xml new file mode 100644 index 0000000000000..fcfe7209df0be --- /dev/null +++ b/app/code/Magento/Persistent/Test/Mftf/Test/StorefrontVerifySecureURLRedirectPersistentTest.xml @@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="StorefrontVerifySecureURLRedirectPersistent"> + <annotations> + <features value="Persistent"/> + <stories value="Storefront Secure URLs"/> + <title value="Verify Secure URLs For Storefront Persistent Pages"/> + <description value="Verify that the Secure URL configuration applies to the Persistent pages on the Storefront"/> + <severity value="MAJOR"/> + <testCaseId value="MC-15617"/> + <group value="persistent"/> + <group value="configuration"/> + <group value="secure_storefront_url"/> + </annotations> + <before> + <createData entity="Simple_US_Customer" stepKey="customer"/> + <createData entity="Default_Company" stepKey="company"> + <requiredEntity createDataKey="customer"/> + </createData> + <actionGroup ref="LoginToStorefrontActionGroup" stepKey="signThirdSimpleUsCustomer"> + <argument name="Customer" value="$$customer$$"/> + </actionGroup> + <executeJS function="return window.location.host" stepKey="hostname"/> + <magentoCLI command="config:set web/secure/base_url https://{$hostname}/" stepKey="setSecureBaseURL"/> + <magentoCLI command="config:set web/secure/use_in_frontend 1" stepKey="useSecureURLsOnStorefront"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> + </before> + <after> + <magentoCLI command="config:set web/secure/use_in_frontend 0" stepKey="dontUseSecureURLsOnStorefront"/> + <magentoCLI command="config:set web/secure/base_url {{_ENV.MAGENTO_BASE_URL}}" stepKey="setSecureBaseURL"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> + <deleteData createDataKey="company" stepKey="deleteCompany"/> + <deleteData createDataKey="customer" stepKey="deleteCompanyAdmin"/> + </after> + <executeJS function="return window.location.host" stepKey="hostname"/> + <amOnUrl url="http://{$hostname}/persistent/index/saveMethod" stepKey="goToUnsecurePersistentIndexSaveMethodURL"/> + <seeCurrentUrlEquals url="https://{$hostname}/persistent/index/saveMethod" stepKey="seeSecurePersistentIndexSaveMethodURL"/> + </test> +</tests> diff --git a/app/code/Magento/Review/Test/Mftf/Test/StorefrontVerifySecureURLRedirectReviewTest.xml b/app/code/Magento/Review/Test/Mftf/Test/StorefrontVerifySecureURLRedirectReviewTest.xml index 8ae4478265b5c..83a547149091a 100644 --- a/app/code/Magento/Review/Test/Mftf/Test/StorefrontVerifySecureURLRedirectReviewTest.xml +++ b/app/code/Magento/Review/Test/Mftf/Test/StorefrontVerifySecureURLRedirectReviewTest.xml @@ -17,25 +17,27 @@ <severity value="MAJOR"/> <testCaseId value="MC-15542"/> <group value="review"/> + <group value="configuration"/> + <group value="secure_storefront_url"/> </annotations> <before> <createData entity="Simple_US_Customer" stepKey="customer"/> <actionGroup ref="LoginToStorefrontActionGroup" stepKey="signThirdSimpleUsCustomer"> <argument name="Customer" value="$$customer$$"/> </actionGroup> - <executeJS function="return window.location.host" stepKey="baseURL"/> - <magentoCLI command="config:set web/secure/base_url https://{$baseURL}/" stepKey="setSecureBaseURL"/> + <executeJS function="return window.location.host" stepKey="hostname"/> + <magentoCLI command="config:set web/secure/base_url https://{$hostname}/" stepKey="setSecureBaseURL"/> <magentoCLI command="config:set web/secure/use_in_frontend 1" stepKey="useSecureURLsOnStorefront"/> <magentoCLI command="cache:flush" stepKey="flushCache"/> </before> <after> <magentoCLI command="config:set web/secure/use_in_frontend 0" stepKey="dontUseSecureURLsOnStorefront"/> + <magentoCLI command="config:set web/secure/base_url {{_ENV.MAGENTO_BASE_URL}}" stepKey="setSecureBaseURL"/> <magentoCLI command="cache:flush" stepKey="flushCache"/> <deleteData createDataKey="customer" stepKey="deleteCustomer"/> </after> - <!-- Go to Unsecure URL --> - <amOnPage url="/review/customer" stepKey="goToReviewPage"/> - <!-- Verify Secure URL Redirect --> - <seeInCurrentUrl url="https://" stepKey="seeSecureURL"/> + <executeJS function="return window.location.host" stepKey="hostname"/> + <amOnUrl url="http://{$hostname}/review/customer" stepKey="goToUnsecureReviewURL"/> + <seeCurrentUrlEquals url="https://{$hostname}/review/customer" stepKey="seeSecureReviewURL"/> </test> </tests> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/StorefrontVerifySecureURLRedirectSalesTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/StorefrontVerifySecureURLRedirectSalesTest.xml new file mode 100644 index 0000000000000..80e083a6886c7 --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/Test/StorefrontVerifySecureURLRedirectSalesTest.xml @@ -0,0 +1,43 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="StorefrontVerifySecureURLRedirectSales"> + <annotations> + <features value="Sales"/> + <stories value="Storefront Secure URLs"/> + <title value="Verify Secure URLs For Storefront Sales Pages"/> + <description value="Verify that the Secure URL configuration applies to the Sales pages on the Storefront"/> + <severity value="MAJOR"/> + <testCaseId value="MC-15607"/> + <group value="sales"/> + <group value="configuration"/> + <group value="secure_storefront_url"/> + </annotations> + <before> + <createData entity="Simple_US_Customer" stepKey="customer"/> + <actionGroup ref="LoginToStorefrontActionGroup" stepKey="signThirdSimpleUsCustomer"> + <argument name="Customer" value="$$customer$$"/> + </actionGroup> + <executeJS function="return window.location.host" stepKey="hostname"/> + <magentoCLI command="config:set web/secure/base_url https://{$hostname}/" stepKey="setSecureBaseURL"/> + <magentoCLI command="config:set web/secure/use_in_frontend 1" stepKey="useSecureURLsOnStorefront"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> + </before> + <after> + <magentoCLI command="config:set web/secure/use_in_frontend 0" stepKey="dontUseSecureURLsOnStorefront"/> + <magentoCLI command="config:set web/secure/base_url {{_ENV.MAGENTO_BASE_URL}}" stepKey="setSecureBaseURL"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> + <deleteData createDataKey="customer" stepKey="deleteCustomer"/> + </after> + <executeJS function="return window.location.host" stepKey="hostname"/> + <amOnUrl url="http://{$hostname}/sales" stepKey="goToUnsecureSalesURL"/> + <seeCurrentUrlEquals url="https://{$hostname}/sales" stepKey="seeSecureSalesURL"/> + </test> +</tests> diff --git a/app/code/Magento/Vault/Test/Mftf/Test/StorefrontVerifySecureURLRedirectVaultTest.xml b/app/code/Magento/Vault/Test/Mftf/Test/StorefrontVerifySecureURLRedirectVaultTest.xml index 05d5ea992bfb9..188747a121331 100644 --- a/app/code/Magento/Vault/Test/Mftf/Test/StorefrontVerifySecureURLRedirectVaultTest.xml +++ b/app/code/Magento/Vault/Test/Mftf/Test/StorefrontVerifySecureURLRedirectVaultTest.xml @@ -18,25 +18,26 @@ <testCaseId value="MC-15562"/> <group value="vault"/> <group value="configuration"/> + <group value="secure_storefront_url"/> </annotations> <before> <createData entity="Simple_US_Customer" stepKey="customer"/> <actionGroup ref="LoginToStorefrontActionGroup" stepKey="signThirdSimpleUsCustomer"> <argument name="Customer" value="$$customer$$"/> </actionGroup> - <executeJS function="return window.location.host" stepKey="baseURL"/> - <magentoCLI command="config:set web/secure/base_url https://{$baseURL}/" stepKey="setSecureBaseURL"/> + <executeJS function="return window.location.host" stepKey="hostname"/> + <magentoCLI command="config:set web/secure/base_url https://{$hostname}/" stepKey="setSecureBaseURL"/> <magentoCLI command="config:set web/secure/use_in_frontend 1" stepKey="useSecureURLsOnStorefront"/> <magentoCLI command="cache:flush" stepKey="flushCache"/> </before> <after> <magentoCLI command="config:set web/secure/use_in_frontend 0" stepKey="dontUseSecureURLsOnStorefront"/> + <magentoCLI command="config:set web/secure/base_url {{_ENV.MAGENTO_BASE_URL}}" stepKey="setSecureBaseURL"/> <magentoCLI command="cache:flush" stepKey="flushCache"/> <deleteData createDataKey="customer" stepKey="deleteCustomer"/> </after> - <!-- Go to Unsecure URL --> - <amOnPage url="/vault/cards/listaction/" stepKey="goToStoreVaultCardsListactionPage"/> - <!-- Verify Secure URL Redirect --> - <seeInCurrentUrl url="https://" stepKey="seeSecureURL"/> + <executeJS function="return window.location.host" stepKey="hostname"/> + <amOnUrl url="http://{$hostname}/vault" stepKey="goToUnsecureVaultURL"/> + <seeCurrentUrlEquals url="https://{$hostname}/vault" stepKey="seeSecureVaultURL"/> </test> </tests> diff --git a/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontVerifySecureURLRedirectWishlistTest.xml b/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontVerifySecureURLRedirectWishlistTest.xml index 4fbfa3dda971d..5f28681031d2a 100644 --- a/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontVerifySecureURLRedirectWishlistTest.xml +++ b/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontVerifySecureURLRedirectWishlistTest.xml @@ -18,14 +18,15 @@ <testCaseId value="MC-15543"/> <group value="wishlist"/> <group value="configuration"/> + <group value="secure_storefront_url"/> </annotations> <before> <createData entity="Simple_US_Customer" stepKey="customer"/> <actionGroup ref="LoginToStorefrontActionGroup" stepKey="signThirdSimpleUsCustomer"> <argument name="Customer" value="$$customer$$"/> </actionGroup> - <executeJS function="return window.location.host" stepKey="baseURL"/> - <magentoCLI command="config:set web/secure/base_url https://{$baseURL}/" stepKey="setSecureBaseURL"/> + <executeJS function="return window.location.host" stepKey="hostname"/> + <magentoCLI command="config:set web/secure/base_url https://{$hostname}/" stepKey="setSecureBaseURL"/> <magentoCLI command="config:set web/secure/use_in_frontend 1" stepKey="useSecureURLsOnStorefront"/> <magentoCLI command="cache:flush" stepKey="flushCache"/> </before> @@ -35,9 +36,8 @@ <magentoCLI command="cache:flush" stepKey="flushCache"/> <deleteData createDataKey="customer" stepKey="deleteCustomer"/> </after> - <!-- Go to Unsecure URL --> - <amOnPage url="/wishlist" stepKey="goToWishlistPage"/> - <!-- Verify Secure URL Redirect --> - <seeInCurrentUrl url="https://" stepKey="seeSecureURL"/> + <executeJS function="return window.location.host" stepKey="hostname"/> + <amOnUrl url="http://{$hostname}/wishlist" stepKey="goToUnsecureWishlistURL"/> + <seeCurrentUrlEquals url="https://{$hostname}/wishlist" stepKey="seeSecureWishlistURL"/> </test> </tests> From 5a628e70e3083a51cf2e9635a5dfe1056ad70cca Mon Sep 17 00:00:00 2001 From: Hwashiang Yu <hwyu@adobe.com> Date: Thu, 28 Mar 2019 15:35:35 -0500 Subject: [PATCH 152/773] MC-13896: User Role Template Update - Updated RolesTest to use the correct mock object interface --- .../Test/Unit/Block/User/Edit/Tab/RolesTest.php | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/app/code/Magento/User/Test/Unit/Block/User/Edit/Tab/RolesTest.php b/app/code/Magento/User/Test/Unit/Block/User/Edit/Tab/RolesTest.php index d1a7fcaaa4540..84e91b4f1e50b 100644 --- a/app/code/Magento/User/Test/Unit/Block/User/Edit/Tab/RolesTest.php +++ b/app/code/Magento/User/Test/Unit/Block/User/Edit/Tab/RolesTest.php @@ -7,13 +7,13 @@ namespace Magento\User\Test\Unit\Block\User\Edit\Tab; /** - * Class UserTest to cover Magento\User\Block\Role\Grid\User + * Class RolesTest to cover \Magento\User\Block\User\Edit\Tab\Roles * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class RolesTest extends \PHPUnit\Framework\TestCase { - /** @var \Magento\User\Block\Role\Grid\User */ + /** @var \Magento\User\Block\User\Edit\Tab\Roles */ protected $model; /** @var \Magento\Backend\Helper\Data|\PHPUnit_Framework_MockObject_MockObject */ @@ -68,13 +68,8 @@ protected function setUp() ->setMethods([]) ->getMock(); - $this->roleFactoryMock = $this->getMockBuilder(\Magento\Authorization\Model\RoleFactory::class) - ->disableOriginalConstructor() - ->setMethods(['create']) - ->getMock(); - $this->userRolesFactoryMock = $this - ->getMockBuilder(\Magento\User\Model\ResourceModel\Role\User\CollectionFactory::class) + ->getMockBuilder(\Magento\Authorization\Model\ResourceModel\Role\CollectionFactory::class) ->disableOriginalConstructor() ->setMethods(['create']) ->getMock(); @@ -106,9 +101,8 @@ protected function setUp() 'backendHelper' => $this->backendHelperMock, 'jsonEncoder' => $this->jsonEncoderMock, 'jsonDecoder' => $this->jsonDecoderMock, - 'coreRegistry' => $this->registryMock, - 'roleFactory' => $this->roleFactoryMock, 'userRolesFactory' => $this->userRolesFactoryMock, + 'coreRegistry' => $this->registryMock, 'request' => $this->requestInterfaceMock, 'urlBuilder' => $this->urlInterfaceMock, 'layout' => $this->layoutMock, @@ -123,6 +117,6 @@ public function testSelectedRolesIncorrectUserRoles() $paramValue = 'not_JSON'; $this->requestInterfaceMock->expects($this->once())->method('getParam')->with($param)->willReturn($paramValue); $this->jsonDecoderMock->expects($this->once())->method('decode')->with($paramValue)->willReturn(null); - $this->assertEquals('{}', $this->model->getUsers(true)); + $this->assertEquals('{}', $this->model->getSelectedRoles(true)); } } From c5fd613a73c3c7ed8afbdc898641dd027584cfcf Mon Sep 17 00:00:00 2001 From: Mark Berube <berube@adobe.com> Date: Thu, 28 Mar 2019 15:44:36 -0500 Subject: [PATCH 153/773] MC-15036: Hardcode DHL gateway URL --- app/code/Magento/Dhl/Model/Carrier.php | 22 ++++++++-- .../Dhl/Test/Unit/Model/CarrierTest.php | 44 +++++++++++++++++++ app/code/Magento/Dhl/etc/adminhtml/system.xml | 7 +-- app/code/Magento/Dhl/etc/config.xml | 1 + 4 files changed, 68 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/Dhl/Model/Carrier.php b/app/code/Magento/Dhl/Model/Carrier.php index 1ad8b79ad12f3..2fc61b89e6990 100644 --- a/app/code/Magento/Dhl/Model/Carrier.php +++ b/app/code/Magento/Dhl/Model/Carrier.php @@ -4,6 +4,8 @@ * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Dhl\Model; use Magento\Catalog\Model\Product\Type; @@ -985,7 +987,7 @@ protected function _getQuotes() protected function _getQuotesFromServer($request) { $client = $this->_httpClientFactory->create(); - $client->setUri((string)$this->getConfigData('gateway_url')); + $client->setUri($this->getGatewayURL()); $client->setConfig(['maxredirects' => 0, 'timeout' => 30]); $client->setRawData(utf8_encode($request)); @@ -1578,7 +1580,7 @@ protected function _doRequest() try { /** @var \Magento\Framework\HTTP\ZendClient $client */ $client = $this->_httpClientFactory->create(); - $client->setUri((string)$this->getConfigData('gateway_url')); + $client->setUri($this->getGatewayURL()); $client->setConfig(['maxredirects' => 0, 'timeout' => 30]); $client->setRawData($request); $responseBody = $client->request(\Magento\Framework\HTTP\ZendClient::POST)->getBody(); @@ -1745,7 +1747,7 @@ protected function _getXMLTracking($trackings) try { /** @var \Magento\Framework\HTTP\ZendClient $client */ $client = $this->_httpClientFactory->create(); - $client->setUri((string)$this->getConfigData('gateway_url')); + $client->setUri($this->getGatewayURL()); $client->setConfig(['maxredirects' => 0, 'timeout' => 30]); $client->setRawData($request); $responseBody = $client->request(\Magento\Framework\HTTP\ZendClient::POST)->getBody(); @@ -2021,4 +2023,18 @@ private function buildSoftwareVersion(): string { return substr($this->productMetadata->getVersion(), 0, 10); } + + /** + * Get the gateway URL + * + * @return string + */ + private function getGatewayURL(): string + { + if ($this->getConfigData('sandbox_mode')) { + return (string)$this->getConfigData('sandbox_url'); + } else { + return (string)$this->getConfigData('gateway_url'); + } + } } diff --git a/app/code/Magento/Dhl/Test/Unit/Model/CarrierTest.php b/app/code/Magento/Dhl/Test/Unit/Model/CarrierTest.php index c3d82ef34a448..1a8b3a7a8d70d 100644 --- a/app/code/Magento/Dhl/Test/Unit/Model/CarrierTest.php +++ b/app/code/Magento/Dhl/Test/Unit/Model/CarrierTest.php @@ -685,6 +685,50 @@ public function buildSoftwareVersionProvider() ]; } + /** + * Tests if the DHL client returns the appropriate API URL. + * + * @dataProvider getGatewayURLProvider + * @param $sandboxMode + * @param $expectedURL + * @throws \ReflectionException + */ + public function testGetGatewayURL($sandboxMode, $expectedURL) + { + $scopeConfigValueMap = [ + ['carriers/dhl/gateway_url', 'store', null, 'https://xmlpi-ea.dhl.com/XMLShippingServlet'], + ['carriers/dhl/sandbox_url', 'store', null, 'https://xmlpitest-ea.dhl.com/XMLShippingServlet'], + ['carriers/dhl/sandbox_mode', 'store', null, $sandboxMode] + ]; + + $this->scope->method('getValue') + ->willReturnMap($scopeConfigValueMap); + + $this->model = $this->objectManager->getObject( + Carrier::class, + [ + 'scopeConfig' => $this->scope + ] + ); + + $method = new \ReflectionMethod($this->model, 'getGatewayURL'); + $method->setAccessible(true); + $this->assertEquals($expectedURL, $method->invoke($this->model)); + } + + /** + * Data provider for testGetGatewayURL + * + * @return array + */ + public function getGatewayURLProvider() + { + return [ + 'standard_url' => [0, 'https://xmlpi-ea.dhl.com/XMLShippingServlet'], + 'sandbox_url' => [1, 'https://xmlpitest-ea.dhl.com/XMLShippingServlet'] + ]; + } + /** * Creates mock for XML factory. * diff --git a/app/code/Magento/Dhl/etc/adminhtml/system.xml b/app/code/Magento/Dhl/etc/adminhtml/system.xml index 37b653225c7b9..84cc7fd7097cd 100644 --- a/app/code/Magento/Dhl/etc/adminhtml/system.xml +++ b/app/code/Magento/Dhl/etc/adminhtml/system.xml @@ -14,9 +14,6 @@ <label>Enabled for Checkout</label> <source_model>Magento\Config\Model\Config\Source\Yesno</source_model> </field> - <field id="gateway_url" translate="label" type="text" sortOrder="20" showInDefault="1" showInWebsite="1" showInStore="0" canRestore="1"> - <label>Gateway URL</label> - </field> <field id="title" translate="label" type="text" sortOrder="20" showInDefault="1" showInWebsite="1" showInStore="1" canRestore="1"> <label>Title</label> </field> @@ -145,6 +142,10 @@ <label>Debug</label> <source_model>Magento\Config\Model\Config\Source\Yesno</source_model> </field> + <field id="sandbox_mode" translate="label" type="select" sortOrder="1960" showInDefault="1" showInWebsite="1" showInStore="0"> + <label>Sandbox Mode</label> + <source_model>Magento\Config\Model\Config\Source\Yesno</source_model> + </field> </group> </section> </system> diff --git a/app/code/Magento/Dhl/etc/config.xml b/app/code/Magento/Dhl/etc/config.xml index 79addefb34a16..b46152fb0ecad 100644 --- a/app/code/Magento/Dhl/etc/config.xml +++ b/app/code/Magento/Dhl/etc/config.xml @@ -25,6 +25,7 @@ <doc_methods>2,5,6,7,9,B,C,D,U,K,L,G,W,I,N,O,R,S,T,X</doc_methods> <free_method>G</free_method> <gateway_url>https://xmlpi-ea.dhl.com/XMLShippingServlet</gateway_url> + <sandbox_url>https://xmlpitest-ea.dhl.com/XMLShippingServlet</sandbox_url> <id backend_model="Magento\Config\Model\Config\Backend\Encrypted" /> <password backend_model="Magento\Config\Model\Config\Backend\Encrypted" /> <content_type>N</content_type> From 2475a7cbb6d2ae628fd46f1b08a40b2afbc4cf3f Mon Sep 17 00:00:00 2001 From: Andrew Molina <amolina@adobe.com> Date: Thu, 28 Mar 2019 15:46:22 -0500 Subject: [PATCH 154/773] MC-13954 - Update Product Import Temp Directory --- .../Model/Import/Uploader.php | 94 +++++++----- .../Test/Unit/Model/Import/UploaderTest.php | 135 +++++++++++++----- 2 files changed, 156 insertions(+), 73 deletions(-) diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Uploader.php b/app/code/Magento/CatalogImportExport/Model/Import/Uploader.php index dd0fb52028ab3..a35d04def43b8 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Uploader.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Uploader.php @@ -6,6 +6,7 @@ namespace Magento\CatalogImportExport\Model\Import; use Magento\Framework\App\Filesystem\DirectoryList; +use Magento\Framework\App\ObjectManager; use Magento\Framework\Filesystem\DriverPool; /** @@ -36,7 +37,7 @@ class Uploader extends \Magento\MediaStorage\Model\File\Uploader * * @var string */ - private $_downloadDir; + private $downloadDir; /** * Destination directory. @@ -101,6 +102,13 @@ class Uploader extends \Magento\MediaStorage\Model\File\Uploader */ protected $_coreFileStorage; + /** + * Instance of random data generator. + * + * @var \Magento\Framework\Math\Random + */ + private $random; + /** * @param \Magento\MediaStorage\Helper\File\Storage\Database $coreFileStorageDb * @param \Magento\MediaStorage\Helper\File\Storage $coreFileStorage @@ -109,6 +117,8 @@ class Uploader extends \Magento\MediaStorage\Model\File\Uploader * @param \Magento\Framework\Filesystem $filesystem * @param \Magento\Framework\Filesystem\File\ReadFactory $readFactory * @param string|null $filePath + * @param \Magento\Framework\Math\Random|null $random + * @throws \Magento\Framework\Exception\FileSystemException * @throws \Magento\Framework\Exception\LocalizedException */ public function __construct( @@ -118,7 +128,8 @@ public function __construct( \Magento\MediaStorage\Model\File\Validator\NotProtectedExtension $validator, \Magento\Framework\Filesystem $filesystem, \Magento\Framework\Filesystem\File\ReadFactory $readFactory, - $filePath = null + $filePath = null, + \Magento\Framework\Math\Random $random = null ) { $this->_imageFactory = $imageFactory; $this->_coreFileStorageDb = $coreFileStorageDb; @@ -129,7 +140,8 @@ public function __construct( if ($filePath !== null) { $this->_setUploadFile($filePath); } - $this->_downloadDir = DirectoryList::getDefaultConfig()[DirectoryList::TMP][DirectoryList::PATH]; + $this->random = $random ?: ObjectManager::getInstance()->get(\Magento\Framework\Math\Random::class); + $this->downloadDir = DirectoryList::getDefaultConfig()[DirectoryList::TMP][DirectoryList::PATH]; } /** @@ -158,49 +170,63 @@ public function init() */ public function move($fileName, $renameFileOff = false) { - if ($renameFileOff) { - $this->setAllowRenameFiles(false); - } - - $filePath = $this->getTmpDir() ? ($this->getTmpDir() . '/') : ''; + $this->setAllowRenameFiles(!$renameFileOff); if (preg_match('/\bhttps?:\/\//i', $fileName, $matches)) { $url = str_replace($matches[0], '', $fileName); - $driver = $matches[0] === $this->httpScheme ? DriverPool::HTTP : DriverPool::HTTPS; - $read = $this->_readFactory->create($url, $driver); - $filePath = $this->_downloadDir . '/'; - - //only use filename (for URI with query parameters) - $parsedUrlPath = parse_url($url, PHP_URL_PATH); - if ($parsedUrlPath) { - $urlPathValues = explode('/', $parsedUrlPath); - if (!empty($urlPathValues)) { - $fileName = end($urlPathValues); - } - } - - $fileExtension = pathinfo($fileName, PATHINFO_EXTENSION); - if ($fileExtension && !$this->checkAllowedExtension($fileExtension)) { - throw new \Magento\Framework\Exception\LocalizedException(__('Disallowed file type.')); - } - - $fileName = preg_replace('/[^a-z0-9\._-]+/i', '', $fileName); - $relativePath = $this->_directory->getRelativePath($filePath . $fileName); - $this->_directory->writeFile( - $relativePath, - $read->readAll() - ); + $driver = ($matches[0] === $this->httpScheme) ? DriverPool::HTTP : DriverPool::HTTPS; + $tmpFilePath = $this->downloadFileFromUrl($url, $driver); + } + else { + $tmpDir = $this->getTmpDir() ? ($this->getTmpDir() . '/') : ''; + $tmpFilePath = $this->_directory->getRelativePath( $tmpDir . $fileName); } - $filePath = $this->_directory->getRelativePath($filePath . $fileName); - $this->_setUploadFile($filePath); + $this->_setUploadFile($tmpFilePath); $destDir = $this->_directory->getAbsolutePath($this->getDestDir()); $result = $this->save($destDir); unset($result['path']); $result['name'] = self::getCorrectFileName($result['name']); + return $result; } + /** + * Writes a url-based file to the temp directory. + * + * @param string $url + * @param string $driver + * @return string + * @throws \Magento\Framework\Exception\FileSystemException + * @throws \Magento\Framework\Exception\LocalizedException + */ + private function downloadFileFromUrl($url, $driver) + { + $parsedUrlPath = parse_url($url, PHP_URL_PATH); + if (!$parsedUrlPath) { + throw new \Magento\Framework\Exception\LocalizedException(__('Could not parse resource url.')); + } + $urlPathValues = explode('/', $parsedUrlPath); + $fileName = preg_replace('/[^a-z0-9\._-]+/i', '', end($urlPathValues)); + + $fileExtension = pathinfo($fileName, PATHINFO_EXTENSION); + if ($fileExtension && !$this->checkAllowedExtension($fileExtension)) { + throw new \Magento\Framework\Exception\LocalizedException(__('Disallowed file type.')); + } + + $tmpFileName = str_replace(".$fileExtension", '', $fileName); + $tmpFileName .= '_' . $this->random->getRandomString(16); + $tmpFileName .= $fileExtension ? ".$fileExtension" : ''; + $tmpFilePath = $this->_directory->getRelativePath( $this->downloadDir . '/' . $tmpFileName); + + $this->_directory->writeFile( + $tmpFilePath, + $this->_readFactory->create($url, $driver)->readAll() + ); + + return $tmpFilePath; + } + /** * Prepare information about the file for moving * diff --git a/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/UploaderTest.php b/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/UploaderTest.php index 03653398599b2..7565e099e2020 100644 --- a/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/UploaderTest.php +++ b/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/UploaderTest.php @@ -43,6 +43,11 @@ class UploaderTest extends \PHPUnit\Framework\TestCase */ protected $directoryMock; + /** + * @var \Magento\Framework\Math\Random|\PHPUnit_Framework_MockObject_MockObject + */ + protected $random; + /** * @var \Magento\CatalogImportExport\Model\Import\Uploader|\PHPUnit_Framework_MockObject_MockObject */ @@ -84,6 +89,11 @@ protected function setUp() ->method('getDirectoryWrite') ->will($this->returnValue($this->directoryMock)); + $this->random = $this->getMockBuilder(\Magento\Framework\Math\Random::class) + ->disableOriginalConstructor() + ->setMethods(['getRandomString']) + ->getMock(); + $this->uploader = $this->getMockBuilder(\Magento\CatalogImportExport\Model\Import\Uploader::class) ->setConstructorArgs([ $this->coreFileStorageDb, @@ -92,6 +102,8 @@ protected function setUp() $this->validator, $this->filesystem, $this->readFactory, + null, + $this->random ]) ->setMethods(['_setUploadFile', 'save', 'getTmpDir', 'checkAllowedExtension']) ->getMock(); @@ -99,20 +111,29 @@ protected function setUp() /** * @dataProvider moveFileUrlDataProvider + * @param $fileUrl + * @param $expectedHost + * @param $expectedFileName + * @param $checkAllowedExtension + * @throws \Magento\Framework\Exception\LocalizedException */ public function testMoveFileUrl($fileUrl, $expectedHost, $expectedFileName, $checkAllowedExtension) { + $tmpDir = 'var/tmp'; $destDir = 'var/dest/dir'; - $expectedTmpDir = 'var/tmp'; - $expectedRelativeFilePath = $expectedTmpDir . '/' . $expectedFileName; - $this->directoryMock->expects($this->once())->method('isWritable')->with($destDir)->willReturn(true); - $this->directoryMock->expects($this->any())->method('getRelativePath')->with($expectedRelativeFilePath); - $this->directoryMock->expects($this->once())->method('getAbsolutePath')->with($destDir) - ->willReturn($destDir . '/' . $expectedFileName); + // Expected invocation to validate file extension + $this->uploader->expects($this->exactly($checkAllowedExtension))->method('checkAllowedExtension') + ->willReturn(true); + + // Expected invocation to generate random string for file name postfix + $this->random->expects($this->once())->method('getRandomString') + ->with(16) + ->willReturn('38GcEmPFKXXR8NMj'); - // Check writeFile() method invoking. - $this->directoryMock->expects($this->any())->method('writeFile')->will($this->returnValue($expectedFileName)); + // Expected invocation to build the temp file path with the correct directory and filename + $this->directoryMock->expects($this->any())->method('getRelativePath') + ->with($tmpDir . '/' . $expectedFileName); // Create adjusted reader which does not validate path. $readMock = $this->getMockBuilder(\Magento\Framework\Filesystem\File\Read::class) @@ -120,24 +141,36 @@ public function testMoveFileUrl($fileUrl, $expectedHost, $expectedFileName, $che ->setMethods(['readAll']) ->getMock(); - // Check readAll() method invoking. - $readMock->expects($this->once())->method('readAll')->will($this->returnValue(null)); - - // Check create() method invoking with expected argument. + // Expected invocations to create reader and read contents from url $this->readFactory->expects($this->once())->method('create') - ->will($this->returnValue($readMock))->with($expectedHost); - - //Check invoking of getTmpDir(), _setUploadFile(), save() methods. - $this->uploader->expects($this->any())->method('getTmpDir')->will($this->returnValue('')); - $this->uploader->expects($this->once())->method('_setUploadFile')->will($this->returnSelf()); + ->with($expectedHost) + ->will($this->returnValue($readMock)); + $readMock->expects($this->once())->method('readAll') + ->will($this->returnValue(null)); + + // Expected invocation to write the temp file + $this->directoryMock->expects($this->any())->method('writeFile') + ->will($this->returnValue($expectedFileName)); + + // Expected invocations to move the temp file to the destination directory + $this->directoryMock->expects($this->once())->method('isWritable') + ->with($destDir) + ->willReturn(true); + $this->directoryMock->expects($this->once())->method('getAbsolutePath') + ->with($destDir) + ->willReturn($destDir . '/' . $expectedFileName); + $this->uploader->expects($this->once())->method('_setUploadFile') + ->willReturnSelf(); $this->uploader->expects($this->once())->method('save') ->with($destDir . '/' . $expectedFileName) ->willReturn(['name' => $expectedFileName, 'path' => 'absPath']); - $this->uploader->expects($this->exactly($checkAllowedExtension))->method('checkAllowedExtension') - ->willReturn(true); + + // Do not use configured temp directory + $this->uploader->expects($this->never())->method('getTmpDir'); $this->uploader->setDestDir($destDir); $result = $this->uploader->move($fileUrl); + $this->assertEquals(['name' => $expectedFileName], $result); $this->assertArrayNotHasKey('path', $result); } @@ -227,42 +260,66 @@ public function moveFileUrlDriverPoolDataProvider() public function moveFileUrlDataProvider() { return [ - [ - '$fileUrl' => 'http://test_uploader_file', + 'https_no_file_ext' => [ + '$fileUrl' => 'https://test_uploader_file', '$expectedHost' => 'test_uploader_file', - '$expectedFileName' => 'test_uploader_file', + '$expectedFileName' => 'test_uploader_file_38GcEmPFKXXR8NMj', '$checkAllowedExtension' => 0 ], - [ - '$fileUrl' => 'https://!:^&`;file', - '$expectedHost' => '!:^&`;file', - '$expectedFileName' => 'file', + 'https_invalid_chars' => [ + '$fileUrl' => 'https://www.google.com/!:^&`;image.jpg', + '$expectedHost' => 'www.google.com/!:^&`;image.jpg', + '$expectedFileName' => 'image_38GcEmPFKXXR8NMj.jpg', + '$checkAllowedExtension' => 1 + ], + 'https_invalid_chars_no_file_ext' => [ + '$fileUrl' => 'https://!:^&`;image', + '$expectedHost' => '!:^&`;image', + '$expectedFileName' => 'image_38GcEmPFKXXR8NMj', '$checkAllowedExtension' => 0 ], - [ + 'http_jpg' => [ + '$fileUrl' => 'http://www.google.com/image.jpg', + '$expectedHost' => 'www.google.com/image.jpg', + '$expectedFileName' => 'image_38GcEmPFKXXR8NMj.jpg', + '$checkAllowedExtension' => 1 + ], + 'https_jpg' => [ '$fileUrl' => 'https://www.google.com/image.jpg', '$expectedHost' => 'www.google.com/image.jpg', - '$expectedFileName' => 'image.jpg', + '$expectedFileName' => 'image_38GcEmPFKXXR8NMj.jpg', '$checkAllowedExtension' => 1 ], - [ + 'https_jpeg' => [ + '$fileUrl' => 'https://www.google.com/image.jpeg', + '$expectedHost' => 'www.google.com/image.jpeg', + '$expectedFileName' => 'image_38GcEmPFKXXR8NMj.jpeg', + '$checkAllowedExtension' => 1 + ], + 'https_png' => [ + '$fileUrl' => 'https://www.google.com/image.png', + '$expectedHost' => 'www.google.com/image.png', + '$expectedFileName' => 'image_38GcEmPFKXXR8NMj.png', + '$checkAllowedExtension' => 1 + ], + 'https_gif' => [ + '$fileUrl' => 'https://www.google.com/image.gif', + '$expectedHost' => 'www.google.com/image.gif', + '$expectedFileName' => 'image_38GcEmPFKXXR8NMj.gif', + '$checkAllowedExtension' => 1 + ], + 'https_one_query_param' => [ '$fileUrl' => 'https://www.google.com/image.jpg?param=1', '$expectedHost' => 'www.google.com/image.jpg?param=1', - '$expectedFileName' => 'image.jpg', + '$expectedFileName' => 'image_38GcEmPFKXXR8NMj.jpg', '$checkAllowedExtension' => 1 ], - [ + 'https_two_query_params' => [ '$fileUrl' => 'https://www.google.com/image.jpg?param=1¶m=2', '$expectedHost' => 'www.google.com/image.jpg?param=1¶m=2', - '$expectedFileName' => 'image.jpg', + '$expectedFileName' => 'image_38GcEmPFKXXR8NMj.jpg', '$checkAllowedExtension' => 1 - ], - [ - '$fileUrl' => 'http://www.google.com/image.jpg?param=1¶m=2', - '$expectedHost' => 'www.google.com/image.jpg?param=1¶m=2', - '$expectedFileName' => 'image.jpg', - '$checkAllowedExtension' => 1 - ], + ] ]; } } From 1ea5a9409849d5a153fdfa82d3c77d3f631b97dd Mon Sep 17 00:00:00 2001 From: Oleksandr Miroshnichenko <omiroshnichenko@magento.com> Date: Thu, 28 Mar 2019 15:49:20 -0500 Subject: [PATCH 155/773] MC-5895: Create a separate data provider --- .../Magento/Ui/Controller/Index/Render.php | 123 +++++- .../Test/Unit/Controller/Index/RenderTest.php | 401 ++++++++++++++++++ 2 files changed, 512 insertions(+), 12 deletions(-) create mode 100644 app/code/Magento/Ui/Test/Unit/Controller/Index/RenderTest.php diff --git a/app/code/Magento/Ui/Controller/Index/Render.php b/app/code/Magento/Ui/Controller/Index/Render.php index 910885b67c948..6aa8f4887d878 100644 --- a/app/code/Magento/Ui/Controller/Index/Render.php +++ b/app/code/Magento/Ui/Controller/Index/Render.php @@ -7,10 +7,13 @@ use Magento\Backend\App\Action\Context; use Magento\Framework\App\ObjectManager; -use Magento\Framework\App\Response\Http as HttpResponse; use Magento\Framework\View\Element\UiComponentFactory; use Magento\Framework\View\Element\UiComponentInterface; use Magento\Ui\Model\UiComponentTypeResolver; +use Magento\Framework\Escaper; +use Magento\Framework\Controller\Result\JsonFactory; +use Psr\Log\LoggerInterface; +use Magento\Framework\AuthorizationInterface; /** * Is responsible for providing ui components information on store front. @@ -34,42 +37,117 @@ class Render extends \Magento\Framework\App\Action\Action */ private $contentTypeResolver; + /** + * @var JsonFactory + */ + private $resultJsonFactory; + + /** + * @var Escaper + */ + private $escaper; + + /** + * @var LoggerInterface + */ + private $logger; + + /** + * @var AuthorizationInterface + */ + private $authorization; + /** * Render constructor. * @param Context $context * @param UiComponentFactory $uiComponentFactory * @param UiComponentTypeResolver|null $contentTypeResolver + * @param JsonFactory|null $resultJsonFactory + * @param Escaper|null $escaper + * @param LoggerInterface|null $logger */ public function __construct( Context $context, UiComponentFactory $uiComponentFactory, - ?UiComponentTypeResolver $contentTypeResolver = null + ?UiComponentTypeResolver $contentTypeResolver = null, + JsonFactory $resultJsonFactory = null, + Escaper $escaper = null, + LoggerInterface $logger = null ) { parent::__construct($context); $this->context = $context; $this->uiComponentFactory = $uiComponentFactory; + $this->authorization = $context->getAuthorization(); $this->contentTypeResolver = $contentTypeResolver ?? ObjectManager::getInstance()->get(UiComponentTypeResolver::class); + $this->resultJsonFactory = $resultJsonFactory ?? ObjectManager::getInstance()->get(JsonFactory::class); + $this->escaper = $escaper ?? ObjectManager::getInstance()->get(Escaper::class); + $this->logger = $logger ?? ObjectManager::getInstance()->get(LoggerInterface::class); } /** - * Action for AJAX request - * - * @return void + * @inheritdoc */ public function execute() { if ($this->_request->getParam('namespace') === null) { - $this->_redirect('noroute'); + $this->_redirect('admin/noroute'); + return; } - $component = $this->uiComponentFactory->create($this->_request->getParam('namespace')); - $this->prepareComponent($component); - /** @var HttpResponse $response */ - $response = $this->getResponse(); - $response->appendBody((string) $component->render()); - $response->setHeader('Content-Type', $this->contentTypeResolver->resolve($component->getContext()), true); + try { + $component = $this->uiComponentFactory->create($this->getRequest()->getParam('namespace')); + if ($this->validateAclResource($component->getContext()->getDataProvider()->getConfigData())) { + $this->prepareComponent($component); + $this->getResponse()->appendBody((string)$component->render()); + + $contentType = $this->contentTypeResolver->resolve($component->getContext()); + $this->getResponse()->setHeader('Content-Type', $contentType, true); + } else { + /** @var \Magento\Framework\Controller\Result\Json $resultJson */ + $resultJson = $this->resultJsonFactory->create(); + $resultJson->setStatusHeader( + \Zend\Http\Response::STATUS_CODE_403, + \Zend\Http\AbstractMessage::VERSION_11, + 'Forbidden' + ); + return $resultJson->setData([ + 'error' => $this->escaper->escapeHtml('Forbidden'), + 'errorcode' => 403 + ]); + } + } catch (\Magento\Framework\Exception\LocalizedException $e) { + $this->logger->critical($e); + $result = [ + 'error' => $this->escaper->escapeHtml($e->getMessage()), + 'errorcode' => $this->escaper->escapeHtml($e->getCode()) + ]; + /** @var \Magento\Framework\Controller\Result\Json $resultJson */ + $resultJson = $this->resultJsonFactory->create(); + $resultJson->setStatusHeader( + \Zend\Http\Response::STATUS_CODE_400, + \Zend\Http\AbstractMessage::VERSION_11, + 'Bad Request' + ); + + return $resultJson->setData($result); + } catch (\Exception $e) { + $this->logger->critical($e); + $result = [ + 'error' => __('UI component could not be rendered because of system exception'), + 'errorcode' => $this->escaper->escapeHtml($e->getCode()) + ]; + /** @var \Magento\Framework\Controller\Result\Json $resultJson */ + $resultJson = $this->resultJsonFactory->create(); + $resultJson->setStatusHeader( + \Zend\Http\Response::STATUS_CODE_400, + \Zend\Http\AbstractMessage::VERSION_11, + 'Bad Request' + ); + + return $resultJson->setData($result); + } } /** @@ -85,4 +163,25 @@ private function prepareComponent(UiComponentInterface $component) } $component->prepare(); } + + /** + * Optionally validate ACL resource of components with a DataSource/DataProvider + * + * @param mixed $dataProviderConfigData + * @return bool + */ + private function validateAclResource($dataProviderConfigData) + { + if (isset($dataProviderConfigData['aclResource'])) { + if (!$this->authorization->isAllowed($dataProviderConfigData['aclResource'])) { + if (!$this->_request->isAjax()) { + $this->_redirect('noroute'); + } + + return false; + } + } + + return true; + } } diff --git a/app/code/Magento/Ui/Test/Unit/Controller/Index/RenderTest.php b/app/code/Magento/Ui/Test/Unit/Controller/Index/RenderTest.php new file mode 100644 index 0000000000000..5d6bdffa12c7a --- /dev/null +++ b/app/code/Magento/Ui/Test/Unit/Controller/Index/RenderTest.php @@ -0,0 +1,401 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Ui\Test\Unit\Controller\Index; + +use Magento\Framework\Controller\Result\Json; +use Magento\Framework\Escaper; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +use Magento\Framework\View\Element\UiComponent\ContextInterface; +use Magento\Ui\Controller\Index\Render; +use Magento\Ui\Model\UiComponentTypeResolver; +use Zend\Http\AbstractMessage; +use Zend\Http\Response; + +/** + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * @SuppressWarnings(PHPMD.TooManyFields) + */ +class RenderTest extends \PHPUnit\Framework\TestCase +{ + /** + * @var Render + */ + private $render; + + /** + * @var ObjectManagerHelper + */ + private $objectManagerHelper; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + private $requestMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + private $responseMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + private $uiFactoryMock; + + /** + * @var \Magento\Backend\App\Action\Context|\PHPUnit_Framework_MockObject_MockObject + */ + private $contextMock; + + /** + * @var \Magento\Framework\AuthorizationInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $authorizationMock; + + /** + * @var \Magento\Backend\Model\Session|\PHPUnit_Framework_MockObject_MockObject + */ + private $sessionMock; + + /** + * @var \Magento\Framework\App\ActionFlag|\PHPUnit_Framework_MockObject_MockObject + */ + private $actionFlagMock; + + /** + * @var \Magento\Backend\Helper\Data|\PHPUnit_Framework_MockObject_MockObject + */ + private $helperMock; + + /** + * @var ContextInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $uiComponentContextMock; + + /** + * @var \Magento\Framework\View\Element\UiComponent\DataProvider\DataProviderInterface| + * \PHPUnit_Framework_MockObject_MockObject + */ + private $dataProviderMock; + + /** + * @var \Magento\Framework\View\Element\UiComponentInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $uiComponentMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject|UiComponentTypeResolver + */ + private $uiComponentTypeResolverMock; + + /** + * @var \Magento\Framework\Controller\Result\JsonFactory|\PHPUnit_Framework_MockObject_MockObject + */ + private $resultJsonFactoryMock; + + /** + * @var \Psr\Log\LoggerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $loggerMock; + + /** + * @var Escaper|\PHPUnit_Framework_MockObject_MockObject + */ + private $escaperMock; + + protected function setUp() + { + $this->requestMock = $this->getMockBuilder(\Magento\Framework\App\Request\Http::class) + ->disableOriginalConstructor() + ->getMock(); + $this->responseMock = $this->getMockBuilder(\Magento\Framework\App\Response\Http::class) + ->disableOriginalConstructor() + ->getMock(); + $this->contextMock = $this->getMockBuilder(\Magento\Backend\App\Action\Context::class) + ->disableOriginalConstructor() + ->getMock(); + $this->uiFactoryMock = $this->getMockBuilder(\Magento\Framework\View\Element\UiComponentFactory::class) + ->disableOriginalConstructor() + ->getMock(); + $this->authorizationMock = $this->getMockBuilder(\Magento\Framework\AuthorizationInterface::class) + ->getMockForAbstractClass(); + $this->sessionMock = $this->getMockBuilder(\Magento\Backend\Model\Session::class) + ->disableOriginalConstructor() + ->getMock(); + $this->actionFlagMock = $this->getMockBuilder(\Magento\Framework\App\ActionFlag::class) + ->disableOriginalConstructor() + ->getMock(); + $this->helperMock = $this->getMockBuilder(\Magento\Backend\Helper\Data::class) + ->disableOriginalConstructor() + ->getMock(); + $this->uiComponentContextMock = $this->getMockForAbstractClass( + ContextInterface::class + ); + $this->dataProviderMock = $this->getMockForAbstractClass( + \Magento\Framework\View\Element\UiComponent\DataProvider\DataProviderInterface::class + ); + $this->uiComponentMock = $this->getMockForAbstractClass( + \Magento\Framework\View\Element\UiComponentInterface::class, + [], + '', + false, + true, + true, + ['render'] + ); + + $this->resultJsonFactoryMock = $this->getMockBuilder( + \Magento\Framework\Controller\Result\JsonFactory::class + ) + ->disableOriginalConstructor() + ->getMock(); + + $this->loggerMock = $this->getMockForAbstractClass(\Psr\Log\LoggerInterface::class); + + $this->contextMock->expects($this->any()) + ->method('getRequest') + ->willReturn($this->requestMock); + $this->contextMock->expects($this->any()) + ->method('getResponse') + ->willReturn($this->responseMock); + $this->contextMock->expects($this->any()) + ->method('getAuthorization') + ->willReturn($this->authorizationMock); + $this->contextMock->expects($this->any()) + ->method('getSession') + ->willReturn($this->sessionMock); + $this->contextMock->expects($this->any()) + ->method('getActionFlag') + ->willReturn($this->actionFlagMock); + $this->contextMock->expects($this->any()) + ->method('getHelper') + ->willReturn($this->helperMock); + $this->uiComponentContextMock->expects($this->once()) + ->method('getDataProvider') + ->willReturn($this->dataProviderMock); + $this->uiComponentTypeResolverMock = $this->getMockBuilder(UiComponentTypeResolver::class) + ->disableOriginalConstructor() + ->getMock(); + $this->escaperMock = $this->createMock(Escaper::class); + $this->escaperMock->expects($this->any()) + ->method('escapeHtml') + ->willReturnArgument(0); + + $this->objectManagerHelper = new ObjectManagerHelper($this); + + $this->render = $this->objectManagerHelper->getObject( + \Magento\Ui\Controller\Index\Render::class, + [ + 'context' => $this->contextMock, + 'uiComponentFactory' => $this->uiFactoryMock, + 'contentTypeResolver' => $this->uiComponentTypeResolverMock, + 'resultJsonFactory' => $this->resultJsonFactoryMock, + 'logger' => $this->loggerMock, + 'escaper' => $this->escaperMock, + ] + ); + } + + public function testExecuteException() + { + $name = 'test-name'; + $renderedData = '<html>data</html>'; + + $this->requestMock->expects($this->any()) + ->method('getParam') + ->with('namespace') + ->willReturn($name); + $this->requestMock->expects($this->any()) + ->method('getParams') + ->willReturn([]); + $this->responseMock->expects($this->once()) + ->method('appendBody') + ->willThrowException(new \Exception('exception')); + + $jsonResultMock = $this->getMockBuilder(Json::class) + ->disableOriginalConstructor() + ->setMethods(['setData']) + ->getMock(); + + $this->resultJsonFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($jsonResultMock); + + $jsonResultMock->expects($this->once()) + ->method('setData') + ->willReturnSelf(); + + $this->loggerMock->expects($this->once()) + ->method('critical') + ->willReturnSelf(); + + $this->dataProviderMock->expects($this->once()) + ->method('getConfigData') + ->willReturn([]); + + $this->uiComponentMock->expects($this->once()) + ->method('render') + ->willReturn($renderedData); + $this->uiComponentMock->expects($this->once()) + ->method('getChildComponents') + ->willReturn([]); + $this->uiComponentMock->expects($this->once()) + ->method('getContext') + ->willReturn($this->uiComponentContextMock); + $this->uiFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($this->uiComponentMock); + + $this->render->execute(); + } + + public function testExecute() + { + $name = 'test-name'; + $renderedData = '<html>data</html>'; + + $this->requestMock->expects($this->any()) + ->method('getParam') + ->with('namespace') + ->willReturn($name); + $this->requestMock->expects($this->any()) + ->method('getParams') + ->willReturn([]); + $this->responseMock->expects($this->once()) + ->method('appendBody') + ->with($renderedData); + $this->dataProviderMock->expects($this->once()) + ->method('getConfigData') + ->willReturn([]); + + $this->uiComponentMock->expects($this->once()) + ->method('render') + ->willReturn($renderedData); + $this->uiComponentMock->expects($this->once()) + ->method('getChildComponents') + ->willReturn([]); + $this->uiComponentMock->expects($this->any()) + ->method('getContext') + ->willReturn($this->uiComponentContextMock); + $this->uiFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($this->uiComponentMock); + $this->uiComponentTypeResolverMock->expects($this->once()) + ->method('resolve') + ->with($this->uiComponentContextMock) + ->willReturn('application/json'); + $this->responseMock->expects($this->once())->method('setHeader') + ->with('Content-Type', 'application/json', true); + + $this->render->execute(); + } + + /** + * @param array $dataProviderConfig + * @param bool|null $isAllowed + * @param int $authCallCount + * @dataProvider executeAjaxRequestWithoutPermissionsDataProvider + */ + public function testExecuteWithoutPermissions(array $dataProviderConfig, $isAllowed, $authCallCount = 1) + { + $name = 'test-name'; + $renderedData = '<html>data</html>'; + + if (false === $isAllowed) { + $jsonResultMock = $this->getMockBuilder(Json::class) + ->disableOriginalConstructor() + ->setMethods(['setStatusHeader', 'setData']) + ->getMock(); + + $jsonResultMock->expects($this->at(0)) + ->method('setStatusHeader') + ->with( + Response::STATUS_CODE_403, + AbstractMessage::VERSION_11, + 'Forbidden' + ) + ->willReturnSelf(); + + $jsonResultMock->expects($this->at(1)) + ->method('setData') + ->with([ + 'error' => 'Forbidden', + 'errorcode' => 403 + ]) + ->willReturnSelf(); + + $this->resultJsonFactoryMock->expects($this->any()) + ->method('create') + ->willReturn($jsonResultMock); + } + + $this->requestMock->expects($this->any()) + ->method('getParam') + ->with('namespace') + ->willReturn($name); + $this->requestMock->expects($this->any()) + ->method('getParams') + ->willReturn([]); + if ($isAllowed === false) { + $this->requestMock->expects($this->once()) + ->method('isAjax') + ->willReturn(true); + } + $this->responseMock->expects($this->never()) + ->method('setRedirect'); + $this->responseMock->expects($this->any()) + ->method('appendBody') + ->with($renderedData); + + $this->dataProviderMock->expects($this->once()) + ->method('getConfigData') + ->willReturn($dataProviderConfig); + + $this->authorizationMock->expects($this->exactly($authCallCount)) + ->method('isAllowed') + ->with(isset($dataProviderConfig['aclResource']) ? $dataProviderConfig['aclResource'] : null) + ->willReturn($isAllowed); + + $this->uiComponentMock->expects($this->any()) + ->method('render') + ->willReturn($renderedData); + $this->uiComponentMock->expects($this->any()) + ->method('getChildComponents') + ->willReturn([]); + $this->uiComponentMock->expects($this->any()) + ->method('getContext') + ->willReturn($this->uiComponentContextMock); + $this->uiFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($this->uiComponentMock); + + $this->render->execute(); + } + + /** + * @return array + */ + public function executeAjaxRequestWithoutPermissionsDataProvider() + { + $aclResource = 'Magento_Test::index_index'; + return [ + [ + 'dataProviderConfig' => ['aclResource' => $aclResource], + 'isAllowed' => true + ], + [ + 'dataProviderConfig' => ['aclResource' => $aclResource], + 'isAllowed' => false + ], + [ + 'dataProviderConfig' => [], + 'isAllowed' => null, + 'authCallCount' => 0 + ], + ]; + } +} From f1fa47c874d99c84a01814226a795d11fa7ae482 Mon Sep 17 00:00:00 2001 From: David Haecker <dhaecker@magento.com> Date: Thu, 28 Mar 2019 15:52:12 -0500 Subject: [PATCH 156/773] MC-5858: HTTPS redirecting problem on storefront - Updating MFTF tests - Moving MFTF suite --- .../Test/StorefrontVerifySecureURLRedirectAuthorizenetTest.xml | 1 - .../Mftf/Test/StorefrontVerifySecureURLRedirectCheckoutTest.xml | 1 - .../Mftf/Test/StorefrontVerifySecureURLRedirectContactTest.xml | 1 - .../Mftf/Test/StorefrontVerifySecureURLRedirectCustomerTest.xml | 1 - .../Test/StorefrontVerifySecureURLRedirectDownloadableTest.xml | 1 - .../Test/StorefrontVerifySecureURLRedirectMultishippingTest.xml | 1 - .../Test/StorefrontVerifySecureURLRedirectNewsletterTest.xml | 1 - .../Mftf/Test/StorefrontVerifySecureURLRedirectPaypalTest.xml | 1 - .../Test/StorefrontVerifySecureURLRedirectPersistentTest.xml | 1 - .../Mftf/Test/StorefrontVerifySecureURLRedirectReviewTest.xml | 1 - .../Mftf/Test/StorefrontVerifySecureURLRedirectSalesTest.xml | 1 - .../Test/Mftf/Suite/SecureStorefrontURLSuite.xml | 0 .../Mftf/Test/StorefrontVerifySecureURLRedirectVaultTest.xml | 1 - .../Mftf/Test/StorefrontVerifySecureURLRedirectWishlistTest.xml | 1 - 14 files changed, 13 deletions(-) rename app/code/Magento/{Checkout => Store}/Test/Mftf/Suite/SecureStorefrontURLSuite.xml (100%) diff --git a/app/code/Magento/Authorizenet/Test/Mftf/Test/StorefrontVerifySecureURLRedirectAuthorizenetTest.xml b/app/code/Magento/Authorizenet/Test/Mftf/Test/StorefrontVerifySecureURLRedirectAuthorizenetTest.xml index 532b99aa78503..afd7815518e98 100644 --- a/app/code/Magento/Authorizenet/Test/Mftf/Test/StorefrontVerifySecureURLRedirectAuthorizenetTest.xml +++ b/app/code/Magento/Authorizenet/Test/Mftf/Test/StorefrontVerifySecureURLRedirectAuthorizenetTest.xml @@ -32,7 +32,6 @@ </before> <after> <magentoCLI command="config:set web/secure/use_in_frontend 0" stepKey="dontUseSecureURLsOnStorefront"/> - <magentoCLI command="config:set web/secure/base_url {{_ENV.MAGENTO_BASE_URL}}" stepKey="setSecureBaseURL"/> <magentoCLI command="cache:flush" stepKey="flushCache"/> <deleteData createDataKey="customer" stepKey="deleteCustomer"/> </after> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontVerifySecureURLRedirectCheckoutTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontVerifySecureURLRedirectCheckoutTest.xml index 89685ad3abd6e..a6300a45ad7bb 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontVerifySecureURLRedirectCheckoutTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontVerifySecureURLRedirectCheckoutTest.xml @@ -29,7 +29,6 @@ </before> <after> <magentoCLI command="config:set web/secure/use_in_frontend 0" stepKey="dontUseSecureURLsOnStorefront"/> - <magentoCLI command="config:set web/secure/base_url {{_ENV.MAGENTO_BASE_URL}}" stepKey="setSecureBaseURL"/> <magentoCLI command="cache:flush" stepKey="flushCache"/> </after> <executeJS function="return window.location.host" stepKey="hostname"/> diff --git a/app/code/Magento/Contact/Test/Mftf/Test/StorefrontVerifySecureURLRedirectContactTest.xml b/app/code/Magento/Contact/Test/Mftf/Test/StorefrontVerifySecureURLRedirectContactTest.xml index 70bb6fa7b9fa7..a41ecf861c43c 100644 --- a/app/code/Magento/Contact/Test/Mftf/Test/StorefrontVerifySecureURLRedirectContactTest.xml +++ b/app/code/Magento/Contact/Test/Mftf/Test/StorefrontVerifySecureURLRedirectContactTest.xml @@ -29,7 +29,6 @@ </before> <after> <magentoCLI command="config:set web/secure/use_in_frontend 0" stepKey="dontUseSecureURLsOnStorefront"/> - <magentoCLI command="config:set web/secure/base_url {{_ENV.MAGENTO_BASE_URL}}" stepKey="setSecureBaseURL"/> <magentoCLI command="cache:flush" stepKey="flushCache"/> </after> <executeJS function="return window.location.host" stepKey="hostname"/> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontVerifySecureURLRedirectCustomerTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontVerifySecureURLRedirectCustomerTest.xml index 0159879b81d46..da9dddf0539d3 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontVerifySecureURLRedirectCustomerTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontVerifySecureURLRedirectCustomerTest.xml @@ -29,7 +29,6 @@ </before> <after> <magentoCLI command="config:set web/secure/use_in_frontend 0" stepKey="dontUseSecureURLsOnStorefront"/> - <magentoCLI command="config:set web/secure/base_url {{_ENV.MAGENTO_BASE_URL}}" stepKey="setSecureBaseURL"/> <magentoCLI command="cache:flush" stepKey="flushCache"/> </after> <executeJS function="return window.location.host" stepKey="hostname"/> diff --git a/app/code/Magento/Downloadable/Test/Mftf/Test/StorefrontVerifySecureURLRedirectDownloadableTest.xml b/app/code/Magento/Downloadable/Test/Mftf/Test/StorefrontVerifySecureURLRedirectDownloadableTest.xml index 3e561d4a4ed5d..b4a8121edb5ca 100644 --- a/app/code/Magento/Downloadable/Test/Mftf/Test/StorefrontVerifySecureURLRedirectDownloadableTest.xml +++ b/app/code/Magento/Downloadable/Test/Mftf/Test/StorefrontVerifySecureURLRedirectDownloadableTest.xml @@ -35,7 +35,6 @@ </before> <after> <magentoCLI command="config:set web/secure/use_in_frontend 0" stepKey="dontUseSecureURLsOnStorefront"/> - <magentoCLI command="config:set web/secure/base_url {{_ENV.MAGENTO_BASE_URL}}" stepKey="setSecureBaseURL"/> <magentoCLI command="cache:flush" stepKey="flushCache"/> <deleteData createDataKey="company" stepKey="deleteCompany"/> <deleteData createDataKey="customer" stepKey="deleteCompanyAdmin"/> diff --git a/app/code/Magento/Multishipping/Test/Mftf/Test/StorefrontVerifySecureURLRedirectMultishippingTest.xml b/app/code/Magento/Multishipping/Test/Mftf/Test/StorefrontVerifySecureURLRedirectMultishippingTest.xml index 5198a02a867e7..a1dd37cd97717 100644 --- a/app/code/Magento/Multishipping/Test/Mftf/Test/StorefrontVerifySecureURLRedirectMultishippingTest.xml +++ b/app/code/Magento/Multishipping/Test/Mftf/Test/StorefrontVerifySecureURLRedirectMultishippingTest.xml @@ -32,7 +32,6 @@ </before> <after> <magentoCLI command="config:set web/secure/use_in_frontend 0" stepKey="dontUseSecureURLsOnStorefront"/> - <magentoCLI command="config:set web/secure/base_url {{_ENV.MAGENTO_BASE_URL}}" stepKey="setSecureBaseURL"/> <magentoCLI command="cache:flush" stepKey="flushCache"/> <deleteData createDataKey="customer" stepKey="deleteCustomer"/> </after> diff --git a/app/code/Magento/Newsletter/Test/Mftf/Test/StorefrontVerifySecureURLRedirectNewsletterTest.xml b/app/code/Magento/Newsletter/Test/Mftf/Test/StorefrontVerifySecureURLRedirectNewsletterTest.xml index c3a475ab3d56f..7237e1801b2b7 100644 --- a/app/code/Magento/Newsletter/Test/Mftf/Test/StorefrontVerifySecureURLRedirectNewsletterTest.xml +++ b/app/code/Magento/Newsletter/Test/Mftf/Test/StorefrontVerifySecureURLRedirectNewsletterTest.xml @@ -32,7 +32,6 @@ </before> <after> <magentoCLI command="config:set web/secure/use_in_frontend 0" stepKey="dontUseSecureURLsOnStorefront"/> - <magentoCLI command="config:set web/secure/base_url {{_ENV.MAGENTO_BASE_URL}}" stepKey="setSecureBaseURL"/> <magentoCLI command="cache:flush" stepKey="flushCache"/> <deleteData createDataKey="customer" stepKey="deleteCustomer"/> </after> diff --git a/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontVerifySecureURLRedirectPaypalTest.xml b/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontVerifySecureURLRedirectPaypalTest.xml index 8de3ad034d632..bd078096b3d65 100644 --- a/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontVerifySecureURLRedirectPaypalTest.xml +++ b/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontVerifySecureURLRedirectPaypalTest.xml @@ -32,7 +32,6 @@ </before> <after> <magentoCLI command="config:set web/secure/use_in_frontend 0" stepKey="dontUseSecureURLsOnStorefront"/> - <magentoCLI command="config:set web/secure/base_url {{_ENV.MAGENTO_BASE_URL}}" stepKey="setSecureBaseURL"/> <magentoCLI command="cache:flush" stepKey="flushCache"/> <deleteData createDataKey="customer" stepKey="deleteCustomer"/> </after> diff --git a/app/code/Magento/Persistent/Test/Mftf/Test/StorefrontVerifySecureURLRedirectPersistentTest.xml b/app/code/Magento/Persistent/Test/Mftf/Test/StorefrontVerifySecureURLRedirectPersistentTest.xml index fcfe7209df0be..3a39f12edf909 100644 --- a/app/code/Magento/Persistent/Test/Mftf/Test/StorefrontVerifySecureURLRedirectPersistentTest.xml +++ b/app/code/Magento/Persistent/Test/Mftf/Test/StorefrontVerifySecureURLRedirectPersistentTest.xml @@ -35,7 +35,6 @@ </before> <after> <magentoCLI command="config:set web/secure/use_in_frontend 0" stepKey="dontUseSecureURLsOnStorefront"/> - <magentoCLI command="config:set web/secure/base_url {{_ENV.MAGENTO_BASE_URL}}" stepKey="setSecureBaseURL"/> <magentoCLI command="cache:flush" stepKey="flushCache"/> <deleteData createDataKey="company" stepKey="deleteCompany"/> <deleteData createDataKey="customer" stepKey="deleteCompanyAdmin"/> diff --git a/app/code/Magento/Review/Test/Mftf/Test/StorefrontVerifySecureURLRedirectReviewTest.xml b/app/code/Magento/Review/Test/Mftf/Test/StorefrontVerifySecureURLRedirectReviewTest.xml index 83a547149091a..f2d3826f3bb04 100644 --- a/app/code/Magento/Review/Test/Mftf/Test/StorefrontVerifySecureURLRedirectReviewTest.xml +++ b/app/code/Magento/Review/Test/Mftf/Test/StorefrontVerifySecureURLRedirectReviewTest.xml @@ -32,7 +32,6 @@ </before> <after> <magentoCLI command="config:set web/secure/use_in_frontend 0" stepKey="dontUseSecureURLsOnStorefront"/> - <magentoCLI command="config:set web/secure/base_url {{_ENV.MAGENTO_BASE_URL}}" stepKey="setSecureBaseURL"/> <magentoCLI command="cache:flush" stepKey="flushCache"/> <deleteData createDataKey="customer" stepKey="deleteCustomer"/> </after> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/StorefrontVerifySecureURLRedirectSalesTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/StorefrontVerifySecureURLRedirectSalesTest.xml index 80e083a6886c7..67b65a586e58b 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/StorefrontVerifySecureURLRedirectSalesTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/StorefrontVerifySecureURLRedirectSalesTest.xml @@ -32,7 +32,6 @@ </before> <after> <magentoCLI command="config:set web/secure/use_in_frontend 0" stepKey="dontUseSecureURLsOnStorefront"/> - <magentoCLI command="config:set web/secure/base_url {{_ENV.MAGENTO_BASE_URL}}" stepKey="setSecureBaseURL"/> <magentoCLI command="cache:flush" stepKey="flushCache"/> <deleteData createDataKey="customer" stepKey="deleteCustomer"/> </after> diff --git a/app/code/Magento/Checkout/Test/Mftf/Suite/SecureStorefrontURLSuite.xml b/app/code/Magento/Store/Test/Mftf/Suite/SecureStorefrontURLSuite.xml similarity index 100% rename from app/code/Magento/Checkout/Test/Mftf/Suite/SecureStorefrontURLSuite.xml rename to app/code/Magento/Store/Test/Mftf/Suite/SecureStorefrontURLSuite.xml diff --git a/app/code/Magento/Vault/Test/Mftf/Test/StorefrontVerifySecureURLRedirectVaultTest.xml b/app/code/Magento/Vault/Test/Mftf/Test/StorefrontVerifySecureURLRedirectVaultTest.xml index 188747a121331..d0ace6aacc89c 100644 --- a/app/code/Magento/Vault/Test/Mftf/Test/StorefrontVerifySecureURLRedirectVaultTest.xml +++ b/app/code/Magento/Vault/Test/Mftf/Test/StorefrontVerifySecureURLRedirectVaultTest.xml @@ -32,7 +32,6 @@ </before> <after> <magentoCLI command="config:set web/secure/use_in_frontend 0" stepKey="dontUseSecureURLsOnStorefront"/> - <magentoCLI command="config:set web/secure/base_url {{_ENV.MAGENTO_BASE_URL}}" stepKey="setSecureBaseURL"/> <magentoCLI command="cache:flush" stepKey="flushCache"/> <deleteData createDataKey="customer" stepKey="deleteCustomer"/> </after> diff --git a/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontVerifySecureURLRedirectWishlistTest.xml b/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontVerifySecureURLRedirectWishlistTest.xml index 5f28681031d2a..427a4b8ed007f 100644 --- a/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontVerifySecureURLRedirectWishlistTest.xml +++ b/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontVerifySecureURLRedirectWishlistTest.xml @@ -32,7 +32,6 @@ </before> <after> <magentoCLI command="config:set web/secure/use_in_frontend 0" stepKey="dontUseSecureURLsOnStorefront"/> - <magentoCLI command="config:set web/secure/base_url {{_ENV.MAGENTO_BASE_URL}}" stepKey="setSecureBaseURL"/> <magentoCLI command="cache:flush" stepKey="flushCache"/> <deleteData createDataKey="customer" stepKey="deleteCustomer"/> </after> From 48bbc91c29d1608bd2821ee1b4ac4129ebeb121f Mon Sep 17 00:00:00 2001 From: Nathan Smith <nathsmit@adobe.com> Date: Thu, 28 Mar 2019 16:33:20 -0500 Subject: [PATCH 157/773] MC-5882: Invalid quote in session --- app/code/Magento/Checkout/Model/Session.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/app/code/Magento/Checkout/Model/Session.php b/app/code/Magento/Checkout/Model/Session.php index 31513d25a9ce1..0756bbda50ae7 100644 --- a/app/code/Magento/Checkout/Model/Session.php +++ b/app/code/Magento/Checkout/Model/Session.php @@ -219,6 +219,15 @@ public function getQuote() $quote = $this->quoteRepository->getActive($this->getQuoteId()); } + $customerId = $this->_customer + ? $this->_customer->getId() + : $this->_customerSession->getCustomerId(); + + if ($quote->getData('customer_id') && $quote->getData('customer_id') !== $customerId) { + $quote = $this->quoteFactory->create(); + throw new \Magento\Framework\Exception\NoSuchEntityException(); + } + /** * If current currency code of quote is not equal current currency code of store, * need recalculate totals of quote. It is possible if customer use currency switcher or From 66c420a47f3824dd6cbd28c99d42ef1fe6e927cd Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun <ogorkun@magento.com> Date: Thu, 28 Mar 2019 16:36:16 -0500 Subject: [PATCH 158/773] MC-10870: Invalid company ID in web API --- .../Controller/Rest/ParamsOverriderTest.php | 28 +++++++++++++++++-- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Webapi/Test/Unit/Controller/Rest/ParamsOverriderTest.php b/app/code/Magento/Webapi/Test/Unit/Controller/Rest/ParamsOverriderTest.php index 239430498a2b4..e93066c651b78 100644 --- a/app/code/Magento/Webapi/Test/Unit/Controller/Rest/ParamsOverriderTest.php +++ b/app/code/Magento/Webapi/Test/Unit/Controller/Rest/ParamsOverriderTest.php @@ -7,6 +7,7 @@ namespace Magento\Webapi\Test\Unit\Controller\Rest; use \Magento\Authorization\Model\UserContextInterface; +use PHPUnit\Framework\MockObject\MockObject; /** * Test Magento\Webapi\Controller\Rest\ParamsOverrider @@ -36,10 +37,31 @@ public function testOverrideParams($requestData, $parameters, $expectedOverridde ['userContext' => $userContextMock] ); + /** @var MockObject $objectConverter */ + $objectConverter = $this->getMockBuilder(SimpleDataObjectConverter::class) + ->disableOriginalConstructor() + ->setMethods(['convertKeysToCamelCase']) + ->getMock(); + $objectConverter->expects($this->any()) + ->method('convertKeysToCamelCase') + ->willReturnCallback( + function (array $array) { + $converted = []; + foreach ($array as $key => $value) { + $converted[mb_strtolower($key)] = $value; + } + + return $converted; + } + ); + /** @var \Magento\Webapi\Controller\Rest\ParamsOverrider $paramsOverrider */ $paramsOverrider = $objectManager->getObject( - \Magento\Webapi\Controller\Rest\ParamsOverrider::class, - ['paramOverriders' => ['%customer_id%' => $paramOverriderCustomerId ]] + 'Magento\Webapi\Controller\Rest\ParamsOverrider', + [ + 'paramOverriders' => ['%customer_id%' => $paramOverriderCustomerId ], + 'dataObjectConverter' => $objectConverter + ] ); $this->assertEquals($expectedOverriddenParams, $paramsOverrider->override($requestData, $parameters)); @@ -54,7 +76,7 @@ public function overrideParamsDataProvider() 'force false, value present' => [ ['Name1' => 'valueIn'], ['Name1' => ['force' => false, 'value' => 'valueOverride']], - ['Name1' => 'valueOverride'], + ['Name1' => 'valueIn'], 1, UserContextInterface::USER_TYPE_INTEGRATION, ], From c8e77bbd11cf040d4f91a4b228516bb66b04e88c Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun <ogorkun@magento.com> Date: Thu, 28 Mar 2019 16:37:35 -0500 Subject: [PATCH 159/773] MC-10870: Invalid company ID in web API --- .../Webapi/Test/Unit/Controller/Rest/ParamsOverriderTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Webapi/Test/Unit/Controller/Rest/ParamsOverriderTest.php b/app/code/Magento/Webapi/Test/Unit/Controller/Rest/ParamsOverriderTest.php index e93066c651b78..c81351a42333d 100644 --- a/app/code/Magento/Webapi/Test/Unit/Controller/Rest/ParamsOverriderTest.php +++ b/app/code/Magento/Webapi/Test/Unit/Controller/Rest/ParamsOverriderTest.php @@ -7,6 +7,7 @@ namespace Magento\Webapi\Test\Unit\Controller\Rest; use \Magento\Authorization\Model\UserContextInterface; +use Magento\Framework\Api\SimpleDataObjectConverter; use PHPUnit\Framework\MockObject\MockObject; /** From 5d4e1b6c5a63f14d29d89a549cad90166af470c8 Mon Sep 17 00:00:00 2001 From: Hwashiang Yu <hwyu@adobe.com> Date: Thu, 28 Mar 2019 16:38:04 -0500 Subject: [PATCH 160/773] MC-13896: User Role Template Update - Added encoding to decoded string to allow it to return to template - Updated test to include correct value --- .../Magento/User/Block/Role/Grid/User.php | 4 ++-- .../User/Block/User/Edit/Tab/Roles.php | 12 ++---------- .../Test/Unit/Block/Role/Grid/UserTest.php | 19 +++++++++---------- .../Unit/Block/User/Edit/Tab/RolesTest.php | 19 +++++++++---------- 4 files changed, 22 insertions(+), 32 deletions(-) diff --git a/app/code/Magento/User/Block/Role/Grid/User.php b/app/code/Magento/User/Block/Role/Grid/User.php index 4c9810d20df9b..4f642d5d04c66 100644 --- a/app/code/Magento/User/Block/Role/Grid/User.php +++ b/app/code/Magento/User/Block/Role/Grid/User.php @@ -201,8 +201,8 @@ public function getUsers($json = false) { $inRoleUser = $this->getRequest()->getParam('in_role_user'); if ($inRoleUser && $json) { - $result = $this->_jsonDecoder->decode($inRoleUser); - return $result ? $result : '{}'; + $result = json_decode($inRoleUser); + return $result ? $this->_jsonEncoder->encode($result) : '{}'; } $roleId = $this->getRequest()->getParam( 'rid' diff --git a/app/code/Magento/User/Block/User/Edit/Tab/Roles.php b/app/code/Magento/User/Block/User/Edit/Tab/Roles.php index c35e889fa5d4e..2707ba00d24ec 100644 --- a/app/code/Magento/User/Block/User/Edit/Tab/Roles.php +++ b/app/code/Magento/User/Block/User/Edit/Tab/Roles.php @@ -30,16 +30,10 @@ class Roles extends \Magento\Backend\Block\Widget\Grid\Extended */ protected $_jsonEncoder; - /** - * @var \Magento\Framework\Json\DecoderInterface - */ - protected $_jsonDecoder; - /** * @param \Magento\Backend\Block\Template\Context $context * @param \Magento\Backend\Helper\Data $backendHelper * @param \Magento\Framework\Json\EncoderInterface $jsonEncoder - * @param \Magento\Framework\Json\DecoderInterface $jsonDecoder * @param \Magento\Authorization\Model\ResourceModel\Role\CollectionFactory $userRolesFactory * @param \Magento\Framework\Registry $coreRegistry * @param array $data @@ -48,13 +42,11 @@ public function __construct( \Magento\Backend\Block\Template\Context $context, \Magento\Backend\Helper\Data $backendHelper, \Magento\Framework\Json\EncoderInterface $jsonEncoder, - \Magento\Framework\Json\DecoderInterface $jsonDecoder, \Magento\Authorization\Model\ResourceModel\Role\CollectionFactory $userRolesFactory, \Magento\Framework\Registry $coreRegistry, array $data = [] ) { $this->_jsonEncoder = $jsonEncoder; - $this->_jsonDecoder = $jsonDecoder; $this->_userRolesFactory = $userRolesFactory; $this->_coreRegistry = $coreRegistry; parent::__construct($context, $backendHelper, $data); @@ -150,8 +142,8 @@ public function getSelectedRoles($json = false) { $userRoles = $this->getRequest()->getParam('user_roles'); if ($userRoles && $json) { - $result = $this->_jsonDecoder->decode($userRoles); - return $result ? $result : '{}'; + $result = json_decode($userRoles); + return $result ? $this->_jsonEncoder->encode($result) : '{}'; } /* @var $user \Magento\User\Model\User */ $user = $this->_coreRegistry->registry('permissions_user'); diff --git a/app/code/Magento/User/Test/Unit/Block/Role/Grid/UserTest.php b/app/code/Magento/User/Test/Unit/Block/Role/Grid/UserTest.php index d9ec719e30193..0700046fd2d58 100644 --- a/app/code/Magento/User/Test/Unit/Block/Role/Grid/UserTest.php +++ b/app/code/Magento/User/Test/Unit/Block/Role/Grid/UserTest.php @@ -22,9 +22,6 @@ class UserTest extends \PHPUnit\Framework\TestCase /** @var \Magento\Framework\Json\EncoderInterface|\PHPUnit_Framework_MockObject_MockObject */ protected $jsonEncoderMock; - /** @var \Magento\Framework\Json\DecoderInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $jsonDecoderMock; - /** @var \Magento\Framework\Registry|\PHPUnit_Framework_MockObject_MockObject */ protected $registryMock; @@ -58,11 +55,6 @@ protected function setUp() ->setMethods([]) ->getMock(); - $this->jsonDecoderMock = $this->getMockBuilder(\Magento\Framework\Json\DecoderInterface::class) - ->disableOriginalConstructor() - ->setMethods([]) - ->getMock(); - $this->registryMock = $this->getMockBuilder(\Magento\Framework\Registry::class) ->disableOriginalConstructor() ->setMethods([]) @@ -105,7 +97,6 @@ protected function setUp() [ 'backendHelper' => $this->backendHelperMock, 'jsonEncoder' => $this->jsonEncoderMock, - 'jsonDecoder' => $this->jsonDecoderMock, 'coreRegistry' => $this->registryMock, 'roleFactory' => $this->roleFactoryMock, 'userRolesFactory' => $this->userRolesFactoryMock, @@ -249,12 +240,20 @@ public function testPrepareColumns() $this->model->toHtml(); } + public function testGetUsersCorrectInRoleUser() + { + $param = 'in_role_user'; + $paramValue = '{"a":"role1","1":"role2","2":"role3"}'; + $this->requestInterfaceMock->expects($this->once())->method('getParam')->with($param)->willReturn($paramValue); + $this->jsonEncoderMock->expects($this->once())->method('encode')->willReturn($paramValue); + $this->assertEquals($paramValue, $this->model->getUsers(true)); + } + public function testGetUsersIncorrectInRoleUser() { $param = 'in_role_user'; $paramValue = 'not_JSON'; $this->requestInterfaceMock->expects($this->once())->method('getParam')->with($param)->willReturn($paramValue); - $this->jsonDecoderMock->expects($this->once())->method('decode')->with($paramValue)->willReturn(null); $this->assertEquals('{}', $this->model->getUsers(true)); } } diff --git a/app/code/Magento/User/Test/Unit/Block/User/Edit/Tab/RolesTest.php b/app/code/Magento/User/Test/Unit/Block/User/Edit/Tab/RolesTest.php index 84e91b4f1e50b..7c6dcae024aca 100644 --- a/app/code/Magento/User/Test/Unit/Block/User/Edit/Tab/RolesTest.php +++ b/app/code/Magento/User/Test/Unit/Block/User/Edit/Tab/RolesTest.php @@ -22,9 +22,6 @@ class RolesTest extends \PHPUnit\Framework\TestCase /** @var \Magento\Framework\Json\EncoderInterface|\PHPUnit_Framework_MockObject_MockObject */ protected $jsonEncoderMock; - /** @var \Magento\Framework\Json\DecoderInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $jsonDecoderMock; - /** @var \Magento\Framework\Registry|\PHPUnit_Framework_MockObject_MockObject */ protected $registryMock; @@ -58,11 +55,6 @@ protected function setUp() ->setMethods([]) ->getMock(); - $this->jsonDecoderMock = $this->getMockBuilder(\Magento\Framework\Json\DecoderInterface::class) - ->disableOriginalConstructor() - ->setMethods([]) - ->getMock(); - $this->registryMock = $this->getMockBuilder(\Magento\Framework\Registry::class) ->disableOriginalConstructor() ->setMethods([]) @@ -100,7 +92,6 @@ protected function setUp() [ 'backendHelper' => $this->backendHelperMock, 'jsonEncoder' => $this->jsonEncoderMock, - 'jsonDecoder' => $this->jsonDecoderMock, 'userRolesFactory' => $this->userRolesFactoryMock, 'coreRegistry' => $this->registryMock, 'request' => $this->requestInterfaceMock, @@ -111,12 +102,20 @@ protected function setUp() ); } + public function testSelectedRolesCorrectUserRoles() + { + $param = 'user_roles'; + $paramValue = '{"a":"role1","1":"role2","2":"role3"}'; + $this->requestInterfaceMock->expects($this->once())->method('getParam')->with($param)->willReturn($paramValue); + $this->jsonEncoderMock->expects($this->once())->method('encode')->willReturn($paramValue); + $this->assertEquals($paramValue, $this->model->getSelectedRoles(true)); + } + public function testSelectedRolesIncorrectUserRoles() { $param = 'user_roles'; $paramValue = 'not_JSON'; $this->requestInterfaceMock->expects($this->once())->method('getParam')->with($param)->willReturn($paramValue); - $this->jsonDecoderMock->expects($this->once())->method('decode')->with($paramValue)->willReturn(null); $this->assertEquals('{}', $this->model->getSelectedRoles(true)); } } From f7ad97674dd78e5bfd10e231e8b3aef7c953e073 Mon Sep 17 00:00:00 2001 From: Andrew Molina <amolina@adobe.com> Date: Fri, 29 Mar 2019 08:27:58 -0500 Subject: [PATCH 161/773] MC-13954: Updated Product Import Temp Directory --- .../CatalogImportExport/Test/Unit/Model/Import/UploaderTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/UploaderTest.php b/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/UploaderTest.php index 7565e099e2020..a4efa7806f5de 100644 --- a/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/UploaderTest.php +++ b/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/UploaderTest.php @@ -46,7 +46,7 @@ class UploaderTest extends \PHPUnit\Framework\TestCase /** * @var \Magento\Framework\Math\Random|\PHPUnit_Framework_MockObject_MockObject */ - protected $random; + private $random; /** * @var \Magento\CatalogImportExport\Model\Import\Uploader|\PHPUnit_Framework_MockObject_MockObject From 70cf58543441496e870e9b97fc4ea0de45668365 Mon Sep 17 00:00:00 2001 From: Sachin Admane <sadmane@magento.com> Date: Fri, 29 Mar 2019 09:41:28 -0500 Subject: [PATCH 162/773] MC-15570: Updating cart form. --- .../Catalog/view/frontend/templates/product/view/form.phtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/view/frontend/templates/product/view/form.phtml b/app/code/Magento/Catalog/view/frontend/templates/product/view/form.phtml index 9c5cce7865532..28656438308bb 100644 --- a/app/code/Magento/Catalog/view/frontend/templates/product/view/form.phtml +++ b/app/code/Magento/Catalog/view/frontend/templates/product/view/form.phtml @@ -22,7 +22,7 @@ <input type="hidden" name="product" value="<?= /* @escapeNotVerified */ $_product->getId() ?>" /> <input type="hidden" name="selected_configurable_option" value="" /> <input type="hidden" name="related_product" id="related-products-field" value="" /> - <input type="hidden" name="item" value="<?= /* @noEscape */ $block->getRequest()->getParam('id') ?>" /> + <input type="hidden" name="item" value="<?= $block->escapeHtml($block->getRequest()->getParam('id')) ?>" /> <?= $block->getBlockHtml('formkey') ?> <?= $block->getChildHtml('form_top') ?> <?php if (!$block->hasOptions()):?> From 1ff1ae11815641cc31dc714042916c1f98693daa Mon Sep 17 00:00:00 2001 From: Nathan Smith <nathsmit@adobe.com> Date: Fri, 29 Mar 2019 10:01:54 -0500 Subject: [PATCH 163/773] MC-5882: Invalid quote in session --- app/code/Magento/Checkout/Model/Session.php | 26 ++++++++++++++++--- .../Magento/Checkout/Model/SessionTest.php | 23 ++++++++++++++++ .../Model/Quote/ResetQuoteAddressesTest.php | 9 +++++++ 3 files changed, 55 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Checkout/Model/Session.php b/app/code/Magento/Checkout/Model/Session.php index 0756bbda50ae7..748a9565fa31e 100644 --- a/app/code/Magento/Checkout/Model/Session.php +++ b/app/code/Magento/Checkout/Model/Session.php @@ -10,8 +10,11 @@ use Magento\Quote\Model\QuoteIdMaskFactory; /** + * Represents the session data for the checkout process + * * @api * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * @SuppressWarnings(PHPMD.CookieAndSessionMisuse) */ class Session extends \Magento\Framework\Session\SessionManager { @@ -294,6 +297,8 @@ public function getQuote() } /** + * Return the quote's key + * * @return string * @codeCoverageIgnore */ @@ -303,6 +308,8 @@ protected function _getQuoteIdKey() } /** + * Set the current session's quote id + * * @param int $quoteId * @return void * @codeCoverageIgnore @@ -313,6 +320,8 @@ public function setQuoteId($quoteId) } /** + * Return the current quote's ID + * * @return int * @codeCoverageIgnore */ @@ -366,6 +375,8 @@ public function loadCustomerQuote() } /** + * Associate data to a specified step of the checkout process + * * @param string $step * @param array|string $data * @param bool|string|null $value @@ -392,6 +403,8 @@ public function setStepData($step, $data, $value = null) } /** + * Return the data associated to a specified step + * * @param string|null $step * @param string|null $data * @return array|string|bool @@ -415,8 +428,7 @@ public function getStepData($step = null, $data = null) } /** - * Destroy/end a session - * Unset all data associated with object + * Destroy/end a session and unset all data associated with it * * @return $this */ @@ -452,6 +464,8 @@ public function clearHelperData() } /** + * Revert the state of the checkout to the beginning + * * @return $this * @codeCoverageIgnore */ @@ -462,6 +476,8 @@ public function resetCheckout() } /** + * Replace the quote in the session with a specified object + * * @param Quote $quote * @return $this */ @@ -514,7 +530,9 @@ public function restoreQuote() } /** - * @param $isQuoteMasked bool + * Flag whether or not the quote uses a masked quote id + * + * @param bool $isQuoteMasked * @return void * @codeCoverageIgnore */ @@ -524,6 +542,8 @@ protected function setIsQuoteMasked($isQuoteMasked) } /** + * Return if the quote has a masked quote id + * * @return bool|null * @codeCoverageIgnore */ diff --git a/dev/tests/integration/testsuite/Magento/Checkout/Model/SessionTest.php b/dev/tests/integration/testsuite/Magento/Checkout/Model/SessionTest.php index af572c556bb07..4682453012952 100644 --- a/dev/tests/integration/testsuite/Magento/Checkout/Model/SessionTest.php +++ b/dev/tests/integration/testsuite/Magento/Checkout/Model/SessionTest.php @@ -13,10 +13,13 @@ use Magento\Framework\Api\SearchCriteriaBuilder; use Magento\Quote\Api\CartRepositoryInterface; use Magento\Quote\Api\Data\CartInterface; +use Magento\Quote\Model\Quote; use Magento\TestFramework\Helper\Bootstrap; /** * Class SessionTest + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class SessionTest extends \PHPUnit\Framework\TestCase { @@ -86,6 +89,26 @@ public function testGetQuoteNotInitializedCustomerLoggedIn() $this->_validateCustomerDataInQuote($quote); } + /** + * @magentoDataFixture Magento/Sales/_files/quote_with_customer.php + * @magentoAppIsolation enabled + */ + public function testGetQuoteWithMismatchingSession() + { + /** @var Quote $quote */ + $quote = Bootstrap::getObjectManager()->create(Quote::class); + /** @var \Magento\Quote\Model\ResourceModel\Quote $quoteResource */ + $quoteResource = Bootstrap::getObjectManager()->create(\Magento\Quote\Model\ResourceModel\Quote::class); + $quoteResource->load($quote, 'test01', 'reserved_order_id'); + + // Customer on quote is not logged in + $this->checkoutSession->setQuoteId($quote->getId()); + + $sessionQuote = $this->checkoutSession->getQuote(); + $this->assertEmpty($sessionQuote->getCustomerId()); + $this->assertNotEquals($quote->getId(), $sessionQuote->getId()); + } + /** * Tes merging of customer data into initialized quote object. * diff --git a/dev/tests/integration/testsuite/Magento/Checkout/Plugin/Model/Quote/ResetQuoteAddressesTest.php b/dev/tests/integration/testsuite/Magento/Checkout/Plugin/Model/Quote/ResetQuoteAddressesTest.php index 60ccdb88676aa..5150f7a1eae18 100644 --- a/dev/tests/integration/testsuite/Magento/Checkout/Plugin/Model/Quote/ResetQuoteAddressesTest.php +++ b/dev/tests/integration/testsuite/Magento/Checkout/Plugin/Model/Quote/ResetQuoteAddressesTest.php @@ -27,6 +27,7 @@ class ResetQuoteAddressesTest extends \PHPUnit\Framework\TestCase */ public function testAfterRemoveItem(): void { + $this->login(1); /** @var Quote $quote */ $quote = Bootstrap::getObjectManager()->create(Quote::class); $quote->load('test_order_with_virtual_product', 'reserved_order_id'); @@ -75,4 +76,12 @@ public function testAfterRemoveItem(): void $this->assertEmpty($quoteBillingAddressUpdated->getPostcode()); $this->assertEmpty($quoteBillingAddressUpdated->getCity()); } + + private function login(int $customerId): void + { + /** @var \Magento\Customer\Model\Session $session */ + $session = Bootstrap::getObjectManager() + ->get(\Magento\Customer\Model\Session::class); + $session->loginById($customerId); + } } From c5a712069a50effe7a61fbfa8f0e72bd40627c85 Mon Sep 17 00:00:00 2001 From: Oleksandr Miroshnichenko <omiroshnichenko@magento.com> Date: Fri, 29 Mar 2019 10:07:06 -0500 Subject: [PATCH 164/773] MC-5895: Create a separate data provider - fix tests --- app/code/Magento/Ui/Controller/Index/Render.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Ui/Controller/Index/Render.php b/app/code/Magento/Ui/Controller/Index/Render.php index 6aa8f4887d878..6f0cc0b6595a4 100644 --- a/app/code/Magento/Ui/Controller/Index/Render.php +++ b/app/code/Magento/Ui/Controller/Index/Render.php @@ -19,6 +19,7 @@ * Is responsible for providing ui components information on store front. * * @SuppressWarnings(PHPMD.AllPurposeAction) + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class Render extends \Magento\Framework\App\Action\Action { From b16d4efcc869a84ba4344ed4c3c7abefc3f9cc73 Mon Sep 17 00:00:00 2001 From: Mark Berube <berube@adobe.com> Date: Fri, 29 Mar 2019 10:45:45 -0500 Subject: [PATCH 165/773] MC-15036: Hardcode DHL gateway URL --- app/code/Magento/Dhl/Model/Carrier.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/code/Magento/Dhl/Model/Carrier.php b/app/code/Magento/Dhl/Model/Carrier.php index 2fc61b89e6990..ff51a71f81e63 100644 --- a/app/code/Magento/Dhl/Model/Carrier.php +++ b/app/code/Magento/Dhl/Model/Carrier.php @@ -4,8 +4,6 @@ * See COPYING.txt for license details. */ -declare(strict_types=1); - namespace Magento\Dhl\Model; use Magento\Catalog\Model\Product\Type; From 10412c45debf61a106530105603a9a7b9fbfe369 Mon Sep 17 00:00:00 2001 From: Mark Berube <berube@adobe.com> Date: Fri, 29 Mar 2019 10:47:38 -0500 Subject: [PATCH 166/773] MC-15036: Hardcode DHL gateway URL --- app/code/Magento/Dhl/Test/Unit/Model/CarrierTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Dhl/Test/Unit/Model/CarrierTest.php b/app/code/Magento/Dhl/Test/Unit/Model/CarrierTest.php index 1a8b3a7a8d70d..d0bc2a04b36eb 100644 --- a/app/code/Magento/Dhl/Test/Unit/Model/CarrierTest.php +++ b/app/code/Magento/Dhl/Test/Unit/Model/CarrierTest.php @@ -718,7 +718,7 @@ public function testGetGatewayURL($sandboxMode, $expectedURL) /** * Data provider for testGetGatewayURL - * + * * @return array */ public function getGatewayURLProvider() From 1b34d1746f9a7c54ca09bc28c7e343aa00fcc5b1 Mon Sep 17 00:00:00 2001 From: Andrew Molina <amolina@adobe.com> Date: Fri, 29 Mar 2019 11:33:41 -0500 Subject: [PATCH 167/773] MC-13954: Update Product Import Temp Directory --- app/code/Magento/CatalogImportExport/Model/Import/Uploader.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Uploader.php b/app/code/Magento/CatalogImportExport/Model/Import/Uploader.php index a35d04def43b8..47bdfe51475a3 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Uploader.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Uploader.php @@ -282,7 +282,6 @@ protected function _validateFile() $fileExtension = pathinfo($filePath, PATHINFO_EXTENSION); if (!$this->checkAllowedExtension($fileExtension)) { - $this->_directory->delete($filePath); throw new \Exception('Disallowed file type.'); } //run validate callbacks From f46c04c81320d76eaf1807cf33fe8601189d6b61 Mon Sep 17 00:00:00 2001 From: Hwashiang Yu <hwyu@adobe.com> Date: Fri, 29 Mar 2019 11:53:19 -0500 Subject: [PATCH 168/773] MC-13896: User Role Template Update - Updated request param collection logic to include non-json - Removed unused mocks in rolesTest --- .../Magento/User/Block/Role/Grid/User.php | 29 ++++------ .../User/Block/User/Edit/Tab/Roles.php | 9 ++- .../Unit/Block/User/Edit/Tab/RolesTest.php | 58 ------------------- 3 files changed, 16 insertions(+), 80 deletions(-) diff --git a/app/code/Magento/User/Block/Role/Grid/User.php b/app/code/Magento/User/Block/Role/Grid/User.php index 4f642d5d04c66..ce9bc3f6749b3 100644 --- a/app/code/Magento/User/Block/Role/Grid/User.php +++ b/app/code/Magento/User/Block/Role/Grid/User.php @@ -34,11 +34,6 @@ class User extends \Magento\Backend\Block\Widget\Grid\Extended */ protected $_jsonEncoder; - /** - * @var \Magento\Framework\Json\DecoderInterface - */ - protected $_jsonDecoder; - /** * @var \Magento\User\Model\ResourceModel\Role\User\CollectionFactory */ @@ -54,7 +49,6 @@ class User extends \Magento\Backend\Block\Widget\Grid\Extended * @param \Magento\Backend\Block\Template\Context $context * @param \Magento\Backend\Helper\Data $backendHelper * @param \Magento\Framework\Json\EncoderInterface $jsonEncoder - * @param \Magento\Framework\Json\DecoderInterface $jsonDecoder * @param \Magento\Framework\Registry $coreRegistry * @param \Magento\Authorization\Model\RoleFactory $roleFactory * @param \Magento\User\Model\ResourceModel\Role\User\CollectionFactory $userRolesFactory @@ -64,7 +58,6 @@ public function __construct( \Magento\Backend\Block\Template\Context $context, \Magento\Backend\Helper\Data $backendHelper, \Magento\Framework\Json\EncoderInterface $jsonEncoder, - \Magento\Framework\Json\DecoderInterface $jsonDecoder, \Magento\Framework\Registry $coreRegistry, \Magento\Authorization\Model\RoleFactory $roleFactory, \Magento\User\Model\ResourceModel\Role\User\CollectionFactory $userRolesFactory, @@ -72,7 +65,6 @@ public function __construct( ) { parent::__construct($context, $backendHelper, $data); $this->_jsonEncoder = $jsonEncoder; - $this->_jsonDecoder = $jsonDecoder; $this->_coreRegistry = $coreRegistry; $this->_roleFactory = $roleFactory; $this->_userRolesFactory = $userRolesFactory; @@ -200,18 +192,17 @@ public function getGridUrl() public function getUsers($json = false) { $inRoleUser = $this->getRequest()->getParam('in_role_user'); - if ($inRoleUser && $json) { - $result = json_decode($inRoleUser); - return $result ? $this->_jsonEncoder->encode($result) : '{}'; + if ($inRoleUser) { + if ($json) { + $result = json_decode($inRoleUser); + return $result ? $this->_jsonEncoder->encode($result) : '{}'; + } + return $this->escapeJs($this->escapeHtml($inRoleUser)); + } + $roleId = $this->getRequest()->getParam('rid'); + if ($roleId <= 0) { + $roleId = $this->_coreRegistry->registry('RID'); } - $roleId = $this->getRequest()->getParam( - 'rid' - ) > 0 ? $this->getRequest()->getParam( - 'rid' - ) : $this->_coreRegistry->registry( - 'RID' - ); - $users = $this->getUsersFormData(); if (false === $users) { $users = $this->_roleFactory->create()->setId($roleId)->getRoleUsers(); diff --git a/app/code/Magento/User/Block/User/Edit/Tab/Roles.php b/app/code/Magento/User/Block/User/Edit/Tab/Roles.php index 2707ba00d24ec..7f57bd4fa0227 100644 --- a/app/code/Magento/User/Block/User/Edit/Tab/Roles.php +++ b/app/code/Magento/User/Block/User/Edit/Tab/Roles.php @@ -141,9 +141,12 @@ public function getGridUrl() public function getSelectedRoles($json = false) { $userRoles = $this->getRequest()->getParam('user_roles'); - if ($userRoles && $json) { - $result = json_decode($userRoles); - return $result ? $this->_jsonEncoder->encode($result) : '{}'; + if ($userRoles) { + if ($json) { + $result = json_decode($userRoles); + return $result ? $this->_jsonEncoder->encode($result) : '{}'; + } + return $this->escapeJs($this->escapeHtml($userRoles)); } /* @var $user \Magento\User\Model\User */ $user = $this->_coreRegistry->registry('permissions_user'); diff --git a/app/code/Magento/User/Test/Unit/Block/User/Edit/Tab/RolesTest.php b/app/code/Magento/User/Test/Unit/Block/User/Edit/Tab/RolesTest.php index 7c6dcae024aca..ca7a0a8e17699 100644 --- a/app/code/Magento/User/Test/Unit/Block/User/Edit/Tab/RolesTest.php +++ b/app/code/Magento/User/Test/Unit/Block/User/Edit/Tab/RolesTest.php @@ -16,88 +16,30 @@ class RolesTest extends \PHPUnit\Framework\TestCase /** @var \Magento\User\Block\User\Edit\Tab\Roles */ protected $model; - /** @var \Magento\Backend\Helper\Data|\PHPUnit_Framework_MockObject_MockObject */ - protected $backendHelperMock; - /** @var \Magento\Framework\Json\EncoderInterface|\PHPUnit_Framework_MockObject_MockObject */ protected $jsonEncoderMock; - /** @var \Magento\Framework\Registry|\PHPUnit_Framework_MockObject_MockObject */ - protected $registryMock; - - /** @var \Magento\Authorization\Model\RoleFactory|\PHPUnit_Framework_MockObject_MockObject */ - protected $roleFactoryMock; - - /** @var \Magento\User\Model\ResourceModel\Role\User\CollectionFactory|\PHPUnit_Framework_MockObject_MockObject */ - protected $userRolesFactoryMock; - /** @var \Magento\Framework\App\RequestInterface|\PHPUnit_Framework_MockObject_MockObject */ protected $requestInterfaceMock; - /** @var \Magento\Framework\UrlInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $urlInterfaceMock; - - /** @var \Magento\Framework\View\LayoutInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $layoutMock; - - /** @var \Magento\Framework\Filesystem|\PHPUnit_Framework_MockObject_MockObject */ - protected $filesystemMock; - protected function setUp() { - $this->backendHelperMock = $this->getMockBuilder(\Magento\Backend\Helper\Data::class) - ->disableOriginalConstructor() - ->setMethods([]) - ->getMock(); - $this->jsonEncoderMock = $this->getMockBuilder(\Magento\Framework\Json\EncoderInterface::class) ->disableOriginalConstructor() ->setMethods([]) ->getMock(); - $this->registryMock = $this->getMockBuilder(\Magento\Framework\Registry::class) - ->disableOriginalConstructor() - ->setMethods([]) - ->getMock(); - - $this->userRolesFactoryMock = $this - ->getMockBuilder(\Magento\Authorization\Model\ResourceModel\Role\CollectionFactory::class) - ->disableOriginalConstructor() - ->setMethods(['create']) - ->getMock(); - $this->requestInterfaceMock = $this->getMockBuilder(\Magento\Framework\App\RequestInterface::class) ->disableOriginalConstructor() ->setMethods([]) ->getMock(); - $this->urlInterfaceMock = $this->getMockBuilder(\Magento\Framework\UrlInterface::class) - ->disableOriginalConstructor() - ->setMethods([]) - ->getMock(); - - $this->layoutMock = $this->getMockBuilder(\Magento\Framework\View\LayoutInterface::class) - ->disableOriginalConstructor() - ->setMethods([]) - ->getMock(); - - $this->filesystemMock = $this->getMockBuilder(\Magento\Framework\Filesystem::class) - ->disableOriginalConstructor() - ->setMethods([]) - ->getMock(); - $objectManagerHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); $this->model = $objectManagerHelper->getObject( \Magento\User\Block\User\Edit\Tab\Roles::class, [ - 'backendHelper' => $this->backendHelperMock, 'jsonEncoder' => $this->jsonEncoderMock, - 'userRolesFactory' => $this->userRolesFactoryMock, - 'coreRegistry' => $this->registryMock, 'request' => $this->requestInterfaceMock, - 'urlBuilder' => $this->urlInterfaceMock, - 'layout' => $this->layoutMock, - 'filesystem' => $this->filesystemMock ] ); } From 5d1486eb72814b90f03257c7fbb3423e795ab819 Mon Sep 17 00:00:00 2001 From: David Haecker <dhaecker@magento.com> Date: Fri, 29 Mar 2019 13:59:57 -0500 Subject: [PATCH 169/773] MC-5858: HTTPS redirecting problem on storefront - Updating MFTF tests --- ...erifySecureURLRedirectAuthorizenetTest.xml | 2 +- ...ontVerifySecureURLRedirectCheckoutTest.xml | 15 ++++++++++++++- ...rontVerifySecureURLRedirectContactTest.xml | 2 ++ ...erifySecureURLRedirectDownloadableTest.xml | 8 ++------ ...rifySecureURLRedirectMultishippingTest.xml | 19 +++++++++++++++++-- ...tVerifySecureURLRedirectNewsletterTest.xml | 2 +- ...frontVerifySecureURLRedirectPaypalTest.xml | 2 +- ...tVerifySecureURLRedirectPersistentTest.xml | 9 +++------ ...frontVerifySecureURLRedirectReviewTest.xml | 2 +- ...efrontVerifySecureURLRedirectSalesTest.xml | 2 +- ...efrontVerifySecureURLRedirectVaultTest.xml | 2 +- ...ontVerifySecureURLRedirectWishlistTest.xml | 2 +- 12 files changed, 45 insertions(+), 22 deletions(-) diff --git a/app/code/Magento/Authorizenet/Test/Mftf/Test/StorefrontVerifySecureURLRedirectAuthorizenetTest.xml b/app/code/Magento/Authorizenet/Test/Mftf/Test/StorefrontVerifySecureURLRedirectAuthorizenetTest.xml index afd7815518e98..5db903f0ed54a 100644 --- a/app/code/Magento/Authorizenet/Test/Mftf/Test/StorefrontVerifySecureURLRedirectAuthorizenetTest.xml +++ b/app/code/Magento/Authorizenet/Test/Mftf/Test/StorefrontVerifySecureURLRedirectAuthorizenetTest.xml @@ -22,7 +22,7 @@ </annotations> <before> <createData entity="Simple_US_Customer" stepKey="customer"/> - <actionGroup ref="LoginToStorefrontActionGroup" stepKey="signThirdSimpleUsCustomer"> + <actionGroup ref="LoginToStorefrontActionGroup" stepKey="loginToStorefront"> <argument name="Customer" value="$$customer$$"/> </actionGroup> <executeJS function="return window.location.host" stepKey="hostname"/> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontVerifySecureURLRedirectCheckoutTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontVerifySecureURLRedirectCheckoutTest.xml index a6300a45ad7bb..cbf0072d44aed 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontVerifySecureURLRedirectCheckoutTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontVerifySecureURLRedirectCheckoutTest.xml @@ -21,7 +21,18 @@ <group value="secure_storefront_url"/> </annotations> <before> - <amOnPage url="/" stepKey="goToHomePage"/> + <createData entity="_defaultCategory" stepKey="category"/> + <createData entity="_defaultProduct" stepKey="product"> + <requiredEntity createDataKey="category"/> + </createData> + <amOnPage url="{{StorefrontCategoryPage.url($$category.name$$)}}" stepKey="goToCategoryPage"/> + <waitForPageLoad stepKey="waitForPageLoad"/> + <moveMouseOver selector="{{StorefrontCategoryMainSection.ProductItemInfo}}" stepKey="moveMouseOverProduct"/> + <click selector="{{StorefrontCategoryMainSection.AddToCartBtn}}" stepKey="clickAddToCartButton"/> + <waitForPageLoad stepKey="waitForAddToCart"/> + <waitForElementVisible selector="{{StorefrontCategoryMainSection.SuccessMsg}}" time="30" stepKey="waitForAddedToCartSuccessMessage"/> + <see selector="{{StorefrontCategoryMainSection.SuccessMsg}}" userInput="You added $$product.name$$ to your shopping cart." stepKey="seeAddedToCartSuccessMessage"/> + <see selector="{{StorefrontMinicartSection.quantity}}" userInput="1" stepKey="seeCartQuantity"/> <executeJS function="return window.location.host" stepKey="hostname"/> <magentoCLI command="config:set web/secure/base_url https://{$hostname}/" stepKey="setSecureBaseURL"/> <magentoCLI command="config:set web/secure/use_in_frontend 1" stepKey="useSecureURLsOnStorefront"/> @@ -30,6 +41,8 @@ <after> <magentoCLI command="config:set web/secure/use_in_frontend 0" stepKey="dontUseSecureURLsOnStorefront"/> <magentoCLI command="cache:flush" stepKey="flushCache"/> + <deleteData createDataKey="product" stepKey="deleteProduct"/> + <deleteData createDataKey="category" stepKey="deleteCategory"/> </after> <executeJS function="return window.location.host" stepKey="hostname"/> <amOnUrl url="http://{$hostname}/checkout" stepKey="goToUnsecureCheckoutURL"/> diff --git a/app/code/Magento/Contact/Test/Mftf/Test/StorefrontVerifySecureURLRedirectContactTest.xml b/app/code/Magento/Contact/Test/Mftf/Test/StorefrontVerifySecureURLRedirectContactTest.xml index a41ecf861c43c..3ef941fa2e0ce 100644 --- a/app/code/Magento/Contact/Test/Mftf/Test/StorefrontVerifySecureURLRedirectContactTest.xml +++ b/app/code/Magento/Contact/Test/Mftf/Test/StorefrontVerifySecureURLRedirectContactTest.xml @@ -34,5 +34,7 @@ <executeJS function="return window.location.host" stepKey="hostname"/> <amOnUrl url="http://{$hostname}/contact" stepKey="goToUnsecureContactURL"/> <seeCurrentUrlEquals url="https://{$hostname}/contact" stepKey="seeSecureContactURL"/> + <amOnUrl url="http://{$hostname}/contact/index/post" stepKey="goToUnsecureContactFormURL"/> + <seeCurrentUrlEquals url="https://{$hostname}/contact/index/post" stepKey="seeSecureContactFormURL"/> </test> </tests> diff --git a/app/code/Magento/Downloadable/Test/Mftf/Test/StorefrontVerifySecureURLRedirectDownloadableTest.xml b/app/code/Magento/Downloadable/Test/Mftf/Test/StorefrontVerifySecureURLRedirectDownloadableTest.xml index b4a8121edb5ca..6e039ca413a08 100644 --- a/app/code/Magento/Downloadable/Test/Mftf/Test/StorefrontVerifySecureURLRedirectDownloadableTest.xml +++ b/app/code/Magento/Downloadable/Test/Mftf/Test/StorefrontVerifySecureURLRedirectDownloadableTest.xml @@ -22,10 +22,7 @@ </annotations> <before> <createData entity="Simple_US_Customer" stepKey="customer"/> - <createData entity="Default_Company" stepKey="company"> - <requiredEntity createDataKey="customer"/> - </createData> - <actionGroup ref="LoginToStorefrontActionGroup" stepKey="signThirdSimpleUsCustomer"> + <actionGroup ref="LoginToStorefrontActionGroup" stepKey="loginToStorefront"> <argument name="Customer" value="$$customer$$"/> </actionGroup> <executeJS function="return window.location.host" stepKey="hostname"/> @@ -36,8 +33,7 @@ <after> <magentoCLI command="config:set web/secure/use_in_frontend 0" stepKey="dontUseSecureURLsOnStorefront"/> <magentoCLI command="cache:flush" stepKey="flushCache"/> - <deleteData createDataKey="company" stepKey="deleteCompany"/> - <deleteData createDataKey="customer" stepKey="deleteCompanyAdmin"/> + <deleteData createDataKey="customer" stepKey="deleteCustomer"/> </after> <executeJS function="return window.location.host" stepKey="hostname"/> <amOnUrl url="http://{$hostname}/downloadable/customer" stepKey="goToUnsecureDownloadableCustomerURL"/> diff --git a/app/code/Magento/Multishipping/Test/Mftf/Test/StorefrontVerifySecureURLRedirectMultishippingTest.xml b/app/code/Magento/Multishipping/Test/Mftf/Test/StorefrontVerifySecureURLRedirectMultishippingTest.xml index a1dd37cd97717..60b09e841a864 100644 --- a/app/code/Magento/Multishipping/Test/Mftf/Test/StorefrontVerifySecureURLRedirectMultishippingTest.xml +++ b/app/code/Magento/Multishipping/Test/Mftf/Test/StorefrontVerifySecureURLRedirectMultishippingTest.xml @@ -9,6 +9,7 @@ <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="StorefrontVerifySecureURLRedirectMultishipping"> + <!--todo MC-5858: can't get to /multishipping/checkout & some sub pages don't redirect to https--> <annotations> <features value="Multishipping"/> <stories value="Storefront Secure URLs"/> @@ -21,10 +22,22 @@ <group value="secure_storefront_url"/> </annotations> <before> + <createData entity="_defaultCategory" stepKey="category"/> + <createData entity="_defaultProduct" stepKey="product"> + <requiredEntity createDataKey="category"/> + </createData> <createData entity="Simple_US_Customer" stepKey="customer"/> - <actionGroup ref="LoginToStorefrontActionGroup" stepKey="signThirdSimpleUsCustomer"> + <actionGroup ref="LoginToStorefrontActionGroup" stepKey="loginToStorefront"> <argument name="Customer" value="$$customer$$"/> </actionGroup> + <amOnPage url="{{StorefrontCategoryPage.url($$category.name$$)}}" stepKey="goToCategoryPage"/> + <waitForPageLoad stepKey="waitForPageLoad"/> + <moveMouseOver selector="{{StorefrontCategoryMainSection.ProductItemInfo}}" stepKey="moveMouseOverProduct"/> + <click selector="{{StorefrontCategoryMainSection.AddToCartBtn}}" stepKey="clickAddToCartButton"/> + <waitForPageLoad stepKey="waitForAddToCart"/> + <waitForElementVisible selector="{{StorefrontCategoryMainSection.SuccessMsg}}" time="30" stepKey="waitForAddedToCartSuccessMessage"/> + <see selector="{{StorefrontCategoryMainSection.SuccessMsg}}" userInput="You added $$product.name$$ to your shopping cart." stepKey="seeAddedToCartSuccessMessage"/> + <see selector="{{StorefrontMinicartSection.quantity}}" userInput="1" stepKey="seeCartQuantity"/> <executeJS function="return window.location.host" stepKey="hostname"/> <magentoCLI command="config:set web/secure/base_url https://{$hostname}/" stepKey="setSecureBaseURL"/> <magentoCLI command="config:set web/secure/use_in_frontend 1" stepKey="useSecureURLsOnStorefront"/> @@ -34,9 +47,11 @@ <magentoCLI command="config:set web/secure/use_in_frontend 0" stepKey="dontUseSecureURLsOnStorefront"/> <magentoCLI command="cache:flush" stepKey="flushCache"/> <deleteData createDataKey="customer" stepKey="deleteCustomer"/> + <deleteData createDataKey="product" stepKey="deleteProduct"/> + <deleteData createDataKey="category" stepKey="deleteCategory"/> </after> <executeJS function="return window.location.host" stepKey="hostname"/> <amOnUrl url="http://{$hostname}/multishipping/checkout" stepKey="goToUnsecureMultishippingCheckoutURL"/> - <seeCurrentUrlEquals url="https://{$hostname}/multishipping/checkout" stepKey="seeSecureMultishippingCheckoutURL"/> + <seeInCurrentUrl url="https://{$hostname}/multishipping/checkout" stepKey="seeSecureMultishippingCheckoutURL"/> </test> </tests> diff --git a/app/code/Magento/Newsletter/Test/Mftf/Test/StorefrontVerifySecureURLRedirectNewsletterTest.xml b/app/code/Magento/Newsletter/Test/Mftf/Test/StorefrontVerifySecureURLRedirectNewsletterTest.xml index 7237e1801b2b7..01b5e706fcefb 100644 --- a/app/code/Magento/Newsletter/Test/Mftf/Test/StorefrontVerifySecureURLRedirectNewsletterTest.xml +++ b/app/code/Magento/Newsletter/Test/Mftf/Test/StorefrontVerifySecureURLRedirectNewsletterTest.xml @@ -22,7 +22,7 @@ </annotations> <before> <createData entity="Simple_US_Customer" stepKey="customer"/> - <actionGroup ref="LoginToStorefrontActionGroup" stepKey="signThirdSimpleUsCustomer"> + <actionGroup ref="LoginToStorefrontActionGroup" stepKey="loginToStorefront"> <argument name="Customer" value="$$customer$$"/> </actionGroup> <executeJS function="return window.location.host" stepKey="hostname"/> diff --git a/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontVerifySecureURLRedirectPaypalTest.xml b/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontVerifySecureURLRedirectPaypalTest.xml index bd078096b3d65..b2fcfa43181dc 100644 --- a/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontVerifySecureURLRedirectPaypalTest.xml +++ b/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontVerifySecureURLRedirectPaypalTest.xml @@ -22,7 +22,7 @@ </annotations> <before> <createData entity="Simple_US_Customer" stepKey="customer"/> - <actionGroup ref="LoginToStorefrontActionGroup" stepKey="signThirdSimpleUsCustomer"> + <actionGroup ref="LoginToStorefrontActionGroup" stepKey="loginToStorefront"> <argument name="Customer" value="$$customer$$"/> </actionGroup> <executeJS function="return window.location.host" stepKey="hostname"/> diff --git a/app/code/Magento/Persistent/Test/Mftf/Test/StorefrontVerifySecureURLRedirectPersistentTest.xml b/app/code/Magento/Persistent/Test/Mftf/Test/StorefrontVerifySecureURLRedirectPersistentTest.xml index 3a39f12edf909..e879824a6f5cb 100644 --- a/app/code/Magento/Persistent/Test/Mftf/Test/StorefrontVerifySecureURLRedirectPersistentTest.xml +++ b/app/code/Magento/Persistent/Test/Mftf/Test/StorefrontVerifySecureURLRedirectPersistentTest.xml @@ -9,6 +9,7 @@ <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="StorefrontVerifySecureURLRedirectPersistent"> + <!--todo MC-5858: can't figure out how to make this work--> <annotations> <features value="Persistent"/> <stories value="Storefront Secure URLs"/> @@ -22,10 +23,7 @@ </annotations> <before> <createData entity="Simple_US_Customer" stepKey="customer"/> - <createData entity="Default_Company" stepKey="company"> - <requiredEntity createDataKey="customer"/> - </createData> - <actionGroup ref="LoginToStorefrontActionGroup" stepKey="signThirdSimpleUsCustomer"> + <actionGroup ref="LoginToStorefrontActionGroup" stepKey="loginToStorefront"> <argument name="Customer" value="$$customer$$"/> </actionGroup> <executeJS function="return window.location.host" stepKey="hostname"/> @@ -36,8 +34,7 @@ <after> <magentoCLI command="config:set web/secure/use_in_frontend 0" stepKey="dontUseSecureURLsOnStorefront"/> <magentoCLI command="cache:flush" stepKey="flushCache"/> - <deleteData createDataKey="company" stepKey="deleteCompany"/> - <deleteData createDataKey="customer" stepKey="deleteCompanyAdmin"/> + <deleteData createDataKey="customer" stepKey="deleteCustomer"/> </after> <executeJS function="return window.location.host" stepKey="hostname"/> <amOnUrl url="http://{$hostname}/persistent/index/saveMethod" stepKey="goToUnsecurePersistentIndexSaveMethodURL"/> diff --git a/app/code/Magento/Review/Test/Mftf/Test/StorefrontVerifySecureURLRedirectReviewTest.xml b/app/code/Magento/Review/Test/Mftf/Test/StorefrontVerifySecureURLRedirectReviewTest.xml index f2d3826f3bb04..b10af7a303cc7 100644 --- a/app/code/Magento/Review/Test/Mftf/Test/StorefrontVerifySecureURLRedirectReviewTest.xml +++ b/app/code/Magento/Review/Test/Mftf/Test/StorefrontVerifySecureURLRedirectReviewTest.xml @@ -22,7 +22,7 @@ </annotations> <before> <createData entity="Simple_US_Customer" stepKey="customer"/> - <actionGroup ref="LoginToStorefrontActionGroup" stepKey="signThirdSimpleUsCustomer"> + <actionGroup ref="LoginToStorefrontActionGroup" stepKey="loginToStorefront"> <argument name="Customer" value="$$customer$$"/> </actionGroup> <executeJS function="return window.location.host" stepKey="hostname"/> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/StorefrontVerifySecureURLRedirectSalesTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/StorefrontVerifySecureURLRedirectSalesTest.xml index 67b65a586e58b..505493e4e5682 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/StorefrontVerifySecureURLRedirectSalesTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/StorefrontVerifySecureURLRedirectSalesTest.xml @@ -22,7 +22,7 @@ </annotations> <before> <createData entity="Simple_US_Customer" stepKey="customer"/> - <actionGroup ref="LoginToStorefrontActionGroup" stepKey="signThirdSimpleUsCustomer"> + <actionGroup ref="LoginToStorefrontActionGroup" stepKey="loginToStorefront"> <argument name="Customer" value="$$customer$$"/> </actionGroup> <executeJS function="return window.location.host" stepKey="hostname"/> diff --git a/app/code/Magento/Vault/Test/Mftf/Test/StorefrontVerifySecureURLRedirectVaultTest.xml b/app/code/Magento/Vault/Test/Mftf/Test/StorefrontVerifySecureURLRedirectVaultTest.xml index d0ace6aacc89c..c9d4cb3391cfd 100644 --- a/app/code/Magento/Vault/Test/Mftf/Test/StorefrontVerifySecureURLRedirectVaultTest.xml +++ b/app/code/Magento/Vault/Test/Mftf/Test/StorefrontVerifySecureURLRedirectVaultTest.xml @@ -22,7 +22,7 @@ </annotations> <before> <createData entity="Simple_US_Customer" stepKey="customer"/> - <actionGroup ref="LoginToStorefrontActionGroup" stepKey="signThirdSimpleUsCustomer"> + <actionGroup ref="LoginToStorefrontActionGroup" stepKey="loginToStorefront"> <argument name="Customer" value="$$customer$$"/> </actionGroup> <executeJS function="return window.location.host" stepKey="hostname"/> diff --git a/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontVerifySecureURLRedirectWishlistTest.xml b/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontVerifySecureURLRedirectWishlistTest.xml index 427a4b8ed007f..21fa334a43196 100644 --- a/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontVerifySecureURLRedirectWishlistTest.xml +++ b/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontVerifySecureURLRedirectWishlistTest.xml @@ -22,7 +22,7 @@ </annotations> <before> <createData entity="Simple_US_Customer" stepKey="customer"/> - <actionGroup ref="LoginToStorefrontActionGroup" stepKey="signThirdSimpleUsCustomer"> + <actionGroup ref="LoginToStorefrontActionGroup" stepKey="loginToStorefront"> <argument name="Customer" value="$$customer$$"/> </actionGroup> <executeJS function="return window.location.host" stepKey="hostname"/> From 4ea104e81f0351e820f0464af5d3caa656cd026a Mon Sep 17 00:00:00 2001 From: Sachin Admane <sadmane@magento.com> Date: Fri, 29 Mar 2019 14:10:21 -0500 Subject: [PATCH 170/773] MC-15570: Customer cart changes. --- .../Catalog/view/frontend/templates/product/view/form.phtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/view/frontend/templates/product/view/form.phtml b/app/code/Magento/Catalog/view/frontend/templates/product/view/form.phtml index 28656438308bb..b6091f13af191 100644 --- a/app/code/Magento/Catalog/view/frontend/templates/product/view/form.phtml +++ b/app/code/Magento/Catalog/view/frontend/templates/product/view/form.phtml @@ -22,7 +22,7 @@ <input type="hidden" name="product" value="<?= /* @escapeNotVerified */ $_product->getId() ?>" /> <input type="hidden" name="selected_configurable_option" value="" /> <input type="hidden" name="related_product" id="related-products-field" value="" /> - <input type="hidden" name="item" value="<?= $block->escapeHtml($block->getRequest()->getParam('id')) ?>" /> + <input type="hidden" name="item" value="<?= $block->escapeHtmlAttr($block->getRequest()->getParam('id')) ?>" /> <?= $block->getBlockHtml('formkey') ?> <?= $block->getChildHtml('form_top') ?> <?php if (!$block->hasOptions()):?> From da48b9555df9cd080deb616ebbe717c4522e1151 Mon Sep 17 00:00:00 2001 From: Hwashiang Yu <hwyu@adobe.com> Date: Fri, 29 Mar 2019 14:36:07 -0500 Subject: [PATCH 171/773] MC-13896: User Role Template Update - Added descriptions to method documentation - Update unit tests to reflect changes to param calls - Refactored getUsers method to reduce cyclical complexity --- .../Magento/User/Block/Role/Grid/User.php | 61 ++++++++++++++----- .../User/Block/User/Edit/Tab/Roles.php | 12 ++++ .../Test/Unit/Block/Role/Grid/UserTest.php | 3 - 3 files changed, 57 insertions(+), 19 deletions(-) diff --git a/app/code/Magento/User/Block/Role/Grid/User.php b/app/code/Magento/User/Block/Role/Grid/User.php index ce9bc3f6749b3..02a1e1fba0178 100644 --- a/app/code/Magento/User/Block/Role/Grid/User.php +++ b/app/code/Magento/User/Block/Role/Grid/User.php @@ -85,6 +85,8 @@ protected function _construct() } /** + * Adds column filter to collection + * * @param Column $column * @return $this */ @@ -109,6 +111,8 @@ protected function _addColumnFilterToCollection($column) } /** + * Prepares collection + * * @return $this */ protected function _prepareCollection() @@ -121,6 +125,8 @@ protected function _prepareCollection() } /** + * Prepares columns + * * @return $this */ protected function _prepareColumns() @@ -177,6 +183,8 @@ protected function _prepareColumns() } /** + * Gets grid url + * * @return string */ public function getGridUrl() @@ -186,6 +194,34 @@ public function getGridUrl() } /** + * Gets role ID + * + * @return string + */ + public function getRoleId() + { + $roleId = $this->getRequest()->getParam('rid'); + if ($roleId <= 0) { + $roleId = $this->_coreRegistry->registry('RID'); + } + return $roleId; + } + + /** + * Gets JSON string + * + * @param string $input + * @return string + */ + public function getJSONString($input) + { + $output = json_decode($input); + return $output ? $this->_jsonEncoder->encode($output) : '{}'; + } + + /** + * Gets users + * * @param bool $json * @return string|array */ @@ -194,15 +230,11 @@ public function getUsers($json = false) $inRoleUser = $this->getRequest()->getParam('in_role_user'); if ($inRoleUser) { if ($json) { - $result = json_decode($inRoleUser); - return $result ? $this->_jsonEncoder->encode($result) : '{}'; + return $this->getJSONString($inRoleUser); } return $this->escapeJs($this->escapeHtml($inRoleUser)); } - $roleId = $this->getRequest()->getParam('rid'); - if ($roleId <= 0) { - $roleId = $this->_coreRegistry->registry('RID'); - } + $roleId = $this->getRoleId(); $users = $this->getUsersFormData(); if (false === $users) { $users = $this->_roleFactory->create()->setId($roleId)->getRoleUsers(); @@ -210,20 +242,17 @@ public function getUsers($json = false) if (sizeof($users) > 0) { if ($json) { $jsonUsers = []; - foreach ($users as $usrid) { - $jsonUsers[$usrid] = 0; + foreach ($users as $userid) { + $jsonUsers[$userid] = 0; } return $this->_jsonEncoder->encode((object)$jsonUsers); - } else { - return array_values($users); - } - } else { - if ($json) { - return '{}'; - } else { - return []; } + return array_values($users); + } + if ($json) { + return '{}'; } + return []; } /** diff --git a/app/code/Magento/User/Block/User/Edit/Tab/Roles.php b/app/code/Magento/User/Block/User/Edit/Tab/Roles.php index 7f57bd4fa0227..96f45c53e96c1 100644 --- a/app/code/Magento/User/Block/User/Edit/Tab/Roles.php +++ b/app/code/Magento/User/Block/User/Edit/Tab/Roles.php @@ -8,6 +8,8 @@ use Magento\Backend\Block\Widget\Grid\Column; /** + * Roles grid + * * @api * @since 100.0.2 */ @@ -68,6 +70,8 @@ protected function _construct() } /** + * Adds column filter to collection + * * @param Column $column * @return $this */ @@ -92,6 +96,8 @@ protected function _addColumnFilterToCollection($column) } /** + * Prepares collection + * * @return $this */ protected function _prepareCollection() @@ -103,6 +109,8 @@ protected function _prepareCollection() } /** + * Prepares columns + * * @return $this */ protected function _prepareColumns() @@ -126,6 +134,8 @@ protected function _prepareColumns() } /** + * Get grid url + * * @return string */ public function getGridUrl() @@ -135,6 +145,8 @@ public function getGridUrl() } /** + * Gets selected roles + * * @param bool $json * @return array|string */ diff --git a/app/code/Magento/User/Test/Unit/Block/Role/Grid/UserTest.php b/app/code/Magento/User/Test/Unit/Block/Role/Grid/UserTest.php index 0700046fd2d58..defdc2b344865 100644 --- a/app/code/Magento/User/Test/Unit/Block/Role/Grid/UserTest.php +++ b/app/code/Magento/User/Test/Unit/Block/Role/Grid/UserTest.php @@ -131,7 +131,6 @@ public function testGetUsersPositiveNumberOfRolesAndJsonFalse() $this->requestInterfaceMock->expects($this->at(0))->method('getParam')->willReturn(""); $this->requestInterfaceMock->expects($this->at(1))->method('getParam')->willReturn($roleId); - $this->requestInterfaceMock->expects($this->at(2))->method('getParam')->willReturn($roleId); $this->registryMock->expects($this->once()) ->method('registry') @@ -158,7 +157,6 @@ public function testGetUsersPositiveNumberOfRolesAndJsonTrue() $this->requestInterfaceMock->expects($this->at(0))->method('getParam')->willReturn(""); $this->requestInterfaceMock->expects($this->at(1))->method('getParam')->willReturn($roleId); - $this->requestInterfaceMock->expects($this->at(2))->method('getParam')->willReturn($roleId); $this->registryMock->expects($this->once()) ->method('registry') @@ -183,7 +181,6 @@ public function testGetUsersNoRolesAndJsonFalse() $this->requestInterfaceMock->expects($this->at(0))->method('getParam')->willReturn(""); $this->requestInterfaceMock->expects($this->at(1))->method('getParam')->willReturn($roleId); - $this->requestInterfaceMock->expects($this->at(2))->method('getParam')->willReturn($roleId); $this->registryMock->expects($this->once()) ->method('registry') From 6fdb9e6d81ac2a29cdc4647bf3974a44b36974eb Mon Sep 17 00:00:00 2001 From: Hwashiang Yu <hwyu@adobe.com> Date: Fri, 29 Mar 2019 15:53:11 -0500 Subject: [PATCH 172/773] MC-13896: User Role Template Update - Changed getRoleId and getJSONString to private method --- .../Magento/User/Block/Role/Grid/User.php | 53 ++++++++++--------- 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/app/code/Magento/User/Block/Role/Grid/User.php b/app/code/Magento/User/Block/Role/Grid/User.php index 02a1e1fba0178..3d7613066d2b3 100644 --- a/app/code/Magento/User/Block/Role/Grid/User.php +++ b/app/code/Magento/User/Block/Role/Grid/User.php @@ -193,32 +193,6 @@ public function getGridUrl() return $this->getUrl('*/*/editrolegrid', ['rid' => $roleId]); } - /** - * Gets role ID - * - * @return string - */ - public function getRoleId() - { - $roleId = $this->getRequest()->getParam('rid'); - if ($roleId <= 0) { - $roleId = $this->_coreRegistry->registry('RID'); - } - return $roleId; - } - - /** - * Gets JSON string - * - * @param string $input - * @return string - */ - public function getJSONString($input) - { - $output = json_decode($input); - return $output ? $this->_jsonEncoder->encode($output) : '{}'; - } - /** * Gets users * @@ -288,4 +262,31 @@ protected function restoreUsersFormData() return false; } + + /** + * Gets role ID + * + * @return string + */ + private function getRoleId() + { + $roleId = $this->getRequest()->getParam('rid'); + if ($roleId <= 0) { + $roleId = $this->_coreRegistry->registry('RID'); + } + return $roleId; + } + + /** + * Gets JSON string + * + * @param string $input + * @return string + */ + private function getJSONString($input) + { + $output = json_decode($input); + return $output ? $this->_jsonEncoder->encode($output) : '{}'; + } + } From 82467ce69f93becfd55f954276a6ccaf0c864589 Mon Sep 17 00:00:00 2001 From: Andrew Molina <amolina@adobe.com> Date: Fri, 29 Mar 2019 16:00:08 -0500 Subject: [PATCH 173/773] MC-13954: Update Product Import Temp Directory --- .../Magento/CatalogImportExport/Model/Import/Uploader.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Uploader.php b/app/code/Magento/CatalogImportExport/Model/Import/Uploader.php index 47bdfe51475a3..e4cf7e08f2e51 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Uploader.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Uploader.php @@ -176,10 +176,9 @@ public function move($fileName, $renameFileOff = false) $url = str_replace($matches[0], '', $fileName); $driver = ($matches[0] === $this->httpScheme) ? DriverPool::HTTP : DriverPool::HTTPS; $tmpFilePath = $this->downloadFileFromUrl($url, $driver); - } - else { + } else { $tmpDir = $this->getTmpDir() ? ($this->getTmpDir() . '/') : ''; - $tmpFilePath = $this->_directory->getRelativePath( $tmpDir . $fileName); + $tmpFilePath = $this->_directory->getRelativePath($tmpDir . $fileName); } $this->_setUploadFile($tmpFilePath); @@ -215,9 +214,10 @@ private function downloadFileFromUrl($url, $driver) } $tmpFileName = str_replace(".$fileExtension", '', $fileName); + $tmpFileName .= '_' . $this->random->getRandomString(16); $tmpFileName .= $fileExtension ? ".$fileExtension" : ''; - $tmpFilePath = $this->_directory->getRelativePath( $this->downloadDir . '/' . $tmpFileName); + $tmpFilePath = $this->_directory->getRelativePath($this->downloadDir . '/' . $tmpFileName); $this->_directory->writeFile( $tmpFilePath, From 7efc8f0ab463f64f86afcfdb1764b72274b378cb Mon Sep 17 00:00:00 2001 From: Andrew Molina <amolina@adobe.com> Date: Fri, 29 Mar 2019 16:06:14 -0500 Subject: [PATCH 174/773] MC-13954: Update Product Import Temp Directory --- app/code/Magento/CatalogImportExport/Model/Import/Uploader.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Uploader.php b/app/code/Magento/CatalogImportExport/Model/Import/Uploader.php index e4cf7e08f2e51..ec9c07e6bd617 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Uploader.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Uploader.php @@ -214,7 +214,6 @@ private function downloadFileFromUrl($url, $driver) } $tmpFileName = str_replace(".$fileExtension", '', $fileName); - $tmpFileName .= '_' . $this->random->getRandomString(16); $tmpFileName .= $fileExtension ? ".$fileExtension" : ''; $tmpFilePath = $this->_directory->getRelativePath($this->downloadDir . '/' . $tmpFileName); From d25f6b8bb606216f8335d9bfd73aef77efe079c6 Mon Sep 17 00:00:00 2001 From: David Haecker <dhaecker@magento.com> Date: Fri, 29 Mar 2019 16:52:03 -0500 Subject: [PATCH 175/773] MC-5858: HTTPS redirecting problem on storefront - Updating MFTF tests --- ...rifySecureURLRedirectMultishippingTest.xml | 2 +- ...tVerifySecureURLRedirectPersistentTest.xml | 43 ------------------- 2 files changed, 1 insertion(+), 44 deletions(-) delete mode 100644 app/code/Magento/Persistent/Test/Mftf/Test/StorefrontVerifySecureURLRedirectPersistentTest.xml diff --git a/app/code/Magento/Multishipping/Test/Mftf/Test/StorefrontVerifySecureURLRedirectMultishippingTest.xml b/app/code/Magento/Multishipping/Test/Mftf/Test/StorefrontVerifySecureURLRedirectMultishippingTest.xml index 60b09e841a864..085a710f2671c 100644 --- a/app/code/Magento/Multishipping/Test/Mftf/Test/StorefrontVerifySecureURLRedirectMultishippingTest.xml +++ b/app/code/Magento/Multishipping/Test/Mftf/Test/StorefrontVerifySecureURLRedirectMultishippingTest.xml @@ -9,7 +9,7 @@ <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="StorefrontVerifySecureURLRedirectMultishipping"> - <!--todo MC-5858: can't get to /multishipping/checkout & some sub pages don't redirect to https--> + <!--todo MC-5858: some urls don't redirect to https--> <annotations> <features value="Multishipping"/> <stories value="Storefront Secure URLs"/> diff --git a/app/code/Magento/Persistent/Test/Mftf/Test/StorefrontVerifySecureURLRedirectPersistentTest.xml b/app/code/Magento/Persistent/Test/Mftf/Test/StorefrontVerifySecureURLRedirectPersistentTest.xml deleted file mode 100644 index e879824a6f5cb..0000000000000 --- a/app/code/Magento/Persistent/Test/Mftf/Test/StorefrontVerifySecureURLRedirectPersistentTest.xml +++ /dev/null @@ -1,43 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> - -<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> - <test name="StorefrontVerifySecureURLRedirectPersistent"> - <!--todo MC-5858: can't figure out how to make this work--> - <annotations> - <features value="Persistent"/> - <stories value="Storefront Secure URLs"/> - <title value="Verify Secure URLs For Storefront Persistent Pages"/> - <description value="Verify that the Secure URL configuration applies to the Persistent pages on the Storefront"/> - <severity value="MAJOR"/> - <testCaseId value="MC-15617"/> - <group value="persistent"/> - <group value="configuration"/> - <group value="secure_storefront_url"/> - </annotations> - <before> - <createData entity="Simple_US_Customer" stepKey="customer"/> - <actionGroup ref="LoginToStorefrontActionGroup" stepKey="loginToStorefront"> - <argument name="Customer" value="$$customer$$"/> - </actionGroup> - <executeJS function="return window.location.host" stepKey="hostname"/> - <magentoCLI command="config:set web/secure/base_url https://{$hostname}/" stepKey="setSecureBaseURL"/> - <magentoCLI command="config:set web/secure/use_in_frontend 1" stepKey="useSecureURLsOnStorefront"/> - <magentoCLI command="cache:flush" stepKey="flushCache"/> - </before> - <after> - <magentoCLI command="config:set web/secure/use_in_frontend 0" stepKey="dontUseSecureURLsOnStorefront"/> - <magentoCLI command="cache:flush" stepKey="flushCache"/> - <deleteData createDataKey="customer" stepKey="deleteCustomer"/> - </after> - <executeJS function="return window.location.host" stepKey="hostname"/> - <amOnUrl url="http://{$hostname}/persistent/index/saveMethod" stepKey="goToUnsecurePersistentIndexSaveMethodURL"/> - <seeCurrentUrlEquals url="https://{$hostname}/persistent/index/saveMethod" stepKey="seeSecurePersistentIndexSaveMethodURL"/> - </test> -</tests> From 2e5377881d888b665810f8a44bf9c410c2130cce Mon Sep 17 00:00:00 2001 From: Viktor Sevch <svitja@ukr.net> Date: Sun, 31 Mar 2019 15:02:25 +0300 Subject: [PATCH 176/773] MC-5864: incorrect rendering of a rss feed --- .../Sales/Block/Order/Info/Buttons/Rss.php | 18 +++- .../Magento/Sales/Model/Rss/OrderStatus.php | 48 ++++++++-- .../Magento/Sales/Model/Rss/Signature.php | 74 ++++++++++++++++ .../Unit/Block/Order/Info/Buttons/RssTest.php | 23 +++-- .../Test/Unit/Model/Rss/OrderStatusTest.php | 42 ++++++--- .../Test/Unit/Model/Rss/SignatureTest.php | 88 +++++++++++++++++++ 6 files changed, 269 insertions(+), 24 deletions(-) create mode 100644 app/code/Magento/Sales/Model/Rss/Signature.php create mode 100644 app/code/Magento/Sales/Test/Unit/Model/Rss/SignatureTest.php diff --git a/app/code/Magento/Sales/Block/Order/Info/Buttons/Rss.php b/app/code/Magento/Sales/Block/Order/Info/Buttons/Rss.php index 626dcf2a5a474..689d02c8eefe2 100644 --- a/app/code/Magento/Sales/Block/Order/Info/Buttons/Rss.php +++ b/app/code/Magento/Sales/Block/Order/Info/Buttons/Rss.php @@ -5,6 +5,9 @@ */ namespace Magento\Sales\Block\Order\Info\Buttons; +use Magento\Framework\App\ObjectManager; +use Magento\Sales\Model\Rss\Signature; + /** * Block of links in Order view page * @@ -28,20 +31,29 @@ class Rss extends \Magento\Framework\View\Element\Template */ protected $rssUrlBuilder; + /** + * @var Signature + */ + private $signature; + /** * @param \Magento\Framework\View\Element\Template\Context $context * @param \Magento\Sales\Model\OrderFactory $orderFactory * @param \Magento\Framework\App\Rss\UrlBuilderInterface $rssUrlBuilder * @param array $data + * @param Signature|null $signature */ public function __construct( \Magento\Framework\View\Element\Template\Context $context, \Magento\Sales\Model\OrderFactory $orderFactory, \Magento\Framework\App\Rss\UrlBuilderInterface $rssUrlBuilder, - array $data = [] + array $data = [], + Signature $signature = null ) { $this->orderFactory = $orderFactory; $this->rssUrlBuilder = $rssUrlBuilder; + $this->signature = $signature ?: ObjectManager::getInstance()->get(Signature::class); + parent::__construct($context, $data); } @@ -103,10 +115,12 @@ protected function getUrlKey($order) protected function getLinkParams() { $order = $this->orderFactory->create()->load($this->_request->getParam('order_id')); + $data = $this->getUrlKey($order); + return [ 'type' => 'order_status', '_secure' => true, - '_query' => ['data' => $this->getUrlKey($order)] + '_query' => ['data' => $data, 'signature' => $this->signature->signData($data)], ]; } } diff --git a/app/code/Magento/Sales/Model/Rss/OrderStatus.php b/app/code/Magento/Sales/Model/Rss/OrderStatus.php index 0da218a316117..c3fda60ba4e79 100644 --- a/app/code/Magento/Sales/Model/Rss/OrderStatus.php +++ b/app/code/Magento/Sales/Model/Rss/OrderStatus.php @@ -6,10 +6,10 @@ namespace Magento\Sales\Model\Rss; use Magento\Framework\App\Rss\DataProviderInterface; +use Magento\Framework\App\ObjectManager; /** - * Class OrderStatus - * @package Magento\Sales\Model\Rss + * Rss renderer for order statuses. */ class OrderStatus implements DataProviderInterface { @@ -55,6 +55,11 @@ class OrderStatus implements DataProviderInterface */ protected $orderFactory; + /** + * @var Signature + */ + private $signature; + /** * @param \Magento\Framework\ObjectManagerInterface $objectManager * @param \Magento\Framework\UrlInterface $urlBuilder @@ -63,6 +68,7 @@ class OrderStatus implements DataProviderInterface * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate * @param \Magento\Sales\Model\OrderFactory $orderFactory * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig + * @param Signature|null $signature */ public function __construct( \Magento\Framework\ObjectManagerInterface $objectManager, @@ -71,7 +77,8 @@ public function __construct( \Magento\Sales\Model\ResourceModel\Order\Rss\OrderStatusFactory $orderResourceFactory, \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate, \Magento\Sales\Model\OrderFactory $orderFactory, - \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig + \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig, + Signature $signature = null ) { $this->objectManager = $objectManager; $this->urlBuilder = $urlBuilder; @@ -80,6 +87,7 @@ public function __construct( $this->localeDate = $localeDate; $this->orderFactory = $orderFactory; $this->config = $scopeConfig; + $this->signature = $signature ?: ObjectManager::getInstance()->get(Signature::class); } /** @@ -96,6 +104,8 @@ public function isAllowed() } /** + * Get rss data. + * * @return array */ public function getRssData() @@ -108,6 +118,8 @@ public function getRssData() } /** + * Get cache key. + * * @return string */ public function getCacheKey() @@ -121,6 +133,8 @@ public function getCacheKey() } /** + * Get cache lifetime. + * * @return int */ public function getCacheLifetime() @@ -129,6 +143,8 @@ public function getCacheLifetime() } /** + * Get order. + * * @return \Magento\Sales\Model\Order */ protected function getOrder() @@ -137,8 +153,11 @@ protected function getOrder() return $this->order; } - $data = null; - $json = base64_decode((string)$this->request->getParam('data')); + $data = (string)$this->request->getParam('data'); + if ((string)$this->request->getParam('signature') !== $this->signature->signData($data)) { + return null; + } + $json = base64_decode($data); if ($json) { $data = json_decode($json, true); } @@ -154,7 +173,7 @@ protected function getOrder() $order = $this->orderFactory->create(); $order->load($data['order_id']); - if ($order->getIncrementId() !== $data['increment_id'] || $order->getCustomerId() !== $data['customer_id']) { + if (!$this->isValidOrderData($order, $data)) { $order = null; } $this->order = $order; @@ -162,6 +181,19 @@ protected function getOrder() return $this->order; } + /** + * Check if selected order data correspond incoming data. + * + * @param \Magento\Sales\Model\Order $order + * @param array $data + * @return bool + */ + private function isValidOrderData(\Magento\Sales\Model\Order $order, array $data): bool + { + return !($order->getIncrementId() !== $data['increment_id'] + || $order->getCustomerId() !== $data['customer_id']); + } + /** * Get RSS feed items * @@ -218,6 +250,8 @@ protected function getHeader() } /** + * Get feeds. + * * @return array */ public function getFeeds() @@ -226,7 +260,7 @@ public function getFeeds() } /** - * {@inheritdoc} + * @inheritdoc */ public function isAuthRequired() { diff --git a/app/code/Magento/Sales/Model/Rss/Signature.php b/app/code/Magento/Sales/Model/Rss/Signature.php new file mode 100644 index 0000000000000..f6536bcc2ae39 --- /dev/null +++ b/app/code/Magento/Sales/Model/Rss/Signature.php @@ -0,0 +1,74 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +declare(strict_types=1); + +namespace Magento\Sales\Model\Rss; + +use Magento\Framework\App\ObjectManager; +use Magento\Framework\Config\ConfigOptionsListConstants; +use Magento\Framework\App\DeploymentConfig; + +/** + * Class for generating signature. + */ +class Signature extends \Magento\Framework\App\Helper\AbstractHelper +{ + /** + * Version of encryption key. + * + * @var int + */ + private $keyVersion; + + /** + * Array of encryption keys. + * + * @var string[] + */ + private $keys = []; + + /** + * @var mixed + */ + private $deploymentConfig; + + /** + * @inheritdoc + */ + public function __construct( + \Magento\Framework\App\DeploymentConfig $deploymentConfig = null + ) { + $this->deploymentConfig = $deploymentConfig ?: ObjectManager::getInstance()->get(DeploymentConfig::class); + // load all possible keys + $this->keys = preg_split( + '/\s+/s', + (string)$this->deploymentConfig->get(ConfigOptionsListConstants::CONFIG_PATH_CRYPT_KEY) + ); + $this->keyVersion = count($this->keys) - 1; + } + + /** + * Get secret key. + * + * @return string + */ + private function getSecretKey(): string + { + return (string)$this->keys[$this->keyVersion]; + } + + /** + * Sign data. + * + * @param string $data + * @return string + */ + public function signData(string $data): string + { + return hash_hmac('sha256', $data, pack('H*', $this->getSecretKey())); + } +} diff --git a/app/code/Magento/Sales/Test/Unit/Block/Order/Info/Buttons/RssTest.php b/app/code/Magento/Sales/Test/Unit/Block/Order/Info/Buttons/RssTest.php index d36952e6aeee1..965a80ef189f6 100644 --- a/app/code/Magento/Sales/Test/Unit/Block/Order/Info/Buttons/RssTest.php +++ b/app/code/Magento/Sales/Test/Unit/Block/Order/Info/Buttons/RssTest.php @@ -6,6 +6,7 @@ namespace Magento\Sales\Test\Unit\Block\Order\Info\Buttons; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +use Magento\Sales\Model\Rss\Signature; /** * Class RssTest @@ -43,6 +44,14 @@ class RssTest extends \PHPUnit\Framework\TestCase */ protected $scopeConfigInterface; + /** + * @var \PHPUnit_Framework_MockObject_MockObject|Signature + */ + private $signature; + + /** + * @inheritdoc + */ protected function setUp() { $this->context = $this->createMock(\Magento\Framework\View\Element\Template\Context::class); @@ -50,6 +59,7 @@ protected function setUp() $this->urlBuilderInterface = $this->createMock(\Magento\Framework\App\Rss\UrlBuilderInterface::class); $this->scopeConfigInterface = $this->createMock(\Magento\Framework\App\Config\ScopeConfigInterface::class); $request = $this->createMock(\Magento\Framework\App\RequestInterface::class); + $this->signature = $this->createMock(Signature::class); $this->objectManagerHelper = new ObjectManagerHelper($this); $this->rss = $this->objectManagerHelper->getObject( @@ -58,7 +68,8 @@ protected function setUp() 'request' => $request, 'orderFactory' => $this->orderFactory, 'rssUrlBuilder' => $this->urlBuilderInterface, - 'scopeConfig' => $this->scopeConfigInterface + 'scopeConfig' => $this->scopeConfigInterface, + 'signature' => $this->signature, ] ); } @@ -75,15 +86,17 @@ public function testGetLink() $order->expects($this->once())->method('getIncrementId')->will($this->returnValue('100000001')); $this->orderFactory->expects($this->once())->method('create')->will($this->returnValue($order)); - $data = base64_encode(json_encode(['order_id' => 1, 'increment_id' => '100000001', 'customer_id' => 1])); - $link = 'http://magento.com/rss/feed/index/type/order_status?data=' . $data; + $signature = '651932dfc862406b72628d95623bae5ea18242be757b3493b337942d61f834be'; + $this->signature->expects($this->once())->method('signData')->willReturn($signature); + $link = 'http://magento.com/rss/feed/index/type/order_status?data=' . $data .'&signature='.$signature; $this->urlBuilderInterface->expects($this->once())->method('getUrl') ->with([ 'type' => 'order_status', '_secure' => true, - '_query' => ['data' => $data], - ])->will($this->returnValue($link)); + '_query' => ['data' => $data, 'signature' => $signature], + ])->willReturn($link); + $this->assertEquals($link, $this->rss->getLink()); } diff --git a/app/code/Magento/Sales/Test/Unit/Model/Rss/OrderStatusTest.php b/app/code/Magento/Sales/Test/Unit/Model/Rss/OrderStatusTest.php index ce2d09c71b52e..e44c098e016b0 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Rss/OrderStatusTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Rss/OrderStatusTest.php @@ -6,6 +6,7 @@ namespace Magento\Sales\Test\Unit\Model\Rss; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +use Magento\Sales\Model\Rss\Signature; /** * Class OrderStatusTest @@ -64,6 +65,11 @@ class OrderStatusTest extends \PHPUnit\Framework\TestCase */ protected $order; + /** + * @var \PHPUnit_Framework_MockObject_MockObject|Signature + */ + private $signature; + /** * @var array */ @@ -120,6 +126,9 @@ protected function setUp() $this->order->expects($this->any())->method('getGrandTotal')->will($this->returnValue(15)); $this->order->expects($this->any())->method('load')->with(1)->will($this->returnSelf()); + $this->signature = $this->createMock(Signature::class); + $this->signature->expects($this->any())->method('signData')->willReturn('signature'); + $this->objectManagerHelper = new ObjectManagerHelper($this); $this->model = $this->objectManagerHelper->getObject( \Magento\Sales\Model\Rss\OrderStatus::class, @@ -130,7 +139,8 @@ protected function setUp() 'orderResourceFactory' => $this->orderStatusFactory, 'localeDate' => $this->timezoneInterface, 'orderFactory' => $this->orderFactory, - 'scopeConfig' => $this->scopeConfigInterface + 'scopeConfig' => $this->scopeConfigInterface, + 'signature' => $this->signature, ] ); } @@ -140,7 +150,14 @@ public function testGetRssData() $this->orderFactory->expects($this->once())->method('create')->willReturn($this->order); $requestData = base64_encode('{"order_id":1,"increment_id":"100000001","customer_id":1}'); - $this->requestInterface->expects($this->any())->method('getParam')->with('data')->willReturn($requestData); + $this->requestInterface->expects($this->any()) + ->method('getParam') + ->willReturnMap( + [ + ['data', null, $requestData], + ['signature', null, 'signature'], + ] + ); $resource = $this->getMockBuilder(\Magento\Sales\Model\ResourceModel\Order\Rss\OrderStatus::class) ->setMethods(['getAllCommentCollection']) @@ -168,15 +185,17 @@ public function testGetRssData() public function testGetRssDataWithError() { $this->orderFactory->expects($this->once())->method('create')->willReturn($this->order); - $requestData = base64_encode('{"order_id":"1","increment_id":true,"customer_id":true}'); - - $this->requestInterface->expects($this->any())->method('getParam')->with('data')->willReturn($requestData); - + $this->requestInterface->expects($this->any()) + ->method('getParam') + ->willReturnMap( + [ + ['data', null, $requestData], + ['signature', null, 'signature'], + ] + ); $this->orderStatusFactory->expects($this->never())->method('create'); - $this->urlInterface->expects($this->never())->method('getUrl'); - $this->assertEquals($this->feedData, $this->model->getRssData()); } @@ -196,8 +215,11 @@ public function testIsAllowed() public function testGetCacheKey($requestData, $result) { $this->requestInterface->expects($this->any())->method('getParam') - ->with('data') - ->will($this->returnValue($requestData)); + ->willReturnMap([ + ['data', null, $requestData], + ['signature', null, 'signature'], + ]); + $this->orderFactory->expects($this->once())->method('create')->will($this->returnValue($this->order)); $this->assertEquals('rss_order_status_data_' . $result, $this->model->getCacheKey()); } diff --git a/app/code/Magento/Sales/Test/Unit/Model/Rss/SignatureTest.php b/app/code/Magento/Sales/Test/Unit/Model/Rss/SignatureTest.php new file mode 100644 index 0000000000000..f7ced8110955f --- /dev/null +++ b/app/code/Magento/Sales/Test/Unit/Model/Rss/SignatureTest.php @@ -0,0 +1,88 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +declare(strict_types=1); + +namespace Magento\Sales\Test\Unit\Model\Rss; + +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +use Magento\Sales\Model\Rss\Signature; + +/** + * Test signature class. + */ +class SignatureTest extends \PHPUnit\Framework\TestCase +{ + /** + * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Framework\App\DeploymentConfig + */ + private $deploymentConfigMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject|Signature + */ + private $signatureMock; + + /** + * @var ObjectManagerHelper + */ + protected $objectManagerHelper; + + /** + * @var \Magento\Sales\Model\Rss\Signature + */ + private $model; + + /** + * @inheritdoc + */ + protected function setUp() + { + $this->deploymentConfigMock = $this->getMockBuilder(\Magento\Framework\App\DeploymentConfig::class) + ->disableOriginalConstructor() + ->getMock(); + $this->deploymentConfigMock->expects($this->any()) + ->method('get') + ->with('crypt/key') + ->willReturn('1234567890abc'); + $this->signatureMock = $this->createMock(Signature::class); + + $this->objectManagerHelper = new ObjectManagerHelper($this); + $this->model = $this->objectManagerHelper->getObject( + Signature::class, + [ + 'deploymentConfig' => $this->deploymentConfigMock, + ] + ); + } + + /** + * Test sign data. + * + * @param string $data + * @param string $expected + * @return void + * @dataProvider checkSignatureDataProvider + */ + public function testSignData(string $data, string $expected): void + { + $this->signatureMock->expects($this->any())->method('signData')->willReturn($expected); + $this->assertEquals($expected, $this->model->signData($data)); + } + + /** + * @return array + */ + public function checkSignatureDataProvider(): array + { + return [ + [ + 'eyJvcmRlcl9pZCI6IjEiLCJjdXN0b21lcl9pZCI6IjEiLCJpbmNyZW1lbnRfaWQiOiIwMDAwMDAwMDEifQ==', + '651932dfc862406b72628d95623bae5ea18242be757b3493b337942d61f834be', + ], + ]; + } +} From bd7e4ccf7eee4fc6b4b50f8a3632bcf11ec8350f Mon Sep 17 00:00:00 2001 From: Stas Kozar <stas.kozar@transoftgroup.com> Date: Mon, 1 Apr 2019 08:24:36 +0300 Subject: [PATCH 177/773] MC-11054: Remove possibility to upload swf files through wysiwyg editor --- app/code/Magento/Cms/etc/di.xml | 1 - .../Cms/Model/Wysiwyg/Images/StorageTest.php | 37 ++++++++++++++---- .../testsuite/Magento/Cms/_files/test.swf | Bin 0 -> 734 bytes .../testsuite/Magento/Cms/_files/text.txt | 1 + 4 files changed, 31 insertions(+), 8 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/Cms/_files/test.swf create mode 100644 dev/tests/integration/testsuite/Magento/Cms/_files/text.txt diff --git a/app/code/Magento/Cms/etc/di.xml b/app/code/Magento/Cms/etc/di.xml index b6e13c63302cd..66b0edf6e1eac 100644 --- a/app/code/Magento/Cms/etc/di.xml +++ b/app/code/Magento/Cms/etc/di.xml @@ -47,7 +47,6 @@ </item> <item name="media_allowed" xsi:type="array"> <item name="flv" xsi:type="string">video/x-flv</item> - <item name="swf" xsi:type="string">application/x-shockwave-flash</item> <item name="avi" xsi:type="string">video/x-msvideo</item> <item name="mov" xsi:type="string">video/x-sgi-movie</item> <item name="rm" xsi:type="string">application/vnd.rn-realmedia</item> diff --git a/dev/tests/integration/testsuite/Magento/Cms/Model/Wysiwyg/Images/StorageTest.php b/dev/tests/integration/testsuite/Magento/Cms/Model/Wysiwyg/Images/StorageTest.php index e25934fb25ee1..423f521a63548 100644 --- a/dev/tests/integration/testsuite/Magento/Cms/Model/Wysiwyg/Images/StorageTest.php +++ b/dev/tests/integration/testsuite/Magento/Cms/Model/Wysiwyg/Images/StorageTest.php @@ -128,30 +128,53 @@ public function testUploadFile(): void } /** + * @param string $fileName + * @param string $fileType + * @param string|null $storageType + * + * @return void + * @dataProvider testUploadFileWithWrongExtensionDataProvider * @expectedException \Magento\Framework\Exception\LocalizedException * @expectedExceptionMessage File validation failed. - * @return void */ - public function testUploadFileWithWrongExtension(): void + public function testUploadFileWithWrongExtension(string $fileName, string $fileType, ?string $storageType): void { - $fileName = 'text.txt'; $tmpDirectory = $this->filesystem->getDirectoryWrite(\Magento\Framework\App\Filesystem\DirectoryList::SYS_TMP); $filePath = $tmpDirectory->getAbsolutePath($fileName); - $file = fopen($filePath, "wb"); - fwrite($file, 'just a text'); + $fixtureDir = realpath(__DIR__ . '/../../../_files'); + copy($fixtureDir . DIRECTORY_SEPARATOR . $fileName, $filePath); $_FILES['image'] = [ 'name' => $fileName, - 'type' => 'text/plain', + 'type' => $fileType, 'tmp_name' => $filePath, 'error' => 0, 'size' => 12500, ]; - $this->storage->uploadFile(self::$_baseDir); + $this->storage->uploadFile(self::$_baseDir, $storageType); $this->assertFalse(is_file(self::$_baseDir . DIRECTORY_SEPARATOR . $fileName)); } + /** + * @return array + */ + public function testUploadFileWithWrongExtensionDataProvider(): array + { + return [ + [ + 'fileName' => 'text.txt', + 'fileType' => 'text/plain', + 'storageType' => null, + ], + [ + 'fileName' => 'test.swf', + 'fileType' => 'application/x-shockwave-flash', + 'storageType' => 'media', + ], + ]; + } + /** * @expectedException \Magento\Framework\Exception\LocalizedException * @expectedExceptionMessage File validation failed. diff --git a/dev/tests/integration/testsuite/Magento/Cms/_files/test.swf b/dev/tests/integration/testsuite/Magento/Cms/_files/test.swf new file mode 100644 index 0000000000000000000000000000000000000000..f0181cbb3e4cd8e6f080e43f575788f2a3b5a02f GIT binary patch literal 734 zcmV<40wMiFS5pZ20ssJboU349jb~usU%<e?!^q$w$N&V+OlSW8|1WZ!iGhKUq2RZ7 zdsEGX4F!L?Q<|3aH83)Ql>BEDVE}{wf~KoWeblW=tr+tC81f@7PrfO<NrB~)0&CxK z+es%FCi*c<RM#n9p40n)<?REeLW>^`3`{)?5JO-zlj^BTndQY=J}Khrvr6Y{on<|- ze(w5H`y7k7pJ#o3tnDMVllQXB>IKs_#~$ssS+zo*1E>+`#QzKeqN`5$sYf+NMcP~6 zpR@kl^5@#0<7fT(T~}>ycYmJ#Wy@c0xUTzen{9AjGJQ+&JIn7fH=Z50OrEpx+=}Nl zB`f>3&NH0D9qcss&ilHe{Z{kmtUp_q{rT<BH$W3A_WL}4y+J$H?pDrWo78z1&+mAC zr#N}G%+tQ2<5r93e!R5I>RQFIvaL*8HdQ}_x`$B%$hdIf0x(og#<8Sc@aL|5_1?W| z*Mr=x63W?m^R7f6Uv~7er|8wwx^5Re0#~s9be-tto05OwsPr2Hfq*M4BASUWE`<ML zyHxDBY4(JCm&aianc0?R9i_7a>O4K=B%NGag%91x&C{Crr6eXIH{+bjY_TQ%Eez<9 z!h6zcZu^nyD|J<Z@;;AVWaMp0VEeiF|Gt!5sh;YEyZ73Dz3(m+{OZE?+BxjLkC`m5 z1P3aMJ23G(Ff?y>y{e`Ytaw3ruMV^Ff|)#S?pe$KeVczdOaAafV1oDn_A1aW)f303 znlI+7J#uV;*#6j{l2knbt%pt5rL={5t_HJ2UWi$GF|Q=|#fE9!OixaAy<e=B+!kj0 zp@D%B7VC_vYl91)bv8RN=xZ@>pImSu)A%o|8Ut5Q0)z3Re{Bu>83bN2uvjG+Xr58} zb&G*3cLBp0Th0#+7(u;iQ=I?Y-t*5-KXqNW`AU1W&y?syqn1@W*!1olXZ2X&DaX*p Q#s*3<3=Tkh0h$*^E0yAd{Qv*} literal 0 HcmV?d00001 diff --git a/dev/tests/integration/testsuite/Magento/Cms/_files/text.txt b/dev/tests/integration/testsuite/Magento/Cms/_files/text.txt new file mode 100644 index 0000000000000..9458610c5e7cf --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Cms/_files/text.txt @@ -0,0 +1 @@ +just a text From f38364e998e8f511c5a6d4382906205f18921079 Mon Sep 17 00:00:00 2001 From: Viktor Sevch <svitja@ukr.net> Date: Mon, 1 Apr 2019 11:36:04 +0300 Subject: [PATCH 178/773] MC-5864: incorrect rendering of a rss feed --- app/code/Magento/Sales/Model/Rss/OrderStatus.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Sales/Model/Rss/OrderStatus.php b/app/code/Magento/Sales/Model/Rss/OrderStatus.php index c3fda60ba4e79..8c5cd8e13e69b 100644 --- a/app/code/Magento/Sales/Model/Rss/OrderStatus.php +++ b/app/code/Magento/Sales/Model/Rss/OrderStatus.php @@ -107,6 +107,7 @@ public function isAllowed() * Get rss data. * * @return array + * @throws \InvalidArgumentException */ public function getRssData() { From 1778d297201a361a901d672d8c830499e9abd47e Mon Sep 17 00:00:00 2001 From: Stas Kozar <stas.kozar@transoftgroup.com> Date: Mon, 1 Apr 2019 14:28:31 +0300 Subject: [PATCH 179/773] MC-15477: Incorrect rendering --- .../Test/Unit/Ui/Component/Listing/Column/PageActionsTest.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/code/Magento/Cms/Test/Unit/Ui/Component/Listing/Column/PageActionsTest.php b/app/code/Magento/Cms/Test/Unit/Ui/Component/Listing/Column/PageActionsTest.php index 9fe21256c4c4a..32bbeed0788a3 100644 --- a/app/code/Magento/Cms/Test/Unit/Ui/Component/Listing/Column/PageActionsTest.php +++ b/app/code/Magento/Cms/Test/Unit/Ui/Component/Listing/Column/PageActionsTest.php @@ -8,6 +8,9 @@ use Magento\Cms\Ui\Component\Listing\Column\PageActions; use Magento\Framework\Escaper; +/** + * Test for Magento\Cms\Ui\Component\Listing\Column\PageActions class. + */ class PageActionsTest extends \PHPUnit\Framework\TestCase { public function testPrepareItemsByPageId() From bc750a5fd47e17038274fd2a7536abc834d9ac67 Mon Sep 17 00:00:00 2001 From: OlgaVasyltsun <olga.vasyltsun@gmail.com> Date: Mon, 1 Apr 2019 14:47:30 +0300 Subject: [PATCH 180/773] MC-11052: Escaper changes --- lib/internal/Magento/Framework/Escaper.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/Escaper.php b/lib/internal/Magento/Framework/Escaper.php index 997f9c5396670..b12548f27bc8b 100644 --- a/lib/internal/Magento/Framework/Escaper.php +++ b/lib/internal/Magento/Framework/Escaper.php @@ -67,7 +67,7 @@ public function escapeHtml($data, $allowedTags = null) foreach ($data as $item) { $result[] = $this->escapeHtml($item, $allowedTags); } - } elseif (strlen($data)) { + } elseif (!empty($data)) { if (is_array($allowedTags) && !empty($allowedTags)) { $allowedTags = $this->filterProhibitedTags($allowedTags); $wrapperElementId = uniqid(); From 65a8be1275eb1480425d4f52843cf2a88e87da02 Mon Sep 17 00:00:00 2001 From: OlgaVasyltsun <olga.vasyltsun@gmail.com> Date: Mon, 1 Apr 2019 14:48:38 +0300 Subject: [PATCH 181/773] MC-11052: Escaper changes --- lib/internal/Magento/Framework/Test/Unit/EscaperTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/internal/Magento/Framework/Test/Unit/EscaperTest.php b/lib/internal/Magento/Framework/Test/Unit/EscaperTest.php index 17fcce92bc729..7b45765fdefe8 100644 --- a/lib/internal/Magento/Framework/Test/Unit/EscaperTest.php +++ b/lib/internal/Magento/Framework/Test/Unit/EscaperTest.php @@ -43,6 +43,7 @@ protected function setUp() * * @param int $codepoint Unicode codepoint in hex notation * @return string UTF-8 literal string + * @throws \Exception */ protected function codepointToUtf8($codepoint) { From a41fede69ecdddae0856c14068a8fe17ed35d625 Mon Sep 17 00:00:00 2001 From: Viktor Sevch <svitja@ukr.net> Date: Mon, 1 Apr 2019 15:51:46 +0300 Subject: [PATCH 182/773] MC-5864: incorrect rendering of a rss feed --- app/code/Magento/Sales/Model/Rss/Signature.php | 8 ++++---- .../Magento/Sales/Test/Unit/Model/Rss/SignatureTest.php | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/Sales/Model/Rss/Signature.php b/app/code/Magento/Sales/Model/Rss/Signature.php index f6536bcc2ae39..72b8f55fbdee6 100644 --- a/app/code/Magento/Sales/Model/Rss/Signature.php +++ b/app/code/Magento/Sales/Model/Rss/Signature.php @@ -15,7 +15,7 @@ /** * Class for generating signature. */ -class Signature extends \Magento\Framework\App\Helper\AbstractHelper +class Signature { /** * Version of encryption key. @@ -37,12 +37,12 @@ class Signature extends \Magento\Framework\App\Helper\AbstractHelper private $deploymentConfig; /** - * @inheritdoc + * @param \Magento\Framework\App\DeploymentConfig $deploymentConfig */ public function __construct( - \Magento\Framework\App\DeploymentConfig $deploymentConfig = null + \Magento\Framework\App\DeploymentConfig $deploymentConfig ) { - $this->deploymentConfig = $deploymentConfig ?: ObjectManager::getInstance()->get(DeploymentConfig::class); + $this->deploymentConfig = $deploymentConfig; // load all possible keys $this->keys = preg_split( '/\s+/s', diff --git a/app/code/Magento/Sales/Test/Unit/Model/Rss/SignatureTest.php b/app/code/Magento/Sales/Test/Unit/Model/Rss/SignatureTest.php index f7ced8110955f..4bdfee9f8beea 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Rss/SignatureTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Rss/SignatureTest.php @@ -29,7 +29,7 @@ class SignatureTest extends \PHPUnit\Framework\TestCase /** * @var ObjectManagerHelper */ - protected $objectManagerHelper; + private $objectManagerHelper; /** * @var \Magento\Sales\Model\Rss\Signature From eddfde66fbccedac486ba9dcc9da60b765d548e4 Mon Sep 17 00:00:00 2001 From: Viktor Sevch <svitja@ukr.net> Date: Mon, 1 Apr 2019 16:44:42 +0300 Subject: [PATCH 183/773] MC-5864: incorrect rendering of a rss feed --- app/code/Magento/Sales/Model/Rss/OrderStatus.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Sales/Model/Rss/OrderStatus.php b/app/code/Magento/Sales/Model/Rss/OrderStatus.php index 8c5cd8e13e69b..f9aabb8c81dfa 100644 --- a/app/code/Magento/Sales/Model/Rss/OrderStatus.php +++ b/app/code/Magento/Sales/Model/Rss/OrderStatus.php @@ -174,7 +174,7 @@ protected function getOrder() $order = $this->orderFactory->create(); $order->load($data['order_id']); - if (!$this->isValidOrderData($order, $data)) { + if (!$this->isOrderSuitable($order, $data)) { $order = null; } $this->order = $order; @@ -189,10 +189,9 @@ protected function getOrder() * @param array $data * @return bool */ - private function isValidOrderData(\Magento\Sales\Model\Order $order, array $data): bool + private function isOrderSuitable(\Magento\Sales\Model\Order $order, array $data): bool { - return !($order->getIncrementId() !== $data['increment_id'] - || $order->getCustomerId() !== $data['customer_id']); + return $order->getIncrementId() === $data['increment_id'] && $order->getCustomerId() === $data['customer_id']; } /** From 2e8faff1ac8e9ab5f61bfbba3c640d3814a44a63 Mon Sep 17 00:00:00 2001 From: Hwashiang Yu <hwyu@adobe.com> Date: Mon, 1 Apr 2019 10:39:26 -0500 Subject: [PATCH 184/773] MC-13896: User Role Template Update - Resolved extra emptyline to fix static test failure --- app/code/Magento/User/Block/Role/Grid/User.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/code/Magento/User/Block/Role/Grid/User.php b/app/code/Magento/User/Block/Role/Grid/User.php index 3d7613066d2b3..bb6051ff89f54 100644 --- a/app/code/Magento/User/Block/Role/Grid/User.php +++ b/app/code/Magento/User/Block/Role/Grid/User.php @@ -288,5 +288,4 @@ private function getJSONString($input) $output = json_decode($input); return $output ? $this->_jsonEncoder->encode($output) : '{}'; } - } From 70f4a583caed43f55f86ebe80c5883b19e9d80d9 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun <ogorkun@magento.com> Date: Mon, 1 Apr 2019 11:51:09 -0500 Subject: [PATCH 185/773] MC-10870: Invalid company ID in web API --- .../Webapi/Test/Unit/Controller/Rest/ParamsOverriderTest.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Webapi/Test/Unit/Controller/Rest/ParamsOverriderTest.php b/app/code/Magento/Webapi/Test/Unit/Controller/Rest/ParamsOverriderTest.php index c81351a42333d..2f909c5b7cd92 100644 --- a/app/code/Magento/Webapi/Test/Unit/Controller/Rest/ParamsOverriderTest.php +++ b/app/code/Magento/Webapi/Test/Unit/Controller/Rest/ParamsOverriderTest.php @@ -8,6 +8,7 @@ use \Magento\Authorization\Model\UserContextInterface; use Magento\Framework\Api\SimpleDataObjectConverter; +use Magento\Webapi\Controller\Rest\ParamsOverrider; use PHPUnit\Framework\MockObject\MockObject; /** @@ -56,9 +57,9 @@ function (array $array) { } ); - /** @var \Magento\Webapi\Controller\Rest\ParamsOverrider $paramsOverrider */ + /** @var ParamsOverrider $paramsOverrider */ $paramsOverrider = $objectManager->getObject( - 'Magento\Webapi\Controller\Rest\ParamsOverrider', + ParamsOverrider::class, [ 'paramOverriders' => ['%customer_id%' => $paramOverriderCustomerId ], 'dataObjectConverter' => $objectConverter From 63de7ff3f59b581352c1109837e8bf5dcc4fe577 Mon Sep 17 00:00:00 2001 From: Andrew Molina <amolina@adobe.com> Date: Mon, 1 Apr 2019 12:20:17 -0500 Subject: [PATCH 186/773] MC-13954: Update Product Import Temp Directory --- app/code/Magento/CatalogImportExport/Model/Import/Uploader.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Uploader.php b/app/code/Magento/CatalogImportExport/Model/Import/Uploader.php index ec9c07e6bd617..3cd5de35eb657 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Uploader.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Uploader.php @@ -14,6 +14,7 @@ * * @api * @since 100.0.2 + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class Uploader extends \Magento\MediaStorage\Model\File\Uploader { From 442c9dbc50897819c019eb74a32530542b1fddcb Mon Sep 17 00:00:00 2001 From: Hwashiang Yu <hwyu@adobe.com> Date: Mon, 1 Apr 2019 13:26:19 -0500 Subject: [PATCH 187/773] MC-13896: User Role Template Update - Resolved static test failures --- app/code/Magento/User/Block/Role/Grid/User.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/User/Block/Role/Grid/User.php b/app/code/Magento/User/Block/Role/Grid/User.php index bb6051ff89f54..b397c41eb84f0 100644 --- a/app/code/Magento/User/Block/Role/Grid/User.php +++ b/app/code/Magento/User/Block/Role/Grid/User.php @@ -213,7 +213,7 @@ public function getUsers($json = false) if (false === $users) { $users = $this->_roleFactory->create()->setId($roleId)->getRoleUsers(); } - if (sizeof($users) > 0) { + if (count($users) > 0) { if ($json) { $jsonUsers = []; foreach ($users as $userid) { @@ -249,6 +249,7 @@ protected function getUsersFormData() * * @return array|bool * @since 100.1.0 + * @SuppressWarnings(PHPMD.ForbiddenFunctionsSniff) */ protected function restoreUsersFormData() { From 0f6902c2e4db9630e437883efd908725ad4b4a9b Mon Sep 17 00:00:00 2001 From: Hwashiang Yu <hwyu@adobe.com> Date: Mon, 1 Apr 2019 14:46:00 -0500 Subject: [PATCH 188/773] MC-13896: User Role Template Update - Resolved static test failures due to disouraged methods --- app/code/Magento/User/Block/Role/Grid/User.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/User/Block/Role/Grid/User.php b/app/code/Magento/User/Block/Role/Grid/User.php index b397c41eb84f0..4cd73f5e0c56e 100644 --- a/app/code/Magento/User/Block/Role/Grid/User.php +++ b/app/code/Magento/User/Block/Role/Grid/User.php @@ -213,7 +213,7 @@ public function getUsers($json = false) if (false === $users) { $users = $this->_roleFactory->create()->setId($roleId)->getRoleUsers(); } - if (count($users) > 0) { + if (!empty($users)) { if ($json) { $jsonUsers = []; foreach ($users as $userid) { @@ -249,7 +249,7 @@ protected function getUsersFormData() * * @return array|bool * @since 100.1.0 - * @SuppressWarnings(PHPMD.ForbiddenFunctionsSniff) + * @SuppressWarnings(PHPMD.DiscouragedFunctionsSniff) */ protected function restoreUsersFormData() { From caa18cdfc57a5f0eac9671f4d006b900d6953eb2 Mon Sep 17 00:00:00 2001 From: Cari Spruiell <spruiell@adobe.com> Date: Mon, 1 Apr 2019 16:39:15 -0500 Subject: [PATCH 189/773] MC-5894: Gift Card Account --- .../Test/Unit/Model/AccountManagementTest.php | 6 ++--- .../Customer/Api/GroupRepositoryTest.php | 18 +------------- .../Model/ResourceModel/Db/ProfilerTest.php | 24 +++++++++++++++---- .../DB/Test/Unit/Ddl/TriggerTest.php | 3 +++ .../Mview/Test/Unit/View/ChangelogTest.php | 3 +++ .../Fixtures/ConfigurableProductsFixture.php | 2 +- .../ImagesGenerator/ImagesGenerator.php | 2 ++ .../Magento/Setup/Fixtures/OrdersFixture.php | 5 +++- .../Setup/Fixtures/Quote/QuoteGenerator.php | 3 +++ .../Test/Unit/Model/DataGeneratorTest.php | 3 +++ 10 files changed, 42 insertions(+), 27 deletions(-) diff --git a/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php b/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php index a773fc2c10932..0bf050f3923e4 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php @@ -1238,7 +1238,7 @@ public function testInitiatePasswordResetEmailReminder() $storeId = 1; - $hash = md5(uniqid(microtime() . random_int(0, PHP_INT_MAX), true)); + $hash = hash("sha256", uniqid(microtime() . random_int(0, PHP_INT_MAX), true)); $this->emailNotificationMock->expects($this->once()) ->method('passwordReminder') @@ -1262,7 +1262,7 @@ public function testInitiatePasswordResetEmailReset() $templateIdentifier = 'Template Identifier'; $sender = 'Sender'; - $hash = md5(uniqid(microtime() . random_int(0, PHP_INT_MAX), true)); + $hash = hash("sha256", uniqid(microtime() . random_int(0, PHP_INT_MAX), true)); $this->emailNotificationMock->expects($this->once()) ->method('passwordResetConfirmation') @@ -1286,7 +1286,7 @@ public function testInitiatePasswordResetNoTemplate() $templateIdentifier = 'Template Identifier'; $sender = 'Sender'; - $hash = md5(uniqid(microtime() . random_int(0, PHP_INT_MAX), true)); + $hash = hash("sha256", uniqid(microtime() . random_int(0, PHP_INT_MAX), true)); $this->prepareInitiatePasswordReset($email, $templateIdentifier, $sender, $storeId, $customerId, $hash); diff --git a/dev/tests/api-functional/testsuite/Magento/Customer/Api/GroupRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Customer/Api/GroupRepositoryTest.php index 4ed32258deecf..920f1f2c428a5 100644 --- a/dev/tests/api-functional/testsuite/Magento/Customer/Api/GroupRepositoryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Customer/Api/GroupRepositoryTest.php @@ -55,22 +55,6 @@ public function setUp() $this->customerGroupFactory = $objectManager->create(\Magento\Customer\Api\Data\GroupInterfaceFactory::class); } - /** - * Execute per test cleanup. - */ - public function tearDown() - { - parent::tearDown(); - } - - /** - * Cleaning up the extra groups that might have been created as part of the testing. - */ - public static function tearDownAfterClass() - { - parent::tearDownAfterClass(); - } - /** * Verify the retrieval of a customer group by Id. * @@ -874,7 +858,7 @@ public function testSearchGroupsDataProvider() return [ ['tax_class_id', 3, []], ['tax_class_id', 0, null], - ['code', md5(random_int(0, 10000000000) . time()), null], + ['code', hash("sha256", random_int(0, 10000000000) . time()), null], [ 'id', 0, diff --git a/dev/tests/integration/testsuite/Magento/Framework/Model/ResourceModel/Db/ProfilerTest.php b/dev/tests/integration/testsuite/Magento/Framework/Model/ResourceModel/Db/ProfilerTest.php index 5046c3328030c..d428552ec5e88 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/Model/ResourceModel/Db/ProfilerTest.php +++ b/dev/tests/integration/testsuite/Magento/Framework/Model/ResourceModel/Db/ProfilerTest.php @@ -9,6 +9,9 @@ use Magento\Framework\Config\ConfigOptionsListConstants; +/** + * Class ProfilerTest + */ class ProfilerTest extends \PHPUnit\Framework\TestCase { /** @@ -21,17 +24,27 @@ class ProfilerTest extends \PHPUnit\Framework\TestCase */ protected static $_testResourceName = 'testtest_0000_setup'; + /** + * @inheritdoc + * + * phpcs:disable Magento2.Functions.StaticFunction + */ public static function setUpBeforeClass() { self::$_testResourceName = 'testtest_' . random_int(1000, 9999) . '_setup'; \Magento\Framework\Profiler::enable(); - } + } // phpcs:enable + /** + * @inheritdoc + * + * phpcs:disable Magento2.Functions.StaticFunction + */ public static function tearDownAfterClass() { \Magento\Framework\Profiler::disable(); - } + } // phpcs:enable protected function setUp() { @@ -126,19 +139,20 @@ public function testProfilerDuringSqlException() $connection = $this->_getConnection(); try { - $connection->query('SELECT * FROM unknown_table'); + $connection->select()->from('unknown_table'); } catch (\Zend_Db_Statement_Exception $exception) { + $this->assertNotEmpty($exception); } if (!isset($exception)) { - $this->fail("Expected exception didn't thrown!"); + $this->fail("Expected exception wasn't thrown!"); } /** @var \Magento\Framework\App\ResourceConnection $resource */ $resource = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() ->get(\Magento\Framework\App\ResourceConnection::class); $testTableName = $resource->getTableName('setup_module'); - $connection->query('SELECT * FROM ' . $testTableName); + $connection->select()->from($testTableName); /** @var \Magento\Framework\Model\ResourceModel\Db\Profiler $profiler */ $profiler = $connection->getProfiler(); diff --git a/lib/internal/Magento/Framework/DB/Test/Unit/Ddl/TriggerTest.php b/lib/internal/Magento/Framework/DB/Test/Unit/Ddl/TriggerTest.php index 5e3840a0bc348..f4dc5f95b5876 100644 --- a/lib/internal/Magento/Framework/DB/Test/Unit/Ddl/TriggerTest.php +++ b/lib/internal/Magento/Framework/DB/Test/Unit/Ddl/TriggerTest.php @@ -5,6 +5,9 @@ */ namespace Magento\Framework\DB\Test\Unit\Ddl; +/** + * Class TriggerTest + */ class TriggerTest extends \PHPUnit\Framework\TestCase { /** diff --git a/lib/internal/Magento/Framework/Mview/Test/Unit/View/ChangelogTest.php b/lib/internal/Magento/Framework/Mview/Test/Unit/View/ChangelogTest.php index ac88684842dc0..50093568161e6 100644 --- a/lib/internal/Magento/Framework/Mview/Test/Unit/View/ChangelogTest.php +++ b/lib/internal/Magento/Framework/Mview/Test/Unit/View/ChangelogTest.php @@ -6,6 +6,9 @@ namespace Magento\Framework\Mview\Test\Unit\View; +/** + * Class ChangelogTest + */ class ChangelogTest extends \PHPUnit\Framework\TestCase { /** diff --git a/setup/src/Magento/Setup/Fixtures/ConfigurableProductsFixture.php b/setup/src/Magento/Setup/Fixtures/ConfigurableProductsFixture.php index 1e76e31733d88..0ffd98a435fa3 100644 --- a/setup/src/Magento/Setup/Fixtures/ConfigurableProductsFixture.php +++ b/setup/src/Magento/Setup/Fixtures/ConfigurableProductsFixture.php @@ -858,7 +858,7 @@ private function getDescriptionClosure( ) { if (null === $this->dataGenerator) { $fileName = __DIR__ . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'dictionary.csv'; - $this->dataGenerator = new DataGenerator(realpath($fileName)); + $this->dataGenerator = new DataGenerator($fileName); } return function ($index) use ( diff --git a/setup/src/Magento/Setup/Fixtures/ImagesGenerator/ImagesGenerator.php b/setup/src/Magento/Setup/Fixtures/ImagesGenerator/ImagesGenerator.php index 4bdb837a8aebe..7173e54716cce 100644 --- a/setup/src/Magento/Setup/Fixtures/ImagesGenerator/ImagesGenerator.php +++ b/setup/src/Magento/Setup/Fixtures/ImagesGenerator/ImagesGenerator.php @@ -42,6 +42,7 @@ public function __construct( */ public function generate($config) { + // phpcs:disable Magento2.Functions.DiscouragedFunction $binaryData = ''; $data = str_split(sha1($config['image-name']), 2); foreach ($data as $item) { @@ -72,6 +73,7 @@ public function generate($config) $absolutePathToMedia = $mediaDirectory->getAbsolutePath($this->mediaConfig->getBaseTmpMediaPath()); $imagePath = $absolutePathToMedia . DIRECTORY_SEPARATOR . $config['image-name']; imagejpeg($image, $imagePath, 100); + // phpcs:enable return $imagePath; } diff --git a/setup/src/Magento/Setup/Fixtures/OrdersFixture.php b/setup/src/Magento/Setup/Fixtures/OrdersFixture.php index 2c9b4569bbd7d..b2773657ebe92 100644 --- a/setup/src/Magento/Setup/Fixtures/OrdersFixture.php +++ b/setup/src/Magento/Setup/Fixtures/OrdersFixture.php @@ -474,6 +474,7 @@ public function execute() private function prepareQueryTemplates() { $fileName = __DIR__ . DIRECTORY_SEPARATOR . "_files" . DIRECTORY_SEPARATOR . "orders_fixture_data.json"; + // phpcs:ignore Magento2.Functions.DiscouragedFunction $templateData = json_decode(file_get_contents(realpath($fileName)), true); foreach ($templateData as $table => $template) { if (isset($template['_table'])) { @@ -512,6 +513,7 @@ private function prepareQueryTemplates() $connection->beginTransaction(); } + // phpcs:ignore Magento2.SQL.RawQuery $this->queryTemplates[$table] = "INSERT INTO `{$tableName}` ({$fields}) VALUES ({$values}){$querySuffix};"; $this->resourceConnections[$table] = $connection; } @@ -561,6 +563,7 @@ private function getMaxEntityId($tableName, $resourceName, $column = 'entity_id' /** @var \Magento\Framework\Model\ResourceModel\Db\VersionControl\AbstractDb $resource */ $resource = $this->fixtureModel->getObjectManager()->get($resourceName); $connection = $resource->getConnection(); + // phpcs:ignore Magento2.SQL.RawQuery return (int)$connection->query("SELECT MAX(`{$column}`) FROM `{$tableName}`;")->fetchColumn(0); } @@ -591,7 +594,7 @@ private function getProductIds(\Magento\Store\Api\Data\StoreInterface $store, $t } $ids = $productCollection->getAllIds($limit); if ($limit && count($ids) < $limit) { - throw new \Exception('Not enough products of type: ' . $typeId); + throw new \RuntimeException('Not enough products of type: ' . $typeId); } return $ids; } diff --git a/setup/src/Magento/Setup/Fixtures/Quote/QuoteGenerator.php b/setup/src/Magento/Setup/Fixtures/Quote/QuoteGenerator.php index f449f63f77ef0..77c8dcb194f75 100644 --- a/setup/src/Magento/Setup/Fixtures/Quote/QuoteGenerator.php +++ b/setup/src/Magento/Setup/Fixtures/Quote/QuoteGenerator.php @@ -530,6 +530,7 @@ private function prepareProductsForQuote() private function prepareQueryTemplates() { $fileName = $this->config->getFixtureDataFilename(); + // phpcs:ignore Magento2.Functions.DiscouragedFunction $templateData = json_decode(file_get_contents(realpath($fileName)), true); foreach ($templateData as $table => $template) { if (isset($template['_table'])) { @@ -566,6 +567,7 @@ private function prepareQueryTemplates() $connection->beginTransaction(); } + // phpcs:ignore Magento2.SQL.RawQuery $this->queryTemplates[$table] = "INSERT INTO `{$tableName}` ({$fields}) VALUES ({$values}){$querySuffix};"; $this->resourceConnections[$table] = $connection; } @@ -606,6 +608,7 @@ private function getMaxEntityId($tableName, $resourceName, $column = 'entity_id' { $tableName = $this->getTableName($tableName, $resourceName); $connection = $this->getConnection($resourceName); + // phpcs:ignore Magento2.SQL.RawQuery return (int)$connection->query("SELECT MAX(`{$column}`) FROM `{$tableName}`;")->fetchColumn(0); } diff --git a/setup/src/Magento/Setup/Test/Unit/Model/DataGeneratorTest.php b/setup/src/Magento/Setup/Test/Unit/Model/DataGeneratorTest.php index ab6701bc345bf..6888ab2858876 100644 --- a/setup/src/Magento/Setup/Test/Unit/Model/DataGeneratorTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Model/DataGeneratorTest.php @@ -8,6 +8,9 @@ use Magento\Setup\Model\DataGenerator; +/** + * Class DataGeneratorTest + */ class DataGeneratorTest extends \PHPUnit\Framework\TestCase { From 83e2374068ad8915f9833287db23b1e2c03cbb3f Mon Sep 17 00:00:00 2001 From: Hwashiang Yu <hwyu@adobe.com> Date: Mon, 1 Apr 2019 16:54:30 -0500 Subject: [PATCH 190/773] MC-13896: User Role Template Update - Resolved static failure with warning suppression --- app/code/Magento/User/Block/Role/Grid/User.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/User/Block/Role/Grid/User.php b/app/code/Magento/User/Block/Role/Grid/User.php index 4cd73f5e0c56e..963eed151ccbd 100644 --- a/app/code/Magento/User/Block/Role/Grid/User.php +++ b/app/code/Magento/User/Block/Role/Grid/User.php @@ -249,7 +249,6 @@ protected function getUsersFormData() * * @return array|bool * @since 100.1.0 - * @SuppressWarnings(PHPMD.DiscouragedFunctionsSniff) */ protected function restoreUsersFormData() { @@ -257,6 +256,7 @@ protected function restoreUsersFormData() \Magento\User\Controller\Adminhtml\User\Role\SaveRole::IN_ROLE_USER_FORM_DATA_SESSION_KEY ); if (null !== $sessionData) { + // phpcs:ignore Magento2.Functions.DiscouragedFunction parse_str($sessionData, $sessionData); return array_keys($sessionData); } From 27b091217579871937de2593842ffabc44248148 Mon Sep 17 00:00:00 2001 From: Andrew Molina <amolina@adobe.com> Date: Mon, 1 Apr 2019 17:15:38 -0500 Subject: [PATCH 191/773] MC-13954: Update Product Import Temp Directory --- .../Magento/CatalogImportExport/Model/Import/Uploader.php | 4 +++- .../Test/Unit/Model/Import/UploaderTest.php | 5 +++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Uploader.php b/app/code/Magento/CatalogImportExport/Model/Import/Uploader.php index 3cd5de35eb657..247684fecd9ad 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Uploader.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Uploader.php @@ -15,6 +15,7 @@ * @api * @since 100.0.2 * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * phpcs:disable Magento2.Functions.DiscouragedFunction */ class Uploader extends \Magento\MediaStorage\Model\File\Uploader { @@ -282,7 +283,7 @@ protected function _validateFile() $fileExtension = pathinfo($filePath, PATHINFO_EXTENSION); if (!$this->checkAllowedExtension($fileExtension)) { - throw new \Exception('Disallowed file type.'); + throw new \Magento\Framework\Exception\LocalizedException('Disallowed file type.'); } //run validate callbacks foreach ($this->_validateCallbacks as $params) { @@ -386,6 +387,7 @@ protected function _moveFile($tmpPath, $destPath) */ protected function chmod($file) { + //phpcs:ignore Squiz.PHP.NonExecutableCode.ReturnNotRequired return; } } diff --git a/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/UploaderTest.php b/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/UploaderTest.php index a4efa7806f5de..186d1e8e422fd 100644 --- a/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/UploaderTest.php +++ b/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/UploaderTest.php @@ -6,6 +6,11 @@ */ namespace Magento\CatalogImportExport\Test\Unit\Model\Import; +/** + * Class UploaderTest + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ class UploaderTest extends \PHPUnit\Framework\TestCase { /** From f18c17278c29c594bc729b0da2e6e91150ab6541 Mon Sep 17 00:00:00 2001 From: OlgaVasyltsun <olga.vasyltsun@gmail.com> Date: Tue, 2 Apr 2019 09:35:48 +0300 Subject: [PATCH 192/773] MC-10858: Escaper refactor --- app/code/Magento/Sales/Helper/Admin.php | 56 ++++++----- .../Sales/Test/Unit/Helper/AdminTest.php | 66 +------------ .../Magento/Sales/Helper/AdminTest.php | 97 +++++++++++++++++++ 3 files changed, 136 insertions(+), 83 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/Sales/Helper/AdminTest.php diff --git a/app/code/Magento/Sales/Helper/Admin.php b/app/code/Magento/Sales/Helper/Admin.php index 7053a696dcab5..29db70e82fcce 100644 --- a/app/code/Magento/Sales/Helper/Admin.php +++ b/app/code/Magento/Sales/Helper/Admin.php @@ -7,6 +7,9 @@ namespace Magento\Sales\Helper; +use Magento\Framework\App\ObjectManager; +use Symfony\Component\DomCrawler\Crawler; + /** * Sales admin helper. */ @@ -150,30 +153,38 @@ public function applySalableProductTypesFilter($collection) public function escapeHtmlWithLinks($data, $allowedTags = null) { if (!empty($data) && is_array($allowedTags) && in_array('a', $allowedTags)) { - $links = []; - $i = 1; - $data = str_replace('%', '%%', $data); - $regexp = "#(?J)<a" - ."(?:(?:\s+(?:(?:href\s*=\s*(['\"])(?<link>.*?)\\1\s*)|(?:\S+\s*=\s*(['\"])(.*?)\\3)\s*)*)|>)" - .">?(?:(?:(?<text>.*?)(?:<\/a\s*>?|(?=<\w))|(?<text>.*)))#si"; - while (preg_match($regexp, $data, $matches)) { - $text = ''; - if (!empty($matches['text'])) { - $text = str_replace('%%', '%', $matches['text']); + $wrapperElementId = uniqid(); + $crawler = ObjectManager::getInstance()->create( + Crawler::class, + [ + 'node' => '<html><body id="' . $wrapperElementId . '">' . $data . '</body></html>', + ] + ); + + $linkTags = $crawler->filter('a'); + + foreach ($linkTags as $linkNode) { + $linkAttributes = []; + foreach ($linkNode->attributes as $attribute) { + $linkAttributes[$attribute->name] = $attribute->value; + } + + foreach ($linkAttributes as $attributeName => $attributeValue) { + if ($attributeName === 'href') { + $url = $this->filterUrl($attributeValue ?? ''); + $url = $this->escaper->escapeUrl($url); + $linkNode->setAttribute('href', $url); + } else { + $linkNode->removeAttribute($attributeName); + } } - $url = $this->filterUrl($matches['link'] ?? ''); - //Recreate a minimalistic secure a tag - $links[] = sprintf( - '<a href="%s">%s</a>', - htmlspecialchars($url, ENT_QUOTES, 'UTF-8', false), - $this->escaper->escapeHtml($text) - ); - $data = str_replace($matches[0], '%' . $i . '$s', $data); - ++$i; } - $data = $this->escaper->escapeHtml($data, $allowedTags); - return vsprintf($data, $links); + + $result = mb_convert_encoding($crawler->html(), 'UTF-8', 'HTML-ENTITIES'); + preg_match('/<body id="' . $wrapperElementId . '">(.+)<\/body>$/si', $result, $matches); + $data = $matches[1] ?? ''; } + return $this->escaper->escapeHtml($data, $allowedTags); } @@ -187,8 +198,9 @@ private function filterUrl(string $url): string { if ($url) { //Revert the sprintf escaping - $url = str_replace('%%', '%', $url); + //phpcs:disable $urlScheme = parse_url($url, PHP_URL_SCHEME); + //phpcs:enable $urlScheme = $urlScheme ? strtolower($urlScheme) : ''; if ($urlScheme !== 'http' && $urlScheme !== 'https') { $url = null; diff --git a/app/code/Magento/Sales/Test/Unit/Helper/AdminTest.php b/app/code/Magento/Sales/Test/Unit/Helper/AdminTest.php index 389064b7274a7..286ebd0932b40 100644 --- a/app/code/Magento/Sales/Test/Unit/Helper/AdminTest.php +++ b/app/code/Magento/Sales/Test/Unit/Helper/AdminTest.php @@ -71,7 +71,7 @@ protected function setUp() ->disableOriginalConstructor() ->getMock(); - $this->adminHelper = (new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this))->getObject( + $this->adminHelper = (new ObjectManager($this))->getObject( \Magento\Sales\Helper\Admin::class, [ 'context' => $this->contextMock, @@ -330,72 +330,16 @@ public function applySalableProductTypesFilterDataProvider() } /** - * @param string $data - * @param string $expected - * @param null|array $allowedTags - * @dataProvider escapeHtmlWithLinksDataProvider + * @return void */ - public function testEscapeHtmlWithLinks($data, $expected, $allowedTags = null) + public function testEscapeHtmlWithLinks(): void { + $expected = '<a>some text in tags</a>'; $this->escaperMock ->expects($this->any()) ->method('escapeHtml') ->will($this->returnValue($expected)); - $actual = $this->adminHelper->escapeHtmlWithLinks($data, $allowedTags); + $actual = $this->adminHelper->escapeHtmlWithLinks('<a>some text in tags</a>'); $this->assertEquals($expected, $actual); } - - /** - * @return array - */ - public function escapeHtmlWithLinksDataProvider() - { - return [ - [ - '<a>some text in tags</a>', - '<a>some text in tags</a>', - 'allowedTags' => null - ], - [ - 'Transaction ID: "<a target="_blank" href="https://www.paypal.com/?id=XX123XX">XX123XX</a>"', - 'Transaction ID: "<a target="_blank" href="https://www.paypal.com/?id=XX123XX">XX123XX</a>"', - 'allowedTags' => ['b', 'br', 'strong', 'i', 'u', 'a'] - ], - [ - '<a>some text in tags</a>', - '<a>some text in tags</a>', - 'allowedTags' => ['a'] - ], - 'Not replacement with placeholders' => [ - "<a><script>alert(1)</script></a>", - '<a><script>alert(1)</script></a>', - 'allowedTags' => ['a'] - ], - 'Normal usage, url escaped' => [ - '<a href=\"#\">Foo</a>', - '<a href="#">Foo</a>', - 'allowedTags' => ['a'] - ], - 'Normal usage, url not escaped' => [ - "<a href=http://example.com?foo=1&bar=2&baz[name]=BAZ>Foo</a>", - '<a href="http://example.com?foo=1&bar=2&baz[name]=BAZ">Foo</a>', - 'allowedTags' => ['a'] - ], - 'XSS test' => [ - "<a href=\"javascript:alert(59)\">Foo</a>", - '<a href="#">Foo</a>', - 'allowedTags' => ['a'] - ], - 'Additional regex test' => [ - "<a href=\"http://example1.com\" href=\"http://example2.com\">Foo</a>", - '<a href="http://example1.com">Foo</a>', - 'allowedTags' => ['a'] - ], - 'Break of valid urls' => [ - "<a href=\"http://example.com?foo=text with space\">Foo</a>", - '<a href="#">Foo</a>', - 'allowedTags' => ['a'] - ], - ]; - } } diff --git a/dev/tests/integration/testsuite/Magento/Sales/Helper/AdminTest.php b/dev/tests/integration/testsuite/Magento/Sales/Helper/AdminTest.php new file mode 100644 index 0000000000000..5d598fa90678b --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Sales/Helper/AdminTest.php @@ -0,0 +1,97 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Sales\Helper; + +use Magento\TestFramework\Helper\Bootstrap; + +/** + * Tests \Magento\Sales\Helper\Admin + */ +class AdminTest extends \PHPUnit\Framework\TestCase +{ + /** + * @var Admin + */ + private $helper; + + /** + * @inheritdoc + */ + protected function setUp() + { + $this->helper = Bootstrap::getObjectManager()->create(Admin::class); + } + + /** + * @param string $data + * @param string $expected + * @param null|array $allowedTags + * @return void + * + * @dataProvider escapeHtmlWithLinksDataProvider + */ + public function testEscapeHtmlWithLinks(string $data, string $expected, $allowedTags = null): void + { + $actual = $this->helper->escapeHtmlWithLinks($data, $allowedTags); + $this->assertEquals($expected, $actual); + } + + /** + * @return array + */ + public function escapeHtmlWithLinksDataProvider(): array + { + return [ + [ + '<a>some text in tags</a>', + '<a>some text in tags</a>', + 'allowedTags' => null, + ], + [ + 'Transaction ID: "<a target="_blank" href="https://www.paypal.com/?id=XX123XX">XX123XX</a>"', + 'Transaction ID: "<a href="https://www.paypal.com/?id=XX123XX">XX123XX</a>"', + 'allowedTags' => ['b', 'br', 'strong', 'i', 'u', 'a'], + ], + [ + '<a>some text in tags</a>', + '<a>some text in tags</a>', + 'allowedTags' => ['a'], + ], + [ + "<a><script>alert(1)</script></a>", + '<a>alert(1)</a>', + 'allowedTags' => ['a'], + ], + [ + '<a href=\"#\">Foo</a>', + '<a href="#">Foo</a>', + 'allowedTags' => ['a'], + ], + [ + "<a href=http://example.com?foo=1&bar=2&baz[name]=BAZ>Foo</a>", + '<a href="http://example.com?foo=1&bar=2&baz%5Bname%5D=BAZ">Foo</a>', + 'allowedTags' => ['a'], + ], + [ + "<a href=\"javascript:alert(59)\">Foo</a>", + '<a href="#">Foo</a>', + 'allowedTags' => ['a'], + ], + [ + "<a href=\"http://example1.com\" href=\"http://example2.com\">Foo</a>", + '<a href="http://example1.com">Foo</a>', + 'allowedTags' => ['a'], + ], + [ + "<a href=\"http://example.com?foo=text with space\">Foo</a>", + '<a href="http://example.com?foo=text%20with%20space">Foo</a>', + 'allowedTags' => ['a'], + ], + ]; + } +} From d2c8482644599ba52aa09a64b0e29babc970f2c4 Mon Sep 17 00:00:00 2001 From: OlgaVasyltsun <olga.vasyltsun@gmail.com> Date: Tue, 2 Apr 2019 11:54:29 +0300 Subject: [PATCH 193/773] MC-10858: Escaper refactor --- app/code/Magento/Sales/Helper/Admin.php | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Sales/Helper/Admin.php b/app/code/Magento/Sales/Helper/Admin.php index 29db70e82fcce..2f0e0ea639fe5 100644 --- a/app/code/Magento/Sales/Helper/Admin.php +++ b/app/code/Magento/Sales/Helper/Admin.php @@ -9,6 +9,7 @@ use Magento\Framework\App\ObjectManager; use Symfony\Component\DomCrawler\Crawler; +use Zend\Stdlib\StringWrapper\MbString; /** * Sales admin helper. @@ -35,24 +36,32 @@ class Admin extends \Magento\Framework\App\Helper\AbstractHelper */ protected $escaper; + /** + * @var MbString + */ + private $converter; + /** * @param \Magento\Framework\App\Helper\Context $context * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\Sales\Model\Config $salesConfig * @param \Magento\Framework\Pricing\PriceCurrencyInterface $priceCurrency * @param \Magento\Framework\Escaper $escaper + * @param Mbstring|null $converter */ public function __construct( \Magento\Framework\App\Helper\Context $context, \Magento\Store\Model\StoreManagerInterface $storeManager, \Magento\Sales\Model\Config $salesConfig, \Magento\Framework\Pricing\PriceCurrencyInterface $priceCurrency, - \Magento\Framework\Escaper $escaper + \Magento\Framework\Escaper $escaper, + MbString $converter = null ) { $this->priceCurrency = $priceCurrency; $this->_storeManager = $storeManager; $this->_salesConfig = $salesConfig; $this->escaper = $escaper; + $this->converter = $converter ?: ObjectManager::getInstance()->get(MbString::class); parent::__construct($context); } @@ -180,7 +189,8 @@ public function escapeHtmlWithLinks($data, $allowedTags = null) } } - $result = mb_convert_encoding($crawler->html(), 'UTF-8', 'HTML-ENTITIES'); + $this->converter->setEncoding('HTML-ENTITIES', 'UTF-8'); + $result = $this->converter->convert($crawler->html()); preg_match('/<body id="' . $wrapperElementId . '">(.+)<\/body>$/si', $result, $matches); $data = $matches[1] ?? ''; } From 375a36d6e50531c5266dc5be9cc845cbd666a855 Mon Sep 17 00:00:00 2001 From: Serhii Voloshkov <serhii.voloshkov@transoftgroup.com> Date: Tue, 2 Apr 2019 13:33:24 +0300 Subject: [PATCH 194/773] MC-14822: Compare action minor changes --- .../Controller/Product/Compare/Add.php | 11 +++- .../Controller/Product/Compare/Remove.php | 9 ++- .../Controller/Product/CompareTest.php | 61 +++++++++++++++++++ 3 files changed, 76 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/Catalog/Controller/Product/Compare/Add.php b/app/code/Magento/Catalog/Controller/Product/Compare/Add.php index d99901c915a10..f5c3171a3fe90 100644 --- a/app/code/Magento/Catalog/Controller/Product/Compare/Add.php +++ b/app/code/Magento/Catalog/Controller/Product/Compare/Add.php @@ -9,10 +9,13 @@ use Magento\Framework\App\Action\HttpPostActionInterface as HttpPostActionInterface; use Magento\Framework\Exception\NoSuchEntityException; +/** + * Add item to compare list action. + */ class Add extends \Magento\Catalog\Controller\Product\Compare implements HttpPostActionInterface { /** - * Add item to compare list + * Add item to compare list. * * @return \Magento\Framework\Controller\ResultInterface */ @@ -27,12 +30,13 @@ public function execute() if ($productId && ($this->_customerVisitor->getId() || $this->_customerSession->isLoggedIn())) { $storeId = $this->_storeManager->getStore()->getId(); try { + /** @var \Magento\Catalog\Model\Product $product */ $product = $this->productRepository->getById($productId, false, $storeId); } catch (NoSuchEntityException $e) { $product = null; } - if ($product) { + if ($product && $product->isSalable()) { $this->_catalogProductCompareList->addProduct($product); $productName = $this->_objectManager->get( \Magento\Framework\Escaper::class @@ -41,7 +45,7 @@ public function execute() 'addCompareSuccessMessage', [ 'product_name' => $productName, - 'compare_list_url' => $this->_url->getUrl('catalog/product_compare') + 'compare_list_url' => $this->_url->getUrl('catalog/product_compare'), ] ); @@ -50,6 +54,7 @@ public function execute() $this->_objectManager->get(\Magento\Catalog\Helper\Product\Compare::class)->calculate(); } + return $resultRedirect->setRefererOrBaseUrl(); } } diff --git a/app/code/Magento/Catalog/Controller/Product/Compare/Remove.php b/app/code/Magento/Catalog/Controller/Product/Compare/Remove.php index eac0ddf94af20..acf0f1b754c12 100644 --- a/app/code/Magento/Catalog/Controller/Product/Compare/Remove.php +++ b/app/code/Magento/Catalog/Controller/Product/Compare/Remove.php @@ -9,10 +9,13 @@ use Magento\Framework\App\Action\HttpPostActionInterface as HttpPostActionInterface; use Magento\Framework\Exception\NoSuchEntityException; +/** + * Remove item from compare list action. + */ class Remove extends \Magento\Catalog\Controller\Product\Compare implements HttpPostActionInterface { /** - * Remove item from compare list + * Remove item from compare list. * * @return \Magento\Framework\Controller\ResultInterface */ @@ -22,12 +25,13 @@ public function execute() if ($productId) { $storeId = $this->_storeManager->getStore()->getId(); try { + /** @var \Magento\Catalog\Model\Product $product */ $product = $this->productRepository->getById($productId, false, $storeId); } catch (NoSuchEntityException $e) { $product = null; } - if ($product) { + if ($product && $product->isSalable()) { /** @var $item \Magento\Catalog\Model\Product\Compare\Item */ $item = $this->_compareItemFactory->create(); if ($this->_customerSession->isLoggedIn()) { @@ -59,6 +63,7 @@ public function execute() if (!$this->getRequest()->getParam('isAjax', false)) { $resultRedirect = $this->resultRedirectFactory->create(); + return $resultRedirect->setRefererOrBaseUrl(); } } diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Product/CompareTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Product/CompareTest.php index 1cb2caace4fa1..3b2f81843988d 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Product/CompareTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Product/CompareTest.php @@ -72,6 +72,34 @@ public function testAddAction() $this->_assertCompareListEquals([$product->getEntityId()]); } + /** + * Test adding disabled product to compare list. + * + * @return void + */ + public function testAddDisabledProductAction() + { + $this->_requireVisitorWithNoProducts(); + $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + /** @var \Magento\Framework\Data\Form\FormKey $formKey */ + $formKey = $objectManager->get(\Magento\Framework\Data\Form\FormKey::class); + /** @var \Magento\Catalog\Model\Product $product */ + $product = $this->setProductDisabled('simple_product_1'); + + $this->getRequest()->setMethod(HttpRequest::METHOD_POST); + $this->dispatch( + sprintf( + 'catalog/product_compare/add/product/%s/form_key/%s?nocookie=1', + $product->getEntityId(), + $formKey->getFormKey() + ) + ); + + $this->assertRedirect(); + + $this->_assertCompareListEquals([]); + } + /** * Test comparing a product. * @@ -110,6 +138,24 @@ public function testRemoveAction() $this->_assertCompareListEquals([$restProduct->getEntityId()]); } + /** + * Test removing a disabled product from compare list. + * + * @return void + */ + public function testRemoveDisabledAction() + { + $this->_requireVisitorWithTwoProducts(); + /** @var \Magento\Catalog\Model\Product $product */ + $product = $this->setProductDisabled('simple_product_1'); + $this->getRequest()->setMethod(HttpRequest::METHOD_POST); + $this->dispatch('catalog/product_compare/remove/product/' . $product->getEntityId()); + + $this->assertRedirect(); + $restProduct = $this->productRepository->get('simple_product_2'); + $this->_assertCompareListEquals([$product->getEntityId(), $restProduct->getEntityId()]); + } + /** * Test removing a product from compare list of a registered customer. * @@ -202,6 +248,21 @@ public function testRemoveActionProductNameXss() ); } + /** + * Set product status disabled. + * + * @param string $sku + * @return \Magento\Catalog\Api\Data\ProductInterface + */ + private function setProductDisabled(string $sku) + { + $product = $this->productRepository->get($sku); + $product->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_DISABLED) + ->save(); + + return $product; + } + /** * Preparing compare list. * From a1b0b7300b3c5a2c376d50de465994ca36451530 Mon Sep 17 00:00:00 2001 From: OlgaVasyltsun <olga.vasyltsun@gmail.com> Date: Tue, 2 Apr 2019 13:48:04 +0300 Subject: [PATCH 195/773] MC-10858: Escaper refactor --- app/code/Magento/Sales/Helper/Admin.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/code/Magento/Sales/Helper/Admin.php b/app/code/Magento/Sales/Helper/Admin.php index 2f0e0ea639fe5..15f9ccb355dde 100644 --- a/app/code/Magento/Sales/Helper/Admin.php +++ b/app/code/Magento/Sales/Helper/Admin.php @@ -13,6 +13,8 @@ /** * Sales admin helper. + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class Admin extends \Magento\Framework\App\Helper\AbstractHelper { From b4cef0f91658861ad1b119e06c3afc16ed8a9408 Mon Sep 17 00:00:00 2001 From: Andrew Molina <amolina@adobe.com> Date: Tue, 2 Apr 2019 08:38:47 -0500 Subject: [PATCH 196/773] MC-13954: Update Product Import Temp Directory --- .../Magento/CatalogImportExport/Model/Import/Uploader.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Uploader.php b/app/code/Magento/CatalogImportExport/Model/Import/Uploader.php index 247684fecd9ad..4ce1c0e39d6de 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Uploader.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Uploader.php @@ -198,7 +198,6 @@ public function move($fileName, $renameFileOff = false) * @param string $url * @param string $driver * @return string - * @throws \Magento\Framework\Exception\FileSystemException * @throws \Magento\Framework\Exception\LocalizedException */ private function downloadFileFromUrl($url, $driver) @@ -270,7 +269,7 @@ protected function _readFileInfo($filePath) * Validate uploaded file by type and etc. * * @return void - * @throws \Exception + * @throws \Magento\Framework\Exception\LocalizedException */ protected function _validateFile() { @@ -283,7 +282,7 @@ protected function _validateFile() $fileExtension = pathinfo($filePath, PATHINFO_EXTENSION); if (!$this->checkAllowedExtension($fileExtension)) { - throw new \Magento\Framework\Exception\LocalizedException('Disallowed file type.'); + throw new \Magento\Framework\Exception\LocalizedException(__('Disallowed file type.')); } //run validate callbacks foreach ($this->_validateCallbacks as $params) { From 8656458b6c6164f4aeb6f18b80c28136454b75ae Mon Sep 17 00:00:00 2001 From: Serhii Voloshkov <serhii.voloshkov@transoftgroup.com> Date: Tue, 2 Apr 2019 16:58:48 +0300 Subject: [PATCH 197/773] MC-14822: Compare action minor changes --- .../Controller/Product/CompareTest.php | 28 ++++++++----------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Product/CompareTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Product/CompareTest.php index 3b2f81843988d..67d58561a633f 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Product/CompareTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Product/CompareTest.php @@ -23,17 +23,19 @@ class CompareTest extends \Magento\TestFramework\TestCase\AbstractController */ protected $productRepository; + /** + * @var \Magento\Framework\Data\Form\FormKey + */ + private $formKey; + /** * @inheritDoc */ protected function setUp() { parent::setUp(); - - /** @var $objectManager \Magento\TestFramework\ObjectManager */ - $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); - - $this->productRepository = $objectManager->create(\Magento\Catalog\Model\ProductRepository::class); + $this->formKey = $this->_objectManager->get(\Magento\Framework\Data\Form\FormKey::class); + $this->productRepository = $this->_objectManager->create(\Magento\Catalog\Model\ProductRepository::class); } /** @@ -44,16 +46,13 @@ protected function setUp() public function testAddAction() { $this->_requireVisitorWithNoProducts(); - $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); - /** @var \Magento\Framework\Data\Form\FormKey $formKey */ - $formKey = $objectManager->get(\Magento\Framework\Data\Form\FormKey::class); $product = $this->productRepository->get('simple_product_1'); $this->getRequest()->setMethod(HttpRequest::METHOD_POST); $this->dispatch( sprintf( 'catalog/product_compare/add/product/%s/form_key/%s?nocookie=1', $product->getEntityId(), - $formKey->getFormKey() + $this->formKey->getFormKey() ) ); @@ -77,12 +76,9 @@ public function testAddAction() * * @return void */ - public function testAddDisabledProductAction() + public function testAddActionForDisabledProduct(): void { $this->_requireVisitorWithNoProducts(); - $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); - /** @var \Magento\Framework\Data\Form\FormKey $formKey */ - $formKey = $objectManager->get(\Magento\Framework\Data\Form\FormKey::class); /** @var \Magento\Catalog\Model\Product $product */ $product = $this->setProductDisabled('simple_product_1'); @@ -91,7 +87,7 @@ public function testAddDisabledProductAction() sprintf( 'catalog/product_compare/add/product/%s/form_key/%s?nocookie=1', $product->getEntityId(), - $formKey->getFormKey() + $this->formKey->getFormKey() ) ); @@ -143,7 +139,7 @@ public function testRemoveAction() * * @return void */ - public function testRemoveDisabledAction() + public function testRemoveActionForDisabledProduct(): void { $this->_requireVisitorWithTwoProducts(); /** @var \Magento\Catalog\Model\Product $product */ @@ -254,7 +250,7 @@ public function testRemoveActionProductNameXss() * @param string $sku * @return \Magento\Catalog\Api\Data\ProductInterface */ - private function setProductDisabled(string $sku) + private function setProductDisabled(string $sku): \Magento\Catalog\Api\Data\ProductInterface { $product = $this->productRepository->get($sku); $product->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_DISABLED) From 2567e0609b911adf6ea3ad7f78c3cbf67506ec25 Mon Sep 17 00:00:00 2001 From: eduard13 <e.chitoraga@atwix.com> Date: Tue, 2 Apr 2019 18:12:56 +0300 Subject: [PATCH 198/773] Adjusting some typos --- .../Test/Mftf/ActionGroup/CreateCustomVariableActionGroup.xml | 4 ++-- app/code/Magento/Variable/Test/Mftf/Data/VariableData.xml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Variable/Test/Mftf/ActionGroup/CreateCustomVariableActionGroup.xml b/app/code/Magento/Variable/Test/Mftf/ActionGroup/CreateCustomVariableActionGroup.xml index 610676b350455..4d36cd0669b8e 100644 --- a/app/code/Magento/Variable/Test/Mftf/ActionGroup/CreateCustomVariableActionGroup.xml +++ b/app/code/Magento/Variable/Test/Mftf/ActionGroup/CreateCustomVariableActionGroup.xml @@ -9,7 +9,7 @@ <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="CreateCustomVariableActionGroup"> - <amOnPage url="admin/admin/system_variable/new/" stepKey="goToNewCustomVarialePage" /> + <amOnPage url="admin/admin/system_variable/new/" stepKey="goToNewCustomVariablePage" /> <waitForPageLoad stepKey="waitForPageLoad" /> <fillField selector="{{CustomVariableSection.variableCode}}" userInput="{{customVariable.code}}" stepKey="fillVariableCode" /> <fillField selector="{{CustomVariableSection.variableName}}" userInput="{{customVariable.name}}" stepKey="fillVariableName" /> @@ -18,7 +18,7 @@ <click selector="{{CustomVariableSection.saveCustomVariable}}" stepKey="clickSaveVariable"/> </actionGroup> <actionGroup name="DeleteCustomVariableActionGroup"> - <amOnPage url="admin/admin/system_variable/" stepKey="goToVarialeGrid" /> + <amOnPage url="admin/admin/system_variable/" stepKey="goToVariableGrid" /> <waitForPageLoad stepKey="waitForPageLoad1" /> <click selector="{{CustomVariableSection.GridCustomVariableCode(customVariable.code)}}" stepKey="goToCustomVariableEditPage" /> <waitForPageLoad stepKey="waitForPageLoad2" /> diff --git a/app/code/Magento/Variable/Test/Mftf/Data/VariableData.xml b/app/code/Magento/Variable/Test/Mftf/Data/VariableData.xml index 7b7fd768f0ab1..4ce0d244560f0 100644 --- a/app/code/Magento/Variable/Test/Mftf/Data/VariableData.xml +++ b/app/code/Magento/Variable/Test/Mftf/Data/VariableData.xml @@ -11,8 +11,8 @@ <entity name="_defaultVariable" type="cms_page"> <data key="city"> Austin </data> </entity> - <entity name="customVariable" type="cms_page"> - <data key="code" unique="suffix">variale-code</data> + <entity name="customVariable" type="variable"> + <data key="code" unique="suffix">variable-code</data> <data key="name">Test Variable</data> <data key="html"> Sample Variable </data> <data key="plain">variable-plain-</data> From 117d7103de2989168af45de550091e79f815d54e Mon Sep 17 00:00:00 2001 From: Nathan Smith <nathsmit@adobe.com> Date: Tue, 2 Apr 2019 10:46:35 -0500 Subject: [PATCH 199/773] MC-5882: Invalid quote in session --- app/code/Magento/Checkout/Model/Session.php | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Checkout/Model/Session.php b/app/code/Magento/Checkout/Model/Session.php index 748a9565fa31e..6b291f40aff6b 100644 --- a/app/code/Magento/Checkout/Model/Session.php +++ b/app/code/Magento/Checkout/Model/Session.php @@ -6,8 +6,10 @@ namespace Magento\Checkout\Model; use Magento\Customer\Api\Data\CustomerInterface; +use Magento\Framework\App\ObjectManager; use Magento\Quote\Model\Quote; use Magento\Quote\Model\QuoteIdMaskFactory; +use Psr\Log\LoggerInterface; /** * Represents the session data for the checkout process @@ -101,6 +103,11 @@ class Session extends \Magento\Framework\Session\SessionManager */ protected $quoteFactory; + /** + * @var LoggerInterface|null + */ + private $logger; + /** * @param \Magento\Framework\App\Request\Http $request * @param \Magento\Framework\Session\SidResolverInterface $sidResolver @@ -120,6 +127,8 @@ class Session extends \Magento\Framework\Session\SessionManager * @param \Magento\Customer\Api\CustomerRepositoryInterface $customerRepository * @param QuoteIdMaskFactory $quoteIdMaskFactory * @param \Magento\Quote\Model\QuoteFactory $quoteFactory + * @param LoggerInterface|null $logger + * @throws \Magento\Framework\Exception\SessionException * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -140,7 +149,8 @@ public function __construct( \Magento\Store\Model\StoreManagerInterface $storeManager, \Magento\Customer\Api\CustomerRepositoryInterface $customerRepository, QuoteIdMaskFactory $quoteIdMaskFactory, - \Magento\Quote\Model\QuoteFactory $quoteFactory + \Magento\Quote\Model\QuoteFactory $quoteFactory, + LoggerInterface $logger = null ) { $this->_orderFactory = $orderFactory; $this->_customerSession = $customerSession; @@ -162,6 +172,8 @@ public function __construct( $cookieMetadataFactory, $appState ); + $this->logger = $logger ?: ObjectManager::getInstance() + ->get(LoggerInterface::class); } /** @@ -205,6 +217,8 @@ public function setLoadInactive($load = true) * Get checkout quote instance by current session * * @return Quote + * @throws \Magento\Framework\Exception\LocalizedException + * @throws \Magento\Framework\Exception\NoSuchEntityException * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) */ @@ -228,7 +242,7 @@ public function getQuote() if ($quote->getData('customer_id') && $quote->getData('customer_id') !== $customerId) { $quote = $this->quoteFactory->create(); - throw new \Magento\Framework\Exception\NoSuchEntityException(); + $this->setQuoteId(null); } /** @@ -259,6 +273,7 @@ public function getQuote() $quote = $this->quoteRepository->getActiveForCustomer($customerId); $this->setQuoteId($quote->getId()); } catch (\Magento\Framework\Exception\NoSuchEntityException $e) { + $this->logger->critical($e); } } else { $quote->setIsCheckoutCart(true); @@ -524,8 +539,10 @@ public function restoreQuote() $this->_eventManager->dispatch('restore_quote', ['order' => $order, 'quote' => $quote]); return true; } catch (\Magento\Framework\Exception\NoSuchEntityException $e) { + $this->logger->critical($e); } } + return false; } From 19a182530a3b5dfac93b9055d517147aac3c4709 Mon Sep 17 00:00:00 2001 From: Nathan Smith <nathsmit@adobe.com> Date: Tue, 2 Apr 2019 10:46:58 -0500 Subject: [PATCH 200/773] MC-15036: Hardcode DHL gateway URL --- app/code/Magento/Dhl/Model/Carrier.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Dhl/Model/Carrier.php b/app/code/Magento/Dhl/Model/Carrier.php index ff51a71f81e63..ebef0be25bce3 100644 --- a/app/code/Magento/Dhl/Model/Carrier.php +++ b/app/code/Magento/Dhl/Model/Carrier.php @@ -715,6 +715,7 @@ protected function _getWeight($weight, $maxWeight = false, $configWeightUnit = f * @return array * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) + * phpcs:disable Generic.Metrics.NestingLevel.TooHigh */ protected function _getAllItems() { @@ -1307,7 +1308,7 @@ public function proccessAdditionalValidation(\Magento\Framework\DataObject $requ public function processAdditionalValidation(\Magento\Framework\DataObject $request) { //Skip by item validation if there is no items in request - if (!count($this->getAllItems($request))) { + if (empty($this->getAllItems($request))) { $this->_errors[] = __('There is no items in this order'); } @@ -1775,7 +1776,7 @@ protected function _parseXmlTrackingResponse($trackings, $response) $errorTitle = __('Unable to retrieve tracking'); $resultArr = []; - if (strlen(trim($response)) > 0) { + if (!empty(trim($response))) { $xml = $this->parseXml($response, \Magento\Shipping\Model\Simplexml\Element::class); if (!is_object($xml)) { $errorTitle = __('Response is in the wrong format'); @@ -1944,6 +1945,7 @@ protected function _prepareShippingLabelContent(\SimpleXMLElement $xml) } $result->setTrackingNumber((string)$xml->AirwayBillNumber); $labelContent = (string)$xml->LabelImage->OutputImage; + // phpcs:ignore Magento2.Functions.DiscouragedFunction $result->setShippingLabelContent(base64_decode($labelContent)); } catch (\Exception $e) { throw new \Magento\Framework\Exception\LocalizedException(__($e->getMessage())); From ddd21812c805a59edfdfeb0665d20c8ebba58d15 Mon Sep 17 00:00:00 2001 From: Cari Spruiell <spruiell@adobe.com> Date: Tue, 2 Apr 2019 10:54:58 -0500 Subject: [PATCH 201/773] MC-5894: Gift Card Account --- .../Magento/Framework/Model/ResourceModel/Db/ProfilerTest.php | 4 ++-- setup/src/Magento/Setup/Fixtures/OrdersFixture.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Framework/Model/ResourceModel/Db/ProfilerTest.php b/dev/tests/integration/testsuite/Magento/Framework/Model/ResourceModel/Db/ProfilerTest.php index d428552ec5e88..99305ad2d4e80 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/Model/ResourceModel/Db/ProfilerTest.php +++ b/dev/tests/integration/testsuite/Magento/Framework/Model/ResourceModel/Db/ProfilerTest.php @@ -139,7 +139,7 @@ public function testProfilerDuringSqlException() $connection = $this->_getConnection(); try { - $connection->select()->from('unknown_table'); + $connection->select()->from('unknown_table')->query()->fetch(); } catch (\Zend_Db_Statement_Exception $exception) { $this->assertNotEmpty($exception); } @@ -152,7 +152,7 @@ public function testProfilerDuringSqlException() $resource = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() ->get(\Magento\Framework\App\ResourceConnection::class); $testTableName = $resource->getTableName('setup_module'); - $connection->select()->from($testTableName); + $connection->select()->from($testTableName)->query()->fetch(); /** @var \Magento\Framework\Model\ResourceModel\Db\Profiler $profiler */ $profiler = $connection->getProfiler(); diff --git a/setup/src/Magento/Setup/Fixtures/OrdersFixture.php b/setup/src/Magento/Setup/Fixtures/OrdersFixture.php index b2773657ebe92..b6455e4d138f4 100644 --- a/setup/src/Magento/Setup/Fixtures/OrdersFixture.php +++ b/setup/src/Magento/Setup/Fixtures/OrdersFixture.php @@ -574,7 +574,7 @@ private function getMaxEntityId($tableName, $resourceName, $column = 'entity_id' * @param string $typeId * @param int $limit * @return array - * @throws \Exception + * @throws \RuntimeException */ private function getProductIds(\Magento\Store\Api\Data\StoreInterface $store, $typeId, $limit = null) { From d7fc607450c72b9982449f9a2d2d8c8341620f1c Mon Sep 17 00:00:00 2001 From: eduard13 <e.chitoraga@atwix.com> Date: Tue, 2 Apr 2019 19:33:01 +0300 Subject: [PATCH 202/773] Marking the variation as migrated to MFTF --- .../Variable/Test/TestCase/CreateCustomVariableEntityTest.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/dev/tests/functional/tests/app/Magento/Variable/Test/TestCase/CreateCustomVariableEntityTest.xml b/dev/tests/functional/tests/app/Magento/Variable/Test/TestCase/CreateCustomVariableEntityTest.xml index d118e835c6c68..9f3fb647575e0 100644 --- a/dev/tests/functional/tests/app/Magento/Variable/Test/TestCase/CreateCustomVariableEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Variable/Test/TestCase/CreateCustomVariableEntityTest.xml @@ -13,6 +13,7 @@ <data name="customVariable/data/name" xsi:type="string">variableName%isolation%</data> <data name="customVariable/data/html_value" xsi:type="string"><h1>variableName%isolation%</h1></data> <data name="customVariable/data/plain_value" xsi:type="string"><p>variablePlainText%isolation%</p></data> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <constraint name="Magento\Variable\Test\Constraint\AssertCustomVariableSuccessSaveMessage" /> <constraint name="Magento\Variable\Test\Constraint\AssertCustomVariableInGrid" /> <constraint name="Magento\Variable\Test\Constraint\AssertCustomVariableForm" /> From 218527010e9587335d13096ae203ddf467783f2b Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun <ogorkun@magento.com> Date: Tue, 2 Apr 2019 11:40:32 -0500 Subject: [PATCH 203/773] MC-15556: Processing of AJAX header --- lib/internal/Magento/Framework/App/Request/CsrfValidator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/App/Request/CsrfValidator.php b/lib/internal/Magento/Framework/App/Request/CsrfValidator.php index c930fc920907c..113c0621d5456 100644 --- a/lib/internal/Magento/Framework/App/Request/CsrfValidator.php +++ b/lib/internal/Magento/Framework/App/Request/CsrfValidator.php @@ -70,7 +70,7 @@ private function validateRequest( } if ($valid === null) { $valid = !$request->isPost() - || $request->isAjax() + || $request->isXmlHttpRequest() || $this->formKeyValidator->validate($request); } From 331b78ced63482627260c38c2e373459c3ee1ff1 Mon Sep 17 00:00:00 2001 From: eduard13 <e.chitoraga@atwix.com> Date: Tue, 2 Apr 2019 20:17:47 +0300 Subject: [PATCH 204/773] Convert CreateCustomVariableEntityTest to MFTF --- .../AdminAssertSuccessAddedActionGroup.xml | 16 ++++++++ .../FilterVariablesGridActionGroup.xml | 22 +++++++++++ .../NavigateToNewVariablePageActionGroup.xml | 15 ++++++++ .../NavigateToVariablesPageActionGroup.xml | 15 ++++++++ .../Test/Mftf/Page/AdminNewVariablePage.xml | 14 +++++++ .../Test/Mftf/Page/AdminVariablesPage.xml | 16 ++++++++ .../Section/AdminVariableMessagesSection.xml | 15 ++++++++ .../Section/AdminVariablesFilterSection.xml | 17 +++++++++ .../Section/AdminVariablesGridSection.xml | 15 ++++++++ .../Test/CreateCustomVariableEntityTest.xml | 37 +++++++++++++++++++ 10 files changed, 182 insertions(+) create mode 100644 app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminAssertSuccessAddedActionGroup.xml create mode 100644 app/code/Magento/Variable/Test/Mftf/ActionGroup/FilterVariablesGridActionGroup.xml create mode 100644 app/code/Magento/Variable/Test/Mftf/ActionGroup/NavigateToNewVariablePageActionGroup.xml create mode 100644 app/code/Magento/Variable/Test/Mftf/ActionGroup/NavigateToVariablesPageActionGroup.xml create mode 100644 app/code/Magento/Variable/Test/Mftf/Page/AdminNewVariablePage.xml create mode 100644 app/code/Magento/Variable/Test/Mftf/Page/AdminVariablesPage.xml create mode 100644 app/code/Magento/Variable/Test/Mftf/Section/AdminVariableMessagesSection.xml create mode 100644 app/code/Magento/Variable/Test/Mftf/Section/AdminVariablesFilterSection.xml create mode 100644 app/code/Magento/Variable/Test/Mftf/Section/AdminVariablesGridSection.xml create mode 100644 app/code/Magento/Variable/Test/Mftf/Test/CreateCustomVariableEntityTest.xml diff --git a/app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminAssertSuccessAddedActionGroup.xml b/app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminAssertSuccessAddedActionGroup.xml new file mode 100644 index 0000000000000..fd1f7870896e7 --- /dev/null +++ b/app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminAssertSuccessAddedActionGroup.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminAssertSuccessMessageActionGroup" > + <see userInput="You saved the custom variable." selector="{{AdminVariableMessagesSection.successMessage}}" stepKey="seeMessage"/> + </actionGroup> + <actionGroup name="AdminSeeVariableInGridActionGroup"> + <see selector="{{AdminVariablesGridSection.rowByValue(customVariable.code)}}" userInput="{{customVariable.code}}" stepKey="seeVariableCodeInGrid"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Variable/Test/Mftf/ActionGroup/FilterVariablesGridActionGroup.xml b/app/code/Magento/Variable/Test/Mftf/ActionGroup/FilterVariablesGridActionGroup.xml new file mode 100644 index 0000000000000..b40725eb781c4 --- /dev/null +++ b/app/code/Magento/Variable/Test/Mftf/ActionGroup/FilterVariablesGridActionGroup.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="FilterVariablesGridActionGroup"> + <arguments> + <argument name="field" type="string"/> + <argument name="value" type="string"/> + </arguments> + <fillField selector="{{field}}" userInput="{{value}}" stepKey="fillVariableAttributeInFilter"/> + <click selector="{{AdminVariablesFilterSection.searchButton}}" stepKey="clickSearchButton"/> + </actionGroup> + <actionGroup name="ResetFilterVariablesGridActionGroup"> + <click selector="{{AdminVariablesFilterSection.resetFilterButton}}" stepKey="clickResetButton"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Variable/Test/Mftf/ActionGroup/NavigateToNewVariablePageActionGroup.xml b/app/code/Magento/Variable/Test/Mftf/ActionGroup/NavigateToNewVariablePageActionGroup.xml new file mode 100644 index 0000000000000..ee80bcc861317 --- /dev/null +++ b/app/code/Magento/Variable/Test/Mftf/ActionGroup/NavigateToNewVariablePageActionGroup.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="NavigateToNewVariablePageActionGroup"> + <amOnPage url="{{AdminNewVariablePage.url}}" stepKey="openNewVariablePage"/> + <waitForPageLoad stepKey="waitForPageLoad"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Variable/Test/Mftf/ActionGroup/NavigateToVariablesPageActionGroup.xml b/app/code/Magento/Variable/Test/Mftf/ActionGroup/NavigateToVariablesPageActionGroup.xml new file mode 100644 index 0000000000000..f4c00b7b60391 --- /dev/null +++ b/app/code/Magento/Variable/Test/Mftf/ActionGroup/NavigateToVariablesPageActionGroup.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="NavigateToVariablesPage"> + <amOnPage url="{{AdminVariablesPage.url}}" stepKey="openVariablesGridPage"/> + <waitForPageLoad stepKey="waitForPageLoad"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Variable/Test/Mftf/Page/AdminNewVariablePage.xml b/app/code/Magento/Variable/Test/Mftf/Page/AdminNewVariablePage.xml new file mode 100644 index 0000000000000..6d09424e44d2a --- /dev/null +++ b/app/code/Magento/Variable/Test/Mftf/Page/AdminNewVariablePage.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<pages xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/PageObject.xsd"> + <page name="AdminNewVariablePage" url="/admin/system_variable/new/" area="admin" module="Magento_Variable"> + <section name="AdminNewVariableSection"/> + </page> +</pages> diff --git a/app/code/Magento/Variable/Test/Mftf/Page/AdminVariablesPage.xml b/app/code/Magento/Variable/Test/Mftf/Page/AdminVariablesPage.xml new file mode 100644 index 0000000000000..ceb53072b7cff --- /dev/null +++ b/app/code/Magento/Variable/Test/Mftf/Page/AdminVariablesPage.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<pages xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/PageObject.xsd"> + <page name="AdminVariablesPage" url="/admin/system_variable/index/" area="admin" module="Magento_Variable"> + <section name="AdminVariableMessagesSection"/> + <section name="AdminVariablesFilterSection"/> + <section name="AdminVariablesGridSection"/> + </page> +</pages> diff --git a/app/code/Magento/Variable/Test/Mftf/Section/AdminVariableMessagesSection.xml b/app/code/Magento/Variable/Test/Mftf/Section/AdminVariableMessagesSection.xml new file mode 100644 index 0000000000000..0acebbd8be880 --- /dev/null +++ b/app/code/Magento/Variable/Test/Mftf/Section/AdminVariableMessagesSection.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="AdminVariableMessagesSection"> + <element name="successMessage" type="text" selector=".message-success"/> + <element name="errorMessage" type="text" selector=".message.message-error.error"/> + </section> +</sections> diff --git a/app/code/Magento/Variable/Test/Mftf/Section/AdminVariablesFilterSection.xml b/app/code/Magento/Variable/Test/Mftf/Section/AdminVariablesFilterSection.xml new file mode 100644 index 0000000000000..3976a5f63e1a1 --- /dev/null +++ b/app/code/Magento/Variable/Test/Mftf/Section/AdminVariablesFilterSection.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="AdminVariablesFilterSection"> + <element name="searchButton" type="button" selector="button.action-default[title='Search']"/> + <element name="resetFilterButton" type="button" selector="button.action-reset[title='Reset Filter']"/> + <element name="codeFilter" type="input" selector="input.admin__control-text[name='code']"/> + <element name="nameFilter" type="input" selector="input.admin__control-text[name='name']"/> + </section> +</sections> diff --git a/app/code/Magento/Variable/Test/Mftf/Section/AdminVariablesGridSection.xml b/app/code/Magento/Variable/Test/Mftf/Section/AdminVariablesGridSection.xml new file mode 100644 index 0000000000000..be91edf59d9c9 --- /dev/null +++ b/app/code/Magento/Variable/Test/Mftf/Section/AdminVariablesGridSection.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="AdminVariablesGridSection"> + <element name="variablesGrid" type="text" selector="table[data-role='grid']"/> + <element name="rowByValue" type="text" selector="//td[text()[contains(.,'{{var}}')]]" parameterized="true" timeout="30"/> + </section> +</sections> diff --git a/app/code/Magento/Variable/Test/Mftf/Test/CreateCustomVariableEntityTest.xml b/app/code/Magento/Variable/Test/Mftf/Test/CreateCustomVariableEntityTest.xml new file mode 100644 index 0000000000000..41bbff38e6678 --- /dev/null +++ b/app/code/Magento/Variable/Test/Mftf/Test/CreateCustomVariableEntityTest.xml @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="CreateCustomVariableEntityTest"> + <annotations> + <features value="Variable"/> + <stories value="Create Custom Variable."/> + <title value="Create Custom Variable."/> + <description value="Test for creating a custom variable."/> + <severity value="MAJOR"/> + <group value="variable"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + </before> + <actionGroup ref="CreateCustomVariableActionGroup" stepKey="createCustomVariable"/> + <waitForPageLoad stepKey="waitForPageLoad"/> + <actionGroup ref="AdminAssertSuccessMessageActionGroup" stepKey="seeSuccessMessage"/> + <actionGroup ref="FilterVariablesGridActionGroup" stepKey="filterVariablesGridByNewVariableCode" > + <argument name="field" value="{{AdminVariablesFilterSection.codeFilter}}"/> + <argument name="value" value="{{customVariable.code}}"/> + </actionGroup> + <actionGroup ref="AdminSeeVariableInGridActionGroup" stepKey="seeNewVariableInGrid"/> + <after> + <actionGroup ref="ResetFilterVariablesGridActionGroup" stepKey="resetVariablesGrid"/> + <actionGroup ref="logout" stepKey="logout"/> + </after> + </test> +</tests> From f1a252fec0c940e084ed09679c2f27fea10084d5 Mon Sep 17 00:00:00 2001 From: Nathan Smith <nathsmit@adobe.com> Date: Tue, 2 Apr 2019 13:06:44 -0500 Subject: [PATCH 205/773] MC-5882: Invalid quote in session --- app/code/Magento/Checkout/Model/Session.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Checkout/Model/Session.php b/app/code/Magento/Checkout/Model/Session.php index 6b291f40aff6b..6dfdefb8601aa 100644 --- a/app/code/Magento/Checkout/Model/Session.php +++ b/app/code/Magento/Checkout/Model/Session.php @@ -240,7 +240,7 @@ public function getQuote() ? $this->_customer->getId() : $this->_customerSession->getCustomerId(); - if ($quote->getData('customer_id') && $quote->getData('customer_id') !== $customerId) { + if ($quote->getData('customer_id') && (int)$quote->getData('customer_id') !== (int)$customerId) { $quote = $this->quoteFactory->create(); $this->setQuoteId(null); } From 6180504e67bf1f603d23af0c4eeae09e774e0ba0 Mon Sep 17 00:00:00 2001 From: Viktor Sevch <svitja@ukr.net> Date: Tue, 2 Apr 2019 22:31:07 +0300 Subject: [PATCH 206/773] MC-5864: incorrect rendering of a rss feed --- .../Test/Unit/Model/Rss/OrderStatusTest.php | 31 ++++++++++++++++--- .../Test/Unit/Model/Rss/SignatureTest.php | 7 ----- 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/app/code/Magento/Sales/Test/Unit/Model/Rss/OrderStatusTest.php b/app/code/Magento/Sales/Test/Unit/Model/Rss/OrderStatusTest.php index e44c098e016b0..7c53949bc8139 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Rss/OrderStatusTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Rss/OrderStatusTest.php @@ -125,10 +125,7 @@ protected function setUp() $this->order->expects($this->any())->method('formatPrice')->will($this->returnValue('15.00')); $this->order->expects($this->any())->method('getGrandTotal')->will($this->returnValue(15)); $this->order->expects($this->any())->method('load')->with(1)->will($this->returnSelf()); - $this->signature = $this->createMock(Signature::class); - $this->signature->expects($this->any())->method('signData')->willReturn('signature'); - $this->objectManagerHelper = new ObjectManagerHelper($this); $this->model = $this->objectManagerHelper->getObject( \Magento\Sales\Model\Rss\OrderStatus::class, @@ -149,6 +146,7 @@ public function testGetRssData() { $this->orderFactory->expects($this->once())->method('create')->willReturn($this->order); $requestData = base64_encode('{"order_id":1,"increment_id":"100000001","customer_id":1}'); + $this->signature->expects($this->any())->method('signData')->willReturn('signature'); $this->requestInterface->expects($this->any()) ->method('getParam') @@ -186,6 +184,31 @@ public function testGetRssDataWithError() { $this->orderFactory->expects($this->once())->method('create')->willReturn($this->order); $requestData = base64_encode('{"order_id":"1","increment_id":true,"customer_id":true}'); + $this->signature->expects($this->any())->method('signData')->willReturn('signature'); + $this->requestInterface->expects($this->any()) + ->method('getParam') + ->willReturnMap( + [ + ['data', null, $requestData], + ['signature', null, 'signature'], + ] + ); + $this->orderStatusFactory->expects($this->never())->method('create'); + $this->urlInterface->expects($this->never())->method('getUrl'); + $this->assertEquals($this->feedData, $this->model->getRssData()); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage Order not found. + */ + public function testGetRssDataWithWrongSignature() + { + $requestData = base64_encode('{"order_id":"1","increment_id":true,"customer_id":true}'); + $this->signature->expects($this->any()) + ->method('signData') + ->with($requestData) + ->willReturn('wrong_signature'); $this->requestInterface->expects($this->any()) ->method('getParam') ->willReturnMap( @@ -219,7 +242,7 @@ public function testGetCacheKey($requestData, $result) ['data', null, $requestData], ['signature', null, 'signature'], ]); - + $this->signature->expects($this->any())->method('signData')->willReturn('signature'); $this->orderFactory->expects($this->once())->method('create')->will($this->returnValue($this->order)); $this->assertEquals('rss_order_status_data_' . $result, $this->model->getCacheKey()); } diff --git a/app/code/Magento/Sales/Test/Unit/Model/Rss/SignatureTest.php b/app/code/Magento/Sales/Test/Unit/Model/Rss/SignatureTest.php index 4bdfee9f8beea..82ab018cfd703 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Rss/SignatureTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Rss/SignatureTest.php @@ -21,11 +21,6 @@ class SignatureTest extends \PHPUnit\Framework\TestCase */ private $deploymentConfigMock; - /** - * @var \PHPUnit_Framework_MockObject_MockObject|Signature - */ - private $signatureMock; - /** * @var ObjectManagerHelper */ @@ -48,7 +43,6 @@ protected function setUp() ->method('get') ->with('crypt/key') ->willReturn('1234567890abc'); - $this->signatureMock = $this->createMock(Signature::class); $this->objectManagerHelper = new ObjectManagerHelper($this); $this->model = $this->objectManagerHelper->getObject( @@ -69,7 +63,6 @@ protected function setUp() */ public function testSignData(string $data, string $expected): void { - $this->signatureMock->expects($this->any())->method('signData')->willReturn($expected); $this->assertEquals($expected, $this->model->signData($data)); } From a61f5e3e04ed9bec375999ee8d6ea1cfb490b22e Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun <ogorkun@magento.com> Date: Tue, 2 Apr 2019 15:46:19 -0500 Subject: [PATCH 207/773] MC-15556: Processing of AJAX header --- .../Magento/Framework/App/Request/CsrfValidator.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/App/Request/CsrfValidator.php b/lib/internal/Magento/Framework/App/Request/CsrfValidator.php index 113c0621d5456..edbf7532551d2 100644 --- a/lib/internal/Magento/Framework/App/Request/CsrfValidator.php +++ b/lib/internal/Magento/Framework/App/Request/CsrfValidator.php @@ -55,8 +55,10 @@ public function __construct( } /** + * Validate given request. + * * @param HttpRequest $request - * @param ActionInterface $action + * @param ActionInterface $action * * @return bool */ @@ -78,6 +80,8 @@ private function validateRequest( } /** + * Create exception for when incoming request failed validation. + * * @param HttpRequest $request * @param ActionInterface $action * From 5d478aede31fbeb71e9a8254b4e729e0dc5b88c2 Mon Sep 17 00:00:00 2001 From: OlgaVasyltsun <olga.vasyltsun@gmail.com> Date: Wed, 3 Apr 2019 08:19:16 +0300 Subject: [PATCH 208/773] MC-10858: Escaper refactor --- app/code/Magento/Sales/Helper/Admin.php | 21 +++------------------ 1 file changed, 3 insertions(+), 18 deletions(-) diff --git a/app/code/Magento/Sales/Helper/Admin.php b/app/code/Magento/Sales/Helper/Admin.php index 15f9ccb355dde..ae283d729ac06 100644 --- a/app/code/Magento/Sales/Helper/Admin.php +++ b/app/code/Magento/Sales/Helper/Admin.php @@ -9,12 +9,9 @@ use Magento\Framework\App\ObjectManager; use Symfony\Component\DomCrawler\Crawler; -use Zend\Stdlib\StringWrapper\MbString; /** * Sales admin helper. - * - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class Admin extends \Magento\Framework\App\Helper\AbstractHelper { @@ -38,32 +35,24 @@ class Admin extends \Magento\Framework\App\Helper\AbstractHelper */ protected $escaper; - /** - * @var MbString - */ - private $converter; - /** * @param \Magento\Framework\App\Helper\Context $context * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\Sales\Model\Config $salesConfig * @param \Magento\Framework\Pricing\PriceCurrencyInterface $priceCurrency * @param \Magento\Framework\Escaper $escaper - * @param Mbstring|null $converter */ public function __construct( \Magento\Framework\App\Helper\Context $context, \Magento\Store\Model\StoreManagerInterface $storeManager, \Magento\Sales\Model\Config $salesConfig, \Magento\Framework\Pricing\PriceCurrencyInterface $priceCurrency, - \Magento\Framework\Escaper $escaper, - MbString $converter = null + \Magento\Framework\Escaper $escaper ) { $this->priceCurrency = $priceCurrency; $this->_storeManager = $storeManager; $this->_salesConfig = $salesConfig; $this->escaper = $escaper; - $this->converter = $converter ?: ObjectManager::getInstance()->get(MbString::class); parent::__construct($context); } @@ -164,11 +153,10 @@ public function applySalableProductTypesFilter($collection) public function escapeHtmlWithLinks($data, $allowedTags = null) { if (!empty($data) && is_array($allowedTags) && in_array('a', $allowedTags)) { - $wrapperElementId = uniqid(); $crawler = ObjectManager::getInstance()->create( Crawler::class, [ - 'node' => '<html><body id="' . $wrapperElementId . '">' . $data . '</body></html>', + 'node' => '<html><body>' . $data . '</body></html>', ] ); @@ -191,10 +179,7 @@ public function escapeHtmlWithLinks($data, $allowedTags = null) } } - $this->converter->setEncoding('HTML-ENTITIES', 'UTF-8'); - $result = $this->converter->convert($crawler->html()); - preg_match('/<body id="' . $wrapperElementId . '">(.+)<\/body>$/si', $result, $matches); - $data = $matches[1] ?? ''; + $data = mb_convert_encoding($crawler->filter('body')->html(), 'UTF-8', 'HTML-ENTITIES'); } return $this->escaper->escapeHtml($data, $allowedTags); From c41b4be439e4eafd83a2efd2225ad3bb224b051d Mon Sep 17 00:00:00 2001 From: Viktor Sevch <svitja@ukr.net> Date: Wed, 3 Apr 2019 09:38:26 +0300 Subject: [PATCH 209/773] MC-5864: incorrect rendering of a rss feed --- app/code/Magento/Sales/Model/Rss/Signature.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/code/Magento/Sales/Model/Rss/Signature.php b/app/code/Magento/Sales/Model/Rss/Signature.php index 72b8f55fbdee6..e2bc1fe8a6411 100644 --- a/app/code/Magento/Sales/Model/Rss/Signature.php +++ b/app/code/Magento/Sales/Model/Rss/Signature.php @@ -8,9 +8,7 @@ namespace Magento\Sales\Model\Rss; -use Magento\Framework\App\ObjectManager; use Magento\Framework\Config\ConfigOptionsListConstants; -use Magento\Framework\App\DeploymentConfig; /** * Class for generating signature. @@ -32,7 +30,7 @@ class Signature private $keys = []; /** - * @var mixed + * @var \Magento\Framework\App\DeploymentConfig */ private $deploymentConfig; From b5afedf5f51503733975373ea925cf43f2289229 Mon Sep 17 00:00:00 2001 From: Leandry <leandry@atwix.com> Date: Wed, 3 Apr 2019 13:22:34 +0300 Subject: [PATCH 210/773] Convert LockAdminUserWhenCreatingNewIntegrationTest to MFTF --- .../Mftf/Section/AdminLoginFormSection.xml | 1 + .../Mftf/Data/AdminNewIntegrationData.xml | 14 +++ .../Mftf/Page/AdminNewIntegrationPage.xml | 14 +++ .../Section/AdminNewIntegrationSection.xml | 16 ++++ ...ewIntegrationRequiredFieldsActionGroup.xml | 25 ++++++ ...dminUserWhenCreatingNewIntegrationTest.xml | 85 +++++++++++++++++++ 6 files changed, 155 insertions(+) create mode 100644 app/code/Magento/Integration/Test/Mftf/Data/AdminNewIntegrationData.xml create mode 100644 app/code/Magento/Integration/Test/Mftf/Page/AdminNewIntegrationPage.xml create mode 100644 app/code/Magento/Integration/Test/Mftf/Section/AdminNewIntegrationSection.xml create mode 100644 app/code/Magento/Security/Test/Mftf/ActionGroup/AdminNewIntegrationRequiredFieldsActionGroup.xml create mode 100644 app/code/Magento/Security/Test/Mftf/Test/LockAdminUserWhenCreatingNewIntegrationTest.xml diff --git a/app/code/Magento/Backend/Test/Mftf/Section/AdminLoginFormSection.xml b/app/code/Magento/Backend/Test/Mftf/Section/AdminLoginFormSection.xml index 3b10fac7bb9dc..58efb66747b15 100644 --- a/app/code/Magento/Backend/Test/Mftf/Section/AdminLoginFormSection.xml +++ b/app/code/Magento/Backend/Test/Mftf/Section/AdminLoginFormSection.xml @@ -12,5 +12,6 @@ <element name="username" type="input" selector="#username"/> <element name="password" type="input" selector="#login"/> <element name="signIn" type="button" selector=".actions .action-primary" timeout="30"/> + <element name="error" type="text" selector=".message.message-error.error"/> </section> </sections> diff --git a/app/code/Magento/Integration/Test/Mftf/Data/AdminNewIntegrationData.xml b/app/code/Magento/Integration/Test/Mftf/Data/AdminNewIntegrationData.xml new file mode 100644 index 0000000000000..1307320ffb8f9 --- /dev/null +++ b/app/code/Magento/Integration/Test/Mftf/Data/AdminNewIntegrationData.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd"> + <entity name="AdminNewIntegrationData" type="admin"> + <data key="integrationName" unique="prefix">_Integration</data> + </entity> +</entities> diff --git a/app/code/Magento/Integration/Test/Mftf/Page/AdminNewIntegrationPage.xml b/app/code/Magento/Integration/Test/Mftf/Page/AdminNewIntegrationPage.xml new file mode 100644 index 0000000000000..c4b0695a05bf0 --- /dev/null +++ b/app/code/Magento/Integration/Test/Mftf/Page/AdminNewIntegrationPage.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<pages xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/PageObject.xsd"> + <page name="AdminNewIntegrationPage" url="admin/integration/new/" area="admin" module="Magento_Integration"> + <section name="AdminNewIntegrationSection"/> + </page> +</pages> diff --git a/app/code/Magento/Integration/Test/Mftf/Section/AdminNewIntegrationSection.xml b/app/code/Magento/Integration/Test/Mftf/Section/AdminNewIntegrationSection.xml new file mode 100644 index 0000000000000..7a193df73063e --- /dev/null +++ b/app/code/Magento/Integration/Test/Mftf/Section/AdminNewIntegrationSection.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="AdminNewIntegrationSection"> + <element name="integrationName" type="input" selector="#integration_properties_name"/> + <element name="currentPassword" type="input" selector="#integration_properties_current_password"/> + <element name="save" type="button" selector="#save-split-button-button"/> + </section> +</sections> diff --git a/app/code/Magento/Security/Test/Mftf/ActionGroup/AdminNewIntegrationRequiredFieldsActionGroup.xml b/app/code/Magento/Security/Test/Mftf/ActionGroup/AdminNewIntegrationRequiredFieldsActionGroup.xml new file mode 100644 index 0000000000000..bb35660ca8edd --- /dev/null +++ b/app/code/Magento/Security/Test/Mftf/ActionGroup/AdminNewIntegrationRequiredFieldsActionGroup.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminNewIntegrationRequiredFieldsActionGroup"> + <arguments> + <argument name="integrationName" type="string" /> + <argument name="currentAdminPassword" type="string" /> + <argument name="message" type="string" defaultValue="The integration '{{AdminNewIntegrationData.integrationName}}' has been saved." /> + <argument name="messageSelector" type="string" defaultValue="{{AdminMessagesSection.success}}" /> + </arguments> + <!-- Fill all Required Fields. --> + <fillField selector="{{AdminNewIntegrationSection.integrationName}}" userInput="{{integrationName}}" stepKey="fillIntegrationName"/> + <fillField selector="{{AdminNewIntegrationSection.currentPassword}}" userInput="{{currentAdminPassword}}" stepKey="fillCurrentUserPassword"/> + <scrollToTopOfPage stepKey="ScrollToTopOfPage"/> + <click selector="{{AdminNewIntegrationSection.save}}" stepKey="saveNewIntegration"/> + <waitForPageLoad stepKey="waitForSaveResultLoad"/> + <see userInput="{{message}}" selector="{{messageSelector}}" stepKey="verifyMessage" /> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Security/Test/Mftf/Test/LockAdminUserWhenCreatingNewIntegrationTest.xml b/app/code/Magento/Security/Test/Mftf/Test/LockAdminUserWhenCreatingNewIntegrationTest.xml new file mode 100644 index 0000000000000..fcef652dfeb9b --- /dev/null +++ b/app/code/Magento/Security/Test/Mftf/Test/LockAdminUserWhenCreatingNewIntegrationTest.xml @@ -0,0 +1,85 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="LockAdminUserWhenCreatingNewIntegrationTest"> + <annotations> + <features value="Security"/> + <stories value="Runs Lock admin user when creating new integration test."/> + <title value="Lock admin user when creating new integration"/> + <description value="Runs Lock admin user when creating new integration test."/> + <severity value="MAJOR"/> + <group value="security"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <!-- Log in to Admin Panel --> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + </before> + <after> + <!-- Unlock Admin user --> + <magentoCLI command="admin:user:unlock {{_ENV.MAGENTO_ADMIN_USERNAME}}" stepKey="unlockAdminUser"/> + </after> + + <!-- Open Admin New Integration Page --> + <amOnPage url="{{AdminNewIntegrationPage.url}}" stepKey="amOnNewAdminIntegrationPage"/> + <waitForPageLoad stepKey="waitForNewAdminIntegrationPageLoad"/> + + <!-- Perform add new admin user 6 specified number of times. + "The password entered for the current user is invalid. Verify the password and try again." appears after each attempt.--> + <actionGroup ref="AdminNewIntegrationRequiredFieldsActionGroup" stepKey="failedSaveIntegrationFirstAttempt"> + <argument name="integrationName" value="{{AdminNewIntegrationData.integrationName}}" /> + <argument name="currentAdminPassword" value="{{_ENV.MAGENTO_ADMIN_PASSWORD}}INVALID" /> + <argument name="messageSelector" value="{{AdminMessagesSection.error}}" /> + <argument name="message" value="The password entered for the current user is invalid. Verify the password and try again." /> + </actionGroup> + + <actionGroup ref="AdminNewIntegrationRequiredFieldsActionGroup" stepKey="failedSaveIntegrationSecondAttempt"> + <argument name="integrationName" value="{{AdminNewIntegrationData.integrationName}}" /> + <argument name="currentAdminPassword" value="{{_ENV.MAGENTO_ADMIN_PASSWORD}}INVALID" /> + <argument name="messageSelector" value="{{AdminMessagesSection.error}}" /> + <argument name="message" value="The password entered for the current user is invalid. Verify the password and try again." /> + </actionGroup> + + <actionGroup ref="AdminNewIntegrationRequiredFieldsActionGroup" stepKey="failedSaveIntegrationThirdAttempt"> + <argument name="integrationName" value="{{AdminNewIntegrationData.integrationName}}" /> + <argument name="currentAdminPassword" value="{{_ENV.MAGENTO_ADMIN_PASSWORD}}INVALID" /> + <argument name="messageSelector" value="{{AdminMessagesSection.error}}" /> + <argument name="message" value="The password entered for the current user is invalid. Verify the password and try again." /> + </actionGroup> + + <actionGroup ref="AdminNewIntegrationRequiredFieldsActionGroup" stepKey="failedSaveIntegrationFourthAttempt"> + <argument name="integrationName" value="{{AdminNewIntegrationData.integrationName}}" /> + <argument name="currentAdminPassword" value="{{_ENV.MAGENTO_ADMIN_PASSWORD}}INVALID" /> + <argument name="messageSelector" value="{{AdminMessagesSection.error}}" /> + <argument name="message" value="The password entered for the current user is invalid. Verify the password and try again." /> + </actionGroup> + + <actionGroup ref="AdminNewIntegrationRequiredFieldsActionGroup" stepKey="failedSaveIntegrationFifthAttempt"> + <argument name="integrationName" value="{{AdminNewIntegrationData.integrationName}}" /> + <argument name="currentAdminPassword" value="{{_ENV.MAGENTO_ADMIN_PASSWORD}}INVALID" /> + <argument name="messageSelector" value="{{AdminMessagesSection.error}}" /> + <argument name="message" value="The password entered for the current user is invalid. Verify the password and try again." /> + </actionGroup> + + <!-- Last invalid current password save integration attempt and check logout error --> + <actionGroup ref="AdminNewIntegrationRequiredFieldsActionGroup" stepKey="failedSaveIntegrationLastAttempt"> + <argument name="integrationName" value="{{AdminNewIntegrationData.integrationName}}" /> + <argument name="currentAdminPassword" value="{{_ENV.MAGENTO_ADMIN_PASSWORD}}INVALID" /> + <argument name="messageSelector" value="{{AdminLoginFormSection.error}}" /> + <argument name="message" value="Your account is temporarily disabled. Please try again later." /> + </actionGroup> + + <!-- Try to login as admin and check error --> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsLockedAdmin"/> + <waitForPageLoad stepKey="waitForError"/> + <see selector="{{AdminLoginFormSection.error}}" userInput="The account sign-in was incorrect or your account is disabled temporarily. Please wait and try again later" + stepKey="seeLoginUserError"/> + </test> +</tests> From 421d73655d8c05771f312382e2d397cb99ec3fe0 Mon Sep 17 00:00:00 2001 From: Leandry <leandry@atwix.com> Date: Wed, 3 Apr 2019 13:26:59 +0300 Subject: [PATCH 211/773] add mftf_migrated:yes tag to old test --- .../TestCase/LockAdminUserWhenCreatingNewIntegrationTest.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenCreatingNewIntegrationTest.xml b/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenCreatingNewIntegrationTest.xml index f3012d9a2e2ce..d9c45881b59dd 100644 --- a/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenCreatingNewIntegrationTest.xml +++ b/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenCreatingNewIntegrationTest.xml @@ -18,6 +18,7 @@ <data name="integration/data/current_password" xsi:type="string">incorrect password</data> <data name="integration/data/resource_access" xsi:type="string">All</data> <data name="attempts" xsi:type="string">4</data> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <constraint name="Magento\Security\Test\Constraint\AssertUserIsLocked" /> </variation> </testCase> From d20307729a50eb0087c50586cda8331fb60dbbaf Mon Sep 17 00:00:00 2001 From: eduard13 <e.chitoraga@atwix.com> Date: Wed, 3 Apr 2019 13:50:30 +0300 Subject: [PATCH 212/773] Reverting the customVariable type --- app/code/Magento/Variable/Test/Mftf/Data/VariableData.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Variable/Test/Mftf/Data/VariableData.xml b/app/code/Magento/Variable/Test/Mftf/Data/VariableData.xml index 4ce0d244560f0..1160b79026617 100644 --- a/app/code/Magento/Variable/Test/Mftf/Data/VariableData.xml +++ b/app/code/Magento/Variable/Test/Mftf/Data/VariableData.xml @@ -11,7 +11,7 @@ <entity name="_defaultVariable" type="cms_page"> <data key="city"> Austin </data> </entity> - <entity name="customVariable" type="variable"> + <entity name="customVariable" type="cms_page"> <data key="code" unique="suffix">variable-code</data> <data key="name">Test Variable</data> <data key="html"> Sample Variable </data> From ca67289a8ce2706e650d4cbff655a4e15902e5cd Mon Sep 17 00:00:00 2001 From: Leandry <leandry@atwix.com> Date: Wed, 3 Apr 2019 19:27:23 +0300 Subject: [PATCH 213/773] Convert LockAdminUserWhenEditingUserTest to MFTF --- .../Mftf/Section/AdminLoginFormSection.xml | 1 + .../Test/LockAdminUserWhenEditingUserTest.xml | 117 ++++++++++++++++++ .../ActionGroup/AdminEditUserActionGroup.xml | 53 ++++++++ .../Mftf/Section/AdminEditUserSection.xml | 1 + .../LockAdminUserWhenEditingUserTest.xml | 1 + 5 files changed, 173 insertions(+) create mode 100644 app/code/Magento/Security/Test/Mftf/Test/LockAdminUserWhenEditingUserTest.xml create mode 100644 app/code/Magento/User/Test/Mftf/ActionGroup/AdminEditUserActionGroup.xml diff --git a/app/code/Magento/Backend/Test/Mftf/Section/AdminLoginFormSection.xml b/app/code/Magento/Backend/Test/Mftf/Section/AdminLoginFormSection.xml index 3b10fac7bb9dc..58efb66747b15 100644 --- a/app/code/Magento/Backend/Test/Mftf/Section/AdminLoginFormSection.xml +++ b/app/code/Magento/Backend/Test/Mftf/Section/AdminLoginFormSection.xml @@ -12,5 +12,6 @@ <element name="username" type="input" selector="#username"/> <element name="password" type="input" selector="#login"/> <element name="signIn" type="button" selector=".actions .action-primary" timeout="30"/> + <element name="error" type="text" selector=".message.message-error.error"/> </section> </sections> diff --git a/app/code/Magento/Security/Test/Mftf/Test/LockAdminUserWhenEditingUserTest.xml b/app/code/Magento/Security/Test/Mftf/Test/LockAdminUserWhenEditingUserTest.xml new file mode 100644 index 0000000000000..a7952cdb6e88d --- /dev/null +++ b/app/code/Magento/Security/Test/Mftf/Test/LockAdminUserWhenEditingUserTest.xml @@ -0,0 +1,117 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="LockAdminUserWhenEditingUserTest"> + <annotations> + <features value="Security"/> + <stories value="Runs Lock admin user when creating new user test."/> + <title value="Lock admin user when creating new user"/> + <description value="Runs Lock admin user when creating new user test."/> + <severity value="MAJOR"/> + <group value="security"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <createData entity="Admin3" stepKey="user"/> + <!-- Log in to Admin Panel --> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + </before> + <after> + <!-- Unlock Admin user --> + <magentoCLI command="admin:user:unlock {{_ENV.MAGENTO_ADMIN_USERNAME}}" stepKey="unlockAdminUser"/> + <!-- TODO Need to create delete operation for data entity="Admin3" + <deleteData createDataKey="user" stepKey="removeAdminUser"/>--> + </after> + + <actionGroup ref="AdminEditUserActionGroup" stepKey="editUserFirstAttempt"> + <argument name="adminUser" value="$$user.username$$"/> + <argument name="adminFirstname" value="NEW$$user.firstname$$"/> + <argument name="adminLastname" value="NEW$$user.lastname$$"/> + <argument name="adminEmail" value="new$$user.email$$"/> + <argument name="adminPassword" value="NEW$$user.password$$"/> + <argument name="adminPasswordConfirmation" value="NEW$$user.password_confirmation$$"/> + <argument name="adminUserRole" value="1"/> + <argument name="messageSelector" value="{{AdminMessagesSection.error}}" /> + <argument name="message" value="The password entered for the current user is invalid. Verify the password and try again." /> + <argument name="currentAdminPassword" value="{{_ENV.MAGENTO_ADMIN_PASSWORD}}INVALID"/> + </actionGroup> + + <actionGroup ref="AdminEditUserActionGroup" stepKey="editUserSecondAttempt"> + <argument name="adminUser" value="$$user.username$$"/> + <argument name="adminFirstname" value="NEW$$user.firstname$$"/> + <argument name="adminLastname" value="NEW$$user.lastname$$"/> + <argument name="adminEmail" value="new$$user.email$$"/> + <argument name="adminPassword" value="NEW$$user.password$$"/> + <argument name="adminPasswordConfirmation" value="NEW$$user.password_confirmation$$"/> + <argument name="adminUserRole" value="1"/> + <argument name="messageSelector" value="{{AdminMessagesSection.error}}" /> + <argument name="message" value="The password entered for the current user is invalid. Verify the password and try again." /> + <argument name="currentAdminPassword" value="{{_ENV.MAGENTO_ADMIN_PASSWORD}}INVALID"/> + </actionGroup> + + <actionGroup ref="AdminEditUserActionGroup" stepKey="editUserThirdAttempt"> + <argument name="adminUser" value="$$user.username$$"/> + <argument name="adminFirstname" value="NEW$$user.firstname$$"/> + <argument name="adminLastname" value="NEW$$user.lastname$$"/> + <argument name="adminEmail" value="new$$user.email$$"/> + <argument name="adminPassword" value="NEW$$user.password$$"/> + <argument name="adminPasswordConfirmation" value="NEW$$user.password_confirmation$$"/> + <argument name="adminUserRole" value="1"/> + <argument name="messageSelector" value="{{AdminMessagesSection.error}}" /> + <argument name="message" value="The password entered for the current user is invalid. Verify the password and try again." /> + <argument name="currentAdminPassword" value="{{_ENV.MAGENTO_ADMIN_PASSWORD}}INVALID"/> + </actionGroup> + + <actionGroup ref="AdminEditUserActionGroup" stepKey="editUserFourthAttempt"> + <argument name="adminUser" value="$$user.username$$"/> + <argument name="adminFirstname" value="NEW$$user.firstname$$"/> + <argument name="adminLastname" value="NEW$$user.lastname$$"/> + <argument name="adminEmail" value="new$$user.email$$"/> + <argument name="adminPassword" value="NEW$$user.password$$"/> + <argument name="adminPasswordConfirmation" value="NEW$$user.password_confirmation$$"/> + <argument name="adminUserRole" value="1"/> + <argument name="messageSelector" value="{{AdminMessagesSection.error}}" /> + <argument name="message" value="The password entered for the current user is invalid. Verify the password and try again." /> + <argument name="currentAdminPassword" value="{{_ENV.MAGENTO_ADMIN_PASSWORD}}INVALID"/> + </actionGroup> + + <actionGroup ref="AdminEditUserActionGroup" stepKey="editUserFifthAttempt"> + <argument name="adminUser" value="$$user.username$$"/> + <argument name="adminFirstname" value="NEW$$user.firstname$$"/> + <argument name="adminLastname" value="NEW$$user.lastname$$"/> + <argument name="adminEmail" value="new$$user.email$$"/> + <argument name="adminPassword" value="NEW$$user.password$$"/> + <argument name="adminPasswordConfirmation" value="NEW$$user.password_confirmation$$"/> + <argument name="adminUserRole" value="1"/> + <argument name="messageSelector" value="{{AdminMessagesSection.error}}" /> + <argument name="message" value="The password entered for the current user is invalid. Verify the password and try again." /> + <argument name="currentAdminPassword" value="{{_ENV.MAGENTO_ADMIN_PASSWORD}}INVALID"/> + </actionGroup> + + <actionGroup ref="AdminEditUserActionGroup" stepKey="openEditLastPage"> + <argument name="adminUser" value="$$user.username$$"/> + <argument name="adminFirstname" value="NEW$$user.firstname$$"/> + <argument name="adminLastname" value="NEW$$user.lastname$$"/> + <argument name="adminEmail" value="new$$user.email$$"/> + <argument name="adminPassword" value="NEW$$user.password$$"/> + <argument name="adminPasswordConfirmation" value="NEW$$user.password_confirmation$$"/> + <argument name="adminUserRole" value="1"/> + <argument name="messageSelector" value="{{AdminLoginFormSection.error}}" /> + <argument name="message" value="Your account is temporarily disabled. Please try again later." /> + <argument name="currentAdminPassword" value="{{_ENV.MAGENTO_ADMIN_PASSWORD}}INVALID"/> + </actionGroup> + + <!-- Try to login as admin and check error --> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsLockedAdmin"/> + <waitForPageLoad stepKey="waitForError"/> + <see selector="{{AdminLoginFormSection.error}}" userInput="The account sign-in was incorrect or your account is disabled temporarily. Please wait and try again later" + stepKey="seeLoginUserError"/> + </test> +</tests> diff --git a/app/code/Magento/User/Test/Mftf/ActionGroup/AdminEditUserActionGroup.xml b/app/code/Magento/User/Test/Mftf/ActionGroup/AdminEditUserActionGroup.xml new file mode 100644 index 0000000000000..7af34fe65947e --- /dev/null +++ b/app/code/Magento/User/Test/Mftf/ActionGroup/AdminEditUserActionGroup.xml @@ -0,0 +1,53 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminEditUserActionGroup"> + <arguments> + <argument name="adminUser" type="string" /> + <argument name="adminFirstname" type="string" /> + <argument name="adminLastname" type="string" /> + <argument name="adminEmail" type="string" /> + <argument name="adminPassword" type="string" /> + <argument name="adminPasswordConfirmation" type="string" /> + <argument name="currentAdminPassword" type="string" /> + <argument name="adminUserRole" type="string"/> + <argument name="message" type="string" defaultValue="You saved the user." /> + <argument name="messageSelector" type="string" defaultValue="{{AdminMessagesSection.success}}" /> + </arguments> + + <!-- Navigate to edit user page --> + <amOnPage url="{{AdminUsersPage.url}}" stepKey="openAdminUsersPage"/> + <fillField selector="{{AdminUserGridSection.usernameFilterTextField}}" userInput="{{adminUser}}" stepKey="fillSearchUsernameFilter"/> + <click selector="{{AdminUserGridSection.searchButton}}" stepKey="clickSearch" /> + <waitForPageLoad stepKey="waitForGridToLoad"/> + <see selector="{{AdminUserGridSection.usernameInFirstRow}}" userInput="{{adminUser}}" stepKey="seeUser" /> + <click selector="{{AdminUserGridSection.searchResultFirstRow}}" stepKey="openUserEdit"/> + <waitForPageLoad stepKey="waitForUserEditPageLoad"/> + + <!-- Edit admin User data --> + <fillField selector="{{AdminEditUserSection.usernameTextField}}" userInput="{{adminUser}}" stepKey="fillUser"/> + <fillField selector="{{AdminEditUserSection.firstNameTextField}}" userInput="{{adminFirstname}}" stepKey="fillFirstName"/> + <fillField selector="{{AdminEditUserSection.lastNameTextField}}" userInput="{{adminLastname}}" stepKey="fillLastName"/> + <fillField selector="{{AdminEditUserSection.emailTextField}}" userInput="{{adminEmail}}" stepKey="fillEmail"/> + <fillField selector="{{AdminEditUserSection.passwordTextField}}" userInput="{{adminPassword}}" stepKey="fillPassword"/> + <fillField selector="{{AdminEditUserSection.pwConfirmationTextField}}" userInput="{{adminPasswordConfirmation}}" stepKey="fillPasswordConfirmation"/> + <fillField selector="{{AdminEditUserSection.currentPasswordField}}" userInput="{{currentAdminPassword}}" stepKey="fillCurrentUserPassword"/> + <scrollToTopOfPage stepKey="ScrollToTopOfPage"/> + + <!-- Set admin User Role --> + <click selector="{{AdminEditUserSection.userRoleTab}}" stepKey="openUserRoleTab"/> + <click selector="{{AdminEditUserSection.administratorRoleRadio(adminUserRole)}}" stepKey="assignRole"/> + + <!-- Save User --> + <click selector="{{AdminEditUserSection.saveButton}}" stepKey="saveUser"/> + <waitForPageLoad stepKey="waitForSaveResultLoad"/> + <see userInput="{{message}}" selector="{{messageSelector}}" stepKey="verifyMessage" /> + + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/User/Test/Mftf/Section/AdminEditUserSection.xml b/app/code/Magento/User/Test/Mftf/Section/AdminEditUserSection.xml index 64068a0a5ef58..90a0ccd5ffa0d 100644 --- a/app/code/Magento/User/Test/Mftf/Section/AdminEditUserSection.xml +++ b/app/code/Magento/User/Test/Mftf/Section/AdminEditUserSection.xml @@ -19,6 +19,7 @@ <element name="pwConfirmationTextField" type="input" selector="#user_confirmation"/> <element name="currentPasswordField" type="input" selector="#user_current_password"/> <element name="userRoleTab" type="button" selector="#page_tabs_roles_section"/> + <element name="administratorRoleRadio" type="radio" selector="//*[@id='permissionsUserRolesGrid_table']//td[{{role}}]/input" parameterized="true"/> <element name="roleNameFilterTextField" type="input" selector="#permissionsUserRolesGrid_filter_role_name"/> <element name="searchButton" type="button" selector=".admin__data-grid-header button[title=Search]"/> <element name="resetButton" type="button" selector="button[title='Reset Filter']"/> diff --git a/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenEditingUserTest.xml b/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenEditingUserTest.xml index bc4a8641d68f7..c5728da99a7a7 100644 --- a/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenEditingUserTest.xml +++ b/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenEditingUserTest.xml @@ -19,6 +19,7 @@ <data name="user/data/password_confirmation" xsi:type="string">123123qq</data> <data name="user/data/current_password" xsi:type="string">incorrect password</data> <data name="attempts" xsi:type="string">4</data> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <constraint name="Magento\Security\Test\Constraint\AssertUserIsLocked" /> </variation> </testCase> From 968f98dc1583cfe3adbf6f67ca3b4245e9a9c950 Mon Sep 17 00:00:00 2001 From: Joan He <johe@magento.com> Date: Wed, 3 Apr 2019 14:05:50 -0500 Subject: [PATCH 214/773] MC-15571: Incorrectly persist and render rule --- .../CatalogRule/Controller/Adminhtml/Promo/Catalog/Save.php | 3 +++ app/code/Magento/Rule/Block/Editable.php | 6 +++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/CatalogRule/Controller/Adminhtml/Promo/Catalog/Save.php b/app/code/Magento/CatalogRule/Controller/Adminhtml/Promo/Catalog/Save.php index 0ff12faf54cbf..4f58293d53359 100644 --- a/app/code/Magento/CatalogRule/Controller/Adminhtml/Promo/Catalog/Save.php +++ b/app/code/Magento/CatalogRule/Controller/Adminhtml/Promo/Catalog/Save.php @@ -97,6 +97,9 @@ public function execute() unset($data['rule']); } + unset($data['conditions_serialized']); + unset($data['actions_serialized']); + $model->loadPost($data); $this->_objectManager->get(\Magento\Backend\Model\Session::class)->setPageData($data); diff --git a/app/code/Magento/Rule/Block/Editable.php b/app/code/Magento/Rule/Block/Editable.php index d53213a7df876..57bbc72ff2660 100644 --- a/app/code/Magento/Rule/Block/Editable.php +++ b/app/code/Magento/Rule/Block/Editable.php @@ -58,11 +58,11 @@ public function render(\Magento\Framework\Data\Form\Element\AbstractElement $ele '" name="' . $this->escapeHtmlAttr($element->getName()) . '" value="' . - $element->getValue() . + $this->escapeHtmlAttr($element->getValue()) . '" data-form-part="' . - $element->getData('data-form-part') . + $this->escapeHtmlAttr($element->getData('data-form-part')) . '"/> ' . - htmlspecialchars( + $this->escapeHtml( $valueName ) . ' '; } else { From e87dfa7f0bd54d378d159e4dbd614ad4963d887c Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun <ogorkun@magento.com> Date: Wed, 3 Apr 2019 17:30:57 -0500 Subject: [PATCH 215/773] MC-13958: Additional Permissions for Design settings --- app/code/Magento/Catalog/Model/Category.php | 47 ++++++++++++++++++- app/code/Magento/Catalog/Model/Product.php | 34 +++++++++++++- .../Catalog/Model/ResourceModel/Category.php | 37 +-------------- .../Catalog/Model/ResourceModel/Product.php | 34 +------------- 4 files changed, 81 insertions(+), 71 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Category.php b/app/code/Magento/Catalog/Model/Category.php index d911bec0aaac9..0d76728752ad3 100644 --- a/app/code/Magento/Catalog/Model/Category.php +++ b/app/code/Magento/Catalog/Model/Category.php @@ -5,10 +5,13 @@ */ namespace Magento\Catalog\Model; +use Magento\Authorization\Model\UserContextInterface; use Magento\Catalog\Api\CategoryRepositoryInterface; use Magento\Catalog\Api\Data\CategoryInterface; use Magento\CatalogUrlRewrite\Model\CategoryUrlRewriteGenerator; use Magento\Framework\Api\AttributeValueFactory; +use Magento\Framework\App\ObjectManager; +use Magento\Framework\AuthorizationInterface; use Magento\Framework\Convert\ConvertArray; use Magento\Framework\Exception\NoSuchEntityException; use Magento\Framework\Profiler; @@ -211,6 +214,17 @@ class Category extends \Magento\Catalog\Model\AbstractModel implements */ protected $metadataService; + /** + * @var UserContextInterface + */ + private $userContext; + + /** + * @var AuthorizationInterface + */ + private $authorization; + + /** * @param \Magento\Framework\Model\Context $context * @param \Magento\Framework\Registry $registry @@ -233,6 +247,8 @@ class Category extends \Magento\Catalog\Model\AbstractModel implements * @param \Magento\Framework\Model\ResourceModel\AbstractResource $resource * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data + * @param UserContextInterface|null $userContext + * @param AuthorizationInterface|null $authorization * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -256,7 +272,9 @@ public function __construct( CategoryRepositoryInterface $categoryRepository, \Magento\Framework\Model\ResourceModel\AbstractResource $resource = null, \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, - array $data = [] + array $data = [], + ?UserContextInterface $userContext = null, + ?AuthorizationInterface $authorization = null ) { $this->metadataService = $metadataService; $this->_treeModel = $categoryTreeResource; @@ -281,6 +299,8 @@ public function __construct( $resourceCollection, $data ); + $this->userContext = $userContext ?? ObjectManager::getInstance()->get(UserContextInterface::class); + $this->authorization = $authorization ?? ObjectManager::getInstance()->get(AuthorizationInterface::class); } /** @@ -914,6 +934,31 @@ public function beforeDelete() return parent::beforeDelete(); } + /** + * @inheritDoc + */ + public function beforeSave() + { + //Validate changing of design. + $userType = $this->userContext->getUserType(); + if (( + $userType === UserContextInterface::USER_TYPE_ADMIN + || $userType === UserContextInterface::USER_TYPE_INTEGRATION + ) + && !$this->authorization->isAllowed('Magento_Catalog::edit_category_design') + ) { + $this->setData('custom_design', $this->getOrigData('custom_design')); + $this->setData('custom_design_from', $this->getOrigData('custom_design_from')); + $this->setData('custom_design_to', $this->getOrigData('custom_design_to')); + $this->setData('page_layout', $this->getOrigData('page_layout')); + $this->setData('custom_layout_update', $this->getOrigData('custom_layout_update')); + $this->setData('custom_apply_to_products', $this->getOrigData('custom_apply_to_products')); + } + + return parent::beforeSave(); + } + + /** * Retrieve anchors above * diff --git a/app/code/Magento/Catalog/Model/Product.php b/app/code/Magento/Catalog/Model/Product.php index 1e774e45df41f..e9fa1616b2fd3 100644 --- a/app/code/Magento/Catalog/Model/Product.php +++ b/app/code/Magento/Catalog/Model/Product.php @@ -5,6 +5,7 @@ */ namespace Magento\Catalog\Model; +use Magento\Authorization\Model\UserContextInterface; use Magento\Catalog\Api\CategoryRepositoryInterface; use Magento\Catalog\Api\Data\ProductAttributeMediaGalleryEntryInterface; use Magento\Catalog\Api\Data\ProductInterface; @@ -14,6 +15,7 @@ use Magento\Framework\Api\AttributeValueFactory; use Magento\Framework\App\Filesystem\DirectoryList; use Magento\Framework\App\ObjectManager; +use Magento\Framework\AuthorizationInterface; use Magento\Framework\DataObject\IdentityInterface; use Magento\Framework\Pricing\SaleableInterface; @@ -353,6 +355,16 @@ class Product extends \Magento\Catalog\Model\AbstractModel implements */ private $filterCustomAttribute; + /** + * @var UserContextInterface + */ + private $userContext; + + /** + * @var AuthorizationInterface + */ + private $authorization; + /** * @param \Magento\Framework\Model\Context $context * @param \Magento\Framework\Registry $registry @@ -391,6 +403,8 @@ class Product extends \Magento\Catalog\Model\AbstractModel implements * @param array $data * @param \Magento\Eav\Model\Config|null $config * @param FilterProductCustomAttribute|null $filterCustomAttribute + * @param UserContextInterface|null $userContext + * @param AuthorizationInterface|null $authorization * @SuppressWarnings(PHPMD.ExcessiveParameterList) * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ @@ -431,7 +445,9 @@ public function __construct( \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface $joinProcessor, array $data = [], \Magento\Eav\Model\Config $config = null, - FilterProductCustomAttribute $filterCustomAttribute = null + FilterProductCustomAttribute $filterCustomAttribute = null, + ?UserContextInterface $userContext = null, + ?AuthorizationInterface $authorization = null ) { $this->metadataService = $metadataService; $this->_itemOptionFactory = $itemOptionFactory; @@ -473,6 +489,8 @@ public function __construct( $this->eavConfig = $config ?? ObjectManager::getInstance()->get(\Magento\Eav\Model\Config::class); $this->filterCustomAttribute = $filterCustomAttribute ?? ObjectManager::getInstance()->get(FilterProductCustomAttribute::class); + $this->userContext = $userContext ?? ObjectManager::getInstance()->get(UserContextInterface::class); + $this->authorization = $authorization ?? ObjectManager::getInstance()->get(AuthorizationInterface::class); } /** @@ -874,6 +892,20 @@ public function beforeSave() $this->getTypeInstance()->beforeSave($this); + //Validate changing of design. + $userType = $this->userContext->getUserType(); + if (( + $userType === UserContextInterface::USER_TYPE_ADMIN + || $userType === UserContextInterface::USER_TYPE_INTEGRATION + ) + && !$this->authorization->isAllowed('Magento_Catalog::edit_product_design') + ) { + $this->setData('custom_design', $this->getOrigData('custom_design')); + $this->setData('page_layout', $this->getOrigData('page_layout')); + $this->setData('options_container', $this->getOrigData('options_container')); + $this->setData('custom_layout_update', $this->getOrigData('custom_layout_update')); + } + $hasOptions = false; $hasRequiredOptions = false; diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Category.php b/app/code/Magento/Catalog/Model/ResourceModel/Category.php index b04190f74e804..3dd05ca9e6b22 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Category.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Category.php @@ -15,8 +15,6 @@ use Magento\Framework\App\ObjectManager; use Magento\Framework\DataObject; use Magento\Framework\EntityManager\EntityManager; -use Magento\Framework\AuthorizationInterface; -use Magento\Authorization\Model\UserContextInterface; use Magento\Catalog\Model\Category as CategoryEntity; /** @@ -94,17 +92,6 @@ class Category extends AbstractResource * @var Processor */ private $indexerProcessor; - - /** - * @var UserContextInterface - */ - private $userContext; - - /** - * @var AuthorizationInterface - */ - private $authorization; - /** * Category constructor. * @param \Magento\Eav\Model\Entity\Context $context @@ -116,8 +103,6 @@ class Category extends AbstractResource * @param Processor $indexerProcessor * @param array $data * @param \Magento\Framework\Serialize\Serializer\Json|null $serializer - * @param UserContextInterface|null $userContext - * @param AuthorizationInterface|null $authorization * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -129,9 +114,7 @@ public function __construct( \Magento\Catalog\Model\ResourceModel\Category\CollectionFactory $categoryCollectionFactory, Processor $indexerProcessor, $data = [], - \Magento\Framework\Serialize\Serializer\Json $serializer = null, - ?UserContextInterface $userContext = null, - ?AuthorizationInterface $authorization = null + \Magento\Framework\Serialize\Serializer\Json $serializer = null ) { parent::__construct( $context, @@ -146,8 +129,6 @@ public function __construct( $this->indexerProcessor = $indexerProcessor; $this->serializer = $serializer ?: ObjectManager::getInstance() ->get(\Magento\Framework\Serialize\Serializer\Json::class); - $this->userContext = $userContext ?? ObjectManager::getInstance()->get(UserContextInterface::class); - $this->authorization = $authorization ?? ObjectManager::getInstance()->get(AuthorizationInterface::class); } /** @@ -1166,22 +1147,6 @@ public function validate($object) return $isValid; } - //Validate changing of design. - $userType = $this->userContext->getUserType(); - if (( - $userType === UserContextInterface::USER_TYPE_ADMIN - || $userType === UserContextInterface::USER_TYPE_INTEGRATION - ) - && !$this->authorization->isAllowed('Magento_Catalog::edit_category_design') - ) { - $object->setData('custom_design', $object->getOrigData('custom_design')); - $object->setData('custom_design_from', $object->getOrigData('custom_design_from')); - $object->setData('custom_design_to', $object->getOrigData('custom_design_to')); - $object->setData('page_layout', $object->getOrigData('page_layout')); - $object->setData('custom_layout_update', $object->getOrigData('custom_layout_update')); - $object->setData('custom_apply_to_products', $object->getOrigData('custom_apply_to_products')); - } - return true; } } diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product.php b/app/code/Magento/Catalog/Model/ResourceModel/Product.php index e48f3ae4bf09d..484bb6f588b8c 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product.php @@ -5,11 +5,9 @@ */ namespace Magento\Catalog\Model\ResourceModel; -use Magento\Authorization\Model\UserContextInterface; use Magento\Catalog\Model\ResourceModel\Product\Website\Link as ProductWebsiteLink; use Magento\Framework\App\ObjectManager; use Magento\Catalog\Model\Indexer\Category\Product\TableMaintainer; -use Magento\Framework\AuthorizationInterface; use Magento\Catalog\Model\Product as ProductEntity; use Magento\Eav\Model\Entity\Attribute\UniqueValidationInterface; @@ -93,16 +91,6 @@ class Product extends AbstractResource */ private $tableMaintainer; - /** - * @var UserContextInterface - */ - private $userContext; - - /** - * @var AuthorizationInterface - */ - private $authorization; - /** * @param \Magento\Eav\Model\Entity\Context $context * @param \Magento\Store\Model\StoreManagerInterface $storeManager @@ -116,8 +104,6 @@ class Product extends AbstractResource * @param array $data * @param TableMaintainer|null $tableMaintainer * @param UniqueValidationInterface|null $uniqueValidator - * @param UserContextInterface|null $userContext - * @param AuthorizationInterface|null $authorization * * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -133,9 +119,7 @@ public function __construct( \Magento\Catalog\Model\Product\Attribute\DefaultAttributes $defaultAttributes, $data = [], TableMaintainer $tableMaintainer = null, - UniqueValidationInterface $uniqueValidator = null, - ?UserContextInterface $userContext = null, - ?AuthorizationInterface $authorization = null + UniqueValidationInterface $uniqueValidator = null ) { $this->_categoryCollectionFactory = $categoryCollectionFactory; $this->_catalogCategory = $catalogCategory; @@ -143,8 +127,6 @@ public function __construct( $this->setFactory = $setFactory; $this->typeFactory = $typeFactory; $this->defaultAttributes = $defaultAttributes; - $this->userContext = $userContext ?? ObjectManager::getInstance()->get(UserContextInterface::class); - $this->authorization = $authorization ?? ObjectManager::getInstance()->get(AuthorizationInterface::class); parent::__construct( $context, $storeManager, @@ -622,20 +604,6 @@ public function countAll() */ public function validate($object) { - //Validate changing of design. - $userType = $this->userContext->getUserType(); - if (( - $userType === UserContextInterface::USER_TYPE_ADMIN - || $userType === UserContextInterface::USER_TYPE_INTEGRATION - ) - && !$this->authorization->isAllowed('Magento_Catalog::edit_product_design') - ) { - $object->setData('custom_design', $object->getOrigData('custom_design')); - $object->setData('page_layout', $object->getOrigData('page_layout')); - $object->setData('options_container', $object->getOrigData('options_container')); - $object->setData('custom_layout_update', $object->getOrigData('custom_layout_update')); - } - //validate attribute set entity type $entityType = $this->typeFactory->create()->loadByCode(\Magento\Catalog\Model\Product::ENTITY); $attributeSet = $this->setFactory->create()->load($object->getAttributeSetId()); From c030426d2fc7b75d5a5114ea47384ac8599f03d8 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun <ogorkun@magento.com> Date: Thu, 4 Apr 2019 11:11:19 -0500 Subject: [PATCH 216/773] MC-13958: Additional Permissions for Design settings --- app/code/Magento/Catalog/Model/Category.php | 2 -- app/code/Magento/Catalog/Model/ResourceModel/Category.php | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Category.php b/app/code/Magento/Catalog/Model/Category.php index 0d76728752ad3..5a4bec34b2e20 100644 --- a/app/code/Magento/Catalog/Model/Category.php +++ b/app/code/Magento/Catalog/Model/Category.php @@ -224,7 +224,6 @@ class Category extends \Magento\Catalog\Model\AbstractModel implements */ private $authorization; - /** * @param \Magento\Framework\Model\Context $context * @param \Magento\Framework\Registry $registry @@ -958,7 +957,6 @@ public function beforeSave() return parent::beforeSave(); } - /** * Retrieve anchors above * diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Category.php b/app/code/Magento/Catalog/Model/ResourceModel/Category.php index 3dd05ca9e6b22..10647effd5764 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Category.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Category.php @@ -1028,7 +1028,7 @@ protected function _processPositions($category, $newParent, $afterCategoryId) if ($afterCategoryId) { $select = $connection->select()->from($table, 'position')->where('entity_id = :entity_id'); $position = $connection->fetchOne($select, ['entity_id' => $afterCategoryId]); - $position += 1; + $position++; } else { $position = 1; } From d2afef4427718d004c5910f95bed54c8065e5a8c Mon Sep 17 00:00:00 2001 From: Dan Mooney <dmooney@adobe.com> Date: Thu, 4 Apr 2019 11:39:43 -0500 Subject: [PATCH 217/773] MC-15418: Elasticsearch configuration updates --- .../Model/ResourceModel/SynonymReader.php | 17 ++--------------- .../Framework/DB/Helper/Mysql/Fulltext.php | 18 ------------------ 2 files changed, 2 insertions(+), 33 deletions(-) diff --git a/app/code/Magento/Search/Model/ResourceModel/SynonymReader.php b/app/code/Magento/Search/Model/ResourceModel/SynonymReader.php index 3230e8e02daf5..cd7466e7ef6ab 100644 --- a/app/code/Magento/Search/Model/ResourceModel/SynonymReader.php +++ b/app/code/Magento/Search/Model/ResourceModel/SynonymReader.php @@ -85,11 +85,10 @@ protected function _construct() */ private function queryByPhrase($phrase) { - $phrase = $this->fullTextSelect->removeSpecialCharacters($phrase); $matchQuery = $this->fullTextSelect->getMatchQuery( ['synonyms' => 'synonyms'], - $this->escapePhrase($phrase), - Fulltext::FULLTEXT_MODE_BOOLEAN + $phrase, + Fulltext::FULLTEXT_MODE_NATURAL ); $query = $this->getConnection()->select()->from( $this->getMainTable() @@ -98,18 +97,6 @@ private function queryByPhrase($phrase) return $this->getConnection()->fetchAll($query); } - /** - * Cut trailing plus or minus sign, and @ symbol, using of which causes InnoDB to report a syntax error. - * - * @see https://dev.mysql.com/doc/refman/5.7/en/fulltext-boolean.html - * @param string $phrase - * @return string - */ - private function escapePhrase(string $phrase): string - { - return preg_replace('/@+|[@+-]+$/', '', $phrase); - } - /** * A private helper function to retrieve matching synonym groups per scope * diff --git a/lib/internal/Magento/Framework/DB/Helper/Mysql/Fulltext.php b/lib/internal/Magento/Framework/DB/Helper/Mysql/Fulltext.php index 5c50faf71a854..5660098157ace 100644 --- a/lib/internal/Magento/Framework/DB/Helper/Mysql/Fulltext.php +++ b/lib/internal/Magento/Framework/DB/Helper/Mysql/Fulltext.php @@ -14,13 +14,6 @@ */ class Fulltext { - /** - * Characters that have special meaning in fulltext match syntax - * - * @var string - */ - const SPECIAL_CHARACTERS = '-+<>*()~'; - /** * FULLTEXT search in MySQL search mode "natural language" */ @@ -106,15 +99,4 @@ public function match($select, $columns, $expression, $isCondition = true, $mode return $select; } - - /** - * Remove special characters from fulltext query expression - * - * @param string $expression - * @return string - */ - public function removeSpecialCharacters(string $expression): string - { - return str_replace(str_split(static::SPECIAL_CHARACTERS), '', $expression); - } } From 5cc351f0b108f8fe71000de64f6a57e38b17d226 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun <ogorkun@magento.com> Date: Thu, 4 Apr 2019 15:52:54 -0500 Subject: [PATCH 218/773] MC-10870: Invalid company ID in web API --- .../Webapi/Model/Config/SchemaLocator.php | 3 +- app/code/Magento/Webapi/etc/webapi.xsd | 78 ++++--------------- app/code/Magento/Webapi/etc/webapi_base.xsd | 71 +++++++++++++++++ app/code/Magento/Webapi/etc/webapi_merged.xsd | 24 ++++++ .../Magento/Webapi/Model/ConfigTest.php | 28 ++++++- .../Model/_files/partial_invalid_webapi.xml | 22 ++++++ .../Webapi/Model/_files/partial_webapi.xml | 39 ++++++++++ 7 files changed, 195 insertions(+), 70 deletions(-) create mode 100644 app/code/Magento/Webapi/etc/webapi_base.xsd create mode 100644 app/code/Magento/Webapi/etc/webapi_merged.xsd create mode 100644 dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Webapi/Model/_files/partial_invalid_webapi.xml create mode 100644 dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Webapi/Model/_files/partial_webapi.xml diff --git a/app/code/Magento/Webapi/Model/Config/SchemaLocator.php b/app/code/Magento/Webapi/Model/Config/SchemaLocator.php index 21111f0e9df38..b94f96c8ba294 100644 --- a/app/code/Magento/Webapi/Model/Config/SchemaLocator.php +++ b/app/code/Magento/Webapi/Model/Config/SchemaLocator.php @@ -31,7 +31,8 @@ class SchemaLocator implements \Magento\Framework\Config\SchemaLocatorInterface */ public function __construct(\Magento\Framework\Module\Dir\Reader $moduleReader) { - $this->_schema = $moduleReader->getModuleDir(Dir::MODULE_ETC_DIR, 'Magento_Webapi') . '/webapi.xsd'; + $this->_schema = $moduleReader->getModuleDir(Dir::MODULE_ETC_DIR, 'Magento_Webapi') . '/webapi_merged.xsd'; + $this->_perFileSchema = $moduleReader->getModuleDir(Dir::MODULE_ETC_DIR, 'Magento_Webapi') . '/webapi.xsd'; } /** diff --git a/app/code/Magento/Webapi/etc/webapi.xsd b/app/code/Magento/Webapi/etc/webapi.xsd index e3b90bd5d5ad1..40962d6d0da2e 100644 --- a/app/code/Magento/Webapi/etc/webapi.xsd +++ b/app/code/Magento/Webapi/etc/webapi.xsd @@ -8,69 +8,17 @@ */ --> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> - <xs:element name="routes" type="routesType"/> - - <xs:complexType name="routesType"> - <xs:sequence> - <xs:element name="route" type="routeType" minOccurs="0" maxOccurs="unbounded"/> - </xs:sequence> - </xs:complexType> - - <xs:complexType name="routeType"> - <xs:sequence> - <xs:element name="service" type="serviceType"/> - <xs:element name="resources" type="resourcesType"/> - <xs:element name="data" type="dataType" minOccurs="0"/> - </xs:sequence> - <xs:attribute name="method" use="required"> - <xs:simpleType> - <xs:restriction base="xs:string"> - <xs:enumeration value="GET"/> - <xs:enumeration value="PUT"/> - <xs:enumeration value="POST"/> - <xs:enumeration value="DELETE"/> - </xs:restriction> - </xs:simpleType> - </xs:attribute> - <xs:attribute name="url" type="xs:string" use="required"/> - <xs:attribute name="secure" type="xs:boolean"/> - <xs:attribute name="soapOperation" type="xs:string"/> - </xs:complexType> - - <xs:complexType name="serviceType"> - <xs:attribute name="class" type="xs:string" use="required"/> - <xs:attribute name="method" type="xs:string" use="required"/> - </xs:complexType> - - <xs:complexType name="resourcesType" > - <xs:sequence> - <xs:element name="resource" type="resourceType" maxOccurs="unbounded"/> - </xs:sequence> - </xs:complexType> - - <xs:complexType name="resourceType"> - <xs:attribute name="ref" use="required"> - <xs:simpleType> - <xs:restriction base="xs:string"> - <xs:pattern value=".+(, ?.+)*"/> - </xs:restriction> - </xs:simpleType> - </xs:attribute> - </xs:complexType> - - <xs:complexType name="dataType" > - <xs:sequence> - <xs:element name="parameter" type="parameterType" maxOccurs="unbounded"/> - </xs:sequence> - </xs:complexType> - - <xs:complexType name="parameterType"> - <xs:simpleContent> - <xs:extension base="xs:string"> - <xs:attribute name="name" type="xs:string" use="required"/> - <xs:attribute name="force" type="xs:boolean"/> - </xs:extension> - </xs:simpleContent> - </xs:complexType> - + <xs:redefine schemaLocation="urn:magento:module:Magento_Webapi:etc/webapi_base.xsd"> + <xs:complexType name="routeType"> + <xs:complexContent> + <xs:extension base="routeType"> + <xs:sequence> + <xs:element name="service" type="serviceType" minOccurs="0"/> + <xs:element name="resources" type="resourcesType" minOccurs="0"/> + <xs:element name="data" type="dataType" minOccurs="0"/> + </xs:sequence> + </xs:extension> + </xs:complexContent> + </xs:complexType> + </xs:redefine> </xs:schema> diff --git a/app/code/Magento/Webapi/etc/webapi_base.xsd b/app/code/Magento/Webapi/etc/webapi_base.xsd new file mode 100644 index 0000000000000..7d1a5a14ba78f --- /dev/null +++ b/app/code/Magento/Webapi/etc/webapi_base.xsd @@ -0,0 +1,71 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/** + * Structure description for webapi.xml configuration files. + * + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> + <xs:element name="routes" type="routesType"/> + + <xs:complexType name="routesType"> + <xs:sequence> + <xs:element name="route" type="routeType" minOccurs="0" maxOccurs="unbounded"/> + </xs:sequence> + </xs:complexType> + + <xs:complexType name="routeType"> + <xs:attribute name="method" use="required"> + <xs:simpleType> + <xs:restriction base="xs:string"> + <xs:enumeration value="GET"/> + <xs:enumeration value="PUT"/> + <xs:enumeration value="POST"/> + <xs:enumeration value="DELETE"/> + </xs:restriction> + </xs:simpleType> + </xs:attribute> + <xs:attribute name="url" type="xs:string" use="required"/> + <xs:attribute name="secure" type="xs:boolean"/> + <xs:attribute name="soapOperation" type="xs:string"/> + </xs:complexType> + + <xs:complexType name="serviceType"> + <xs:attribute name="class" type="xs:string" use="required"/> + <xs:attribute name="method" type="xs:string" use="required"/> + </xs:complexType> + + <xs:complexType name="resourcesType" > + <xs:sequence> + <xs:element name="resource" type="resourceType" maxOccurs="unbounded"/> + </xs:sequence> + </xs:complexType> + + <xs:complexType name="resourceType"> + <xs:attribute name="ref" use="required"> + <xs:simpleType> + <xs:restriction base="xs:string"> + <xs:pattern value=".+(, ?.+)*"/> + </xs:restriction> + </xs:simpleType> + </xs:attribute> + </xs:complexType> + + <xs:complexType name="dataType" > + <xs:sequence> + <xs:element name="parameter" type="parameterType" maxOccurs="unbounded"/> + </xs:sequence> + </xs:complexType> + + <xs:complexType name="parameterType"> + <xs:simpleContent> + <xs:extension base="xs:string"> + <xs:attribute name="name" type="xs:string" use="required"/> + <xs:attribute name="force" type="xs:boolean"/> + </xs:extension> + </xs:simpleContent> + </xs:complexType> + +</xs:schema> diff --git a/app/code/Magento/Webapi/etc/webapi_merged.xsd b/app/code/Magento/Webapi/etc/webapi_merged.xsd new file mode 100644 index 0000000000000..b775d5bbac609 --- /dev/null +++ b/app/code/Magento/Webapi/etc/webapi_merged.xsd @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/** + * Structure description for webapi.xml configuration files. + * + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> + <xs:redefine schemaLocation="urn:magento:module:Magento_Webapi:etc/webapi_base.xsd"> + <xs:complexType name="routeType"> + <xs:complexContent> + <xs:extension base="routeType"> + <xs:sequence> + <xs:element name="service" type="serviceType"/> + <xs:element name="resources" type="resourcesType"/> + <xs:element name="data" type="dataType" minOccurs="0"/> + </xs:sequence> + </xs:extension> + </xs:complexContent> + </xs:complexType> + </xs:redefine> +</xs:schema> diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Webapi/Model/ConfigTest.php b/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Webapi/Model/ConfigTest.php index 85a2d286eac95..c6d90fd55af93 100644 --- a/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Webapi/Model/ConfigTest.php +++ b/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Webapi/Model/ConfigTest.php @@ -12,6 +12,9 @@ */ class ConfigTest extends AbstractConfig { + /** + * @inheritdoc + */ public function testSchemaUsingInvalidXml($expectedErrors = null) { // @codingStandardsIgnoreStart @@ -27,6 +30,22 @@ public function testSchemaUsingInvalidXml($expectedErrors = null) parent::testSchemaUsingInvalidXml($expectedErrors); } + /** + * @inheritdoc + */ + public function testFileSchemaUsingInvalidXml($expectedErrors = null) + { + // @codingStandardsIgnoreStart + $expectedErrors = [ + "Element 'route', attribute 'method': [facet 'enumeration'] The value 'PATCH' is not an element of the set {'GET', 'PUT', 'POST', 'DELETE'}.", + "Element 'route', attribute 'method': 'PATCH' is not a valid value of the local atomic type.", + "Element 'service': The attribute 'method' is required but missing.", + "Element 'data': Missing child element(s). Expected is ( parameter ).", + ]; + // @codingStandardsIgnoreEnd + parent::testFileSchemaUsingInvalidXml($expectedErrors); + } + /** * Returns the name of the xml files to validate * @@ -64,7 +83,7 @@ protected function _getKnownInvalidXml() */ protected function _getKnownValidPartialXml() { - return null; + return __DIR__ . '/_files/partial_webapi.xml'; } /** @@ -74,7 +93,7 @@ protected function _getKnownValidPartialXml() */ protected function _getKnownInvalidPartialXml() { - return null; + return __DIR__ . '/_files/partial_invalid_webapi.xml'; } /** @@ -85,7 +104,7 @@ protected function _getKnownInvalidPartialXml() protected function _getXsd() { $urnResolver = new \Magento\Framework\Config\Dom\UrnResolver(); - return $urnResolver->getRealPath('urn:magento:module:Magento_Webapi:etc/webapi.xsd'); + return $urnResolver->getRealPath('urn:magento:module:Magento_Webapi:etc/webapi_merged.xsd'); } /** @@ -95,6 +114,7 @@ protected function _getXsd() */ protected function _getFileXsd() { - return null; + $urnResolver = new \Magento\Framework\Config\Dom\UrnResolver(); + return $urnResolver->getRealPath('urn:magento:module:Magento_Webapi:etc/webapi.xsd'); } } diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Webapi/Model/_files/partial_invalid_webapi.xml b/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Webapi/Model/_files/partial_invalid_webapi.xml new file mode 100644 index 0000000000000..7761eac3fbdb0 --- /dev/null +++ b/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Webapi/Model/_files/partial_invalid_webapi.xml @@ -0,0 +1,22 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<routes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Webapi:etc/webapi.xsd"> + <route url="/V1/customer/me" method="PATCH"> + <service class="Magento\Customer\Api\CustomerRepositoryInterface" /> + <resources> + <resource ref="a resource" /> + </resources> + <data> + </data> + </route> + <route url="/V1/customers" method="POST"/> + <route url="/V1/customers" method="PUT"> + <service class="Magento\Customer\Api\CustomerRepositoryInterface" method="foo" /> + </route> +</routes> diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Webapi/Model/_files/partial_webapi.xml b/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Webapi/Model/_files/partial_webapi.xml new file mode 100644 index 0000000000000..00fc8f16d85cc --- /dev/null +++ b/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Webapi/Model/_files/partial_webapi.xml @@ -0,0 +1,39 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<routes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Webapi:etc/webapi.xsd"> + <route url="/V1/customers/me" method="GET"> + <service class="Magento\Customer\Api\CustomerRepositoryInterface" method="getById" /> + <resources> + <resource ref="Magento_Customer::customer_self" /> + </resources> + <data> + <parameter name="id" force="true">null</parameter> + </data> + </route> + <route url="/V1/customers/me" method="PUT" secure="true"> + <service class="Magento\Customer\Api\CustomerRepositoryInterface" method="save" /> + <resources> + <resource ref="Magento_Customer::customer_self" /> + </resources> + <data> + <parameter name="id">null</parameter> + </data> + </route> + <route url="/V1/customers" method="POST"> + <service class="Magento\Customer\Api\CustomerRepositoryInterface" method="save" /> + <resources> + <resource ref="Magento_Customer::manage" /> + </resources> + </route> + <route url="/V1/customers/:id" method="GET"> + <resources> + <resource ref="Magento_Customer::read" /> + </resources> + </route> +</routes> From d0723579e59dae8a4c19b1e8a732557654cff725 Mon Sep 17 00:00:00 2001 From: Oleksandr Miroshnichenko <omiroshnichenko@magento.com> Date: Thu, 4 Apr 2019 16:03:30 -0500 Subject: [PATCH 219/773] MC-13806: Replace rand with random_int --- lib/internal/Magento/Framework/Encryption/Crypt.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/Encryption/Crypt.php b/lib/internal/Magento/Framework/Encryption/Crypt.php index d52db40b395ab..29f4397dec94b 100644 --- a/lib/internal/Magento/Framework/Encryption/Crypt.php +++ b/lib/internal/Magento/Framework/Encryption/Crypt.php @@ -66,7 +66,7 @@ public function __construct( $allowedCharacters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; $initVector = ''; for ($i = 0; $i < $initVectorSize; $i++) { - $initVector .= $allowedCharacters[rand(0, strlen($allowedCharacters) - 1)]; + $initVector .= $allowedCharacters[random_int(0, strlen($allowedCharacters) - 1)]; } // @codingStandardsIgnoreStart @mcrypt_generic_deinit($handle); From 6d34d895cb2c2154122d5c13f1cb773400f3bf3d Mon Sep 17 00:00:00 2001 From: Cari Spruiell <spruiell@adobe.com> Date: Thu, 4 Apr 2019 17:01:25 -0500 Subject: [PATCH 220/773] MC-5894: Gift Card Account --- .../src/Magento/Setup/Fixtures/BundleProductsFixture.php | 3 ++- .../Setup/Fixtures/ConfigurableProductsFixture.php | 7 ++++++- setup/src/Magento/Setup/Fixtures/OrdersFixture.php | 7 ++++--- .../src/Magento/Setup/Fixtures/SimpleProductsFixture.php | 8 ++++++-- 4 files changed, 18 insertions(+), 7 deletions(-) diff --git a/setup/src/Magento/Setup/Fixtures/BundleProductsFixture.php b/setup/src/Magento/Setup/Fixtures/BundleProductsFixture.php index 1b6e66202297d..e22c051749c6d 100644 --- a/setup/src/Magento/Setup/Fixtures/BundleProductsFixture.php +++ b/setup/src/Magento/Setup/Fixtures/BundleProductsFixture.php @@ -165,8 +165,9 @@ public function execute() 'sku' => $skuClosure, 'meta_title' => $skuClosure, 'price' => function ($index) use ($priceTypeClosure) { + // phpcs:ignore Magento2.Functions.DiscouragedFunction return $priceTypeClosure($index) === LinkInterface::PRICE_TYPE_PERCENT - ? random_int(10, 90) + ? mt_rand(10, 90) : $this->priceProvider->getPrice(); }, 'priceType' => $priceTypeClosure, diff --git a/setup/src/Magento/Setup/Fixtures/ConfigurableProductsFixture.php b/setup/src/Magento/Setup/Fixtures/ConfigurableProductsFixture.php index 0ffd98a435fa3..7d618b46df209 100644 --- a/setup/src/Magento/Setup/Fixtures/ConfigurableProductsFixture.php +++ b/setup/src/Magento/Setup/Fixtures/ConfigurableProductsFixture.php @@ -320,9 +320,12 @@ private function getDefaultAttributeSetsConfig(array $defaultAttributeSets, $con { $attributeSetClosure = function ($index) use ($defaultAttributeSets) { $attributeSetAmount = count(array_keys($defaultAttributeSets)); + // phpcs:ignore Magento2.Functions.DiscouragedFunction + mt_srand($index); + // phpcs:ignore Magento2.Functions.DiscouragedFunction return $attributeSetAmount > ($index - 1) % (int)$this->fixtureModel->getValue('categories', 30) - ? array_keys($defaultAttributeSets)[random_int(0, $attributeSetAmount - 1)] + ? array_keys($defaultAttributeSets)[mt_rand(0, $attributeSetAmount - 1)] : 'Default'; }; $productsPerSet = []; @@ -877,6 +880,8 @@ private function getDescriptionClosure( $configurableProductsCount / ($simpleProductsCount + $configurableProductsCount) ) ); + // phpcs:ignore Magento2.Functions.DiscouragedFunction + mt_srand($index); return $this->dataGenerator->generate( $minAmountOfWordsDescription, $maxAmountOfWordsDescription, diff --git a/setup/src/Magento/Setup/Fixtures/OrdersFixture.php b/setup/src/Magento/Setup/Fixtures/OrdersFixture.php index b6455e4d138f4..936a82bebf246 100644 --- a/setup/src/Magento/Setup/Fixtures/OrdersFixture.php +++ b/setup/src/Magento/Setup/Fixtures/OrdersFixture.php @@ -324,10 +324,11 @@ public function execute() $entityId++; while ($entityId <= $requestedOrders) { $batchNumber++; + // phpcs:ignore Magento2.Functions.DiscouragedFunction $productCount = [ - Type::TYPE_SIMPLE => random_int($orderSimpleCountFrom, $orderSimpleCountTo), - Configurable::TYPE_CODE => random_int($orderConfigurableCountFrom, $orderConfigurableCountTo), - self::BIG_CONFIGURABLE_TYPE => random_int($orderBigConfigurableCountFrom, $orderBigConfigurableCountTo) + Type::TYPE_SIMPLE => mt_rand($orderSimpleCountFrom, $orderSimpleCountTo), + Configurable::TYPE_CODE => mt_rand($orderConfigurableCountFrom, $orderConfigurableCountTo), + self::BIG_CONFIGURABLE_TYPE => mt_rand($orderBigConfigurableCountFrom, $orderBigConfigurableCountTo) ]; $order = [ '%itemsPerOrder%' => array_sum($productCount), diff --git a/setup/src/Magento/Setup/Fixtures/SimpleProductsFixture.php b/setup/src/Magento/Setup/Fixtures/SimpleProductsFixture.php index ce3bc2c7cfcb3..803a9b5cc12f3 100644 --- a/setup/src/Magento/Setup/Fixtures/SimpleProductsFixture.php +++ b/setup/src/Magento/Setup/Fixtures/SimpleProductsFixture.php @@ -186,9 +186,12 @@ public function execute() $additionalAttributeSets = $this->getAdditionalAttributeSets(); $attributeSet = function ($index) use ($defaultAttributeSets, $additionalAttributeSets) { + // phpcs:ignore Magento2.Functions.DiscouragedFunction + mt_srand($index); $attributeSetCount = count(array_keys($defaultAttributeSets)); if ($attributeSetCount > (($index - 1) % (int)$this->fixtureModel->getValue('categories', 30))) { - return array_keys($defaultAttributeSets)[random_int(0, count(array_keys($defaultAttributeSets)) - 1)]; + // phpcs:ignore Magento2.Functions.DiscouragedFunction + return array_keys($defaultAttributeSets)[mt_rand(0, count(array_keys($defaultAttributeSets)) - 1)]; } else { $customSetsAmount = count($additionalAttributeSets); return $customSetsAmount @@ -207,7 +210,8 @@ public function execute() $attributeValues = []; if (isset($defaultAttributeSets[$attributeSetId])) { foreach ($defaultAttributeSets[$attributeSetId] as $attributeCode => $values) { - $attributeValues[$attributeCode] = $values[random_int(0, count($values) - 1)]; + // phpcs:ignore Magento2.Functions.DiscouragedFunction + $attributeValues[$attributeCode] = $values[mt_rand(0, count($values) - 1)]; } } From a83762680d7bdb36be5f9e12a0a4cbda7684560c Mon Sep 17 00:00:00 2001 From: OlgaVasyltsun <olga.vasyltsun@gmail.com> Date: Fri, 5 Apr 2019 09:56:07 +0300 Subject: [PATCH 221/773] MC-10858: Escaper refactor --- app/code/Magento/Sales/Helper/Admin.php | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Sales/Helper/Admin.php b/app/code/Magento/Sales/Helper/Admin.php index ae283d729ac06..6f5389c5a33de 100644 --- a/app/code/Magento/Sales/Helper/Admin.php +++ b/app/code/Magento/Sales/Helper/Admin.php @@ -8,7 +8,7 @@ namespace Magento\Sales\Helper; use Magento\Framework\App\ObjectManager; -use Symfony\Component\DomCrawler\Crawler; +use Symfony\Component\DomCrawler\CrawlerFactory; /** * Sales admin helper. @@ -35,24 +35,32 @@ class Admin extends \Magento\Framework\App\Helper\AbstractHelper */ protected $escaper; + /** + * @var CrawlerFactory + */ + private $crawlerFactory; + /** * @param \Magento\Framework\App\Helper\Context $context * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\Sales\Model\Config $salesConfig * @param \Magento\Framework\Pricing\PriceCurrencyInterface $priceCurrency * @param \Magento\Framework\Escaper $escaper + * @param CrawlerFactory $crawlerFactory */ public function __construct( \Magento\Framework\App\Helper\Context $context, \Magento\Store\Model\StoreManagerInterface $storeManager, \Magento\Sales\Model\Config $salesConfig, \Magento\Framework\Pricing\PriceCurrencyInterface $priceCurrency, - \Magento\Framework\Escaper $escaper + \Magento\Framework\Escaper $escaper, + CrawlerFactory $crawlerFactory = null ) { $this->priceCurrency = $priceCurrency; $this->_storeManager = $storeManager; $this->_salesConfig = $salesConfig; $this->escaper = $escaper; + $this->crawlerFactory = $crawlerFactory ?: ObjectManager::getInstance()->get(CrawlerFactory::class); parent::__construct($context); } @@ -153,8 +161,7 @@ public function applySalableProductTypesFilter($collection) public function escapeHtmlWithLinks($data, $allowedTags = null) { if (!empty($data) && is_array($allowedTags) && in_array('a', $allowedTags)) { - $crawler = ObjectManager::getInstance()->create( - Crawler::class, + $crawler = $this->crawlerFactory->create( [ 'node' => '<html><body>' . $data . '</body></html>', ] From 9364787d9445c7d698492e3819aa98c7ed0d7897 Mon Sep 17 00:00:00 2001 From: AnnaShepilova <angymay01@gmail.com> Date: Wed, 3 Apr 2019 16:25:01 +0200 Subject: [PATCH 222/773] BeanShells are changed to correct using of variables --- setup/performance-toolkit/benchmark.jmx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/setup/performance-toolkit/benchmark.jmx b/setup/performance-toolkit/benchmark.jmx index c0d57ba0e2cef..cda123b00d71a 100644 --- a/setup/performance-toolkit/benchmark.jmx +++ b/setup/performance-toolkit/benchmark.jmx @@ -1503,6 +1503,7 @@ props.put("cms_pages", cmsPages); <stringProp name="BeanShellSampler.query">import java.util.ArrayList; import java.util.HashMap; import org.apache.commons.codec.binary.Base64; +ArrayList productList; // If it is first iteration of cycle then recreate productList if (1 == Integer.parseInt(vars.get("configurable_products_counter"))) { @@ -1641,12 +1642,13 @@ productList.add(productMap);</stringProp> <stringProp name="BeanShellSampler.query">import java.util.ArrayList; import java.util.HashMap; import org.apache.commons.codec.binary.Base64; +ArrayList editProductList; if (1 == Integer.parseInt(vars.get("configurable_products_counter_for_edit"))) { editProductList = new ArrayList(); props.put("configurable_products_list_for_edit", editProductList); } else { - productList = props.get("configurable_products_list_for_edit"); + editProductList = props.get("configurable_products_list_for_edit"); } String productUrl = vars.get("request_protocol") + "://" + vars.get("host") + vars.get("base_path") + vars.get("configurable_products_for_edit_url_keys_" + vars.get("configurable_products_counter_for_edit"))+ vars.get("url_suffix"); @@ -1785,6 +1787,7 @@ editProductList.add(editProductMap);</stringProp> <stringProp name="BeanShellSampler.query">import java.util.ArrayList; import java.util.HashMap; import org.apache.commons.codec.binary.Base64; +ArrayList productList; // If it is first iteration of cycle then recreate productList if (1 == Integer.parseInt(vars.get("simple_products_counter"))) { @@ -1936,12 +1939,13 @@ productList.add(productMap);</stringProp> <stringProp name="BeanShellSampler.query">import java.util.ArrayList; import java.util.HashMap; import org.apache.commons.codec.binary.Base64; +ArrayList editProductList; if (1 == Integer.parseInt(vars.get("simple_products_counter_for_edit"))) { editProductList = new ArrayList(); props.put("simple_products_list_for_edit", editProductList); } else { - productList = props.get("simple_products_counter_for_edit"); + editProductList = props.get("simple_products_list_for_edit"); } String productUrl = vars.get("request_protocol") + "://" + vars.get("host") + vars.get("base_path") + vars.get("simple_products_for_edit_url_keys_" + vars.get("simple_products_counter_for_edit"))+ vars.get("url_suffix"); From 2cd9195073a6bd29fbc8b9ae40ebf1ea136b62cd Mon Sep 17 00:00:00 2001 From: OlgaVasyltsun <olga.vasyltsun@gmail.com> Date: Fri, 5 Apr 2019 12:34:51 +0300 Subject: [PATCH 223/773] MC-11046: Newsletter Template update --- .../Test/Mftf/Test/AdminAddImageToWYSIWYGNewsletterTest.xml | 1 + .../Test/Mftf/Test/AdminAddVariableToWYSIWYGNewsletterTest.xml | 1 + .../Test/Mftf/Test/AdminAddWidgetToWYSIWYGNewsletterTest.xml | 1 + .../Test/VerifyTinyMCEv4IsNativeWYSIWYGOnNewsletterTest.xml | 1 + .../view/adminhtml/templates/preview/iframeswitcher.phtml | 2 +- 5 files changed, 5 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddImageToWYSIWYGNewsletterTest.xml b/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddImageToWYSIWYGNewsletterTest.xml index f69f94dbd79e3..582e0f37fba49 100644 --- a/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddImageToWYSIWYGNewsletterTest.xml +++ b/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddImageToWYSIWYGNewsletterTest.xml @@ -51,6 +51,7 @@ <waitForPageLoad stepKey="waitForPageLoad11"/> <click selector="{{NewsletterWYSIWYGSection.Preview(_defaultNewsletter.name)}}" stepKey="clickPreview"/> <switchToWindow stepKey="switchToWindow" userInput="action_window"/> + <executeJS function="document.getElementById('preview_iframe').sandbox.add('allow-scripts')" stepKey="addSandboxValue"/> <switchToIFrame userInput="preview_iframe" stepKey="switchToIframe" /> <waitForPageLoad stepKey="waitForPageLoad9"/> <!--Verify that the text and image are present--> diff --git a/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddVariableToWYSIWYGNewsletterTest.xml b/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddVariableToWYSIWYGNewsletterTest.xml index e3d73fb57333e..c17f397dfdb38 100644 --- a/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddVariableToWYSIWYGNewsletterTest.xml +++ b/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddVariableToWYSIWYGNewsletterTest.xml @@ -83,6 +83,7 @@ <waitForPageLoad stepKey="waitForPageLoad9" /> <click selector="{{NewsletterWYSIWYGSection.Preview(_defaultNewsletter.name)}}" stepKey="clickPreview1" /> <switchToWindow userInput="action_window" stepKey="switchToWindow1"/> + <executeJS function="document.getElementById('preview_iframe').sandbox.add('allow-scripts')" stepKey="addSandboxValue"/> <switchToIFrame userInput="preview_iframe" stepKey="switchToIframe1" /> <waitForPageLoad stepKey="waitForPageLoad7"/> <!--see Default Variable on Storefront--> diff --git a/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddWidgetToWYSIWYGNewsletterTest.xml b/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddWidgetToWYSIWYGNewsletterTest.xml index 50a6b74a67233..29f67b26edb2f 100644 --- a/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddWidgetToWYSIWYGNewsletterTest.xml +++ b/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddWidgetToWYSIWYGNewsletterTest.xml @@ -48,6 +48,7 @@ <waitForPageLoad stepKey="waitForPageLoad10" /> <click selector="{{NewsletterWYSIWYGSection.Preview(_defaultNewsletter.name)}}" stepKey="clickPreview" /> <switchToWindow stepKey="switchToWindow" userInput="action_window"/> + <executeJS function="document.getElementById('preview_iframe').sandbox.add('allow-scripts')" stepKey="addSandboxValue"/> <switchToIFrame userInput="preview_iframe" stepKey="switchToIframe" /> <waitForText userInput="Home page" stepKey="waitForPageLoad9"/> <see userInput="Home page" stepKey="seeHomePageCMSPage"/> diff --git a/app/code/Magento/Newsletter/Test/Mftf/Test/VerifyTinyMCEv4IsNativeWYSIWYGOnNewsletterTest.xml b/app/code/Magento/Newsletter/Test/Mftf/Test/VerifyTinyMCEv4IsNativeWYSIWYGOnNewsletterTest.xml index 3c19a3fa99d3c..7e2395e90181f 100644 --- a/app/code/Magento/Newsletter/Test/Mftf/Test/VerifyTinyMCEv4IsNativeWYSIWYGOnNewsletterTest.xml +++ b/app/code/Magento/Newsletter/Test/Mftf/Test/VerifyTinyMCEv4IsNativeWYSIWYGOnNewsletterTest.xml @@ -42,6 +42,7 @@ <waitForPageLoad stepKey="waitForPageLoad3" /> <click selector="{{NewsletterWYSIWYGSection.Preview(_defaultNewsletter.name)}}" stepKey="clickPreview" /> <switchToWindow stepKey="switchToWindow" userInput="action_window"/> + <executeJS function="document.getElementById('preview_iframe').sandbox.add('allow-scripts')" stepKey="addSandboxValue"/> <switchToIFrame userInput="preview_iframe" stepKey="switchToIframe" /> <waitForText userInput="Hello World From Newsletter Template!" stepKey="waitForPageLoad2"/> <see userInput="Hello World From Newsletter Template!" stepKey="seeContent" /> diff --git a/app/code/Magento/Newsletter/view/adminhtml/templates/preview/iframeswitcher.phtml b/app/code/Magento/Newsletter/view/adminhtml/templates/preview/iframeswitcher.phtml index 532ecde456077..720a3930b2db7 100644 --- a/app/code/Magento/Newsletter/view/adminhtml/templates/preview/iframeswitcher.phtml +++ b/app/code/Magento/Newsletter/view/adminhtml/templates/preview/iframeswitcher.phtml @@ -22,7 +22,7 @@ frameborder="0" title="<?= $block->escapeHtmlAttr(__('Preview')) ?>" width="100%" - sandbox="allow-forms allow-pointer-lock allow-scripts" + sandbox="allow-forms allow-pointer-lock" > </iframe> From f06a4b74840de2a7c6697787e27be48d43e5fb90 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Thu, 28 Mar 2019 17:25:47 +0200 Subject: [PATCH 224/773] magento/magento2#18075: Constant fix. --- .../Magento/Framework/Config/ConfigOptionsListConstants.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/Config/ConfigOptionsListConstants.php b/lib/internal/Magento/Framework/Config/ConfigOptionsListConstants.php index 909208d75b698..9e10b316ed213 100644 --- a/lib/internal/Magento/Framework/Config/ConfigOptionsListConstants.php +++ b/lib/internal/Magento/Framework/Config/ConfigOptionsListConstants.php @@ -118,7 +118,11 @@ class ConfigOptionsListConstants const KEY_MYSQL_SSL_KEY = \PDO::MYSQL_ATTR_SSL_KEY; const KEY_MYSQL_SSL_CERT = \PDO::MYSQL_ATTR_SSL_CERT; const KEY_MYSQL_SSL_CA = \PDO::MYSQL_ATTR_SSL_CA; - const KEY_MYSQL_SSL_VERIFY = \PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT; + /** + * Constant \PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT cannot be used as it was introduced in PHP 7.1.4 + * and Magento 2 is currently supporting PHP 7.1.3. + */ + const KEY_MYSQL_SSL_VERIFY = 1014; /**#@-*/ /** From 7d7f79884714523371412921ff8181c8a3f1031d Mon Sep 17 00:00:00 2001 From: Oleksandr Miroshnichenko <omiroshnichenko@magento.com> Date: Fri, 5 Apr 2019 09:43:40 -0500 Subject: [PATCH 225/773] MC-13806: Replace rand with random_int - fix static tests --- .../Magento/Framework/Encryption/Crypt.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/internal/Magento/Framework/Encryption/Crypt.php b/lib/internal/Magento/Framework/Encryption/Crypt.php index 29f4397dec94b..930cfa7a44f68 100644 --- a/lib/internal/Magento/Framework/Encryption/Crypt.php +++ b/lib/internal/Magento/Framework/Encryption/Crypt.php @@ -41,13 +41,13 @@ class Crypt /** * Constructor * - * @param string $key Secret encryption key. - * It's unsafe to store encryption key in memory, so no getter for key exists. - * @param string $cipher Cipher algorithm (one of the MCRYPT_ciphername constants) - * @param string $mode Mode of cipher algorithm (MCRYPT_MODE_modeabbr constants) - * @param string|bool $initVector Initial vector to fill algorithm blocks. - * TRUE generates a random initial vector. - * FALSE fills initial vector with zero bytes to not use it. + * @param string $key Secret encryption key. + * It's unsafe to store encryption key in memory, so no getter for key exists. + * @param string $cipher Cipher algorithm (one of the MCRYPT_ciphername constants) + * @param string $mode Mode of cipher algorithm (MCRYPT_MODE_modeabbr constants) + * @param string|bool $initVector Initial vector to fill algorithm blocks. + * TRUE generates a random initial vector. + * FALSE fills initial vector with zero bytes to not use it. * @throws \Exception */ public function __construct( From cf153cfec482c9d3882f903aff2eac138f670b06 Mon Sep 17 00:00:00 2001 From: Hwashiang Yu <hwyu@adobe.com> Date: Fri, 5 Apr 2019 13:24:21 -0500 Subject: [PATCH 226/773] MC-15662: Currency symbol template update - Updated data template --- .../adminhtml/templates/order/create/data.phtml | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/app/code/Magento/Sales/view/adminhtml/templates/order/create/data.phtml b/app/code/Magento/Sales/view/adminhtml/templates/order/create/data.phtml index 170fea937348d..5e40327cfe88b 100644 --- a/app/code/Magento/Sales/view/adminhtml/templates/order/create/data.phtml +++ b/app/code/Magento/Sales/view/adminhtml/templates/order/create/data.phtml @@ -4,13 +4,11 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - ?> <div class="page-create-order"> <script> require(["Magento_Sales/order/create/form"], function(){ - order.setCurrencySymbol('<?= /* @escapeNotVerified */ $block->getCurrencySymbol($block->getCurrentCurrencyCode()) ?>') + order.setCurrencySymbol('<?= $block->escapeJs($block->getCurrencySymbol($block->getCurrentCurrencyCode())) ?>') }); </script> <div class="order-details<?php if ($block->getCustomerId()): ?> order-details-existing-customer<?php endif; ?>"> @@ -35,7 +33,7 @@ <section id="order-addresses" class="admin__page-section order-addresses"> <div class="admin__page-section-title"> - <span class="title"><?= /* @escapeNotVerified */ __('Address Information') ?></span> + <span class="title"><?= $block->escapeHtml(__('Address Information')) ?></span> </div> <div class="admin__page-section-content"> <div id="order-billing_address" class="admin__page-section-item order-billing-address"> @@ -69,11 +67,11 @@ <section class="admin__page-section order-summary"> <div class="admin__page-section-title"> - <span class="title"><?= /* @escapeNotVerified */ __('Order Total') ?></span> + <span class="title"><?= $block->escapeHtml(__('Order Total')) ?></span> </div> <div class="admin__page-section-content"> <fieldset class="admin__fieldset order-history" id="order-comment"> - <legend class="admin__legend"><span><?= /* @escapeNotVerified */ __('Order History') ?></span></legend> + <legend class="admin__legend"><span><?= $block->escapeHtml(__('Order History')) ?></span></legend> <br> <?= $block->getChildHtml('comment') ?> </fieldset> @@ -88,15 +86,15 @@ <div class="order-sidebar"> <div class="store-switcher order-currency"> <label class="admin__field-label" for="currency_switcher"> - <?= /* @escapeNotVerified */ __('Order Currency:') ?> + <?= $block->escapeHtml(__('Order Currency:')) ?> </label> <select id="currency_switcher" class="admin__control-select" name="order[currency]" onchange="order.setCurrencyId(this.value); order.setCurrencySymbol(this.options[this.selectedIndex].getAttribute('symbol'));"> <?php foreach ($block->getAvailableCurrencies() as $_code): ?> - <option value="<?= /* @escapeNotVerified */ $_code ?>"<?php if ($_code == $block->getCurrentCurrencyCode()): ?> selected="selected"<?php endif; ?> symbol="<?= /* @escapeNotVerified */ $block->getCurrencySymbol($_code) ?>"> - <?= /* @escapeNotVerified */ $block->getCurrencyName($_code) ?> + <option value="<?= $block->escapeHtmlAttr($_code) ?>"<?php if ($_code == $block->getCurrentCurrencyCode()): ?> selected="selected"<?php endif; ?> symbol="<?=$block->escapeHtmlAttr($block->getCurrencySymbol($_code)) ?>"> + <?= $block->escapeHtml($block->getCurrencyName($_code)) ?> </option> <?php endforeach; ?> </select> From 14ea7da376022e99eb217e554b86253e8927c714 Mon Sep 17 00:00:00 2001 From: Cari Spruiell <spruiell@adobe.com> Date: Fri, 5 Apr 2019 10:50:24 -0500 Subject: [PATCH 227/773] MC-5894: Gift Card Account --- .../Magento/Setup/Fixtures/BundleProductsFixture.php | 6 +++--- .../Setup/Fixtures/ConfigurableProductsFixture.php | 8 ++++---- .../Setup/Fixtures/ImagesGenerator/ImagesGenerator.php | 2 +- setup/src/Magento/Setup/Fixtures/PriceProvider.php | 10 +++++++--- .../Magento/Setup/Fixtures/SimpleProductsFixture.php | 8 +++++--- 5 files changed, 20 insertions(+), 14 deletions(-) diff --git a/setup/src/Magento/Setup/Fixtures/BundleProductsFixture.php b/setup/src/Magento/Setup/Fixtures/BundleProductsFixture.php index e22c051749c6d..3ad22e8f7bcd1 100644 --- a/setup/src/Magento/Setup/Fixtures/BundleProductsFixture.php +++ b/setup/src/Magento/Setup/Fixtures/BundleProductsFixture.php @@ -127,8 +127,8 @@ public function execute() $fixtureMap = [ 'name' => $variationSkuClosure, 'sku' => $variationSkuClosure, - 'price' => function () { - return $this->priceProvider->getPrice(); + 'price' => function ($index, $entityNumber) { + return $this->priceProvider->getPrice($entityNumber); }, 'website_ids' => function ($index, $entityNumber) use ($variationCount) { $configurableIndex = $this->getBundleProductIndex($entityNumber, $variationCount); @@ -168,7 +168,7 @@ public function execute() // phpcs:ignore Magento2.Functions.DiscouragedFunction return $priceTypeClosure($index) === LinkInterface::PRICE_TYPE_PERCENT ? mt_rand(10, 90) - : $this->priceProvider->getPrice(); + : $this->priceProvider->getPrice($index); }, 'priceType' => $priceTypeClosure, 'website_ids' => function ($index, $entityNumber) { diff --git a/setup/src/Magento/Setup/Fixtures/ConfigurableProductsFixture.php b/setup/src/Magento/Setup/Fixtures/ConfigurableProductsFixture.php index 7d618b46df209..8c2aed521dbe8 100644 --- a/setup/src/Magento/Setup/Fixtures/ConfigurableProductsFixture.php +++ b/setup/src/Magento/Setup/Fixtures/ConfigurableProductsFixture.php @@ -255,8 +255,8 @@ public function execute() $fixture = [ 'name' => $variationSkuClosure, 'sku' => $variationSkuClosure, - 'price' => function () { - return $this->priceProvider->getPrice(); + 'price' => function ($index, $entityNumber) { + return $this->priceProvider->getPrice($entityNumber); }, 'website_ids' => function ($index, $entityNumber) use ($variationCount) { $configurableIndex = $this->getConfigurableProductIndex($entityNumber, $variationCount); @@ -320,7 +320,7 @@ private function getDefaultAttributeSetsConfig(array $defaultAttributeSets, $con { $attributeSetClosure = function ($index) use ($defaultAttributeSets) { $attributeSetAmount = count(array_keys($defaultAttributeSets)); - // phpcs:ignore Magento2.Functions.DiscouragedFunction + // phpcs:ignore mt_srand($index); // phpcs:ignore Magento2.Functions.DiscouragedFunction @@ -880,7 +880,7 @@ private function getDescriptionClosure( $configurableProductsCount / ($simpleProductsCount + $configurableProductsCount) ) ); - // phpcs:ignore Magento2.Functions.DiscouragedFunction + // phpcs:ignore mt_srand($index); return $this->dataGenerator->generate( $minAmountOfWordsDescription, diff --git a/setup/src/Magento/Setup/Fixtures/ImagesGenerator/ImagesGenerator.php b/setup/src/Magento/Setup/Fixtures/ImagesGenerator/ImagesGenerator.php index 7173e54716cce..cfcdebd4ac373 100644 --- a/setup/src/Magento/Setup/Fixtures/ImagesGenerator/ImagesGenerator.php +++ b/setup/src/Magento/Setup/Fixtures/ImagesGenerator/ImagesGenerator.php @@ -52,7 +52,7 @@ public function generate($config) $image = imagecreate($config['image-width'], $config['image-height']); $bgColor = imagecolorallocate($image, 240, 240, 240); - $fgColor = imagecolorallocate($image, random_int(0, 230), random_int(0, 230), random_int(0, 230)); + $fgColor = imagecolorallocate($image, mt_rand(0, 230), mt_rand(0, 230), mt_rand(0, 230)); $colors = [$fgColor, $bgColor]; imagefilledrectangle($image, 0, 0, $config['image-width'], $config['image-height'], $bgColor); diff --git a/setup/src/Magento/Setup/Fixtures/PriceProvider.php b/setup/src/Magento/Setup/Fixtures/PriceProvider.php index c19ea4d683ca5..63ad3f0be6bb2 100644 --- a/setup/src/Magento/Setup/Fixtures/PriceProvider.php +++ b/setup/src/Magento/Setup/Fixtures/PriceProvider.php @@ -14,11 +14,14 @@ class PriceProvider /** * Get random price for product * + * @param int $productIndex * @return float */ - public function getPrice() + public function getPrice($productIndex) { - switch (random_int(0, 3)) { + // phpcs:disable + mt_srand($productIndex); + switch (mt_rand(0, 3)) { case 0: return 9.99; case 1: @@ -26,7 +29,8 @@ public function getPrice() case 2: return 1; case 3: - return random_int(1, 10000) / 10; + return mt_rand(1, 10000) / 10; } + // phpcs:enable } } diff --git a/setup/src/Magento/Setup/Fixtures/SimpleProductsFixture.php b/setup/src/Magento/Setup/Fixtures/SimpleProductsFixture.php index 803a9b5cc12f3..8e2e842a7d805 100644 --- a/setup/src/Magento/Setup/Fixtures/SimpleProductsFixture.php +++ b/setup/src/Magento/Setup/Fixtures/SimpleProductsFixture.php @@ -186,7 +186,7 @@ public function execute() $additionalAttributeSets = $this->getAdditionalAttributeSets(); $attributeSet = function ($index) use ($defaultAttributeSets, $additionalAttributeSets) { - // phpcs:ignore Magento2.Functions.DiscouragedFunction + // phpcs:ignore mt_srand($index); $attributeSetCount = count(array_keys($defaultAttributeSets)); if ($attributeSetCount > (($index - 1) % (int)$this->fixtureModel->getValue('categories', 30))) { @@ -208,6 +208,8 @@ public function execute() $additionalAttributeSets ) { $attributeValues = []; + // phpcs:ignore + mt_srand($index); if (isset($defaultAttributeSets[$attributeSetId])) { foreach ($defaultAttributeSets[$attributeSetId] as $attributeCode => $values) { // phpcs:ignore Magento2.Functions.DiscouragedFunction @@ -225,8 +227,8 @@ public function execute() 'sku' => function ($productId) { return sprintf($this->getSkuPattern(), $productId); }, - 'price' => function () { - return $this->priceProvider->getPrice(); + 'price' => function ($index, $entityNumber) { + return $this->priceProvider->getPrice($entityNumber); }, 'url_key' => function ($productId) { return sprintf('simple-product-%s', $productId); From 5290c7b27437321048e732b9caf06a000612f07a Mon Sep 17 00:00:00 2001 From: OlgaVasyltsun <olga.vasyltsun@gmail.com> Date: Mon, 8 Apr 2019 08:18:22 +0300 Subject: [PATCH 228/773] MC-11046: Newsletter Template update --- .../Test/Mftf/Test/AdminAddVariableToWYSIWYGNewsletterTest.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddVariableToWYSIWYGNewsletterTest.xml b/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddVariableToWYSIWYGNewsletterTest.xml index c17f397dfdb38..510e46ce83197 100644 --- a/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddVariableToWYSIWYGNewsletterTest.xml +++ b/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddVariableToWYSIWYGNewsletterTest.xml @@ -85,7 +85,7 @@ <switchToWindow userInput="action_window" stepKey="switchToWindow1"/> <executeJS function="document.getElementById('preview_iframe').sandbox.add('allow-scripts')" stepKey="addSandboxValue"/> <switchToIFrame userInput="preview_iframe" stepKey="switchToIframe1" /> - <waitForPageLoad stepKey="waitForPageLoad7"/> + <waitForPageLoad time="30" stepKey="waitForPageLoad7"/> <!--see Default Variable on Storefront--> <see userInput="{{_defaultVariable.city}}" stepKey="seeDefaultVariable" /> <!--see Custom Variable on Storefront--> @@ -96,6 +96,7 @@ <amOnPage url="{{NewsletterTemplateGrid.url}}" stepKey="amOnTemplateGrid" /> <click selector="{{NewsletterWYSIWYGSection.Preview(_defaultNewsletter.name)}}" stepKey="clickPreview2" /> <switchToWindow userInput="action_window" stepKey="switchToWindow2"/> + <executeJS function="document.getElementById('preview_iframe').sandbox.add('allow-scripts')" stepKey="addSandboxValue1"/> <switchToIFrame userInput="preview_iframe" stepKey="switchToIframe2" /> <wait time="10" stepKey="waitForPageLoad8"/> <!--see custom variable blank--> From 186d9aa1dc3133fe038f9bd17ceb2d81ef0dc7c4 Mon Sep 17 00:00:00 2001 From: OlgaVasyltsun <olga.vasyltsun@gmail.com> Date: Mon, 8 Apr 2019 10:02:55 +0300 Subject: [PATCH 229/773] MC-11046: Newsletter Template update --- .../Test/Mftf/Test/AdminAddVariableToWYSIWYGNewsletterTest.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddVariableToWYSIWYGNewsletterTest.xml b/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddVariableToWYSIWYGNewsletterTest.xml index 510e46ce83197..0116c546d2964 100644 --- a/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddVariableToWYSIWYGNewsletterTest.xml +++ b/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddVariableToWYSIWYGNewsletterTest.xml @@ -84,6 +84,7 @@ <click selector="{{NewsletterWYSIWYGSection.Preview(_defaultNewsletter.name)}}" stepKey="clickPreview1" /> <switchToWindow userInput="action_window" stepKey="switchToWindow1"/> <executeJS function="document.getElementById('preview_iframe').sandbox.add('allow-scripts')" stepKey="addSandboxValue"/> + <wait time="30" stepKey="waitBeforeSwitchToIframe"/> <switchToIFrame userInput="preview_iframe" stepKey="switchToIframe1" /> <waitForPageLoad time="30" stepKey="waitForPageLoad7"/> <!--see Default Variable on Storefront--> From f36ef3aa5d07dddcfc73820bf800a0c8469b2d88 Mon Sep 17 00:00:00 2001 From: OlgaVasyltsun <olga.vasyltsun@gmail.com> Date: Mon, 8 Apr 2019 10:25:17 +0300 Subject: [PATCH 230/773] MC-10858: Escaper refactor --- app/code/Magento/Sales/Helper/Admin.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Sales/Helper/Admin.php b/app/code/Magento/Sales/Helper/Admin.php index 6f5389c5a33de..d71e248e615e2 100644 --- a/app/code/Magento/Sales/Helper/Admin.php +++ b/app/code/Magento/Sales/Helper/Admin.php @@ -46,7 +46,7 @@ class Admin extends \Magento\Framework\App\Helper\AbstractHelper * @param \Magento\Sales\Model\Config $salesConfig * @param \Magento\Framework\Pricing\PriceCurrencyInterface $priceCurrency * @param \Magento\Framework\Escaper $escaper - * @param CrawlerFactory $crawlerFactory + * @param CrawlerFactory|null $crawlerFactory */ public function __construct( \Magento\Framework\App\Helper\Context $context, From 194e97c9d3b660128712b86f2b4bf52a157e4f9d Mon Sep 17 00:00:00 2001 From: Andrii Meysar <andrii.meysar@transoftgroup.com> Date: Mon, 8 Apr 2019 11:54:25 +0300 Subject: [PATCH 231/773] MC-5892: Fixed incorrect template rendering --- .../Product/Form/Modifier/Categories.php | 1 + .../Form/Modifier/_files/expected_categories.php | 12 ++++++++++++ .../Model/Config/Source/Group/MultiselectTest.php | 9 +++++---- 3 files changed, 18 insertions(+), 4 deletions(-) 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 681435851fbde..0c93f6938d14e 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 @@ -362,6 +362,7 @@ protected function getCategoriesTree($filter = null) $categoryById[$category->getId()]['is_active'] = $category->getIsActive(); $categoryById[$category->getId()]['label'] = $category->getName(); + $categoryById[$category->getId()]['__disableTmpl'] = true; $categoryById[$category->getParentId()]['optgroup'][] = &$categoryById[$category->getId()]; } 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 index 744d368a467d5..beaa9f5dfb7f2 100644 --- 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 @@ -10,17 +10,20 @@ 'value' => '2', 'is_active' => '1', 'label' => 'Default Category', + '__disableTmpl' => true, 'optgroup' => [ 0 => [ 'value' => '3', 'is_active' => '1', 'label' => 'Category 1', + '__disableTmpl' => true, 'optgroup' => [ 0 => [ 'value' => '4', 'is_active' => '1', 'label' => 'Category 1.1', + '__disableTmpl' => true, 'optgroup' => [ 0 => @@ -28,6 +31,7 @@ 'value' => '5', 'is_active' => '1', 'label' => 'Category 1.1.1', + '__disableTmpl' => true, ], ], ], @@ -35,6 +39,7 @@ 'value' => '13', 'is_active' => '1', 'label' => 'Category 1.2', + '__disableTmpl' => true, ], ], ], @@ -42,36 +47,43 @@ 'value' => '6', 'is_active' => '1', 'label' => 'Category 2', + '__disableTmpl' => true, ], 2 => [ 'value' => '7', 'is_active' => '1', 'label' => 'Movable', + '__disableTmpl' => true, ], 3 => [ 'value' => '8', 'is_active' => '0', 'label' => 'Inactive', + '__disableTmpl' => true, ], 4 => [ 'value' => '9', 'is_active' => '1', 'label' => 'Movable Position 1', + '__disableTmpl' => true, ], 5 => [ 'value' => '10', 'is_active' => '1', 'label' => 'Movable Position 2', + '__disableTmpl' => true, ], 6 => [ 'value' => '11', 'is_active' => '1', 'label' => 'Movable Position 3', + '__disableTmpl' => true, ], 7 => [ 'value' => '12', 'is_active' => '1', 'label' => 'Category 12', + '__disableTmpl' => true, ], ], ], diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/Config/Source/Group/MultiselectTest.php b/dev/tests/integration/testsuite/Magento/Customer/Model/Config/Source/Group/MultiselectTest.php index 918b085580420..9f121268135f8 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Model/Config/Source/Group/MultiselectTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Model/Config/Source/Group/MultiselectTest.php @@ -35,22 +35,23 @@ public function testToOptionArray() [ [ 'value' => 1, - 'label' => 'Default (General)' + 'label' => 'Default (General)', + '__disableTmpl' => true, ], [ 'value' => 1, 'label' => 'General', - '__disableTmpl' => true + '__disableTmpl' => true, ], [ 'value' => 2, 'label' => 'Wholesale', - '__disableTmpl' => true + '__disableTmpl' => true, ], [ 'value' => 3, 'label' => 'Retailer', - '__disableTmpl' => true + '__disableTmpl' => true, ], ] ); From 72a5dd0e0068723c4f4a78bdbb5093c66dc7b6ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karla=20Saarem=C3=A4e?= <karlasaaremae@gmail.com> Date: Mon, 8 Apr 2019 14:09:31 +0300 Subject: [PATCH 232/773] add locale date format option add option to fallback to locale date format configuration --- app/code/Magento/Ui/view/base/web/js/grid/columns/date.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Ui/view/base/web/js/grid/columns/date.js b/app/code/Magento/Ui/view/base/web/js/grid/columns/date.js index 81c0cc1ccdbb7..3bd6ee4145bfb 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/columns/date.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/columns/date.js @@ -25,8 +25,8 @@ define([ */ initConfig: function () { this._super(); - - this.dateFormat = utils.normalizeDate(this.dateFormat); + + this.dateFormat = utils.normalizeDate(this.dateFormat ? this.dateFormat : this.options.dateFormat); return this; }, From 3f22c453d621f193222201536228a15b0593a05e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karla=20Saarem=C3=A4e?= <karlasaaremae@gmail.com> Date: Mon, 8 Apr 2019 14:23:30 +0300 Subject: [PATCH 233/773] remove spaces code clean up --- app/code/Magento/Ui/view/base/web/js/grid/columns/date.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Ui/view/base/web/js/grid/columns/date.js b/app/code/Magento/Ui/view/base/web/js/grid/columns/date.js index 3bd6ee4145bfb..d3cf55d663e12 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/columns/date.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/columns/date.js @@ -25,7 +25,7 @@ define([ */ initConfig: function () { this._super(); - + this.dateFormat = utils.normalizeDate(this.dateFormat ? this.dateFormat : this.options.dateFormat); return this; From afbb952f7e6c8ff8b85502c40b2a4b765ffc2c75 Mon Sep 17 00:00:00 2001 From: OlgaVasyltsun <olga.vasyltsun@gmail.com> Date: Mon, 8 Apr 2019 15:08:32 +0300 Subject: [PATCH 234/773] MC-11046: Newsletter Template update --- .../Test/Mftf/Test/AdminAddWidgetToWYSIWYGNewsletterTest.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddWidgetToWYSIWYGNewsletterTest.xml b/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddWidgetToWYSIWYGNewsletterTest.xml index 29f67b26edb2f..695ac82b9a800 100644 --- a/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddWidgetToWYSIWYGNewsletterTest.xml +++ b/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddWidgetToWYSIWYGNewsletterTest.xml @@ -49,6 +49,7 @@ <click selector="{{NewsletterWYSIWYGSection.Preview(_defaultNewsletter.name)}}" stepKey="clickPreview" /> <switchToWindow stepKey="switchToWindow" userInput="action_window"/> <executeJS function="document.getElementById('preview_iframe').sandbox.add('allow-scripts')" stepKey="addSandboxValue"/> + <wait time="30" stepKey="waitBeforeSwitchToIframe"/> <switchToIFrame userInput="preview_iframe" stepKey="switchToIframe" /> <waitForText userInput="Home page" stepKey="waitForPageLoad9"/> <see userInput="Home page" stepKey="seeHomePageCMSPage"/> From d2f66a0cb0a7f6454f49781f891c25490fbe96e7 Mon Sep 17 00:00:00 2001 From: OlgaVasyltsun <olga.vasyltsun@gmail.com> Date: Mon, 8 Apr 2019 16:28:24 +0300 Subject: [PATCH 235/773] MC-11046: Newsletter Template update --- .../Mftf/Test/VerifyTinyMCEv4IsNativeWYSIWYGOnNewsletterTest.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Newsletter/Test/Mftf/Test/VerifyTinyMCEv4IsNativeWYSIWYGOnNewsletterTest.xml b/app/code/Magento/Newsletter/Test/Mftf/Test/VerifyTinyMCEv4IsNativeWYSIWYGOnNewsletterTest.xml index 7e2395e90181f..7ecb576e29582 100644 --- a/app/code/Magento/Newsletter/Test/Mftf/Test/VerifyTinyMCEv4IsNativeWYSIWYGOnNewsletterTest.xml +++ b/app/code/Magento/Newsletter/Test/Mftf/Test/VerifyTinyMCEv4IsNativeWYSIWYGOnNewsletterTest.xml @@ -43,6 +43,7 @@ <click selector="{{NewsletterWYSIWYGSection.Preview(_defaultNewsletter.name)}}" stepKey="clickPreview" /> <switchToWindow stepKey="switchToWindow" userInput="action_window"/> <executeJS function="document.getElementById('preview_iframe').sandbox.add('allow-scripts')" stepKey="addSandboxValue"/> + <wait time="30" stepKey="waitBeforeSwitchToIframe"/> <switchToIFrame userInput="preview_iframe" stepKey="switchToIframe" /> <waitForText userInput="Hello World From Newsletter Template!" stepKey="waitForPageLoad2"/> <see userInput="Hello World From Newsletter Template!" stepKey="seeContent" /> From 9a746d74cbcb01866ec7f5dc888a74dc54695ce4 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Mon, 8 Apr 2019 21:46:11 +0300 Subject: [PATCH 236/773] MC-15424: Sitemap generation issues --- app/code/Magento/Sitemap/Model/Sitemap.php | 8 ++++++-- app/code/Magento/Sitemap/Test/Unit/Model/SitemapTest.php | 8 ++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Sitemap/Model/Sitemap.php b/app/code/Magento/Sitemap/Model/Sitemap.php index c35e20d997d85..2685bf59fcd0b 100644 --- a/app/code/Magento/Sitemap/Model/Sitemap.php +++ b/app/code/Magento/Sitemap/Model/Sitemap.php @@ -544,10 +544,10 @@ protected function _getSitemapRow($url, $lastmod = null, $changefreq = null, $pr $row .= '<lastmod>' . $this->_getFormattedLastmodDate($lastmod) . '</lastmod>'; } if ($changefreq) { - $row .= '<changefreq>' . $changefreq . '</changefreq>'; + $row .= '<changefreq>' . $this->_escaper->escapeHtml($changefreq) . '</changefreq>'; } if ($priority) { - $row .= sprintf('<priority>%.1f</priority>', $priority); + $row .= sprintf('<priority>%.1f</priority>', $this->_escaper->escapeHtml($priority)); } if ($images) { // Add Images to sitemap @@ -722,7 +722,9 @@ protected function _getFormattedLastmodDate($date) */ protected function _getDocumentRoot() { + // @codingStandardsIgnoreStart return realpath($this->_request->getServer('DOCUMENT_ROOT')); + // @codingStandardsIgnoreEnd } /** @@ -732,7 +734,9 @@ protected function _getDocumentRoot() */ protected function _getStoreBaseDomain() { + // @codingStandardsIgnoreStart $storeParsedUrl = parse_url($this->_getStoreBaseUrl()); + // @codingStandardsIgnoreEnd $url = $storeParsedUrl['scheme'] . '://' . $storeParsedUrl['host']; $documentRoot = trim(str_replace('\\', '/', $this->_getDocumentRoot()), '/'); diff --git a/app/code/Magento/Sitemap/Test/Unit/Model/SitemapTest.php b/app/code/Magento/Sitemap/Test/Unit/Model/SitemapTest.php index f805d4471553b..0aaf8f5f7b010 100644 --- a/app/code/Magento/Sitemap/Test/Unit/Model/SitemapTest.php +++ b/app/code/Magento/Sitemap/Test/Unit/Model/SitemapTest.php @@ -87,7 +87,7 @@ class SitemapTest extends \PHPUnit\Framework\TestCase private $configReaderMock; /** - * Set helper mocks, create resource model mock + * @inheritdoc */ protected function setUp() { @@ -162,7 +162,7 @@ public function testNotAllowedPath() * Check not exists sitemap path validation * * @expectedException \Magento\Framework\Exception\LocalizedException - * @expectedExceptionMessage Please create the specified folder "" before saving the sitemap. + * @expectedExceptionMessage Please create the specified folder "/" before saving the sitemap. */ public function testPathNotExists() { @@ -598,6 +598,9 @@ private function getModelConstructorArgs() ->getMockForAbstractClass(); $objectManager = new ObjectManager($this); + + $escaper = $objectManager->getObject(\Magento\Framework\Escaper::class); + $constructArguments = $objectManager->getConstructArguments( Sitemap::class, [ @@ -609,6 +612,7 @@ private function getModelConstructorArgs() 'filesystem' => $this->filesystemMock, 'itemProvider' => $this->itemProviderMock, 'configReader' => $this->configReaderMock, + 'escaper' => $escaper, ] ); $constructArguments['resource'] = null; From 1a8fbf29ca145ea7883f94d76faa8addb260e979 Mon Sep 17 00:00:00 2001 From: Mark Berube <berube@adobe.com> Date: Mon, 8 Apr 2019 16:49:23 -0500 Subject: [PATCH 237/773] MC-5881: Changing random string generation --- .../Magento/Captcha/Model/DefaultModel.php | 35 +++++++++-------- .../Captcha/Test/Unit/Model/DefaultTest.php | 38 +++++++++++++++++++ 2 files changed, 55 insertions(+), 18 deletions(-) diff --git a/app/code/Magento/Captcha/Model/DefaultModel.php b/app/code/Magento/Captcha/Model/DefaultModel.php index 483f9c3fb4d20..8ed434e420f94 100644 --- a/app/code/Magento/Captcha/Model/DefaultModel.php +++ b/app/code/Magento/Captcha/Model/DefaultModel.php @@ -3,13 +3,18 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Captcha\Model; use Magento\Captcha\Helper\Data; +use Magento\Framework\Math\Random; /** * Implementation of \Zend\Captcha\Image * + * @SuppressWarnings(PHPMD.CookieAndSessionMisuse) + * * @api * @since 100.0.2 */ @@ -83,24 +88,32 @@ class DefaultModel extends \Zend\Captcha\Image implements \Magento\Captcha\Model */ private $words; + /** + * @var Random + */ + private $randomMath; + /** * @param \Magento\Framework\Session\SessionManagerInterface $session * @param \Magento\Captcha\Helper\Data $captchaData * @param ResourceModel\LogFactory $resLogFactory * @param string $formId + * @param Random $randomMath * @throws \Zend\Captcha\Exception\ExtensionNotLoadedException */ public function __construct( \Magento\Framework\Session\SessionManagerInterface $session, \Magento\Captcha\Helper\Data $captchaData, \Magento\Captcha\Model\ResourceModel\LogFactory $resLogFactory, - $formId + $formId, + Random $randomMath = null ) { parent::__construct(); $this->session = $session; $this->captchaData = $captchaData; $this->resLogFactory = $resLogFactory; $this->formId = $formId; + $this->randomMath = $randomMath ?? \Magento\Framework\App\ObjectManager::getInstance()->get(Random::class); } /** @@ -382,23 +395,9 @@ public function setShowCaptchaInSession($value = true) */ protected function generateWord() { - $word = ''; - $symbols = $this->getSymbols(); + $symbols = (string)$this->captchaData->getConfig('symbols'); $wordLen = $this->getWordLen(); - for ($i = 0; $i < $wordLen; $i++) { - $word .= $symbols[array_rand($symbols)]; - } - return $word; - } - - /** - * Get symbols array to use for word generation - * - * @return array - */ - private function getSymbols() - { - return str_split((string)$this->captchaData->getConfig('symbols')); + return $this->randomMath->getRandomString($wordLen, $symbols); } /** @@ -562,7 +561,7 @@ protected function randomSize() */ protected function gc() { - //do nothing + return; // required for static testing to pass } /** diff --git a/app/code/Magento/Captcha/Test/Unit/Model/DefaultTest.php b/app/code/Magento/Captcha/Test/Unit/Model/DefaultTest.php index eef75d2c01ec7..a1206a06dccd0 100644 --- a/app/code/Magento/Captcha/Test/Unit/Model/DefaultTest.php +++ b/app/code/Magento/Captcha/Test/Unit/Model/DefaultTest.php @@ -3,8 +3,12 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Captcha\Test\Unit\Model; +use Magento\Framework\Math\Random; + /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ @@ -375,4 +379,38 @@ public function isShownToLoggedInUserDataProvider() [false, 'user_forgotpassword'] ]; } + + /** + * @param string $string + * @dataProvider generateWordProvider + * @throws \ReflectionException + */ + public function testGenerateWord($string) + { + $randomMock = $this->createMock(Random::class); + $randomMock->expects($this->once()) + ->method('getRandomString') + ->will($this->returnValue($string)); + $captcha = new \Magento\Captcha\Model\DefaultModel( + $this->session, + $this->_getHelperStub(), + $this->_resLogFactory, + 'user_create', + $randomMock + ); + $method = new \ReflectionMethod($captcha, 'generateWord'); + $method->setAccessible(true); + $this->assertEquals($string, $method->invoke($captcha)); + } + /** + * @return array + */ + public function generateWordProvider() + { + return [ + ['ABC123'], + ['1234567890'], + ['The quick brown fox jumps over the lazy dog.'] + ]; + } } From ba04a56071e9dc54b786308546d9fb8f32735a6c Mon Sep 17 00:00:00 2001 From: OlgaVasyltsun <olga.vasyltsun@gmail.com> Date: Tue, 9 Apr 2019 13:53:16 +0300 Subject: [PATCH 238/773] MC-11046: Newsletter Template update --- .../AdminNewsletterTemplateActionGroup.xml | 16 ++++++++++++++++ .../AdminAddImageToWYSIWYGNewsletterTest.xml | 4 +--- .../AdminAddVariableToWYSIWYGNewsletterTest.xml | 9 ++------- .../AdminAddWidgetToWYSIWYGNewsletterTest.xml | 4 +--- ...yTinyMCEv4IsNativeWYSIWYGOnNewsletterTest.xml | 4 +--- 5 files changed, 21 insertions(+), 16 deletions(-) create mode 100644 app/code/Magento/Newsletter/Test/Mftf/ActionGroup/AdminNewsletterTemplateActionGroup.xml diff --git a/app/code/Magento/Newsletter/Test/Mftf/ActionGroup/AdminNewsletterTemplateActionGroup.xml b/app/code/Magento/Newsletter/Test/Mftf/ActionGroup/AdminNewsletterTemplateActionGroup.xml new file mode 100644 index 0000000000000..31d54e492ddd2 --- /dev/null +++ b/app/code/Magento/Newsletter/Test/Mftf/ActionGroup/AdminNewsletterTemplateActionGroup.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="SwitchToIframeActionGroup"> + <executeJS function="document.getElementById('preview_iframe').sandbox.add('allow-scripts')" stepKey="addSandboxValue"/> + <wait time="10" stepKey="waitBeforeSwitchToIframe"/> + <switchToIFrame userInput="preview_iframe" stepKey="switchToIframe" /> + <waitForPageLoad stepKey="waitForPageLoad"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddImageToWYSIWYGNewsletterTest.xml b/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddImageToWYSIWYGNewsletterTest.xml index 582e0f37fba49..f9172f8f2bf65 100644 --- a/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddImageToWYSIWYGNewsletterTest.xml +++ b/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddImageToWYSIWYGNewsletterTest.xml @@ -51,9 +51,7 @@ <waitForPageLoad stepKey="waitForPageLoad11"/> <click selector="{{NewsletterWYSIWYGSection.Preview(_defaultNewsletter.name)}}" stepKey="clickPreview"/> <switchToWindow stepKey="switchToWindow" userInput="action_window"/> - <executeJS function="document.getElementById('preview_iframe').sandbox.add('allow-scripts')" stepKey="addSandboxValue"/> - <switchToIFrame userInput="preview_iframe" stepKey="switchToIframe" /> - <waitForPageLoad stepKey="waitForPageLoad9"/> + <actionGroup ref="SwitchToIframeActionGroup" stepKey="switchToIframe"/> <!--Verify that the text and image are present--> <seeElement selector="{{StorefrontNewsletterSection.mediaDescription}}" stepKey="assertMediaDescription"/> <seeElementInDOM selector="{{StorefrontNewsletterSection.imageSource(ImageUpload3.fileName)}}" stepKey="assertMediaSource"/> diff --git a/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddVariableToWYSIWYGNewsletterTest.xml b/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddVariableToWYSIWYGNewsletterTest.xml index 0116c546d2964..00910e68cd48e 100644 --- a/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddVariableToWYSIWYGNewsletterTest.xml +++ b/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddVariableToWYSIWYGNewsletterTest.xml @@ -83,10 +83,7 @@ <waitForPageLoad stepKey="waitForPageLoad9" /> <click selector="{{NewsletterWYSIWYGSection.Preview(_defaultNewsletter.name)}}" stepKey="clickPreview1" /> <switchToWindow userInput="action_window" stepKey="switchToWindow1"/> - <executeJS function="document.getElementById('preview_iframe').sandbox.add('allow-scripts')" stepKey="addSandboxValue"/> - <wait time="30" stepKey="waitBeforeSwitchToIframe"/> - <switchToIFrame userInput="preview_iframe" stepKey="switchToIframe1" /> - <waitForPageLoad time="30" stepKey="waitForPageLoad7"/> + <actionGroup ref="SwitchToIframeActionGroup" stepKey="switchToIframe"/> <!--see Default Variable on Storefront--> <see userInput="{{_defaultVariable.city}}" stepKey="seeDefaultVariable" /> <!--see Custom Variable on Storefront--> @@ -97,9 +94,7 @@ <amOnPage url="{{NewsletterTemplateGrid.url}}" stepKey="amOnTemplateGrid" /> <click selector="{{NewsletterWYSIWYGSection.Preview(_defaultNewsletter.name)}}" stepKey="clickPreview2" /> <switchToWindow userInput="action_window" stepKey="switchToWindow2"/> - <executeJS function="document.getElementById('preview_iframe').sandbox.add('allow-scripts')" stepKey="addSandboxValue1"/> - <switchToIFrame userInput="preview_iframe" stepKey="switchToIframe2" /> - <wait time="10" stepKey="waitForPageLoad8"/> + <actionGroup ref="SwitchToIframeActionGroup" stepKey="switchToIframe1"/> <!--see custom variable blank--> <dontSee userInput="{{customVariable.html}}" stepKey="dontSeeCustomVariableName" /> <closeTab stepKey="closeTab"/> diff --git a/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddWidgetToWYSIWYGNewsletterTest.xml b/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddWidgetToWYSIWYGNewsletterTest.xml index 695ac82b9a800..75850ac5c5e27 100644 --- a/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddWidgetToWYSIWYGNewsletterTest.xml +++ b/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddWidgetToWYSIWYGNewsletterTest.xml @@ -48,9 +48,7 @@ <waitForPageLoad stepKey="waitForPageLoad10" /> <click selector="{{NewsletterWYSIWYGSection.Preview(_defaultNewsletter.name)}}" stepKey="clickPreview" /> <switchToWindow stepKey="switchToWindow" userInput="action_window"/> - <executeJS function="document.getElementById('preview_iframe').sandbox.add('allow-scripts')" stepKey="addSandboxValue"/> - <wait time="30" stepKey="waitBeforeSwitchToIframe"/> - <switchToIFrame userInput="preview_iframe" stepKey="switchToIframe" /> + <actionGroup ref="SwitchToIframeActionGroup" stepKey="switchToIframe"/> <waitForText userInput="Home page" stepKey="waitForPageLoad9"/> <see userInput="Home page" stepKey="seeHomePageCMSPage"/> <closeTab stepKey="closeTab"/> diff --git a/app/code/Magento/Newsletter/Test/Mftf/Test/VerifyTinyMCEv4IsNativeWYSIWYGOnNewsletterTest.xml b/app/code/Magento/Newsletter/Test/Mftf/Test/VerifyTinyMCEv4IsNativeWYSIWYGOnNewsletterTest.xml index 7ecb576e29582..3944bccf5672b 100644 --- a/app/code/Magento/Newsletter/Test/Mftf/Test/VerifyTinyMCEv4IsNativeWYSIWYGOnNewsletterTest.xml +++ b/app/code/Magento/Newsletter/Test/Mftf/Test/VerifyTinyMCEv4IsNativeWYSIWYGOnNewsletterTest.xml @@ -42,9 +42,7 @@ <waitForPageLoad stepKey="waitForPageLoad3" /> <click selector="{{NewsletterWYSIWYGSection.Preview(_defaultNewsletter.name)}}" stepKey="clickPreview" /> <switchToWindow stepKey="switchToWindow" userInput="action_window"/> - <executeJS function="document.getElementById('preview_iframe').sandbox.add('allow-scripts')" stepKey="addSandboxValue"/> - <wait time="30" stepKey="waitBeforeSwitchToIframe"/> - <switchToIFrame userInput="preview_iframe" stepKey="switchToIframe" /> + <actionGroup ref="SwitchToIframeActionGroup" stepKey="switchToIframe"/> <waitForText userInput="Hello World From Newsletter Template!" stepKey="waitForPageLoad2"/> <see userInput="Hello World From Newsletter Template!" stepKey="seeContent" /> <closeTab stepKey="closeTab"/> From 2035cf8f8edee0518a266bad4c3caff871251511 Mon Sep 17 00:00:00 2001 From: OlgaVasyltsun <olga.vasyltsun@gmail.com> Date: Tue, 9 Apr 2019 16:34:57 +0300 Subject: [PATCH 239/773] MC-11046: Newsletter Template update --- .../Mftf/ActionGroup/AdminNewsletterTemplateActionGroup.xml | 2 +- .../Test/Mftf/Test/AdminAddImageToWYSIWYGNewsletterTest.xml | 2 +- .../Mftf/Test/AdminAddVariableToWYSIWYGNewsletterTest.xml | 4 ++-- .../Test/Mftf/Test/AdminAddWidgetToWYSIWYGNewsletterTest.xml | 2 +- .../Test/VerifyTinyMCEv4IsNativeWYSIWYGOnNewsletterTest.xml | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/Newsletter/Test/Mftf/ActionGroup/AdminNewsletterTemplateActionGroup.xml b/app/code/Magento/Newsletter/Test/Mftf/ActionGroup/AdminNewsletterTemplateActionGroup.xml index 31d54e492ddd2..bd6842f785ecf 100644 --- a/app/code/Magento/Newsletter/Test/Mftf/ActionGroup/AdminNewsletterTemplateActionGroup.xml +++ b/app/code/Magento/Newsletter/Test/Mftf/ActionGroup/AdminNewsletterTemplateActionGroup.xml @@ -7,7 +7,7 @@ --> <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="SwitchToIframeActionGroup"> + <actionGroup name="SwitchToPreviewIframeActionGroup"> <executeJS function="document.getElementById('preview_iframe').sandbox.add('allow-scripts')" stepKey="addSandboxValue"/> <wait time="10" stepKey="waitBeforeSwitchToIframe"/> <switchToIFrame userInput="preview_iframe" stepKey="switchToIframe" /> diff --git a/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddImageToWYSIWYGNewsletterTest.xml b/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddImageToWYSIWYGNewsletterTest.xml index f9172f8f2bf65..0371c0265d149 100644 --- a/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddImageToWYSIWYGNewsletterTest.xml +++ b/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddImageToWYSIWYGNewsletterTest.xml @@ -51,7 +51,7 @@ <waitForPageLoad stepKey="waitForPageLoad11"/> <click selector="{{NewsletterWYSIWYGSection.Preview(_defaultNewsletter.name)}}" stepKey="clickPreview"/> <switchToWindow stepKey="switchToWindow" userInput="action_window"/> - <actionGroup ref="SwitchToIframeActionGroup" stepKey="switchToIframe"/> + <actionGroup ref="SwitchToPreviewIframeActionGroup" stepKey="switchToIframe"/> <!--Verify that the text and image are present--> <seeElement selector="{{StorefrontNewsletterSection.mediaDescription}}" stepKey="assertMediaDescription"/> <seeElementInDOM selector="{{StorefrontNewsletterSection.imageSource(ImageUpload3.fileName)}}" stepKey="assertMediaSource"/> diff --git a/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddVariableToWYSIWYGNewsletterTest.xml b/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddVariableToWYSIWYGNewsletterTest.xml index 00910e68cd48e..5b009aaa9572d 100644 --- a/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddVariableToWYSIWYGNewsletterTest.xml +++ b/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddVariableToWYSIWYGNewsletterTest.xml @@ -83,7 +83,7 @@ <waitForPageLoad stepKey="waitForPageLoad9" /> <click selector="{{NewsletterWYSIWYGSection.Preview(_defaultNewsletter.name)}}" stepKey="clickPreview1" /> <switchToWindow userInput="action_window" stepKey="switchToWindow1"/> - <actionGroup ref="SwitchToIframeActionGroup" stepKey="switchToIframe"/> + <actionGroup ref="SwitchToPreviewIframeActionGroup" stepKey="switchToIframe"/> <!--see Default Variable on Storefront--> <see userInput="{{_defaultVariable.city}}" stepKey="seeDefaultVariable" /> <!--see Custom Variable on Storefront--> @@ -94,7 +94,7 @@ <amOnPage url="{{NewsletterTemplateGrid.url}}" stepKey="amOnTemplateGrid" /> <click selector="{{NewsletterWYSIWYGSection.Preview(_defaultNewsletter.name)}}" stepKey="clickPreview2" /> <switchToWindow userInput="action_window" stepKey="switchToWindow2"/> - <actionGroup ref="SwitchToIframeActionGroup" stepKey="switchToIframe1"/> + <actionGroup ref="SwitchToPreviewIframeActionGroup" stepKey="switchToIframeAfterVariableDelete"/> <!--see custom variable blank--> <dontSee userInput="{{customVariable.html}}" stepKey="dontSeeCustomVariableName" /> <closeTab stepKey="closeTab"/> diff --git a/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddWidgetToWYSIWYGNewsletterTest.xml b/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddWidgetToWYSIWYGNewsletterTest.xml index 75850ac5c5e27..9c961f9da751a 100644 --- a/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddWidgetToWYSIWYGNewsletterTest.xml +++ b/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddWidgetToWYSIWYGNewsletterTest.xml @@ -48,7 +48,7 @@ <waitForPageLoad stepKey="waitForPageLoad10" /> <click selector="{{NewsletterWYSIWYGSection.Preview(_defaultNewsletter.name)}}" stepKey="clickPreview" /> <switchToWindow stepKey="switchToWindow" userInput="action_window"/> - <actionGroup ref="SwitchToIframeActionGroup" stepKey="switchToIframe"/> + <actionGroup ref="SwitchToPreviewIframeActionGroup" stepKey="switchToIframe"/> <waitForText userInput="Home page" stepKey="waitForPageLoad9"/> <see userInput="Home page" stepKey="seeHomePageCMSPage"/> <closeTab stepKey="closeTab"/> diff --git a/app/code/Magento/Newsletter/Test/Mftf/Test/VerifyTinyMCEv4IsNativeWYSIWYGOnNewsletterTest.xml b/app/code/Magento/Newsletter/Test/Mftf/Test/VerifyTinyMCEv4IsNativeWYSIWYGOnNewsletterTest.xml index 3944bccf5672b..c5846582b2c7a 100644 --- a/app/code/Magento/Newsletter/Test/Mftf/Test/VerifyTinyMCEv4IsNativeWYSIWYGOnNewsletterTest.xml +++ b/app/code/Magento/Newsletter/Test/Mftf/Test/VerifyTinyMCEv4IsNativeWYSIWYGOnNewsletterTest.xml @@ -42,7 +42,7 @@ <waitForPageLoad stepKey="waitForPageLoad3" /> <click selector="{{NewsletterWYSIWYGSection.Preview(_defaultNewsletter.name)}}" stepKey="clickPreview" /> <switchToWindow stepKey="switchToWindow" userInput="action_window"/> - <actionGroup ref="SwitchToIframeActionGroup" stepKey="switchToIframe"/> + <actionGroup ref="SwitchToPreviewIframeActionGroup" stepKey="switchToIframe"/> <waitForText userInput="Hello World From Newsletter Template!" stepKey="waitForPageLoad2"/> <see userInput="Hello World From Newsletter Template!" stepKey="seeContent" /> <closeTab stepKey="closeTab"/> From 3dbcab76451883c15a70440e18fb38cc4f5040e7 Mon Sep 17 00:00:00 2001 From: Dmytro Voskoboinikov <voskoboi@adobe.com> Date: Tue, 9 Apr 2019 15:57:53 -0500 Subject: [PATCH 240/773] MC-10870: Invalid company ID in web API --- .../Magento/Webapi/Model/Config/Reader.php | 32 ------------------- app/code/Magento/Webapi/etc/di.xml | 7 ++++ 2 files changed, 7 insertions(+), 32 deletions(-) diff --git a/app/code/Magento/Webapi/Model/Config/Reader.php b/app/code/Magento/Webapi/Model/Config/Reader.php index 59e183092cbd6..fbdef3c5dc62c 100644 --- a/app/code/Magento/Webapi/Model/Config/Reader.php +++ b/app/code/Magento/Webapi/Model/Config/Reader.php @@ -20,36 +20,4 @@ class Reader extends \Magento\Framework\Config\Reader\Filesystem '/routes/route/resources/resource' => 'ref', '/routes/route/data/parameter' => 'name', ]; - - /** - * @param \Magento\Framework\Config\FileResolverInterface $fileResolver - * @param Converter $converter - * @param SchemaLocator $schemaLocator - * @param \Magento\Framework\Config\ValidationStateInterface $validationState - * @param string $fileName - * @param array $idAttributes - * @param string $domDocumentClass - * @param string $defaultScope - */ - public function __construct( - \Magento\Framework\Config\FileResolverInterface $fileResolver, - Converter $converter, - SchemaLocator $schemaLocator, - \Magento\Framework\Config\ValidationStateInterface $validationState, - $fileName = 'webapi.xml', - $idAttributes = [], - $domDocumentClass = \Magento\Framework\Config\Dom::class, - $defaultScope = 'global' - ) { - parent::__construct( - $fileResolver, - $converter, - $schemaLocator, - $validationState, - $fileName, - $idAttributes, - $domDocumentClass, - $defaultScope - ); - } } diff --git a/app/code/Magento/Webapi/etc/di.xml b/app/code/Magento/Webapi/etc/di.xml index 62ba22a658aaa..a08bb04a39433 100644 --- a/app/code/Magento/Webapi/etc/di.xml +++ b/app/code/Magento/Webapi/etc/di.xml @@ -58,4 +58,11 @@ </argument> </arguments> </type> + <type name="Magento\Webapi\Model\Config\Reader"> + <arguments> + <argument name="converter" xsi:type="object">Magento\Webapi\Model\Config\Converter</argument> + <argument name="schemaLocator" xsi:type="object">Magento\Webapi\Model\Config\SchemaLocator</argument> + <argument name="fileName" xsi:type="string">webapi.xml</argument> + </arguments> + </type> </config> From f3912ff46b3370d79c74a8c1eefc624d708b5985 Mon Sep 17 00:00:00 2001 From: Dmytro Voskoboinikov <voskoboi@adobe.com> Date: Tue, 9 Apr 2019 16:05:19 -0500 Subject: [PATCH 241/773] MC-14893: Fixed incorrect behavior of email templates --- .../Magento/Framework/Filter/Test/Unit/TemplateTest.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/internal/Magento/Framework/Filter/Test/Unit/TemplateTest.php b/lib/internal/Magento/Framework/Filter/Test/Unit/TemplateTest.php index edf3774fc91fc..0ee3a06ce5420 100644 --- a/lib/internal/Magento/Framework/Filter/Test/Unit/TemplateTest.php +++ b/lib/internal/Magento/Framework/Filter/Test/Unit/TemplateTest.php @@ -8,6 +8,9 @@ use Magento\Store\Model\Store; +/** + * Template Filter test. + */ class TemplateTest extends \PHPUnit\Framework\TestCase { /** From 0396441d5aa53a295e40355944e584dae92b827e Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Wed, 10 Apr 2019 11:52:07 +0300 Subject: [PATCH 242/773] MC-5864: incorrect rendering of a rss feed --- app/code/Magento/Sales/Model/Rss/OrderStatus.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/code/Magento/Sales/Model/Rss/OrderStatus.php b/app/code/Magento/Sales/Model/Rss/OrderStatus.php index f9aabb8c81dfa..d0a15056e95bf 100644 --- a/app/code/Magento/Sales/Model/Rss/OrderStatus.php +++ b/app/code/Magento/Sales/Model/Rss/OrderStatus.php @@ -10,6 +10,8 @@ /** * Rss renderer for order statuses. + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class OrderStatus implements DataProviderInterface { @@ -128,8 +130,10 @@ public function getCacheKey() $order = $this->getOrder(); $key = ''; if ($order !== null) { + // phpcs:ignore $key = md5($order->getId() . $order->getIncrementId() . $order->getCustomerId()); } + return 'rss_order_status_data_' . $key; } @@ -158,6 +162,7 @@ protected function getOrder() if ((string)$this->request->getParam('signature') !== $this->signature->signData($data)) { return null; } + // phpcs:ignore $json = base64_decode($data); if ($json) { $data = json_decode($json, true); From f3b2034065d70c067ee7c42e8a28795fbd8fd09e Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Wed, 10 Apr 2019 12:20:16 +0300 Subject: [PATCH 243/773] MC-5864: incorrect rendering of a rss feed --- app/code/Magento/Sales/Test/Unit/Model/Rss/OrderStatusTest.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/code/Magento/Sales/Test/Unit/Model/Rss/OrderStatusTest.php b/app/code/Magento/Sales/Test/Unit/Model/Rss/OrderStatusTest.php index 7c53949bc8139..23f633d10caa3 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Rss/OrderStatusTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Rss/OrderStatusTest.php @@ -252,10 +252,12 @@ public function testGetCacheKey($requestData, $result) */ public function getCacheKeyDataProvider() { + // phpcs:disable return [ [base64_encode('{"order_id":1,"increment_id":"100000001","customer_id":1}'), md5('11000000011')], [base64_encode('{"order_id":"1","increment_id":true,"customer_id":true}'), ''] ]; + // phpcs:enable } public function testGetCacheLifetime() From fff3d99f83a545a487259de62a26d7cb4848bec8 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Wed, 10 Apr 2019 12:27:59 +0300 Subject: [PATCH 244/773] MC-14822: Compare action minor changes --- .../Magento/Catalog/Controller/Product/CompareTest.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Product/CompareTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Product/CompareTest.php index 67d58561a633f..0c3e81fd52e81 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Product/CompareTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Product/CompareTest.php @@ -271,6 +271,7 @@ protected function _prepareCompareListWithProductNameXss() $visitor = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() ->create(\Magento\Customer\Model\Visitor::class); /** @var \Magento\Framework\Stdlib\DateTime $dateTime */ + // phpcs:ignore $visitor->setSessionId(md5(time()) . md5(microtime())) ->setLastVisitAt((new \DateTime())->format(\Magento\Framework\Stdlib\DateTime::DATETIME_PHP_FORMAT)) ->save(); @@ -298,6 +299,7 @@ protected function _requireVisitorWithNoProducts() $visitor = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() ->create(\Magento\Customer\Model\Visitor::class); + // phpcs:ignore $visitor->setSessionId(md5(time()) . md5(microtime())) ->setLastVisitAt((new \DateTime())->format(\Magento\Framework\Stdlib\DateTime::DATETIME_PHP_FORMAT)) ->save(); @@ -322,6 +324,7 @@ protected function _requireVisitorWithTwoProducts() /** @var $visitor \Magento\Customer\Model\Visitor */ $visitor = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() ->create(\Magento\Customer\Model\Visitor::class); + // phpcs:ignore $visitor->setSessionId(md5(time()) . md5(microtime())) ->setLastVisitAt((new \DateTime())->format(\Magento\Framework\Stdlib\DateTime::DATETIME_PHP_FORMAT)) ->save(); @@ -385,6 +388,7 @@ protected function _requireCustomerWithTwoProducts() /** @var $visitor \Magento\Customer\Model\Visitor */ $visitor = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() ->create(\Magento\Customer\Model\Visitor::class); + // phpcs:ignore $visitor->setSessionId(md5(time()) . md5(microtime())) ->setLastVisitAt((new \DateTime())->format(\Magento\Framework\Stdlib\DateTime::DATETIME_PHP_FORMAT)) ->save(); From dabf303fd7c17e51d8a355a5aaf9ca942fcf07b1 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Wed, 10 Apr 2019 12:35:16 +0300 Subject: [PATCH 245/773] MC-11054: Remove possibility to upload swf files through wysiwyg editor --- .../Magento/Cms/Model/Wysiwyg/Images/StorageTest.php | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/dev/tests/integration/testsuite/Magento/Cms/Model/Wysiwyg/Images/StorageTest.php b/dev/tests/integration/testsuite/Magento/Cms/Model/Wysiwyg/Images/StorageTest.php index 423f521a63548..fd450e9fef593 100644 --- a/dev/tests/integration/testsuite/Magento/Cms/Model/Wysiwyg/Images/StorageTest.php +++ b/dev/tests/integration/testsuite/Magento/Cms/Model/Wysiwyg/Images/StorageTest.php @@ -38,6 +38,7 @@ class StorageTest extends \PHPUnit\Framework\TestCase /** * @inheritdoc */ + // phpcs:disable public static function setUpBeforeClass() { self::$_baseDir = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get( @@ -48,10 +49,12 @@ public static function setUpBeforeClass() } touch(self::$_baseDir . '/1.swf'); } + // phpcs:enable /** * @inheritdoc */ + // phpcs:ignore public static function tearDownAfterClass() { \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( @@ -112,6 +115,7 @@ public function testUploadFile(): void $fileName = 'magento_small_image.jpg'; $tmpDirectory = $this->filesystem->getDirectoryWrite(\Magento\Framework\App\Filesystem\DirectoryList::SYS_TMP); $filePath = $tmpDirectory->getAbsolutePath($fileName); + // phpcs:disable $fixtureDir = realpath(__DIR__ . '/../../../../Catalog/_files'); copy($fixtureDir . DIRECTORY_SEPARATOR . $fileName, $filePath); @@ -122,9 +126,9 @@ public function testUploadFile(): void 'error' => 0, 'size' => 12500, ]; - $this->storage->uploadFile(self::$_baseDir); $this->assertTrue(is_file(self::$_baseDir . DIRECTORY_SEPARATOR . $fileName)); + // phpcs:enable } /** @@ -141,6 +145,7 @@ public function testUploadFileWithWrongExtension(string $fileName, string $fileT { $tmpDirectory = $this->filesystem->getDirectoryWrite(\Magento\Framework\App\Filesystem\DirectoryList::SYS_TMP); $filePath = $tmpDirectory->getAbsolutePath($fileName); + // phpcs:disable $fixtureDir = realpath(__DIR__ . '/../../../_files'); copy($fixtureDir . DIRECTORY_SEPARATOR . $fileName, $filePath); @@ -154,6 +159,7 @@ public function testUploadFileWithWrongExtension(string $fileName, string $fileT $this->storage->uploadFile(self::$_baseDir, $storageType); $this->assertFalse(is_file(self::$_baseDir . DIRECTORY_SEPARATOR . $fileName)); + // phpcs:enable } /** @@ -185,6 +191,7 @@ public function testUploadFileWithWrongFile(): void $fileName = 'file.gif'; $tmpDirectory = $this->filesystem->getDirectoryWrite(\Magento\Framework\App\Filesystem\DirectoryList::SYS_TMP); $filePath = $tmpDirectory->getAbsolutePath($fileName); + // phpcs:disable $file = fopen($filePath, "wb"); fwrite($file, 'just a text'); @@ -198,5 +205,6 @@ public function testUploadFileWithWrongFile(): void $this->storage->uploadFile(self::$_baseDir); $this->assertFalse(is_file(self::$_baseDir . DIRECTORY_SEPARATOR . $fileName)); + // phpcs:enable } } From b14a2d1e229c87784901e8367b5ebbeb461659bd Mon Sep 17 00:00:00 2001 From: Oleksandr Miroshnichenko <omiroshnichenko@magento.com> Date: Wed, 10 Apr 2019 13:19:19 -0500 Subject: [PATCH 246/773] MC-15070: Fix HttpGetActionInterface --- .../Magento/Framework/App/Action/HttpGetActionInterface.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/internal/Magento/Framework/App/Action/HttpGetActionInterface.php b/lib/internal/Magento/Framework/App/Action/HttpGetActionInterface.php index 308b77aa8dbcf..c3d3d2d6fd5ec 100644 --- a/lib/internal/Magento/Framework/App/Action/HttpGetActionInterface.php +++ b/lib/internal/Magento/Framework/App/Action/HttpGetActionInterface.php @@ -8,12 +8,10 @@ namespace Magento\Framework\App\Action; -use Magento\Framework\App\ActionInterface; - /** * Marker for actions processing GET requests. */ -interface HttpGetActionInterface extends ActionInterface +interface HttpGetActionInterface extends HttpHeadActionInterface { } From 1eb4619bbc9b201c99b76a6a109b6e1f3c59f818 Mon Sep 17 00:00:00 2001 From: Joan He <johe@magento.com> Date: Wed, 10 Apr 2019 16:34:00 -0500 Subject: [PATCH 247/773] MC-13810: Shipping information saved incorrectly --- .../Model/ShippingInformationManagement.php | 44 ++++++++--------- .../ShippingInformationManagementTest.php | 48 ++++++++++--------- 2 files changed, 47 insertions(+), 45 deletions(-) diff --git a/app/code/Magento/Checkout/Model/ShippingInformationManagement.php b/app/code/Magento/Checkout/Model/ShippingInformationManagement.php index cd3bd2c5a7deb..0adfbad3c8aeb 100644 --- a/app/code/Magento/Checkout/Model/ShippingInformationManagement.php +++ b/app/code/Magento/Checkout/Model/ShippingInformationManagement.php @@ -53,7 +53,6 @@ class ShippingInformationManagement implements \Magento\Checkout\Api\ShippingInf /** * @var QuoteAddressValidator - * @deprecated 100.2.0 */ protected $addressValidator; @@ -152,35 +151,36 @@ public function saveAddressInformation( $cartId, \Magento\Checkout\Api\Data\ShippingInformationInterface $addressInformation ) { - $address = $addressInformation->getShippingAddress(); - $billingAddress = $addressInformation->getBillingAddress(); - $carrierCode = $addressInformation->getShippingCarrierCode(); - $methodCode = $addressInformation->getShippingMethodCode(); + /** @var \Magento\Quote\Model\Quote $quote */ + $quote = $this->quoteRepository->getActive($cartId); + $this->validateQuote($quote); + $address = $addressInformation->getShippingAddress(); + if (!$address || !$address->getCountryId()) { + throw new StateException(__('The shipping address is missing. Set the address and try again.')); + } if (!$address->getCustomerAddressId()) { $address->setCustomerAddressId(null); } - if ($billingAddress && !$billingAddress->getCustomerAddressId()) { - $billingAddress->setCustomerAddressId(null); - } - - if (!$address->getCountryId()) { - throw new StateException(__('The shipping address is missing. Set the address and try again.')); - } + try { + $billingAddress = $addressInformation->getBillingAddress(); + if ($billingAddress) { + if (!$billingAddress->getCustomerAddressId()) { + $billingAddress->setCustomerAddressId(null); + } + $this->addressValidator->validateForCart($quote, $billingAddress); + $quote->setBillingAddress($billingAddress); + } - /** @var \Magento\Quote\Model\Quote $quote */ - $quote = $this->quoteRepository->getActive($cartId); - $address->setLimitCarrier($carrierCode); - $quote = $this->prepareShippingAssignment($quote, $address, $carrierCode . '_' . $methodCode); - $this->validateQuote($quote); - $quote->setIsMultiShipping(false); + $this->addressValidator->validateForCart($quote, $address); + $carrierCode = $addressInformation->getShippingCarrierCode(); + $address->setLimitCarrier($carrierCode); + $methodCode = $addressInformation->getShippingMethodCode(); + $quote = $this->prepareShippingAssignment($quote, $address, $carrierCode . '_' . $methodCode); - if ($billingAddress) { - $quote->setBillingAddress($billingAddress); - } + $quote->setIsMultiShipping(false); - try { $this->quoteRepository->save($quote); } catch (\Exception $e) { $this->logger->critical($e); diff --git a/app/code/Magento/Checkout/Test/Unit/Model/ShippingInformationManagementTest.php b/app/code/Magento/Checkout/Test/Unit/Model/ShippingInformationManagementTest.php index dd88b7161acdf..93375bb884535 100644 --- a/app/code/Magento/Checkout/Test/Unit/Model/ShippingInformationManagementTest.php +++ b/app/code/Magento/Checkout/Test/Unit/Model/ShippingInformationManagementTest.php @@ -82,6 +82,11 @@ class ShippingInformationManagementTest extends \PHPUnit\Framework\TestCase */ private $shippingMock; + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + private $addressValidatorMock; + protected function setUp() { $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); @@ -141,6 +146,9 @@ protected function setUp() $this->createPartialMock(\Magento\Quote\Api\Data\CartExtensionFactory::class, ['create']); $this->shippingFactoryMock = $this->createPartialMock(\Magento\Quote\Model\ShippingFactory::class, ['create']); + $this->addressValidatorMock = $this->createMock( + \Magento\Quote\Model\QuoteAddressValidator::class + ); $this->model = $this->objectManager->getObject( \Magento\Checkout\Model\ShippingInformationManagement::class, @@ -151,7 +159,8 @@ protected function setUp() 'quoteRepository' => $this->quoteRepositoryMock, 'shippingAssignmentFactory' => $this->shippingAssignmentFactoryMock, 'cartExtensionFactory' => $this->cartExtensionFactoryMock, - 'shippingFactory' => $this->shippingFactoryMock + 'shippingFactory' => $this->shippingFactoryMock, + 'addressValidator' => $this->addressValidatorMock, ] ); } @@ -163,22 +172,8 @@ protected function setUp() public function testSaveAddressInformationIfCartIsEmpty() { $cartId = 100; - $carrierCode = 'carrier_code'; - $shippingMethod = 'shipping_method'; $addressInformationMock = $this->createMock(\Magento\Checkout\Api\Data\ShippingInformationInterface::class); - $billingAddress = $this->createMock(\Magento\Quote\Api\Data\AddressInterface::class); - $addressInformationMock->expects($this->once()) - ->method('getShippingAddress') - ->willReturn($this->shippingAddressMock); - $addressInformationMock->expects($this->once())->method('getBillingAddress')->willReturn($billingAddress); - $addressInformationMock->expects($this->once())->method('getShippingCarrierCode')->willReturn($carrierCode); - $addressInformationMock->expects($this->once())->method('getShippingMethodCode')->willReturn($shippingMethod); - - $this->shippingAddressMock->expects($this->once())->method('getCountryId')->willReturn('USA'); - - $this->setShippingAssignmentsMocks($carrierCode . '_' . $shippingMethod); - $this->quoteMock->expects($this->once())->method('getItemsCount')->willReturn(0); $this->quoteRepositoryMock->expects($this->once()) ->method('getActive') @@ -244,21 +239,19 @@ private function setShippingAssignmentsMocks($shippingMethod) public function testSaveAddressInformationIfShippingAddressNotSet() { $cartId = 100; - $carrierCode = 'carrier_code'; - $shippingMethod = 'shipping_method'; $addressInformationMock = $this->createMock(\Magento\Checkout\Api\Data\ShippingInformationInterface::class); - $addressInformationMock->expects($this->once()) ->method('getShippingAddress') ->willReturn($this->shippingAddressMock); - $addressInformationMock->expects($this->once())->method('getShippingCarrierCode')->willReturn($carrierCode); - $addressInformationMock->expects($this->once())->method('getShippingMethodCode')->willReturn($shippingMethod); - - $billingAddress = $this->createMock(\Magento\Quote\Api\Data\AddressInterface::class); - $addressInformationMock->expects($this->once())->method('getBillingAddress')->willReturn($billingAddress); $this->shippingAddressMock->expects($this->once())->method('getCountryId')->willReturn(null); + $this->quoteRepositoryMock->expects($this->once()) + ->method('getActive') + ->with($cartId) + ->willReturn($this->quoteMock); + $this->quoteMock->expects($this->once())->method('getItemsCount')->willReturn(100); + $this->model->saveAddressInformation($cartId, $addressInformationMock); } @@ -273,6 +266,9 @@ public function testSaveAddressInformationIfCanNotSaveQuote() $shippingMethod = 'shipping_method'; $addressInformationMock = $this->createMock(\Magento\Checkout\Api\Data\ShippingInformationInterface::class); + $this->addressValidatorMock->expects($this->exactly(2)) + ->method('validateForCart'); + $this->quoteRepositoryMock->expects($this->once()) ->method('getActive') ->with($cartId) @@ -314,6 +310,9 @@ public function testSaveAddressInformationIfCarrierCodeIsInvalid() $shippingMethod = 'shipping_method'; $addressInformationMock = $this->createMock(\Magento\Checkout\Api\Data\ShippingInformationInterface::class); + $this->addressValidatorMock->expects($this->exactly(2)) + ->method('validateForCart'); + $this->quoteRepositoryMock->expects($this->once()) ->method('getActive') ->with($cartId) @@ -355,6 +354,9 @@ public function testSaveAddressInformation() $shippingMethod = 'shipping_method'; $addressInformationMock = $this->createMock(\Magento\Checkout\Api\Data\ShippingInformationInterface::class); + $this->addressValidatorMock->expects($this->exactly(2)) + ->method('validateForCart'); + $this->quoteRepositoryMock->expects($this->once()) ->method('getActive') ->with($cartId) From bf929aa2899798f293b82fcedd65d7e52fffd2d6 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun <ogorkun@magento.com> Date: Wed, 10 Apr 2019 18:06:17 -0500 Subject: [PATCH 248/773] MC-13958: Additional Permissions for Design settings --- .../Magento/Cms/Model/Page/DataProvider.php | 30 +++---------------- 1 file changed, 4 insertions(+), 26 deletions(-) diff --git a/app/code/Magento/Cms/Model/Page/DataProvider.php b/app/code/Magento/Cms/Model/Page/DataProvider.php index 0f0edf878c7b8..cece4b9486bc8 100644 --- a/app/code/Magento/Cms/Model/Page/DataProvider.php +++ b/app/code/Magento/Cms/Model/Page/DataProvider.php @@ -113,32 +113,10 @@ public function getMeta() if (!$this->auth->isAllowed('Magento_Cms::save_design')) { $designMeta = [ 'design' => [ - 'children' => [ - 'page_layout' => [ - 'arguments' => [ - 'data' => [ - 'config' => [ - 'disabled' => true, - ] - ] - ] - ], - 'layout_update_xml' => [ - 'arguments' => [ - 'data' => [ - 'config' => [ - 'disabled' => true, - ] - ] - ] - ], - 'custom_theme' => [ - 'arguments' => [ - 'data' => [ - 'config' => [ - 'disabled' => true, - ] - ] + 'arguments' => [ + 'data' => [ + 'config' => [ + 'disabled' => true ] ] ] From c390a91bc61ec4ceb803cd0c9f616f4316ecabce Mon Sep 17 00:00:00 2001 From: Viktor Sevch <svitja@ukr.net> Date: Thu, 11 Apr 2019 14:57:19 +0300 Subject: [PATCH 249/773] MC-15574: Fix associated product grid --- .../Adminhtml/Product/Edit/Tab/Variations/Config/Matrix.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/ConfigurableProduct/Block/Adminhtml/Product/Edit/Tab/Variations/Config/Matrix.php b/app/code/Magento/ConfigurableProduct/Block/Adminhtml/Product/Edit/Tab/Variations/Config/Matrix.php index a994532d5a69e..508755a7a13b2 100644 --- a/app/code/Magento/ConfigurableProduct/Block/Adminhtml/Product/Edit/Tab/Variations/Config/Matrix.php +++ b/app/code/Magento/ConfigurableProduct/Block/Adminhtml/Product/Edit/Tab/Variations/Config/Matrix.php @@ -360,6 +360,7 @@ protected function prepareVariations() 'id' => $option->getValue(), 'label' => $option->getLabel(), 'value' => $option->getValue(), + '__disableTmpl' => true, ]; } } @@ -371,6 +372,7 @@ protected function prepareVariations() 'id' => $optionId, 'label' => $variation[$attribute->getId()]['label'], 'value' => $optionId, + '__disableTmpl' => true, ]; $variationOptions[] = $variationOption; $attributes[$attribute->getAttributeId()]['chosen'][] = $variationOption; @@ -387,7 +389,8 @@ protected function prepareVariations() 'price' => $price, 'options' => $variationOptions, 'weight' => $product->getWeight(), - 'status' => $product->getStatus() + 'status' => $product->getStatus(), + '__disableTmpl' => true, ]; } } From f5d3217a406628207c4cbbaa3599e8ed70f77ef9 Mon Sep 17 00:00:00 2001 From: Viktor Sevch <svitja@ukr.net> Date: Thu, 11 Apr 2019 20:28:52 +0300 Subject: [PATCH 250/773] MC-15574: Fix associated product grid --- .../Product/Edit/Tab/Variations/Config/Matrix.php | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/app/code/Magento/ConfigurableProduct/Block/Adminhtml/Product/Edit/Tab/Variations/Config/Matrix.php b/app/code/Magento/ConfigurableProduct/Block/Adminhtml/Product/Edit/Tab/Variations/Config/Matrix.php index 508755a7a13b2..d43ff185d778c 100644 --- a/app/code/Magento/ConfigurableProduct/Block/Adminhtml/Product/Edit/Tab/Variations/Config/Matrix.php +++ b/app/code/Magento/ConfigurableProduct/Block/Adminhtml/Product/Edit/Tab/Variations/Config/Matrix.php @@ -98,6 +98,8 @@ public function __construct( } /** + * Return currency symbol. + * * @return string */ public function getCurrencySymbol() @@ -274,6 +276,8 @@ public function getImageUploadUrl() } /** + * Return product qty. + * * @param Product $product * @return float */ @@ -283,6 +287,8 @@ public function getProductStockQty(Product $product) } /** + * Return variation wizard. + * * @param array $initData * @return string */ @@ -298,6 +304,8 @@ public function getVariationWizard($initData) } /** + * Return product configuration matrix. + * * @return array|null */ public function getProductMatrix() @@ -309,6 +317,8 @@ public function getProductMatrix() } /** + * Return product attributes. + * * @return array|null */ public function getProductAttributes() @@ -316,10 +326,13 @@ public function getProductAttributes() if ($this->productAttributes === null) { $this->prepareVariations(); } + return $this->productAttributes; } /** + * Prepare product variations. + * * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @return void * TODO: move to class From bb03bcf96b7a166ccd43a41369cf5b51f06c8b54 Mon Sep 17 00:00:00 2001 From: Leandry <leandry@atwix.com> Date: Thu, 11 Apr 2019 22:45:05 +0300 Subject: [PATCH 251/773] Refactoring --- .../AssertAdminNotSuccessLoginActionGroup.xml | 19 +++++ .../AssertMessageOnBackendActionGroup.xml | 18 ++++ .../Mftf/Section/AdminMessagesSection.xml | 1 + ...lIntegrationRequiredFieldsActionGroup.xml} | 12 +-- ...AdminOpenNewIntegrationPageActionGroup.xml | 14 +++ .../AssertSaveIntegrationActionGroup.xml | 14 +++ ...ntegrationData.xml => IntegrationData.xml} | 4 +- ...dminUserWhenCreatingNewIntegrationTest.xml | 76 +++++++++++++++++ ...dminUserWhenCreatingNewIntegrationTest.xml | 85 ------------------- ...dminUserWhenCreatingNewIntegrationTest.xml | 3 +- 10 files changed, 148 insertions(+), 98 deletions(-) create mode 100644 app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertAdminNotSuccessLoginActionGroup.xml create mode 100644 app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertMessageOnBackendActionGroup.xml rename app/code/Magento/{Security/Test/Mftf/ActionGroup/AdminNewIntegrationRequiredFieldsActionGroup.xml => Integration/Test/Mftf/ActionGroup/AdminFillIntegrationRequiredFieldsActionGroup.xml} (54%) create mode 100644 app/code/Magento/Integration/Test/Mftf/ActionGroup/AdminOpenNewIntegrationPageActionGroup.xml create mode 100644 app/code/Magento/Integration/Test/Mftf/ActionGroup/AssertSaveIntegrationActionGroup.xml rename app/code/Magento/Integration/Test/Mftf/Data/{AdminNewIntegrationData.xml => IntegrationData.xml} (72%) create mode 100644 app/code/Magento/Security/Test/Mftf/Test/AdminLockAdminUserWhenCreatingNewIntegrationTest.xml delete mode 100644 app/code/Magento/Security/Test/Mftf/Test/LockAdminUserWhenCreatingNewIntegrationTest.xml diff --git a/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertAdminNotSuccessLoginActionGroup.xml b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertAdminNotSuccessLoginActionGroup.xml new file mode 100644 index 0000000000000..f932924edbd72 --- /dev/null +++ b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertAdminNotSuccessLoginActionGroup.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AssertAdminNotSuccessLoginActionGroup"> + <arguments> + <argument name="message" type="string" defaultValue="The account sign-in was incorrect or your account is disabled temporarily. Please wait and try again later"/> + </arguments> + <waitForPageLoad stepKey="waitForPageReload"/> + <see selector="{{AdminLoginFormSection.error}}" userInput="{{message}}" + stepKey="seeLoginAdminError"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertMessageOnBackendActionGroup.xml b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertMessageOnBackendActionGroup.xml new file mode 100644 index 0000000000000..b75fcd47c61bd --- /dev/null +++ b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertMessageOnBackendActionGroup.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AssertMessageOnBackendActionGroup"> + <arguments> + <argument name="message" type="string" defaultValue="The password entered for the current user is invalid. Verify the password and try again." /> + <argument name="messageType" type="string" defaultValue="error" /> + </arguments> + <see userInput="{{message}}" selector="{{AdminMessagesSection.messageByType(messageType)}}" stepKey="verifyMessage" /> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Backend/Test/Mftf/Section/AdminMessagesSection.xml b/app/code/Magento/Backend/Test/Mftf/Section/AdminMessagesSection.xml index 88e740d689cdd..be3ef92acf0ac 100644 --- a/app/code/Magento/Backend/Test/Mftf/Section/AdminMessagesSection.xml +++ b/app/code/Magento/Backend/Test/Mftf/Section/AdminMessagesSection.xml @@ -13,5 +13,6 @@ <element name="nthSuccess" type="text" selector=".message.message-success.success:nth-of-type({{n}})>div" parameterized="true"/> <element name="error" type="text" selector="#messages div.message-error"/> <element name="notice" type="text" selector=".message.message-notice.notice"/> + <element name="messageByType" type="text" selector="#messages div.message-{{messageType}}" parameterized="true" /> </section> </sections> diff --git a/app/code/Magento/Security/Test/Mftf/ActionGroup/AdminNewIntegrationRequiredFieldsActionGroup.xml b/app/code/Magento/Integration/Test/Mftf/ActionGroup/AdminFillIntegrationRequiredFieldsActionGroup.xml similarity index 54% rename from app/code/Magento/Security/Test/Mftf/ActionGroup/AdminNewIntegrationRequiredFieldsActionGroup.xml rename to app/code/Magento/Integration/Test/Mftf/ActionGroup/AdminFillIntegrationRequiredFieldsActionGroup.xml index bb35660ca8edd..d1dc2996ee2e4 100644 --- a/app/code/Magento/Security/Test/Mftf/ActionGroup/AdminNewIntegrationRequiredFieldsActionGroup.xml +++ b/app/code/Magento/Integration/Test/Mftf/ActionGroup/AdminFillIntegrationRequiredFieldsActionGroup.xml @@ -7,19 +7,13 @@ --> <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="AdminNewIntegrationRequiredFieldsActionGroup"> + <actionGroup name="AdminFillIntegrationRequiredFieldsActionGroup"> <arguments> - <argument name="integrationName" type="string" /> - <argument name="currentAdminPassword" type="string" /> - <argument name="message" type="string" defaultValue="The integration '{{AdminNewIntegrationData.integrationName}}' has been saved." /> - <argument name="messageSelector" type="string" defaultValue="{{AdminMessagesSection.success}}" /> + <argument name="integrationName" type="string" defaultValue="{{IntegrationData.name}}"/> + <argument name="currentAdminPassword" type="string" defaultValue="{{_ENV.MAGENTO_ADMIN_PASSWORD}}" /> </arguments> - <!-- Fill all Required Fields. --> <fillField selector="{{AdminNewIntegrationSection.integrationName}}" userInput="{{integrationName}}" stepKey="fillIntegrationName"/> <fillField selector="{{AdminNewIntegrationSection.currentPassword}}" userInput="{{currentAdminPassword}}" stepKey="fillCurrentUserPassword"/> <scrollToTopOfPage stepKey="ScrollToTopOfPage"/> - <click selector="{{AdminNewIntegrationSection.save}}" stepKey="saveNewIntegration"/> - <waitForPageLoad stepKey="waitForSaveResultLoad"/> - <see userInput="{{message}}" selector="{{messageSelector}}" stepKey="verifyMessage" /> </actionGroup> </actionGroups> diff --git a/app/code/Magento/Integration/Test/Mftf/ActionGroup/AdminOpenNewIntegrationPageActionGroup.xml b/app/code/Magento/Integration/Test/Mftf/ActionGroup/AdminOpenNewIntegrationPageActionGroup.xml new file mode 100644 index 0000000000000..0ddb0664b9798 --- /dev/null +++ b/app/code/Magento/Integration/Test/Mftf/ActionGroup/AdminOpenNewIntegrationPageActionGroup.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminOpenNewIntegrationPageActionGroup"> + <amOnPage url="{{AdminNewIntegrationPage.url}}" stepKey="amOnNewAdminIntegrationPage"/> + <waitForPageLoad stepKey="waitForNewAdminIntegrationPageLoad"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Integration/Test/Mftf/ActionGroup/AssertSaveIntegrationActionGroup.xml b/app/code/Magento/Integration/Test/Mftf/ActionGroup/AssertSaveIntegrationActionGroup.xml new file mode 100644 index 0000000000000..0c53f4455befb --- /dev/null +++ b/app/code/Magento/Integration/Test/Mftf/ActionGroup/AssertSaveIntegrationActionGroup.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AssertSaveIntegrationActionGroup"> + <click selector="{{AdminNewIntegrationSection.save}}" stepKey="saveIntegration"/> + <waitForPageLoad stepKey="waitForSaveResultLoad"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Integration/Test/Mftf/Data/AdminNewIntegrationData.xml b/app/code/Magento/Integration/Test/Mftf/Data/IntegrationData.xml similarity index 72% rename from app/code/Magento/Integration/Test/Mftf/Data/AdminNewIntegrationData.xml rename to app/code/Magento/Integration/Test/Mftf/Data/IntegrationData.xml index 1307320ffb8f9..3e7b6c49e2bc5 100644 --- a/app/code/Magento/Integration/Test/Mftf/Data/AdminNewIntegrationData.xml +++ b/app/code/Magento/Integration/Test/Mftf/Data/IntegrationData.xml @@ -8,7 +8,7 @@ <entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd"> - <entity name="AdminNewIntegrationData" type="admin"> - <data key="integrationName" unique="prefix">_Integration</data> + <entity name="IntegrationData" type="admin"> + <data key="name" unique="prefix">_Integration</data> </entity> </entities> diff --git a/app/code/Magento/Security/Test/Mftf/Test/AdminLockAdminUserWhenCreatingNewIntegrationTest.xml b/app/code/Magento/Security/Test/Mftf/Test/AdminLockAdminUserWhenCreatingNewIntegrationTest.xml new file mode 100644 index 0000000000000..96ef122fd7a48 --- /dev/null +++ b/app/code/Magento/Security/Test/Mftf/Test/AdminLockAdminUserWhenCreatingNewIntegrationTest.xml @@ -0,0 +1,76 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AdminLockAdminUserWhenCreatingNewIntegrationTest"> + <annotations> + <features value="Security"/> + <stories value="Runs Lock admin user when creating new integration test."/> + <title value="Lock admin user when creating new integration"/> + <description value="Runs Lock admin user when creating new integration test."/> + <severity value="MAJOR"/> + <group value="security"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <!-- Log in to Admin Panel --> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + </before> + <after> + <!-- Unlock Admin user --> + <magentoCLI command="admin:user:unlock {{_ENV.MAGENTO_ADMIN_USERNAME}}" stepKey="unlockAdminUser"/> + </after> + + <actionGroup ref="AdminOpenNewIntegrationPageActionGroup" stepKey="openNewIntegrationPage"/> + <!-- Perform add new admin user 6 specified number of times. + "The password entered for the current user is invalid. Verify the password and try again." appears after each attempt.--> + <actionGroup ref="AdminFillIntegrationRequiredFieldsActionGroup" stepKey="fillFieldFirstAttempt"> + <argument name="currentAdminPassword" value="{{_ENV.MAGENTO_ADMIN_PASSWORD}}INVALID" /> + </actionGroup> + <actionGroup ref="AssertSaveIntegrationActionGroup" stepKey="saveIntegrationFirstAttempt"/> + <actionGroup ref="AssertMessageOnBackendActionGroup" stepKey="checkFirstSaveIntegrationError"/> + + <actionGroup ref="AdminFillIntegrationRequiredFieldsActionGroup" stepKey="fillFieldSecondAttempt"> + <argument name="currentAdminPassword" value="{{_ENV.MAGENTO_ADMIN_PASSWORD}}INVALID" /> + </actionGroup> + <actionGroup ref="AssertSaveIntegrationActionGroup" stepKey="saveIntegrationSecondAttempt"/> + <actionGroup ref="AssertMessageOnBackendActionGroup" stepKey="checkSecondSaveIntegrationError"/> + + <actionGroup ref="AdminFillIntegrationRequiredFieldsActionGroup" stepKey="fillFieldThirdAttempt"> + <argument name="currentAdminPassword" value="{{_ENV.MAGENTO_ADMIN_PASSWORD}}INVALID" /> + </actionGroup> + <actionGroup ref="AssertSaveIntegrationActionGroup" stepKey="saveIntegrationThirdAttempt"/> + <actionGroup ref="AssertMessageOnBackendActionGroup" stepKey="checkThirdSaveIntegrationError"/> + + <actionGroup ref="AdminFillIntegrationRequiredFieldsActionGroup" stepKey="fillFieldFourthAttempt"> + <argument name="currentAdminPassword" value="{{_ENV.MAGENTO_ADMIN_PASSWORD}}INVALID" /> + </actionGroup> + <actionGroup ref="AssertSaveIntegrationActionGroup" stepKey="saveIntegrationFourthAttempt"/> + <actionGroup ref="AssertMessageOnBackendActionGroup" stepKey="checkFourthSaveIntegrationError"/> + + <actionGroup ref="AdminFillIntegrationRequiredFieldsActionGroup" stepKey="fillFieldFifthAttempt"> + <argument name="currentAdminPassword" value="{{_ENV.MAGENTO_ADMIN_PASSWORD}}INVALID" /> + </actionGroup> + <actionGroup ref="AssertSaveIntegrationActionGroup" stepKey="saveIntegrationFifthAttempt"/> + <actionGroup ref="AssertMessageOnBackendActionGroup" stepKey="checkFifthSaveIntegrationError"/> + + <!-- Last invalid current password save integration attempt and check logout error --> + <actionGroup ref="AdminFillIntegrationRequiredFieldsActionGroup" stepKey="fillFieldLastAttempt"> + <argument name="currentAdminPassword" value="{{_ENV.MAGENTO_ADMIN_PASSWORD}}INVALID" /> + </actionGroup> + <actionGroup ref="AssertSaveIntegrationActionGroup" stepKey="saveIntegrationLastAttempt"/> + <actionGroup ref="AssertAdminNotSuccessLoginActionGroup" stepKey="checkFifthError"> + <argument name="message" value="Your account is temporarily disabled. Please try again later."/> + </actionGroup> + + <!-- Try to login as admin and check error --> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsLockedAdmin"/> + <actionGroup ref="AssertAdminNotSuccessLoginActionGroup" stepKey="checkLoginError"/> + </test> +</tests> diff --git a/app/code/Magento/Security/Test/Mftf/Test/LockAdminUserWhenCreatingNewIntegrationTest.xml b/app/code/Magento/Security/Test/Mftf/Test/LockAdminUserWhenCreatingNewIntegrationTest.xml deleted file mode 100644 index fcef652dfeb9b..0000000000000 --- a/app/code/Magento/Security/Test/Mftf/Test/LockAdminUserWhenCreatingNewIntegrationTest.xml +++ /dev/null @@ -1,85 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> - -<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> - <test name="LockAdminUserWhenCreatingNewIntegrationTest"> - <annotations> - <features value="Security"/> - <stories value="Runs Lock admin user when creating new integration test."/> - <title value="Lock admin user when creating new integration"/> - <description value="Runs Lock admin user when creating new integration test."/> - <severity value="MAJOR"/> - <group value="security"/> - <group value="mtf_migrated"/> - </annotations> - <before> - <!-- Log in to Admin Panel --> - <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> - </before> - <after> - <!-- Unlock Admin user --> - <magentoCLI command="admin:user:unlock {{_ENV.MAGENTO_ADMIN_USERNAME}}" stepKey="unlockAdminUser"/> - </after> - - <!-- Open Admin New Integration Page --> - <amOnPage url="{{AdminNewIntegrationPage.url}}" stepKey="amOnNewAdminIntegrationPage"/> - <waitForPageLoad stepKey="waitForNewAdminIntegrationPageLoad"/> - - <!-- Perform add new admin user 6 specified number of times. - "The password entered for the current user is invalid. Verify the password and try again." appears after each attempt.--> - <actionGroup ref="AdminNewIntegrationRequiredFieldsActionGroup" stepKey="failedSaveIntegrationFirstAttempt"> - <argument name="integrationName" value="{{AdminNewIntegrationData.integrationName}}" /> - <argument name="currentAdminPassword" value="{{_ENV.MAGENTO_ADMIN_PASSWORD}}INVALID" /> - <argument name="messageSelector" value="{{AdminMessagesSection.error}}" /> - <argument name="message" value="The password entered for the current user is invalid. Verify the password and try again." /> - </actionGroup> - - <actionGroup ref="AdminNewIntegrationRequiredFieldsActionGroup" stepKey="failedSaveIntegrationSecondAttempt"> - <argument name="integrationName" value="{{AdminNewIntegrationData.integrationName}}" /> - <argument name="currentAdminPassword" value="{{_ENV.MAGENTO_ADMIN_PASSWORD}}INVALID" /> - <argument name="messageSelector" value="{{AdminMessagesSection.error}}" /> - <argument name="message" value="The password entered for the current user is invalid. Verify the password and try again." /> - </actionGroup> - - <actionGroup ref="AdminNewIntegrationRequiredFieldsActionGroup" stepKey="failedSaveIntegrationThirdAttempt"> - <argument name="integrationName" value="{{AdminNewIntegrationData.integrationName}}" /> - <argument name="currentAdminPassword" value="{{_ENV.MAGENTO_ADMIN_PASSWORD}}INVALID" /> - <argument name="messageSelector" value="{{AdminMessagesSection.error}}" /> - <argument name="message" value="The password entered for the current user is invalid. Verify the password and try again." /> - </actionGroup> - - <actionGroup ref="AdminNewIntegrationRequiredFieldsActionGroup" stepKey="failedSaveIntegrationFourthAttempt"> - <argument name="integrationName" value="{{AdminNewIntegrationData.integrationName}}" /> - <argument name="currentAdminPassword" value="{{_ENV.MAGENTO_ADMIN_PASSWORD}}INVALID" /> - <argument name="messageSelector" value="{{AdminMessagesSection.error}}" /> - <argument name="message" value="The password entered for the current user is invalid. Verify the password and try again." /> - </actionGroup> - - <actionGroup ref="AdminNewIntegrationRequiredFieldsActionGroup" stepKey="failedSaveIntegrationFifthAttempt"> - <argument name="integrationName" value="{{AdminNewIntegrationData.integrationName}}" /> - <argument name="currentAdminPassword" value="{{_ENV.MAGENTO_ADMIN_PASSWORD}}INVALID" /> - <argument name="messageSelector" value="{{AdminMessagesSection.error}}" /> - <argument name="message" value="The password entered for the current user is invalid. Verify the password and try again." /> - </actionGroup> - - <!-- Last invalid current password save integration attempt and check logout error --> - <actionGroup ref="AdminNewIntegrationRequiredFieldsActionGroup" stepKey="failedSaveIntegrationLastAttempt"> - <argument name="integrationName" value="{{AdminNewIntegrationData.integrationName}}" /> - <argument name="currentAdminPassword" value="{{_ENV.MAGENTO_ADMIN_PASSWORD}}INVALID" /> - <argument name="messageSelector" value="{{AdminLoginFormSection.error}}" /> - <argument name="message" value="Your account is temporarily disabled. Please try again later." /> - </actionGroup> - - <!-- Try to login as admin and check error --> - <actionGroup ref="LoginAsAdmin" stepKey="loginAsLockedAdmin"/> - <waitForPageLoad stepKey="waitForError"/> - <see selector="{{AdminLoginFormSection.error}}" userInput="The account sign-in was incorrect or your account is disabled temporarily. Please wait and try again later" - stepKey="seeLoginUserError"/> - </test> -</tests> diff --git a/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenCreatingNewIntegrationTest.xml b/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenCreatingNewIntegrationTest.xml index d9c45881b59dd..13c38af948441 100644 --- a/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenCreatingNewIntegrationTest.xml +++ b/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenCreatingNewIntegrationTest.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\Security\Test\TestCase\LockAdminUserWhenCreatingNewIntegrationTest" summary="Lock admin user after entering incorrect password while creating new integration"> <variation name="LockAdminUserWhenCreatingNewIntegrationTestVariation1"> - <data name="tag" xsi:type="string">severity:S2</data> + <data name="tag" xsi:type="string">severity:S2, mftf_migrated:yes</data> <data name="configData" xsi:type="string">user_lockout_failures</data> <data name="customAdmin/dataset" xsi:type="string">custom_admin_with_default_role</data> <data name="integration/data/name" xsi:type="string">Integration%isolation%</data> @@ -18,7 +18,6 @@ <data name="integration/data/current_password" xsi:type="string">incorrect password</data> <data name="integration/data/resource_access" xsi:type="string">All</data> <data name="attempts" xsi:type="string">4</data> - <data name="tag" xsi:type="string">mftf_migrated:yes</data> <constraint name="Magento\Security\Test\Constraint\AssertUserIsLocked" /> </variation> </testCase> From 89abbe47bb6585767b54d1dd4b67402f94ec177d Mon Sep 17 00:00:00 2001 From: OlgaVasyltsun <olga.vasyltsun@gmail.com> Date: Fri, 12 Apr 2019 11:13:02 +0300 Subject: [PATCH 252/773] MC-10858: Escaper refactor --- app/code/Magento/Sales/Helper/Admin.php | 33 ++++++++++++++----------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/app/code/Magento/Sales/Helper/Admin.php b/app/code/Magento/Sales/Helper/Admin.php index d71e248e615e2..8a312cbcf7c4d 100644 --- a/app/code/Magento/Sales/Helper/Admin.php +++ b/app/code/Magento/Sales/Helper/Admin.php @@ -8,7 +8,6 @@ namespace Magento\Sales\Helper; use Magento\Framework\App\ObjectManager; -use Symfony\Component\DomCrawler\CrawlerFactory; /** * Sales admin helper. @@ -36,9 +35,9 @@ class Admin extends \Magento\Framework\App\Helper\AbstractHelper protected $escaper; /** - * @var CrawlerFactory + * @var \DOMDocumentFactory */ - private $crawlerFactory; + private $domDocumentFactory; /** * @param \Magento\Framework\App\Helper\Context $context @@ -46,7 +45,7 @@ class Admin extends \Magento\Framework\App\Helper\AbstractHelper * @param \Magento\Sales\Model\Config $salesConfig * @param \Magento\Framework\Pricing\PriceCurrencyInterface $priceCurrency * @param \Magento\Framework\Escaper $escaper - * @param CrawlerFactory|null $crawlerFactory + * @param \DOMDocumentFactory|null $domDocumentFactory */ public function __construct( \Magento\Framework\App\Helper\Context $context, @@ -54,13 +53,14 @@ public function __construct( \Magento\Sales\Model\Config $salesConfig, \Magento\Framework\Pricing\PriceCurrencyInterface $priceCurrency, \Magento\Framework\Escaper $escaper, - CrawlerFactory $crawlerFactory = null + \DOMDocumentFactory $domDocumentFactory ) { $this->priceCurrency = $priceCurrency; $this->_storeManager = $storeManager; $this->_salesConfig = $salesConfig; $this->escaper = $escaper; - $this->crawlerFactory = $crawlerFactory ?: ObjectManager::getInstance()->get(CrawlerFactory::class); + $this->domDocumentFactory = $domDocumentFactory + ?: ObjectManager::getInstance()->get(\DOMDocumentFactory::class); parent::__construct($context); } @@ -161,13 +161,18 @@ public function applySalableProductTypesFilter($collection) public function escapeHtmlWithLinks($data, $allowedTags = null) { if (!empty($data) && is_array($allowedTags) && in_array('a', $allowedTags)) { - $crawler = $this->crawlerFactory->create( - [ - 'node' => '<html><body>' . $data . '</body></html>', - ] + $wrapperElementId = uniqid(); + $domDocument = $this->domDocumentFactory->create(); + + $internalErrors = libxml_use_internal_errors(true); + + $domDocument->loadHTML( + '<html><body id="' . $wrapperElementId . '">' . $data . '</body></html>' ); - $linkTags = $crawler->filter('a'); + libxml_use_internal_errors($internalErrors); + + $linkTags = $domDocument->getElementsByTagName('a'); foreach ($linkTags as $linkNode) { $linkAttributes = []; @@ -186,7 +191,9 @@ public function escapeHtmlWithLinks($data, $allowedTags = null) } } - $data = mb_convert_encoding($crawler->filter('body')->html(), 'UTF-8', 'HTML-ENTITIES'); + $result = mb_convert_encoding($domDocument->saveHTML(), 'UTF-8', 'HTML-ENTITIES'); + preg_match('/<body id="' . $wrapperElementId . '">(.+)<\/body><\/html>$/si', $result, $matches); + $data = !empty($matches) ? $matches[1] : ''; } return $this->escaper->escapeHtml($data, $allowedTags); @@ -202,9 +209,7 @@ private function filterUrl(string $url): string { if ($url) { //Revert the sprintf escaping - //phpcs:disable $urlScheme = parse_url($url, PHP_URL_SCHEME); - //phpcs:enable $urlScheme = $urlScheme ? strtolower($urlScheme) : ''; if ($urlScheme !== 'http' && $urlScheme !== 'https') { $url = null; From 3e05b6748a5bf55f42a2d0c452ca31af69a9de48 Mon Sep 17 00:00:00 2001 From: Viktor Sevch <svitja@ukr.net> Date: Fri, 12 Apr 2019 12:19:45 +0300 Subject: [PATCH 253/773] MC-15574: Fix associated product grid --- .../Edit/Tab/Variations/Config/Matrix.php | 92 ++++++++++++------- 1 file changed, 60 insertions(+), 32 deletions(-) diff --git a/app/code/Magento/ConfigurableProduct/Block/Adminhtml/Product/Edit/Tab/Variations/Config/Matrix.php b/app/code/Magento/ConfigurableProduct/Block/Adminhtml/Product/Edit/Tab/Variations/Config/Matrix.php index d43ff185d778c..4874dc8ea03ae 100644 --- a/app/code/Magento/ConfigurableProduct/Block/Adminhtml/Product/Edit/Tab/Variations/Config/Matrix.php +++ b/app/code/Magento/ConfigurableProduct/Block/Adminhtml/Product/Edit/Tab/Variations/Config/Matrix.php @@ -357,38 +357,13 @@ protected function prepareVariations() $price = $product->getPrice(); $variationOptions = []; foreach ($usedProductAttributes as $attribute) { - if (!isset($attributes[$attribute->getAttributeId()])) { - $attributes[$attribute->getAttributeId()] = [ - 'code' => $attribute->getAttributeCode(), - 'label' => $attribute->getStoreLabel(), - 'id' => $attribute->getAttributeId(), - 'position' => $configurableAttributes[$attribute->getAttributeId()]['position'], - 'chosen' => [], - ]; - foreach ($attribute->getOptions() as $option) { - if (!empty($option->getValue())) { - $attributes[$attribute->getAttributeId()]['options'][] = [ - 'attribute_code' => $attribute->getAttributeCode(), - 'attribute_label' => $attribute->getStoreLabel(0), - 'id' => $option->getValue(), - 'label' => $option->getLabel(), - 'value' => $option->getValue(), - '__disableTmpl' => true, - ]; - } - } - } - $optionId = $variation[$attribute->getId()]['value']; - $variationOption = [ - 'attribute_code' => $attribute->getAttributeCode(), - 'attribute_label' => $attribute->getStoreLabel(0), - 'id' => $optionId, - 'label' => $variation[$attribute->getId()]['label'], - 'value' => $optionId, - '__disableTmpl' => true, - ]; - $variationOptions[] = $variationOption; - $attributes[$attribute->getAttributeId()]['chosen'][] = $variationOption; + list($attributes, $variationOptions) = $this->prepareAttributes( + $attributes, + $attribute, + $configurableAttributes, + $variation, + $variationOptions + ); } $productMatrix[] = [ @@ -411,4 +386,57 @@ protected function prepareVariations() $this->productMatrix = $productMatrix; $this->productAttributes = array_values($attributes); } + + /** + * Prepare attributes. + * + * @param array $attributes + * @param object $attribute + * @param array $configurableAttributes + * @param array $variation + * @param array $variationOptions + * @return array + */ + private function prepareAttributes( + array $attributes, + $attribute, + array $configurableAttributes, + array $variation, + array $variationOptions + ): array { + if (!isset($attributes[$attribute->getAttributeId()])) { + $attributes[$attribute->getAttributeId()] = [ + 'code' => $attribute->getAttributeCode(), + 'label' => $attribute->getStoreLabel(), + 'id' => $attribute->getAttributeId(), + 'position' => $configurableAttributes[$attribute->getAttributeId()]['position'], + 'chosen' => [], + ]; + foreach ($attribute->getOptions() as $option) { + if (!empty($option->getValue())) { + $attributes[$attribute->getAttributeId()]['options'][] = [ + 'attribute_code' => $attribute->getAttributeCode(), + 'attribute_label' => $attribute->getStoreLabel(0), + 'id' => $option->getValue(), + 'label' => $option->getLabel(), + 'value' => $option->getValue(), + '__disableTmpl' => true, + ]; + } + } + } + $optionId = $variation[$attribute->getId()]['value']; + $variationOption = [ + 'attribute_code' => $attribute->getAttributeCode(), + 'attribute_label' => $attribute->getStoreLabel(0), + 'id' => $optionId, + 'label' => $variation[$attribute->getId()]['label'], + 'value' => $optionId, + '__disableTmpl' => true, + ]; + $variationOptions[] = $variationOption; + $attributes[$attribute->getAttributeId()]['chosen'][] = $variationOption; + + return [$attributes, $variationOptions]; + } } From 3fd9515d559e429b3a6b8a26ea9fbe1eea7b052a Mon Sep 17 00:00:00 2001 From: OlgaVasyltsun <olga.vasyltsun@gmail.com> Date: Fri, 12 Apr 2019 12:35:09 +0300 Subject: [PATCH 254/773] MC-10858: Escaper refactor --- app/code/Magento/Sales/Helper/Admin.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Sales/Helper/Admin.php b/app/code/Magento/Sales/Helper/Admin.php index 8a312cbcf7c4d..793872ac33166 100644 --- a/app/code/Magento/Sales/Helper/Admin.php +++ b/app/code/Magento/Sales/Helper/Admin.php @@ -53,7 +53,7 @@ public function __construct( \Magento\Sales\Model\Config $salesConfig, \Magento\Framework\Pricing\PriceCurrencyInterface $priceCurrency, \Magento\Framework\Escaper $escaper, - \DOMDocumentFactory $domDocumentFactory + \DOMDocumentFactory $domDocumentFactory = null ) { $this->priceCurrency = $priceCurrency; $this->_storeManager = $storeManager; From 1f7017a41bddae5d538eb78e56cbd6374d158503 Mon Sep 17 00:00:00 2001 From: OlgaVasyltsun <olga.vasyltsun@gmail.com> Date: Fri, 12 Apr 2019 15:40:13 +0300 Subject: [PATCH 255/773] MC-10858: Escaper refactor --- app/code/Magento/Sales/Helper/Admin.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Sales/Helper/Admin.php b/app/code/Magento/Sales/Helper/Admin.php index 793872ac33166..f04584ea19c37 100644 --- a/app/code/Magento/Sales/Helper/Admin.php +++ b/app/code/Magento/Sales/Helper/Admin.php @@ -209,6 +209,7 @@ private function filterUrl(string $url): string { if ($url) { //Revert the sprintf escaping + // phpcs:ignore Magento2.Functions.DiscouragedFunction $urlScheme = parse_url($url, PHP_URL_SCHEME); $urlScheme = $urlScheme ? strtolower($urlScheme) : ''; if ($urlScheme !== 'http' && $urlScheme !== 'https') { From 484c8530afe0a2003d9f52517f64131ae04ac722 Mon Sep 17 00:00:00 2001 From: Serhii Voloshkov <serhii.voloshkov@transoftgroup.com> Date: Fri, 12 Apr 2019 16:46:58 +0300 Subject: [PATCH 256/773] MC-14824: Sample links minor changes --- .../Model/Product/SalabilityChecker.php | 57 +++++++++++++++++++ .../Controller/Download/LinkSample.php | 24 +++++++- .../Controller/Download/Sample.php | 24 +++++++- .../Controller/Download/LinkSampleTest.php | 23 +++++++- .../Unit/Controller/Download/SampleTest.php | 27 ++++++++- 5 files changed, 147 insertions(+), 8 deletions(-) create mode 100644 app/code/Magento/Catalog/Model/Product/SalabilityChecker.php diff --git a/app/code/Magento/Catalog/Model/Product/SalabilityChecker.php b/app/code/Magento/Catalog/Model/Product/SalabilityChecker.php new file mode 100644 index 0000000000000..404760a51eff5 --- /dev/null +++ b/app/code/Magento/Catalog/Model/Product/SalabilityChecker.php @@ -0,0 +1,57 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Catalog\Model\Product; + +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Store\Model\StoreManagerInterface; + +/** + * Class to check that product is saleable. + */ +class SalabilityChecker +{ + /** + * @var ProductRepositoryInterface + */ + private $productRepository; + + /** + * @var StoreManagerInterface + */ + private $storeManager; + + /** + * @param ProductRepositoryInterface $productRepository + * @param StoreManagerInterface $storeManager + */ + public function __construct( + ProductRepositoryInterface $productRepository, + StoreManagerInterface $storeManager + ) { + $this->productRepository = $productRepository; + $this->storeManager = $storeManager; + } + + /** + * Check if product is salable. + * + * @param int|string $productId + * @param int|null $storeId + * @return bool + */ + public function isSalable($productId, $storeId = null): bool + { + if ($storeId === null) { + $storeId = $this->storeManager->getStore()->getId(); + } + /** @var \Magento\Catalog\Model\Product $product */ + $product = $this->productRepository->getById($productId, false, $storeId); + + return $product->isSalable(); + } +} diff --git a/app/code/Magento/Downloadable/Controller/Download/LinkSample.php b/app/code/Magento/Downloadable/Controller/Download/LinkSample.php index f40df744dd3ea..c0bc825a8285b 100644 --- a/app/code/Magento/Downloadable/Controller/Download/LinkSample.php +++ b/app/code/Magento/Downloadable/Controller/Download/LinkSample.php @@ -7,7 +7,9 @@ namespace Magento\Downloadable\Controller\Download; +use Magento\Catalog\Model\Product\SalabilityChecker; use Magento\Downloadable\Helper\Download as DownloadHelper; +use Magento\Framework\App\Action\Context; use Magento\Framework\App\ResponseInterface; /** @@ -18,7 +20,24 @@ class LinkSample extends \Magento\Downloadable\Controller\Download { /** - * Download link's sample action + * @var SalabilityChecker + */ + private $salabilityChecker; + + /** + * @param Context $context + * @param SalabilityChecker|null $salabilityChecker + */ + public function __construct( + Context $context, + SalabilityChecker $salabilityChecker = null + ) { + parent::__construct($context); + $this->salabilityChecker = $salabilityChecker ?: $this->_objectManager->get(SalabilityChecker::class); + } + + /** + * Download link's sample action. * * @return ResponseInterface */ @@ -27,7 +46,7 @@ public function execute() $linkId = $this->getRequest()->getParam('link_id', 0); /** @var \Magento\Downloadable\Model\Link $link */ $link = $this->_objectManager->create(\Magento\Downloadable\Model\Link::class)->load($linkId); - if ($link->getId()) { + if ($link->getId() && $this->salabilityChecker->isSalable($link->getProductId())) { $resource = ''; $resourceType = ''; if ($link->getSampleType() == DownloadHelper::LINK_TYPE_URL) { @@ -52,6 +71,7 @@ public function execute() ); } } + return $this->getResponse()->setRedirect($this->_redirect->getRedirectUrl()); } } diff --git a/app/code/Magento/Downloadable/Controller/Download/Sample.php b/app/code/Magento/Downloadable/Controller/Download/Sample.php index ac9eeac678f8d..b95ec510fdd9b 100644 --- a/app/code/Magento/Downloadable/Controller/Download/Sample.php +++ b/app/code/Magento/Downloadable/Controller/Download/Sample.php @@ -7,7 +7,9 @@ namespace Magento\Downloadable\Controller\Download; +use Magento\Catalog\Model\Product\SalabilityChecker; use Magento\Downloadable\Helper\Download as DownloadHelper; +use Magento\Framework\App\Action\Context; use Magento\Framework\App\ResponseInterface; /** @@ -18,7 +20,24 @@ class Sample extends \Magento\Downloadable\Controller\Download { /** - * Download sample action + * @var SalabilityChecker + */ + private $salabilityChecker; + + /** + * @param Context $context + * @param SalabilityChecker|null $salabilityChecker + */ + public function __construct( + Context $context, + SalabilityChecker $salabilityChecker = null + ) { + parent::__construct($context); + $this->salabilityChecker = $salabilityChecker ?: $this->_objectManager->get(SalabilityChecker::class); + } + + /** + * Download sample action. * * @return ResponseInterface */ @@ -27,7 +46,7 @@ public function execute() $sampleId = $this->getRequest()->getParam('sample_id', 0); /** @var \Magento\Downloadable\Model\Sample $sample */ $sample = $this->_objectManager->create(\Magento\Downloadable\Model\Sample::class)->load($sampleId); - if ($sample->getId()) { + if ($sample->getId() && $this->salabilityChecker->isSalable($sample->getProductId())) { $resource = ''; $resourceType = ''; if ($sample->getSampleType() == DownloadHelper::LINK_TYPE_URL) { @@ -49,6 +68,7 @@ public function execute() ); } } + return $this->getResponse()->setRedirect($this->_redirect->getRedirectUrl()); } } diff --git a/app/code/Magento/Downloadable/Test/Unit/Controller/Download/LinkSampleTest.php b/app/code/Magento/Downloadable/Test/Unit/Controller/Download/LinkSampleTest.php index ce01b449d3388..78b707619f994 100644 --- a/app/code/Magento/Downloadable/Test/Unit/Controller/Download/LinkSampleTest.php +++ b/app/code/Magento/Downloadable/Test/Unit/Controller/Download/LinkSampleTest.php @@ -8,6 +8,8 @@ use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; /** + * Unit tests for \Magento\Downloadable\Controller\Download\LinkSample. + * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class LinkSampleTest extends \PHPUnit\Framework\TestCase @@ -63,6 +65,11 @@ class LinkSampleTest extends \PHPUnit\Framework\TestCase */ protected $urlInterface; + /** + * @var \Magento\Catalog\Model\Product\SalabilityChecker|\PHPUnit_Framework_MockObject_MockObject + */ + private $salabilityCheckerMock; + /** * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ @@ -104,6 +111,7 @@ protected function setUp() $this->messageManager = $this->createMock(\Magento\Framework\Message\ManagerInterface::class); $this->redirect = $this->createMock(\Magento\Framework\App\Response\RedirectInterface::class); $this->urlInterface = $this->createMock(\Magento\Framework\UrlInterface::class); + $this->salabilityCheckerMock = $this->createMock(\Magento\Catalog\Model\Product\SalabilityChecker::class); $this->objectManager = $this->createPartialMock(\Magento\Framework\ObjectManager\ObjectManager::class, [ 'create', 'get' @@ -115,11 +123,17 @@ protected function setUp() 'request' => $this->request, 'response' => $this->response, 'messageManager' => $this->messageManager, - 'redirect' => $this->redirect + 'redirect' => $this->redirect, + 'salabilityChecker' => $this->salabilityCheckerMock, ] ); } + /** + * Execute Download link's sample action with Url link. + * + * @return void + */ public function testExecuteLinkTypeUrl() { $linkMock = $this->getMockBuilder(\Magento\Downloadable\Model\Link::class) @@ -134,6 +148,7 @@ public function testExecuteLinkTypeUrl() ->willReturn($linkMock); $linkMock->expects($this->once())->method('load')->with('some_link_id')->willReturnSelf(); $linkMock->expects($this->once())->method('getId')->willReturn('some_link_id'); + $this->salabilityCheckerMock->expects($this->once())->method('isSalable')->willReturn(true); $linkMock->expects($this->once())->method('getSampleType')->willReturn( \Magento\Downloadable\Helper\Download::LINK_TYPE_URL ); @@ -155,6 +170,11 @@ public function testExecuteLinkTypeUrl() $this->assertEquals($this->response, $this->linkSample->execute()); } + /** + * Execute Download link's sample action with File link. + * + * @return void + */ public function testExecuteLinkTypeFile() { $linkMock = $this->getMockBuilder(\Magento\Downloadable\Model\Link::class) @@ -173,6 +193,7 @@ public function testExecuteLinkTypeFile() ->willReturn($linkMock); $linkMock->expects($this->once())->method('load')->with('some_link_id')->willReturnSelf(); $linkMock->expects($this->once())->method('getId')->willReturn('some_link_id'); + $this->salabilityCheckerMock->expects($this->once())->method('isSalable')->willReturn(true); $linkMock->expects($this->any())->method('getSampleType')->willReturn( \Magento\Downloadable\Helper\Download::LINK_TYPE_FILE ); diff --git a/app/code/Magento/Downloadable/Test/Unit/Controller/Download/SampleTest.php b/app/code/Magento/Downloadable/Test/Unit/Controller/Download/SampleTest.php index 2545e15317ebb..501ed58a3961b 100644 --- a/app/code/Magento/Downloadable/Test/Unit/Controller/Download/SampleTest.php +++ b/app/code/Magento/Downloadable/Test/Unit/Controller/Download/SampleTest.php @@ -8,6 +8,8 @@ use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; /** + * Unit tests for \Magento\Downloadable\Controller\Download\Sample. + * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class SampleTest extends \PHPUnit\Framework\TestCase @@ -63,6 +65,11 @@ class SampleTest extends \PHPUnit\Framework\TestCase */ protected $urlInterface; + /** + * @var \Magento\Catalog\Model\Product\SalabilityChecker|\PHPUnit_Framework_MockObject_MockObject + */ + private $salabilityCheckerMock; + /** * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ @@ -104,6 +111,7 @@ protected function setUp() $this->messageManager = $this->createMock(\Magento\Framework\Message\ManagerInterface::class); $this->redirect = $this->createMock(\Magento\Framework\App\Response\RedirectInterface::class); $this->urlInterface = $this->createMock(\Magento\Framework\UrlInterface::class); + $this->salabilityCheckerMock = $this->createMock(\Magento\Catalog\Model\Product\SalabilityChecker::class); $this->objectManager = $this->createPartialMock(\Magento\Framework\ObjectManager\ObjectManager::class, [ 'create', 'get' @@ -115,12 +123,18 @@ protected function setUp() 'request' => $this->request, 'response' => $this->response, 'messageManager' => $this->messageManager, - 'redirect' => $this->redirect + 'redirect' => $this->redirect, + 'salabilityChecker' => $this->salabilityCheckerMock, ] ); } - public function testExecuteLinkTypeUrl() + /** + * Execute Download sample action with Sample Url. + * + * @return void + */ + public function testExecuteSampleWithUrlType() { $sampleMock = $this->getMockBuilder(\Magento\Downloadable\Model\Sample::class) ->disableOriginalConstructor() @@ -134,6 +148,7 @@ public function testExecuteLinkTypeUrl() ->willReturn($sampleMock); $sampleMock->expects($this->once())->method('load')->with('some_sample_id')->willReturnSelf(); $sampleMock->expects($this->once())->method('getId')->willReturn('some_link_id'); + $this->salabilityCheckerMock->expects($this->once())->method('isSalable')->willReturn(true); $sampleMock->expects($this->once())->method('getSampleType')->willReturn( \Magento\Downloadable\Helper\Download::LINK_TYPE_URL ); @@ -155,7 +170,12 @@ public function testExecuteLinkTypeUrl() $this->assertEquals($this->response, $this->sample->execute()); } - public function testExecuteLinkTypeFile() + /** + * Execute Download sample action with Sample File. + * + * @return void + */ + public function testExecuteSampleWithFileType() { $sampleMock = $this->getMockBuilder(\Magento\Downloadable\Model\Sample::class) ->disableOriginalConstructor() @@ -173,6 +193,7 @@ public function testExecuteLinkTypeFile() ->willReturn($sampleMock); $sampleMock->expects($this->once())->method('load')->with('some_sample_id')->willReturnSelf(); $sampleMock->expects($this->once())->method('getId')->willReturn('some_sample_id'); + $this->salabilityCheckerMock->expects($this->once())->method('isSalable')->willReturn(true); $sampleMock->expects($this->any())->method('getSampleType')->willReturn( \Magento\Downloadable\Helper\Download::LINK_TYPE_FILE ); From ba5b1ba11ecabec3baa76ff15662cf780155cfad Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Sat, 13 Apr 2019 19:57:48 +0300 Subject: [PATCH 257/773] MAGETWO-99203: [FT] [MFTF] AdminExportSimpleProductAndConfigurableProductsWithAssignedImagesTest fails because of bad design --- .../Test/Mftf/ActionGroup/AdminExportActionGroup.xml | 4 ++-- ...leProductAndConfigurableProductsWithAssignedImagesTest.xml | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/CatalogImportExport/Test/Mftf/ActionGroup/AdminExportActionGroup.xml b/app/code/Magento/CatalogImportExport/Test/Mftf/ActionGroup/AdminExportActionGroup.xml index b9eea2b114634..7f8a854d8fb13 100644 --- a/app/code/Magento/CatalogImportExport/Test/Mftf/ActionGroup/AdminExportActionGroup.xml +++ b/app/code/Magento/CatalogImportExport/Test/Mftf/ActionGroup/AdminExportActionGroup.xml @@ -54,12 +54,12 @@ <argument name="rowIndex" type="string"/> </arguments> <reloadPage stepKey="refreshPage"/> - <waitForPageLoad stepKey="waitFormReload"/> + <waitForPageLoad time="30" stepKey="waitFormReload"/> <click stepKey="clickSelectBtn" selector="{{AdminExportAttributeSection.selectByIndex(rowIndex)}}"/> <click stepKey="clickOnDelete" selector="{{AdminExportAttributeSection.delete(rowIndex)}}" after="clickSelectBtn"/> <waitForElementVisible selector="{{AdminProductGridConfirmActionSection.title}}" stepKey="waitForConfirmModal"/> <click selector="{{AdminProductGridConfirmActionSection.ok}}" stepKey="confirmDelete"/> - <waitForPageLoad stepKey="waitForExportDataDeleted" /> + <waitForElementVisible selector="{{AdminDataGridTableSection.dataGridEmpty}}" stepKey="waitDataGridEmptyMessageAppears"/> <see selector="{{AdminDataGridTableSection.dataGridEmpty}}" userInput="We couldn't find any records." stepKey="assertDataGridEmptyMessage"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportSimpleProductAndConfigurableProductsWithAssignedImagesTest.xml b/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportSimpleProductAndConfigurableProductsWithAssignedImagesTest.xml index 993f1c9cd9da2..1442311709b3d 100644 --- a/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportSimpleProductAndConfigurableProductsWithAssignedImagesTest.xml +++ b/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportSimpleProductAndConfigurableProductsWithAssignedImagesTest.xml @@ -115,7 +115,6 @@ <!-- Go to export page --> <amOnPage url="{{AdminExportIndexPage.url}}" stepKey="goToExportIndexPage"/> - <waitForPageLoad stepKey="waitForExportIndexPageLoad"/> <!-- Fill entity attributes data --> <actionGroup ref="exportProductsFilterByAttribute" stepKey="exportProductBySku"> From 74628174c0c2b76b6ef1088a6304a2e65c262991 Mon Sep 17 00:00:00 2001 From: OlgaVasyltsun <olga.vasyltsun@gmail.com> Date: Mon, 15 Apr 2019 10:48:50 +0300 Subject: [PATCH 258/773] MC-10858: Escaper refactor --- .../Sales/Test/Mftf/Test/AdminChangeCustomerGroupInNewOrder.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminChangeCustomerGroupInNewOrder.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminChangeCustomerGroupInNewOrder.xml index 85ef563e10db7..315a097eb2323 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminChangeCustomerGroupInNewOrder.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminChangeCustomerGroupInNewOrder.xml @@ -26,7 +26,7 @@ <actionGroup ref="logout" stepKey="logout"/> </after> - <actionGroup ref="navigateToNewOrderPageNewCustomerSingleStore" stepKey="openNewOrder"/> + <actionGroup ref="navigateToNewOrderPageNewCustomer" stepKey="openNewOrder"/> <selectOption selector="{{AdminOrderFormAccountSection.group}}" userInput="Retailer" stepKey="selectCustomerGroup"/> <waitForPageLoad stepKey="waitForPageLoad"/> <grabValueFrom selector="{{AdminOrderFormAccountSection.group}}" stepKey="grabGroupValue"/> From d6308844c7b2f7da0ef8df958f3c4a7995f5aa7a Mon Sep 17 00:00:00 2001 From: Oleksandr Miroshnichenko <omiroshnichenko@magento.com> Date: Mon, 15 Apr 2019 11:43:26 -0500 Subject: [PATCH 259/773] MC-15385: Path check for images --- .../Cms/Model/Wysiwyg/Images/Storage.php | 39 ++++++++++++++++++- .../Unit/Model/Wysiwyg/Images/StorageTest.php | 7 ++-- 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Cms/Model/Wysiwyg/Images/Storage.php b/app/code/Magento/Cms/Model/Wysiwyg/Images/Storage.php index dfbbce99b6515..677a0f2460b61 100644 --- a/app/code/Magento/Cms/Model/Wysiwyg/Images/Storage.php +++ b/app/code/Magento/Cms/Model/Wysiwyg/Images/Storage.php @@ -430,12 +430,19 @@ public function deleteDirectory($path) if ($this->_coreFileStorageDb->checkDbUsage()) { $this->_directoryDatabaseFactory->create()->deleteDirectory($path); } + if (!$this->isPathAllowed($path, $this->getConditionsForExcludeDirs())) { + throw new \Magento\Framework\Exception\LocalizedException( + __('We cannot delete directory %1.', $this->_getRelativePathToRoot($path)) + ); + } try { $this->_deleteByPath($path); $path = $this->getThumbnailRoot() . $this->_getRelativePathToRoot($path); $this->_deleteByPath($path); } catch (\Magento\Framework\Exception\FileSystemException $e) { - throw new \Magento\Framework\Exception\LocalizedException(__('We cannot delete directory %1.', $path)); + throw new \Magento\Framework\Exception\LocalizedException( + __('We cannot delete directory %1.', $this->_getRelativePathToRoot($path)) + ); } } @@ -489,6 +496,11 @@ public function deleteFile($target) */ public function uploadFile($targetPath, $type = null) { + if (!$this->isPathAllowed($targetPath, $this->getConditionsForExcludeDirs())) { + throw new \Magento\Framework\Exception\LocalizedException( + __('We can\'t upload the file to current folder right now. Please try another folder.') + ); + } /** @var \Magento\MediaStorage\Model\File\Uploader $uploader */ $uploader = $this->_uploaderFactory->create(['fileId' => 'image']); $allowed = $this->getAllowedExtensions($type); @@ -784,4 +796,29 @@ private function getExtensionsList($type = null): array return $allowed; } + + /** + * Check if path is not in excluded dirs. + * + * @param string $path + * @param array $conditions + * @return bool + */ + private function isPathAllowed($path, array $conditions): bool + { + $isAllowed = true; + $regExp = $conditions['reg_exp'] ? '~' . implode('|', array_keys($conditions['reg_exp'])) . '~i' : null; + $storageRoot = $this->_cmsWysiwygImages->getStorageRoot(); + $storageRootLength = strlen($storageRoot); + + $mediaSubPathname = substr($path, $storageRootLength); + $rootChildParts = explode('/', '/' . ltrim($mediaSubPathname, '/')); + + if (array_key_exists($rootChildParts[1], $conditions['plain']) + || ($regExp && preg_match($regExp, $path))) { + $isAllowed = false; + } + + return $isAllowed; + } } diff --git a/app/code/Magento/Cms/Test/Unit/Model/Wysiwyg/Images/StorageTest.php b/app/code/Magento/Cms/Test/Unit/Model/Wysiwyg/Images/StorageTest.php index 7bec1e3601461..6cf38324b3917 100644 --- a/app/code/Magento/Cms/Test/Unit/Model/Wysiwyg/Images/StorageTest.php +++ b/app/code/Magento/Cms/Test/Unit/Model/Wysiwyg/Images/StorageTest.php @@ -18,7 +18,7 @@ class StorageTest extends \PHPUnit\Framework\TestCase /** * Directory paths samples */ - const STORAGE_ROOT_DIR = '/storage/root/dir'; + const STORAGE_ROOT_DIR = '/storage/root/dir/'; const INVALID_DIRECTORY_OVER_ROOT = '/storage/some/another/dir'; @@ -437,10 +437,11 @@ protected function generalTestGetDirsCollection($path, $collectionArray = [], $e public function testUploadFile() { - $targetPath = '/target/path'; + $path = 'target/path'; + $targetPath = self::STORAGE_ROOT_DIR . $path; $fileName = 'image.gif'; $realPath = $targetPath . '/' . $fileName; - $thumbnailTargetPath = self::STORAGE_ROOT_DIR . '/.thumbs'; + $thumbnailTargetPath = self::STORAGE_ROOT_DIR . '/.thumbs' . $path; $thumbnailDestination = $thumbnailTargetPath . '/' . $fileName; $type = 'image'; $result = [ From 51ec7f7980edfe1e8d56f8a5caecee48038ac4cf Mon Sep 17 00:00:00 2001 From: Oleksandr Miroshnichenko <omiroshnichenko@magento.com> Date: Mon, 15 Apr 2019 13:25:47 -0500 Subject: [PATCH 260/773] MC-15385: Path check for images - fix static tests --- app/code/Magento/Cms/Model/Wysiwyg/Images/Storage.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app/code/Magento/Cms/Model/Wysiwyg/Images/Storage.php b/app/code/Magento/Cms/Model/Wysiwyg/Images/Storage.php index 677a0f2460b61..16f4aaf02f3c2 100644 --- a/app/code/Magento/Cms/Model/Wysiwyg/Images/Storage.php +++ b/app/code/Magento/Cms/Model/Wysiwyg/Images/Storage.php @@ -328,6 +328,7 @@ public function getFilesCollection($path, $type = null) $item->setName($item->getBasename()); $item->setShortName($this->_cmsWysiwygImages->getShortFilename($item->getBasename())); $item->setUrl($this->_cmsWysiwygImages->getCurrentUrl() . $item->getBasename()); + // phpcs:ignore Magento2.Functions.DiscouragedFunction $item->setSize(filesize($item->getFilename())); $item->setMimeType(\mime_content_type($item->getFilename())); @@ -338,6 +339,7 @@ public function getFilesCollection($path, $type = null) $thumbUrl = $this->_backendUrl->getUrl('cms/*/thumbnail', ['file' => $item->getId()]); } + // phpcs:ignore Generic.PHP.NoSilencedErrors $size = @getimagesize($item->getFilename()); if (is_array($size)) { @@ -413,6 +415,7 @@ public function createDirectory($name, $path) 'id' => $this->_cmsWysiwygImages->convertPathToId($newPath), ]; return $result; + // phpcs:ignore Magento2.Exceptions.ThrowCatch } catch (\Magento\Framework\Exception\FileSystemException $e) { throw new \Magento\Framework\Exception\LocalizedException(__('We cannot create a new directory.')); } @@ -439,6 +442,7 @@ public function deleteDirectory($path) $this->_deleteByPath($path); $path = $this->getThumbnailRoot() . $this->_getRelativePathToRoot($path); $this->_deleteByPath($path); + // phpcs:ignore Magento2.Exceptions.ThrowCatch } catch (\Magento\Framework\Exception\FileSystemException $e) { throw new \Magento\Framework\Exception\LocalizedException( __('We cannot delete directory %1.', $this->_getRelativePathToRoot($path)) @@ -601,6 +605,7 @@ public function resizeFile($source, $keepRatio = true) $image->open($source); $image->keepAspectRatio($keepRatio); $image->resize($this->_resizeParameters['width'], $this->_resizeParameters['height']); + // phpcs:ignore Magento2.Functions.DiscouragedFunction $dest = $targetDir . '/' . pathinfo($source, PATHINFO_BASENAME); $image->save($dest); if ($this->_directory->isFile($this->_directory->getRelativePath($dest))) { @@ -636,6 +641,7 @@ public function getThumbsPath($filePath = false) $thumbnailDir = $this->getThumbnailRoot(); if ($filePath && strpos($filePath, $mediaRootDir) === 0) { + // phpcs:ignore Magento2.Functions.DiscouragedFunction $thumbnailDir .= dirname(substr($filePath, strlen($mediaRootDir))); } @@ -686,6 +692,7 @@ public function isImage($filename) if (!$this->hasData('_image_extensions')) { $this->setData('_image_extensions', $this->getAllowedExtensions('image')); } + // phpcs:ignore Magento2.Functions.DiscouragedFunction $ext = strtolower(pathinfo($filename, PATHINFO_EXTENSION)); return in_array($ext, $this->_getData('_image_extensions')); } From 6eabaae46cd019332224712faddd0faad65b57b6 Mon Sep 17 00:00:00 2001 From: Hwashiang Yu <hwyu@adobe.com> Date: Mon, 15 Apr 2019 14:41:10 -0500 Subject: [PATCH 261/773] MC-15662: Currency symbol template update - Reverted coding standard ignore --- .../Sales/view/adminhtml/templates/order/create/data.phtml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/code/Magento/Sales/view/adminhtml/templates/order/create/data.phtml b/app/code/Magento/Sales/view/adminhtml/templates/order/create/data.phtml index 5e40327cfe88b..17d43266ba524 100644 --- a/app/code/Magento/Sales/view/adminhtml/templates/order/create/data.phtml +++ b/app/code/Magento/Sales/view/adminhtml/templates/order/create/data.phtml @@ -4,6 +4,8 @@ * See COPYING.txt for license details. */ +// @codingStandardsIgnoreFile + ?> <div class="page-create-order"> <script> From 92d8bcadd444263cc19ce6fd43c45e32c58496bb Mon Sep 17 00:00:00 2001 From: Oleksandr Miroshnichenko <omiroshnichenko@magento.com> Date: Tue, 16 Apr 2019 11:44:41 -0500 Subject: [PATCH 262/773] MC-15385: Path check for images --- .../Cms/Model/Wysiwyg/Images/Storage.php | 8 ++-- .../Wysiwyg/Images/DeleteFolderTest.php | 37 +++++++++++++++++++ .../Adminhtml/Wysiwyg/Images/UploadTest.php | 35 ++++++++++++++++++ 3 files changed, 76 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Cms/Model/Wysiwyg/Images/Storage.php b/app/code/Magento/Cms/Model/Wysiwyg/Images/Storage.php index 16f4aaf02f3c2..6cfa43eb36e2c 100644 --- a/app/code/Magento/Cms/Model/Wysiwyg/Images/Storage.php +++ b/app/code/Magento/Cms/Model/Wysiwyg/Images/Storage.php @@ -424,7 +424,7 @@ public function createDirectory($name, $path) /** * Recursively delete directory from storage * - * @param string $path Target dir + * @param string $path Absolute path to target directory * @return void * @throws \Magento\Framework\Exception\LocalizedException */ @@ -493,7 +493,7 @@ public function deleteFile($target) /** * Upload and resize new file * - * @param string $targetPath Target directory + * @param string $targetPath Absolute path to target directory * @param string $type Type of storage, e.g. image, media etc. * @return array File info Array * @throws \Magento\Framework\Exception\LocalizedException @@ -807,8 +807,8 @@ private function getExtensionsList($type = null): array /** * Check if path is not in excluded dirs. * - * @param string $path - * @param array $conditions + * @param string $path Absolute path + * @param array $conditions Exclude conditions * @return bool */ private function isPathAllowed($path, array $conditions): bool diff --git a/dev/tests/integration/testsuite/Magento/Cms/Controller/Adminhtml/Wysiwyg/Images/DeleteFolderTest.php b/dev/tests/integration/testsuite/Magento/Cms/Controller/Adminhtml/Wysiwyg/Images/DeleteFolderTest.php index c574869a83cab..af495841b9672 100644 --- a/dev/tests/integration/testsuite/Magento/Cms/Controller/Adminhtml/Wysiwyg/Images/DeleteFolderTest.php +++ b/dev/tests/integration/testsuite/Magento/Cms/Controller/Adminhtml/Wysiwyg/Images/DeleteFolderTest.php @@ -7,6 +7,7 @@ namespace Magento\Cms\Controller\Adminhtml\Wysiwyg\Images; use Magento\Framework\App\Filesystem\DirectoryList; +use Magento\Framework\App\Response\HttpFactory as ResponseFactory; /** * Test for \Magento\Cms\Controller\Adminhtml\Wysiwyg\Images\DeleteFolder class. @@ -38,6 +39,11 @@ class DeleteFolderTest extends \PHPUnit\Framework\TestCase */ private $filesystem; + /** + * @var HttpFactory + */ + private $responseFactory; + /** * @inheritdoc */ @@ -49,6 +55,7 @@ protected function setUp() /** @var \Magento\Cms\Helper\Wysiwyg\Images $imagesHelper */ $this->imagesHelper = $objectManager->get(\Magento\Cms\Helper\Wysiwyg\Images::class); $this->fullDirectoryPath = $this->imagesHelper->getStorageRoot(); + $this->responseFactory = $objectManager->get(ResponseFactory::class); $this->model = $objectManager->get(\Magento\Cms\Controller\Adminhtml\Wysiwyg\Images\DeleteFolder::class); } @@ -83,6 +90,7 @@ public function testExecute() * can be removed. * * @magentoDataFixture Magento/Cms/_files/linked_media.php + * @magentoAppIsolation enabled */ public function testExecuteWithLinkedMedia() { @@ -106,6 +114,7 @@ public function testExecuteWithLinkedMedia() * under media directory. * * @return void + * @magentoAppIsolation enabled */ public function testExecuteWithWrongDirectoryName() { @@ -116,6 +125,31 @@ public function testExecuteWithWrongDirectoryName() $this->assertFileExists($this->fullDirectoryPath . $directoryName); } + /** + * Execute method to check that there is no ability to remove folder which is in excluded directories list. + * + * @return void + * @magentoAppIsolation enabled + */ + public function testExecuteWithExcludedDirectoryName() + { + $directoryName = 'downloadable'; + $expectedResponseMessage = 'We cannot delete directory /downloadable.'; + $mediaDirectory = $this->filesystem->getDirectoryWrite(DirectoryList::MEDIA); + $mediaDirectory->create($directoryName); + $this->assertFileExists($this->fullDirectoryPath . $directoryName); + + $this->model->getRequest()->setParams(['node' => $this->imagesHelper->idEncode($directoryName)]); + $this->model->getRequest()->setMethod('POST'); + $jsonResponse = $this->model->execute(); + $jsonResponse->renderResult($response = $this->responseFactory->create()); + $data = json_decode($response->getBody(), true); + + $this->assertTrue($data['error']); + $this->assertEquals($expectedResponseMessage, $data['message']); + $this->assertFileExists($this->fullDirectoryPath . $directoryName); + } + /** * @inheritdoc */ @@ -128,5 +162,8 @@ public static function tearDownAfterClass() if ($directory->isExist('wysiwyg')) { $directory->delete('wysiwyg'); } + if ($directory->isExist('downloadable')) { + $directory->delete('downloadable'); + } } } diff --git a/dev/tests/integration/testsuite/Magento/Cms/Controller/Adminhtml/Wysiwyg/Images/UploadTest.php b/dev/tests/integration/testsuite/Magento/Cms/Controller/Adminhtml/Wysiwyg/Images/UploadTest.php index 00f56e5700415..9303a5eac7868 100644 --- a/dev/tests/integration/testsuite/Magento/Cms/Controller/Adminhtml/Wysiwyg/Images/UploadTest.php +++ b/dev/tests/integration/testsuite/Magento/Cms/Controller/Adminhtml/Wysiwyg/Images/UploadTest.php @@ -33,6 +33,11 @@ class UploadTest extends \PHPUnit\Framework\TestCase */ private $fullDirectoryPath; + /** + * @var string + */ + private $fullExcludedDirectoryPath; + /** * @var string */ @@ -60,11 +65,13 @@ protected function setUp() { $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); $directoryName = 'directory1'; + $excludedDirName = 'downloadable'; $this->filesystem = $this->objectManager->get(\Magento\Framework\Filesystem::class); /** @var \Magento\Cms\Helper\Wysiwyg\Images $imagesHelper */ $imagesHelper = $this->objectManager->get(\Magento\Cms\Helper\Wysiwyg\Images::class); $this->mediaDirectory = $this->filesystem->getDirectoryWrite(DirectoryList::MEDIA); $this->fullDirectoryPath = $imagesHelper->getStorageRoot() . DIRECTORY_SEPARATOR . $directoryName; + $this->fullExcludedDirectoryPath = $imagesHelper->getStorageRoot() . DIRECTORY_SEPARATOR . $excludedDirName; $this->mediaDirectory->create($this->mediaDirectory->getRelativePath($this->fullDirectoryPath)); $this->responseFactory = $this->objectManager->get(ResponseFactory::class); $this->model = $this->objectManager->get(\Magento\Cms\Controller\Adminhtml\Wysiwyg\Images\Upload::class); @@ -115,6 +122,34 @@ public function testExecute() $this->assertEquals($keys, $dataKeys); } + /** + * Execute method with excluded directory path and file name to check that file can't be uploaded. + * + * @return void + * @magentoAppIsolation enabled + */ + public function testExecuteWithExcludedDirectory() + { + $expectedError = 'We can\'t upload the file to current folder right now. Please try another folder.'; + $this->model->getRequest()->setParams(['type' => 'image/png']); + $this->model->getRequest()->setMethod('POST'); + $this->model->getStorage()->getSession()->setCurrentPath($this->fullExcludedDirectoryPath); + /** @var JsonResponse $jsonResponse */ + $jsonResponse = $this->model->execute(); + /** @var Response $response */ + $jsonResponse->renderResult($response = $this->responseFactory->create()); + $data = json_decode($response->getBody(), true); + + $this->assertEquals($expectedError, $data['error']); + $this->assertFalse( + $this->mediaDirectory->isExist( + $this->mediaDirectory->getRelativePath( + $this->fullExcludedDirectoryPath . DIRECTORY_SEPARATOR . $this->fileName + ) + ) + ); + } + /** * Execute method with correct directory path and file name to check that file can be uploaded to the directory * located under linked folder. From b967a6854b2d345381c07ebe14d72a719a9633f0 Mon Sep 17 00:00:00 2001 From: Nathan Smith <nathsmit@adobe.com> Date: Tue, 16 Apr 2019 13:44:32 -0500 Subject: [PATCH 263/773] MC-15425: Incorrect ImportExport entity handling --- app/code/Magento/ImportExport/Model/Import.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/ImportExport/Model/Import.php b/app/code/Magento/ImportExport/Model/Import.php index 53fe190b34138..04f4111d3a0a8 100644 --- a/app/code/Magento/ImportExport/Model/Import.php +++ b/app/code/Magento/ImportExport/Model/Import.php @@ -45,6 +45,7 @@ * @method self setEntity() setEntity(string $value) * @SuppressWarnings(PHPMD.CouplingBetweenObjects) * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) + * @SuppressWarnings(PHPMD.TooManyFields) * @since 100.0.2 */ class Import extends AbstractModel @@ -367,6 +368,7 @@ public function getOperationResultMessages(ProcessingErrorAggregatorInterface $v * * @param AbstractAttribute|Attribute $attribute * @return string + * phpcs:disable Magento2.Functions.StaticFunction */ public static function getAttributeType(AbstractAttribute $attribute) { @@ -548,6 +550,7 @@ public function uploadSource() $uploader->skipDbProcessing(true); $fileName = $this->random->getRandomString(32) . '.' . $uploader->getFileExtension(); $result = $uploader->save($this->getWorkingDir(), $fileName); + // phpcs:disable Magento2.Functions.DiscouragedFunction.Discouraged $extension = pathinfo($result['file'], PATHINFO_EXTENSION); $uploadedFile = $result['path'] . $result['file']; @@ -583,7 +586,6 @@ public function uploadSource() * Move uploaded file and provide source instance. * * @return Import\AbstractSource - * @throws FileSystemException * @throws LocalizedException */ public function uploadFileAndGetSource() @@ -679,6 +681,7 @@ public function invalidateIndex() if (!$indexer->isScheduled()) { $indexer->invalidate(); } + // phpcs:disable Magento2.CodeAnalysis.EmptyBlock.DetectedCatch } catch (\InvalidArgumentException $e) { } } @@ -798,6 +801,7 @@ protected function createHistoryReport($sourceFileRelative, $entity, $extension } elseif ($extension !== null) { $fileName = $entity . $extension; } else { + // phpcs:disable Magento2.Functions.DiscouragedFunction.Discouraged $fileName = basename($sourceFileRelative); } $copyName = $this->localeDate->gmtTimestamp() . '_' . $fileName; From ac171e161d9938031a41616dad2ea91195658945 Mon Sep 17 00:00:00 2001 From: Hwashiang Yu <hwyu@adobe.com> Date: Tue, 16 Apr 2019 15:02:20 -0500 Subject: [PATCH 264/773] MC-14826: Incorrect customer html address template - Updated personal info and address templates --- .../view/adminhtml/templates/tab/view/personal_info.phtml | 5 ++++- .../Sales/view/adminhtml/templates/order/view/info.phtml | 7 +++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Customer/view/adminhtml/templates/tab/view/personal_info.phtml b/app/code/Magento/Customer/view/adminhtml/templates/tab/view/personal_info.phtml index f43cb8ab5f0de..6ac770f65b271 100644 --- a/app/code/Magento/Customer/view/adminhtml/templates/tab/view/personal_info.phtml +++ b/app/code/Magento/Customer/view/adminhtml/templates/tab/view/personal_info.phtml @@ -13,6 +13,9 @@ $lastLoginDateStore = $block->getStoreLastLoginDate(); $createDateAdmin = $block->getCreateDate(); $createDateStore = $block->getStoreCreateDate(); +$allowedAddressHtmlTags = ['abbr', 'b', 'blockquote', 'br', 'code', 'dd', 'del', 'dl', 'dt', 'em', + 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'kbd', 'li', 'ol', 'p', 'pre', 's', 'strike', + 'strong', 'sub', 'sup', 'ul']; ?> <div class="fieldset-wrapper customer-information"> <div class="fieldset-wrapper-title"> @@ -61,7 +64,7 @@ $createDateStore = $block->getStoreCreateDate(); </table> <address> <strong><?= $block->escapeHtml(__('Default Billing Address')) ?></strong><br/> - <?= $block->getBillingAddressHtml() ?> + <?= $block->escapeHtml($block->getBillingAddressHtml(), $allowedAddressHtmlTags) ?> </address> </div> diff --git a/app/code/Magento/Sales/view/adminhtml/templates/order/view/info.phtml b/app/code/Magento/Sales/view/adminhtml/templates/order/view/info.phtml index bbd6394097f9e..d8726bd58e308 100644 --- a/app/code/Magento/Sales/view/adminhtml/templates/order/view/info.phtml +++ b/app/code/Magento/Sales/view/adminhtml/templates/order/view/info.phtml @@ -26,6 +26,9 @@ $orderStoreDate = $block->formatDate( ); $customerUrl = $block->getCustomerViewUrl(); +$allowedAddressHtmlTags = ['abbr', 'b', 'blockquote', 'br', 'code', 'dd', 'del', 'dl', 'dt', 'em', + 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'kbd', 'li', 'ol', 'p', 'pre', 's', 'strike', + 'strong', 'sub', 'sup', 'ul']; ?> <section class="admin__page-section order-view-account-information"> @@ -171,7 +174,7 @@ $customerUrl = $block->getCustomerViewUrl(); <span class="title"><?= $block->escapeHtml(__('Billing Address')) ?></span> <div class="actions"><?= /* @noEscape */ $block->getAddressEditLink($order->getBillingAddress()); ?></div> </div> - <address class="admin__page-section-item-content"><?= /* @noEscape */ $block->getFormattedAddress($order->getBillingAddress()); ?></address> + <address class="admin__page-section-item-content"><?= $block->escapeHtml($block->getFormattedAddress($order->getBillingAddress()), $allowedAddressHtmlTags); ?></address> </div> <?php if (!$block->getOrder()->getIsVirtual()): ?> <div class="admin__page-section-item order-shipping-address"> @@ -180,7 +183,7 @@ $customerUrl = $block->getCustomerViewUrl(); <span class="title"><?= $block->escapeHtml(__('Shipping Address')) ?></span> <div class="actions"><?= /* @noEscape */ $block->getAddressEditLink($order->getShippingAddress()); ?></div> </div> - <address class="admin__page-section-item-content"><?= /* @noEscape */ $block->getFormattedAddress($order->getShippingAddress()); ?></address> + <address class="admin__page-section-item-content"><?= $block->escapeHtml($block->getFormattedAddress($order->getShippingAddress()), $allowedAddressHtmlTags); ?></address> </div> <?php endif; ?> </div> From 81397bdc67efa516a2f822812ac5f684638c8dbb Mon Sep 17 00:00:00 2001 From: Hwashiang Yu <hwyu@adobe.com> Date: Tue, 16 Apr 2019 15:34:32 -0500 Subject: [PATCH 265/773] MC-14826: Incorrect customer html address template - Updated personal info and address templates - Updated translation file - Add label on allowed tags --- app/code/Magento/Customer/etc/adminhtml/system.xml | 1 + app/code/Magento/Customer/i18n/en_US.csv | 1 + .../view/adminhtml/templates/tab/view/personal_info.phtml | 4 +--- .../Sales/view/adminhtml/templates/order/view/info.phtml | 4 +--- 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/Customer/etc/adminhtml/system.xml b/app/code/Magento/Customer/etc/adminhtml/system.xml index 86e5852d67aeb..8a4d07d2bc4f3 100644 --- a/app/code/Magento/Customer/etc/adminhtml/system.xml +++ b/app/code/Magento/Customer/etc/adminhtml/system.xml @@ -280,6 +280,7 @@ </field> <field id="html" translate="label" type="textarea" sortOrder="3" showInDefault="1" showInWebsite="1" showInStore="1" canRestore="1"> <label>HTML</label> + <comment>Only 'b', 'br', 'em', 'i', 'li', 'ol', 'p', 'strong', 'sub', 'sup', 'ul' tags are allowed</comment> </field> <field id="pdf" translate="label" type="textarea" sortOrder="4" showInDefault="1" showInWebsite="1" showInStore="1" canRestore="1"> <label>PDF</label> diff --git a/app/code/Magento/Customer/i18n/en_US.csv b/app/code/Magento/Customer/i18n/en_US.csv index 578267984f985..1d4193d1b1ea8 100644 --- a/app/code/Magento/Customer/i18n/en_US.csv +++ b/app/code/Magento/Customer/i18n/en_US.csv @@ -500,6 +500,7 @@ Strong,Strong "Address Templates","Address Templates" "Online Customers Options","Online Customers Options" "Online Minutes Interval","Online Minutes Interval" +"Only 'b', 'br', 'em', 'i', 'li', 'ol', 'p', 'strong', 'sub', 'sup', 'ul' tags are allowed","Only 'b', 'br', 'em', 'i', 'li', 'ol', 'p', 'strong', 'sub', 'sup', 'ul' tags are allowed" "Leave empty for default (15 minutes).","Leave empty for default (15 minutes)." "Customer Notification","Customer Notification" "Customer Grid","Customer Grid" diff --git a/app/code/Magento/Customer/view/adminhtml/templates/tab/view/personal_info.phtml b/app/code/Magento/Customer/view/adminhtml/templates/tab/view/personal_info.phtml index 6ac770f65b271..2bf1e0c32112f 100644 --- a/app/code/Magento/Customer/view/adminhtml/templates/tab/view/personal_info.phtml +++ b/app/code/Magento/Customer/view/adminhtml/templates/tab/view/personal_info.phtml @@ -13,9 +13,7 @@ $lastLoginDateStore = $block->getStoreLastLoginDate(); $createDateAdmin = $block->getCreateDate(); $createDateStore = $block->getStoreCreateDate(); -$allowedAddressHtmlTags = ['abbr', 'b', 'blockquote', 'br', 'code', 'dd', 'del', 'dl', 'dt', 'em', - 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'kbd', 'li', 'ol', 'p', 'pre', 's', 'strike', - 'strong', 'sub', 'sup', 'ul']; +$allowedAddressHtmlTags = ['b', 'br', 'em', 'i', 'li', 'ol', 'p', 'strong', 'sub', 'sup', 'ul']; ?> <div class="fieldset-wrapper customer-information"> <div class="fieldset-wrapper-title"> diff --git a/app/code/Magento/Sales/view/adminhtml/templates/order/view/info.phtml b/app/code/Magento/Sales/view/adminhtml/templates/order/view/info.phtml index d8726bd58e308..5c96cb118fa45 100644 --- a/app/code/Magento/Sales/view/adminhtml/templates/order/view/info.phtml +++ b/app/code/Magento/Sales/view/adminhtml/templates/order/view/info.phtml @@ -26,9 +26,7 @@ $orderStoreDate = $block->formatDate( ); $customerUrl = $block->getCustomerViewUrl(); -$allowedAddressHtmlTags = ['abbr', 'b', 'blockquote', 'br', 'code', 'dd', 'del', 'dl', 'dt', 'em', - 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'kbd', 'li', 'ol', 'p', 'pre', 's', 'strike', - 'strong', 'sub', 'sup', 'ul']; +$allowedAddressHtmlTags = ['b', 'br', 'em', 'i', 'li', 'ol', 'p', 'strong', 'sub', 'sup', 'ul']; ?> <section class="admin__page-section order-view-account-information"> From d38b533306d3111e7287a74db68947a242c4f087 Mon Sep 17 00:00:00 2001 From: Oleksandr Miroshnichenko <omiroshnichenko@magento.com> Date: Tue, 16 Apr 2019 15:59:06 -0500 Subject: [PATCH 266/773] MC-15385: Path check for images --- .../Cms/Model/Wysiwyg/Images/StorageTest.php | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/dev/tests/integration/testsuite/Magento/Cms/Model/Wysiwyg/Images/StorageTest.php b/dev/tests/integration/testsuite/Magento/Cms/Model/Wysiwyg/Images/StorageTest.php index fd450e9fef593..5d256f2234a53 100644 --- a/dev/tests/integration/testsuite/Magento/Cms/Model/Wysiwyg/Images/StorageTest.php +++ b/dev/tests/integration/testsuite/Magento/Cms/Model/Wysiwyg/Images/StorageTest.php @@ -107,6 +107,31 @@ public function testGetThumbsPath(): void ); } + /** + * @return void + */ + public function testDeleteDirectory(): void + { + $path = $this->objectManager->get(\Magento\Cms\Helper\Wysiwyg\Images::class)->getCurrentPath(); + $dir = 'testDeleteDirectory'; + $fullPath = $path . $dir; + $this->storage->createDirectory($dir, $path); + $this->assertFileExists($fullPath); + $this->storage->deleteDirectory($fullPath); + $this->assertFileNotExists($fullPath); + } + + /** + * @return void + * @expectedException \Magento\Framework\Exception\LocalizedException + * @expectedExceptionMessage We cannot delete directory /downloadable. + */ + public function testDeleteDirectoryWithExcludedDirPath(): void + { + $dir = $this->objectManager->get(\Magento\Cms\Helper\Wysiwyg\Images::class)->getCurrentPath() . 'downloadable'; + $this->storage->deleteDirectory($dir); + } + /** * @return void */ @@ -126,11 +151,39 @@ public function testUploadFile(): void 'error' => 0, 'size' => 12500, ]; + $this->storage->uploadFile(self::$_baseDir); $this->assertTrue(is_file(self::$_baseDir . DIRECTORY_SEPARATOR . $fileName)); // phpcs:enable } + /** + * @return void + * @expectedException \Magento\Framework\Exception\LocalizedException + * @expectedExceptionMessage We can't upload the file to current folder right now. Please try another folder. + */ + public function testUploadFileWithExcludedDirPath(): void + { + $fileName = 'magento_small_image.jpg'; + $tmpDirectory = $this->filesystem->getDirectoryWrite(\Magento\Framework\App\Filesystem\DirectoryList::SYS_TMP); + $filePath = $tmpDirectory->getAbsolutePath($fileName); + // phpcs:disable + $fixtureDir = realpath(__DIR__ . '/../../../../Catalog/_files'); + copy($fixtureDir . DIRECTORY_SEPARATOR . $fileName, $filePath); + + $_FILES['image'] = [ + 'name' => $fileName, + 'type' => 'image/jpeg', + 'tmp_name' => $filePath, + 'error' => 0, + 'size' => 12500, + ]; + + $dir = $this->objectManager->get(\Magento\Cms\Helper\Wysiwyg\Images::class)->getCurrentPath() . 'downloadable'; + $this->storage->uploadFile($dir); + // phpcs:enable + } + /** * @param string $fileName * @param string $fileType From 01c96b830d4738bee35509e1c687254b715b9ded Mon Sep 17 00:00:00 2001 From: eduard13 <e.chitoraga@atwix.com> Date: Wed, 17 Apr 2019 13:35:49 +0300 Subject: [PATCH 267/773] Refactoring the Action Groups and the overall implementation --- .../AdminFilterGridActionGroup.xml} | 10 +++--- .../AdminResetFilterActionGroup.xml | 17 ++++++++++ .../ActionGroup/AssertMessageActionGroup.xml | 18 +++++++++++ .../AssertValueInGridActionGroup.xml | 16 ++++++++++ .../Mftf/Section/AdminGridTableSection.xml | 1 + .../AdminAssertSuccessAddedActionGroup.xml | 16 ---------- .../AdminCreateCustomVariableActionGroup.xml | 20 ++++++++++++ .../AdminDeleteCustomVariableActionGroup.xml | 22 +++++++++++++ .../CreateCustomVariableActionGroup.xml | 31 ------------------- .../Test/Mftf/Page/AdminNewVariablePage.xml | 2 +- .../Test/Mftf/Page/AdminVariablesPage.xml | 2 +- .../Section/AdminVariableMessagesSection.xml | 15 --------- .../Section/AdminVariablesFilterSection.xml | 2 -- .../Section/AdminVariablesGridSection.xml | 1 - .../Test/CreateCustomVariableEntityTest.xml | 19 ++++++++---- .../CreateCustomVariableEntityTest.xml | 3 +- 16 files changed, 114 insertions(+), 81 deletions(-) rename app/code/Magento/{Variable/Test/Mftf/ActionGroup/FilterVariablesGridActionGroup.xml => Backend/Test/Mftf/ActionGroup/AdminFilterGridActionGroup.xml} (59%) create mode 100644 app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminResetFilterActionGroup.xml create mode 100644 app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertMessageActionGroup.xml create mode 100644 app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertValueInGridActionGroup.xml delete mode 100644 app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminAssertSuccessAddedActionGroup.xml create mode 100644 app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminCreateCustomVariableActionGroup.xml create mode 100644 app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminDeleteCustomVariableActionGroup.xml delete mode 100644 app/code/Magento/Variable/Test/Mftf/ActionGroup/CreateCustomVariableActionGroup.xml delete mode 100644 app/code/Magento/Variable/Test/Mftf/Section/AdminVariableMessagesSection.xml diff --git a/app/code/Magento/Variable/Test/Mftf/ActionGroup/FilterVariablesGridActionGroup.xml b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminFilterGridActionGroup.xml similarity index 59% rename from app/code/Magento/Variable/Test/Mftf/ActionGroup/FilterVariablesGridActionGroup.xml rename to app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminFilterGridActionGroup.xml index b40725eb781c4..dea1038159fce 100644 --- a/app/code/Magento/Variable/Test/Mftf/ActionGroup/FilterVariablesGridActionGroup.xml +++ b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminFilterGridActionGroup.xml @@ -8,15 +8,13 @@ <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="FilterVariablesGridActionGroup"> + <actionGroup name="AdminFilterGridActionGroup"> <arguments> <argument name="field" type="string"/> <argument name="value" type="string"/> + <argument name="button" type="string" defaultValue="{{AdminSecondaryGridSection.searchButton}}"/> </arguments> - <fillField selector="{{field}}" userInput="{{value}}" stepKey="fillVariableAttributeInFilter"/> - <click selector="{{AdminVariablesFilterSection.searchButton}}" stepKey="clickSearchButton"/> - </actionGroup> - <actionGroup name="ResetFilterVariablesGridActionGroup"> - <click selector="{{AdminVariablesFilterSection.resetFilterButton}}" stepKey="clickResetButton"/> + <fillField selector="{{field}}" userInput="{{value}}" stepKey="fillFieldInFilter"/> + <click selector="{{button}}" stepKey="clickSearchButton"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminResetFilterActionGroup.xml b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminResetFilterActionGroup.xml new file mode 100644 index 0000000000000..0b778cae0be50 --- /dev/null +++ b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminResetFilterActionGroup.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminResetFilterActionGroup"> + <arguments> + <argument name="selector" type="string" defaultValue="{{AdminSecondaryGridSection.resetFilters}}"/> + </arguments> + <click selector="{{selector}}" stepKey="clickResetButton"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertMessageActionGroup.xml b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertMessageActionGroup.xml new file mode 100644 index 0000000000000..25e716a139487 --- /dev/null +++ b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertMessageActionGroup.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AssertMessageActionGroup"> + <arguments> + <argument name="message" type="string" /> + <argument name="messageType" type="string" defaultValue="success" /> + </arguments> + <see userInput="{{message}}" selector=".messages .message-{{messageType}}" stepKey="verifyMessage" /> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertValueInGridActionGroup.xml b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertValueInGridActionGroup.xml new file mode 100644 index 0000000000000..20efab26455f2 --- /dev/null +++ b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertValueInGridActionGroup.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AssertValueInGridActionGroup"> + <arguments> + <argument name="value" type="string" /> + </arguments> + <see selector="{{AdminGridTableSection.rowByValue(value)}}" userInput="{{value}}" stepKey="seeValueInGrid"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Backend/Test/Mftf/Section/AdminGridTableSection.xml b/app/code/Magento/Backend/Test/Mftf/Section/AdminGridTableSection.xml index cc92e530cf3d4..bb3cf57e4d6ef 100644 --- a/app/code/Magento/Backend/Test/Mftf/Section/AdminGridTableSection.xml +++ b/app/code/Magento/Backend/Test/Mftf/Section/AdminGridTableSection.xml @@ -10,5 +10,6 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="AdminGridTableSection"> <element name="row" type="text" selector="table.data-grid tbody tr[data-role=row]:nth-of-type({{row}})" parameterized="true"/> + <element name="rowByValue" type="text" selector="//tr[@data-role='row'] //td[contains(., '{{var}}')]" parameterized="true" timeout="30"/> </section> </sections> diff --git a/app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminAssertSuccessAddedActionGroup.xml b/app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminAssertSuccessAddedActionGroup.xml deleted file mode 100644 index fd1f7870896e7..0000000000000 --- a/app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminAssertSuccessAddedActionGroup.xml +++ /dev/null @@ -1,16 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="AdminAssertSuccessMessageActionGroup" > - <see userInput="You saved the custom variable." selector="{{AdminVariableMessagesSection.successMessage}}" stepKey="seeMessage"/> - </actionGroup> - <actionGroup name="AdminSeeVariableInGridActionGroup"> - <see selector="{{AdminVariablesGridSection.rowByValue(customVariable.code)}}" userInput="{{customVariable.code}}" stepKey="seeVariableCodeInGrid"/> - </actionGroup> -</actionGroups> diff --git a/app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminCreateCustomVariableActionGroup.xml b/app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminCreateCustomVariableActionGroup.xml new file mode 100644 index 0000000000000..21d98617d9a4e --- /dev/null +++ b/app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminCreateCustomVariableActionGroup.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminCreateCustomVariableActionGroup"> + <amOnPage url="admin/admin/system_variable/new/" stepKey="goToNewCustomVariablePage"/> + <waitForPageLoad stepKey="waitForPageLoad"/> + <fillField selector="{{CustomVariableSection.variableCode}}" userInput="{{customVariable.code}}" stepKey="fillVariableCode"/> + <fillField selector="{{CustomVariableSection.variableName}}" userInput="{{customVariable.name}}" stepKey="fillVariableName"/> + <fillField selector="{{CustomVariableSection.variableHTML}}" userInput="{{customVariable.html}}" stepKey="fillVariableHtml"/> + <fillField selector="{{CustomVariableSection.variablePlain}}" userInput="{{customVariable.plain}}" stepKey="fillVariablePlain"/> + <click selector="{{AdminMainActionsSection.save}}" stepKey="clickSaveVariable"/> + <waitForPageLoad stepKey="waitForPageLoad2"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminDeleteCustomVariableActionGroup.xml b/app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminDeleteCustomVariableActionGroup.xml new file mode 100644 index 0000000000000..bbd17b2ed39e2 --- /dev/null +++ b/app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminDeleteCustomVariableActionGroup.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminDeleteCustomVariableActionGroup"> + <amOnPage url="admin/admin/system_variable/" stepKey="goToVariableGrid"/> + <waitForPageLoad stepKey="waitForPageLoad1"/> + <click selector="{{CustomVariableSection.GridCustomVariableCode(customVariable.code)}}" stepKey="goToCustomVariableEditPage"/> + <waitForPageLoad stepKey="waitForPageLoad2"/> + <waitForElementVisible selector="{{CustomVariableSection.delete}}" stepKey="waitForDeleteBtn"/> + <click selector="{{CustomVariableSection.delete}}" stepKey="deleteCustomVariable"/> + <waitForText userInput="Are you sure you want to do this?" stepKey="waitForText"/> + <click selector="{{CustomVariableSection.confirmDelete}}" stepKey="confirmDelete"/> + <waitForPageLoad stepKey="waitForPageLoad3"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Variable/Test/Mftf/ActionGroup/CreateCustomVariableActionGroup.xml b/app/code/Magento/Variable/Test/Mftf/ActionGroup/CreateCustomVariableActionGroup.xml deleted file mode 100644 index 4d36cd0669b8e..0000000000000 --- a/app/code/Magento/Variable/Test/Mftf/ActionGroup/CreateCustomVariableActionGroup.xml +++ /dev/null @@ -1,31 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> - <!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - --> - -<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> -<actionGroup name="CreateCustomVariableActionGroup"> - <amOnPage url="admin/admin/system_variable/new/" stepKey="goToNewCustomVariablePage" /> - <waitForPageLoad stepKey="waitForPageLoad" /> - <fillField selector="{{CustomVariableSection.variableCode}}" userInput="{{customVariable.code}}" stepKey="fillVariableCode" /> - <fillField selector="{{CustomVariableSection.variableName}}" userInput="{{customVariable.name}}" stepKey="fillVariableName" /> - <fillField selector="{{CustomVariableSection.variableHTML}}" userInput="{{customVariable.html}}" stepKey="fillVariableHtml" /> - <fillField selector="{{CustomVariableSection.variablePlain}}" userInput="{{customVariable.plain}}" stepKey="fillVariablePlain" /> - <click selector="{{CustomVariableSection.saveCustomVariable}}" stepKey="clickSaveVariable"/> -</actionGroup> -<actionGroup name="DeleteCustomVariableActionGroup"> - <amOnPage url="admin/admin/system_variable/" stepKey="goToVariableGrid" /> - <waitForPageLoad stepKey="waitForPageLoad1" /> - <click selector="{{CustomVariableSection.GridCustomVariableCode(customVariable.code)}}" stepKey="goToCustomVariableEditPage" /> - <waitForPageLoad stepKey="waitForPageLoad2" /> - <waitForElementVisible selector="{{CustomVariableSection.delete}}" stepKey="waitForDeleteBtn" /> - <click selector="{{CustomVariableSection.delete}}" stepKey="deleteCustomVariable" /> - <waitForText userInput="Are you sure you want to do this?" stepKey="waitForText" /> - <click selector="{{CustomVariableSection.confirmDelete}}" stepKey="confirmDelete" /> - <waitForPageLoad stepKey="waitForPageLoad3" /> -</actionGroup> -</actionGroups> diff --git a/app/code/Magento/Variable/Test/Mftf/Page/AdminNewVariablePage.xml b/app/code/Magento/Variable/Test/Mftf/Page/AdminNewVariablePage.xml index 6d09424e44d2a..bc5dff0feefa4 100644 --- a/app/code/Magento/Variable/Test/Mftf/Page/AdminNewVariablePage.xml +++ b/app/code/Magento/Variable/Test/Mftf/Page/AdminNewVariablePage.xml @@ -9,6 +9,6 @@ <pages xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/PageObject.xsd"> <page name="AdminNewVariablePage" url="/admin/system_variable/new/" area="admin" module="Magento_Variable"> - <section name="AdminNewVariableSection"/> + <section name="AdminMessagesSection"/> </page> </pages> diff --git a/app/code/Magento/Variable/Test/Mftf/Page/AdminVariablesPage.xml b/app/code/Magento/Variable/Test/Mftf/Page/AdminVariablesPage.xml index ceb53072b7cff..b65c8c99b1b89 100644 --- a/app/code/Magento/Variable/Test/Mftf/Page/AdminVariablesPage.xml +++ b/app/code/Magento/Variable/Test/Mftf/Page/AdminVariablesPage.xml @@ -9,7 +9,7 @@ <pages xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/PageObject.xsd"> <page name="AdminVariablesPage" url="/admin/system_variable/index/" area="admin" module="Magento_Variable"> - <section name="AdminVariableMessagesSection"/> + <section name="AdminMessagesSection"/> <section name="AdminVariablesFilterSection"/> <section name="AdminVariablesGridSection"/> </page> diff --git a/app/code/Magento/Variable/Test/Mftf/Section/AdminVariableMessagesSection.xml b/app/code/Magento/Variable/Test/Mftf/Section/AdminVariableMessagesSection.xml deleted file mode 100644 index 0acebbd8be880..0000000000000 --- a/app/code/Magento/Variable/Test/Mftf/Section/AdminVariableMessagesSection.xml +++ /dev/null @@ -1,15 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> - -<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> - <section name="AdminVariableMessagesSection"> - <element name="successMessage" type="text" selector=".message-success"/> - <element name="errorMessage" type="text" selector=".message.message-error.error"/> - </section> -</sections> diff --git a/app/code/Magento/Variable/Test/Mftf/Section/AdminVariablesFilterSection.xml b/app/code/Magento/Variable/Test/Mftf/Section/AdminVariablesFilterSection.xml index 3976a5f63e1a1..8c3eb683184dc 100644 --- a/app/code/Magento/Variable/Test/Mftf/Section/AdminVariablesFilterSection.xml +++ b/app/code/Magento/Variable/Test/Mftf/Section/AdminVariablesFilterSection.xml @@ -9,8 +9,6 @@ <sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="AdminVariablesFilterSection"> - <element name="searchButton" type="button" selector="button.action-default[title='Search']"/> - <element name="resetFilterButton" type="button" selector="button.action-reset[title='Reset Filter']"/> <element name="codeFilter" type="input" selector="input.admin__control-text[name='code']"/> <element name="nameFilter" type="input" selector="input.admin__control-text[name='name']"/> </section> diff --git a/app/code/Magento/Variable/Test/Mftf/Section/AdminVariablesGridSection.xml b/app/code/Magento/Variable/Test/Mftf/Section/AdminVariablesGridSection.xml index be91edf59d9c9..0a58b92839659 100644 --- a/app/code/Magento/Variable/Test/Mftf/Section/AdminVariablesGridSection.xml +++ b/app/code/Magento/Variable/Test/Mftf/Section/AdminVariablesGridSection.xml @@ -10,6 +10,5 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="AdminVariablesGridSection"> <element name="variablesGrid" type="text" selector="table[data-role='grid']"/> - <element name="rowByValue" type="text" selector="//td[text()[contains(.,'{{var}}')]]" parameterized="true" timeout="30"/> </section> </sections> diff --git a/app/code/Magento/Variable/Test/Mftf/Test/CreateCustomVariableEntityTest.xml b/app/code/Magento/Variable/Test/Mftf/Test/CreateCustomVariableEntityTest.xml index 41bbff38e6678..fb6328b6a3059 100644 --- a/app/code/Magento/Variable/Test/Mftf/Test/CreateCustomVariableEntityTest.xml +++ b/app/code/Magento/Variable/Test/Mftf/Test/CreateCustomVariableEntityTest.xml @@ -21,16 +21,23 @@ <before> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> </before> - <actionGroup ref="CreateCustomVariableActionGroup" stepKey="createCustomVariable"/> - <waitForPageLoad stepKey="waitForPageLoad"/> - <actionGroup ref="AdminAssertSuccessMessageActionGroup" stepKey="seeSuccessMessage"/> - <actionGroup ref="FilterVariablesGridActionGroup" stepKey="filterVariablesGridByNewVariableCode" > + <actionGroup ref="AdminCreateCustomVariableActionGroup" stepKey="createCustomVariable"/> + <actionGroup ref="AssertMessageActionGroup" stepKey="seeSuccessMessage"> + <argument name="message" value="You saved the custom variable."/> + </actionGroup> + <actionGroup ref="AdminFilterGridActionGroup" stepKey="filterVariablesGridByNewVariableCode" > <argument name="field" value="{{AdminVariablesFilterSection.codeFilter}}"/> <argument name="value" value="{{customVariable.code}}"/> </actionGroup> - <actionGroup ref="AdminSeeVariableInGridActionGroup" stepKey="seeNewVariableInGrid"/> + <actionGroup ref="AdminFilterGridActionGroup" stepKey="filterVariablesGridByNewVariableName" > + <argument name="field" value="{{AdminVariablesFilterSection.nameFilter}}"/> + <argument name="value" value="{{customVariable.name}}"/> + </actionGroup> + <actionGroup ref="AssertValueInGridActionGroup" stepKey="seeNewVariableInGrid"> + <argument name="value" value="{{customVariable.code}}"/> + </actionGroup> <after> - <actionGroup ref="ResetFilterVariablesGridActionGroup" stepKey="resetVariablesGrid"/> + <actionGroup ref="AdminResetFilterActionGroup" stepKey="resetVariablesGrid"/> <actionGroup ref="logout" stepKey="logout"/> </after> </test> diff --git a/dev/tests/functional/tests/app/Magento/Variable/Test/TestCase/CreateCustomVariableEntityTest.xml b/dev/tests/functional/tests/app/Magento/Variable/Test/TestCase/CreateCustomVariableEntityTest.xml index 9f3fb647575e0..644055052658e 100644 --- a/dev/tests/functional/tests/app/Magento/Variable/Test/TestCase/CreateCustomVariableEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Variable/Test/TestCase/CreateCustomVariableEntityTest.xml @@ -8,12 +8,11 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Variable\Test\TestCase\CreateCustomVariableEntityTest" summary="Create Custom Variable" ticketId="MAGETWO-23293"> <variation name="CreateCustomVariableEntityTestVariation1"> - <data name="tag" xsi:type="string">test_type:extended_acceptance_test</data> + <data name="tag" xsi:type="string">test_type:extended_acceptance_test, mftf_migrated:yes</data> <data name="customVariable/data/code" xsi:type="string">variableCode%isolation%</data> <data name="customVariable/data/name" xsi:type="string">variableName%isolation%</data> <data name="customVariable/data/html_value" xsi:type="string"><h1>variableName%isolation%</h1></data> <data name="customVariable/data/plain_value" xsi:type="string"><p>variablePlainText%isolation%</p></data> - <data name="tag" xsi:type="string">mftf_migrated:yes</data> <constraint name="Magento\Variable\Test\Constraint\AssertCustomVariableSuccessSaveMessage" /> <constraint name="Magento\Variable\Test\Constraint\AssertCustomVariableInGrid" /> <constraint name="Magento\Variable\Test\Constraint\AssertCustomVariableForm" /> From 2949b0169fc44178f3d4cda03ad4b93f015c81fc Mon Sep 17 00:00:00 2001 From: Anahit Martirosyan <anahit_martirosyan@epam.com> Date: Thu, 4 Apr 2019 16:04:53 +0400 Subject: [PATCH 268/773] MAGETWO-98818: [Magento Cloud] Tier price was not set as a discount on the original price - Added automated test script --- .../Mftf/ActionGroup/AdminProductActionGroup.xml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductActionGroup.xml index da570f9ed99b0..c75d8e1d139bc 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductActionGroup.xml @@ -472,4 +472,17 @@ <click selector="{{AdminAddUpSellProductsModalSection.AddSelectedProductsButton}}" stepKey="addRelatedProductSelected"/> <waitForPageLoad stepKey="waitForPageToLoad1"/> </actionGroup> + <actionGroup name="AdminProductAdvancedPricingNewCustomerGroupPrice"> + <arguments> + <argument name="qty" type="string"/> + <argument name="priceType" type="string"/> + <argument name="discount" type="string"/> + <argument name="customerGroup" type="string"/> + </arguments> + <click selector="{{AdminProductFormAdvancedPricingSection.customerGroupPriceAddButton}}" stepKey="addCustomerGroup"/> + <fillField selector="{{AdminProductFormAdvancedPricingSection.productTierPriceQtyInput(customerGroup)}}" userInput="{{qty}}" stepKey="fillProductTierPriceQtyInput1"/> + <selectOption selector="{{AdminProductFormAdvancedPricingSection.productTierPriceValueTypeSelect(customerGroup)}}" userInput="{{priceType}}" stepKey="selectProductTierPriceValueType1"/> + <fillField selector="{{AdminProductFormAdvancedPricingSection.productTierPricePercentageValuePriceInput(customerGroup)}}" userInput="{{discount}}" stepKey="selectProductTierPricePriceInput"/> + <click selector="{{AdminProductFormAdvancedPricingSection.doneButton}}" stepKey="clickDoneButton1"/> + </actionGroup> </actionGroups> From fe88f29623acb6f58453ff19fc9fc2b8f812e6ae Mon Sep 17 00:00:00 2001 From: eduard13 <e.chitoraga@atwix.com> Date: Wed, 17 Apr 2019 18:30:20 +0300 Subject: [PATCH 269/773] Refactoring the Action Groups. Minor fixes --- .../AdminClickMainButtonActionGroup.xml | 19 +++++++++++++++++++ ...ml => AdminResetGridFilterActionGroup.xml} | 2 +- ... => AssertValueInAdminGridActionGroup.xml} | 2 +- .../Mftf/Section/AdminGridTableSection.xml | 2 +- ...dminFillFormCustomVariableActionGroup.xml} | 6 +----- ...nNavigateToNewVariablePageActionGroup.xml} | 2 +- ...AdminNavigateToVariablePageActionGroup.xml | 17 +++++++++++++++++ ...avigateToVariablesGridPageActionGroup.xml} | 2 +- .../Test/CreateCustomVariableEntityTest.xml | 16 ++++++++++------ 9 files changed, 52 insertions(+), 16 deletions(-) create mode 100644 app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminClickMainButtonActionGroup.xml rename app/code/Magento/Backend/Test/Mftf/ActionGroup/{AdminResetFilterActionGroup.xml => AdminResetGridFilterActionGroup.xml} (90%) rename app/code/Magento/Backend/Test/Mftf/ActionGroup/{AssertValueInGridActionGroup.xml => AssertValueInAdminGridActionGroup.xml} (90%) rename app/code/Magento/Variable/Test/Mftf/ActionGroup/{AdminCreateCustomVariableActionGroup.xml => AdminFillFormCustomVariableActionGroup.xml} (71%) rename app/code/Magento/Variable/Test/Mftf/ActionGroup/{NavigateToNewVariablePageActionGroup.xml => AdminNavigateToNewVariablePageActionGroup.xml} (87%) create mode 100644 app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminNavigateToVariablePageActionGroup.xml rename app/code/Magento/Variable/Test/Mftf/ActionGroup/{NavigateToVariablesPageActionGroup.xml => AdminNavigateToVariablesGridPageActionGroup.xml} (87%) diff --git a/app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminClickMainButtonActionGroup.xml b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminClickMainButtonActionGroup.xml new file mode 100644 index 0000000000000..6eef596957458 --- /dev/null +++ b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminClickMainButtonActionGroup.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminClickMainButtonActionGroup"> + <arguments> + <argument name="button" type="string" /> + </arguments> + <waitForElementVisible selector="{{button}}" stepKey="waitForButton"/> + <click selector="{{button}}" stepKey="clickButton"/> + <waitForPageLoad stepKey="waitForPageLoad"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminResetFilterActionGroup.xml b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminResetGridFilterActionGroup.xml similarity index 90% rename from app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminResetFilterActionGroup.xml rename to app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminResetGridFilterActionGroup.xml index 0b778cae0be50..7e22309493be8 100644 --- a/app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminResetFilterActionGroup.xml +++ b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminResetGridFilterActionGroup.xml @@ -8,7 +8,7 @@ <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="AdminResetFilterActionGroup"> + <actionGroup name="AdminResetGridFilterActionGroup"> <arguments> <argument name="selector" type="string" defaultValue="{{AdminSecondaryGridSection.resetFilters}}"/> </arguments> diff --git a/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertValueInGridActionGroup.xml b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertValueInAdminGridActionGroup.xml similarity index 90% rename from app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertValueInGridActionGroup.xml rename to app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertValueInAdminGridActionGroup.xml index 20efab26455f2..f3eec4446ae72 100644 --- a/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertValueInGridActionGroup.xml +++ b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertValueInAdminGridActionGroup.xml @@ -7,7 +7,7 @@ --> <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="AssertValueInGridActionGroup"> + <actionGroup name="AssertValueInAdminGridActionGroup"> <arguments> <argument name="value" type="string" /> </arguments> diff --git a/app/code/Magento/Backend/Test/Mftf/Section/AdminGridTableSection.xml b/app/code/Magento/Backend/Test/Mftf/Section/AdminGridTableSection.xml index bb3cf57e4d6ef..080f598480dcd 100644 --- a/app/code/Magento/Backend/Test/Mftf/Section/AdminGridTableSection.xml +++ b/app/code/Magento/Backend/Test/Mftf/Section/AdminGridTableSection.xml @@ -10,6 +10,6 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="AdminGridTableSection"> <element name="row" type="text" selector="table.data-grid tbody tr[data-role=row]:nth-of-type({{row}})" parameterized="true"/> - <element name="rowByValue" type="text" selector="//tr[@data-role='row'] //td[contains(., '{{var}}')]" parameterized="true" timeout="30"/> + <element name="rowByValue" type="text" selector="//table[@class='data-grid']//tr[@data-role='row'] //td[contains(., '{{var}}')]" parameterized="true" timeout="30"/> </section> </sections> diff --git a/app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminCreateCustomVariableActionGroup.xml b/app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminFillFormCustomVariableActionGroup.xml similarity index 71% rename from app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminCreateCustomVariableActionGroup.xml rename to app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminFillFormCustomVariableActionGroup.xml index 21d98617d9a4e..4dabe6f0ae192 100644 --- a/app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminCreateCustomVariableActionGroup.xml +++ b/app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminFillFormCustomVariableActionGroup.xml @@ -7,14 +7,10 @@ --> <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="AdminCreateCustomVariableActionGroup"> - <amOnPage url="admin/admin/system_variable/new/" stepKey="goToNewCustomVariablePage"/> - <waitForPageLoad stepKey="waitForPageLoad"/> + <actionGroup name="AdminFillFormCustomVariableActionGroup"> <fillField selector="{{CustomVariableSection.variableCode}}" userInput="{{customVariable.code}}" stepKey="fillVariableCode"/> <fillField selector="{{CustomVariableSection.variableName}}" userInput="{{customVariable.name}}" stepKey="fillVariableName"/> <fillField selector="{{CustomVariableSection.variableHTML}}" userInput="{{customVariable.html}}" stepKey="fillVariableHtml"/> <fillField selector="{{CustomVariableSection.variablePlain}}" userInput="{{customVariable.plain}}" stepKey="fillVariablePlain"/> - <click selector="{{AdminMainActionsSection.save}}" stepKey="clickSaveVariable"/> - <waitForPageLoad stepKey="waitForPageLoad2"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/Variable/Test/Mftf/ActionGroup/NavigateToNewVariablePageActionGroup.xml b/app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminNavigateToNewVariablePageActionGroup.xml similarity index 87% rename from app/code/Magento/Variable/Test/Mftf/ActionGroup/NavigateToNewVariablePageActionGroup.xml rename to app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminNavigateToNewVariablePageActionGroup.xml index ee80bcc861317..060a2a608b125 100644 --- a/app/code/Magento/Variable/Test/Mftf/ActionGroup/NavigateToNewVariablePageActionGroup.xml +++ b/app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminNavigateToNewVariablePageActionGroup.xml @@ -8,7 +8,7 @@ <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="NavigateToNewVariablePageActionGroup"> + <actionGroup name="AdminNavigateToNewVariablePageActionGroup"> <amOnPage url="{{AdminNewVariablePage.url}}" stepKey="openNewVariablePage"/> <waitForPageLoad stepKey="waitForPageLoad"/> </actionGroup> diff --git a/app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminNavigateToVariablePageActionGroup.xml b/app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminNavigateToVariablePageActionGroup.xml new file mode 100644 index 0000000000000..4904b45a47e48 --- /dev/null +++ b/app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminNavigateToVariablePageActionGroup.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminNavigateToVariablePageActionGroup"> + <arguments> + <argument name="code" type="string"/> + </arguments> + <click selector="{{CustomVariableSection.GridCustomVariableCode(code)}}" stepKey="goToCustomVariableEditPage"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Variable/Test/Mftf/ActionGroup/NavigateToVariablesPageActionGroup.xml b/app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminNavigateToVariablesGridPageActionGroup.xml similarity index 87% rename from app/code/Magento/Variable/Test/Mftf/ActionGroup/NavigateToVariablesPageActionGroup.xml rename to app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminNavigateToVariablesGridPageActionGroup.xml index f4c00b7b60391..cc57f6b83d49f 100644 --- a/app/code/Magento/Variable/Test/Mftf/ActionGroup/NavigateToVariablesPageActionGroup.xml +++ b/app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminNavigateToVariablesGridPageActionGroup.xml @@ -8,7 +8,7 @@ <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="NavigateToVariablesPage"> + <actionGroup name="AdminNavigateToVariablesGridPageActionGroup"> <amOnPage url="{{AdminVariablesPage.url}}" stepKey="openVariablesGridPage"/> <waitForPageLoad stepKey="waitForPageLoad"/> </actionGroup> diff --git a/app/code/Magento/Variable/Test/Mftf/Test/CreateCustomVariableEntityTest.xml b/app/code/Magento/Variable/Test/Mftf/Test/CreateCustomVariableEntityTest.xml index fb6328b6a3059..cb843f64d341a 100644 --- a/app/code/Magento/Variable/Test/Mftf/Test/CreateCustomVariableEntityTest.xml +++ b/app/code/Magento/Variable/Test/Mftf/Test/CreateCustomVariableEntityTest.xml @@ -21,7 +21,15 @@ <before> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> </before> - <actionGroup ref="AdminCreateCustomVariableActionGroup" stepKey="createCustomVariable"/> + <after> + <actionGroup ref="AdminResetGridFilterActionGroup" stepKey="resetVariablesGrid"/> + <actionGroup ref="logout" stepKey="logout"/> + </after> + <actionGroup ref="AdminNavigateToNewVariablePageActionGroup" stepKey="goToNewVariableAdminPage"/> + <actionGroup ref="AdminFillFormCustomVariableActionGroup" stepKey="fillInCustomVariableData"/> + <actionGroup ref="AdminClickMainButtonActionGroup" stepKey="clickSaveCustomVariable"> + <argument name="button" value="{{AdminMainActionsSection.save}}"/> + </actionGroup> <actionGroup ref="AssertMessageActionGroup" stepKey="seeSuccessMessage"> <argument name="message" value="You saved the custom variable."/> </actionGroup> @@ -33,12 +41,8 @@ <argument name="field" value="{{AdminVariablesFilterSection.nameFilter}}"/> <argument name="value" value="{{customVariable.name}}"/> </actionGroup> - <actionGroup ref="AssertValueInGridActionGroup" stepKey="seeNewVariableInGrid"> + <actionGroup ref="AssertValueInAdminGridActionGroup" stepKey="seeNewVariableInGrid"> <argument name="value" value="{{customVariable.code}}"/> </actionGroup> - <after> - <actionGroup ref="AdminResetFilterActionGroup" stepKey="resetVariablesGrid"/> - <actionGroup ref="logout" stepKey="logout"/> - </after> </test> </tests> From a4923d86608b964f1297cd6373b9c9b65ca05f17 Mon Sep 17 00:00:00 2001 From: Joan He <johe@magento.com> Date: Wed, 17 Apr 2019 14:11:27 -0500 Subject: [PATCH 270/773] MC-15575: Correct filter output --- app/code/Magento/Email/Model/Template/Filter.php | 2 +- .../testsuite/Magento/Email/Model/Template/FilterTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Email/Model/Template/Filter.php b/app/code/Magento/Email/Model/Template/Filter.php index 1d8218f90a0b2..3bb849931c7f8 100644 --- a/app/code/Magento/Email/Model/Template/Filter.php +++ b/app/code/Magento/Email/Model/Template/Filter.php @@ -849,7 +849,7 @@ public function cssDirective($construction) return $css; } else { // Return CSS comment for debugging purposes - return '/* ' . sprintf(__('Contents of %s could not be loaded or is empty'), $file) . ' */'; + return '/* ' . __('Contents of the specified CSS file could not be loaded or is empty') . ' */'; } } 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 dd55dcc8b47c7..7e16115ed2fef 100644 --- a/dev/tests/integration/testsuite/Magento/Email/Model/Template/FilterTest.php +++ b/dev/tests/integration/testsuite/Magento/Email/Model/Template/FilterTest.php @@ -267,7 +267,7 @@ public function cssDirectiveDataProvider() 'Empty or missing file' => [ TemplateTypesInterface::TYPE_HTML, 'file="css/non-existent-file.css"', - '/* Contents of css/non-existent-file.css could not be loaded or is empty */' + '/* Contents of the specified CSS file could not be loaded or is empty */' ], 'File with compilation error results in error message' => [ TemplateTypesInterface::TYPE_HTML, From cd722a566288f764e4aeef241bfb43ca7cf50169 Mon Sep 17 00:00:00 2001 From: Viktor Sevch <svitja@ukr.net> Date: Thu, 18 Apr 2019 10:24:03 +0300 Subject: [PATCH 271/773] MC-11050: Invalid action behavior --- .../Block/Adminhtml/Template/Preview.php | 5 +- .../Adminhtml/Email/Template/Popup.php | 54 +++++++++++++ .../Adminhtml/Email/Template/Preview.php | 11 ++- .../ActionGroup/EmailTemplateActionGroup.xml | 77 ++++++++++++++----- .../Test/Mftf/Data/EmailTemplateData.xml | 2 + .../Mftf/Page/AdminEmailTemplateEditPage.xml | 14 ++++ ...ge.xml => AdminEmailTemplateIndexPage.xml} | 4 +- .../Page/AdminEmailTemplatePreviewPage.xml | 14 ++++ .../Section/AdminEmailTemplateEditSection.xml | 20 +++++ .../AdminEmailTemplateIndexSection.xml | 15 ++++ .../AdminEmailTemplatePreviewSection.xml | 14 ++++ .../Mftf/Section/EmailTemplateSection.xml | 30 -------- .../Test/AdminEmailTemplatePreviewTest.xml | 40 ++++++++++ .../Block/Adminhtml/Template/PreviewTest.php | 10 --- .../Adminhtml/Email/Template/PreviewTest.php | 6 +- .../layout/adminhtml_email_template_popup.xml | 14 ++++ .../adminhtml_email_template_preview.xml | 9 ++- .../templates/preview/iframeswitcher.phtml | 19 +++++ .../adminhtml/templates/template/edit.phtml | 2 +- 19 files changed, 286 insertions(+), 74 deletions(-) create mode 100644 app/code/Magento/Email/Controller/Adminhtml/Email/Template/Popup.php create mode 100644 app/code/Magento/Email/Test/Mftf/Page/AdminEmailTemplateEditPage.xml rename app/code/Magento/Email/Test/Mftf/Page/{AdminEmailTemplatePage.xml => AdminEmailTemplateIndexPage.xml} (65%) create mode 100644 app/code/Magento/Email/Test/Mftf/Page/AdminEmailTemplatePreviewPage.xml create mode 100644 app/code/Magento/Email/Test/Mftf/Section/AdminEmailTemplateEditSection.xml create mode 100644 app/code/Magento/Email/Test/Mftf/Section/AdminEmailTemplateIndexSection.xml create mode 100644 app/code/Magento/Email/Test/Mftf/Section/AdminEmailTemplatePreviewSection.xml delete mode 100644 app/code/Magento/Email/Test/Mftf/Section/EmailTemplateSection.xml create mode 100644 app/code/Magento/Email/Test/Mftf/Test/AdminEmailTemplatePreviewTest.xml create mode 100644 app/code/Magento/Email/view/adminhtml/layout/adminhtml_email_template_popup.xml create mode 100644 app/code/Magento/Email/view/adminhtml/templates/preview/iframeswitcher.phtml diff --git a/app/code/Magento/Email/Block/Adminhtml/Template/Preview.php b/app/code/Magento/Email/Block/Adminhtml/Template/Preview.php index 5f22a36510c4e..acc367de742dd 100644 --- a/app/code/Magento/Email/Block/Adminhtml/Template/Preview.php +++ b/app/code/Magento/Email/Block/Adminhtml/Template/Preview.php @@ -12,6 +12,8 @@ namespace Magento\Email\Block\Adminhtml\Template; /** + * Email template preview block. + * * @api * @since 100.0.2 */ @@ -68,8 +70,6 @@ protected function _toHtml() $template->setTemplateStyles($this->getRequest()->getParam('styles')); } - $template->setTemplateText($this->_maliciousCode->filter($template->getTemplateText())); - \Magento\Framework\Profiler::start($this->profilerName); $template->emulateDesign($storeId); @@ -78,6 +78,7 @@ protected function _toHtml() [$template, 'getProcessedTemplate'] ); $template->revertDesign(); + $templateProcessed = $this->_maliciousCode->filter($templateProcessed); if ($template->isPlain()) { $templateProcessed = "<pre>" . htmlspecialchars($templateProcessed) . "</pre>"; diff --git a/app/code/Magento/Email/Controller/Adminhtml/Email/Template/Popup.php b/app/code/Magento/Email/Controller/Adminhtml/Email/Template/Popup.php new file mode 100644 index 0000000000000..8e619a746a2b8 --- /dev/null +++ b/app/code/Magento/Email/Controller/Adminhtml/Email/Template/Popup.php @@ -0,0 +1,54 @@ +<?php +/** + * + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Email\Controller\Adminhtml\Email\Template; + +use Magento\Framework\App\Action\HttpGetActionInterface; + +/** + * Rendering popup email template. + */ +class Popup extends \Magento\Backend\App\Action implements HttpGetActionInterface +{ + /** + * @var \Magento\Framework\View\Result\PageFactory + */ + private $resultPageFactory; + + /** + * @param \Magento\Backend\App\Action\Context $context + * @param \Magento\Framework\View\Result\PageFactory $resultPageFactory + */ + public function __construct( + \Magento\Backend\App\Action\Context $context, + \Magento\Framework\View\Result\PageFactory $resultPageFactory + ) { + parent::__construct($context); + $this->resultPageFactory = $resultPageFactory; + } + + /** + * Load the page. + * + * Load the page defined in view/adminhtml/layout/adminhtml_email_template_popup.xml + * + * @return \Magento\Framework\View\Result\Page + */ + public function execute() + { + return $this->resultPageFactory->create(); + } + + /** + * @inheritdoc + */ + protected function _isAllowed() + { + return $this->_authorization->isAllowed('Magento_Email::template'); + } +} diff --git a/app/code/Magento/Email/Controller/Adminhtml/Email/Template/Preview.php b/app/code/Magento/Email/Controller/Adminhtml/Email/Template/Preview.php index 404f97c937167..c1a8eec07e461 100644 --- a/app/code/Magento/Email/Controller/Adminhtml/Email/Template/Preview.php +++ b/app/code/Magento/Email/Controller/Adminhtml/Email/Template/Preview.php @@ -6,10 +6,15 @@ */ namespace Magento\Email\Controller\Adminhtml\Email\Template; -class Preview extends \Magento\Email\Controller\Adminhtml\Email\Template +use Magento\Framework\App\Action\HttpGetActionInterface; + +/** + * Rendering email template preview. + */ +class Preview extends \Magento\Email\Controller\Adminhtml\Email\Template implements HttpGetActionInterface { /** - * Preview transactional email action + * Preview transactional email action. * * @return void */ @@ -19,7 +24,7 @@ public function execute() $this->_view->loadLayout(); $this->_view->getPage()->getConfig()->getTitle()->prepend(__('Email Preview')); $this->_view->renderLayout(); - $this->getResponse()->setHeader('Content-Security-Policy', "script-src 'none'"); + $this->getResponse()->setHeader('Content-Security-Policy', "script-src 'self'"); } catch (\Exception $e) { $this->messageManager->addErrorMessage( __('An error occurred. The email template can not be opened for preview.') diff --git a/app/code/Magento/Email/Test/Mftf/ActionGroup/EmailTemplateActionGroup.xml b/app/code/Magento/Email/Test/Mftf/ActionGroup/EmailTemplateActionGroup.xml index d299acd28fc1c..4285f6dbdbb08 100644 --- a/app/code/Magento/Email/Test/Mftf/ActionGroup/EmailTemplateActionGroup.xml +++ b/app/code/Magento/Email/Test/Mftf/ActionGroup/EmailTemplateActionGroup.xml @@ -11,29 +11,70 @@ <!--Create New Template --> <actionGroup name="CreateNewTemplate"> + <arguments> + <argument name="template" defaultValue="EmailTemplate"/> + </arguments> + + <!--Go to Marketing> Email Templates--> + <amOnPage url="{{AdminEmailTemplateIndexPage.url}}" stepKey="navigateToEmailTemplatePage"/> <!--Click "Add New Template" button--> - <click stepKey="clickAddNewTemplateButton" selector="{{EmailTemplatesSection.addNewTemplateButton}}"/> - <waitForPageLoad stepKey="waitForNewEmailTemplatesPageLoaded"/> + <click selector="{{AdminMainActionsSection.add}}" stepKey="clickAddNewTemplateButton"/> <!--Select value for "Template" drop-down menu in "Load default template" tab--> - <selectOption selector="{{EmailTemplatesSection.templateDropDown}}" stepKey="selectValueFromTemplateDropDown" userInput="Registry Update"/> - + <selectOption selector="{{AdminEmailTemplateEditSection.templateDropDown}}" userInput="Registry Update" stepKey="selectValueFromTemplateDropDown"/> <!--Fill in required fields in "Template Information" tab and click "Save Template" button--> - <click stepKey="clickLoadTemplateButton" selector="{{EmailTemplatesSection.loadTemplateButton}}" after="selectValueFromTemplateDropDown"/> - <fillField stepKey="fillTemplateNameField" selector="{{EmailTemplatesSection.templateNameField}}" userInput="{{EmailTemplate.templateName}}" after="clickLoadTemplateButton"/> - <waitForLoadingMaskToDisappear stepKey="wait1"/> - <click stepKey="clickSaveTemplateButton" selector="{{EmailTemplatesSection.saveTemplateButton}}"/> - <waitForPageLoad stepKey="waitForNewTemplateCreated"/> + <click selector="{{AdminEmailTemplateEditSection.loadTemplateButton}}" stepKey="clickLoadTemplateButton"/> + <fillField selector="{{AdminEmailTemplateEditSection.templateCode}}" userInput="{{EmailTemplate.templateName}}" stepKey="fillTemplateNameField"/> + <click selector="{{AdminMainActionsSection.save}}" stepKey="clickSaveTemplateButton"/> + <waitForElementVisible selector="{{AdminMessagesSection.successMessage}}" stepKey="waitForSuccessMessage"/> + <see selector="{{AdminMessagesSection.successMessage}}" userInput="You saved the email template." stepKey="seeSuccessMessage"/> + </actionGroup> + + <!--Create New Custom Template --> + <actionGroup name="CreateCustomTemplate" extends="CreateNewTemplate"> + <remove keyForRemoval="selectValueFromTemplateDropDown"/> + <remove keyForRemoval="clickLoadTemplateButton"/> + + <fillField selector="{{AdminEmailTemplateEditSection.templateSubject}}" userInput="{{template.templateSubject}}" after="fillTemplateNameField" stepKey="fillTemplateSubject"/> + <fillField selector="{{AdminEmailTemplateEditSection.templateText}}" userInput="{{template.templateText}}" after="fillTemplateSubject" stepKey="fillTemplateText"/> + </actionGroup> + + <!-- Find and Open Email Template --> + <actionGroup name="FindAndOpenEmailTemplate"> + <arguments> + <argument name="template" defaultValue="EmailTemplate"/> + </arguments> + + <amOnPage url="{{AdminEmailTemplateIndexPage.url}}" stepKey="navigateEmailTemplatePage" /> + <click selector="{{AdminDataGridHeaderSection.clearFilters}}" stepKey="clearFilters"/> + <fillField selector="{{AdminEmailTemplateIndexSection.searchTemplateField}}" userInput="{{template.templateName}}" stepKey="findCreatedTemplate"/> + <click selector="{{AdminDataGridHeaderSection.applyFilters}}" stepKey="clickSearch"/> + <waitForElementVisible selector="{{AdminEmailTemplateIndexSection.templateRowByName(template.templateName)}}" stepKey="waitForTemplatesAppeared"/> + <click selector="{{AdminEmailTemplateIndexSection.templateRowByName(template.templateName)}}" stepKey="clickToOpenTemplate"/> + <waitForElementVisible selector="{{AdminEmailTemplateEditSection.templateCode}}" stepKey="waitForTemplateNameisible"/> + <seeInField selector="{{AdminEmailTemplateEditSection.templateCode}}" userInput="{{template.templateName}}" stepKey="checkTemplateName"/> + </actionGroup> + + <actionGroup name="DeleteEmailTemplate" extends="FindAndOpenEmailTemplate"> + <click selector="{{AdminEmailTemplateEditSection.deleteTemplateButton}}" after="checkTemplateName" stepKey="deleteTemplate"/> + <acceptPopup after="deleteTemplate" stepKey="acceptPopup"/> + <waitForElementVisible selector="{{AdminMessagesSection.successMessage}}" after="acceptPopup" stepKey="waitForSuccessMessage"/> + <see selector="{{AdminMessagesSection.successMessage}}" userInput="You deleted the email template." after="waitForSuccessMessage" stepKey="seeSuccessfulMessage"/> </actionGroup> - <!--Delete created Template--> - <actionGroup name="DeleteCreatedTemplate"> - <switchToPreviousTab stepKey="switchToPreviousTab"/> - <seeInCurrentUrl stepKey="seeCreatedTemplateUrl" url="email_template/edit/id"/> - <click stepKey="clickDeleteTemplateButton" selector="{{EmailTemplatesSection.deleteTemplateButton}}"/> - <acceptPopup stepKey="acceptDeletingTemplatePopUp"/> - <see stepKey="SeeSuccessfulMessage" userInput="You deleted the email template."/> - <click stepKey="clickResetFilterButton" selector="{{EmailTemplatesSection.resetFilterButton}}"/> - <waitForElementNotVisible selector="{{MarketingEmailTemplateSection.clearSearchTemplate(EmailTemplate.templateName)}}" stepKey="waitForSearchFieldCleared"/> + <actionGroup name="PreviewEmailTemplate" extends="FindAndOpenEmailTemplate"> + <click selector="{{AdminEmailTemplateEditSection.previewTemplateButton}}" after="checkTemplateName" stepKey="clickPreviewTemplate"/> + <switchToNextTab after="clickPreviewTemplate" stepKey="switchToNewOpenedTab"/> + <seeInCurrentUrl url="{{AdminEmailTemplatePreviewPage.url}}" after="switchToNewOpenedTab" stepKey="seeCurrentUrl"/> + <seeElement selector="{{AdminEmailTemplatePreviewSection.iframe}}" after="seeCurrentUrl" stepKey="seeIframeOnPage"/> + <switchToIFrame userInput="preview_iframe" after="seeIframeOnPage" stepKey="switchToIframe"/> + <waitForPageLoad after="switchToIframe" stepKey="waitForPageLoaded"/> </actionGroup> + <actionGroup name="AssertEmailTemplateContent"> + <arguments> + <argument name="expectedContent" type="string" defaultValue="{{EmailTemplate.templateText}}"/> + </arguments> + + <see userInput="{{expectedContent}}" stepKey="checkTemplateContainText"/> + </actionGroup> </actionGroups> diff --git a/app/code/Magento/Email/Test/Mftf/Data/EmailTemplateData.xml b/app/code/Magento/Email/Test/Mftf/Data/EmailTemplateData.xml index 04e597244833a..7f28e2241761b 100644 --- a/app/code/Magento/Email/Test/Mftf/Data/EmailTemplateData.xml +++ b/app/code/Magento/Email/Test/Mftf/Data/EmailTemplateData.xml @@ -10,5 +10,7 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd"> <entity name="EmailTemplate" type="template"> <data key="templateName" unique="suffix">Template</data> + <data key="templateSubject" unique="suffix">Template Subject_</data> + <data key="templateText" unique="suffix">Template Text_</data> </entity> </entities> diff --git a/app/code/Magento/Email/Test/Mftf/Page/AdminEmailTemplateEditPage.xml b/app/code/Magento/Email/Test/Mftf/Page/AdminEmailTemplateEditPage.xml new file mode 100644 index 0000000000000..f369e84abf374 --- /dev/null +++ b/app/code/Magento/Email/Test/Mftf/Page/AdminEmailTemplateEditPage.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<pages xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:/Page/etc/PageObject.xsd"> + <page name="AdminEmailTemplateEditPage" url="/admin/email_template/edit/id/{{templateId}}/" area="admin" module="Magento_Email" parameterized="true"> + <section name="AdminEmailTemplateEditSection"/> + </page> +</pages> diff --git a/app/code/Magento/Email/Test/Mftf/Page/AdminEmailTemplatePage.xml b/app/code/Magento/Email/Test/Mftf/Page/AdminEmailTemplateIndexPage.xml similarity index 65% rename from app/code/Magento/Email/Test/Mftf/Page/AdminEmailTemplatePage.xml rename to app/code/Magento/Email/Test/Mftf/Page/AdminEmailTemplateIndexPage.xml index 9636986dda8fa..c4ba7aa006203 100644 --- a/app/code/Magento/Email/Test/Mftf/Page/AdminEmailTemplatePage.xml +++ b/app/code/Magento/Email/Test/Mftf/Page/AdminEmailTemplateIndexPage.xml @@ -8,7 +8,7 @@ <pages xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:/Page/etc/PageObject.xsd"> - <page name="AdminEmailTemplatePage" url="/admin/email_template/" area="admin" module="Email"> - <section name="AdminEmailTemplatePageActionSection"/> + <page name="AdminEmailTemplateIndexPage" url="/admin/email_template/" area="admin" module="Magento_Email"> + <section name="AdminEmailTemplateIndexSection"/> </page> </pages> diff --git a/app/code/Magento/Email/Test/Mftf/Page/AdminEmailTemplatePreviewPage.xml b/app/code/Magento/Email/Test/Mftf/Page/AdminEmailTemplatePreviewPage.xml new file mode 100644 index 0000000000000..aae010be27fd8 --- /dev/null +++ b/app/code/Magento/Email/Test/Mftf/Page/AdminEmailTemplatePreviewPage.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<pages xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:/Page/etc/PageObject.xsd"> + <page name="AdminEmailTemplatePreviewPage" url="/admin/email_template/preview/" area="admin" module="Magento_Email"> + <section name="AdminEmailTemplatePreviewSection"/> + </page> +</pages> diff --git a/app/code/Magento/Email/Test/Mftf/Section/AdminEmailTemplateEditSection.xml b/app/code/Magento/Email/Test/Mftf/Section/AdminEmailTemplateEditSection.xml new file mode 100644 index 0000000000000..4dd4ac14cc040 --- /dev/null +++ b/app/code/Magento/Email/Test/Mftf/Section/AdminEmailTemplateEditSection.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="AdminEmailTemplateEditSection"> + <element name="templateCode" type="input" selector="#template_code"/> + <element name="templateSubject" type="input" selector="#template_subject"/> + <element name="templateText" type="input" selector="#template_text"/> + <element name="templateDropDown" type="select" selector="#template_select"/> + <element name="loadTemplateButton" type="button" selector="#load" timeout="30"/> + <element name="deleteTemplateButton" type="button" selector="#delete"/> + <element name="previewTemplateButton" type="button" selector="#preview" timeout="30"/> + </section> +</sections> diff --git a/app/code/Magento/Email/Test/Mftf/Section/AdminEmailTemplateIndexSection.xml b/app/code/Magento/Email/Test/Mftf/Section/AdminEmailTemplateIndexSection.xml new file mode 100644 index 0000000000000..54d5c54627047 --- /dev/null +++ b/app/code/Magento/Email/Test/Mftf/Section/AdminEmailTemplateIndexSection.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="AdminEmailTemplateIndexSection"> + <element name="searchTemplateField" type="input" selector="#systemEmailTemplateGrid_filter_code"/> + <element name="templateRowByName" type="button" selector="//*[@id='systemEmailTemplateGrid_table']//td[contains(@class, 'col-code') and normalize-space(.)='{{templateName}}']/ancestor::tr" parameterized="true"/> + </section> +</sections> diff --git a/app/code/Magento/Email/Test/Mftf/Section/AdminEmailTemplatePreviewSection.xml b/app/code/Magento/Email/Test/Mftf/Section/AdminEmailTemplatePreviewSection.xml new file mode 100644 index 0000000000000..5510800edc06e --- /dev/null +++ b/app/code/Magento/Email/Test/Mftf/Section/AdminEmailTemplatePreviewSection.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="AdminEmailTemplatePreviewSection"> + <element name="iframe" type="iframe" selector="#preview_iframe"/> + </section> +</sections> diff --git a/app/code/Magento/Email/Test/Mftf/Section/EmailTemplateSection.xml b/app/code/Magento/Email/Test/Mftf/Section/EmailTemplateSection.xml deleted file mode 100644 index 4e877bd24239e..0000000000000 --- a/app/code/Magento/Email/Test/Mftf/Section/EmailTemplateSection.xml +++ /dev/null @@ -1,30 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> - -<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> - - <section name="MarketingEmailTemplateSection"> - <element name="searchTemplateField" type="input" selector="#systemEmailTemplateGrid_filter_code"/> - <element name="searchButton" type="button" selector="//*[@title='Search' and @class='action-default scalable action-secondary']"/> - <element name="createdTemplate" type="button" selector="//*[normalize-space() ='{{arg}}']" parameterized="true"/> - <element name="clearSearchTemplate" type="input" selector="//*[@id='systemEmailTemplateGrid_filter_code' and @value='{{arg2}}']" parameterized="true"/> - </section> - - <section name="EmailTemplatesSection"> - <element name="addNewTemplateButton" type="button" selector="#add"/> - <element name="templateDropDown" type="select" selector="#template_select"/> - <element name="loadTemplateButton" type="button" selector="#load"/> - <element name="templateNameField" type="input" selector="#template_code"/> - <element name="saveTemplateButton" type="button" selector="#save"/> - <element name="previewTemplateButton" type="button" selector="#preview"/> - <element name="deleteTemplateButton" type="button" selector="#delete"/> - <element name="resetFilterButton" type="button" selector="//span[contains(text(),'Reset Filter')]"/> - </section> - -</sections> diff --git a/app/code/Magento/Email/Test/Mftf/Test/AdminEmailTemplatePreviewTest.xml b/app/code/Magento/Email/Test/Mftf/Test/AdminEmailTemplatePreviewTest.xml new file mode 100644 index 0000000000000..459e3c0f9290f --- /dev/null +++ b/app/code/Magento/Email/Test/Mftf/Test/AdminEmailTemplatePreviewTest.xml @@ -0,0 +1,40 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AdminEmailTemplatePreviewTest"> + <annotations> + <features value="Email"/> + <stories value="Create email template"/> + <title value="Check email template preview"/> + <description value="Check if email template preview works correctly"/> + <severity value="AVERAGE"/> + <testCaseId value="MC-15794"/> + <useCaseId value="MC-11050"/> + <group value="email"/> + </annotations> + + <before> + <!--Login to Admin Area--> + <actionGroup ref="LoginAsAdmin" stepKey="loginToAdminArea"/> + </before> + + <after> + <!--Delete created Template--> + <actionGroup ref="DeleteEmailTemplate" stepKey="deleteTemplate"/> + <click selector="{{AdminDataGridHeaderSection.clearFilters}}" stepKey="clearFilters"/> + <!--Logout from Admin Area--> + <actionGroup ref="logout" stepKey="logoutOfAdmin"/> + </after> + + <actionGroup ref="CreateCustomTemplate" stepKey="createTemplate"/> + <actionGroup ref="PreviewEmailTemplate" stepKey="previewTemplate"/> + <actionGroup ref="AssertEmailTemplateContent" stepKey="assertContent"/> + </test> +</tests> diff --git a/app/code/Magento/Email/Test/Unit/Block/Adminhtml/Template/PreviewTest.php b/app/code/Magento/Email/Test/Unit/Block/Adminhtml/Template/PreviewTest.php index e11d7fc4db534..b91d94edb589e 100644 --- a/app/code/Magento/Email/Test/Unit/Block/Adminhtml/Template/PreviewTest.php +++ b/app/code/Magento/Email/Test/Unit/Block/Adminhtml/Template/PreviewTest.php @@ -128,16 +128,6 @@ public function toHtmlDataProvider() { return [ ['data 1' => [ - ['type', null, ''], - ['text', null, sprintf('<javascript>%s</javascript>', self::MALICIOUS_TEXT)], - ['styles', null, ''], - ]], - ['data 2' => [ - ['type', null, ''], - ['text', null, sprintf('<iframe>%s</iframe>', self::MALICIOUS_TEXT)], - ['styles', null, ''], - ]], - ['data 3' => [ ['type', null, ''], ['text', null, self::MALICIOUS_TEXT], ['styles', null, ''], diff --git a/app/code/Magento/Email/Test/Unit/Controller/Adminhtml/Email/Template/PreviewTest.php b/app/code/Magento/Email/Test/Unit/Controller/Adminhtml/Email/Template/PreviewTest.php index 0ba717a461718..9a67bf59dd4bf 100644 --- a/app/code/Magento/Email/Test/Unit/Controller/Adminhtml/Email/Template/PreviewTest.php +++ b/app/code/Magento/Email/Test/Unit/Controller/Adminhtml/Email/Template/PreviewTest.php @@ -15,9 +15,7 @@ use Magento\Framework\View\Result\Page; /** - * Preview Test - * - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * Preview Test. */ class PreviewTest extends \PHPUnit\Framework\TestCase { @@ -122,7 +120,7 @@ public function testExecute() ->willReturnSelf(); $this->responseMock->expects($this->once()) ->method('setHeader') - ->with('Content-Security-Policy', "script-src 'none'"); + ->with('Content-Security-Policy', "script-src 'self'"); $this->assertNull($this->object->execute()); } diff --git a/app/code/Magento/Email/view/adminhtml/layout/adminhtml_email_template_popup.xml b/app/code/Magento/Email/view/adminhtml/layout/adminhtml_email_template_popup.xml new file mode 100644 index 0000000000000..d633ac8ccf9e1 --- /dev/null +++ b/app/code/Magento/Email/view/adminhtml/layout/adminhtml_email_template_popup.xml @@ -0,0 +1,14 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<layout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/layout_generic.xsd"> + <container name="root"> + <block class="Magento\Framework\View\Element\Template" name="page.block" template="Magento_Email::template/preview.phtml"> + <block class="Magento\Email\Block\Adminhtml\Template\Preview" name="content" as="content"/> + </block> + </container> +</layout> diff --git a/app/code/Magento/Email/view/adminhtml/layout/adminhtml_email_template_preview.xml b/app/code/Magento/Email/view/adminhtml/layout/adminhtml_email_template_preview.xml index b308ad7d3dfcd..97f31c618f9b7 100644 --- a/app/code/Magento/Email/view/adminhtml/layout/adminhtml_email_template_preview.xml +++ b/app/code/Magento/Email/view/adminhtml/layout/adminhtml_email_template_preview.xml @@ -6,12 +6,13 @@ */ --> <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="admin-1column" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"> - <update handle="empty" /> <body> + <attribute name="id" value="html-body"/> + <attribute name="class" value="preview-window"/> + <referenceContainer name="backend.page" remove="true"/> + <referenceContainer name="menu.wrapper" remove="true"/> <referenceContainer name="root"> - <block name="preview.page.content" class="Magento\Framework\View\Element\Template" template="Magento_Email::template/preview.phtml"> - <block class="Magento\Email\Block\Adminhtml\Template\Preview" name="content" as="content"/> - </block> + <block name="preview.page.content" class="Magento\Backend\Block\Page" template="Magento_Email::preview/iframeswitcher.phtml"/> </referenceContainer> </body> </page> diff --git a/app/code/Magento/Email/view/adminhtml/templates/preview/iframeswitcher.phtml b/app/code/Magento/Email/view/adminhtml/templates/preview/iframeswitcher.phtml new file mode 100644 index 0000000000000..4d26b59b093e2 --- /dev/null +++ b/app/code/Magento/Email/view/adminhtml/templates/preview/iframeswitcher.phtml @@ -0,0 +1,19 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +/** @var \Magento\Backend\Block\Page $block */ +?> +<div id="preview" class="cms-revision-preview"> + <iframe + name="preview_iframe" + id="preview_iframe" + frameborder="0" + title="<?= $block->escapeHtmlAttr(__('Preview')) ?>" + width="100%" + sandbox="allow-forms allow-pointer-lock" + src="<?= $block->escapeUrl($block->getUrl('*/*/popup', ['_current' => true])) ?>" + /> +</div> diff --git a/app/code/Magento/Email/view/adminhtml/templates/template/edit.phtml b/app/code/Magento/Email/view/adminhtml/templates/template/edit.phtml index 05a873f8ddd5a..d75f2922140c7 100644 --- a/app/code/Magento/Email/view/adminhtml/templates/template/edit.phtml +++ b/app/code/Magento/Email/view/adminhtml/templates/template/edit.phtml @@ -50,7 +50,7 @@ use Magento\Framework\App\TemplateTypesInterface; <?= /* @noEscape */ $block->getFormHtml() ?> </form> -<form action="<?= $block->escapeUrl($block->getPreviewUrl()) ?>" method="post" id="email_template_preview_form" target="_blank"> +<form action="<?= $block->escapeUrl($block->getPreviewUrl()) ?>" method="get" id="email_template_preview_form" target="_blank"> <?= /* @noEscape */ $block->getBlockHtml('formkey') ?> <div class="no-display"> <input type="hidden" id="preview_type" name="type" value="<?= /* @noEscape */ $block->isTextType() ? 1 : 2 ?>" /> From 3a99c068d9f17f1c46ccaab44422a6cb0ba34e93 Mon Sep 17 00:00:00 2001 From: Viktor Sevch <svitja@ukr.net> Date: Thu, 18 Apr 2019 14:56:46 +0300 Subject: [PATCH 272/773] MC-11050: Invalid action behavior --- .../Magento/Email/Controller/Adminhtml/Email/Template/Popup.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/code/Magento/Email/Controller/Adminhtml/Email/Template/Popup.php b/app/code/Magento/Email/Controller/Adminhtml/Email/Template/Popup.php index 8e619a746a2b8..31d172935da7f 100644 --- a/app/code/Magento/Email/Controller/Adminhtml/Email/Template/Popup.php +++ b/app/code/Magento/Email/Controller/Adminhtml/Email/Template/Popup.php @@ -1,6 +1,5 @@ <?php /** - * * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ From 3e9c2c36f2e9aed37dc87c2fa6a51979629c96d1 Mon Sep 17 00:00:00 2001 From: Joan He <johe@magento.com> Date: Thu, 18 Apr 2019 11:42:43 -0500 Subject: [PATCH 273/773] MC-15575: Correct filter output - fix static test failures --- app/code/Magento/Email/Model/Template/Filter.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app/code/Magento/Email/Model/Template/Filter.php b/app/code/Magento/Email/Model/Template/Filter.php index 3bb849931c7f8..31a44de7fd3f4 100644 --- a/app/code/Magento/Email/Model/Template/Filter.php +++ b/app/code/Magento/Email/Model/Template/Filter.php @@ -321,6 +321,8 @@ public function setDesignParams(array $designParams) } /** + * Get Css processor + * * @deprecated 100.1.2 * @return Css\Processor */ @@ -333,6 +335,8 @@ private function getCssProcessor() } /** + * Get pub directory + * * @deprecated 100.1.2 * @param string $dirType * @return ReadInterface @@ -523,6 +527,7 @@ public function mediaDirective($construction) /** * Retrieve store URL directive + * * Support url and direct_url properties * * @param string[] $construction @@ -958,6 +963,8 @@ public function getCssFilesContent(array $files) } /** + * Apply inline css + * * Merge HTML and CSS and return HTML that has CSS styles applied "inline" to the HTML tags. This is necessary * in order to support all email clients. * From 6a74efb80be824545eb3de5c59139e7dd27dd479 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Fri, 19 Apr 2019 15:37:19 +0300 Subject: [PATCH 274/773] MC-15929: [TSG] PR48 stabilization --- .../Test/Mftf/Test/AddOutOfStockProductToCompareListTest.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AddOutOfStockProductToCompareListTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AddOutOfStockProductToCompareListTest.xml index 4f66395bd0fbf..10d9342566040 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AddOutOfStockProductToCompareListTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AddOutOfStockProductToCompareListTest.xml @@ -17,6 +17,9 @@ <testCaseId value="MAGETWO-98644"/> <useCaseId value="MAGETWO-98522"/> <group value="Catalog"/> + <skip> + <issueId value="MC-15930"/> + </skip> </annotations> <before> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> From 9ff38e5345e6d1ffccdf24cc3f6d079361817419 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Fri, 19 Apr 2019 17:49:45 +0300 Subject: [PATCH 275/773] MC-15929: [TSG] PR48 stabilization --- .../Test/Mftf/Test/AdminExportBundleProductTest.xml | 3 +++ .../Test/AdminExportSimpleProductWithCustomAttributeTest.xml | 3 +++ 2 files changed, 6 insertions(+) diff --git a/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportBundleProductTest.xml b/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportBundleProductTest.xml index 1f5ae6b6905bc..b571b32331dde 100644 --- a/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportBundleProductTest.xml +++ b/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportBundleProductTest.xml @@ -18,6 +18,9 @@ <testCaseId value="MC-14008"/> <group value="catalog_import_export"/> <group value="mtf_migrated"/> + <skip> + <issueId value="MC-15934"/> + </skip> </annotations> <before> <!--Create bundle product with dynamic price with two simple products --> diff --git a/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportSimpleProductWithCustomAttributeTest.xml b/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportSimpleProductWithCustomAttributeTest.xml index f671b54803e35..365139eda06c1 100644 --- a/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportSimpleProductWithCustomAttributeTest.xml +++ b/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportSimpleProductWithCustomAttributeTest.xml @@ -18,6 +18,9 @@ <testCaseId value="MC-14007"/> <group value="catalog_import_export"/> <group value="mtf_migrated"/> + <skip> + <issueId value="MC-15934"/> + </skip> </annotations> <before> <!-- Create simple product with custom attribute set --> From 9e5cde84d0b7a453c72e09ce196f846cdea57c8f Mon Sep 17 00:00:00 2001 From: Kavitha <kanair@adobe.com> Date: Fri, 19 Apr 2019 16:53:39 -0500 Subject: [PATCH 276/773] MC-4459: Convert OnePageCheckoutOfflinePaymentMethodsTest to MFTF --- .../ActionGroup/AdminProductActionGroup.xml | 4 + .../Mftf/Data/CatalogInventryConfigData.xml | 24 ++ ...tFillEstimateShippingAndTaxActionGroup.xml | 22 ++ ...CheckoutShippingAddressFormActionGroup.xml | 27 +++ ...orefrontCustomerSignInPopUpActionGroup.xml | 23 ++ ...gisterCustomerAfterCheckoutActionGroup.xml | 21 ++ .../Test/Mftf/Data/CheckoutConfigData.xml | 35 +++ .../Section/CheckoutCartSummarySection.xml | 1 + .../Mftf/Section/CheckoutPaymentSection.xml | 3 + .../Mftf/Section/CheckoutShippingSection.xml | 4 + .../Section/CheckoutSuccessMainSection.xml | 1 + ...ingAddressAndProductWithTierPricesTest.xml | 129 ++++++++++ ...ssAndRegisterCustomerAfterCheckoutTest.xml | 102 ++++++++ ...ntCheckoutWithSpecialPriceProductsTest.xml | 171 ++++++++++++++ ...OnLoginWhenGuestCheckoutIsDisabledTest.xml | 92 ++++++++ ...egistrationAndDisableGuestCheckoutTest.xml | 132 +++++++++++ ...tCheckoutUsingFreeShippingAndTaxesTest.xml | 221 ++++++++++++++++++ ...tCheckoutWithCouponAndZeroSubtotalTest.xml | 93 ++++++++ ...ngesInBackendAfterCustomerCheckoutTest.xml | 105 +++++++++ ...efrontUKCustomerCheckoutWithCouponTest.xml | 128 ++++++++++ ...uctQuantityEqualsToOrderedQuantityTest.xml | 100 ++++++++ ...CouponAndBankTransferPaymentMethodTest.xml | 97 ++++++++ ...torefrontFillBillingAddressActionGroup.xml | 24 ++ .../Customer/Test/Mftf/Data/AddressData.xml | 14 ++ .../Test/Mftf/Data/CustomerConfigData.xml | 12 + .../Customer/Test/Mftf/Data/CustomerData.xml | 14 ++ .../StorefrontCustomerAddressesSection.xml | 2 + .../StorefrontCustomerSignInFormSection.xml | 1 + .../Test/Mftf/Data/PaymentConfigData.xml | 35 +++ ...AssertOrderAvailableButtonsActionGroup.xml | 20 ++ .../ActionGroup/AdminOrderActionGroup.xml | 9 + .../AdminShipThePendingOrderActionGroup.xml | 21 ++ .../Mftf/Section/AdminOrdersGridSection.xml | 1 + .../Test/Mftf/Data/SalesRuleData.xml | 29 +++ .../Mftf/Data/StoreShippingMethodsData.xml | 7 + 35 files changed, 1724 insertions(+) create mode 100644 app/code/Magento/CatalogInventory/Test/Mftf/Data/CatalogInventryConfigData.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/CheckoutFillEstimateShippingAndTaxActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/FillGuestCheckoutShippingAddressFormActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCustomerSignInPopUpActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontRegisterCustomerAfterCheckoutActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/Data/CheckoutConfigData.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckoutWithDifferentShippingAndBillingAddressAndProductWithTierPricesTest.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckoutWithDifferentShippingAndBillingAddressAndRegisterCustomerAfterCheckoutTest.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckoutWithSpecialPriceProductsTest.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerCheckoutOnLoginWhenGuestCheckoutIsDisabledTest.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerCheckoutWithNewCustomerRegistrationAndDisableGuestCheckoutTest.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/Test/StorefrontGuestCheckoutUsingFreeShippingAndTaxesTest.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/Test/StorefrontGuestCheckoutWithCouponAndZeroSubtotalTest.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/Test/StorefrontProductQuantityChangesInBackendAfterCustomerCheckoutTest.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/Test/StorefrontUKCustomerCheckoutWithCouponTest.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/Test/StorefrontUKGuestCheckoutWithConditionProductQuantityEqualsToOrderedQuantityTest.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/Test/StorefrontUSCustomerCheckoutWithCouponAndBankTransferPaymentMethodTest.xml create mode 100644 app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontFillBillingAddressActionGroup.xml create mode 100644 app/code/Magento/Payment/Test/Mftf/Data/PaymentConfigData.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAssertOrderAvailableButtonsActionGroup.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminShipThePendingOrderActionGroup.xml diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductActionGroup.xml index 3c44a8f1898ad..d7a9ee9ae85c2 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductActionGroup.xml @@ -248,6 +248,10 @@ <waitForPageLoad time="60" stepKey="WaitForProductSave1"/> <see userInput="You saved the product." stepKey="seeSaveConfirmation"/> </actionGroup> + <actionGroup name="ProductSetAdvancedTierFixedPricing" extends="ProductSetAdvancedPricing"> + <remove keyForRemoval="selectProductTierPricePriceInput"/> + <fillField selector="{{AdminProductFormAdvancedPricingSection.productTierPriceFixedPriceInput('0')}}" userInput="{{amount}}" stepKey="selectProductTierPricePriceInput" after="selectProductTierPriceValueType"/> + </actionGroup> <!--Assert text in Related, Up-Sell or Cross-Sell section in Admin Product page--> <actionGroup name="AssertTextInAdminProductRelatedUpSellCrossSellSection"> diff --git a/app/code/Magento/CatalogInventory/Test/Mftf/Data/CatalogInventryConfigData.xml b/app/code/Magento/CatalogInventory/Test/Mftf/Data/CatalogInventryConfigData.xml new file mode 100644 index 0000000000000..c48631a8d03c1 --- /dev/null +++ b/app/code/Magento/CatalogInventory/Test/Mftf/Data/CatalogInventryConfigData.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd"> + <entity name="EnableCatalogInventoryConfigData"> + <!--Default Value --> + <data key="path">cataloginventory/options/can_subtract</data> + <data key="scope_id">0</data> + <data key="label">Yes</data> + <data key="value">1</data> + </entity> + <entity name="DisableCatalogInventoryConfigData"> + <data key="path">cataloginventory/options/can_subtract</data> + <data key="scope_id">0</data> + <data key="label">No</data> + <data key="value">0</data> + </entity> +</entities> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/CheckoutFillEstimateShippingAndTaxActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/CheckoutFillEstimateShippingAndTaxActionGroup.xml new file mode 100644 index 0000000000000..985d9d3bee186 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/CheckoutFillEstimateShippingAndTaxActionGroup.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="CheckoutFillEstimateShippingAndTaxActionGroup"> + <arguments> + <argument name="address" defaultValue="US_Address_TX"/> + </arguments> + <conditionalClick selector="{{CheckoutCartSummarySection.estimateShippingAndTax}}" dependentSelector="{{CheckoutCartSummarySection.estimateShippingAndTaxSummary}}" visible="false" stepKey="openShippingDetails"/> + <selectOption selector="{{CheckoutCartSummarySection.country}}" userInput="{{address.country_id}}" stepKey="selectCountry"/> + <selectOption selector="{{CheckoutCartSummarySection.stateProvince}}" userInput="{{address.state}}" stepKey="selectState"/> + <waitForElementVisible selector="{{CheckoutCartSummarySection.postcode}}" stepKey="waitForPasswordFieldToBeVisisble"/> + <fillField selector="{{CheckoutCartSummarySection.postcode}}" userInput="{{address.postcode}}" stepKey="selectPostCode"/> + <waitForLoadingMaskToDisappear stepKey="waitForLoadingMaskToDiappear"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/FillGuestCheckoutShippingAddressFormActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/FillGuestCheckoutShippingAddressFormActionGroup.xml new file mode 100644 index 0000000000000..3203c8eef5ac6 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/FillGuestCheckoutShippingAddressFormActionGroup.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="FillGuestCheckoutShippingAddressFormActionGroup"> + <arguments> + <argument name="customer" defaultValue="Simple_US_Customer"/> + <argument name="customerAddress" defaultValue="US_Address_TX"/> + </arguments> + <fillField selector="{{CheckoutShippingSection.emailAddress}}" userInput="{{customer.email}}" stepKey="setCustomerEmail"/> + <fillField selector="{{CheckoutShippingSection.firstName}}" userInput="{{customer.firstname}}" stepKey="SetCustomerFirstName"/> + <fillField selector="{{CheckoutShippingSection.lastName}}" userInput="{{customer.lastname}}" stepKey="SetCustomerLastName"/> + <fillField selector="{{CheckoutShippingSection.street}}" userInput="{{customerAddress.street[0]}}" stepKey="SetCustomerStreetAddress"/> + <fillField selector="{{CheckoutShippingSection.city}}" userInput="{{customerAddress.city}}" stepKey="SetCustomerCity"/> + <fillField selector="{{CheckoutShippingSection.postcode}}" userInput="{{customerAddress.postcode}}" stepKey="SetCustomerZipCode"/> + <fillField selector="{{CheckoutShippingSection.telephone}}" userInput="{{customerAddress.telephone}}" stepKey="SetCustomerPhoneNumber"/> + </actionGroup> + <actionGroup name="FillGuestCheckoutShippingAddressWithCountryActionGroup" extends="FillGuestCheckoutShippingAddressFormActionGroup"> + <selectOption selector="{{CheckoutShippingSection.country}}" userInput="{{customerAddress.country_id}}" stepKey="selectCountry" after="SetCustomerCity"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCustomerSignInPopUpActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCustomerSignInPopUpActionGroup.xml new file mode 100644 index 0000000000000..627ca6237017a --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCustomerSignInPopUpActionGroup.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="StorefrontCustomerSignInPopUpActionGroup"> + <arguments> + <argument name="customerEmail" type="string"/> + <argument name="customerPwd" type="string"/> + </arguments> + <waitForElementVisible selector="{{StorefrontCustomerSignInPopupFormSection.email}}" stepKey="waitForElementToBeVisible"/> + <fillField stepKey="fillEmail" userInput="{{customerEmail}}" selector="{{StorefrontCustomerSignInPopupFormSection.email}}"/> + <fillField stepKey="fillPassword" userInput="{{customerPwd}}" selector="{{StorefrontCustomerSignInPopupFormSection.password}}"/> + <click stepKey="clickSignInAccountButton" selector="{{StorefrontCustomerSignInPopupFormSection.signIn}}"/> + <click selector="{{CheckoutCartSummarySection.proceedToCheckout}}" stepKey="goToCheckout"/> + <waitForPageLoad stepKey="waitForPageToLoad"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontRegisterCustomerAfterCheckoutActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontRegisterCustomerAfterCheckoutActionGroup.xml new file mode 100644 index 0000000000000..b72c63668edf2 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontRegisterCustomerAfterCheckoutActionGroup.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="StorefrontRegisterCustomerAfterCheckoutActionGroup"> + <arguments> + <argument name="customerPassword" defaultValue="UKCustomer"/> + </arguments> + <click selector="{{CheckoutSuccessRegisterSection.createAccountButton}}" stepKey="clickOnCreateAnAccountButton"/> + <fillField selector="{{StorefrontCustomerAccountInformationSection.newPassword}}" userInput="{{customerPassword.password}}" stepKey="fillPassword"/> + <fillField selector="{{StorefrontCustomerAccountInformationSection.confirmNewPassword}}" userInput="{{customerPassword.password}}" stepKey="reconfirmPassword"/> + <click selector="{{StorefrontCustomerCreateFormSection.createAccountButton}}" stepKey="clickOnCreateAnAccount"/> + <seeElement selector="{{StorefrontCustomerMessagesSection.successMessage}}" stepKey="seeSuccessMessage1"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/Checkout/Test/Mftf/Data/CheckoutConfigData.xml b/app/code/Magento/Checkout/Test/Mftf/Data/CheckoutConfigData.xml new file mode 100644 index 0000000000000..13d9385101f18 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/Data/CheckoutConfigData.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd"> + <entity name="EnableGuestCheckoutConfigData"> + <data key="path">checkout/options/guest_checkout</data> + <data key="scope_id">0</data> + <data key="label">Yes</data> + <data key="value">1</data> + </entity> + <entity name="DisableGuestCheckoutConfigData"> + <data key="path">checkout/options/guest_checkout</data> + <data key="scope_id">0</data> + <data key="label">No</data> + <data key="value">0</data> + </entity> + <entity name="EnableHttpsFrontendConfigData"> + <data key="path">web/secure/use_in_frontend</data> + <data key="scope_id">0</data> + <data key="label">Yes</data> + <data key="value">1</data> + </entity> + <entity name="DisableHttpsFrontendConfigData"> + <data key="path">web/secure/use_in_frontend</data> + <data key="scope_id">0</data> + <data key="label">No</data> + <data key="value">0</data> + </entity> +</entities> \ No newline at end of file diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartSummarySection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartSummarySection.xml index 8d14a9a561900..9de85ddb369d4 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartSummarySection.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartSummarySection.xml @@ -24,5 +24,6 @@ <element name="countryParameterized" type="select" selector="select[name='country_id'] > option:nth-child({{var}})" timeout="10" parameterized="true"/> <element name="estimateShippingAndTax" type="text" selector="#block-shipping-heading" timeout="5"/> <element name="flatRateShippingMethod" type="input" selector="#s_method_flatrate_flatrate" timeout="30"/> + <element name="estimateShippingAndTaxSummary" type="text" selector="#block-summary"/> </section> </sections> diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutPaymentSection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutPaymentSection.xml index 0206c18b819c2..0dc88506027d6 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutPaymentSection.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutPaymentSection.xml @@ -23,6 +23,7 @@ <element name="guestRegion" type="select" selector=".billing-address-form select[name*='region_id']"/> <element name="guestPostcode" type="input" selector=".billing-address-form input[name*='postcode']"/> <element name="guestTelephone" type="input" selector=".billing-address-form input[name*='telephone']"/> + <element name="guestCountry" type="select" selector=".billing-address-form select[name*='country_id']"/> <element name="billingAddress" type="text" selector=".payment-method._active div.billing-address-details"/> <element name="cartItems" type="text" selector="ol.minicart-items"/> <element name="cartItemsArea" type="button" selector="div.block.items-in-cart"/> @@ -54,5 +55,7 @@ <element name="addressBook" type="button" selector="//a[text()='Address Book']"/> <element name="noQuotes" type="text" selector=".no-quotes-block"/> <element name="paymentMethodByName" type="text" selector="//*[@id='checkout-payment-method-load']//*[contains(@class, 'payment-group')]//label[normalize-space(.)='{{var1}}']" parameterized="true"/> + <element name="checkBankTransferPayment" type="radio" selector="//input[@id='banktransfer']"/> + <element name="billingAddressNotSameBankTransferCheckbox" type="checkbox" selector="#billing-address-same-as-shipping-banktransfer"/> </section> </sections> diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingSection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingSection.xml index d825e10395145..ba4f42d3dca2b 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingSection.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingSection.xml @@ -36,5 +36,9 @@ <element name="stateInput" type="input" selector="input[name=region]"/> <element name="regionOptions" type="select" selector="select[name=region_id] option"/> <element name="editActiveAddress" type="button" selector="//div[@class='shipping-address-item selected-item']//span[text()='Edit']" timeout="30"/> + <element name="password" type="input" selector="#customer-password"/> + <element name="loginButton" type="button" selector="//button[@data-action='checkout-method-login']" timeout="30"/> + <element name="editActiveAddressButton" type="button" selector="//div[@class='payment-method _active']//button[@class='action action-edit-address']" timeout="30"/> + <element name="emailAddress" type="input" selector="#checkout-customer-email"/> </section> </sections> diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutSuccessMainSection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutSuccessMainSection.xml index bc65f8a2c0816..04eda22c31913 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutSuccessMainSection.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutSuccessMainSection.xml @@ -18,5 +18,6 @@ <element name="continueShoppingButton" type="button" selector=".action.primary.continue" timeout="30"/> <element name="createAnAccount" type="button" selector="input[value='Create an Account']" timeout="30"/> <element name="printLink" type="button" selector=".print" timeout="30"/> + <element name="orderNumberWithoutLink" type="text" selector="//div[@class='checkout-success']/p/span"/> </section> </sections> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckoutWithDifferentShippingAndBillingAddressAndProductWithTierPricesTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckoutWithDifferentShippingAndBillingAddressAndProductWithTierPricesTest.xml new file mode 100644 index 0000000000000..f7365dd8522a7 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckoutWithDifferentShippingAndBillingAddressAndProductWithTierPricesTest.xml @@ -0,0 +1,129 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="StorefrontCheckoutWithDifferentShippingAndBillingAddressAndProductWithTierPricesTest"> + <annotations> + <stories value="Checkout"/> + <title value="Verify checkout with different shipping and billing address and product with tier prices"/> + <description value="Checkout as a customer with different shipping and billing address and product with tier prices"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-14713"/> + <group value="mtf_migrated"/> + </annotations> + + <before> + <magentoCLI command="config:set {{EnablePaymentBankTransferConfigData.path}} {{EnablePaymentBankTransferConfigData.value}}" stepKey="enableBankTransferPayment"/> <actionGroup ref="LoginAsAdmin" stepKey="loginToAdminPanel"/> + <createData entity="SimpleProduct2" stepKey="simpleProduct"> + <field key="price">50.00</field> + </createData> + <actionGroup ref="filterAndSelectProduct" stepKey="filterAndSelectTheProduct"> + <argument name="productSku" value="$$simpleProduct.sku$$"/> + </actionGroup> + <actionGroup ref="ProductSetAdvancedTierFixedPricing" stepKey="setTierPrice"> + <argument name="website" value=""/> + <argument name="group" value=""/> + <argument name="quantity" value="3"/> + <argument name="price" value="Fixed"/> + <argument name="amount" value="24.00"/> + </actionGroup> + <magentoCLI command="cache:flush" stepKey="flushCache"/> + </before> + <after> + <deleteData createDataKey="simpleProduct" stepKey="deleteProduct"/> + <actionGroup ref="AdminDeleteCustomerActionGroup" stepKey="deleteCustomer"> + <argument name="customerEmail" value="UKCustomer.email"/> + </actionGroup> + <actionGroup ref="logout" stepKey="logout"/> + <magentoCLI command="config:set {{DisablePaymentBankTransferConfigData.path}} {{DisablePaymentBankTransferConfigData.value}}" stepKey="enableGuestCheckout"/> + </after> + + <!--Open Product page in StoreFront and assert product and price range --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProductPageAndVerifyProduct"> + <argument name="product" value="$$simpleProduct$$"/> + </actionGroup> + + <!--Add product to the cart --> + <actionGroup ref="StorefrontAddProductToCartWithQtyActionGroup" stepKey="addProductToTheCart"> + <argument name="productQty" value="3"/> + </actionGroup> + + <!--Open View and edit --> + <actionGroup ref="clickViewAndEditCartFromMiniCart" stepKey="clickMiniCart"/> + + <!-- Fill the Estimate Shipping and Tax section --> + <actionGroup ref="CheckoutFillEstimateShippingAndTaxActionGroup" stepKey="fillEstimateShippingAndTaxFields"/> + <click selector="{{CheckoutCartSummarySection.proceedToCheckout}}" stepKey="goToCheckout"/> + <waitForPageLoad stepKey="waitForPageToLoad"/> + + <!-- Fill the guest form --> + <actionGroup ref="FillGuestCheckoutShippingAddressWithCountryActionGroup" stepKey="fillGuestForm"> + <argument name="customer" value="UKCustomer"/> + <argument name="customerAddress" value="updateCustomerUKAddress"/> + </actionGroup> + <waitForElementVisible selector="{{CheckoutShippingMethodsSection.next}}" stepKey="waitForNextButton"/> + <click selector="{{CheckoutShippingMethodsSection.next}}" stepKey="clickOnNextButton"/> + <waitForElementVisible selector="{{CheckoutPaymentSection.checkBankTransferPayment}}" stepKey="waitForPlaceOrderButton"/> + <checkOption selector="{{CheckoutPaymentSection.checkBankTransferPayment}}" stepKey="selectBankTransfer"/> + <waitForElementVisible selector="{{CheckoutPaymentSection.billingAddressNotSameBankTransferCheckbox}}" stepKey="waitForElementToBeVisible"/> + <uncheckOption selector="{{CheckoutPaymentSection.billingAddressNotSameBankTransferCheckbox}}" stepKey="uncheckSameBillingAndShippingAddress"/> + <conditionalClick selector="{{CheckoutShippingSection.editActiveAddressButton}}" dependentSelector="{{CheckoutShippingSection.editActiveAddressButton}}" visible="true" stepKey="clickEditButton"/> + <waitForLoadingMaskToDisappear stepKey="waitForLoadingMask"/> + + <!-- Fill Billing Address --> + <actionGroup ref="StorefrontFillBillingAddressActionGroup" stepKey="fillBillingAddress"/> + <click selector="{{CheckoutPaymentSection.update}}" stepKey="clickOnUpdateButton"/> + + <!--Place order and Assert success message --> + <actionGroup ref="ClickPlaceOrderActionGroup" stepKey="clickOnPlaceOrder"/> + + <!-- Assert Empty Mini Cart --> + <seeElement selector="{{StorefrontMiniCartSection.emptyMiniCart}}" stepKey="assertEmptyCart" /> + <grabTextFrom selector="{{CheckoutSuccessMainSection.orderNumberWithoutLink}}" stepKey="orderId"/> + + <!-- Register customer after checkout --> + <actionGroup ref="StorefrontRegisterCustomerAfterCheckoutActionGroup" stepKey="registerCustomer"/> + + <!-- Assert Billing Address in Storefront --> + <see selector="{{StorefrontCustomerAddressesSection.billingAddress}}" userInput="{{CustomerUKAddress.street[0]}}" stepKey="seeStreetNameInBillingAddress"/> + <see selector="{{StorefrontCustomerAddressesSection.billingAddress}}" userInput="{{CustomerUKAddress.city}}" stepKey="seeCityInBillingAddress"/> + <see selector="{{StorefrontCustomerAddressesSection.billingAddress}}" userInput="{{CustomerUKAddress.country}}" stepKey="seeCountryInBillingAddress"/> + <see selector="{{StorefrontCustomerAddressesSection.billingAddress}}" userInput="T: {{CustomerUKAddress.telephone}}" stepKey="seeTelephoneInBillingAddress"/> + + <!-- Assert Billing Address in Storefront --> + <see selector="{{StorefrontCustomerAddressesSection.shippingAddress}}" userInput="{{updateCustomerUKAddress.street[0]}}" stepKey="seeStreetNameInShippingAddress"/> + <see selector="{{StorefrontCustomerAddressesSection.shippingAddress}}" userInput="{{updateCustomerUKAddress.city}}" stepKey="seeCityInShippingAddress"/> + <see selector="{{StorefrontCustomerAddressesSection.shippingAddress}}" userInput="{{updateCustomerUKAddress.country}}" stepKey="seeCountryInShippingAddress"/> + <see selector="{{StorefrontCustomerAddressesSection.shippingAddress}}" userInput="T: {{updateCustomerUKAddress.telephone}}" stepKey="seeTelephoneInShippingAddress"/> + + <!--Open Order Index Page --> + <amOnPage url="{{AdminOrdersPage.url}}" stepKey="goToOrders"/> + <waitForPageLoad stepKey="waitForOrderIndexPageToLoad"/> + + <!-- Filter Order using orderId and assert order--> + <actionGroup ref="filterOrderGridById" stepKey="filterOrderGridById"> + <argument name="orderId" value="$orderId"/> + </actionGroup> + <click selector="{{AdminOrdersGridSection.viewLink('$orderId')}}" stepKey="clickOnViewLink"/> + <waitForPageLoad stepKey="waitForOrderPageToLoad"/> + + <!-- Assert Grand Total --> + <see selector="{{AdminOrderTotalSection.grandTotal}}" userInput="$87.00" stepKey="seeGrandTotal"/> + <see selector="{{AdminOrderDetailsInformationSection.orderStatus}}" userInput="Pending" stepKey="seeOrderStatus"/> + + <!-- Ship the order and assert the status --> + <actionGroup ref="AdminShipThePendingOrderActionGroup" stepKey="shipTheOrder"/> + + <!-- Assert order buttons --> + <actionGroup ref="AdminAssertOrderAvailableButtonsActionGroup" stepKey="assertOrderButtons"/> + + <!-- Sign out Customer from storefront --> + <actionGroup ref="StorefrontOpenHomePageActionGroup" stepKey="openHomePage"/> + <actionGroup ref="StorefrontSignOutActionGroup" stepKey="customerLogout"/> + </test> +</tests> \ No newline at end of file diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckoutWithDifferentShippingAndBillingAddressAndRegisterCustomerAfterCheckoutTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckoutWithDifferentShippingAndBillingAddressAndRegisterCustomerAfterCheckoutTest.xml new file mode 100644 index 0000000000000..c52e8b73b262e --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckoutWithDifferentShippingAndBillingAddressAndRegisterCustomerAfterCheckoutTest.xml @@ -0,0 +1,102 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="StorefrontCheckoutWithDifferentShippingAndBillingAddressAndRegisterCustomerAfterCheckoutTest"> + <annotations> + <stories value="Checkout"/> + <title value="Verify UK customer checkout with different billing and shipping address and register customer after checkout"/> + <description value="Checkout as UK customer with different shipping/billing address and register checkout method"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-14712"/> + <group value="mtf_migrated"/> + </annotations> + + <before> + <actionGroup ref="LoginAsAdmin" stepKey="loginToAdminPanel"/> + <createData entity="SimpleProduct2" stepKey="simpleProduct"> + <field key="price">50.00</field> + </createData> + </before> + <after> + <deleteData createDataKey="simpleProduct" stepKey="deleteProduct"/> + <actionGroup ref="AdminDeleteCustomerActionGroup" stepKey="deleteCustomer"> + <argument name="customerEmail" value="UKCustomer.email"/> + </actionGroup> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <!--Open Product page in StoreFront and assert product and price range --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProductPageAndVerifyProduct"> + <argument name="product" value="$$simpleProduct$$"/> + </actionGroup> + + <!--Add product to the cart --> + <actionGroup ref="StorefrontAddProductToCartWithQtyActionGroup" stepKey="addProductToTheCart"> + <argument name="productQty" value="1"/> + </actionGroup> + + <!--Open View and edit --> + <actionGroup ref="clickViewAndEditCartFromMiniCart" stepKey="clickMiniCart"/> + + <!-- Fill the Estimate Shipping and Tax section --> + <actionGroup ref="CheckoutFillEstimateShippingAndTaxActionGroup" stepKey="fillEstimateShippingAndTaxFields"/> + <click selector="{{CheckoutCartSummarySection.proceedToCheckout}}" stepKey="goToCheckout"/> + <waitForPageLoad stepKey="waitForPageToLoad"/> + + <!-- Fill the guest form --> + <actionGroup ref="FillGuestCheckoutShippingAddressFormActionGroup" stepKey="fillGuestForm"> + <argument name="customer" value="UKCustomer"/> + <argument name="customerAddress" value="updateCustomerUKAddress"/> + </actionGroup> + <waitForElementVisible selector="{{CheckoutShippingMethodsSection.next}}" stepKey="waitForNextButton"/> + <click selector="{{CheckoutShippingMethodsSection.next}}" stepKey="clickOnNextButton"/> + <waitForElementVisible selector="{{CheckoutPaymentSection.billingAddressNotSameCheckbox}}" stepKey="waitForElementToBeVisible"/> + <uncheckOption selector="{{CheckoutPaymentSection.billingAddressNotSameCheckbox}}" stepKey="uncheckSameBillingAndShippingAddress"/> + <conditionalClick selector="{{CheckoutShippingSection.editAddressButton}}" dependentSelector="{{CheckoutShippingSection.editAddressButton}}" visible="true" stepKey="clickEditButton"/> + <waitForLoadingMaskToDisappear stepKey="waitForLoadingMask"/> + + <!-- Fill Billing Address --> + <actionGroup ref="StorefrontFillBillingAddressActionGroup" stepKey="fillBillingAddress"/> + <click selector="{{CheckoutPaymentSection.update}}" stepKey="clickOnUpdateButton"/> + + <!--Place order --> + <actionGroup ref="ClickPlaceOrderActionGroup" stepKey="clickOnPlaceOrder"/> + <seeElement selector="{{StorefrontMiniCartSection.emptyMiniCart}}" stepKey="assertEmptyCart" /> + <grabTextFrom selector="{{CheckoutSuccessMainSection.orderNumberWithoutLink}}" stepKey="orderId"/> + + <!-- Register customer after checkout --> + <actionGroup ref="StorefrontRegisterCustomerAfterCheckoutActionGroup" stepKey="registerCustomer"/> + + <!-- Open Order Index Page --> + <amOnPage url="{{AdminOrdersPage.url}}" stepKey="goToOrders"/> + <waitForPageLoad stepKey="waitForPageLoad5"/> + + <!-- Filter Order using orderId and assert order--> + <actionGroup ref="filterOrderGridById" stepKey="filterOrderGridById"> + <argument name="orderId" value="$orderId"/> + </actionGroup> + + <click selector="{{AdminOrdersGridSection.viewLink('$orderId')}}" stepKey="clickOnViewLink"/> + <waitForPageLoad stepKey="waitForOrderPageToLoad"/> + + <!-- Assert Grand Total --> + <see selector="{{AdminOrderTotalSection.grandTotal}}" userInput="$55.00" stepKey="seeGrandTotal"/> + <see selector="{{AdminOrderDetailsInformationSection.orderStatus}}" userInput="Pending" stepKey="seeOrderStatus"/> + + <!-- Ship the order and assert the status --> + <actionGroup ref="AdminShipThePendingOrderActionGroup" stepKey="shipTheOrder"/> + + <!-- Assert order buttons --> + <actionGroup ref="AdminAssertOrderAvailableButtonsActionGroup" stepKey="assertOrderButtons"/> + + <!-- Sign out Customer from storefront --> + <actionGroup ref="StorefrontOpenHomePageActionGroup" stepKey="openHomePage"/> + <actionGroup ref="StorefrontSignOutActionGroup" stepKey="customerLogout"/> + </test> +</tests> \ No newline at end of file diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckoutWithSpecialPriceProductsTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckoutWithSpecialPriceProductsTest.xml new file mode 100644 index 0000000000000..6ccb05bf4c4f7 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckoutWithSpecialPriceProductsTest.xml @@ -0,0 +1,171 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="StorefrontCheckoutWithSpecialPriceProductsTest"> + <annotations> + <stories value="Checkout"/> + <title value="Verify customer checkout with special price simple and configurable products"/> + <description value="Create simple and configurable product with special prices and verify customer checkout"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-14708"/> + <group value="mtf_migrated"/> + </annotations> + + <before> + <actionGroup ref="LoginAsAdmin" stepKey="loginToAdminPanel"/> + <createData entity="Simple_US_Customer" stepKey="createCustomer"/> + <createData entity="defaultSimpleProduct" stepKey="simpleProduct"> + <field key="price">10.00</field> + </createData> + + <actionGroup ref="filterAndSelectProduct" stepKey="filterAndSelectTheProduct"> + <argument name="productSku" value="$$simpleProduct.sku$$"/> + </actionGroup> + + <actionGroup ref="AddSpecialPriceToProductActionGroup" stepKey="addSpecialPriceTopTheProduct"> + <argument name="price" value="9"/> + </actionGroup> + <click selector="{{AdminProductFormAdvancedPricingSection.save}}" stepKey="clickSaveProduct"/> + <waitForPageLoad time='60' stepKey="waitForProducrSaved"/> + <waitForElementVisible selector="{{AdminMessagesSection.success}}" stepKey="waitForSaveSuccessMessage"/> + + <!-- Create the configurable product with product Attribute options--> + <createData entity="ApiCategory" stepKey="createCategory"/> + <createData entity="ApiConfigurableProduct" stepKey="createConfigProduct"> + <requiredEntity createDataKey="createCategory"/> + </createData> + <createData entity="productAttributeWithTwoOptions" stepKey="createConfigProductAttribute"/> + <createData entity="productAttributeOption1" stepKey="createConfigProductAttributeOption1"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + </createData> + <createData entity="productAttributeOption2" stepKey="createConfigProductAttributeOption2"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + </createData> + <createData entity="AddToDefaultSet" stepKey="delete"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + </createData> + <getData entity="ProductAttributeOptionGetter" index="1" stepKey="getConfigAttributeOption1"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + </getData> + <getData entity="ProductAttributeOptionGetter" index="2" stepKey="getConfigAttributeOption2"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + </getData> + <createData entity="ApiSimpleOne" stepKey="createConfigChildProduct1"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + <requiredEntity createDataKey="getConfigAttributeOption1"/> + <field key="price">20.00</field> + </createData> + <createData entity="ApiSimpleTwo" stepKey="createConfigChildProduct2"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + <requiredEntity createDataKey="getConfigAttributeOption2"/> + <field key="price">10.00</field> + </createData> + <createData entity="ConfigurableProductTwoOptions" stepKey="createConfigProductOption"> + <requiredEntity createDataKey="createConfigProduct"/> + <requiredEntity createDataKey="createConfigProductAttribute"/> + <requiredEntity createDataKey="getConfigAttributeOption1"/> + <requiredEntity createDataKey="getConfigAttributeOption2"/> + </createData> + <createData entity="ConfigurableProductAddChild" stepKey="createConfigProductAddChild1"> + <requiredEntity createDataKey="createConfigProduct"/> + <requiredEntity createDataKey="createConfigChildProduct1"/> + </createData> + <createData entity="ConfigurableProductAddChild" stepKey="createConfigProductAddChild2"> + <requiredEntity createDataKey="createConfigProduct"/> + <requiredEntity createDataKey="createConfigChildProduct2"/> + </createData> + + <actionGroup ref="filterAndSelectProduct" stepKey="filterAndSelectTheProduct2"> + <argument name="productSku" value="$$createConfigChildProduct2.sku$$"/> + </actionGroup> + <actionGroup ref="AddSpecialPriceToProductActionGroup" stepKey="addSpecialPriceTopTheProduct2"> + <argument name="price" value="9"/> + </actionGroup> + <click selector="{{AdminProductFormAdvancedPricingSection.save}}" stepKey="clickSaveProduct1"/> + <waitForPageLoad time='60' stepKey="waitForSpecialPriceProductSaved"/> + <waitForElementVisible selector="{{AdminMessagesSection.success}}" stepKey="waitForSaveSuccessMessage1"/> + <magentoCLI command="indexer:reindex" stepKey="reindex"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> + </before> + <after> + <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + <deleteData createDataKey="simpleProduct" stepKey="deleteProduct"/> + <deleteData createDataKey="createConfigChildProduct1" stepKey="deleteConfigProduct1"/> + <deleteData createDataKey="createConfigChildProduct2" stepKey="deleteConfigProduct2"/> + <deleteData createDataKey="createConfigProduct" stepKey="deleteConfigProduct"/> + <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteProductAttribute"/> + <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <!--Open Product page in StoreFront and assert product and price range --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProductPageAndVerifyProduct"> + <argument name="product" value="$$simpleProduct$$"/> + </actionGroup> + + <!--Add product to the cart --> + <actionGroup ref="StorefrontAddProductToCartWithQtyActionGroup" stepKey="addProductToTheCart"> + <argument name="productQty" value="1"/> + </actionGroup> + + <!-- Add Configurable Product to the cart --> + <actionGroup ref="StorefrontAddConfigurableProductToTheCartActionGroup" stepKey="addConfigurableProductToCart"> + <argument name="urlKey" value="$$createConfigProduct.custom_attributes[url_key]$$" /> + <argument name="productAttribute" value="$$createConfigProductAttribute.default_value$$"/> + <argument name="productOption" value="$$getConfigAttributeOption2.label$$"/> + <argument name="qty" value="1"/> + </actionGroup> + + <!--Open View and edit --> + <actionGroup ref="clickViewAndEditCartFromMiniCart" stepKey="clickMiniCart"/> + + <!-- Fill the Estimate Shipping and Tax section --> + <actionGroup ref="CheckoutFillEstimateShippingAndTaxActionGroup" stepKey="fillEstimateShippingAndTaxFields"/> + <click selector="{{CheckoutCartSummarySection.proceedToCheckout}}" stepKey="goToCheckout"/> + <waitForPageLoad stepKey="waitForPageToLoad"/> + + <!-- Sign in using already existed customer details --> + <fillField selector="{{CheckoutShippingSection.emailAddress}}" userInput="$$createCustomer.email$$" stepKey="fillEmailAddress"/> + <waitForElementVisible selector="{{CheckoutShippingSection.password}}" stepKey="waitForPasswordFieldToBeVisible"/> + <fillField selector="{{CheckoutShippingSection.password}}" userInput="$$createCustomer.password$$" stepKey="fillPassword"/> + <click selector="{{CheckoutShippingSection.loginButton}}" stepKey="clickLoginButton"/> + <waitForPageLoad stepKey="waitForLoginPageToLoad"/> + <waitForElementVisible selector="{{CheckoutShippingMethodsSection.next}}" stepKey="waitForNextButton"/> + <click selector="{{CheckoutShippingMethodsSection.next}}" stepKey="clickOnNextButton"/> + + <!-- Place order and Assert success message --> + <actionGroup ref="ClickPlaceOrderActionGroup" stepKey="clickOnPlaceOrder"/> + + <!-- Assert empty Mini Cart --> + <seeElement selector="{{StorefrontMiniCartSection.emptyMiniCart}}" stepKey="assertEmptyCart" /> + <grabTextFrom selector="{{CheckoutSuccessMainSection.orderLink}}" stepKey="orderId"/> + + <!-- Open Order Index Page --> + <amOnPage url="{{AdminOrdersPage.url}}" stepKey="goToOrders"/> + <waitForPageLoad stepKey="waitForPageLoad5"/> + + <!-- Filter Order using orderId and assert order--> + <actionGroup ref="filterOrderGridById" stepKey="filterOrderGridById"> + <argument name="orderId" value="$orderId"/> + </actionGroup> + + <click selector="{{AdminOrdersGridSection.viewLink('$orderId')}}" stepKey="clickOnViewLink"/> + <waitForPageLoad stepKey="waitForOrderPageToLoad"/> + + <!-- Assert Grand Total --> + <see selector="{{AdminOrderTotalSection.grandTotal}}" userInput="$28.00" stepKey="seeGrandTotal"/> + <see selector="{{AdminOrderDetailsInformationSection.orderStatus}}" userInput="Pending" stepKey="seeOrderStatus"/> + + <!-- Ship the order and assert the status --> + <actionGroup ref="AdminShipThePendingOrderActionGroup" stepKey="shipTheOrder"/> + + <!-- Assert order buttons --> + <actionGroup ref="AdminAssertOrderAvailableButtonsActionGroup" stepKey="assertOrderButtons"/> + </test> +</tests> \ No newline at end of file diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerCheckoutOnLoginWhenGuestCheckoutIsDisabledTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerCheckoutOnLoginWhenGuestCheckoutIsDisabledTest.xml new file mode 100644 index 0000000000000..4d205e0d40490 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerCheckoutOnLoginWhenGuestCheckoutIsDisabledTest.xml @@ -0,0 +1,92 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="StorefrontCustomerCheckoutOnLoginWhenGuestCheckoutIsDisabledTest"> + <annotations> + <stories value="Checkout"/> + <title value="Verify customer is redirected to checkout on login when guest checkout is disabled"/> + <description value="Customer is redirected to checkout on login when guest checkout is disabled"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-14703"/> + <group value="mtf_migrated"/> + </annotations> + + <before> + <actionGroup ref="LoginAsAdmin" stepKey="loginToAdminPanel"/> + <magentoCLI command="config:set {{DisableGuestCheckoutConfigData.path}} {{DisableGuestCheckoutConfigData.value}}" stepKey="disableGuestCheckout"/> + <magentoCLI command="config:set {{DisableCustomerRedirectToDashboardConfigData.path}} {{DisableCustomerRedirectToDashboardConfigData.value}}" stepKey="disableCustomerRedirect"/> + <createData entity="SimpleProduct2" stepKey="simpleProduct"> + <field key="price">50.00</field> + </createData> + <createData entity="Simple_US_Customer" stepKey="createCustomer"/> + </before> + <after> + <deleteData createDataKey="simpleProduct" stepKey="deleteProduct"/> + <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> + <magentoCLI command="config:set {{EnableGuestCheckoutConfigData.path}} {{EnableGuestCheckoutConfigData.value}}" stepKey="enableGuestCheckout"/> + <magentoCLI command="config:set {{EnableCustomerRedirectToDashboardConfigData.path}} {{EnableCustomerRedirectToDashboardConfigData.value}}" stepKey="enableCustomerRedirect"/> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <!--Open Product page in StoreFront and assert product and price range --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProductPageAndVerifyProduct"> + <argument name="product" value="$$simpleProduct$$"/> + </actionGroup> + + <!--Add product to the cart --> + <actionGroup ref="StorefrontAddProductToCartWithQtyActionGroup" stepKey="addProductToTheCart"> + <argument name="productQty" value="1"/> + </actionGroup> + + <!--Open View and edit --> + <actionGroup ref="clickViewAndEditCartFromMiniCart" stepKey="clickMiniCart"/> + + <!-- Fill the Estimate Shipping and Tax section --> + <actionGroup ref="CheckoutFillEstimateShippingAndTaxActionGroup" stepKey="fillEstimateShippingAndTaxFields"/> + <click selector="{{CheckoutCartSummarySection.proceedToCheckout}}" stepKey="goToCheckout"/> + + <!--Fill the pop up sign form --> + <actionGroup ref="StorefrontCustomerSignInPopUpActionGroup" stepKey="customerSignIn"> + <argument name="customerEmail" value="$$createCustomer.email$$"/> + <argument name="customerPwd" value="$$createCustomer.password$$"/> + </actionGroup> + <waitForElementVisible selector="{{CheckoutShippingMethodsSection.next}}" stepKey="waitForNextButton"/> + <click selector="{{CheckoutShippingMethodsSection.next}}" stepKey="clickOnNextButton"/> + + <!-- Verify order summary on payment page --> + <actionGroup ref="VerifyCheckoutPaymentOrderSummaryActionGroup" stepKey="verifyCheckoutPaymentOrderSummary"> + <argument name="orderSummarySubTotal" value="$50.00"/> + <argument name="orderSummaryShippingTotal" value="$5.00"/> + <argument name="orderSummaryTotal" value="$55.00"/> + </actionGroup> + + <!-- Place order and Assert success message --> + <actionGroup ref="ClickPlaceOrderActionGroup" stepKey="clickOnPlaceOrder"/> + <grabTextFrom selector="{{CheckoutSuccessMainSection.orderLink}}" stepKey="orderId"/> + + <!-- Open Order Index Page --> + <amOnPage url="{{AdminOrdersPage.url}}" stepKey="goToOrders"/> + <waitForPageLoad stepKey="waitForPageLoad"/> + + <!-- Filter Order using orderId and assert order--> + <actionGroup ref="filterOrderGridById" stepKey="filterOrderGridById"> + <argument name="orderId" value="$orderId"/> + </actionGroup> + + <click selector="{{AdminOrdersGridSection.viewLink('$orderId')}}" stepKey="clickOnViewLink"/> + <waitForPageLoad stepKey="waitForOrderPageToLoad"/> + + <!-- Ship the order and assert the shipping status --> + <actionGroup ref="AdminShipThePendingOrderActionGroup" stepKey="shipTheOrder"/> + + <!-- Sign out Customer from storefront --> + <actionGroup ref="StorefrontOpenHomePageActionGroup" stepKey="openHomePage"/> + <actionGroup ref="StorefrontSignOutActionGroup" stepKey="customerLogout"/> + </test> +</tests> \ No newline at end of file diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerCheckoutWithNewCustomerRegistrationAndDisableGuestCheckoutTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerCheckoutWithNewCustomerRegistrationAndDisableGuestCheckoutTest.xml new file mode 100644 index 0000000000000..b523a6e3b9e6a --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerCheckoutWithNewCustomerRegistrationAndDisableGuestCheckoutTest.xml @@ -0,0 +1,132 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="StorefrontCustomerCheckoutWithNewCustomerRegistrationAndDisableGuestCheckoutTest"> + <annotations> + <stories value="Checkout"/> + <title value="Verify customer checkout by following new customer registration when guest checkout is disabled"/> + <description value="Customer is redirected to checkout on login, follow the new Customer registration when guest checkout is disabled"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-14704"/> + <group value="mtf_migrated"/> + </annotations> + + <before> + <actionGroup ref="LoginAsAdmin" stepKey="loginToAdminPanel"/> + <magentoCLI command="config:set {{DisableGuestCheckoutConfigData.path}} {{DisableGuestCheckoutConfigData.value}}" stepKey="disableGuestCheckout"/> + <magentoCLI command="config:set {{DisableCustomerRedirectToDashboardConfigData.path}} {{DisableCustomerRedirectToDashboardConfigData.value}}" stepKey="disableCustomerRedirect"/> + <createData entity="SimpleProduct2" stepKey="simpleProduct"> + <field key="price">50.00</field> + </createData> + <createData entity="Simple_US_Customer" stepKey="createCustomer"/> + </before> + <after> + <deleteData createDataKey="simpleProduct" stepKey="deleteProduct"/> + <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> + <magentoCLI command="config:set {{EnableGuestCheckoutConfigData.path}} {{EnableGuestCheckoutConfigData.value}}" stepKey="enableGuestCheckout"/> + <magentoCLI command="config:set {{EnableCustomerRedirectToDashboardConfigData.path}} {{EnableCustomerRedirectToDashboardConfigData.value}}" stepKey="enableCustomerRedirect"/> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <!--Open Product page in StoreFront and assert product and price range --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProductPageAndVerifyProduct"> + <argument name="product" value="$$simpleProduct$$"/> + </actionGroup> + + <!--Add product to the cart --> + <actionGroup ref="StorefrontAddProductToCartWithQtyActionGroup" stepKey="addProductToTheCart"> + <argument name="productQty" value="1"/> + </actionGroup> + + <!--Open View and edit --> + <actionGroup ref="clickViewAndEditCartFromMiniCart" stepKey="clickMiniCart"/> + <click selector="{{CheckoutCartSummarySection.proceedToCheckout}}" stepKey="goToCheckout"/> + <waitForPageLoad stepKey="waitForPageToLoad"/> + + <!--Create an account--> + <waitForElementVisible selector="{{StorefrontCustomerSignInPopupFormSection.createAnAccount}}" stepKey="waitForElementToBeVisible"/> + <click selector="{{StorefrontCustomerSignInPopupFormSection.createAnAccount}}" stepKey="clickOnCreateAnAccountButton"/> + <waitForPageLoad stepKey="waitForCreateAccountPageToLoad"/> + + <!--Fill the registration form --> + <actionGroup ref="StorefrontFillCustomerAccountCreationFormActionGroup" stepKey="createNewCustomerAccount"> + <argument name="customer" value="Simple_US_Customer" /> + </actionGroup> + <click stepKey="clickCreateAccountButton" selector="{{StorefrontCustomerCreateFormSection.createAccountButton}}"/> + <waitForPageLoad stepKey="waitForCreateAccountButtonToLoad"/> + + <!--Assert customer information--> + <see stepKey="seeThankYouMessage" userInput="Thank you for registering with Main Website Store."/> + <see stepKey="seeFirstName" userInput="{{Simple_US_Customer.firstname}}" selector="{{StorefrontCustomerDashboardAccountInformationSection.ContactInformation}}" /> + <see stepKey="seeLastName" userInput="{{Simple_US_Customer.lastname}}" selector="{{StorefrontCustomerDashboardAccountInformationSection.ContactInformation}}" /> + <see stepKey="seeEmail" userInput="{{Simple_US_Customer.email}}" selector="{{StorefrontCustomerDashboardAccountInformationSection.ContactInformation}}" /> + + <!--Fill Address details --> + <click selector="{{CheckoutPaymentSection.addressBook}}" stepKey="goToAddressBook"/> + <fillField stepKey="fillPhoneNumber" userInput="{{US_Address_TX.telephone}}" selector="{{StorefrontCustomerAddressFormSection.phoneNumber}}"/> + <fillField stepKey="fillStreetAddress" userInput="{{US_Address_TX.street[0]}}" selector="{{StorefrontCustomerAddressFormSection.streetAddress}}"/> + <fillField stepKey="fillCity" userInput="{{US_Address_TX.city}}" selector="{{StorefrontCustomerAddressFormSection.city}}"/> + <selectOption stepKey="selectStateForAddress" userInput="{{CustomerAddressSimple.state}}" selector="{{StorefrontCustomerAddressFormSection.state}}"/> + <fillField stepKey="fillZip" userInput="{{US_Address_TX.postcode}}" selector="{{StorefrontCustomerAddressFormSection.zip}}"/> + <selectOption stepKey="selectCountryForAddress" userInput="{{US_Address_TX.country}}" selector="{{StorefrontCustomerAddressFormSection.country}}"/> + <click stepKey="saveCustomerAddress" selector="{{StorefrontCustomerAddressFormSection.saveAddress}}"/> + <see userInput="You saved the address." stepKey="verifyAddressAdded"/> + + <!-- Open Edit and View from cart --> + <actionGroup ref="clickViewAndEditCartFromMiniCart" stepKey="openViewAndEditOption"/> + + <!-- Proceed to checkout --> + <click selector="{{CheckoutCartSummarySection.proceedToCheckout}}" stepKey="goToCheckout1"/> + <waitForElementVisible selector="{{CheckoutShippingMethodsSection.next}}" stepKey="waitForNextButton"/> + <click selector="{{CheckoutShippingMethodsSection.next}}" stepKey="clickOnNextButton"/> + + <!-- Verify order summary on payment page --> + <actionGroup ref="VerifyCheckoutPaymentOrderSummaryActionGroup" stepKey="verifyCheckoutPaymentOrderSummary"> + <argument name="orderSummarySubTotal" value="$50.00"/> + <argument name="orderSummaryShippingTotal" value="$5.00"/> + <argument name="orderSummaryTotal" value="$55.00"/> + </actionGroup> + + <!-- Assert Shipping Address --> + <actionGroup ref="CheckShipToInformationInCheckoutActionGroup" stepKey="assertShippingAddressDetails"> + <argument name="customerVar" value="Simple_US_Customer"/> + <argument name="customerAddressVar" value="US_Address_TX"/> + </actionGroup> + + <!-- Assert Billing Address --> + <actionGroup ref="CheckBillingAddressInCheckoutActionGroup" stepKey="assertBillingAddressDetails"> + <argument name="customerVar" value="Simple_US_Customer"/> + <argument name="customerAddressVar" value="US_Address_TX"/> + </actionGroup> + <see userInput="Flat Rate - Fixed" selector="{{CheckoutPaymentSection.shippingMethodInformation}}" stepKey="assertShippingMethodInformation"/> + + <!-- Place order and Assert success message --> + <actionGroup ref="ClickPlaceOrderActionGroup" stepKey="clickOnPlaceOrder"/> + <grabTextFrom selector="{{CheckoutSuccessMainSection.orderLink}}" stepKey="orderId"/> + + <!-- Open Order Index Page --> + <amOnPage url="{{AdminOrdersPage.url}}" stepKey="goToOrders"/> + <waitForPageLoad stepKey="waitForPageLoad"/> + + <!-- Filter Order using orderId and assert order--> + <actionGroup ref="filterOrderGridById" stepKey="filterOrderGridById"> + <argument name="orderId" value="$orderId"/> + </actionGroup> + + <click selector="{{AdminOrdersGridSection.viewLink('$orderId')}}" stepKey="clickOnViewLink"/> + <waitForPageLoad stepKey="waitForOrderPageToLoad"/> + + <!-- Ship the order and assert the shipping status --> + <actionGroup ref="AdminShipThePendingOrderActionGroup" stepKey="shipTheOrder"/> + + <!-- Sign out Customer from storefront --> + <actionGroup ref="StorefrontOpenHomePageActionGroup" stepKey="openHomePage"/> + <actionGroup ref="StorefrontSignOutActionGroup" stepKey="customerLogout"/> + </test> +</tests> \ No newline at end of file diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontGuestCheckoutUsingFreeShippingAndTaxesTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontGuestCheckoutUsingFreeShippingAndTaxesTest.xml new file mode 100644 index 0000000000000..728225d460081 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontGuestCheckoutUsingFreeShippingAndTaxesTest.xml @@ -0,0 +1,221 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="StorefrontGuestCheckoutUsingFreeShippingAndTaxesTest"> + <annotations> + <stories value="Checkout"/> + <title value="Verify guest checkout using free shipping and tax variations"/> + <description value="Verify guest checkout using free shipping and tax variations"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-14709"/> + <group value="mtf_migrated"/> + </annotations> + + <before> + <actionGroup ref="LoginAsAdmin" stepKey="loginToAdminPanel"/> + <createData entity="FlatRateShippingMethodConfig" stepKey="enableFlatRate"/> + <createData entity="FreeShippingMethodsSettingConfig" stepKey="freeShippingMethodsSettingConfig"/> + <createData entity="MinimumOrderAmount100" stepKey="minimumOrderAmount100"/> + <createData entity="taxRate_US_NY_8_1" stepKey="createTaxRule"/> + + <!--Create Simple Product --> + <createData entity="defaultSimpleProduct" stepKey="simpleProduct"> + <field key="price">10.00</field> + </createData> + + <!-- Create the configurable product with product Attribute options--> + <createData entity="ApiCategory" stepKey="createCategory"/> + <createData entity="ApiConfigurableProduct" stepKey="createConfigProduct"> + <requiredEntity createDataKey="createCategory"/> + </createData> + <createData entity="productAttributeWithTwoOptions" stepKey="createConfigProductAttribute"/> + <createData entity="productAttributeOption1" stepKey="createConfigProductAttributeOption1"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + </createData> + + <createData entity="AddToDefaultSet" stepKey="addToDefaultSet"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + </createData> + <getData entity="ProductAttributeOptionGetter" index="1" stepKey="getConfigAttributeOption1"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + </getData> + + <createData entity="ApiSimpleOne" stepKey="createConfigChildProduct1"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + <requiredEntity createDataKey="getConfigAttributeOption1"/> + <field key="price">10.00</field> + </createData> + + <createData entity="ConfigurableProductTwoOptions" stepKey="createConfigProductOption"> + <requiredEntity createDataKey="createConfigProduct"/> + <requiredEntity createDataKey="createConfigProductAttribute"/> + <requiredEntity createDataKey="getConfigAttributeOption1"/> + </createData> + <createData entity="ConfigurableProductAddChild" stepKey="createConfigProductAddChild1"> + <requiredEntity createDataKey="createConfigProduct"/> + <requiredEntity createDataKey="createConfigChildProduct1"/> + </createData> + + <!-- Create Bundle Product --> + <createData entity="SimpleProduct2" stepKey="simpleProduct1"> + <field key="price">100.00</field> + </createData> + <createData entity="SimpleProduct2" stepKey="simpleProduct2"> + <field key="price">200.00</field> + </createData> + <!--Create Bundle product with multi select option--> + <createData entity="BundleProductPriceViewRange" stepKey="createBundleProduct"> + <requiredEntity createDataKey="createCategory"/> + </createData> + <createData entity="MultipleSelectOption" stepKey="createBundleOption1_1"> + <requiredEntity createDataKey="createBundleProduct"/> + <field key="required">True</field> + </createData> + <createData entity="ApiBundleLink" stepKey="linkOptionToProduct"> + <requiredEntity createDataKey="createBundleProduct"/> + <requiredEntity createDataKey="createBundleOption1_1"/> + <requiredEntity createDataKey="simpleProduct1"/> + </createData> + <createData entity="ApiBundleLink" stepKey="linkOptionToProduct2"> + <requiredEntity createDataKey="createBundleProduct"/> + <requiredEntity createDataKey="createBundleOption1_1"/> + <requiredEntity createDataKey="simpleProduct2"/> + </createData> + <magentoCLI command="indexer:reindex" stepKey="reindex"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> + </before> + <after> + <actionGroup ref="AdminDeleteTaxRule" stepKey="deleteTaxRule"> + <argument name="taxRuleCode" value="{{SimpleTaxRule.code}}" /> + </actionGroup> + <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + <deleteData createDataKey="simpleProduct" stepKey="deleteProduct"/> + <deleteData createDataKey="createConfigChildProduct1" stepKey="deleteConfigProduct1"/> + <deleteData createDataKey="createConfigProduct" stepKey="deleteConfigProduct"/> + <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteProductAttribute"/> + <deleteData createDataKey="simpleProduct1" stepKey="deleteProduct1"/> + <deleteData createDataKey="simpleProduct2" stepKey="deleteProduct2"/> + <deleteData createDataKey="createBundleProduct" stepKey="deleteBundleProduct"/> + <deleteData createDataKey="createTaxRule" stepKey="deleteTaxRule1"/> + <createData entity="DefaultShippingMethodsConfig" stepKey="defaultShippingMethodsConfig"/> + <createData entity="DefaultMinimumOrderAmount" stepKey="defaultMinimumOrderAmount"/> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <!-- Create a Tax Rule --> + <amOnPage url="{{AdminTaxRuleGridPage.url}}" stepKey="goToTaxRuleIndex1"/> + <waitForPageLoad stepKey="waitForTaxRuleIndex1"/> + <click selector="{{AdminTaxRuleGridSection.add}}" stepKey="clickAddNewTaxRuleButton"/> + <waitForPageLoad stepKey="waitForTaxRuleIndex2"/> + + <!-- Create a tax rule with defaults --> + <fillField selector="{{AdminTaxRuleFormSection.code}}" userInput="{{SimpleTaxRule.code}}" stepKey="fillTaxRuleCode1"/> + <fillField selector="{{AdminTaxRuleFormSection.taxRateSearch}}" userInput="$$createTaxRule.code$$" stepKey="fillTaxRateSearch"/> + <wait stepKey="waitForSearch" time="5" /> + <click selector="{{AdminTaxRuleFormSection.taxRateOption($$createTaxRule.code$$)}}" stepKey="selectNeededItem" /> + <click selector="{{AdminTaxRuleFormSection.save}}" stepKey="saveTaxRule" /> + <waitForPageLoad stepKey="waitForTaxRuleSaved" /> + + <!-- Verify we see success message --> + <see selector="{{AdminTaxRuleGridSection.successMessage}}" userInput="You saved the tax rule." stepKey="assertTaxRuleSuccessMessage" /> + + <!--Open Product page in StoreFront and assert product and price range --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProductPageAndVerifyProduct"> + <argument name="product" value="$$simpleProduct$$"/> + </actionGroup> + + <!--Add product to the cart --> + <actionGroup ref="StorefrontAddProductToCartWithQtyActionGroup" stepKey="addProductToTheCart"> + <argument name="productQty" value="1"/> + </actionGroup> + + <!-- Add Configurable Product to the cart --> + <actionGroup ref="StorefrontAddConfigurableProductToTheCartActionGroup" stepKey="addConfigurableProductToCart"> + <argument name="urlKey" value="$$createConfigProduct.custom_attributes[url_key]$$" /> + <argument name="productAttribute" value="$$createConfigProductAttribute.default_value$$"/> + <argument name="productOption" value="$$getConfigAttributeOption1.label$$"/> + <argument name="qty" value="1"/> + </actionGroup> + + <!--Open Product page in StoreFront --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openBundleProduct"> + <argument name="product" value="$$createBundleProduct$$"/> + </actionGroup> + + <!-- Click on customize And Add To Cart Button --> + <actionGroup ref="StorefrontSelectCustomizeAndAddToTheCartButtonActionGroup" stepKey="clickOnCustomizeAndAddtoCartButton"/> + + <!-- Select Two Products, enter the quantity and add product to the cart --> + <selectOption selector="{{StorefrontBundledSection.multiSelectOption}}" userInput="$$simpleProduct1.name$$ +$100.00" stepKey="selectOption"/> + <actionGroup ref="StorefrontEnterProductQuantityAndAddToTheCartActionGroup" stepKey="enterProductQuantityAndAddToTheCart"> + <argument name="quantity" value="1"/> + </actionGroup> + + <!--Open View and edit --> + <actionGroup ref="clickViewAndEditCartFromMiniCart" stepKey="clickMiniCart"/> + + <!-- Fill the Estimate Shipping and Tax section --> + <actionGroup ref="CheckoutFillEstimateShippingAndTaxActionGroup" stepKey="fillEstimateShippingAndTaxFields"> + <argument name="address" value="US_Address_NY_Default_Shipping"/> + </actionGroup> + <reloadPage stepKey="reloadThePage"/> + <waitForPageLoad stepKey="waitForPageToReload"/> + <waitForElementVisible selector="{{CheckoutCartSummarySection.taxAmount}}" stepKey="waitForShippingOption"/> + <see selector="{{CheckoutCartSummarySection.taxAmount}}" userInput="$9.60" stepKey="seeTaxInTheCartSummary"/> + + <!--Select Free Shipping and proceed to checkout --> + <click selector="{{AdminOrderFormPaymentSection.freeShippingOption}}" stepKey="selectFlatRateShippingMethod"/> + <click selector="{{CheckoutCartSummarySection.proceedToCheckout}}" stepKey="goToCheckout"/> + <waitForPageLoad stepKey="waitForPageToLoad"/> + + <!-- Fill Guest form --> + <actionGroup ref="FillGuestCheckoutShippingAddressFormActionGroup" stepKey="fillTheSignInForm"> + <argument name="customer" value="Simple_US_Customer"/> + <argument name="customerAddress" value="US_Address_NY_Default_Shipping"/> + </actionGroup> + <waitForElementVisible selector="{{CheckoutShippingMethodsSection.next}}" stepKey="waitForNextButton"/> + <click selector="{{CheckoutShippingMethodsSection.next}}" stepKey="clickOnNextButton"/> + + <!-- Place order and Assert success message --> + <actionGroup ref="ClickPlaceOrderActionGroup" stepKey="clickOnPlaceOrder"/> + + <!-- Assert empty Mini Cart --> + <seeElement selector="{{StorefrontMiniCartSection.emptyMiniCart}}" stepKey="assertEmptyCart" /> + <grabTextFrom selector="{{CheckoutSuccessMainSection.orderNumberWithoutLink}}" stepKey="orderId"/> + + <!-- Open Order Index Page --> + <amOnPage url="{{AdminOrdersPage.url}}" stepKey="goToOrders"/> + <waitForPageLoad stepKey="waitForPageLoad5"/> + + <!-- Filter Order using orderId and assert order--> + <actionGroup ref="filterOrderGridById" stepKey="filterOrderGridById"> + <argument name="orderId" value="$orderId"/> + </actionGroup> + <click selector="{{AdminOrdersGridSection.viewLink('$orderId')}}" stepKey="clickOnViewLink"/> + <waitForPageLoad stepKey="waitForOrderPageToLoad"/> + + <!-- Assert order buttons --> + <actionGroup ref="AdminAssertOrderAvailableButtonsActionGroup" stepKey="assertOrderButtons"/> + + <!-- Assert Grand Total --> + <see selector="{{AdminOrderTotalSection.grandTotal}}" userInput="$129.60" stepKey="seeGrandTotal"/> + <see selector="{{AdminOrderDetailsInformationSection.orderStatus}}" userInput="Pending" stepKey="seeOrderStatus"/> + + <!-- Ship the order and assert the status --> + <actionGroup ref="AdminShipThePendingOrderActionGroup" stepKey="shipTheOrder"/> + + <!-- Assert customer order address --> + <actionGroup ref="AssertOrderAddressInformationActionGroup" stepKey="assertCustomerInformation"> + <argument name="customer" value=""/> + <argument name="shippingAddress" value="US_Address_NY_Default_Shipping"/> + <argument name="billingAddress" value="US_Address_NY_Default_Shipping"/> + <argument name="customerGroup" value=""/> + </actionGroup> + </test> +</tests> \ No newline at end of file diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontGuestCheckoutWithCouponAndZeroSubtotalTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontGuestCheckoutWithCouponAndZeroSubtotalTest.xml new file mode 100644 index 0000000000000..33ec099aa2ace --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontGuestCheckoutWithCouponAndZeroSubtotalTest.xml @@ -0,0 +1,93 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="StorefrontGuestCheckoutWithCouponAndZeroSubtotalTest"> + <annotations> + <stories value="Checkout"/> + <title value="Verify guest checkout with virtual product using coupon for not logged in customers with Zero Subtotal"/> + <description value="Checkout with virtual product using coupon for not logged in customers with Zero Subtotal"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-14710"/> + <group value="mtf_migrated"/> + </annotations> + + <before> + <actionGroup ref="LoginAsAdmin" stepKey="loginToAdminPanel"/> + <createData entity="VirtualProduct" stepKey="virtualProduct"> + <field key="price">50.00</field> + </createData> + <createData entity="SalesRuleNoCouponWithFixedDiscount" stepKey="createSalesRule"/> + </before> + <after> + <deleteData createDataKey="virtualProduct" stepKey="deleteVirtualProduct"/> + <deleteData createDataKey="createSalesRule" stepKey="deleteSalesRule"/> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <!--Open Product page in StoreFront and assert product and price range --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openVirtualProductPageAndVerifyProduct"> + <argument name="product" value="$$virtualProduct$$"/> + </actionGroup> + + <!-- Add Product to the cart --> + <actionGroup ref="addToCartFromStorefrontProductPage" stepKey="addProduct1ToTheCart"> + <argument name="productName" value="$$virtualProduct.name$$"/> + </actionGroup> + + <!--Open View and edit --> + <actionGroup ref="clickViewAndEditCartFromMiniCart" stepKey="clickMiniCart"/> + + <!-- Fill the Estimate Shipping and Tax section --> + <actionGroup ref="CheckoutFillEstimateShippingAndTaxActionGroup" stepKey="fillEstimateShippingAndTaxFields"/> + + <!-- Assert Discount and proceed to checkout --> + <waitForElementVisible selector="{{CheckoutCartSummarySection.discountAmount}}" stepKey="waitForDiscountElement"/> + <see selector="{{CheckoutCartSummarySection.discountAmount}}" userInput="-$50.00" stepKey="seeDiscountTotal"/> + <click selector="{{CheckoutCartSummarySection.proceedToCheckout}}" stepKey="goToCheckout"/> + <waitForPageLoad stepKey="waitForPageToLoad"/> + + <!--Fill Customer Information --> + <fillField selector="{{CheckoutShippingSection.emailAddress}}" userInput="{{Simple_US_Customer.email}}" stepKey="enterEmail"/> + <waitForLoadingMaskToDisappear stepKey="waitForLoading" /> + <fillField selector="{{CheckoutPaymentSection.guestFirstName}}" userInput="{{Simple_US_Customer.firstname}}" stepKey="enterFirstName"/> + <fillField selector="{{CheckoutPaymentSection.guestLastName}}" userInput="{{Simple_US_Customer.lastname}}" stepKey="enterLastName"/> + <fillField selector="{{CheckoutPaymentSection.guestStreet}}" userInput="{{US_Address_TX.street[0]}}" stepKey="enterStreet"/> + <fillField selector="{{CheckoutPaymentSection.guestCity}}" userInput="{{US_Address_TX.city}}" stepKey="enterCity"/> + <selectOption selector="{{CheckoutPaymentSection.guestRegion}}" userInput="{{US_Address_TX.state}}" stepKey="selectRegion"/> + <fillField selector="{{CheckoutPaymentSection.guestPostcode}}" userInput="{{US_Address_TX.postcode}}" stepKey="enterPostcode"/> + <fillField selector="{{CheckoutPaymentSection.guestTelephone}}" userInput="{{US_Address_TX.telephone}}" stepKey="enterTelephone"/> + <waitForElementVisible selector="{{CheckoutPaymentSection.update}}" stepKey="waitForUpdateButton"/> + <click selector="{{CheckoutPaymentSection.update}}" stepKey="clickOnUpdateButton"/> + + <!-- Place order and Assert success message --> + <actionGroup ref="ClickPlaceOrderActionGroup" stepKey="clickOnPlaceOrder"/> + + <!-- Assert empty Mini Cart --> + <seeElement selector="{{StorefrontMiniCartSection.emptyMiniCart}}" stepKey="assertEmptyCart" /> + <grabTextFrom selector="{{CheckoutSuccessMainSection.orderNumberWithoutLink}}" stepKey="orderId"/> + + <!-- Open Order Index Page --> + <amOnPage url="{{AdminOrdersPage.url}}" stepKey="goToOrders"/> + <waitForPageLoad stepKey="waitForPageLoad5"/> + + <!-- Filter Order using orderId and assert order--> + <actionGroup ref="filterOrderGridById" stepKey="filterOrderGridById"> + <argument name="orderId" value="$orderId"/> + </actionGroup> + <click selector="{{AdminOrdersGridSection.viewLink('$orderId')}}" stepKey="clickOnViewLink"/> + <waitForPageLoad stepKey="waitForOrderPageToLoad"/> + + <!-- Assert order buttons --> + <actionGroup ref="AdminAssertOrderAvailableButtonsActionGroup" stepKey="assertOrderButtons"/> + + <!-- Assert Grand Total --> + <see selector="{{AdminOrderTotalSection.grandTotal}}" userInput="$0.00" stepKey="seeGrandTotal"/> + <see selector="{{AdminOrderDetailsInformationSection.orderStatus}}" userInput="Pending" stepKey="seeOrderStatus"/> + </test> +</tests> \ No newline at end of file diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontProductQuantityChangesInBackendAfterCustomerCheckoutTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontProductQuantityChangesInBackendAfterCustomerCheckoutTest.xml new file mode 100644 index 0000000000000..e5f6c52e445c5 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontProductQuantityChangesInBackendAfterCustomerCheckoutTest.xml @@ -0,0 +1,105 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="StorefrontProductQuantityChangesInBackendAfterCustomerCheckoutTest"> + <annotations> + <stories value="Checkout"/> + <title value="Verify product quantity changes in backend after customer checkout"/> + <description value="Checkout as UK customer with bank transfer payment method and verify product quantity reduced after order processed "/> + <severity value="CRITICAL"/> + <testCaseId value="MC-14707"/> + <group value="mtf_migrated"/> + </annotations> + + <before> + <actionGroup ref="LoginAsAdmin" stepKey="loginToAdminPanel"/> + <magentoCLI command="config:set {{EnablePaymentBankTransferConfigData.path}} {{EnablePaymentBankTransferConfigData.value}}" stepKey="enableBankTransferPayment"/> + <magentoCLI command="config:set {{EnableCatalogInventoryConfigData.path}} {{EnableCatalogInventoryConfigData.value}}" stepKey="enableCatalogInventoryStock"/> + <createData entity="defaultSimpleProduct" stepKey="simpleProduct"> + <field key="price">10.00</field> + </createData> + </before> + <after> + <deleteData createDataKey="simpleProduct" stepKey="deleteProduct"/> + <magentoCLI command="config:set {{DisablePaymentBankTransferConfigData.path}} {{DisablePaymentBankTransferConfigData.value}}" stepKey="enableGuestCheckout"/> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <!--Open Product page in StoreFront and assert product and price range --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProductPageAndVerifyProduct"> + <argument name="product" value="$$simpleProduct$$"/> + </actionGroup> + + <!--Add product to the cart --> + <actionGroup ref="StorefrontAddProductToCartWithQtyActionGroup" stepKey="addProductToTheCart"> + <argument name="productQty" value="100"/> + </actionGroup> + + <!--Open View and edit --> + <actionGroup ref="clickViewAndEditCartFromMiniCart" stepKey="clickMiniCart"/> + + <!-- Fill the Estimate Shipping and Tax section --> + <actionGroup ref="CheckoutFillEstimateShippingAndTaxActionGroup" stepKey="fillEstimateShippingAndTaxFields"/> + <click selector="{{CheckoutCartSummarySection.proceedToCheckout}}" stepKey="goToCheckout"/> + <waitForPageLoad stepKey="waitForPageToLoad"/> + + <!-- Fill Customer Sign In Information --> + <actionGroup ref="FillGuestCheckoutShippingAddressFormActionGroup" stepKey="fillGuestForm"> + <argument name="customer" value="UKCustomer"/> + <argument name="customerAddress" value="updateCustomerUKAddress"/> + </actionGroup> + <waitForElementVisible selector="{{CheckoutShippingMethodsSection.next}}" stepKey="waitForNextButton"/> + <click selector="{{CheckoutShippingMethodsSection.next}}" stepKey="clickOnNextButton"/> + <waitForElementVisible selector="{{CheckoutPaymentSection.checkBankTransferPayment}}" stepKey="waitForPlaceOrderButton"/> + <click selector="{{CheckoutPaymentSection.checkBankTransferPayment}}" stepKey="selectBankTransfer"/> + + <!-- Place order and Assert success message --> + <actionGroup ref="ClickPlaceOrderActionGroup" stepKey="clickOnPlaceOrder"/> + + <!-- Assert empty Mini Cart --> + <seeElement selector="{{StorefrontMiniCartSection.emptyMiniCart}}" stepKey="assertEmptyCart" /> + <grabTextFrom selector="{{CheckoutSuccessMainSection.orderNumberWithoutLink}}" stepKey="orderId"/> + + <!-- Open Order Index Page --> + <amOnPage url="{{AdminOrdersPage.url}}" stepKey="goToOrders"/> + <waitForPageLoad stepKey="waitForPageLoad5"/> + + <!-- Filter Order using orderId and assert order--> + <actionGroup ref="filterOrderGridById" stepKey="filterOrderGridById"> + <argument name="orderId" value="$orderId"/> + </actionGroup> + <click selector="{{AdminOrdersGridSection.viewLink('$orderId')}}" stepKey="clickOnViewLink"/> + <waitForPageLoad stepKey="waitForOrderPageToLoad"/> + + <!-- Assert Grand Total --> + <see selector="{{AdminOrderTotalSection.grandTotal}}" userInput="$1,500.00" stepKey="seeGrandTotal"/> + <see selector="{{AdminOrderDetailsInformationSection.orderStatus}}" userInput="Pending" stepKey="seeOrderStatus"/> + + <!-- Ship the order and assert the status --> + <actionGroup ref="AdminShipThePendingOrderActionGroup" stepKey="shipTheOrder"/> + + <!-- Assert order buttons --> + <actionGroup ref="AdminAssertOrderAvailableButtonsActionGroup" stepKey="assertOrderButtons"/> + + <!-- Assert Product Quantity in backend reduced after order processed --> + <actionGroup ref="filterAndSelectProduct" stepKey="filterAndSelectTheProduct"> + <argument name="productSku" value="$$simpleProduct.sku$$"/> + </actionGroup> + <waitForElementVisible selector="{{AdminProductFormSection.productName}}" stepKey="waitForProductDetailsToLoad"/> + <seeInField selector="{{AdminProductFormSection.productName}}" userInput="$$simpleProduct.name$$" stepKey="seeProductName"/> + <seeInField selector="{{AdminProductFormSection.productQuantity}}" userInput="0" stepKey="seeProductQuantity"/> + <seeInField selector="{{AdminProductFormSection.productStockStatus}}" userInput="Out of Stock" stepKey="seeProductStockStatus"/> + + <!-- Assert Product is Out of Stock in frontend --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="assertProductInStorefront"> + <argument name="product" value="$$simpleProduct$$"/> + </actionGroup> + <see selector="{{StorefrontProductInfoMainSection.productStockStatus}}" userInput="Out Of Stock" stepKey="seeProductDisplayedAsOutOfStock"/> + </test> +</tests> \ No newline at end of file diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontUKCustomerCheckoutWithCouponTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontUKCustomerCheckoutWithCouponTest.xml new file mode 100644 index 0000000000000..0e5d50df0fb3a --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontUKCustomerCheckoutWithCouponTest.xml @@ -0,0 +1,128 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="StorefrontUKCustomerCheckoutWithCouponTest"> + <annotations> + <stories value="Checkout"/> + <title value="Verify UK customer checkout with Virtual and Downloadable products using coupon"/> + <description value="Checkout as UK Customer with virtual product and downloadable product using coupon"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-14705"/> + <group value="mtf_migrated"/> + </annotations> + + <before> + <actionGroup ref="LoginAsAdmin" stepKey="loginToAdminPanel"/> + <createData entity="ApiDownloadableProduct" stepKey="createDownloadableProduct"> + <field key="price">20.00</field> + </createData> + <createData entity="downloadableLink1" stepKey="addDownloadableLink1"> + <requiredEntity createDataKey="createDownloadableProduct"/> + </createData> + <createData entity="downloadableLink2" stepKey="addDownloadableLink2"> + <requiredEntity createDataKey="createDownloadableProduct"/> + </createData> + <createData entity="VirtualProduct" stepKey="virtualProduct"> + <field key="price">10.00</field> + </createData> + <createData entity="UKCustomer" stepKey="createCustomer"/> + <createData entity="SalesRuleSpecificCouponAndByPercent" stepKey="createSalesRule"/> + <createData entity="SimpleSalesRuleCoupon" stepKey="createCouponForCartPriceRule"> + <requiredEntity createDataKey="createSalesRule"/> + </createData> + </before> + <after> + <deleteData createDataKey="createDownloadableProduct" stepKey="deleteProduct"/> + <deleteData createDataKey="virtualProduct" stepKey="deleteVirtualProduct"/> + <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> + <deleteData createDataKey="createSalesRule" stepKey="deleteSalesRule"/> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <!-- Open Downloadable Product page --> + <amOnPage url="{{StorefrontProductPage.url($$createDownloadableProduct.custom_attributes[url_key]$$)}}" stepKey="OpenStoreFrontProductPage"/> + <waitForPageLoad stepKey="waitForPageToLoad"/> + + <!-- Add Downloadable product to the cart --> + <actionGroup ref="StorefrontAddToCartCustomOptionsProductPageActionGroup" stepKey="addToTheCart"> + <argument name="productName" value="$$createDownloadableProduct.name$$" /> + </actionGroup> + + <!--Open Product page in StoreFront and assert product and price range --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openVirtualProductPageAndVerifyProduct"> + <argument name="product" value="$$virtualProduct$$"/> + </actionGroup> + + <!-- Add Product to the cart --> + <actionGroup ref="addToCartFromStorefrontProductPage" stepKey="addProduct1ToTheCart"> + <argument name="productName" value="$$virtualProduct.name$$"/> + </actionGroup> + + <!--Open View and edit --> + <actionGroup ref="clickViewAndEditCartFromMiniCart" stepKey="clickMiniCart"/> + + <!-- Apply Coupon --> + <actionGroup ref="StorefrontApplyCouponActionGroup" stepKey="applyDiscount"> + <argument name="coupon" value="$$createCouponForCartPriceRule$$"/> + </actionGroup> + + <!-- Assert Discount and proceed to checkout --> + <waitForElementVisible selector="{{CheckoutCartSummarySection.discountAmount}}" stepKey="waitForDiscountElement"/> + <see selector="{{CheckoutCartSummarySection.discountAmount}}" userInput="-$15.00" stepKey="seeDiscountTotal"/> + <click selector="{{CheckoutCartSummarySection.proceedToCheckout}}" stepKey="goToCheckout"/> + <waitForPageLoad stepKey="waitForPageToLoad1"/> + + <!--Fill the pop up sign form --> + <actionGroup ref="StorefrontCustomerSignInPopUpActionGroup" stepKey="customerSignIn"> + <argument name="customerEmail" value="$$createCustomer.email$$"/> + <argument name="customerPwd" value="$$createCustomer.password$$"/> + </actionGroup> + + <!-- Click and open order summary tab--> + <conditionalClick selector="{{CheckoutOrderSummarySection.miniCartTab}}" dependentSelector="{{CheckoutOrderSummarySection.miniCartTabClosed}}" visible="true" stepKey="clickOnOrderSummaryTab"/> + <waitForPageLoad stepKey="waitForPageToLoad5"/> + + <!-- Assert Product displayed in Order Summary --> + <actionGroup ref="StorefrontAssertProductDetailsInOrderSummaryActionGroup" stepKey="assertProduct3InOrderSummary"> + <argument name="productName" value="$$virtualProduct.name$$"/> + <argument name="qty" value="1"/> + <argument name="price" value="$10.00"/> + </actionGroup> + <waitForElementVisible selector="{{CheckoutPaymentSection.update}}" stepKey="waitForUpdateButton"/> + <click selector="{{CheckoutPaymentSection.update}}" stepKey="clickOnUpdateButton"/> + + <!-- Place the order and Verify Success message --> + <actionGroup ref="ClickPlaceOrderActionGroup" stepKey="clickOnPlaceOrder"/> + + <!-- Assert empty Mini Cart --> + <seeElement selector="{{StorefrontMiniCartSection.emptyMiniCart}}" stepKey="assertEmptyCart" /> + <grabTextFrom selector="{{CheckoutSuccessMainSection.orderLink}}" stepKey="orderId"/> + + <!-- Open Order Index Page --> + <amOnPage url="{{AdminOrdersPage.url}}" stepKey="goToOrders"/> + <waitForPageLoad stepKey="waitForPageLoad5"/> + + <!-- Filter Order using orderId and assert order--> + <actionGroup ref="filterOrderGridById" stepKey="filterOrderGridById"> + <argument name="orderId" value="$orderId"/> + </actionGroup> + <see selector="{{AdminOrdersGridSection.firstRow}}" userInput="$$createCustomer.fullname$$" stepKey="seeCustomerNameInGrid"/> + <see selector="{{AdminOrdersGridSection.firstRow}}" userInput="$15.00" stepKey="seeGrandTotalInGrid"/> + <see selector="{{AdminOrdersGridSection.firstRow}}" userInput="Pending" stepKey="seeStatusIdInGrid"/> + <click selector="{{AdminOrdersGridSection.viewLink('$orderId')}}" stepKey="clickOnOrderViewLink"/> + <waitForPageLoad stepKey="waitForOrderPageToLoad"/> + + <!-- Assert order buttons --> + <actionGroup ref="AdminAssertOrderAvailableButtonsActionGroup" stepKey="assertOrderButtons"/> + + <!-- Assert Grand Total --> + <see selector="{{AdminOrderTotalSection.grandTotal}}" userInput="$15.00" stepKey="seeGrandTotal"/> + <see selector="{{AdminOrderDetailsInformationSection.orderStatus}}" userInput="Pending" stepKey="seeOrderStatus"/> + </test> +</tests> \ No newline at end of file diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontUKGuestCheckoutWithConditionProductQuantityEqualsToOrderedQuantityTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontUKGuestCheckoutWithConditionProductQuantityEqualsToOrderedQuantityTest.xml new file mode 100644 index 0000000000000..deab32aede324 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontUKGuestCheckoutWithConditionProductQuantityEqualsToOrderedQuantityTest.xml @@ -0,0 +1,100 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="StorefrontUKGuestCheckoutWithConditionProductQuantityEqualsToOrderedQuantityTest"> + <annotations> + <stories value="Checkout"/> + <title value="Checkout as UK guest with condition available product quantity equals to ordered product quantity"/> + <description value="Checkout as UK guest with condition available product quantity equals to ordered product quantity"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-14711"/> + <group value="mtf_migrated"/> + </annotations> + + <before> + <actionGroup ref="LoginAsAdmin" stepKey="loginToAdminPanel"/> + <createData entity="defaultSimpleProduct" stepKey="simpleProduct"> + <field key="price">10.00</field> + </createData> + </before> + <after> + <deleteData createDataKey="simpleProduct" stepKey="deleteProduct"/> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <!--Open Product page in StoreFront and assert product and price range --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProductPageAndVerifyProduct"> + <argument name="product" value="$$simpleProduct$$"/> + </actionGroup> + + <!--Add product to the cart --> + <actionGroup ref="StorefrontAddProductToCartWithQtyActionGroup" stepKey="addProductToTheCart"> + <argument name="productQty" value="100"/> + </actionGroup> + + <!--Open View and edit --> + <actionGroup ref="clickViewAndEditCartFromMiniCart" stepKey="clickMiniCart"/> + + <!-- Fill the Estimate Shipping and Tax section --> + <actionGroup ref="CheckoutFillEstimateShippingAndTaxActionGroup" stepKey="fillEstimateShippingAndTaxFields"/> + <click selector="{{CheckoutCartSummarySection.proceedToCheckout}}" stepKey="goToCheckout"/> + <waitForPageLoad stepKey="waitForPageToLoad"/> + + <!-- Fill Customer Sign In Information --> + <actionGroup ref="FillGuestCheckoutShippingAddressFormActionGroup" stepKey="fillGuestForm"> + <argument name="customer" value="UKCustomer"/> + <argument name="customerAddress" value="UK_Not_Default_Address"/> + </actionGroup> + <waitForElementVisible selector="{{CheckoutShippingMethodsSection.next}}" stepKey="waitForNextButton"/> + <click selector="{{CheckoutShippingMethodsSection.next}}" stepKey="clickOnNextButton"/> + + <!-- Place order and Assert success message --> + <actionGroup ref="ClickPlaceOrderActionGroup" stepKey="clickOnPlaceOrder"/> + + <!-- Assert empty Mini Cart --> + <seeElement selector="{{StorefrontMiniCartSection.emptyMiniCart}}" stepKey="assertEmptyCart" /> + <grabTextFrom selector="{{CheckoutSuccessMainSection.orderNumberWithoutLink}}" stepKey="orderId"/> + + <!-- Open Order Index Page --> + <amOnPage url="{{AdminOrdersPage.url}}" stepKey="goToOrders"/> + <waitForPageLoad stepKey="waitForPageLoad5"/> + + <!-- Filter Order using orderId and assert order--> + <actionGroup ref="filterOrderGridById" stepKey="filterOrderGridById"> + <argument name="orderId" value="$orderId"/> + </actionGroup> + <click selector="{{AdminOrdersGridSection.viewLink('$orderId')}}" stepKey="clickOnViewLink"/> + <waitForPageLoad stepKey="waitForOrderPageToLoad"/> + + <!-- Assert Grand Total --> + <see selector="{{AdminOrderTotalSection.grandTotal}}" userInput="$1,500.00" stepKey="seeGrandTotal"/> + <see selector="{{AdminOrderDetailsInformationSection.orderStatus}}" userInput="Pending" stepKey="seeOrderStatus"/> + + <!-- Ship the order and assert the status --> + <actionGroup ref="AdminShipThePendingOrderActionGroup" stepKey="shipTheOrder"/> + + <!-- Assert order buttons --> + <actionGroup ref="AdminAssertOrderAvailableButtonsActionGroup" stepKey="assertOrderButtons"/> + + <!-- Assert Product Quantity in backend reduced after order processed --> + <actionGroup ref="filterAndSelectProduct" stepKey="filterAndSelectTheProduct"> + <argument name="productSku" value="$$simpleProduct.sku$$"/> + </actionGroup> + <waitForElementVisible selector="{{AdminProductFormSection.productName}}" stepKey="waitForProductDetailsToLoad"/> + <seeInField selector="{{AdminProductFormSection.productName}}" userInput="$$simpleProduct.name$$" stepKey="seeProductName"/> + <seeInField selector="{{AdminProductFormSection.productQuantity}}" userInput="0" stepKey="seeProductQuantity"/> + <seeInField selector="{{AdminProductFormSection.productStockStatus}}" userInput="Out of Stock" stepKey="seeProductStockStatus"/> + + <!-- Assert Product is Out of Stock in frontend --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="assertProductInStorefront"> + <argument name="product" value="$$simpleProduct$$"/> + </actionGroup> + <see selector="{{StorefrontProductInfoMainSection.productStockStatus}}" userInput="Out Of Stock" stepKey="seeProductDisplayedAsOutOfStock"/> + </test> +</tests> \ No newline at end of file diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontUSCustomerCheckoutWithCouponAndBankTransferPaymentMethodTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontUSCustomerCheckoutWithCouponAndBankTransferPaymentMethodTest.xml new file mode 100644 index 0000000000000..72b124ca0d005 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontUSCustomerCheckoutWithCouponAndBankTransferPaymentMethodTest.xml @@ -0,0 +1,97 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="StorefrontUSCustomerCheckoutWithCouponAndBankTransferPaymentMethodTest"> + <annotations> + <stories value="Checkout"/> + <title value="Verify US customer checkout using coupon and bank transfer payment method"/> + <description value="Checkout as US customer using coupon and bank transfer payment method"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-14706"/> + <group value="mtf_migrated"/> + </annotations> + + <before> + <actionGroup ref="LoginAsAdmin" stepKey="loginToAdminPanel"/> + <magentoCLI command="config:set {{EnablePaymentBankTransferConfigData.path}} {{EnablePaymentBankTransferConfigData.value}}" stepKey="enableBankTransferPayment"/> + <createData entity="SimpleProduct2" stepKey="simpleProduct"> + <field key="price">50.00</field> + </createData> + <createData entity="SalesRuleSpecificCouponAndByPercent" stepKey="createSalesRule"/> + <createData entity="SimpleSalesRuleCoupon" stepKey="createCouponForCartPriceRule"> + <requiredEntity createDataKey="createSalesRule"/> + </createData> + </before> + <after> + <deleteData createDataKey="simpleProduct" stepKey="deleteProduct"/> + <deleteData createDataKey="createSalesRule" stepKey="deleteSalesRule"/> + <magentoCLI command="config:set {{DisablePaymentBankTransferConfigData.path}} {{DisablePaymentBankTransferConfigData.value}}" stepKey="disableBankTransferPayment"/> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <!-- Open Product page in StoreFront and assert product and price range --> + <actionGroup ref="AssertProductNameAndSkuInStorefrontProductPageByCustomAttributeUrlKey" stepKey="openProductPageAndVerifyProduct"> + <argument name="product" value="$$simpleProduct$$"/> + </actionGroup> + + <!-- Add product to the cart --> + <actionGroup ref="StorefrontAddProductToCartWithQtyActionGroup" stepKey="addProductToTheCart"> + <argument name="productQty" value="1"/> + </actionGroup> + + <!-- Open View and edit --> + <actionGroup ref="clickViewAndEditCartFromMiniCart" stepKey="clickMiniCart"/> + + <!-- Fill the Estimate Shipping and Tax section --> + <actionGroup ref="CheckoutFillEstimateShippingAndTaxActionGroup" stepKey="fillEstimateShippingAndTaxFields"/> + + <!-- Apply Coupon --> + <actionGroup ref="StorefrontApplyCouponActionGroup" stepKey="applyDiscount"> + <argument name="coupon" value="$$createCouponForCartPriceRule$$"/> + </actionGroup> + + <click selector="{{CheckoutCartSummarySection.proceedToCheckout}}" stepKey="goToCheckout"/> + <waitForPageLoad stepKey="waitForPageToLoad"/> + + <!-- Fill the guest form --> + <actionGroup ref="FillGuestCheckoutShippingAddressFormActionGroup" stepKey="fillGuestForm"/> + <waitForElementVisible selector="{{CheckoutShippingMethodsSection.next}}" stepKey="waitForNextButton"/> + <click selector="{{CheckoutShippingMethodsSection.next}}" stepKey="clickOnNextButton"/> + <waitForElementVisible selector="{{CheckoutPaymentSection.checkBankTransferPayment}}" stepKey="waitForPlaceOrderButton"/> + <checkOption selector="{{CheckoutPaymentSection.checkBankTransferPayment}}" stepKey="selectBankTransfer"/> + + <!-- Place order and Assert success message --> + <actionGroup ref="ClickPlaceOrderActionGroup" stepKey="clickOnPlaceOrder"/> + + <!-- Assert empty Mini Cart --> + <seeElement selector="{{StorefrontMiniCartSection.emptyMiniCart}}" stepKey="assertEmptyCart" /> + <grabTextFrom selector="{{CheckoutSuccessMainSection.orderNumberWithoutLink}}" stepKey="orderId"/> + + <!-- Open Order Index Page --> + <amOnPage url="{{AdminOrdersPage.url}}" stepKey="goToOrders"/> + <waitForPageLoad stepKey="waitForPageLoad"/> + + <!-- Filter Order using orderId and assert order--> + <actionGroup ref="filterOrderGridById" stepKey="filterOrderGridById"> + <argument name="orderId" value="$orderId"/> + </actionGroup> + <click selector="{{AdminOrdersGridSection.viewLink('$orderId')}}" stepKey="clickOnViewLink"/> + <waitForPageLoad stepKey="waitForOrderPageToLoad"/> + + <!-- Assert Grand Total --> + <see selector="{{AdminOrderTotalSection.grandTotal}}" userInput="$25.00" stepKey="seeGrandTotal"/> + <see selector="{{AdminOrderDetailsInformationSection.orderStatus}}" userInput="Pending" stepKey="seeOrderStatus"/> + + <!-- Ship the order and assert the status --> + <actionGroup ref="AdminShipThePendingOrderActionGroup" stepKey="shipTheOrder"/> + + <!-- Assert order buttons --> + <actionGroup ref="AdminAssertOrderAvailableButtonsActionGroup" stepKey="assertOrderButtons"/> + </test> +</tests> \ No newline at end of file diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontFillBillingAddressActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontFillBillingAddressActionGroup.xml new file mode 100644 index 0000000000000..1521f8c6f1f71 --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontFillBillingAddressActionGroup.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="StorefrontFillBillingAddressActionGroup"> + <arguments> + <argument name="address" defaultValue="CustomerUKAddress"/> + </arguments> + <fillField selector="{{CheckoutPaymentSection.guestFirstName}}" userInput="{{address.firstname}}" stepKey="enterFirstName"/> + <fillField selector="{{CheckoutPaymentSection.guestLastName}}" userInput="{{address.lastname}}" stepKey="enterLastName"/> + <fillField selector="{{CheckoutPaymentSection.guestStreet}}" userInput="{{address.street[0]}}" stepKey="enterStreet"/> + <fillField selector="{{CheckoutPaymentSection.guestCity}}" userInput="{{address.city}}" stepKey="enterCity"/> + <fillField selector="{{CheckoutPaymentSection.guestPostcode}}" userInput="{{address.postcode}}" stepKey="enterPostcode"/> + <selectOption selector="{{CheckoutPaymentSection.guestCountry}}" userInput="{{address.country_id}}" stepKey="enterCountry"/> + <fillField selector="{{CheckoutPaymentSection.guestTelephone}}" userInput="{{address.telephone}}" stepKey="enterTelephone"/> + <waitForLoadingMaskToDisappear stepKey="waitForLoadingMask"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/Customer/Test/Mftf/Data/AddressData.xml b/app/code/Magento/Customer/Test/Mftf/Data/AddressData.xml index 5d1a900167144..59d0eb5507647 100755 --- a/app/code/Magento/Customer/Test/Mftf/Data/AddressData.xml +++ b/app/code/Magento/Customer/Test/Mftf/Data/AddressData.xml @@ -271,4 +271,18 @@ <data key="default_shipping">Yes</data> <requiredEntity type="region">RegionUT</requiredEntity> </entity> + <entity name="CustomerUKAddress" type="address"> + <data key="firstname">Jane</data> + <data key="lastname">Miller</data> + <data key="company">Magento</data> + <data key="telephone">44 20 7123 1234</data> + <array key="street"> + <item>1 London Bridge Street</item> + </array> + <data key="country_id">GB</data> + <data key="country">United Kingdom</data> + <data key="city">London</data> + <data key="state"></data> + <data key="postcode">SE12 9GF</data> + </entity> </entities> diff --git a/app/code/Magento/Customer/Test/Mftf/Data/CustomerConfigData.xml b/app/code/Magento/Customer/Test/Mftf/Data/CustomerConfigData.xml index 3cbd70d342824..1bb90a1a11542 100644 --- a/app/code/Magento/Customer/Test/Mftf/Data/CustomerConfigData.xml +++ b/app/code/Magento/Customer/Test/Mftf/Data/CustomerConfigData.xml @@ -21,4 +21,16 @@ <entity name="GlobalCustomerAccountSharing" type="account_share_scope_value"> <data key="value">0</data> </entity> + <entity name="EnableCustomerRedirectToDashboardConfigData"> + <data key="path">customer/startup/redirect_dashboard</data> + <data key="scope_id">0</data> + <data key="label">Yes</data> + <data key="value">1</data> + </entity> + <entity name="DisableCustomerRedirectToDashboardConfigData"> + <data key="path">customer/startup/redirect_dashboard</data> + <data key="scope_id">0</data> + <data key="label">No</data> + <data key="value">0</data> + </entity> </entities> diff --git a/app/code/Magento/Customer/Test/Mftf/Data/CustomerData.xml b/app/code/Magento/Customer/Test/Mftf/Data/CustomerData.xml index 4796fd73e104f..35065f7c876ed 100644 --- a/app/code/Magento/Customer/Test/Mftf/Data/CustomerData.xml +++ b/app/code/Magento/Customer/Test/Mftf/Data/CustomerData.xml @@ -216,4 +216,18 @@ <data key="store_id">0</data> <data key="website_id">0</data> </entity> + <entity name="UKCustomer" type="customer"> + <data key="group_id">0</data> + <data key="default_billing">true</data> + <data key="default_shipping">true</data> + <data key="email" unique="prefix">david@email.com</data> + <data key="firstname">David</data> + <data key="lastname">Mill</data> + <data key="fullname">David Mill</data> + <data key="password">pwdTest123!</data> + <data key="gender">0</data> + <data key="store_id">0</data> + <data key="website_id">0</data> + <requiredEntity type="address">updateCustomerUKAddress</requiredEntity> + </entity> </entities> diff --git a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerAddressesSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerAddressesSection.xml index aad9d02842271..52430cfb0225c 100644 --- a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerAddressesSection.xml +++ b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerAddressesSection.xml @@ -18,5 +18,7 @@ <element name="editAdditionalAddress" type="button" selector="//tbody//tr[{{var}}]//a[@class='action edit']" parameterized="true" timeout="30"/> <element name="addNewAddress" type="button" selector="//span[text()='Add New Address']"/> <element name="numberOfAddresses" type="text" selector=".toolbar-number"/> + <element name="shippingAddress" type="text" selector="//div[@class='box box-shipping-address']//div/address"/> + <element name="billingAddress" type="text" selector="//div[@class='box box-billing-address']//div/address"/> </section> </sections> diff --git a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerSignInFormSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerSignInFormSection.xml index 7bc057b8be7b7..99eb54627eb26 100644 --- a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerSignInFormSection.xml +++ b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerSignInFormSection.xml @@ -19,5 +19,6 @@ <element name="email" type="input" selector="#customer-email"/> <element name="password" type="input" selector="#pass"/> <element name="signIn" type="button" selector="#send2" timeout="30"/> + <element name="createAnAccount" type="button" selector="//div[@class='actions-toolbar']//a[contains(.,'Create an Account')]" timeout="30"/> </section> </sections> diff --git a/app/code/Magento/Payment/Test/Mftf/Data/PaymentConfigData.xml b/app/code/Magento/Payment/Test/Mftf/Data/PaymentConfigData.xml new file mode 100644 index 0000000000000..f3c27902be572 --- /dev/null +++ b/app/code/Magento/Payment/Test/Mftf/Data/PaymentConfigData.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd"> + <entity name="EnablePaymentCheckMOConfigData"> + <data key="path">payment/checkmo/active</data> + <data key="scope_id">0</data> + <data key="label">Yes</data> + <data key="value">1</data> + </entity> + <entity name="DisablePaymentCheckMOConfigData"> + <data key="path">payment/checkmo/active</data> + <data key="scope_id">0</data> + <data key="label">No</data> + <data key="value">0</data> + </entity> + <entity name="EnablePaymentBankTransferConfigData"> + <data key="path">payment/banktransfer/active</data> + <data key="scope_id">0</data> + <data key="label">Yes</data> + <data key="value">1</data> + </entity> + <entity name="DisablePaymentBankTransferConfigData"> + <data key="path">payment/banktransfer/active</data> + <data key="scope_id">0</data> + <data key="label">No</data> + <data key="value">0</data> + </entity> +</entities> diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAssertOrderAvailableButtonsActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAssertOrderAvailableButtonsActionGroup.xml new file mode 100644 index 0000000000000..39520fd9ec2e1 --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAssertOrderAvailableButtonsActionGroup.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminAssertOrderAvailableButtonsActionGroup"> + <seeElement selector="{{AdminOrderDetailsMainActionsSection.back}}" stepKey="seeBackButton"/> + <seeElement selector="{{AdminOrderDetailsMainActionsSection.cancel}}" stepKey="seeCancelButton"/> + <seeElement selector="{{AdminOrderDetailsMainActionsSection.sendEmail}}" stepKey="seeSendEmailButton"/> + <seeElement selector="{{AdminOrderDetailsMainActionsSection.hold}}" stepKey="seeHoldButton"/> + <seeElement selector="{{AdminOrderDetailsMainActionsSection.invoice}}" stepKey="seeInvoiceButton"/> + <seeElement selector="{{AdminOrderDetailsMainActionsSection.reorder}}" stepKey="seeReorderButton"/> + <seeElement selector="{{AdminOrderDetailsMainActionsSection.edit}}" stepKey="seeEditButton"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOrderActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOrderActionGroup.xml index 0e09f3933c1aa..c6c9f21a40144 100644 --- a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOrderActionGroup.xml +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOrderActionGroup.xml @@ -281,6 +281,15 @@ <see selector="{{AdminOrderAddressInformationSection.shippingAddress}}" userInput="{{shippingAddress.country_id}}" stepKey="seeShippingAddressCountry"/> <see selector="{{AdminOrderAddressInformationSection.shippingAddress}}" userInput="{{shippingAddress.postcode}}" stepKey="seeShippingAddressPostcode"/> </actionGroup> + <actionGroup name="AssertOrderAddressInformationActionGroup" extends="verifyBasicOrderInformation"> + <remove keyForRemoval="seeCustomerName"/> + <remove keyForRemoval="seeCustomerEmail"/> + <remove keyForRemoval="seeCustomerGroup"/> + <remove keyForRemoval="seeBillingAddressCountry"/> + <remove keyForRemoval="seeShippingAddressCountry"/> + <see selector="{{AdminOrderAddressInformationSection.billingAddress}}" userInput="{{billingAddress.country}}" stepKey="seeBillingCountry" after="seeBillingAddressCity"/> + <see selector="{{AdminOrderAddressInformationSection.shippingAddress}}" userInput="{{shippingAddress.country}}" stepKey="seeAddressCountry" after="seeShippingAddressCity"/> + </actionGroup> <!--Verify order information--> <actionGroup name="verifyCreatedOrderInformation"> diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminShipThePendingOrderActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminShipThePendingOrderActionGroup.xml new file mode 100644 index 0000000000000..1084bdc08bbcd --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminShipThePendingOrderActionGroup.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminShipThePendingOrderActionGroup"> + <waitForElementVisible selector="{{AdminOrderDetailsMainActionsSection.ship}}" stepKey="waitForShipTab"/> + <click selector="{{AdminOrderDetailsMainActionsSection.ship}}" stepKey="clickShipButton"/> + <waitForPageLoad stepKey="waitForShippingPageToLoad"/> + <scrollTo selector="{{AdminShipmentMainActionsSection.submitShipment}}" stepKey="scrollToSubmitShipmentButton"/> + <click selector="{{AdminShipmentMainActionsSection.submitShipment}}" stepKey="clickOnSubmitShipmentButton"/> + <waitForPageLoad stepKey="waitToProcessShippingPageToLoad"/> + <see selector="{{AdminOrderDetailsInformationSection.orderStatus}}" userInput="Processing" stepKey="seeOrderStatus"/> + <see selector="{{AdminOrderDetailsMessagesSection.successMessage}}" userInput="The shipment has been created." stepKey="seeShipmentCreateSuccess"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrdersGridSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrdersGridSection.xml index 53a6cbffcdac6..c87a1b70cb8fb 100644 --- a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrdersGridSection.xml +++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrdersGridSection.xml @@ -31,5 +31,6 @@ <element name="viewColumnCheckbox" type="checkbox" selector="//div[contains(@class,'admin__data-grid-action-columns')]//div[contains(@class, 'admin__field-option')]//label[text() = '{{column}}']/preceding-sibling::input" parameterized="true"/> <element name="customerInOrdersSection" type="button" selector="(//td[contains(text(),'{{customer}}')])[1]" parameterized="true"/> <element name="productForOrder" type="button" selector="//td[contains(text(),'{{var}}')]" parameterized="true"/> + <element name="viewLink" type="text" selector="//td/div[contains(.,'{{orderID}}')]/../..//a[@class='action-menu-item']" parameterized="true"/> </section> </sections> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Data/SalesRuleData.xml b/app/code/Magento/SalesRule/Test/Mftf/Data/SalesRuleData.xml index 74ee28de2d3fa..97995b7f7ca0a 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Data/SalesRuleData.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Data/SalesRuleData.xml @@ -241,4 +241,33 @@ <data key="apply">Percent of product price discount</data> <data key="discountAmount">50</data> </entity> + <entity name="SalesRuleSpecificCouponAndByPercent" type="SalesRule"> + <data key="name" unique="suffix">SalesRule</data> + <data key="description">Sales Rule Description</data> + <array key="website_ids"> + <item>1</item> + </array> + <array key="customer_group_ids"> + <item>0</item> + <item>1</item> + <item>2</item> + <item>3</item> + </array> + <data key="uses_per_customer">1</data> + <data key="is_active">true</data> + <data key="stop_rules_processing">false</data> + <data key="is_advanced">true</data> + <data key="sort_order">2</data> + <data key="simple_action">by_percent</data> + <data key="discount_amount">50</data> + <data key="discount_qty">1</data> + <data key="discount_step">0</data> + <data key="apply_to_shipping">false</data> + <data key="times_used">1</data> + <data key="is_rss">false</data> + <data key="coupon_type">SPECIFIC_COUPON</data> + <data key="use_auto_generation">false</data> + <data key="uses_per_coupon">2</data> + <data key="simple_free_shipping">1</data> + </entity> </entities> \ No newline at end of file diff --git a/app/code/Magento/Store/Test/Mftf/Data/StoreShippingMethodsData.xml b/app/code/Magento/Store/Test/Mftf/Data/StoreShippingMethodsData.xml index bc9746c132d4b..37687461d8db6 100644 --- a/app/code/Magento/Store/Test/Mftf/Data/StoreShippingMethodsData.xml +++ b/app/code/Magento/Store/Test/Mftf/Data/StoreShippingMethodsData.xml @@ -35,6 +35,13 @@ <data key="value">90</data> </entity> + <entity name="MinimumOrderAmount100" type="minimum_order_amount"> + <requiredEntity type="free_shipping_subtotal">Price</requiredEntity> + </entity> + <entity name="Price" type="free_shipping_subtotal"> + <data key="value">100</data> + </entity> + <entity name="DefaultMinimumOrderAmount" type="minimum_order_amount"> <requiredEntity type="free_shipping_subtotal">DefaultPrice</requiredEntity> </entity> From 4c3a8b969859b845ea1bf02962b4bd2186a0faa4 Mon Sep 17 00:00:00 2001 From: eduard13 <e.chitoraga@atwix.com> Date: Sun, 21 Apr 2019 09:28:44 +0300 Subject: [PATCH 277/773] Adjusting the grid row selector --- .../Magento/Backend/Test/Mftf/Section/AdminGridTableSection.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Backend/Test/Mftf/Section/AdminGridTableSection.xml b/app/code/Magento/Backend/Test/Mftf/Section/AdminGridTableSection.xml index 080f598480dcd..cc6476547dc80 100644 --- a/app/code/Magento/Backend/Test/Mftf/Section/AdminGridTableSection.xml +++ b/app/code/Magento/Backend/Test/Mftf/Section/AdminGridTableSection.xml @@ -10,6 +10,6 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="AdminGridTableSection"> <element name="row" type="text" selector="table.data-grid tbody tr[data-role=row]:nth-of-type({{row}})" parameterized="true"/> - <element name="rowByValue" type="text" selector="//table[@class='data-grid']//tr[@data-role='row'] //td[contains(., '{{var}}')]" parameterized="true" timeout="30"/> + <element name="rowByValue" type="text" selector="//table[@class='data-grid']//tbody//tr[@data-role='row'] //td[contains(., '{{var}}')]" parameterized="true" timeout="30"/> </section> </sections> From dfd785f5f2934a4c79262d44c4ff5543ba577b51 Mon Sep 17 00:00:00 2001 From: eduard13 <e.chitoraga@atwix.com> Date: Sun, 21 Apr 2019 09:56:06 +0300 Subject: [PATCH 278/773] Refactoring the delete action group --- ...eMainButtonWithConfirmationActionGroup.xml | 18 +++++++++++++++ .../Mftf/Section/AdminMainActionsSection.xml | 2 ++ .../AdminDeleteCustomVariableActionGroup.xml | 22 ------------------- 3 files changed, 20 insertions(+), 22 deletions(-) create mode 100644 app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminClickDeleteMainButtonWithConfirmationActionGroup.xml delete mode 100644 app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminDeleteCustomVariableActionGroup.xml diff --git a/app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminClickDeleteMainButtonWithConfirmationActionGroup.xml b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminClickDeleteMainButtonWithConfirmationActionGroup.xml new file mode 100644 index 0000000000000..17c9c2dea3652 --- /dev/null +++ b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminClickDeleteMainButtonWithConfirmationActionGroup.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminClickDeleteMainButtonWithConfirmationActionGroup"> + <waitForElementVisible selector="{{AdminMainActionsSection.delete}}" stepKey="waitForDeleteButton"/> + <click selector="{{AdminMainActionsSection.delete}}" stepKey="clickDeleteButton"/> + <waitForText userInput="Are you sure you want to do this?" stepKey="waitForText"/> + <click selector="{{AdminMainActionsSection.confirmDelete}}" stepKey="confirmDelete"/> + <waitForPageLoad stepKey="waitForPageLoad3"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Backend/Test/Mftf/Section/AdminMainActionsSection.xml b/app/code/Magento/Backend/Test/Mftf/Section/AdminMainActionsSection.xml index 4867b5ba5ae08..291f61e17a508 100644 --- a/app/code/Magento/Backend/Test/Mftf/Section/AdminMainActionsSection.xml +++ b/app/code/Magento/Backend/Test/Mftf/Section/AdminMainActionsSection.xml @@ -13,5 +13,7 @@ <element name="saveAndContinue" type="button" selector="button[id*=save_and_continue]" timeout="30"/> <element name="delete" type="button" selector="#delete" timeout="30"/> <element name="add" type="button" selector="#add" timeout="30"/> + <element name="cancelDelete" type="button" selector=".modal-popup.confirm button.action-dismiss" timeout="10"/> + <element name="confirmDelete" type="button" selector=".modal-popup.confirm button.action-accept" timeout="10"/> </section> </sections> diff --git a/app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminDeleteCustomVariableActionGroup.xml b/app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminDeleteCustomVariableActionGroup.xml deleted file mode 100644 index bbd17b2ed39e2..0000000000000 --- a/app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminDeleteCustomVariableActionGroup.xml +++ /dev/null @@ -1,22 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> - -<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="AdminDeleteCustomVariableActionGroup"> - <amOnPage url="admin/admin/system_variable/" stepKey="goToVariableGrid"/> - <waitForPageLoad stepKey="waitForPageLoad1"/> - <click selector="{{CustomVariableSection.GridCustomVariableCode(customVariable.code)}}" stepKey="goToCustomVariableEditPage"/> - <waitForPageLoad stepKey="waitForPageLoad2"/> - <waitForElementVisible selector="{{CustomVariableSection.delete}}" stepKey="waitForDeleteBtn"/> - <click selector="{{CustomVariableSection.delete}}" stepKey="deleteCustomVariable"/> - <waitForText userInput="Are you sure you want to do this?" stepKey="waitForText"/> - <click selector="{{CustomVariableSection.confirmDelete}}" stepKey="confirmDelete"/> - <waitForPageLoad stepKey="waitForPageLoad3"/> - </actionGroup> -</actionGroups> From bad978fd6cbc3fab185526eec7559f03be0eb9a1 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun <ogorkun@magento.com> Date: Mon, 22 Apr 2019 14:58:52 -0500 Subject: [PATCH 279/773] MC-13958: Additional Permissions for Design settings --- app/code/Magento/Catalog/Model/Product.php | 2 ++ .../Ui/DataProvider/Product/Form/Modifier/Eav.php | 4 ++-- app/code/Magento/Cms/Model/Page/DataProvider.php | 9 +++++++++ app/code/Magento/Cms/Model/PageRepository.php | 4 ++++ 4 files changed, 17 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Product.php b/app/code/Magento/Catalog/Model/Product.php index e9fa1616b2fd3..3170c13037bac 100644 --- a/app/code/Magento/Catalog/Model/Product.php +++ b/app/code/Magento/Catalog/Model/Product.php @@ -904,6 +904,8 @@ public function beforeSave() $this->setData('page_layout', $this->getOrigData('page_layout')); $this->setData('options_container', $this->getOrigData('options_container')); $this->setData('custom_layout_update', $this->getOrigData('custom_layout_update')); + $this->setData('custom_design_from', $this->getOrigData('custom_design_from')); + $this->setData('custom_design_to', $this->getOrigData('custom_design_to')); } $hasOptions = false; diff --git a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php index 3414da72641f5..6f60a114737b0 100755 --- a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php +++ b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php @@ -743,8 +743,8 @@ public function setupAttributeMeta(ProductAttributeInterface $attribute, $groupC } //Checking access to design config. - $designAttributeCodes = ['custom_design', 'page_layout', 'options_container', 'custom_layout_update']; - if (in_array($attributeCode, $designAttributeCodes, true)) { + $designDesignGroups = ['design', 'schedule-design-update']; + if (in_array($groupCode, $designDesignGroups, true)) { if (!$this->auth->isAllowed('Magento_Catalog::edit_product_design')) { $meta = $this->arrayManager->merge( $configPath, diff --git a/app/code/Magento/Cms/Model/Page/DataProvider.php b/app/code/Magento/Cms/Model/Page/DataProvider.php index cece4b9486bc8..64abaffd04e66 100644 --- a/app/code/Magento/Cms/Model/Page/DataProvider.php +++ b/app/code/Magento/Cms/Model/Page/DataProvider.php @@ -120,6 +120,15 @@ public function getMeta() ] ] ] + ], + 'custom_design_update' => [ + 'arguments' => [ + 'data' => [ + 'config' => [ + 'disabled' => true + ] + ] + ] ] ]; $meta = array_merge_recursive($meta, $designMeta); diff --git a/app/code/Magento/Cms/Model/PageRepository.php b/app/code/Magento/Cms/Model/PageRepository.php index 4366eef4cbe67..4b6c933c4fef1 100644 --- a/app/code/Magento/Cms/Model/PageRepository.php +++ b/app/code/Magento/Cms/Model/PageRepository.php @@ -149,12 +149,16 @@ public function save(\Magento\Cms\Api\Data\PageInterface $page) $page->setPageLayout(null); $page->setCustomTheme(null); $page->setCustomLayoutUpdateXml(null); + $page->setCustomThemeTo(null); + $page->setCustomThemeFrom(null); } else { $savedPage = $this->getById($page->getId()); $page->setLayoutUpdateXml($savedPage->getLayoutUpdateXml()); $page->setPageLayout($savedPage->getPageLayout()); $page->setCustomTheme($savedPage->getCustomTheme()); $page->setCustomLayoutUpdateXml($savedPage->getCustomLayoutUpdateXml()); + $page->setCustomThemeTo($savedPage->getCustomThemeTo()); + $page->setCustomThemeFrom($savedPage->getCustomThemeFrom()); } } From 49a22591d1793a06dc6fc9337f9b0da87187d18a Mon Sep 17 00:00:00 2001 From: Kavitha <kanair@adobe.com> Date: Mon, 22 Apr 2019 16:30:51 -0500 Subject: [PATCH 280/773] MC-4459: Convert OnePageCheckoutOfflinePaymentMethodsTest to MFTF --- .../Mftf/Data/CatalogInventryConfigData.xml | 4 ++-- ...orefrontCustomerSignInPopUpActionGroup.xml | 1 - ...gisterCustomerAfterCheckoutActionGroup.xml | 6 +++--- .../Mftf/Section/CheckoutPaymentSection.xml | 2 +- ...ingAddressAndProductWithTierPricesTest.xml | 19 ++++++++++--------- ...ssAndRegisterCustomerAfterCheckoutTest.xml | 7 +++---- ...OnLoginWhenGuestCheckoutIsDisabledTest.xml | 14 ++++++++------ ...egistrationAndDisableGuestCheckoutTest.xml | 12 ++++++------ ...ngesInBackendAfterCustomerCheckoutTest.xml | 8 ++++---- ...efrontUKCustomerCheckoutWithCouponTest.xml | 2 ++ ...CouponAndBankTransferPaymentMethodTest.xml | 6 +++--- 11 files changed, 42 insertions(+), 39 deletions(-) diff --git a/app/code/Magento/CatalogInventory/Test/Mftf/Data/CatalogInventryConfigData.xml b/app/code/Magento/CatalogInventory/Test/Mftf/Data/CatalogInventryConfigData.xml index c48631a8d03c1..35dc1919c8e4a 100644 --- a/app/code/Magento/CatalogInventory/Test/Mftf/Data/CatalogInventryConfigData.xml +++ b/app/code/Magento/CatalogInventory/Test/Mftf/Data/CatalogInventryConfigData.xml @@ -8,14 +8,14 @@ <entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd"> - <entity name="EnableCatalogInventoryConfigData"> + <entity name="CatalogInventoryOptionsCanSubtractEnable"> <!--Default Value --> <data key="path">cataloginventory/options/can_subtract</data> <data key="scope_id">0</data> <data key="label">Yes</data> <data key="value">1</data> </entity> - <entity name="DisableCatalogInventoryConfigData"> + <entity name="CatalogInventoryOptionsCanSubtractDisable"> <data key="path">cataloginventory/options/can_subtract</data> <data key="scope_id">0</data> <data key="label">No</data> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCustomerSignInPopUpActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCustomerSignInPopUpActionGroup.xml index 627ca6237017a..8139ac1f7929b 100644 --- a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCustomerSignInPopUpActionGroup.xml +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCustomerSignInPopUpActionGroup.xml @@ -17,7 +17,6 @@ <fillField stepKey="fillEmail" userInput="{{customerEmail}}" selector="{{StorefrontCustomerSignInPopupFormSection.email}}"/> <fillField stepKey="fillPassword" userInput="{{customerPwd}}" selector="{{StorefrontCustomerSignInPopupFormSection.password}}"/> <click stepKey="clickSignInAccountButton" selector="{{StorefrontCustomerSignInPopupFormSection.signIn}}"/> - <click selector="{{CheckoutCartSummarySection.proceedToCheckout}}" stepKey="goToCheckout"/> <waitForPageLoad stepKey="waitForPageToLoad"/> </actionGroup> </actionGroups> \ No newline at end of file diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontRegisterCustomerAfterCheckoutActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontRegisterCustomerAfterCheckoutActionGroup.xml index b72c63668edf2..7546e04759503 100644 --- a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontRegisterCustomerAfterCheckoutActionGroup.xml +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontRegisterCustomerAfterCheckoutActionGroup.xml @@ -10,11 +10,11 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="StorefrontRegisterCustomerAfterCheckoutActionGroup"> <arguments> - <argument name="customerPassword" defaultValue="UKCustomer"/> + <argument name="customerPassword" defaultValue="UKCustomer.password" type="string"/> </arguments> <click selector="{{CheckoutSuccessRegisterSection.createAccountButton}}" stepKey="clickOnCreateAnAccountButton"/> - <fillField selector="{{StorefrontCustomerAccountInformationSection.newPassword}}" userInput="{{customerPassword.password}}" stepKey="fillPassword"/> - <fillField selector="{{StorefrontCustomerAccountInformationSection.confirmNewPassword}}" userInput="{{customerPassword.password}}" stepKey="reconfirmPassword"/> + <fillField selector="{{StorefrontCustomerAccountInformationSection.newPassword}}" userInput="{{customerPassword}}" stepKey="fillPassword"/> + <fillField selector="{{StorefrontCustomerAccountInformationSection.confirmNewPassword}}" userInput="{{customerPassword}}" stepKey="reconfirmPassword"/> <click selector="{{StorefrontCustomerCreateFormSection.createAccountButton}}" stepKey="clickOnCreateAnAccount"/> <seeElement selector="{{StorefrontCustomerMessagesSection.successMessage}}" stepKey="seeSuccessMessage1"/> </actionGroup> diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutPaymentSection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutPaymentSection.xml index 0dc88506027d6..fc19eca9ec523 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutPaymentSection.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutPaymentSection.xml @@ -55,7 +55,7 @@ <element name="addressBook" type="button" selector="//a[text()='Address Book']"/> <element name="noQuotes" type="text" selector=".no-quotes-block"/> <element name="paymentMethodByName" type="text" selector="//*[@id='checkout-payment-method-load']//*[contains(@class, 'payment-group')]//label[normalize-space(.)='{{var1}}']" parameterized="true"/> - <element name="checkBankTransferPayment" type="radio" selector="//input[@id='banktransfer']"/> + <element name="bankTransfer" type="radio" selector="//input[@id='banktransfer']"/> <element name="billingAddressNotSameBankTransferCheckbox" type="checkbox" selector="#billing-address-same-as-shipping-banktransfer"/> </section> </sections> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckoutWithDifferentShippingAndBillingAddressAndProductWithTierPricesTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckoutWithDifferentShippingAndBillingAddressAndProductWithTierPricesTest.xml index f7365dd8522a7..c5d1c34a93b32 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckoutWithDifferentShippingAndBillingAddressAndProductWithTierPricesTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckoutWithDifferentShippingAndBillingAddressAndProductWithTierPricesTest.xml @@ -18,7 +18,8 @@ </annotations> <before> - <magentoCLI command="config:set {{EnablePaymentBankTransferConfigData.path}} {{EnablePaymentBankTransferConfigData.value}}" stepKey="enableBankTransferPayment"/> <actionGroup ref="LoginAsAdmin" stepKey="loginToAdminPanel"/> + <magentoCLI command="config:set {{EnablePaymentBankTransferConfigData.path}} {{EnablePaymentBankTransferConfigData.value}}" stepKey="enableBankTransferPayment"/> + <actionGroup ref="LoginAsAdmin" stepKey="loginToAdminPanel"/> <createData entity="SimpleProduct2" stepKey="simpleProduct"> <field key="price">50.00</field> </createData> @@ -35,12 +36,16 @@ <magentoCLI command="cache:flush" stepKey="flushCache"/> </before> <after> + <magentoCLI command="config:set {{DisablePaymentBankTransferConfigData.path}} {{DisablePaymentBankTransferConfigData.value}}" stepKey="enableGuestCheckout"/> + + <!-- Sign out Customer from storefront --> + <actionGroup ref="StorefrontOpenHomePageActionGroup" stepKey="openHomePage"/> + <actionGroup ref="StorefrontSignOutActionGroup" stepKey="customerLogout"/> <deleteData createDataKey="simpleProduct" stepKey="deleteProduct"/> <actionGroup ref="AdminDeleteCustomerActionGroup" stepKey="deleteCustomer"> <argument name="customerEmail" value="UKCustomer.email"/> </actionGroup> <actionGroup ref="logout" stepKey="logout"/> - <magentoCLI command="config:set {{DisablePaymentBankTransferConfigData.path}} {{DisablePaymentBankTransferConfigData.value}}" stepKey="enableGuestCheckout"/> </after> <!--Open Product page in StoreFront and assert product and price range --> @@ -68,8 +73,8 @@ </actionGroup> <waitForElementVisible selector="{{CheckoutShippingMethodsSection.next}}" stepKey="waitForNextButton"/> <click selector="{{CheckoutShippingMethodsSection.next}}" stepKey="clickOnNextButton"/> - <waitForElementVisible selector="{{CheckoutPaymentSection.checkBankTransferPayment}}" stepKey="waitForPlaceOrderButton"/> - <checkOption selector="{{CheckoutPaymentSection.checkBankTransferPayment}}" stepKey="selectBankTransfer"/> + <waitForElementVisible selector="{{CheckoutPaymentSection.bankTransfer}}" stepKey="waitForPlaceOrderButton"/> + <checkOption selector="{{CheckoutPaymentSection.bankTransfer}}" stepKey="selectBankTransfer"/> <waitForElementVisible selector="{{CheckoutPaymentSection.billingAddressNotSameBankTransferCheckbox}}" stepKey="waitForElementToBeVisible"/> <uncheckOption selector="{{CheckoutPaymentSection.billingAddressNotSameBankTransferCheckbox}}" stepKey="uncheckSameBillingAndShippingAddress"/> <conditionalClick selector="{{CheckoutShippingSection.editActiveAddressButton}}" dependentSelector="{{CheckoutShippingSection.editActiveAddressButton}}" visible="true" stepKey="clickEditButton"/> @@ -95,7 +100,7 @@ <see selector="{{StorefrontCustomerAddressesSection.billingAddress}}" userInput="{{CustomerUKAddress.country}}" stepKey="seeCountryInBillingAddress"/> <see selector="{{StorefrontCustomerAddressesSection.billingAddress}}" userInput="T: {{CustomerUKAddress.telephone}}" stepKey="seeTelephoneInBillingAddress"/> - <!-- Assert Billing Address in Storefront --> + <!-- Assert Shipping Address in Storefront --> <see selector="{{StorefrontCustomerAddressesSection.shippingAddress}}" userInput="{{updateCustomerUKAddress.street[0]}}" stepKey="seeStreetNameInShippingAddress"/> <see selector="{{StorefrontCustomerAddressesSection.shippingAddress}}" userInput="{{updateCustomerUKAddress.city}}" stepKey="seeCityInShippingAddress"/> <see selector="{{StorefrontCustomerAddressesSection.shippingAddress}}" userInput="{{updateCustomerUKAddress.country}}" stepKey="seeCountryInShippingAddress"/> @@ -121,9 +126,5 @@ <!-- Assert order buttons --> <actionGroup ref="AdminAssertOrderAvailableButtonsActionGroup" stepKey="assertOrderButtons"/> - - <!-- Sign out Customer from storefront --> - <actionGroup ref="StorefrontOpenHomePageActionGroup" stepKey="openHomePage"/> - <actionGroup ref="StorefrontSignOutActionGroup" stepKey="customerLogout"/> </test> </tests> \ No newline at end of file diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckoutWithDifferentShippingAndBillingAddressAndRegisterCustomerAfterCheckoutTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckoutWithDifferentShippingAndBillingAddressAndRegisterCustomerAfterCheckoutTest.xml index c52e8b73b262e..34dc6617d25d5 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckoutWithDifferentShippingAndBillingAddressAndRegisterCustomerAfterCheckoutTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckoutWithDifferentShippingAndBillingAddressAndRegisterCustomerAfterCheckoutTest.xml @@ -24,6 +24,9 @@ </createData> </before> <after> + <!-- Sign out Customer from storefront --> + <actionGroup ref="StorefrontOpenHomePageActionGroup" stepKey="openHomePage"/> + <actionGroup ref="StorefrontSignOutActionGroup" stepKey="customerLogout"/> <deleteData createDataKey="simpleProduct" stepKey="deleteProduct"/> <actionGroup ref="AdminDeleteCustomerActionGroup" stepKey="deleteCustomer"> <argument name="customerEmail" value="UKCustomer.email"/> @@ -94,9 +97,5 @@ <!-- Assert order buttons --> <actionGroup ref="AdminAssertOrderAvailableButtonsActionGroup" stepKey="assertOrderButtons"/> - - <!-- Sign out Customer from storefront --> - <actionGroup ref="StorefrontOpenHomePageActionGroup" stepKey="openHomePage"/> - <actionGroup ref="StorefrontSignOutActionGroup" stepKey="customerLogout"/> </test> </tests> \ No newline at end of file diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerCheckoutOnLoginWhenGuestCheckoutIsDisabledTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerCheckoutOnLoginWhenGuestCheckoutIsDisabledTest.xml index 4d205e0d40490..b0b72515611e8 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerCheckoutOnLoginWhenGuestCheckoutIsDisabledTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerCheckoutOnLoginWhenGuestCheckoutIsDisabledTest.xml @@ -27,10 +27,14 @@ <createData entity="Simple_US_Customer" stepKey="createCustomer"/> </before> <after> - <deleteData createDataKey="simpleProduct" stepKey="deleteProduct"/> - <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> <magentoCLI command="config:set {{EnableGuestCheckoutConfigData.path}} {{EnableGuestCheckoutConfigData.value}}" stepKey="enableGuestCheckout"/> <magentoCLI command="config:set {{EnableCustomerRedirectToDashboardConfigData.path}} {{EnableCustomerRedirectToDashboardConfigData.value}}" stepKey="enableCustomerRedirect"/> + + <!-- Sign out Customer from storefront --> + <actionGroup ref="StorefrontOpenHomePageActionGroup" stepKey="openHomePage"/> + <actionGroup ref="StorefrontSignOutActionGroup" stepKey="customerLogout"/> + <deleteData createDataKey="simpleProduct" stepKey="deleteProduct"/> + <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> <actionGroup ref="logout" stepKey="logout"/> </after> @@ -56,6 +60,8 @@ <argument name="customerEmail" value="$$createCustomer.email$$"/> <argument name="customerPwd" value="$$createCustomer.password$$"/> </actionGroup> + <click selector="{{CheckoutCartSummarySection.proceedToCheckout}}" stepKey="goToCheckout1"/> + <waitForPageLoad stepKey="waitForShippingMethodSectionToLoad"/> <waitForElementVisible selector="{{CheckoutShippingMethodsSection.next}}" stepKey="waitForNextButton"/> <click selector="{{CheckoutShippingMethodsSection.next}}" stepKey="clickOnNextButton"/> @@ -84,9 +90,5 @@ <!-- Ship the order and assert the shipping status --> <actionGroup ref="AdminShipThePendingOrderActionGroup" stepKey="shipTheOrder"/> - - <!-- Sign out Customer from storefront --> - <actionGroup ref="StorefrontOpenHomePageActionGroup" stepKey="openHomePage"/> - <actionGroup ref="StorefrontSignOutActionGroup" stepKey="customerLogout"/> </test> </tests> \ No newline at end of file diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerCheckoutWithNewCustomerRegistrationAndDisableGuestCheckoutTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerCheckoutWithNewCustomerRegistrationAndDisableGuestCheckoutTest.xml index b523a6e3b9e6a..f7e54867b1ae4 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerCheckoutWithNewCustomerRegistrationAndDisableGuestCheckoutTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerCheckoutWithNewCustomerRegistrationAndDisableGuestCheckoutTest.xml @@ -27,10 +27,14 @@ <createData entity="Simple_US_Customer" stepKey="createCustomer"/> </before> <after> - <deleteData createDataKey="simpleProduct" stepKey="deleteProduct"/> - <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> <magentoCLI command="config:set {{EnableGuestCheckoutConfigData.path}} {{EnableGuestCheckoutConfigData.value}}" stepKey="enableGuestCheckout"/> <magentoCLI command="config:set {{EnableCustomerRedirectToDashboardConfigData.path}} {{EnableCustomerRedirectToDashboardConfigData.value}}" stepKey="enableCustomerRedirect"/> + + <!-- Sign out Customer from storefront --> + <actionGroup ref="StorefrontOpenHomePageActionGroup" stepKey="openHomePage"/> + <actionGroup ref="StorefrontSignOutActionGroup" stepKey="customerLogout"/> + <deleteData createDataKey="simpleProduct" stepKey="deleteProduct"/> + <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> <actionGroup ref="logout" stepKey="logout"/> </after> @@ -124,9 +128,5 @@ <!-- Ship the order and assert the shipping status --> <actionGroup ref="AdminShipThePendingOrderActionGroup" stepKey="shipTheOrder"/> - - <!-- Sign out Customer from storefront --> - <actionGroup ref="StorefrontOpenHomePageActionGroup" stepKey="openHomePage"/> - <actionGroup ref="StorefrontSignOutActionGroup" stepKey="customerLogout"/> </test> </tests> \ No newline at end of file diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontProductQuantityChangesInBackendAfterCustomerCheckoutTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontProductQuantityChangesInBackendAfterCustomerCheckoutTest.xml index e5f6c52e445c5..b963fb9ae8f64 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontProductQuantityChangesInBackendAfterCustomerCheckoutTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontProductQuantityChangesInBackendAfterCustomerCheckoutTest.xml @@ -20,14 +20,14 @@ <before> <actionGroup ref="LoginAsAdmin" stepKey="loginToAdminPanel"/> <magentoCLI command="config:set {{EnablePaymentBankTransferConfigData.path}} {{EnablePaymentBankTransferConfigData.value}}" stepKey="enableBankTransferPayment"/> - <magentoCLI command="config:set {{EnableCatalogInventoryConfigData.path}} {{EnableCatalogInventoryConfigData.value}}" stepKey="enableCatalogInventoryStock"/> + <magentoCLI command="config:set {{CatalogInventoryOptionsCanSubtractEnable.path}} {{CatalogInventoryOptionsCanSubtractEnable.value}}" stepKey="enableCatalogInventoryStock"/> <createData entity="defaultSimpleProduct" stepKey="simpleProduct"> <field key="price">10.00</field> </createData> </before> <after> - <deleteData createDataKey="simpleProduct" stepKey="deleteProduct"/> <magentoCLI command="config:set {{DisablePaymentBankTransferConfigData.path}} {{DisablePaymentBankTransferConfigData.value}}" stepKey="enableGuestCheckout"/> + <deleteData createDataKey="simpleProduct" stepKey="deleteProduct"/> <actionGroup ref="logout" stepKey="logout"/> </after> @@ -56,8 +56,8 @@ </actionGroup> <waitForElementVisible selector="{{CheckoutShippingMethodsSection.next}}" stepKey="waitForNextButton"/> <click selector="{{CheckoutShippingMethodsSection.next}}" stepKey="clickOnNextButton"/> - <waitForElementVisible selector="{{CheckoutPaymentSection.checkBankTransferPayment}}" stepKey="waitForPlaceOrderButton"/> - <click selector="{{CheckoutPaymentSection.checkBankTransferPayment}}" stepKey="selectBankTransfer"/> + <waitForElementVisible selector="{{CheckoutPaymentSection.bankTransfer}}" stepKey="waitForPlaceOrderButton"/> + <click selector="{{CheckoutPaymentSection.bankTransfer}}" stepKey="selectBankTransfer"/> <!-- Place order and Assert success message --> <actionGroup ref="ClickPlaceOrderActionGroup" stepKey="clickOnPlaceOrder"/> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontUKCustomerCheckoutWithCouponTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontUKCustomerCheckoutWithCouponTest.xml index 0e5d50df0fb3a..ebf24e710fe39 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontUKCustomerCheckoutWithCouponTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontUKCustomerCheckoutWithCouponTest.xml @@ -83,6 +83,8 @@ <argument name="customerEmail" value="$$createCustomer.email$$"/> <argument name="customerPwd" value="$$createCustomer.password$$"/> </actionGroup> + <click selector="{{CheckoutCartSummarySection.proceedToCheckout}}" stepKey="goToCheckout1"/> + <waitForPageLoad stepKey="waitForShippingMethodSectionToLoad"/> <!-- Click and open order summary tab--> <conditionalClick selector="{{CheckoutOrderSummarySection.miniCartTab}}" dependentSelector="{{CheckoutOrderSummarySection.miniCartTabClosed}}" visible="true" stepKey="clickOnOrderSummaryTab"/> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontUSCustomerCheckoutWithCouponAndBankTransferPaymentMethodTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontUSCustomerCheckoutWithCouponAndBankTransferPaymentMethodTest.xml index 72b124ca0d005..6d5f79f3aadf4 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontUSCustomerCheckoutWithCouponAndBankTransferPaymentMethodTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontUSCustomerCheckoutWithCouponAndBankTransferPaymentMethodTest.xml @@ -29,9 +29,9 @@ </createData> </before> <after> + <magentoCLI command="config:set {{DisablePaymentBankTransferConfigData.path}} {{DisablePaymentBankTransferConfigData.value}}" stepKey="disableBankTransferPayment"/> <deleteData createDataKey="simpleProduct" stepKey="deleteProduct"/> <deleteData createDataKey="createSalesRule" stepKey="deleteSalesRule"/> - <magentoCLI command="config:set {{DisablePaymentBankTransferConfigData.path}} {{DisablePaymentBankTransferConfigData.value}}" stepKey="disableBankTransferPayment"/> <actionGroup ref="logout" stepKey="logout"/> </after> @@ -63,8 +63,8 @@ <actionGroup ref="FillGuestCheckoutShippingAddressFormActionGroup" stepKey="fillGuestForm"/> <waitForElementVisible selector="{{CheckoutShippingMethodsSection.next}}" stepKey="waitForNextButton"/> <click selector="{{CheckoutShippingMethodsSection.next}}" stepKey="clickOnNextButton"/> - <waitForElementVisible selector="{{CheckoutPaymentSection.checkBankTransferPayment}}" stepKey="waitForPlaceOrderButton"/> - <checkOption selector="{{CheckoutPaymentSection.checkBankTransferPayment}}" stepKey="selectBankTransfer"/> + <waitForElementVisible selector="{{CheckoutPaymentSection.bankTransfer}}" stepKey="waitForPlaceOrderButton"/> + <checkOption selector="{{CheckoutPaymentSection.bankTransfer}}" stepKey="selectBankTransfer"/> <!-- Place order and Assert success message --> <actionGroup ref="ClickPlaceOrderActionGroup" stepKey="clickOnPlaceOrder"/> From 1988de33c2d7eb68b8d7bc43f6a50e4b5bc73b6a Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun <ogorkun@magento.com> Date: Mon, 22 Apr 2019 17:31:50 -0500 Subject: [PATCH 281/773] MC-13958: Additional Permissions for Design settings --- app/code/Magento/Catalog/Model/Category.php | 1 + app/code/Magento/Catalog/Model/Category/DataProvider.php | 1 + app/code/Magento/Catalog/Model/Product.php | 1 + 3 files changed, 3 insertions(+) diff --git a/app/code/Magento/Catalog/Model/Category.php b/app/code/Magento/Catalog/Model/Category.php index 5a4bec34b2e20..05847377b80f5 100644 --- a/app/code/Magento/Catalog/Model/Category.php +++ b/app/code/Magento/Catalog/Model/Category.php @@ -339,6 +339,7 @@ protected function getCustomAttributesCodes() */ protected function _getResource() { + //phpcs:ignore Generic.CodeAnalysis.UselessOverridingMethod return parent::_getResource(); } diff --git a/app/code/Magento/Catalog/Model/Category/DataProvider.php b/app/code/Magento/Catalog/Model/Category/DataProvider.php index 2e0e71003beab..e4423c02fbaa3 100644 --- a/app/code/Magento/Catalog/Model/Category/DataProvider.php +++ b/app/code/Magento/Catalog/Model/Category/DataProvider.php @@ -519,6 +519,7 @@ private function convertValues($category, $categoryData) $stat = $fileInfo->getStat($fileName); $mime = $fileInfo->getMimeType($fileName); + //phpcs:ignore Generic.PHP.ForbiddenFunctions $categoryData[$attributeCode][0]['name'] = basename($fileName); if ($fileInfo->isBeginsWithMediaDirectoryPath($fileName)) { diff --git a/app/code/Magento/Catalog/Model/Product.php b/app/code/Magento/Catalog/Model/Product.php index 3170c13037bac..68afdb17a9563 100644 --- a/app/code/Magento/Catalog/Model/Product.php +++ b/app/code/Magento/Catalog/Model/Product.php @@ -512,6 +512,7 @@ protected function _construct() */ protected function _getResource() { + //phpcs:ignore Generic.CodeAnalysis.UselessOverridingMethod return parent::_getResource(); } From 23f9442b2fde6e53974498c3eb9c1470a512e835 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun <ogorkun@magento.com> Date: Tue, 23 Apr 2019 12:18:24 -0500 Subject: [PATCH 282/773] MC-13958: Additional Permissions for Design settings --- app/code/Magento/Catalog/Model/Category.php | 3 ++- app/code/Magento/Catalog/Model/Category/DataProvider.php | 2 +- app/code/Magento/Catalog/Model/Product.php | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Category.php b/app/code/Magento/Catalog/Model/Category.php index 05847377b80f5..b864b7fdafad2 100644 --- a/app/code/Magento/Catalog/Model/Category.php +++ b/app/code/Magento/Catalog/Model/Category.php @@ -330,6 +330,7 @@ protected function getCustomAttributesCodes() return $this->customAttributesCodes; } + // phpcs:disable Generic.CodeAnalysis.UselessOverridingMethod /** * Returns model resource * @@ -339,9 +340,9 @@ protected function getCustomAttributesCodes() */ protected function _getResource() { - //phpcs:ignore Generic.CodeAnalysis.UselessOverridingMethod return parent::_getResource(); } + // phpcs:enable /** * Get flat resource model flag diff --git a/app/code/Magento/Catalog/Model/Category/DataProvider.php b/app/code/Magento/Catalog/Model/Category/DataProvider.php index e4423c02fbaa3..174c90ae1635c 100644 --- a/app/code/Magento/Catalog/Model/Category/DataProvider.php +++ b/app/code/Magento/Catalog/Model/Category/DataProvider.php @@ -519,7 +519,7 @@ private function convertValues($category, $categoryData) $stat = $fileInfo->getStat($fileName); $mime = $fileInfo->getMimeType($fileName); - //phpcs:ignore Generic.PHP.ForbiddenFunctions + // phpcs:ignore Magento2.Functions.DiscouragedFunction $categoryData[$attributeCode][0]['name'] = basename($fileName); if ($fileInfo->isBeginsWithMediaDirectoryPath($fileName)) { diff --git a/app/code/Magento/Catalog/Model/Product.php b/app/code/Magento/Catalog/Model/Product.php index 68afdb17a9563..af8401d3df1a9 100644 --- a/app/code/Magento/Catalog/Model/Product.php +++ b/app/code/Magento/Catalog/Model/Product.php @@ -503,6 +503,7 @@ protected function _construct() $this->_init(\Magento\Catalog\Model\ResourceModel\Product::class); } + // phpcs:disable Generic.CodeAnalysis.UselessOverridingMethod /** * Get resource instance * @@ -512,9 +513,9 @@ protected function _construct() */ protected function _getResource() { - //phpcs:ignore Generic.CodeAnalysis.UselessOverridingMethod return parent::_getResource(); } + // phpcs:enable /** * Get a list of custom attribute codes that belongs to product attribute set. From b7baf25ebe63a0c47abbacde1939dff2ec02ed2b Mon Sep 17 00:00:00 2001 From: Oleksandr Miroshnichenko <omiroshnichenko@magento.com> Date: Tue, 23 Apr 2019 16:02:39 -0500 Subject: [PATCH 283/773] MC-5843: Add Argon2ID support --- .../Command/UpgradeHashAlgorithmCommand.php | 7 +- .../Framework/Encryption/Encryptor.php | 78 +++++++++++++++++-- 2 files changed, 77 insertions(+), 8 deletions(-) diff --git a/app/code/Magento/Customer/Console/Command/UpgradeHashAlgorithmCommand.php b/app/code/Magento/Customer/Console/Command/UpgradeHashAlgorithmCommand.php index dd8dec0b94c15..0632a5970ceb4 100644 --- a/app/code/Magento/Customer/Console/Command/UpgradeHashAlgorithmCommand.php +++ b/app/code/Magento/Customer/Console/Command/UpgradeHashAlgorithmCommand.php @@ -65,8 +65,11 @@ protected function execute(InputInterface $input, OutputInterface $output) $customer->load($customer->getId()); if (!$this->encryptor->validateHashVersion($customer->getPasswordHash())) { list($hash, $salt, $version) = explode(Encryptor::DELIMITER, $customer->getPasswordHash(), 3); - $version .= Encryptor::DELIMITER . Encryptor::HASH_VERSION_LATEST; - $customer->setPasswordHash($this->encryptor->getHash($hash, $salt, $version)); + $version .= Encryptor::DELIMITER . $this->encryptor->getLatestHashVersion(); + $hash = $this->encryptor->getHash($hash, $salt, $this->encryptor->getLatestHashVersion()); + list($hash, $salt) = explode(Encryptor::DELIMITER, $hash, 3); + $hash = implode(Encryptor::DELIMITER, [$hash, $salt, $version]); + $customer->setPasswordHash($hash); $customer->save(); $output->write("."); } diff --git a/lib/internal/Magento/Framework/Encryption/Encryptor.php b/lib/internal/Magento/Framework/Encryption/Encryptor.php index 791e6d72b951f..5eb4785e1fa8a 100644 --- a/lib/internal/Magento/Framework/Encryption/Encryptor.php +++ b/lib/internal/Magento/Framework/Encryption/Encryptor.php @@ -31,10 +31,17 @@ class Encryptor implements EncryptorInterface */ const HASH_VERSION_SHA256 = 1; + /** + * Key of sha256 algorithm + */ + const HASH_VERSION_ARGON2ID13 = 2; + /** * Key of latest used algorithm + * @deprecated + * @see \Magento\Framework\Encryption\Encryptor::getLatestHashVersion */ - const HASH_VERSION_LATEST = 1; + const HASH_VERSION_LATEST = 2; /** * Default length of salt in bytes @@ -138,6 +145,20 @@ public function __construct( $this->keys = preg_split('/\s+/s', trim((string)$deploymentConfig->get(self::PARAM_CRYPT_KEY))); $this->keyVersion = count($this->keys) - 1; $this->keyValidator = $keyValidator ?: ObjectManager::getInstance()->get(KeyValidator::class); + $latestHashVersion = $this->getLatestHashVersion(); + if ($latestHashVersion === self::HASH_VERSION_ARGON2ID13) { + $this->hashVersionMap[self::HASH_VERSION_ARGON2ID13] = SODIUM_CRYPTO_PWHASH_ALG_ARGON2ID13; + } + } + + + public function getLatestHashVersion() + { + if (extension_loaded('sodium')) { + return self::HASH_VERSION_ARGON2ID13; + } + + return self::HASH_VERSION_SHA256; } /** @@ -170,20 +191,39 @@ public function validateCipher($version) */ public function getHash($password, $salt = false, $version = self::HASH_VERSION_LATEST) { + if (!isset($this->hashVersionMap[$version])) { + $version = self::HASH_VERSION_SHA256; + } + if ($salt === false) { return $this->hash($password, $version); } if ($salt === true) { - $salt = self::DEFAULT_SALT_LENGTH; + $salt = $version === self::HASH_VERSION_ARGON2ID13 ? + SODIUM_CRYPTO_PWHASH_SALTBYTES : + self::DEFAULT_SALT_LENGTH; } if (is_integer($salt)) { $salt = $this->random->getRandomString($salt); } + if ($version === self::HASH_VERSION_ARGON2ID13) { + $hash = bin2hex(sodium_crypto_pwhash( + SODIUM_CRYPTO_SIGN_SEEDBYTES, + $password, + substr($salt, 0, SODIUM_CRYPTO_PWHASH_SALTBYTES), + SODIUM_CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE, + SODIUM_CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE, + $this->hashVersionMap[self::HASH_VERSION_ARGON2ID13] + )); + } else { + $hash = $this->hash($salt . $password, $version); + } + return implode( self::DELIMITER, [ - $this->hash($salt . $password, $version), + $hash, $salt, $version ] @@ -195,6 +235,21 @@ public function getHash($password, $salt = false, $version = self::HASH_VERSION_ */ public function hash($data, $version = self::HASH_VERSION_LATEST) { + if (!isset($this->hashVersionMap[$version])) { + $version = self::HASH_VERSION_SHA256; + } + + if ($version === self::HASH_VERSION_ARGON2ID13) { + return bin2hex(sodium_crypto_pwhash( + SODIUM_CRYPTO_SIGN_SEEDBYTES, + $data, + random_bytes(SODIUM_CRYPTO_PWHASH_SALTBYTES), + SODIUM_CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE, + SODIUM_CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE, + $this->hashVersionMap[self::HASH_VERSION_ARGON2ID13] + )); + } + return hash($this->hashVersionMap[$version], (string)$data); } @@ -214,7 +269,18 @@ public function isValidHash($password, $hash) $this->explodePasswordHash($hash); foreach ($this->getPasswordVersion() as $hashVersion) { - $password = $this->hash($this->getPasswordSalt() . $password, $hashVersion); + if ($hashVersion === self::HASH_VERSION_ARGON2ID13) { + $password = bin2hex(sodium_crypto_pwhash( + SODIUM_CRYPTO_SIGN_SEEDBYTES, + $password, + substr($this->getPasswordSalt(), 0, SODIUM_CRYPTO_PWHASH_SALTBYTES), + SODIUM_CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE, + SODIUM_CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE, + $this->hashVersionMap[self::HASH_VERSION_ARGON2ID13] + )); + } else { + $password = $this->hash($this->getPasswordSalt() . $password, $hashVersion); + } } return Security::compareStrings( @@ -232,8 +298,8 @@ public function validateHashVersion($hash, $validateCount = false) $hashVersions = $this->getPasswordVersion(); return $validateCount - ? end($hashVersions) === self::HASH_VERSION_LATEST && count($hashVersions) === 1 - : end($hashVersions) === self::HASH_VERSION_LATEST; + ? end($hashVersions) === $this->getLatestHashVersion() && count($hashVersions) === 1 + : end($hashVersions) === $this->getLatestHashVersion(); } /** From 30d989538d17afd7315c3392b2072b771b70b45e Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Tue, 23 Apr 2019 18:14:02 -0500 Subject: [PATCH 284/773] GraphQL-299: Do not rely on global state in resolvers --- app/code/Magento/GraphQl/Model/Query/Resolver/Context.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/GraphQl/Model/Query/Resolver/Context.php b/app/code/Magento/GraphQl/Model/Query/Resolver/Context.php index b222689ed6b96..5b6105df65790 100644 --- a/app/code/Magento/GraphQl/Model/Query/Resolver/Context.php +++ b/app/code/Magento/GraphQl/Model/Query/Resolver/Context.php @@ -138,10 +138,10 @@ public function setUserType(int $typeId) : ContextInterface */ public function getStoreId(): int { - if (!$this->getData(self::STORE_ID)) { - $this->setStoreId($this->storeManager->getStore()->getId()); + if (null !== $this->getData(self::STORE_ID)) { + $this->setStoreId((int)$this->storeManager->getStore()->getId()); } - return (int) $this->getData(self::STORE_ID); + return $this->getData(self::STORE_ID); } /** From 161532938fcf9a209848dabc97d8b698e7521715 Mon Sep 17 00:00:00 2001 From: Oleksandr Miroshnichenko <omiroshnichenko@magento.com> Date: Wed, 24 Apr 2019 11:07:48 -0500 Subject: [PATCH 285/773] MC-5843: Add Argon2ID support --- .../Command/UpgradeHashAlgorithmCommand.php | 3 + .../Customer/Model/AccountManagement.php | 2 +- .../Framework/Encryption/Encryptor.php | 84 ++++++++++--------- .../Encryption/Test/Unit/EncryptorTest.php | 22 +++-- 4 files changed, 66 insertions(+), 45 deletions(-) diff --git a/app/code/Magento/Customer/Console/Command/UpgradeHashAlgorithmCommand.php b/app/code/Magento/Customer/Console/Command/UpgradeHashAlgorithmCommand.php index 0632a5970ceb4..f81413b35f165 100644 --- a/app/code/Magento/Customer/Console/Command/UpgradeHashAlgorithmCommand.php +++ b/app/code/Magento/Customer/Console/Command/UpgradeHashAlgorithmCommand.php @@ -13,6 +13,9 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +/** + * Upgrade users passwords to the new algorithm + */ class UpgradeHashAlgorithmCommand extends Command { /** diff --git a/app/code/Magento/Customer/Model/AccountManagement.php b/app/code/Magento/Customer/Model/AccountManagement.php index 250d190f8fae7..d48ab1cc623af 100644 --- a/app/code/Magento/Customer/Model/AccountManagement.php +++ b/app/code/Magento/Customer/Model/AccountManagement.php @@ -1532,7 +1532,7 @@ protected function getFullCustomerObject($customer) */ public function getPasswordHash($password) { - return $this->encryptor->getHash($password); + return $this->encryptor->getHash($password, true); } /** diff --git a/lib/internal/Magento/Framework/Encryption/Encryptor.php b/lib/internal/Magento/Framework/Encryption/Encryptor.php index 5eb4785e1fa8a..2ba8544883800 100644 --- a/lib/internal/Magento/Framework/Encryption/Encryptor.php +++ b/lib/internal/Magento/Framework/Encryption/Encryptor.php @@ -34,7 +34,7 @@ class Encryptor implements EncryptorInterface /** * Key of sha256 algorithm */ - const HASH_VERSION_ARGON2ID13 = 2; + public const HASH_VERSION_ARGON2ID13 = 2; /** * Key of latest used algorithm @@ -130,6 +130,7 @@ class Encryptor implements EncryptorInterface /** * Encryptor constructor. + * * @param Random $random * @param DeploymentConfig $deploymentConfig * @param KeyValidator|null $keyValidator @@ -151,8 +152,12 @@ public function __construct( } } - - public function getLatestHashVersion() + /** + * Gets latest hash algorithm version. + * + * @return int + */ + public function getLatestHashVersion(): int { if (extension_loaded('sodium')) { return self::HASH_VERSION_ARGON2ID13; @@ -181,6 +186,7 @@ public function validateCipher($version) $version = (int)$version; if (!in_array($version, $types, true)) { + // phpcs:ignore Magento2.Exceptions.DirectThrow throw new \Exception((string)new \Magento\Framework\Phrase('Not supported cipher version')); } return $version; @@ -196,26 +202,21 @@ public function getHash($password, $salt = false, $version = self::HASH_VERSION_ } if ($salt === false) { + $version = $version === self::HASH_VERSION_LATEST ? self::HASH_VERSION_SHA256 : $version; return $this->hash($password, $version); } if ($salt === true) { - $salt = $version === self::HASH_VERSION_ARGON2ID13 ? - SODIUM_CRYPTO_PWHASH_SALTBYTES : - self::DEFAULT_SALT_LENGTH; + $salt = self::DEFAULT_SALT_LENGTH; } if (is_integer($salt)) { + $salt = $version === self::HASH_VERSION_ARGON2ID13 ? + SODIUM_CRYPTO_PWHASH_SALTBYTES : + $salt; $salt = $this->random->getRandomString($salt); } if ($version === self::HASH_VERSION_ARGON2ID13) { - $hash = bin2hex(sodium_crypto_pwhash( - SODIUM_CRYPTO_SIGN_SEEDBYTES, - $password, - substr($salt, 0, SODIUM_CRYPTO_PWHASH_SALTBYTES), - SODIUM_CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE, - SODIUM_CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE, - $this->hashVersionMap[self::HASH_VERSION_ARGON2ID13] - )); + $hash = $this->getArgonHash($password, $salt); } else { $hash = $this->hash($salt . $password, $version); } @@ -233,23 +234,8 @@ public function getHash($password, $salt = false, $version = self::HASH_VERSION_ /** * @inheritdoc */ - public function hash($data, $version = self::HASH_VERSION_LATEST) + public function hash($data, $version = self::HASH_VERSION_SHA256) { - if (!isset($this->hashVersionMap[$version])) { - $version = self::HASH_VERSION_SHA256; - } - - if ($version === self::HASH_VERSION_ARGON2ID13) { - return bin2hex(sodium_crypto_pwhash( - SODIUM_CRYPTO_SIGN_SEEDBYTES, - $data, - random_bytes(SODIUM_CRYPTO_PWHASH_SALTBYTES), - SODIUM_CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE, - SODIUM_CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE, - $this->hashVersionMap[self::HASH_VERSION_ARGON2ID13] - )); - } - return hash($this->hashVersionMap[$version], (string)$data); } @@ -270,14 +256,7 @@ public function isValidHash($password, $hash) foreach ($this->getPasswordVersion() as $hashVersion) { if ($hashVersion === self::HASH_VERSION_ARGON2ID13) { - $password = bin2hex(sodium_crypto_pwhash( - SODIUM_CRYPTO_SIGN_SEEDBYTES, - $password, - substr($this->getPasswordSalt(), 0, SODIUM_CRYPTO_PWHASH_SALTBYTES), - SODIUM_CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE, - SODIUM_CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE, - $this->hashVersionMap[self::HASH_VERSION_ARGON2ID13] - )); + $password = $this->getArgonHash($password, $this->getPasswordSalt()); } else { $password = $this->hash($this->getPasswordSalt() . $password, $hashVersion); } @@ -450,6 +429,7 @@ public function decrypt($data) public function validateKey($key) { if (!$this->keyValidator->isValid($key)) { + // phpcs:ignore Magento2.Exceptions.DirectThrow throw new \Exception( (string)new \Magento\Framework\Phrase( 'Encryption key must be 32 character string without any white space.' @@ -547,4 +527,32 @@ private function getCipherVersion() return self::CIPHER_RIJNDAEL_256; } } + + /** + * Generate Argon2ID13 hash. + * + * @param $data + * @param string $salt + * @return string + * @throws \SodiumException + */ + private function getArgonHash($data, $salt = ''): string + { + $salt = empty($salt) ? + random_bytes(SODIUM_CRYPTO_PWHASH_SALTBYTES) : + substr($salt, 0, SODIUM_CRYPTO_PWHASH_SALTBYTES); + + if (strlen($salt) < SODIUM_CRYPTO_PWHASH_SALTBYTES) { + $salt = str_pad($salt, SODIUM_CRYPTO_PWHASH_SALTBYTES, $salt); + } + + return bin2hex(sodium_crypto_pwhash( + SODIUM_CRYPTO_SIGN_SEEDBYTES, + $data, + $salt, + SODIUM_CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE, + SODIUM_CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE, + $this->hashVersionMap[self::HASH_VERSION_ARGON2ID13] + )); + } } diff --git a/lib/internal/Magento/Framework/Encryption/Test/Unit/EncryptorTest.php b/lib/internal/Magento/Framework/Encryption/Test/Unit/EncryptorTest.php index 3feb4b4122843..718e64f8e4e36 100644 --- a/lib/internal/Magento/Framework/Encryption/Test/Unit/EncryptorTest.php +++ b/lib/internal/Magento/Framework/Encryption/Test/Unit/EncryptorTest.php @@ -67,7 +67,9 @@ public function testGetHashNoSalt(): void public function testGetHashSpecifiedSalt(): void { $this->randomGeneratorMock->expects($this->never())->method('getRandomString'); - $expected = '13601bda4ea78e55a07b98866d2be6be0744e3866f13c00c811cab608a28f322:salt:1'; + $expected = $this->encryptor->getLatestHashVersion() === Encryptor::HASH_VERSION_ARGON2ID13 ? + '7640855aef9cb6ffd20229601d2904a2192e372b391db8230d7faf073b393e4c:salt:2' : + '13601bda4ea78e55a07b98866d2be6be0744e3866f13c00c811cab608a28f322:salt:1'; $actual = $this->encryptor->getHash('password', 'salt'); $this->assertEquals($expected, $actual); } @@ -78,9 +80,11 @@ public function testGetHashRandomSaltDefaultLength(): void $this->randomGeneratorMock ->expects($this->once()) ->method('getRandomString') - ->with(32) + ->with($this->encryptor->getLatestHashVersion() === Encryptor::HASH_VERSION_ARGON2ID13 ? 16 : 32) ->willReturn($salt); - $expected = 'a1c7fc88037b70c9be84d3ad12522c7888f647915db78f42eb572008422ba2fa:' . $salt . ':1'; + $expected = $this->encryptor->getLatestHashVersion() === Encryptor::HASH_VERSION_ARGON2ID13 ? + '0be2351d7513d3e9622bd2df1891c39ba5ba6d1e3d67a058c60d6fd83f6641d8:' . $salt . ':2' : + 'a1c7fc88037b70c9be84d3ad12522c7888f647915db78f42eb572008422ba2fa:' . $salt . ':1'; $actual = $this->encryptor->getHash('password', true); $this->assertEquals($expected, $actual); } @@ -90,9 +94,15 @@ public function testGetHashRandomSaltSpecifiedLength(): void $this->randomGeneratorMock ->expects($this->once()) ->method('getRandomString') - ->with(11) - ->willReturn('random_salt'); - $expected = '4c5cab8dd00137d11258f8f87b93fd17bd94c5026fc52d3c5af911dd177a2611:random_salt:1'; + ->with($this->encryptor->getLatestHashVersion() === Encryptor::HASH_VERSION_ARGON2ID13 ? 16 : 11) + ->willReturn( + $this->encryptor->getLatestHashVersion() === Encryptor::HASH_VERSION_ARGON2ID13 ? + 'random_salt12345' : + 'random_salt' + ); + $expected = $this->encryptor->getLatestHashVersion() === Encryptor::HASH_VERSION_ARGON2ID13 ? + 'ca7982945fa90444b78d586678ff1c223ce13f99a39ec9541eae8b63ada3816a:random_salt12345:2' : + '4c5cab8dd00137d11258f8f87b93fd17bd94c5026fc52d3c5af911dd177a2611:random_salt:1'; $actual = $this->encryptor->getHash('password', 11); $this->assertEquals($expected, $actual); } From fa41a7156c84524e32be0b41016009e2643fee84 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun <ogorkun@magento.com> Date: Wed, 24 Apr 2019 11:28:43 -0500 Subject: [PATCH 286/773] MC-13958: Additional Permissions for Design settings --- .../Catalog/view/adminhtml/ui_component/category_form.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Catalog/view/adminhtml/ui_component/category_form.xml b/app/code/Magento/Catalog/view/adminhtml/ui_component/category_form.xml index 84c3c35f1af18..1ce9a669f0ee6 100644 --- a/app/code/Magento/Catalog/view/adminhtml/ui_component/category_form.xml +++ b/app/code/Magento/Catalog/view/adminhtml/ui_component/category_form.xml @@ -544,7 +544,7 @@ <dataType>string</dataType> <label translate="true">Schedule Update From</label> <imports> - <link name="disabled">ns = ${ $.ns }, index = custom_use_parent_settings :checked</link> + <link name="disabled">${ $.parentName }.custom_use_parent_settings:checked || $.data.serviceDisabled</link> </imports> </settings> </field> @@ -557,7 +557,7 @@ <dataType>string</dataType> <label translate="true">To</label> <imports> - <link name="disabled">ns = ${ $.ns }, index = custom_use_parent_settings :checked</link> + <link name="disabled">${ $.parentName }.custom_use_parent_settings:checked || $.data.serviceDisabled</link> </imports> </settings> </field> From 77656967a5d72ab5e39feed23aee8aa732fd2f87 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Wed, 24 Apr 2019 11:40:48 -0500 Subject: [PATCH 287/773] GraphQL-299: Do not rely on global state in resolvers --- app/code/Magento/GraphQl/Model/Query/Resolver/Context.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/GraphQl/Model/Query/Resolver/Context.php b/app/code/Magento/GraphQl/Model/Query/Resolver/Context.php index 5b6105df65790..e49040f70215b 100644 --- a/app/code/Magento/GraphQl/Model/Query/Resolver/Context.php +++ b/app/code/Magento/GraphQl/Model/Query/Resolver/Context.php @@ -138,7 +138,7 @@ public function setUserType(int $typeId) : ContextInterface */ public function getStoreId(): int { - if (null !== $this->getData(self::STORE_ID)) { + if (null === $this->getData(self::STORE_ID)) { $this->setStoreId((int)$this->storeManager->getStore()->getId()); } return $this->getData(self::STORE_ID); From 9665d6b394efcbee98c0f1f8d435b6ae0964e65c Mon Sep 17 00:00:00 2001 From: Leandry <leandry@atwix.com> Date: Wed, 24 Apr 2019 19:43:51 +0300 Subject: [PATCH 288/773] Refactoring --- ...sertAdminLoginErrorMessageActionGroup.xml} | 5 ++-- ...ml => AssertMessageOnAdminActionGroup.xml} | 2 +- .../Mftf/Section/AdminLoginFormSection.xml | 1 - ...ml => AdminSaveIntegrationActionGroup.xml} | 2 +- ...dminUserWhenCreatingNewIntegrationTest.xml | 26 +++++++++---------- 5 files changed, 18 insertions(+), 18 deletions(-) rename app/code/Magento/Backend/Test/Mftf/ActionGroup/{AssertAdminNotSuccessLoginActionGroup.xml => AssertAdminLoginErrorMessageActionGroup.xml} (72%) rename app/code/Magento/Backend/Test/Mftf/ActionGroup/{AssertMessageOnBackendActionGroup.xml => AssertMessageOnAdminActionGroup.xml} (92%) rename app/code/Magento/Integration/Test/Mftf/ActionGroup/{AssertSaveIntegrationActionGroup.xml => AdminSaveIntegrationActionGroup.xml} (89%) diff --git a/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertAdminNotSuccessLoginActionGroup.xml b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertAdminLoginErrorMessageActionGroup.xml similarity index 72% rename from app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertAdminNotSuccessLoginActionGroup.xml rename to app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertAdminLoginErrorMessageActionGroup.xml index f932924edbd72..6ad3b7cfb9121 100644 --- a/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertAdminNotSuccessLoginActionGroup.xml +++ b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertAdminLoginErrorMessageActionGroup.xml @@ -8,12 +8,13 @@ <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="AssertAdminNotSuccessLoginActionGroup"> + <actionGroup name="AssertAdminLoginErrorMessageActionGroup"> <arguments> <argument name="message" type="string" defaultValue="The account sign-in was incorrect or your account is disabled temporarily. Please wait and try again later"/> + <argument name="messageType" type="string" defaultValue="error" /> </arguments> <waitForPageLoad stepKey="waitForPageReload"/> - <see selector="{{AdminLoginFormSection.error}}" userInput="{{message}}" + <see selector="{{AdminLoginMessagesSection.messageByType(messageType)}}" userInput="{{message}}" stepKey="seeLoginAdminError"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertMessageOnBackendActionGroup.xml b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertMessageOnAdminActionGroup.xml similarity index 92% rename from app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertMessageOnBackendActionGroup.xml rename to app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertMessageOnAdminActionGroup.xml index b75fcd47c61bd..414a9b56b8b0e 100644 --- a/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertMessageOnBackendActionGroup.xml +++ b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertMessageOnAdminActionGroup.xml @@ -8,7 +8,7 @@ <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="AssertMessageOnBackendActionGroup"> + <actionGroup name="AssertMessageOnAdminActionGroup"> <arguments> <argument name="message" type="string" defaultValue="The password entered for the current user is invalid. Verify the password and try again." /> <argument name="messageType" type="string" defaultValue="error" /> diff --git a/app/code/Magento/Backend/Test/Mftf/Section/AdminLoginFormSection.xml b/app/code/Magento/Backend/Test/Mftf/Section/AdminLoginFormSection.xml index 58efb66747b15..3b10fac7bb9dc 100644 --- a/app/code/Magento/Backend/Test/Mftf/Section/AdminLoginFormSection.xml +++ b/app/code/Magento/Backend/Test/Mftf/Section/AdminLoginFormSection.xml @@ -12,6 +12,5 @@ <element name="username" type="input" selector="#username"/> <element name="password" type="input" selector="#login"/> <element name="signIn" type="button" selector=".actions .action-primary" timeout="30"/> - <element name="error" type="text" selector=".message.message-error.error"/> </section> </sections> diff --git a/app/code/Magento/Integration/Test/Mftf/ActionGroup/AssertSaveIntegrationActionGroup.xml b/app/code/Magento/Integration/Test/Mftf/ActionGroup/AdminSaveIntegrationActionGroup.xml similarity index 89% rename from app/code/Magento/Integration/Test/Mftf/ActionGroup/AssertSaveIntegrationActionGroup.xml rename to app/code/Magento/Integration/Test/Mftf/ActionGroup/AdminSaveIntegrationActionGroup.xml index 0c53f4455befb..5169fd9476362 100644 --- a/app/code/Magento/Integration/Test/Mftf/ActionGroup/AssertSaveIntegrationActionGroup.xml +++ b/app/code/Magento/Integration/Test/Mftf/ActionGroup/AdminSaveIntegrationActionGroup.xml @@ -7,7 +7,7 @@ --> <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="AssertSaveIntegrationActionGroup"> + <actionGroup name="AdminSaveIntegrationActionGroup"> <click selector="{{AdminNewIntegrationSection.save}}" stepKey="saveIntegration"/> <waitForPageLoad stepKey="waitForSaveResultLoad"/> </actionGroup> diff --git a/app/code/Magento/Security/Test/Mftf/Test/AdminLockAdminUserWhenCreatingNewIntegrationTest.xml b/app/code/Magento/Security/Test/Mftf/Test/AdminLockAdminUserWhenCreatingNewIntegrationTest.xml index 96ef122fd7a48..ce101c09dfeeb 100644 --- a/app/code/Magento/Security/Test/Mftf/Test/AdminLockAdminUserWhenCreatingNewIntegrationTest.xml +++ b/app/code/Magento/Security/Test/Mftf/Test/AdminLockAdminUserWhenCreatingNewIntegrationTest.xml @@ -33,44 +33,44 @@ <actionGroup ref="AdminFillIntegrationRequiredFieldsActionGroup" stepKey="fillFieldFirstAttempt"> <argument name="currentAdminPassword" value="{{_ENV.MAGENTO_ADMIN_PASSWORD}}INVALID" /> </actionGroup> - <actionGroup ref="AssertSaveIntegrationActionGroup" stepKey="saveIntegrationFirstAttempt"/> - <actionGroup ref="AssertMessageOnBackendActionGroup" stepKey="checkFirstSaveIntegrationError"/> + <actionGroup ref="AdminSaveIntegrationActionGroup" stepKey="saveIntegrationFirstAttempt"/> + <actionGroup ref="AssertMessageOnAdminActionGroup" stepKey="checkFirstSaveIntegrationError"/> <actionGroup ref="AdminFillIntegrationRequiredFieldsActionGroup" stepKey="fillFieldSecondAttempt"> <argument name="currentAdminPassword" value="{{_ENV.MAGENTO_ADMIN_PASSWORD}}INVALID" /> </actionGroup> - <actionGroup ref="AssertSaveIntegrationActionGroup" stepKey="saveIntegrationSecondAttempt"/> - <actionGroup ref="AssertMessageOnBackendActionGroup" stepKey="checkSecondSaveIntegrationError"/> + <actionGroup ref="AdminSaveIntegrationActionGroup" stepKey="saveIntegrationSecondAttempt"/> + <actionGroup ref="AssertMessageOnAdminActionGroup" stepKey="checkSecondSaveIntegrationError"/> <actionGroup ref="AdminFillIntegrationRequiredFieldsActionGroup" stepKey="fillFieldThirdAttempt"> <argument name="currentAdminPassword" value="{{_ENV.MAGENTO_ADMIN_PASSWORD}}INVALID" /> </actionGroup> - <actionGroup ref="AssertSaveIntegrationActionGroup" stepKey="saveIntegrationThirdAttempt"/> - <actionGroup ref="AssertMessageOnBackendActionGroup" stepKey="checkThirdSaveIntegrationError"/> + <actionGroup ref="AdminSaveIntegrationActionGroup" stepKey="saveIntegrationThirdAttempt"/> + <actionGroup ref="AssertMessageOnAdminActionGroup" stepKey="checkThirdSaveIntegrationError"/> <actionGroup ref="AdminFillIntegrationRequiredFieldsActionGroup" stepKey="fillFieldFourthAttempt"> <argument name="currentAdminPassword" value="{{_ENV.MAGENTO_ADMIN_PASSWORD}}INVALID" /> </actionGroup> - <actionGroup ref="AssertSaveIntegrationActionGroup" stepKey="saveIntegrationFourthAttempt"/> - <actionGroup ref="AssertMessageOnBackendActionGroup" stepKey="checkFourthSaveIntegrationError"/> + <actionGroup ref="AdminSaveIntegrationActionGroup" stepKey="saveIntegrationFourthAttempt"/> + <actionGroup ref="AssertMessageOnAdminActionGroup" stepKey="checkFourthSaveIntegrationError"/> <actionGroup ref="AdminFillIntegrationRequiredFieldsActionGroup" stepKey="fillFieldFifthAttempt"> <argument name="currentAdminPassword" value="{{_ENV.MAGENTO_ADMIN_PASSWORD}}INVALID" /> </actionGroup> - <actionGroup ref="AssertSaveIntegrationActionGroup" stepKey="saveIntegrationFifthAttempt"/> - <actionGroup ref="AssertMessageOnBackendActionGroup" stepKey="checkFifthSaveIntegrationError"/> + <actionGroup ref="AdminSaveIntegrationActionGroup" stepKey="saveIntegrationFifthAttempt"/> + <actionGroup ref="AssertMessageOnAdminActionGroup" stepKey="checkFifthSaveIntegrationError"/> <!-- Last invalid current password save integration attempt and check logout error --> <actionGroup ref="AdminFillIntegrationRequiredFieldsActionGroup" stepKey="fillFieldLastAttempt"> <argument name="currentAdminPassword" value="{{_ENV.MAGENTO_ADMIN_PASSWORD}}INVALID" /> </actionGroup> - <actionGroup ref="AssertSaveIntegrationActionGroup" stepKey="saveIntegrationLastAttempt"/> - <actionGroup ref="AssertAdminNotSuccessLoginActionGroup" stepKey="checkFifthError"> + <actionGroup ref="AdminSaveIntegrationActionGroup" stepKey="saveIntegrationLastAttempt"/> + <actionGroup ref="AssertAdminLoginErrorMessageActionGroup" stepKey="checkFifthError"> <argument name="message" value="Your account is temporarily disabled. Please try again later."/> </actionGroup> <!-- Try to login as admin and check error --> <actionGroup ref="LoginAsAdmin" stepKey="loginAsLockedAdmin"/> - <actionGroup ref="AssertAdminNotSuccessLoginActionGroup" stepKey="checkLoginError"/> + <actionGroup ref="AssertAdminLoginErrorMessageActionGroup" stepKey="checkLoginError"/> </test> </tests> From 9cea3ca10a8456092236ebca430cec09d0ce47f1 Mon Sep 17 00:00:00 2001 From: Leandry <leandry@atwix.com> Date: Wed, 24 Apr 2019 19:51:37 +0300 Subject: [PATCH 289/773] Refactoring --- .../Integration/Test/Mftf/Page/AdminNewIntegrationPage.xml | 2 +- .../Test/Mftf/Section/AdminNewIntegrationSection.xml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Integration/Test/Mftf/Page/AdminNewIntegrationPage.xml b/app/code/Magento/Integration/Test/Mftf/Page/AdminNewIntegrationPage.xml index c4b0695a05bf0..7b46029aa1eec 100644 --- a/app/code/Magento/Integration/Test/Mftf/Page/AdminNewIntegrationPage.xml +++ b/app/code/Magento/Integration/Test/Mftf/Page/AdminNewIntegrationPage.xml @@ -9,6 +9,6 @@ <pages xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/PageObject.xsd"> <page name="AdminNewIntegrationPage" url="admin/integration/new/" area="admin" module="Magento_Integration"> - <section name="AdminNewIntegrationSection"/> + <section name="AdminNewIntegrationSection"/> </page> </pages> diff --git a/app/code/Magento/Integration/Test/Mftf/Section/AdminNewIntegrationSection.xml b/app/code/Magento/Integration/Test/Mftf/Section/AdminNewIntegrationSection.xml index 7a193df73063e..89588f7775098 100644 --- a/app/code/Magento/Integration/Test/Mftf/Section/AdminNewIntegrationSection.xml +++ b/app/code/Magento/Integration/Test/Mftf/Section/AdminNewIntegrationSection.xml @@ -9,8 +9,8 @@ <sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="AdminNewIntegrationSection"> - <element name="integrationName" type="input" selector="#integration_properties_name"/> - <element name="currentPassword" type="input" selector="#integration_properties_current_password"/> + <element name="integrationName" type="input" selector="#edit_form input[name='name']"/> + <element name="currentPassword" type="input" selector="#edit_form input[name='current_password']"/> <element name="save" type="button" selector="#save-split-button-button"/> </section> </sections> From cb7f7d9d8e56bdd05aa5dc705cebff0921601a63 Mon Sep 17 00:00:00 2001 From: Oleksandr Miroshnichenko <omiroshnichenko@magento.com> Date: Wed, 24 Apr 2019 13:39:53 -0500 Subject: [PATCH 290/773] MC-5843: Add Argon2ID support --- .../Magento/Customer/Model/AccountManagement.php | 5 +++++ .../testsuite/Magento/User/Model/UserTest.php | 14 +++++++++++++- .../Magento/Framework/Encryption/Encryptor.php | 5 +++-- .../Encryption/Test/Unit/EncryptorTest.php | 3 +++ 4 files changed, 24 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Customer/Model/AccountManagement.php b/app/code/Magento/Customer/Model/AccountManagement.php index d48ab1cc623af..257f1c08289b6 100644 --- a/app/code/Magento/Customer/Model/AccountManagement.php +++ b/app/code/Magento/Customer/Model/AccountManagement.php @@ -554,6 +554,7 @@ public function authenticate($username, $password) } try { $this->getAuthentication()->authenticate($customerId, $password); + // phpcs:ignore Magento2.Exceptions.ThrowCatch } catch (InvalidEmailOrPasswordException $e) { throw new InvalidEmailOrPasswordException(__('Invalid login or password.')); } @@ -894,6 +895,7 @@ public function createAccountWithPasswordHash(CustomerInterface $customer, $hash throw new InputMismatchException( __('A customer with the same email address already exists in an associated website.') ); + // phpcs:ignore Magento2.Exceptions.ThrowCatch } catch (LocalizedException $e) { throw $e; } @@ -910,6 +912,7 @@ public function createAccountWithPasswordHash(CustomerInterface $customer, $hash } } $this->customerRegistry->remove($customer->getId()); + // phpcs:ignore Magento2.Exceptions.ThrowCatch } catch (InputException $e) { $this->customerRepository->delete($customer); throw $e; @@ -1012,6 +1015,7 @@ private function changePasswordForCustomer($customer, $currentPassword, $newPass { try { $this->getAuthentication()->authenticate($customer->getId(), $currentPassword); + // phpcs:ignore Magento2.Exceptions.ThrowCatch } catch (InvalidEmailOrPasswordException $e) { throw new InvalidEmailOrPasswordException( __("The password doesn't match this account. Verify the password and try again.") @@ -1070,6 +1074,7 @@ public function validate(CustomerInterface $customer) $result = $this->getEavValidator()->isValid($customerModel); if ($result === false && is_array($this->getEavValidator()->getMessages())) { + // phpcs:ignore Magento2.Functions.DiscouragedFunction return $validationResults->setIsValid(false)->setMessages( call_user_func_array( 'array_merge', diff --git a/dev/tests/integration/testsuite/Magento/User/Model/UserTest.php b/dev/tests/integration/testsuite/Magento/User/Model/UserTest.php index 8b85339afd789..edd48355a8351 100644 --- a/dev/tests/integration/testsuite/Magento/User/Model/UserTest.php +++ b/dev/tests/integration/testsuite/Magento/User/Model/UserTest.php @@ -7,6 +7,7 @@ namespace Magento\User\Model; use Magento\Framework\Serialize\Serializer\Json; +use Magento\Framework\Encryption\Encryptor; /** * @magentoAppArea adminhtml @@ -33,6 +34,11 @@ class UserTest extends \PHPUnit\Framework\TestCase */ private $serializer; + /** + * @var Encryptor + */ + private $encryptor; + protected function setUp() { $this->_model = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( @@ -44,6 +50,9 @@ protected function setUp() $this->serializer = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( Json::class ); + $this->encryptor = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( + Encryptor::class + ); } /** @@ -335,6 +344,9 @@ public function testBeforeSaveRequiredFieldsValidation() */ public function testBeforeSavePasswordHash() { + $pattern = $this->encryptor->getLatestHashVersion() === Encryptor::HASH_VERSION_ARGON2ID13 ? + '/^[0-9a-f]+:[0-9a-zA-Z]{16}:[0-9]+$/' : + '/^[0-9a-f]+:[0-9a-zA-Z]{32}:[0-9]+$/'; $this->_model->setUsername( 'john.doe' )->setFirstname( @@ -349,7 +361,7 @@ public function testBeforeSavePasswordHash() $this->_model->save(); $this->assertNotContains('123123q', $this->_model->getPassword(), 'Password is expected to be hashed'); $this->assertRegExp( - '/^[0-9a-f]+:[0-9a-zA-Z]{32}:[0-9]+$/', + $pattern, $this->_model->getPassword(), 'Salt is expected to be saved along with the password' ); diff --git a/lib/internal/Magento/Framework/Encryption/Encryptor.php b/lib/internal/Magento/Framework/Encryption/Encryptor.php index 2ba8544883800..fdce00847ff1c 100644 --- a/lib/internal/Magento/Framework/Encryption/Encryptor.php +++ b/lib/internal/Magento/Framework/Encryption/Encryptor.php @@ -94,7 +94,7 @@ class Encryptor implements EncryptorInterface private $passwordHashMap = [ self::PASSWORD_HASH => '', self::PASSWORD_SALT => '', - self::PASSWORD_VERSION => self::HASH_VERSION_LATEST + self::PASSWORD_VERSION => self::HASH_VERSION_SHA256 ]; /** @@ -149,6 +149,7 @@ public function __construct( $latestHashVersion = $this->getLatestHashVersion(); if ($latestHashVersion === self::HASH_VERSION_ARGON2ID13) { $this->hashVersionMap[self::HASH_VERSION_ARGON2ID13] = SODIUM_CRYPTO_PWHASH_ALG_ARGON2ID13; + $this->passwordHashMap[self::PASSWORD_VERSION] = self::HASH_VERSION_ARGON2ID13; } } @@ -531,7 +532,7 @@ private function getCipherVersion() /** * Generate Argon2ID13 hash. * - * @param $data + * @param string $data * @param string $salt * @return string * @throws \SodiumException diff --git a/lib/internal/Magento/Framework/Encryption/Test/Unit/EncryptorTest.php b/lib/internal/Magento/Framework/Encryption/Test/Unit/EncryptorTest.php index 718e64f8e4e36..f6f92f390fc54 100644 --- a/lib/internal/Magento/Framework/Encryption/Test/Unit/EncryptorTest.php +++ b/lib/internal/Magento/Framework/Encryption/Test/Unit/EncryptorTest.php @@ -16,6 +16,9 @@ use Magento\Framework\Encryption\KeyValidator; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +/** + * Test case for \Magento\Framework\Encryption\Encryptor + */ class EncryptorTest extends \PHPUnit\Framework\TestCase { private const CRYPT_KEY_1 = 'g9mY9KLrcuAVJfsmVUSRkKFLDdUPVkaZ'; From aa188884f1f046dad30823dd3d224e625937121e Mon Sep 17 00:00:00 2001 From: Oleksandr Miroshnichenko <omiroshnichenko@magento.com> Date: Wed, 24 Apr 2019 15:20:03 -0500 Subject: [PATCH 291/773] MC-5843: Add Argon2ID support --- .../Customer/Console/Command/UpgradeHashAlgorithmCommand.php | 2 +- lib/internal/Magento/Framework/Encryption/Encryptor.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Customer/Console/Command/UpgradeHashAlgorithmCommand.php b/app/code/Magento/Customer/Console/Command/UpgradeHashAlgorithmCommand.php index f81413b35f165..c980fe1fe7769 100644 --- a/app/code/Magento/Customer/Console/Command/UpgradeHashAlgorithmCommand.php +++ b/app/code/Magento/Customer/Console/Command/UpgradeHashAlgorithmCommand.php @@ -14,7 +14,7 @@ use Symfony\Component\Console\Output\OutputInterface; /** - * Upgrade users passwords to the new algorithm + * Upgrade users passwords to the new algorithm */ class UpgradeHashAlgorithmCommand extends Command { diff --git a/lib/internal/Magento/Framework/Encryption/Encryptor.php b/lib/internal/Magento/Framework/Encryption/Encryptor.php index fdce00847ff1c..5e6c6e42913ba 100644 --- a/lib/internal/Magento/Framework/Encryption/Encryptor.php +++ b/lib/internal/Magento/Framework/Encryption/Encryptor.php @@ -32,7 +32,7 @@ class Encryptor implements EncryptorInterface const HASH_VERSION_SHA256 = 1; /** - * Key of sha256 algorithm + * Key of Argon2ID13 algorithm */ public const HASH_VERSION_ARGON2ID13 = 2; From 05e5c8e1b15e59c69c0e880005a4b9241fd42a18 Mon Sep 17 00:00:00 2001 From: Oleksandr Miroshnichenko <omiroshnichenko@magento.com> Date: Wed, 24 Apr 2019 15:23:39 -0500 Subject: [PATCH 292/773] MC-5843: Add Argon2ID support --- lib/internal/Magento/Framework/Encryption/Encryptor.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/Encryption/Encryptor.php b/lib/internal/Magento/Framework/Encryption/Encryptor.php index 5e6c6e42913ba..65922d69a823c 100644 --- a/lib/internal/Magento/Framework/Encryption/Encryptor.php +++ b/lib/internal/Magento/Framework/Encryption/Encryptor.php @@ -203,7 +203,7 @@ public function getHash($password, $salt = false, $version = self::HASH_VERSION_ } if ($salt === false) { - $version = $version === self::HASH_VERSION_LATEST ? self::HASH_VERSION_SHA256 : $version; + $version = $version === self::HASH_VERSION_ARGON2ID13 ? self::HASH_VERSION_SHA256 : $version; return $this->hash($password, $version); } if ($salt === true) { From ace73cbf9f5a8c003ef4db415c759ea48bb36bad Mon Sep 17 00:00:00 2001 From: Oleksandr Miroshnichenko <omiroshnichenko@magento.com> Date: Thu, 25 Apr 2019 09:38:53 -0500 Subject: [PATCH 293/773] MC-5843: Add Argon2ID support - fix static test --- app/code/Magento/Customer/Model/AccountManagement.php | 2 +- .../integration/testsuite/Magento/User/Model/UserTest.php | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Customer/Model/AccountManagement.php b/app/code/Magento/Customer/Model/AccountManagement.php index 257f1c08289b6..23d667812c357 100644 --- a/app/code/Magento/Customer/Model/AccountManagement.php +++ b/app/code/Magento/Customer/Model/AccountManagement.php @@ -1074,8 +1074,8 @@ public function validate(CustomerInterface $customer) $result = $this->getEavValidator()->isValid($customerModel); if ($result === false && is_array($this->getEavValidator()->getMessages())) { - // phpcs:ignore Magento2.Functions.DiscouragedFunction return $validationResults->setIsValid(false)->setMessages( + // phpcs:ignore Magento2.Functions.DiscouragedFunction call_user_func_array( 'array_merge', $this->getEavValidator()->getMessages() diff --git a/dev/tests/integration/testsuite/Magento/User/Model/UserTest.php b/dev/tests/integration/testsuite/Magento/User/Model/UserTest.php index edd48355a8351..a6fc9999ad267 100644 --- a/dev/tests/integration/testsuite/Magento/User/Model/UserTest.php +++ b/dev/tests/integration/testsuite/Magento/User/Model/UserTest.php @@ -113,6 +113,9 @@ public function testUpdateRoleOnSave() $this->assertEquals('admin_role', $this->_model->getRole()->getRoleName()); } + /** + * phpcs:disable Magento2.Functions.StaticFunction + */ public static function roleDataFixture() { self::$_newRole = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( From 92e848e04fadfba434d6e60271b66340cb6789ca Mon Sep 17 00:00:00 2001 From: Daniel Renaud <drenaud@magento.com> Date: Thu, 25 Apr 2019 16:06:31 -0500 Subject: [PATCH 294/773] MC-15941: Product media_gallery_entries / types only present if image, thumbnail, small_image is requested --- .../Products/DataProvider/Product.php | 3 - .../MediaGalleryProcessor.php | 57 +++++++++++++++++++ app/code/Magento/CatalogGraphQl/etc/di.xml | 1 + 3 files changed, 58 insertions(+), 3 deletions(-) create mode 100644 app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Product/CollectionProcessor/MediaGalleryProcessor.php diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Product.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Product.php index 7f1fd71942253..aed667695a748 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Product.php +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Product.php @@ -86,9 +86,6 @@ public function getList( $collection->load(); // Methods that perform extra fetches post-load - if (in_array('media_gallery_entries', $attributes)) { - $collection->addMediaGalleryData(); - } if (in_array('options', $attributes)) { $collection->addOptionsToResult(); } diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Product/CollectionProcessor/MediaGalleryProcessor.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Product/CollectionProcessor/MediaGalleryProcessor.php new file mode 100644 index 0000000000000..c34a198e48e80 --- /dev/null +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Product/CollectionProcessor/MediaGalleryProcessor.php @@ -0,0 +1,57 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\Product\CollectionProcessor; + +use Magento\Catalog\Model\ResourceModel\Product\Collection; +use Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\Product\CollectionProcessorInterface; +use Magento\Framework\Api\SearchCriteriaInterface; +use Magento\Catalog\Model\Product\Media\Config as MediaConfig; + +/** + * Add attributes required for every GraphQL product resolution process. + * + * {@inheritdoc} + */ +class MediaGalleryProcessor implements CollectionProcessorInterface +{ + /** + * @var MediaConfig + */ + private $mediaConfig; + + /** + * Add media gallery attributes to collection + * + * @param MediaConfig $mediaConfig + */ + public function __construct(MediaConfig $mediaConfig) + { + $this->mediaConfig = $mediaConfig; + } + + /** + * @inheritdoc + */ + public function process( + Collection $collection, + SearchCriteriaInterface $searchCriteria, + array $attributeNames + ): Collection { + if (in_array('media_gallery_entries', $attributeNames)) { + $mediaAttributes = $this->mediaConfig->getMediaAttributeCodes(); + foreach ($mediaAttributes as $mediaAttribute) { + if (!in_array($mediaAttribute, $attributeNames)) { + $collection->addAttributeToSelect($mediaAttribute); + } + } + $collection->addMediaGalleryData(); + } + + return $collection; + } +} diff --git a/app/code/Magento/CatalogGraphQl/etc/di.xml b/app/code/Magento/CatalogGraphQl/etc/di.xml index 406d37b2ea200..a5006355ed265 100644 --- a/app/code/Magento/CatalogGraphQl/etc/di.xml +++ b/app/code/Magento/CatalogGraphQl/etc/di.xml @@ -46,6 +46,7 @@ <item name="search" xsi:type="object">Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\Product\CollectionProcessor\SearchCriteriaProcessor</item> <item name="stock" xsi:type="object">Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\Product\CollectionProcessor\StockProcessor</item> <item name="visibility" xsi:type="object">Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\Product\CollectionProcessor\VisibilityStatusProcessor</item> + <item name="mediaGallery" xsi:type="object">Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\Product\CollectionProcessor\MediaGalleryProcessor</item> </argument> </arguments> </type> From a8a8abfac03316daa245acf426ad19105027620e Mon Sep 17 00:00:00 2001 From: pdohogne-magento <pdohogne@magento.com> Date: Thu, 25 Apr 2019 16:24:16 -0500 Subject: [PATCH 295/773] MC-16002: Correcting the pre_composer_update_2.3.php script with 2.3.2 values --- dev/tools/UpgradeScripts/pre_composer_update_2.3.php | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/dev/tools/UpgradeScripts/pre_composer_update_2.3.php b/dev/tools/UpgradeScripts/pre_composer_update_2.3.php index 04e64ba45ba0e..3b3f575632124 100644 --- a/dev/tools/UpgradeScripts/pre_composer_update_2.3.php +++ b/dev/tools/UpgradeScripts/pre_composer_update_2.3.php @@ -233,12 +233,16 @@ output('\nUpdating "require-dev" section of composer.json'); runComposer('require --dev ' . - 'phpunit/phpunit:~6.2.0 ' . - 'friendsofphp/php-cs-fixer:~2.10.1 ' . + 'allure-framework/allure-phpunit:~1.2.0 ' . + 'friendsofphp/php-cs-fixer:~2.13.0 ' . 'lusitanian/oauth:~0.8.10 ' . + 'magento/magento-coding-standard:~1.0.0 ' . + 'magento/magento2-functional-testing-framework:~2.3.14 ' . 'pdepend/pdepend:2.5.2 ' . + 'phpunit/phpunit:~6.5.0 ' . 'sebastian/phpcpd:~3.0.0 ' . - 'squizlabs/php_codesniffer:3.2.2 --no-update'); + 'squizlabs/php_codesniffer:3.3.1 ' . + '--sort-packages --no-update'); output(''); runComposer('remove --dev sjparkinson/static-review fabpot/php-cs-fixer --no-update'); From 8f492299953c139357bdcdf1ad16b6a32e1ff7da Mon Sep 17 00:00:00 2001 From: Daniel Renaud <drenaud@magento.com> Date: Fri, 26 Apr 2019 11:21:42 -0500 Subject: [PATCH 296/773] MC-15941: Product media_gallery_entries / types only present if image, thumbnail, small_image is requested - add api-functional test --- .../GraphQl/Catalog/MediaGalleryTest.php | 40 +++++++++++++++++++ .../Magento/Catalog/_files/product_image.php | 15 +++++-- .../_files/product_with_multiple_images.php | 37 +++++++++++++++++ .../product_with_multiple_images_rollback.php | 7 ++++ 4 files changed, 95 insertions(+), 4 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/_files/product_with_multiple_images.php create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/_files/product_with_multiple_images_rollback.php diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/MediaGalleryTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/MediaGalleryTest.php index 8da2702917af0..0daccf3c6d869 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/MediaGalleryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/MediaGalleryTest.php @@ -9,6 +9,9 @@ use Magento\TestFramework\TestCase\GraphQlAbstract; +/** + * Test media gallery queries + */ class MediaGalleryTest extends GraphQlAbstract { /** @@ -45,6 +48,43 @@ public function testProductSmallImageUrlWithExistingImage() self::assertTrue($this->checkImageExists($response['products']['items'][0]['small_image']['url'])); } + /** + * @magentoApiDataFixture Magento/Catalog/_files/product_with_multiple_images.php + */ + public function testMediaGalleryTypesAreCorrect() + { + $productSku = 'simple'; + $query = <<<QUERY +{ + products(filter: {sku: {eq: "{$productSku}"}}) { + items { + media_gallery_entries { + label + media_type + file + types + } + } + } +} +QUERY; + $response = $this->graphQlQuery($query); + + $this->assertNotEmpty($response['products']['items'][0]['media_gallery_entries']); + $mediaGallery = $response['products']['items'][0]['media_gallery_entries']; + $this->assertCount(2, $mediaGallery); + + $this->assertEquals('Image Alt Text', $mediaGallery[0]['label']); + $this->assertEquals('image', $mediaGallery[0]['media_type']); + $this->assertContains('magento_image', $mediaGallery[0]['file']); + $this->assertEquals(['image', 'small_image'], $mediaGallery[0]['types']); + + $this->assertEquals('Thumbnail Image', $mediaGallery[1]['label']); + $this->assertEquals('image', $mediaGallery[1]['media_type']); + $this->assertContains('magento_thumbnail', $mediaGallery[1]['file']); + $this->assertEquals(['thumbnail', 'swatch_image'], $mediaGallery[1]['types']); + } + /** * @param string $url * @return bool diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_image.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_image.php index 8b19c185b0d35..95424484380f1 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_image.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_image.php @@ -18,7 +18,14 @@ $mediaDirectory->create($targetDirPath); $mediaDirectory->create($targetTmpDirPath); -$targetTmpFilePath = $mediaDirectory->getAbsolutePath() . DIRECTORY_SEPARATOR . $targetTmpDirPath - . DIRECTORY_SEPARATOR . 'magento_image.jpg'; -copy(__DIR__ . '/magento_image.jpg', $targetTmpFilePath); -// Copying the image to target dir is not necessary because during product save, it will be moved there from tmp dir +$images = ['magento_image.jpg', 'magento_small_image.jpg', 'magento_thumbnail.jpg']; + +foreach ($images as $image) { + $targetTmpFilePath = $mediaDirectory->getAbsolutePath() . DIRECTORY_SEPARATOR . $targetTmpDirPath + . DIRECTORY_SEPARATOR . $image; + + $sourceFilePath = __DIR__ . DIRECTORY_SEPARATOR . $image; + + copy($sourceFilePath, $targetTmpFilePath); + // Copying the image to target dir is not necessary because during product save, it will be moved there from tmp dir +} diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_with_multiple_images.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_with_multiple_images.php new file mode 100644 index 0000000000000..44c425c50bc19 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_with_multiple_images.php @@ -0,0 +1,37 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +require __DIR__ . '/product_image.php'; +require __DIR__ . '/product_simple.php'; + +$objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); +$productRepository = $objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class); +$product = $productRepository->get('simple'); + +/** @var $product \Magento\Catalog\Model\Product */ +$product->setStoreId(0) + ->setImage('/m/a/magento_image.jpg') + ->setSmallImage('/m/a/magento_image.jpg') + ->setThumbnail('/m/a/magento_thumbnail.jpg') + ->setSwatchImage('/m/a/magento_thumbnail.jpg') + ->setData('media_gallery', ['images' => [ + [ + 'file' => '/m/a/magento_image.jpg', + 'position' => 1, + 'label' => 'Image Alt Text', + 'disabled' => 0, + 'media_type' => 'image' + ], + [ + 'file' => '/m/a/magento_thumbnail.jpg', + 'position' => 2, + 'label' => 'Thumbnail Image', + 'disabled' => 0, + 'media_type' => 'image' + ], + ]]) + ->setCanSaveCustomOptions(true) + ->save(); diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_with_multiple_images_rollback.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_with_multiple_images_rollback.php new file mode 100644 index 0000000000000..c165ca930cdad --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_with_multiple_images_rollback.php @@ -0,0 +1,7 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +require __DIR__ . '/product_with_image_rollback.php'; From 9e9262d1861136dff75b5960d1478007a466498f Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun <ogorkun@magento.com> Date: Fri, 26 Apr 2019 13:22:49 -0500 Subject: [PATCH 297/773] MC-13958: Additional Permissions for Design settings --- .../Catalog/Model/CategoryRepository.php | 3 +++ .../Catalog/Model/ResourceModel/Category.php | 15 --------------- .../Catalog/Model/CategoryRepositoryTest.php | 19 +++++++++++++++++++ 3 files changed, 22 insertions(+), 15 deletions(-) diff --git a/app/code/Magento/Catalog/Model/CategoryRepository.php b/app/code/Magento/Catalog/Model/CategoryRepository.php index 7485d9f6cb247..61bb0c76b62dc 100644 --- a/app/code/Magento/Catalog/Model/CategoryRepository.php +++ b/app/code/Magento/Catalog/Model/CategoryRepository.php @@ -102,6 +102,9 @@ public function save(\Magento\Catalog\Api\Data\CategoryInterface $category) } } } else { + //Clearing all redundant data and using only properly extracted data for the entity. + /** @var Category $category */ + $category = $this->categoryFactory->create(); $parentId = $category->getParentId() ?: $this->storeManager->getStore()->getRootCategoryId(); $parentCategory = $this->get($parentId, $storeId); $existingData['path'] = $parentCategory->getPath(); diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Category.php b/app/code/Magento/Catalog/Model/ResourceModel/Category.php index 10647effd5764..786cec391c460 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Category.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Category.php @@ -1134,19 +1134,4 @@ private function getAggregateCount() } return $this->aggregateCount; } - - /** - * @inheritDoc - * - * @param CategoryEntity|object $object - */ - public function validate($object) - { - $isValid = parent::validate($object); - if ($isValid !== true) { - return $isValid; - } - - return true; - } } diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/CategoryRepositoryTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/CategoryRepositoryTest.php index df9774ceddba2..c80915fcbdc2f 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Model/CategoryRepositoryTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/CategoryRepositoryTest.php @@ -9,6 +9,8 @@ use Magento\Backend\Model\Auth; use Magento\Catalog\Api\CategoryRepositoryInterface; +use Magento\Catalog\Api\Data\CategoryInterface; +use Magento\Catalog\Api\Data\CategoryInterfaceFactory; use Magento\Framework\Acl\Builder; use Magento\TestFramework\Helper\Bootstrap; use PHPUnit\Framework\TestCase; @@ -36,6 +38,11 @@ class CategoryRepositoryTest extends TestCase */ private $aclBuilder; + /** + * @var CategoryInterfaceFactory + */ + private $categoryFactory; + /** * Sets up common objects. * @@ -46,6 +53,7 @@ protected function setUp() $this->repo = Bootstrap::getObjectManager()->create(CategoryRepositoryInterface::class); $this->auth = Bootstrap::getObjectManager()->get(Auth::class); $this->aclBuilder = Bootstrap::getObjectManager()->get(Builder::class); + $this->categoryFactory = Bootstrap::getObjectManager()->get(CategoryInterfaceFactory::class); } /** @@ -87,5 +95,16 @@ public function testSaveDesign() $category = $this->repo->save($category); $this->assertNotEmpty($category->getCustomAttribute('custom_design')); $this->assertEquals(2, $category->getCustomAttribute('custom_design')->getValue()); + + //Creating a new one + /** @var CategoryInterface $newCategory */ + $newCategory = $this->categoryFactory->create(); + $newCategory->setName('new category without design'); + $newCategory->setParentId($category->getParentId()); + $newCategory->setIsActive(true); + $this->aclBuilder->getAcl()->deny(null, 'Magento_Catalog::edit_category_design'); + $newCategory->setCustomAttribute('custom_design', 2); + $newCategory = $this->repo->save($newCategory); + $this->assertEmpty($newCategory->getCustomAttribute('custom_design')); } } From 5a5b4062aa93577520a029baed0f07f5fbb7f955 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun <ogorkun@magento.com> Date: Fri, 26 Apr 2019 14:08:22 -0500 Subject: [PATCH 298/773] MC-13958: Additional Permissions for Design settings --- .../Magento/Catalog/Model/CategoryRepository.php | 14 ++++++++++---- app/code/Magento/Catalog/Model/Product.php | 4 ++-- .../Catalog/Model/ResourceModel/Product.php | 2 +- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/app/code/Magento/Catalog/Model/CategoryRepository.php b/app/code/Magento/Catalog/Model/CategoryRepository.php index 61bb0c76b62dc..31dd747f6e4ab 100644 --- a/app/code/Magento/Catalog/Model/CategoryRepository.php +++ b/app/code/Magento/Catalog/Model/CategoryRepository.php @@ -13,6 +13,8 @@ use Magento\Catalog\Api\Data\CategoryInterface; /** + * Repository for categories. + * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class CategoryRepository implements \Magento\Catalog\Api\CategoryRepositoryInterface @@ -70,7 +72,7 @@ public function __construct( } /** - * {@inheritdoc} + * @inheritdoc */ public function save(\Magento\Catalog\Api\Data\CategoryInterface $category) { @@ -128,7 +130,7 @@ public function save(\Magento\Catalog\Api\Data\CategoryInterface $category) } /** - * {@inheritdoc} + * @inheritdoc */ public function get($categoryId, $storeId = null) { @@ -149,7 +151,7 @@ public function get($categoryId, $storeId = null) } /** - * {@inheritdoc} + * @inheritdoc */ public function delete(\Magento\Catalog\Api\Data\CategoryInterface $category) { @@ -170,7 +172,7 @@ public function delete(\Magento\Catalog\Api\Data\CategoryInterface $category) } /** - * {@inheritdoc} + * @inheritdoc */ public function deleteByIdentifier($categoryId) { @@ -211,6 +213,8 @@ protected function validateCategory(Category $category) } /** + * Lazy loader for the converter. + * * @return \Magento\Framework\Api\ExtensibleDataObjectConverter * * @deprecated 101.0.0 @@ -225,6 +229,8 @@ private function getExtensibleDataObjectConverter() } /** + * Lazy loader for the metadata pool. + * * @return \Magento\Framework\EntityManager\MetadataPool */ private function getMetadataPool() diff --git a/app/code/Magento/Catalog/Model/Product.php b/app/code/Magento/Catalog/Model/Product.php index af8401d3df1a9..d43bc51eb7273 100644 --- a/app/code/Magento/Catalog/Model/Product.php +++ b/app/code/Magento/Catalog/Model/Product.php @@ -1202,7 +1202,7 @@ public function getFormattedPrice() /** * Get formatted by currency product price * - * @return array|double + * @return array|double * * @deprecated * @see getFormattedPrice() @@ -1853,7 +1853,7 @@ public function formatUrlKey($str) /** * Save current attribute with code $code and assign new value * - * @param string $code Attribute code + * @param string $code Attribute code * @param mixed $value New attribute value * @param int $store Store ID * @return void diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product.php b/app/code/Magento/Catalog/Model/ResourceModel/Product.php index 484bb6f588b8c..464df2ef4c249 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product.php @@ -670,7 +670,7 @@ protected function evaluateDelete($object, $id, $connection) /** * Save entity's attributes into the object's resource * - * @param \Magento\Framework\Model\AbstractModel $object + * @param \Magento\Framework\Model\AbstractModel $object * @return $this * @throws \Exception * @since 101.0.0 From b643af828555ecc501ca5713977b713d7e5ce6b5 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun <ogorkun@magento.com> Date: Fri, 26 Apr 2019 16:31:06 -0500 Subject: [PATCH 299/773] MC-13958: Additional Permissions for Design settings --- app/code/Magento/Catalog/Model/Category.php | 14 ++++++++------ .../Magento/Catalog/Model/CategoryRepository.php | 3 --- .../Catalog/Model/CategoryRepositoryTest.php | 6 ++++-- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Category.php b/app/code/Magento/Catalog/Model/Category.php index b864b7fdafad2..a5aeb574f0a54 100644 --- a/app/code/Magento/Catalog/Model/Category.php +++ b/app/code/Magento/Catalog/Model/Category.php @@ -948,12 +948,14 @@ public function beforeSave() ) && !$this->authorization->isAllowed('Magento_Catalog::edit_category_design') ) { - $this->setData('custom_design', $this->getOrigData('custom_design')); - $this->setData('custom_design_from', $this->getOrigData('custom_design_from')); - $this->setData('custom_design_to', $this->getOrigData('custom_design_to')); - $this->setData('page_layout', $this->getOrigData('page_layout')); - $this->setData('custom_layout_update', $this->getOrigData('custom_layout_update')); - $this->setData('custom_apply_to_products', $this->getOrigData('custom_apply_to_products')); + $this->getCustomAttributes(); + foreach ($this->_designAttributes as $attributeCode) { + $this->setData($attributeCode, $value = $this->getOrigData($attributeCode)); + if (array_key_exists($attributeCode, $this->_data[self::CUSTOM_ATTRIBUTES])) { + //In case custom attribute were used to update the entity. + $this->_data[self::CUSTOM_ATTRIBUTES][$attributeCode]->setValue($value); + } + } } return parent::beforeSave(); diff --git a/app/code/Magento/Catalog/Model/CategoryRepository.php b/app/code/Magento/Catalog/Model/CategoryRepository.php index 31dd747f6e4ab..a8636306f5e5b 100644 --- a/app/code/Magento/Catalog/Model/CategoryRepository.php +++ b/app/code/Magento/Catalog/Model/CategoryRepository.php @@ -104,9 +104,6 @@ public function save(\Magento\Catalog\Api\Data\CategoryInterface $category) } } } else { - //Clearing all redundant data and using only properly extracted data for the entity. - /** @var Category $category */ - $category = $this->categoryFactory->create(); $parentId = $category->getParentId() ?: $this->storeManager->getStore()->getRootCategoryId(); $parentCategory = $this->get($parentId, $storeId); $existingData['path'] = $parentCategory->getPath(); diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/CategoryRepositoryTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/CategoryRepositoryTest.php index c80915fcbdc2f..f1e235f8c9bf2 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Model/CategoryRepositoryTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/CategoryRepositoryTest.php @@ -85,7 +85,8 @@ public function testSaveDesign() $category->setCustomAttribute('custom_design', 2); $category = $this->repo->save($category); - $this->assertEmpty($category->getCustomAttribute('custom_design')); + $customDesignAttribute = $category->getCustomAttribute('custom_design'); + $this->assertTrue(!$customDesignAttribute || !$customDesignAttribute->getValue()); //Admin has access to category' design. $this->aclBuilder->getAcl() @@ -105,6 +106,7 @@ public function testSaveDesign() $this->aclBuilder->getAcl()->deny(null, 'Magento_Catalog::edit_category_design'); $newCategory->setCustomAttribute('custom_design', 2); $newCategory = $this->repo->save($newCategory); - $this->assertEmpty($newCategory->getCustomAttribute('custom_design')); + $customDesignAttribute = $newCategory->getCustomAttribute('custom_design'); + $this->assertTrue(!$customDesignAttribute || !$customDesignAttribute->getValue()); } } From 43d7516b8b82fee92e9a8ee784ce2173ec2885ea Mon Sep 17 00:00:00 2001 From: Daniel Renaud <drenaud@magento.com> Date: Mon, 29 Apr 2019 12:04:44 -0500 Subject: [PATCH 300/773] MC-15882: GraphQL getTree method does not work correctly --- .../Magento/CatalogGraphQl/Model/Category/LevelCalculator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/CatalogGraphQl/Model/Category/LevelCalculator.php b/app/code/Magento/CatalogGraphQl/Model/Category/LevelCalculator.php index f587be245c99d..67ca3b85d6f2f 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Category/LevelCalculator.php +++ b/app/code/Magento/CatalogGraphQl/Model/Category/LevelCalculator.php @@ -48,7 +48,7 @@ public function calculate(int $rootCategoryId) : int $connection = $this->resourceConnection->getConnection(); $select = $connection->select() ->from($this->resourceConnection->getTableName('catalog_category_entity'), 'level') - ->where($this->resourceCategory->getLinkField() . " = ?", $rootCategoryId); + ->where($this->resourceCategory->getEntityIdField() . " = ?", $rootCategoryId); return (int) $connection->fetchOne($select); } From f1e5df1a7f6878b137e44777ad23f56d39058295 Mon Sep 17 00:00:00 2001 From: Kavitha <kanair@adobe.com> Date: Mon, 29 Apr 2019 13:28:54 -0500 Subject: [PATCH 301/773] MC-4459: Convert OnePageCheckoutOfflinePaymentMethodsTest to MFTF --- .../CheckoutFillEstimateShippingAndTaxActionGroup.xml | 4 ++-- .../FillGuestCheckoutShippingAddressFormActionGroup.xml | 6 +++--- .../Checkout/Test/Mftf/Section/CheckoutPaymentSection.xml | 2 +- .../Checkout/Test/Mftf/Section/CheckoutShippingSection.xml | 2 +- .../Test/Mftf/Section/CheckoutSuccessMainSection.xml | 2 +- .../ActionGroup/StorefrontFillBillingAddressActionGroup.xml | 2 +- .../Mftf/Section/StorefrontCustomerAddressesSection.xml | 4 ++-- .../Mftf/Section/StorefrontCustomerSignInFormSection.xml | 2 +- 8 files changed, 12 insertions(+), 12 deletions(-) diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/CheckoutFillEstimateShippingAndTaxActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/CheckoutFillEstimateShippingAndTaxActionGroup.xml index 985d9d3bee186..f564e14989e75 100644 --- a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/CheckoutFillEstimateShippingAndTaxActionGroup.xml +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/CheckoutFillEstimateShippingAndTaxActionGroup.xml @@ -10,12 +10,12 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="CheckoutFillEstimateShippingAndTaxActionGroup"> <arguments> - <argument name="address" defaultValue="US_Address_TX"/> + <argument name="address" defaultValue="US_Address_TX" type="entity"/> </arguments> <conditionalClick selector="{{CheckoutCartSummarySection.estimateShippingAndTax}}" dependentSelector="{{CheckoutCartSummarySection.estimateShippingAndTaxSummary}}" visible="false" stepKey="openShippingDetails"/> <selectOption selector="{{CheckoutCartSummarySection.country}}" userInput="{{address.country_id}}" stepKey="selectCountry"/> <selectOption selector="{{CheckoutCartSummarySection.stateProvince}}" userInput="{{address.state}}" stepKey="selectState"/> - <waitForElementVisible selector="{{CheckoutCartSummarySection.postcode}}" stepKey="waitForPasswordFieldToBeVisisble"/> + <waitForElementVisible selector="{{CheckoutCartSummarySection.postcode}}" stepKey="waitForPostCodeVisible"/> <fillField selector="{{CheckoutCartSummarySection.postcode}}" userInput="{{address.postcode}}" stepKey="selectPostCode"/> <waitForLoadingMaskToDisappear stepKey="waitForLoadingMaskToDiappear"/> </actionGroup> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/FillGuestCheckoutShippingAddressFormActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/FillGuestCheckoutShippingAddressFormActionGroup.xml index 3203c8eef5ac6..80fd604e752e9 100644 --- a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/FillGuestCheckoutShippingAddressFormActionGroup.xml +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/FillGuestCheckoutShippingAddressFormActionGroup.xml @@ -10,8 +10,8 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="FillGuestCheckoutShippingAddressFormActionGroup"> <arguments> - <argument name="customer" defaultValue="Simple_US_Customer"/> - <argument name="customerAddress" defaultValue="US_Address_TX"/> + <argument name="customer" defaultValue="Simple_US_Customer" type="entity"/> + <argument name="customerAddress" defaultValue="US_Address_TX" type="entity"/> </arguments> <fillField selector="{{CheckoutShippingSection.emailAddress}}" userInput="{{customer.email}}" stepKey="setCustomerEmail"/> <fillField selector="{{CheckoutShippingSection.firstName}}" userInput="{{customer.firstname}}" stepKey="SetCustomerFirstName"/> @@ -22,6 +22,6 @@ <fillField selector="{{CheckoutShippingSection.telephone}}" userInput="{{customerAddress.telephone}}" stepKey="SetCustomerPhoneNumber"/> </actionGroup> <actionGroup name="FillGuestCheckoutShippingAddressWithCountryActionGroup" extends="FillGuestCheckoutShippingAddressFormActionGroup"> - <selectOption selector="{{CheckoutShippingSection.country}}" userInput="{{customerAddress.country_id}}" stepKey="selectCountry" after="SetCustomerCity"/> + <selectOption selector="{{CheckoutShippingSection.country}}" userInput="{{customerAddress.country_id}}" stepKey="selectCustomerCountry" after="SetCustomerCity"/> </actionGroup> </actionGroups> \ No newline at end of file diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutPaymentSection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutPaymentSection.xml index eed49065e375f..ce3f3829fe458 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutPaymentSection.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutPaymentSection.xml @@ -54,7 +54,7 @@ <element name="addressBook" type="button" selector="//a[text()='Address Book']"/> <element name="noQuotes" type="text" selector=".no-quotes-block"/> <element name="paymentMethodByName" type="text" selector="//*[@id='checkout-payment-method-load']//*[contains(@class, 'payment-group')]//label[normalize-space(.)='{{var1}}']" parameterized="true"/> - <element name="bankTransfer" type="radio" selector="//input[@id='banktransfer']"/> + <element name="bankTransfer" type="radio" selector="#banktransfer"/> <element name="billingAddressNotSameBankTransferCheckbox" type="checkbox" selector="#billing-address-same-as-shipping-banktransfer"/> <element name="billingAddressSelectShared" type="select" selector=".checkout-billing-address select[name='billing_address_id']"/> </section> diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingSection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingSection.xml index ba4f42d3dca2b..1081506b9e595 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingSection.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingSection.xml @@ -38,7 +38,7 @@ <element name="editActiveAddress" type="button" selector="//div[@class='shipping-address-item selected-item']//span[text()='Edit']" timeout="30"/> <element name="password" type="input" selector="#customer-password"/> <element name="loginButton" type="button" selector="//button[@data-action='checkout-method-login']" timeout="30"/> - <element name="editActiveAddressButton" type="button" selector="//div[@class='payment-method _active']//button[@class='action action-edit-address']" timeout="30"/> + <element name="editActiveAddressButton" type="button" selector="//div[contains(@class,'payment-method _active')]//button[contains(@class,'action action-edit-address')]" timeout="30"/> <element name="emailAddress" type="input" selector="#checkout-customer-email"/> </section> </sections> diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutSuccessMainSection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutSuccessMainSection.xml index 04eda22c31913..6414d65f7d1aa 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutSuccessMainSection.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutSuccessMainSection.xml @@ -18,6 +18,6 @@ <element name="continueShoppingButton" type="button" selector=".action.primary.continue" timeout="30"/> <element name="createAnAccount" type="button" selector="input[value='Create an Account']" timeout="30"/> <element name="printLink" type="button" selector=".print" timeout="30"/> - <element name="orderNumberWithoutLink" type="text" selector="//div[@class='checkout-success']/p/span"/> + <element name="orderNumberWithoutLink" type="text" selector="//div[contains(@class, 'checkout-success')]//p/span"/> </section> </sections> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontFillBillingAddressActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontFillBillingAddressActionGroup.xml index 1521f8c6f1f71..accf8f40bb282 100644 --- a/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontFillBillingAddressActionGroup.xml +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontFillBillingAddressActionGroup.xml @@ -10,7 +10,7 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="StorefrontFillBillingAddressActionGroup"> <arguments> - <argument name="address" defaultValue="CustomerUKAddress"/> + <argument name="address" defaultValue="CustomerUKAddress" type="entity"/> </arguments> <fillField selector="{{CheckoutPaymentSection.guestFirstName}}" userInput="{{address.firstname}}" stepKey="enterFirstName"/> <fillField selector="{{CheckoutPaymentSection.guestLastName}}" userInput="{{address.lastname}}" stepKey="enterLastName"/> diff --git a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerAddressesSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerAddressesSection.xml index 52430cfb0225c..0c9475409e42f 100644 --- a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerAddressesSection.xml +++ b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerAddressesSection.xml @@ -18,7 +18,7 @@ <element name="editAdditionalAddress" type="button" selector="//tbody//tr[{{var}}]//a[@class='action edit']" parameterized="true" timeout="30"/> <element name="addNewAddress" type="button" selector="//span[text()='Add New Address']"/> <element name="numberOfAddresses" type="text" selector=".toolbar-number"/> - <element name="shippingAddress" type="text" selector="//div[@class='box box-shipping-address']//div/address"/> - <element name="billingAddress" type="text" selector="//div[@class='box box-billing-address']//div/address"/> + <element name="shippingAddress" type="text" selector="//div[contains(@class,'box box-shipping-address')]//div/address"/> + <element name="billingAddress" type="text" selector="//div[contains(@class,'box box-billing-address')]//div/address"/> </section> </sections> diff --git a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerSignInFormSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerSignInFormSection.xml index 99eb54627eb26..f68a283291675 100644 --- a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerSignInFormSection.xml +++ b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerSignInFormSection.xml @@ -19,6 +19,6 @@ <element name="email" type="input" selector="#customer-email"/> <element name="password" type="input" selector="#pass"/> <element name="signIn" type="button" selector="#send2" timeout="30"/> - <element name="createAnAccount" type="button" selector="//div[@class='actions-toolbar']//a[contains(.,'Create an Account')]" timeout="30"/> + <element name="createAnAccount" type="button" selector="//div[contains(@class,'actions-toolbar')]//a[contains(.,'Create an Account')]" timeout="30"/> </section> </sections> From 8fba0f8dae008b5ebdfe239c8d2c7af85a7e086c Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun <ogorkun@magento.com> Date: Tue, 30 Apr 2019 12:16:26 -0500 Subject: [PATCH 302/773] MC-16089: Category saved through API with parent category, saved like root category --- app/code/Magento/Catalog/Model/Category.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/code/Magento/Catalog/Model/Category.php b/app/code/Magento/Catalog/Model/Category.php index a5aeb574f0a54..84893797dd5ea 100644 --- a/app/code/Magento/Catalog/Model/Category.php +++ b/app/code/Magento/Catalog/Model/Category.php @@ -948,7 +948,6 @@ public function beforeSave() ) && !$this->authorization->isAllowed('Magento_Catalog::edit_category_design') ) { - $this->getCustomAttributes(); foreach ($this->_designAttributes as $attributeCode) { $this->setData($attributeCode, $value = $this->getOrigData($attributeCode)); if (array_key_exists($attributeCode, $this->_data[self::CUSTOM_ATTRIBUTES])) { From 8e91f7995084bd5c2c7637f9f5213ce7872ba3c6 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun <ogorkun@magento.com> Date: Tue, 30 Apr 2019 15:49:57 -0500 Subject: [PATCH 303/773] MC-16089: Category saved through API with parent category, saved like root category --- app/code/Magento/Catalog/Model/Category.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Model/Category.php b/app/code/Magento/Catalog/Model/Category.php index 84893797dd5ea..61c9962486ad1 100644 --- a/app/code/Magento/Catalog/Model/Category.php +++ b/app/code/Magento/Catalog/Model/Category.php @@ -950,7 +950,8 @@ public function beforeSave() ) { foreach ($this->_designAttributes as $attributeCode) { $this->setData($attributeCode, $value = $this->getOrigData($attributeCode)); - if (array_key_exists($attributeCode, $this->_data[self::CUSTOM_ATTRIBUTES])) { + if (!empty($this->_data[self::CUSTOM_ATTRIBUTES]) + && array_key_exists($attributeCode, $this->_data[self::CUSTOM_ATTRIBUTES])) { //In case custom attribute were used to update the entity. $this->_data[self::CUSTOM_ATTRIBUTES][$attributeCode]->setValue($value); } From bc7a00c2e7636301306d97449609cabce11ca9e4 Mon Sep 17 00:00:00 2001 From: Vitalii Zabaznov <vzabaznov@magento.com> Date: Wed, 1 May 2019 11:10:38 -0500 Subject: [PATCH 304/773] MC-16005: Deferred loading / parsing of JS p2 --- app/code/Magento/Backend/etc/adminhtml/system.xml | 4 ---- app/code/Magento/Theme/Controller/Result/JsFooterPlugin.php | 2 +- app/code/Magento/Theme/etc/{ => adminhtml}/system.xml | 4 ++-- app/code/Magento/Theme/etc/config.xml | 2 +- 4 files changed, 4 insertions(+), 8 deletions(-) rename app/code/Magento/Theme/etc/{ => adminhtml}/system.xml (80%) diff --git a/app/code/Magento/Backend/etc/adminhtml/system.xml b/app/code/Magento/Backend/etc/adminhtml/system.xml index 65744e56d94ac..c762dbf58de62 100644 --- a/app/code/Magento/Backend/etc/adminhtml/system.xml +++ b/app/code/Magento/Backend/etc/adminhtml/system.xml @@ -182,10 +182,6 @@ <source_model>Magento\Config\Model\Config\Source\Yesno</source_model> <comment>Minification is not applied in developer mode.</comment> </field> - <field id="move_inline_to_bottom" translate="label" type="select" sortOrder="25" showInDefault="1" showInWebsite="1" showInStore="1" canRestore="1"> - <label>Move JS code to the bottom of the page</label> - <source_model>Magento\Config\Model\Config\Source\Yesno</source_model> - </field> </group> <group id="css" translate="label" type="text" sortOrder="110" showInDefault="1" showInWebsite="1" showInStore="1"> <label>CSS Settings</label> diff --git a/app/code/Magento/Theme/Controller/Result/JsFooterPlugin.php b/app/code/Magento/Theme/Controller/Result/JsFooterPlugin.php index a234cd589904c..0ca435c506647 100644 --- a/app/code/Magento/Theme/Controller/Result/JsFooterPlugin.php +++ b/app/code/Magento/Theme/Controller/Result/JsFooterPlugin.php @@ -14,7 +14,7 @@ */ class JsFooterPlugin { - private const XML_PATH_DEV_MOVE_JS_TO_BOTTOM = 'dev/js/move_inline_to_bottom'; + private const XML_PATH_DEV_MOVE_JS_TO_BOTTOM = 'dev/js/move_script_to_bottom'; /** * @var ScopeConfigInterface diff --git a/app/code/Magento/Theme/etc/system.xml b/app/code/Magento/Theme/etc/adminhtml/system.xml similarity index 80% rename from app/code/Magento/Theme/etc/system.xml rename to app/code/Magento/Theme/etc/adminhtml/system.xml index 4abc87e845122..b0d3ba90e8edb 100644 --- a/app/code/Magento/Theme/etc/system.xml +++ b/app/code/Magento/Theme/etc/adminhtml/system.xml @@ -8,8 +8,8 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Config:etc/system_file.xsd"> <system> <section id="dev" translate="label" type="text" sortOrder="920" showInDefault="1" showInWebsite="1" showInStore="1"> - <group id="js" translate="label" type="text" sortOrder="100" showInDefault="1" showInWebsite="1" showInStore="1"> - <field id="move_inline_to_bottom" translate="label" type="select" sortOrder="25" showInDefault="1" showInWebsite="1" showInStore="1" canRestore="1"> + <group id="js"> + <field id="move_script_to_bottom" translate="label" type="select" sortOrder="25" showInDefault="1" showInWebsite="1" showInStore="1" canRestore="1"> <label>Move JS code to the bottom of the page</label> <source_model>Magento\Config\Model\Config\Source\Yesno</source_model> </field> diff --git a/app/code/Magento/Theme/etc/config.xml b/app/code/Magento/Theme/etc/config.xml index 37841789c0e10..f5cc312101fe8 100644 --- a/app/code/Magento/Theme/etc/config.xml +++ b/app/code/Magento/Theme/etc/config.xml @@ -68,7 +68,7 @@ Disallow: /*SID= </static> <dev> <js> - <move_inline_to_bottom>0</move_inline_to_bottom> + <move_script_to_bottom>0</move_script_to_bottom> </js> </dev> </dev> From 05e7ec2a8a82c6f5751c5fc3f10f57495825dc87 Mon Sep 17 00:00:00 2001 From: Patrick McLain <pat@pmclain.com> Date: Wed, 24 Apr 2019 20:59:18 -0400 Subject: [PATCH 305/773] Test for offline payment methods Fixes #601 --- .../SetOfflinePaymentMethodsOnCartTest.php | 168 ++++++++++++++++++ .../SetOfflinePaymentMethodsOnCartTest.php | 147 +++++++++++++++ 2 files changed, 315 insertions(+) create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetOfflinePaymentMethodsOnCartTest.php create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetOfflinePaymentMethodsOnCartTest.php diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetOfflinePaymentMethodsOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetOfflinePaymentMethodsOnCartTest.php new file mode 100644 index 0000000000000..e0f4756177715 --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetOfflinePaymentMethodsOnCartTest.php @@ -0,0 +1,168 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQl\Quote\Customer; + +use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; +use Magento\Integration\Api\CustomerTokenServiceInterface; +use Magento\OfflinePayments\Model\Banktransfer; +use Magento\OfflinePayments\Model\Cashondelivery; +use Magento\OfflinePayments\Model\Checkmo; +use Magento\OfflinePayments\Model\Purchaseorder; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\TestCase\GraphQlAbstract; + +/** + * Test for setting offline payment methods on cart + */ +class SetOfflinePaymentMethodsOnCartTest extends GraphQlAbstract +{ + /** + * @var GetMaskedQuoteIdByReservedOrderId + */ + private $getMaskedQuoteIdByReservedOrderId; + + /** + * @var CustomerTokenServiceInterface + */ + private $customerTokenService; + + /** + * @inheritdoc + */ + protected function setUp() + { + $objectManager = Bootstrap::getObjectManager(); + $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); + $this->customerTokenService = $objectManager->get(CustomerTokenServiceInterface::class); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_payment_methods.php + * + * @param string $methodCode + * @dataProvider offlinePaymentMethodDataProvider + */ + public function testSetOfflinePaymentMethod(string $methodCode) + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + + $query = $this->getQuery( + $maskedQuoteId, + $methodCode + ); + $response = $this->graphQlMutation($query, [], '', $this->getHeaderMap()); + + self::assertArrayHasKey('setPaymentMethodOnCart', $response); + self::assertArrayHasKey('cart', $response['setPaymentMethodOnCart']); + self::assertArrayHasKey('selected_payment_method', $response['setPaymentMethodOnCart']['cart']); + self::assertArrayHasKey('code', $response['setPaymentMethodOnCart']['cart']['selected_payment_method']); + self::assertEquals($methodCode, $response['setPaymentMethodOnCart']['cart']['selected_payment_method']['code']); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_payment_methods.php + * + * @param string $methodCode + */ + public function testSetPurchaseOrderPaymentMethod() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $methodCode = Purchaseorder::PAYMENT_METHOD_PURCHASEORDER_CODE; + $poNumber = 'abc123'; + + $query = <<<QUERY +mutation { + setPaymentMethodOnCart(input: { + cart_id: "{$maskedQuoteId}", + payment_method: { + code: "{$methodCode}" + purchase_order_number: "{$poNumber}" + } + }) { + cart { + selected_payment_method { + code + purchase_order_number + } + } + } +} +QUERY; + + $response = $this->graphQlMutation($query, [], '', $this->getHeaderMap()); + + self::assertArrayHasKey('setPaymentMethodOnCart', $response); + self::assertArrayHasKey('cart', $response['setPaymentMethodOnCart']); + self::assertArrayHasKey('selected_payment_method', $response['setPaymentMethodOnCart']['cart']); + self::assertArrayHasKey('code', $response['setPaymentMethodOnCart']['cart']['selected_payment_method']); + self::assertArrayHasKey('purchase_order_number', $response['setPaymentMethodOnCart']['cart']['selected_payment_method']); + self::assertEquals($methodCode, $response['setPaymentMethodOnCart']['cart']['selected_payment_method']['code']); + self::assertEquals($poNumber, $response['setPaymentMethodOnCart']['cart']['selected_payment_method']['purchase_order_number']); + } + + /** + * @return array + */ + public function offlinePaymentMethodDataProvider(): array + { + return [ + 'check_mo' => [Checkmo::PAYMENT_METHOD_CHECKMO_CODE], + 'bank_transfer' => [Banktransfer::PAYMENT_METHOD_BANKTRANSFER_CODE], + 'cash_on_delivery' => [Cashondelivery::PAYMENT_METHOD_CASHONDELIVERY_CODE], + ]; + } + + /** + * @param string $maskedQuoteId + * @param string $methodCode + * @return string + */ + private function getQuery( + string $maskedQuoteId, + string $methodCode + ) : string { + return <<<QUERY +mutation { + setPaymentMethodOnCart(input: { + cart_id: "{$maskedQuoteId}", + payment_method: { + code: "{$methodCode}" + } + }) { + cart { + selected_payment_method { + code + } + } + } +} +QUERY; + } + + /** + * @param string $username + * @param string $password + * @return array + */ + private function getHeaderMap(string $username = 'customer@example.com', string $password = 'password'): array + { + $customerToken = $this->customerTokenService->createCustomerAccessToken($username, $password); + $headerMap = ['Authorization' => 'Bearer ' . $customerToken]; + return $headerMap; + } +} diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetOfflinePaymentMethodsOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetOfflinePaymentMethodsOnCartTest.php new file mode 100644 index 0000000000000..83fffd9defabf --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetOfflinePaymentMethodsOnCartTest.php @@ -0,0 +1,147 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQl\Quote\Guest; + +use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; +use Magento\OfflinePayments\Model\Banktransfer; +use Magento\OfflinePayments\Model\Cashondelivery; +use Magento\OfflinePayments\Model\Checkmo; +use Magento\OfflinePayments\Model\Purchaseorder; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\TestCase\GraphQlAbstract; + +/** + * Test for setting offline payment methods on cart + */ +class SetOfflinePaymentMethodsOnCartTest extends GraphQlAbstract +{ + /** + * @var GetMaskedQuoteIdByReservedOrderId + */ + private $getMaskedQuoteIdByReservedOrderId; + + /** + * @inheritdoc + */ + protected function setUp() + { + $objectManager = Bootstrap::getObjectManager(); + $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); + } + + /** + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_payment_methods.php + * + * @param string $methodCode + * @dataProvider offlinePaymentMethodDataProvider + */ + public function testSetOfflinePaymentMethod(string $methodCode) + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + + $query = $this->getQuery( + $maskedQuoteId, + $methodCode + ); + $response = $this->graphQlMutation($query); + + self::assertArrayHasKey('setPaymentMethodOnCart', $response); + self::assertArrayHasKey('cart', $response['setPaymentMethodOnCart']); + self::assertArrayHasKey('selected_payment_method', $response['setPaymentMethodOnCart']['cart']); + self::assertArrayHasKey('code', $response['setPaymentMethodOnCart']['cart']['selected_payment_method']); + self::assertEquals($methodCode, $response['setPaymentMethodOnCart']['cart']['selected_payment_method']['code']); + } + + /** + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_payment_methods.php + * + * @param string $methodCode + */ + public function testSetPurchaseOrderPaymentMethod() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $methodCode = Purchaseorder::PAYMENT_METHOD_PURCHASEORDER_CODE; + $poNumber = 'abc123'; + + $query = <<<QUERY +mutation { + setPaymentMethodOnCart(input: { + cart_id: "{$maskedQuoteId}", + payment_method: { + code: "{$methodCode}" + purchase_order_number: "{$poNumber}" + } + }) { + cart { + selected_payment_method { + code + purchase_order_number + } + } + } +} +QUERY; + + $response = $this->graphQlMutation($query); + + self::assertArrayHasKey('setPaymentMethodOnCart', $response); + self::assertArrayHasKey('cart', $response['setPaymentMethodOnCart']); + self::assertArrayHasKey('selected_payment_method', $response['setPaymentMethodOnCart']['cart']); + self::assertArrayHasKey('code', $response['setPaymentMethodOnCart']['cart']['selected_payment_method']); + self::assertArrayHasKey('purchase_order_number', $response['setPaymentMethodOnCart']['cart']['selected_payment_method']); + self::assertEquals($methodCode, $response['setPaymentMethodOnCart']['cart']['selected_payment_method']['code']); + self::assertEquals($poNumber, $response['setPaymentMethodOnCart']['cart']['selected_payment_method']['purchase_order_number']); + } + + /** + * @return array + */ + public function offlinePaymentMethodDataProvider(): array + { + return [ + 'check_mo' => [Checkmo::PAYMENT_METHOD_CHECKMO_CODE], + 'bank_transfer' => [Banktransfer::PAYMENT_METHOD_BANKTRANSFER_CODE], + 'cash_on_delivery' => [Cashondelivery::PAYMENT_METHOD_CASHONDELIVERY_CODE], + ]; + } + + /** + * @param string $maskedQuoteId + * @param string $methodCode + * @return string + */ + private function getQuery( + string $maskedQuoteId, + string $methodCode + ) : string { + return <<<QUERY +mutation { + setPaymentMethodOnCart(input: { + cart_id: "{$maskedQuoteId}", + payment_method: { + code: "{$methodCode}" + } + }) { + cart { + selected_payment_method { + code + } + } + } +} +QUERY; + } +} From b35ec0084d2f80892f5d8c9e413943abf1994314 Mon Sep 17 00:00:00 2001 From: Oscar Recio <osrecio@gmail.com> Date: Thu, 25 Apr 2019 16:45:56 +0200 Subject: [PATCH 306/773] #631 Rename qty by quantity Rename CartItemQuantityInput by CartItemUpdateQuantityInput Rename CartItemInput by CartItemQuantityInput Adapt tests --- .../ConfigurableProductGraphQl/etc/schema.graphqls | 2 +- .../Model/Cart/AddSimpleProductToCart.php | 4 ++-- .../QuoteGraphQl/Model/Resolver/CartItems.php | 2 +- app/code/Magento/QuoteGraphQl/etc/schema.graphqls | 14 +++++++------- .../CatalogInventory/AddProductToCartTest.php | 4 ++-- .../AddConfigurableProductToCartTest.php | 6 +++--- ...AddSimpleProductWithCustomOptionsToCartTest.php | 4 ++-- ...ddVirtualProductWithCustomOptionsToCartTest.php | 4 ++-- .../Quote/Customer/AddSimpleProductToCartTest.php | 6 +++--- .../Quote/Customer/AddVirtualProductToCartTest.php | 6 +++--- .../Quote/Customer/CheckoutEndToEndTest.php | 4 ++-- .../Magento/GraphQl/Quote/Customer/GetCartTest.php | 6 +++--- .../Quote/Customer/RemoveItemFromCartTest.php | 4 ++-- .../Quote/Customer/SetPaymentMethodOnCartTest.php | 2 +- .../GraphQl/Quote/Customer/UpdateCartItemsTest.php | 10 +++++----- .../Quote/Guest/AddSimpleProductToCartTest.php | 6 +++--- .../Quote/Guest/AddVirtualProductToCartTest.php | 6 +++--- .../GraphQl/Quote/Guest/CheckoutEndToEndTest.php | 4 ++-- .../Magento/GraphQl/Quote/Guest/GetCartTest.php | 6 +++--- .../GraphQl/Quote/Guest/RemoveItemFromCartTest.php | 4 ++-- .../Quote/Guest/SetPaymentMethodOnCartTest.php | 2 +- .../GraphQl/Quote/Guest/UpdateCartItemsTest.php | 10 +++++----- 22 files changed, 58 insertions(+), 58 deletions(-) diff --git a/app/code/Magento/ConfigurableProductGraphQl/etc/schema.graphqls b/app/code/Magento/ConfigurableProductGraphQl/etc/schema.graphqls index d4780c5c0867a..bf4ff723a646f 100644 --- a/app/code/Magento/ConfigurableProductGraphQl/etc/schema.graphqls +++ b/app/code/Magento/ConfigurableProductGraphQl/etc/schema.graphqls @@ -49,7 +49,7 @@ type AddConfigurableProductsToCartOutput { } input ConfigurableProductCartItemInput { - data: CartItemInput! + data: CartItemQuantityInput! variant_sku: String! customizable_options:[CustomizableOptionInput!] } diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php b/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php index 6868ce3f7f1ff..ef9830bc75993 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php @@ -121,9 +121,9 @@ private function extractSku(array $cartItemData): string */ private function extractQty(array $cartItemData): float { - $qty = $this->arrayManager->get('data/qty', $cartItemData); + $qty = $this->arrayManager->get('data/quantity', $cartItemData); if (!isset($qty)) { - throw new GraphQlInputException(__('Missing key "qty" in cart item data')); + throw new GraphQlInputException(__('Missing key "quantity" in cart item data')); } return (float)$qty; } diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/CartItems.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/CartItems.php index da6619d15a489..f259dcd4a78ff 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/CartItems.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/CartItems.php @@ -38,7 +38,7 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value $itemsData[] = [ 'id' => $cartItem->getItemId(), - 'qty' => $cartItem->getQty(), + 'quantity' => $cartItem->getQty(), 'product' => $productData, 'model' => $cartItem, ]; diff --git a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls index 6d94685ac4d0f..cbaee4000df68 100644 --- a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls +++ b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls @@ -31,7 +31,7 @@ input AddSimpleProductsToCartInput { } input SimpleProductCartItemInput { - data: CartItemInput! + data: CartItemQuantityInput! customizable_options:[CustomizableOptionInput!] } @@ -41,13 +41,13 @@ input AddVirtualProductsToCartInput { } input VirtualProductCartItemInput { - data: CartItemInput! + data: CartItemQuantityInput! customizable_options:[CustomizableOptionInput!] } -input CartItemInput { +input CartItemQuantityInput { sku: String! - qty: Float! + quantity: Float! } input CustomizableOptionInput { @@ -62,10 +62,10 @@ input ApplyCouponToCartInput { input UpdateCartItemsInput { cart_id: String! - cart_items: [CartItemQuantityInput!]! + cart_items: [CartItemUpdateQuantityInput!]! } -input CartItemQuantityInput { +input CartItemUpdateQuantityInput { cart_item_id: Int! quantity: Float! } @@ -304,7 +304,7 @@ type VirtualCartItem implements CartItemInterface @doc(description: "Virtual Car interface CartItemInterface @typeResolver(class: "Magento\\QuoteGraphQl\\Model\\Resolver\\CartItemTypeResolver") { id: String! - qty: Float! + quantity: Float! product: ProductInterface! } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php index a97d30fef803f..968ba7f1da46c 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php @@ -115,7 +115,7 @@ private function getQuery(string $maskedQuoteId, string $sku, float $qty) : stri cartItems: [ { data: { - qty: $qty + quantity: $qty sku: "$sku" } } @@ -124,7 +124,7 @@ private function getQuery(string $maskedQuoteId, string $sku, float $qty) : stri ) { cart { items { - qty + quantity } } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/AddConfigurableProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/AddConfigurableProductToCartTest.php index d22cd14a4ae26..fa45263e65548 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/AddConfigurableProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/AddConfigurableProductToCartTest.php @@ -44,7 +44,7 @@ public function testAddConfigurableProductToCart() $response = $this->graphQlMutation($query); $cartItems = $response['addConfigurableProductsToCart']['cart']['items']; - self::assertEquals($qty, $cartItems[0]['qty']); + self::assertEquals($qty, $cartItems[0]['quantity']); self::assertEquals($variantSku, $cartItems[0]['product']['sku']); } @@ -97,7 +97,7 @@ private function getQuery(string $maskedQuoteId, string $variantSku, int $qty): { variant_sku: "{$variantSku}" data: { - qty: {$qty} + quantity: {$qty} sku: "{$variantSku}" } } @@ -107,7 +107,7 @@ private function getQuery(string $maskedQuoteId, string $variantSku, int $qty): cart { items { id - qty + quantity product { name sku diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductWithCustomOptionsToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductWithCustomOptionsToCartTest.php index f33ccce82fcb7..714447f1e36a5 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductWithCustomOptionsToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductWithCustomOptionsToCartTest.php @@ -62,7 +62,7 @@ public function testAddSimpleProductWithOptions() cartItems: [ { data: { - qty: $qty + quantity: $qty sku: "$sku" }, customizable_options: $queryCustomizableOptions @@ -121,7 +121,7 @@ public function testAddSimpleProductWithNoRequiredOptionsSet() cartItems: [ { data: { - qty: $qty + quantity: $qty sku: "$sku" } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddVirtualProductWithCustomOptionsToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddVirtualProductWithCustomOptionsToCartTest.php index ffd52bcf7fb15..6172403c74086 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddVirtualProductWithCustomOptionsToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddVirtualProductWithCustomOptionsToCartTest.php @@ -62,7 +62,7 @@ public function testAddVirtualProductWithOptions() cartItems: [ { data: { - qty: $qty + quantity: $qty sku: "$sku" }, customizable_options: $queryCustomizableOptions @@ -121,7 +121,7 @@ public function testAddVirtualProductWithNoRequiredOptionsSet() cartItems: [ { data: { - qty: $qty + quantity: $qty sku: "$sku" } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddSimpleProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddSimpleProductToCartTest.php index 73b3e39721866..775d2733464ac 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddSimpleProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddSimpleProductToCartTest.php @@ -49,7 +49,7 @@ public function testAddSimpleProductToCart() $response = $this->graphQlMutation($query, [], '', $this->getHeaderMap()); self::assertArrayHasKey('cart', $response['addSimpleProductsToCart']); - self::assertEquals($qty, $response['addSimpleProductsToCart']['cart']['items'][0]['qty']); + self::assertEquals($qty, $response['addSimpleProductsToCart']['cart']['items'][0]['quantity']); self::assertEquals($sku, $response['addSimpleProductsToCart']['cart']['items'][0]['product']['sku']); } @@ -142,7 +142,7 @@ private function getQuery(string $maskedQuoteId, string $sku, int $qty): string cartItems: [ { data: { - qty: {$qty} + quantity: {$qty} sku: "{$sku}" } } @@ -151,7 +151,7 @@ private function getQuery(string $maskedQuoteId, string $sku, int $qty): string cart { items { id - qty + quantity product { sku } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddVirtualProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddVirtualProductToCartTest.php index 4ec25bb030079..86444f767ca78 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddVirtualProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddVirtualProductToCartTest.php @@ -49,7 +49,7 @@ public function testAddVirtualProductToCart() $response = $this->graphQlMutation($query, [], '', $this->getHeaderMap()); self::assertArrayHasKey('cart', $response['addVirtualProductsToCart']); - self::assertEquals($qty, $response['addVirtualProductsToCart']['cart']['items'][0]['qty']); + self::assertEquals($qty, $response['addVirtualProductsToCart']['cart']['items'][0]['quantity']); self::assertEquals($sku, $response['addVirtualProductsToCart']['cart']['items'][0]['product']['sku']); } @@ -142,7 +142,7 @@ private function getQuery(string $maskedQuoteId, string $sku, int $qty): string cartItems: [ { data: { - qty: {$qty} + quantity: {$qty} sku: "{$sku}" } } @@ -151,7 +151,7 @@ private function getQuery(string $maskedQuoteId, string $sku, int $qty): string cart { items { id - qty + quantity product { sku } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php index a49b84e20a8a6..d8b695941d3a3 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php @@ -215,7 +215,7 @@ private function addProductToCart(string $cartId, float $qty, string $sku): void cartItems: [ { data: { - qty: {$qty} + quantity: {$qty} sku: "{$sku}" } } @@ -224,7 +224,7 @@ private function addProductToCart(string $cartId, float $qty, string $sku): void ) { cart { items { - qty + quantity product { sku } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetCartTest.php index 60790aacb37b2..99e1c0bbd1579 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetCartTest.php @@ -54,11 +54,11 @@ public function testGetCart() self::assertCount(2, $response['cart']['items']); self::assertNotEmpty($response['cart']['items'][0]['id']); - self::assertEquals(2, $response['cart']['items'][0]['qty']); + self::assertEquals(2, $response['cart']['items'][0]['quantity']); self::assertEquals('simple_product', $response['cart']['items'][0]['product']['sku']); self::assertNotEmpty($response['cart']['items'][1]['id']); - self::assertEquals(2, $response['cart']['items'][1]['qty']); + self::assertEquals(2, $response['cart']['items'][1]['quantity']); self::assertEquals('virtual-product', $response['cart']['items'][1]['product']['sku']); } @@ -187,7 +187,7 @@ private function getQuery(string $maskedQuoteId): string cart(cart_id: "{$maskedQuoteId}") { items { id - qty + quantity product { sku } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/RemoveItemFromCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/RemoveItemFromCartTest.php index 39803f8d58447..5f953d43355fd 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/RemoveItemFromCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/RemoveItemFromCartTest.php @@ -107,7 +107,7 @@ public function testUpdateWithMissedItemRequiredParameters(string $input, string ) { cart { items { - qty + quantity } } } @@ -216,7 +216,7 @@ private function getQuery(string $maskedQuoteId, int $itemId): string ) { cart { items { - qty + quantity } } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetPaymentMethodOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetPaymentMethodOnCartTest.php index 2604ec5f0a0f9..593bb8c9fcb78 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetPaymentMethodOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetPaymentMethodOnCartTest.php @@ -196,7 +196,7 @@ public function testSetPaymentMethodWithoutRequiredParameters(string $input, str ) { cart { items { - qty + quantity } } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/UpdateCartItemsTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/UpdateCartItemsTest.php index 35e2d62214fb2..5ab0213db6074 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/UpdateCartItemsTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/UpdateCartItemsTest.php @@ -76,7 +76,7 @@ public function testUpdateCartItemQty() $item = current($responseCart['items']); $this->assertEquals($itemId, $item['id']); - $this->assertEquals($qty, $item['qty']); + $this->assertEquals($qty, $item['quantity']); } /** @@ -229,7 +229,7 @@ public function testUpdateWithMissedCartItemId() cart { items { id - qty + quantity } } } @@ -259,7 +259,7 @@ public function testUpdateWithMissedItemRequiredParameters(string $input, string cart { items { id - qty + quantity } } } @@ -285,7 +285,7 @@ public function dataProviderUpdateWithMissedRequiredParameters(): array ], 'missed_cart_item_qty' => [ 'cart_items: [{ cart_item_id: 1 }]', - 'Required parameter "quantity" for "cart_items" is missing.' + 'Field CartItemUpdateQuantityInput.quantity of required type Float! was not provided.' ], ]; } @@ -312,7 +312,7 @@ private function getQuery(string $maskedQuoteId, int $itemId, float $qty): strin cart { items { id - qty + quantity } } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddSimpleProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddSimpleProductToCartTest.php index 9e0693b160851..04c2daf755c1a 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddSimpleProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddSimpleProductToCartTest.php @@ -44,7 +44,7 @@ public function testAddSimpleProductToCart() $response = $this->graphQlMutation($query); self::assertArrayHasKey('cart', $response['addSimpleProductsToCart']); - self::assertEquals($qty, $response['addSimpleProductsToCart']['cart']['items'][0]['qty']); + self::assertEquals($qty, $response['addSimpleProductsToCart']['cart']['items'][0]['quantity']); self::assertEquals($sku, $response['addSimpleProductsToCart']['cart']['items'][0]['product']['sku']); } @@ -115,7 +115,7 @@ private function getQuery(string $maskedQuoteId, string $sku, int $qty): string cartItems: [ { data: { - qty: $qty + quantity: $qty sku: "$sku" } } @@ -124,7 +124,7 @@ private function getQuery(string $maskedQuoteId, string $sku, int $qty): string ) { cart { items { - qty + quantity product { sku } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddVirtualProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddVirtualProductToCartTest.php index 3f2d734635c3e..def3306d4e822 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddVirtualProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddVirtualProductToCartTest.php @@ -44,7 +44,7 @@ public function testAddVirtualProductToCart() $response = $this->graphQlMutation($query); self::assertArrayHasKey('cart', $response['addVirtualProductsToCart']); - self::assertEquals($qty, $response['addVirtualProductsToCart']['cart']['items'][0]['qty']); + self::assertEquals($qty, $response['addVirtualProductsToCart']['cart']['items'][0]['quantity']); self::assertEquals($sku, $response['addVirtualProductsToCart']['cart']['items'][0]['product']['sku']); } @@ -116,7 +116,7 @@ private function getQuery(string $maskedQuoteId, string $sku, int $qty): string cartItems: [ { data: { - qty: {$qty} + quantity: {$qty} sku: "{$sku}" } } @@ -125,7 +125,7 @@ private function getQuery(string $maskedQuoteId, string $sku, int $qty): string ) { cart { items { - qty + quantity product { sku } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php index 7cd4e06a19e23..ea3f958ff6bcb 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php @@ -175,7 +175,7 @@ private function addProductToCart(string $cartId, float $qty, string $sku): void cartItems: [ { data: { - qty: {$qty} + quantity: {$qty} sku: "{$sku}" } } @@ -184,7 +184,7 @@ private function addProductToCart(string $cartId, float $qty, string $sku): void ) { cart { items { - qty + quantity product { sku } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetCartTest.php index 8e4feb1d48e8c..b35d689af7d20 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetCartTest.php @@ -46,11 +46,11 @@ public function testGetCart() self::assertCount(2, $response['cart']['items']); self::assertNotEmpty($response['cart']['items'][0]['id']); - self::assertEquals(2, $response['cart']['items'][0]['qty']); + self::assertEquals(2, $response['cart']['items'][0]['quantity']); self::assertEquals('simple_product', $response['cart']['items'][0]['product']['sku']); self::assertNotEmpty($response['cart']['items'][1]['id']); - self::assertEquals(2, $response['cart']['items'][1]['qty']); + self::assertEquals(2, $response['cart']['items'][1]['quantity']); self::assertEquals('virtual-product', $response['cart']['items'][1]['product']['sku']); } @@ -156,7 +156,7 @@ private function getQuery(string $maskedQuoteId): string cart(cart_id: "{$maskedQuoteId}") { items { id - qty + quantity product { sku } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/RemoveItemFromCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/RemoveItemFromCartTest.php index 27f3f6367f662..77a057e52f686 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/RemoveItemFromCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/RemoveItemFromCartTest.php @@ -96,7 +96,7 @@ public function testUpdateWithMissedItemRequiredParameters(string $input, string ) { cart { items { - qty + quantity } } } @@ -179,7 +179,7 @@ private function getQuery(string $maskedQuoteId, int $itemId): string ) { cart { items { - qty + quantity } } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetPaymentMethodOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetPaymentMethodOnCartTest.php index 4ea7eac290f80..1b2ceecd213ab 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetPaymentMethodOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetPaymentMethodOnCartTest.php @@ -164,7 +164,7 @@ public function testSetPaymentMethodWithoutRequiredParameters(string $input, str ) { cart { items { - qty + quantity } } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/UpdateCartItemsTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/UpdateCartItemsTest.php index 1b8cf2e1c57f7..0d03b49125ce3 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/UpdateCartItemsTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/UpdateCartItemsTest.php @@ -69,7 +69,7 @@ public function testUpdateCartItemQty() $item = current($responseCart['items']); $this->assertEquals($itemId, $item['id']); - $this->assertEquals($qty, $item['qty']); + $this->assertEquals($qty, $item['quantity']); } /** @@ -180,7 +180,7 @@ public function testUpdateWithMissedCartItemId() cart { items { id - qty + quantity } } } @@ -210,7 +210,7 @@ public function testUpdateWithMissedItemRequiredParameters(string $input, string cart { items { id - qty + quantity } } } @@ -236,7 +236,7 @@ public function dataProviderUpdateWithMissedRequiredParameters(): array ], 'missed_cart_item_qty' => [ 'cart_items: [{ cart_item_id: 1 }]', - 'Required parameter "quantity" for "cart_items" is missing.' + 'Field CartItemUpdateQuantityInput.quantity of required type Float! was not provided.' ], ]; } @@ -263,7 +263,7 @@ private function getQuery(string $maskedQuoteId, int $itemId, float $qty): strin cart { items { id - qty + quantity } } } From 9b4de989a6f640c1feef066d2272245fe9c07197 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Mon, 29 Apr 2019 13:43:49 -0500 Subject: [PATCH 307/773] GraphQL-621: BillingAddress and ShippingAddress should have different fields but share the common interface --- .../Model/Cart/ExtractQuoteAddressData.php | 9 ----- .../Resolver/CartAddressTypeResolver.php | 40 +++++++++++++++++++ .../Magento/QuoteGraphQl/etc/schema.graphqls | 20 +++++----- .../Quote/Customer/CheckoutEndToEndTest.php | 2 +- .../GetSpecifiedBillingAddressTest.php | 6 +-- .../Customer/SetBillingAddressOnCartTest.php | 12 +++--- .../Customer/SetShippingAddressOnCartTest.php | 4 +- .../Quote/Guest/CheckoutEndToEndTest.php | 2 +- .../Guest/GetSpecifiedBillingAddressTest.php | 6 +-- .../Guest/SetBillingAddressOnCartTest.php | 12 +++--- .../Guest/SetShippingAddressOnCartTest.php | 4 +- 11 files changed, 74 insertions(+), 43 deletions(-) create mode 100644 app/code/Magento/QuoteGraphQl/Model/Resolver/CartAddressTypeResolver.php diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/ExtractQuoteAddressData.php b/app/code/Magento/QuoteGraphQl/Model/Cart/ExtractQuoteAddressData.php index 4d832f603cd91..c4d795293220f 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/ExtractQuoteAddressData.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/ExtractQuoteAddressData.php @@ -41,16 +41,7 @@ public function execute(QuoteAddress $address): array $addressData = $this->dataObjectConverter->toFlatArray($address, [], AddressInterface::class); $addressData['model'] = $address; - if ($address->getAddressType() == AbstractAddress::TYPE_SHIPPING) { - $addressType = 'SHIPPING'; - } elseif ($address->getAddressType() == AbstractAddress::TYPE_BILLING) { - $addressType = 'BILLING'; - } else { - $addressType = null; - } - $addressData = array_merge($addressData, [ - 'address_type' => $addressType, 'country' => [ 'code' => $address->getCountryId(), 'label' => $address->getCountry() diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/CartAddressTypeResolver.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/CartAddressTypeResolver.php new file mode 100644 index 0000000000000..14c1dc76590a4 --- /dev/null +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/CartAddressTypeResolver.php @@ -0,0 +1,40 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\QuoteGraphQl\Model\Resolver; + +use Magento\Customer\Model\Address\AbstractAddress; +use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\GraphQl\Query\Resolver\TypeResolverInterface; +use Magento\Quote\Model\Quote\Address; + +/** + * @inheritdoc + */ +class CartAddressTypeResolver implements TypeResolverInterface +{ + /** + * @inheritdoc + */ + public function resolveType(array $data) : string + { + if (!isset($data['model'])) { + throw new LocalizedException(__('Missing key "model" in cart address data')); + } + /** @var Address $address */ + $address = $data['model']; + + if ($address->getAddressType() == AbstractAddress::TYPE_SHIPPING) { + $addressType = 'ShippingCartAddress'; + } elseif ($address->getAddressType() == AbstractAddress::TYPE_BILLING) { + $addressType = 'BillingCartAddress'; + } else { + throw new LocalizedException( __('Unsupported cart address type')); + } + return $addressType; + } +} diff --git a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls index cbaee4000df68..29e9b9e5131e2 100644 --- a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls +++ b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls @@ -183,14 +183,14 @@ type Cart { items: [CartItemInterface] @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\CartItems") applied_coupon: AppliedCoupon @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\AppliedCoupon") email: String @resolver (class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\CartEmail") - shipping_addresses: [CartAddress]! @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\ShippingAddresses") - billing_address: CartAddress! @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\BillingAddress") + shipping_addresses: [ShippingCartAddress]! @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\ShippingAddresses") + billing_address: BillingCartAddress! @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\BillingAddress") available_payment_methods: [AvailablePaymentMethod] @resolver(class: "Magento\\QuoteGraphQl\\Model\\Resolver\\AvailablePaymentMethods") @doc(description: "Available payment methods") selected_payment_method: SelectedPaymentMethod @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\SelectedPaymentMethod") prices: CartPrices @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\CartPrices") } -type CartAddress { +interface CartAddressInterface @typeResolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\CartAddressTypeResolver") { firstname: String lastname: String company: String @@ -200,14 +200,19 @@ type CartAddress { postcode: String country: CartAddressCountry telephone: String - address_type: AdressTypeEnum + customer_notes: String +} + +type ShippingCartAddress implements CartAddressInterface { available_shipping_methods: [AvailableShippingMethod] @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\ShippingAddress\\AvailableShippingMethods") selected_shipping_method: SelectedShippingMethod @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\ShippingAddress\\SelectedShippingMethod") items_weight: Float - customer_notes: String cart_items: [CartItemQuantity] } +type BillingCartAddress implements CartAddressInterface { +} + type CartItemQuantity { cart_item_id: Int! quantity: Float! @@ -257,11 +262,6 @@ type SelectedPaymentMethod { type SelectedPaymentMethodAdditionalData { } -enum AdressTypeEnum { - SHIPPING - BILLING -} - type AppliedCoupon { code: String! } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php index d8b695941d3a3..2a8609e009f4d 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php @@ -266,7 +266,7 @@ private function setBillingAddress(string $cartId): void ) { cart { billing_address { - address_type + __typename } } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSpecifiedBillingAddressTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSpecifiedBillingAddressTest.php index 1ba94346073db..e10d12d73e7a6 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSpecifiedBillingAddressTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSpecifiedBillingAddressTest.php @@ -71,7 +71,7 @@ public function testGeSpecifiedBillingAddress() 'label' => 'US', ], 'telephone' => '3468676', - 'address_type' => 'BILLING', + '__typename' => 'BillingCartAddress', 'customer_notes' => null, ]; self::assertEquals($expectedBillingAddressData, $response['cart']['billing_address']); @@ -110,7 +110,7 @@ public function testGeSpecifiedBillingAddressIfBillingAddressIsNotSet() 'label' => null, ], 'telephone' => null, - 'address_type' => 'BILLING', + '__typename' => null, 'customer_notes' => null, ]; self::assertEquals($expectedBillingAddressData, $response['cart']['billing_address']); @@ -197,7 +197,7 @@ private function getQuery(string $maskedQuoteId): string label } telephone - address_type + __typename customer_notes } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetBillingAddressOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetBillingAddressOnCartTest.php index 6b15f947a2477..fc73d88be1f87 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetBillingAddressOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetBillingAddressOnCartTest.php @@ -99,7 +99,7 @@ public function testSetNewBillingAddress() code label } - address_type + __typename } } } @@ -159,7 +159,7 @@ public function testSetNewBillingAddressWithUseForShippingParameter() code label } - address_type + __typename } shipping_addresses { firstname @@ -173,7 +173,7 @@ public function testSetNewBillingAddressWithUseForShippingParameter() code label } - address_type + __typename } } } @@ -188,7 +188,7 @@ public function testSetNewBillingAddressWithUseForShippingParameter() self::assertArrayHasKey('shipping_addresses', $cartResponse); $shippingAddressResponse = current($cartResponse['shipping_addresses']); $this->assertNewAddressFields($billingAddressResponse); - $this->assertNewAddressFields($shippingAddressResponse, 'SHIPPING'); + $this->assertNewAddressFields($shippingAddressResponse, 'ShippingCartAddress'); } /** @@ -560,7 +560,7 @@ public function testSetNewBillingAddressWithRedundantStreetLine() * @param array $addressResponse * @param string $addressType */ - private function assertNewAddressFields(array $addressResponse, string $addressType = 'BILLING'): void + private function assertNewAddressFields(array $addressResponse, string $addressType = 'BillingCartAddress'): void { $assertionMap = [ ['response_field' => 'firstname', 'expected_value' => 'test firstname'], @@ -571,7 +571,7 @@ private function assertNewAddressFields(array $addressResponse, string $addressT ['response_field' => 'postcode', 'expected_value' => '887766'], ['response_field' => 'telephone', 'expected_value' => '88776655'], ['response_field' => 'country', 'expected_value' => ['code' => 'US', 'label' => 'US']], - ['response_field' => 'address_type', 'expected_value' => $addressType] + ['response_field' => '__typename', 'expected_value' => $addressType] ]; $this->assertResponseFields($addressResponse, $assertionMap); diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingAddressOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingAddressOnCartTest.php index 6b097e028ffe5..5d7a073d2d6d5 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingAddressOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingAddressOnCartTest.php @@ -101,7 +101,7 @@ public function testSetNewShippingAddressOnCartWithSimpleProduct() label code } - address_type + __typename } } } @@ -548,7 +548,7 @@ private function assertNewShippingAddressFields(array $shippingAddressResponse): ['response_field' => 'postcode', 'expected_value' => '887766'], ['response_field' => 'telephone', 'expected_value' => '88776655'], ['response_field' => 'country', 'expected_value' => ['code' => 'US', 'label' => 'US']], - ['response_field' => 'address_type', 'expected_value' => 'SHIPPING'] + ['response_field' => '__typename', 'expected_value' => 'ShippingCartAddress'] ]; $this->assertResponseFields($shippingAddressResponse, $assertionMap); diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php index ea3f958ff6bcb..614c4c244d4d6 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php @@ -226,7 +226,7 @@ private function setBillingAddress(string $cartId): void ) { cart { billing_address { - address_type + __typename } } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedBillingAddressTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedBillingAddressTest.php index d592443aed499..48bff73226894 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedBillingAddressTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedBillingAddressTest.php @@ -63,7 +63,7 @@ public function testGeSpecifiedBillingAddress() 'label' => 'US', ], 'telephone' => '3468676', - 'address_type' => 'BILLING', + '__typename' => 'BillingCartAddress', ]; self::assertEquals($expectedBillingAddressData, $response['cart']['billing_address']); } @@ -100,7 +100,7 @@ public function testGeSpecifiedBillingAddressIfBillingAddressIsNotSet() 'label' => null, ], 'telephone' => null, - 'address_type' => 'BILLING', + '__typename' => 'BillingCartAddress', ]; self::assertEquals($expectedBillingAddressData, $response['cart']['billing_address']); } @@ -161,7 +161,7 @@ private function getQuery(string $maskedQuoteId): string label } telephone - address_type + __typename } } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetBillingAddressOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetBillingAddressOnCartTest.php index d2d53220f0042..d8d95040eea45 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetBillingAddressOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetBillingAddressOnCartTest.php @@ -70,7 +70,7 @@ public function testSetNewBillingAddress() code label } - address_type + __typename } } } @@ -129,7 +129,7 @@ public function testSetNewBillingAddressWithUseForShippingParameter() code label } - address_type + __typename } shipping_addresses { firstname @@ -143,7 +143,7 @@ public function testSetNewBillingAddressWithUseForShippingParameter() code label } - address_type + __typename } } } @@ -158,7 +158,7 @@ public function testSetNewBillingAddressWithUseForShippingParameter() self::assertArrayHasKey('shipping_addresses', $cartResponse); $shippingAddressResponse = current($cartResponse['shipping_addresses']); $this->assertNewAddressFields($billingAddressResponse); - $this->assertNewAddressFields($shippingAddressResponse, 'SHIPPING'); + $this->assertNewAddressFields($shippingAddressResponse, 'ShippingCartAddress'); } /** @@ -380,7 +380,7 @@ public function testSetNewBillingAddressRedundantStreetLine() * @param array $addressResponse * @param string $addressType */ - private function assertNewAddressFields(array $addressResponse, string $addressType = 'BILLING'): void + private function assertNewAddressFields(array $addressResponse, string $addressType = 'BillingCartAddress'): void { $assertionMap = [ ['response_field' => 'firstname', 'expected_value' => 'test firstname'], @@ -391,7 +391,7 @@ private function assertNewAddressFields(array $addressResponse, string $addressT ['response_field' => 'postcode', 'expected_value' => '887766'], ['response_field' => 'telephone', 'expected_value' => '88776655'], ['response_field' => 'country', 'expected_value' => ['code' => 'US', 'label' => 'US']], - ['response_field' => 'address_type', 'expected_value' => $addressType] + ['response_field' => '__typename', 'expected_value' => $addressType] ]; $this->assertResponseFields($addressResponse, $assertionMap); diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingAddressOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingAddressOnCartTest.php index 888b0e87734b6..c58098c6c2547 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingAddressOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingAddressOnCartTest.php @@ -72,7 +72,7 @@ public function testSetNewShippingAddressOnCartWithSimpleProduct() code label } - address_type + __typename } } } @@ -383,7 +383,7 @@ private function assertNewShippingAddressFields(array $shippingAddressResponse): ['response_field' => 'postcode', 'expected_value' => '887766'], ['response_field' => 'telephone', 'expected_value' => '88776655'], ['response_field' => 'country', 'expected_value' => ['code' => 'US', 'label' => 'US']], - ['response_field' => 'address_type', 'expected_value' => 'SHIPPING'] + ['response_field' => '__typename', 'expected_value' => 'ShippingCartAddress'] ]; $this->assertResponseFields($shippingAddressResponse, $assertionMap); From 42d536858ed767207cd669b973774c9c0fb7971c Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Mon, 29 Apr 2019 13:53:34 -0500 Subject: [PATCH 308/773] GraphQL-631: Schema inconsistency of "Quantity / Qty" declaration --- .../Magento/GraphQl/Quote/Customer/UpdateCartItemsTest.php | 2 +- .../Magento/GraphQl/Quote/Guest/UpdateCartItemsTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/UpdateCartItemsTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/UpdateCartItemsTest.php index 5ab0213db6074..c7f51efe3c98e 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/UpdateCartItemsTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/UpdateCartItemsTest.php @@ -285,7 +285,7 @@ public function dataProviderUpdateWithMissedRequiredParameters(): array ], 'missed_cart_item_qty' => [ 'cart_items: [{ cart_item_id: 1 }]', - 'Field CartItemUpdateQuantityInput.quantity of required type Float! was not provided.' + 'Field CartItemUpdateInput.quantity of required type Float! was not provided.' ], ]; } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/UpdateCartItemsTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/UpdateCartItemsTest.php index 0d03b49125ce3..8738650b25b3f 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/UpdateCartItemsTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/UpdateCartItemsTest.php @@ -236,7 +236,7 @@ public function dataProviderUpdateWithMissedRequiredParameters(): array ], 'missed_cart_item_qty' => [ 'cart_items: [{ cart_item_id: 1 }]', - 'Field CartItemUpdateQuantityInput.quantity of required type Float! was not provided.' + 'Field CartItemUpdateInput.quantity of required type Float! was not provided.' ], ]; } From ca618196d71a862b2cd12a17b0ed68b793fb1f24 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Mon, 29 Apr 2019 14:49:10 -0500 Subject: [PATCH 309/773] GraphQL-631: Schema inconsistency of "Quantity / Qty" declaration --- setup/performance-toolkit/benchmark.jmx | 52 ++++++++++++------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/setup/performance-toolkit/benchmark.jmx b/setup/performance-toolkit/benchmark.jmx index 384832532ae00..c1d21a08f9e2d 100644 --- a/setup/performance-toolkit/benchmark.jmx +++ b/setup/performance-toolkit/benchmark.jmx @@ -40796,7 +40796,7 @@ vars.putObject("randomIntGenerator", random); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n items {\n id\n qty\n product {\n sku\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n items {\n id\n quantity\n product {\n sku\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -40947,7 +40947,7 @@ vars.putObject("randomIntGenerator", random); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n items {\n id\n qty\n product {\n sku\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n items {\n id\n quantity\n product {\n sku\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -41137,7 +41137,7 @@ vars.putObject("randomIntGenerator", random); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n items {\n id\n qty\n product {\n sku\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n items {\n id\n quantity\n product {\n sku\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -41347,7 +41347,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n data: {\n qty: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n qty\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n data: {\n quantity: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n quantity\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -41567,7 +41567,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation {\n addConfigurableProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n variant_sku: \"${product_option}\"\n data: {\n qty: 2\n sku: \"${product_option}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n id\n qty\n product {\n name\n sku\n }\n ... on ConfigurableCartItem {\n configurable_options {\n option_label\n }\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation {\n addConfigurableProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n variant_sku: \"${product_option}\"\n data: {\n quantity: 2\n sku: \"${product_option}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n id\n quantity\n product {\n name\n sku\n }\n ... on ConfigurableCartItem {\n configurable_options {\n option_label\n }\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -41739,7 +41739,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n data: {\n qty: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n qty\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n data: {\n quantity: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n quantity\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -41779,7 +41779,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n items {\n id\n qty\n product {\n sku\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n items {\n id\n quantity\n product {\n sku\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -41820,13 +41820,13 @@ vars.put("product_sku", product.get("sku")); <hashTree/> </hashTree> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Update Simple Product qty In Cart" enabled="true"> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Update Simple Product quantity In Cart" enabled="true"> <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation {\n updateCartItems(input: {\n cart_id: \"${quote_id}\"\n cart_items: [\n {\n cart_item_id: ${item_id}\n quantity: 5\n }\n ]\n }) {\n cart {\n items {\n id\n qty\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation {\n updateCartItems(input: {\n cart_id: \"${quote_id}\"\n cart_items: [\n {\n cart_item_id: ${item_id}\n quantity: 5\n }\n ]\n }) {\n cart {\n items {\n id\n quantity\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -41850,7 +41850,7 @@ vars.put("product_sku", product.get("sku")); <hashTree> <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> <collectionProp name="Asserion.test_strings"> - <stringProp name="664196114">{"data":{"updateCartItems":{"cart":{"items":[{"id":"${item_id}","qty":5}]}}}}</stringProp> + <stringProp name="664196114">{"data":{"updateCartItems":{"cart":{"items":[{"id":"${item_id}","quantity":5}]}}}}</stringProp> </collectionProp> <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> <boolProp name="Assertion.assume_success">false</boolProp> @@ -42045,7 +42045,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation {\n addConfigurableProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n variant_sku: \"${product_option}\"\n data: {\n qty: 2\n sku: \"${product_option}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n id\n qty\n product {\n name\n sku\n }\n ... on ConfigurableCartItem {\n configurable_options {\n option_label\n }\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation {\n addConfigurableProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n variant_sku: \"${product_option}\"\n data: {\n quantity: 2\n sku: \"${product_option}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n id\n quantity\n product {\n name\n sku\n }\n ... on ConfigurableCartItem {\n configurable_options {\n option_label\n }\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -42085,7 +42085,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n items {\n id\n qty\n product {\n sku\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n items {\n id\n quantity\n product {\n sku\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -42126,13 +42126,13 @@ vars.put("product_sku", product.get("sku")); <hashTree/> </hashTree> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Update Configurable Product qty In Cart" enabled="true"> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Update Configurable Product quantity In Cart" enabled="true"> <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation {\n updateCartItems(input: {\n cart_id: \"${quote_id}\"\n cart_items: [\n {\n cart_item_id: ${item_id}\n quantity: 5\n }\n ]\n }) {\n cart {\n items {\n id\n qty\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation {\n updateCartItems(input: {\n cart_id: \"${quote_id}\"\n cart_items: [\n {\n cart_item_id: ${item_id}\n quantity: 5\n }\n ]\n }) {\n cart {\n items {\n id\n quantity\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -42156,7 +42156,7 @@ vars.put("product_sku", product.get("sku")); <hashTree> <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> <collectionProp name="Asserion.test_strings"> - <stringProp name="664196114">{"data":{"updateCartItems":{"cart":{"items":[{"id":"${item_id}","qty":5}]}}}}</stringProp> + <stringProp name="664196114">{"data":{"updateCartItems":{"cart":{"items":[{"id":"${item_id}","quantity":5}]}}}}</stringProp> </collectionProp> <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> <boolProp name="Assertion.assume_success">false</boolProp> @@ -42303,7 +42303,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n data: {\n qty: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n qty\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n data: {\n quantity: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n quantity\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -42343,7 +42343,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n items {\n id\n qty\n product {\n sku\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n items {\n id\n quantity\n product {\n sku\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -42390,7 +42390,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation {\n removeItemFromCart(\n input: {\n cart_id: \"${quote_id}\"\n cart_item_id: ${item_id}\n }\n ) {\n cart {\n items {\n qty\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation {\n removeItemFromCart(\n input: {\n cart_id: \"${quote_id}\"\n cart_item_id: ${item_id}\n }\n ) {\n cart {\n items {\n quantity\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -42609,7 +42609,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation {\n addConfigurableProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n variant_sku: \"${product_option}\"\n data: {\n qty: 2\n sku: \"${product_option}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n id\n qty\n product {\n name\n sku\n }\n ... on ConfigurableCartItem {\n configurable_options {\n option_label\n }\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation {\n addConfigurableProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n variant_sku: \"${product_option}\"\n data: {\n quantity: 2\n sku: \"${product_option}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n id\n quantity\n product {\n name\n sku\n }\n ... on ConfigurableCartItem {\n configurable_options {\n option_label\n }\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -42649,7 +42649,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n items {\n id\n qty\n product {\n sku\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n items {\n id\n quantity\n product {\n sku\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -42696,7 +42696,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation {\n removeItemFromCart(\n input: {\n cart_id: \"${quote_id}\"\n cart_item_id: ${item_id}\n }\n ) {\n cart {\n items {\n qty\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation {\n removeItemFromCart(\n input: {\n cart_id: \"${quote_id}\"\n cart_item_id: ${item_id}\n }\n ) {\n cart {\n items {\n quantity\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -42867,7 +42867,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n data: {\n qty: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n qty\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n data: {\n quantity: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n quantity\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -43094,7 +43094,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n data: {\n qty: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n qty\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n data: {\n quantity: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n quantity\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -43852,7 +43852,7 @@ vars.putObject("randomIntGenerator", random); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n items {\n id\n qty\n product {\n sku\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"{\n cart(cart_id: \"${quote_id}\") {\n items {\n id\n quantity\n product {\n sku\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -43959,7 +43959,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation {\n addConfigurableProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n variant_sku: \"${product_option}\"\n data: {\n qty: 2\n sku: \"${product_option}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n id\n qty\n product {\n name\n sku\n }\n ... on ConfigurableCartItem {\n configurable_options {\n option_label\n }\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation {\n addConfigurableProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n variant_sku: \"${product_option}\"\n data: {\n quantity: 2\n sku: \"${product_option}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n id\n quantity\n product {\n name\n sku\n }\n ... on ConfigurableCartItem {\n configurable_options {\n option_label\n }\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -44019,7 +44019,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n data: {\n qty: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n qty\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n data: {\n quantity: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n quantity\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> From 04c1f805da4a885173f0eba8e50f75180451ce37 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Mon, 29 Apr 2019 15:12:53 -0500 Subject: [PATCH 310/773] GraphQL-631: Schema inconsistency of "Quantity / Qty" declaration --- .../Model/Resolver/CartAddressTypeResolver.php | 4 ++-- .../CatalogInventory/AddProductToCartTest.php | 16 ++++++++-------- .../CatalogInventory/UpdateCartItemsTest.php | 14 +++++++------- .../Guest/GetSpecifiedBillingAddressTest.php | 2 +- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/CartAddressTypeResolver.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/CartAddressTypeResolver.php index 14c1dc76590a4..6f7c70b09cb0c 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/CartAddressTypeResolver.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/CartAddressTypeResolver.php @@ -20,7 +20,7 @@ class CartAddressTypeResolver implements TypeResolverInterface /** * @inheritdoc */ - public function resolveType(array $data) : string + public function resolveType(array $data): string { if (!isset($data['model'])) { throw new LocalizedException(__('Missing key "model" in cart address data')); @@ -33,7 +33,7 @@ public function resolveType(array $data) : string } elseif ($address->getAddressType() == AbstractAddress::TYPE_BILLING) { $addressType = 'BillingCartAddress'; } else { - throw new LocalizedException( __('Unsupported cart address type')); + throw new LocalizedException(__('Unsupported cart address type')); } return $addressType; } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php index 968ba7f1da46c..68938e4c9dd2e 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php @@ -71,13 +71,13 @@ public function testAddMoreProductsThatAllowed() * @expectedException \Exception * @expectedExceptionMessage Please enter a number greater than 0 in this field. */ - public function testAddSimpleProductToCartWithNegativeQty() + public function testAddSimpleProductToCartWithNegativeQuantity() { $sku = 'simple'; - $qty = -2; + $quantity = -2; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); - $query = $this->getQuery($maskedQuoteId, $sku, $qty); + $query = $this->getQuery($maskedQuoteId, $sku, $quantity); $this->graphQlMutation($query); } @@ -88,10 +88,10 @@ public function testAddSimpleProductToCartWithNegativeQty() public function testAddProductIfQuantityIsDecimal() { $sku = 'simple_product'; - $qty = 0.2; + $quantity = 0.2; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); - $query = $this->getQuery($maskedQuoteId, $sku, $qty); + $query = $this->getQuery($maskedQuoteId, $sku, $quantity); $this->expectExceptionMessage( "Could not add the product with SKU {$sku} to the shopping cart: The fewest you may purchase is 1" @@ -102,10 +102,10 @@ public function testAddProductIfQuantityIsDecimal() /** * @param string $maskedQuoteId * @param string $sku - * @param float $qty + * @param float $quantity * @return string */ - private function getQuery(string $maskedQuoteId, string $sku, float $qty) : string + private function getQuery(string $maskedQuoteId, string $sku, float $quantity) : string { return <<<QUERY mutation { @@ -115,7 +115,7 @@ private function getQuery(string $maskedQuoteId, string $sku, float $qty) : stri cartItems: [ { data: { - quantity: $qty + quantity: $quantity sku: "$sku" } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/UpdateCartItemsTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/UpdateCartItemsTest.php index b13277136fadb..3b238f8641637 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/UpdateCartItemsTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/UpdateCartItemsTest.php @@ -41,26 +41,26 @@ protected function setUp() * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php */ - public function testUpdateCartItemDecimalQty() + public function testUpdateCartItemDecimalQuantity() { $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $itemId = $this->getQuoteItemIdByReservedQuoteIdAndSku->execute('test_quote', 'simple_product'); - $qty = 0.5; + $quantity = 0.5; $this->expectExceptionMessage( "Could not update the product with SKU simple_product: The fewest you may purchase is 1" ); - $query = $this->getQuery($maskedQuoteId, $itemId, $qty); + $query = $this->getQuery($maskedQuoteId, $itemId, $quantity); $this->graphQlMutation($query); } /** * @param string $maskedQuoteId * @param int $itemId - * @param float $qty + * @param float $quantity * @return string */ - private function getQuery(string $maskedQuoteId, int $itemId, float $qty): string + private function getQuery(string $maskedQuoteId, int $itemId, float $quantity): string { return <<<QUERY mutation { @@ -69,14 +69,14 @@ private function getQuery(string $maskedQuoteId, int $itemId, float $qty): strin cart_items:[ { cart_item_id: {$itemId} - quantity: {$qty} + quantity: {$quantity} } ] }) { cart { items { id - qty + quantity } } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedBillingAddressTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedBillingAddressTest.php index 48bff73226894..68e99feb5fae2 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedBillingAddressTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedBillingAddressTest.php @@ -100,7 +100,7 @@ public function testGeSpecifiedBillingAddressIfBillingAddressIsNotSet() 'label' => null, ], 'telephone' => null, - '__typename' => 'BillingCartAddress', + '__typename' => null, ]; self::assertEquals($expectedBillingAddressData, $response['cart']['billing_address']); } From d0ff6c8ff3e78f896a1142b359e4852df28b1444 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Mon, 29 Apr 2019 16:41:23 -0500 Subject: [PATCH 311/773] GraphQL-575: Schema inconsistency of "SelectedShippingMethod" declaration --- .../CatalogGraphQl/etc/schema.graphqls | 178 ------------------ app/code/Magento/GraphQl/etc/schema.graphqls | 178 ++++++++++++++++++ .../SelectedShippingMethod.php | 43 +++-- .../Magento/QuoteGraphQl/etc/schema.graphqls | 6 +- .../GetSelectedShippingMethodTest.php | 38 +++- .../SetOfflineShippingMethodsOnCartTest.php | 66 +++++-- .../Customer/SetShippingMethodsOnCartTest.php | 36 +++- .../Guest/GetSelectedShippingMethodTest.php | 38 +++- .../SetOfflineShippingMethodsOnCartTest.php | 66 +++++-- .../Guest/SetShippingMethodsOnCartTest.php | 36 +++- .../Ups/SetUpsShippingMethodsOnCartTest.php | 35 ++-- 11 files changed, 480 insertions(+), 240 deletions(-) diff --git a/app/code/Magento/CatalogGraphQl/etc/schema.graphqls b/app/code/Magento/CatalogGraphQl/etc/schema.graphqls index 08066e5fdfed3..9f102a1c6a150 100644 --- a/app/code/Magento/CatalogGraphQl/etc/schema.graphqls +++ b/app/code/Magento/CatalogGraphQl/etc/schema.graphqls @@ -16,179 +16,6 @@ type Query { @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\CategoryTree") @doc(description: "The category query searches for categories that match the criteria specified in the search and filter attributes") @cache(cacheTag: "cat_c", cacheIdentity: "Magento\\CatalogGraphQl\\Model\\Resolver\\Category\\CategoryTreeIdentity") } -enum CurrencyEnum @doc(description: "The list of available currency codes") { - AFN - ALL - AZN - DZD - AOA - ARS - AMD - AWG - AUD - BSD - BHD - BDT - BBD - BYR - BZD - BMD - BTN - BOB - BAM - BWP - BRL - GBP - BND - BGN - BUK - BIF - KHR - CAD - CVE - CZK - KYD - GQE - CLP - CNY - COP - KMF - CDF - CRC - HRK - CUP - DKK - DJF - DOP - XCD - EGP - SVC - ERN - EEK - ETB - EUR - FKP - FJD - GMD - GEK - GEL - GHS - GIP - GTQ - GNF - GYD - HTG - HNL - HKD - HUF - ISK - INR - IDR - IRR - IQD - ILS - JMD - JPY - JOD - KZT - KES - KWD - KGS - LAK - LVL - LBP - LSL - LRD - LYD - LTL - MOP - MKD - MGA - MWK - MYR - MVR - LSM - MRO - MUR - MXN - MDL - MNT - MAD - MZN - MMK - NAD - NPR - ANG - YTL - NZD - NIC - NGN - KPW - NOK - OMR - PKR - PAB - PGK - PYG - PEN - PHP - PLN - QAR - RHD - RON - RUB - RWF - SHP - STD - SAR - RSD - SCR - SLL - SGD - SKK - SBD - SOS - ZAR - KRW - LKR - SDG - SRD - SZL - SEK - CHF - SYP - TWD - TJS - TZS - THB - TOP - TTD - TND - TMM - USD - UGX - UAH - AED - UYU - UZS - VUV - VEB - VEF - VND - CHE - CHW - XOF - WST - YER - ZMK - ZWD - TRY - AZM - ROL - TRL - XPF -} - type Price @doc(description: "The Price object defines the price of a product as well as any tax-related adjustments.") { amount: Money @doc(description: "The price of a product plus a three-letter currency code") adjustments: [PriceAdjustment] @doc(description: "An array that provides information about tax, weee, or weee_tax adjustments") @@ -214,11 +41,6 @@ enum PriceTypeEnum @doc(description: "This enumeration the price type.") { DYNAMIC } -type Money @doc(description: "A Money object defines a monetary value, including a numeric value and a currency code.") { - value: Float @doc(description: "A number expressing a monetary value") - currency: CurrencyEnum @doc(description: "A three-letter currency code, such as USD or EUR") -} - type ProductPrices @doc(description: "The ProductPrices object contains the regular price of an item, as well as its minimum and maximum prices. Only composite products, which include bundle, configurable, and grouped products, can contain a minimum and maximum price.") { minimalPrice: Price @doc(description: "The lowest possible final price for all the options defined within a composite product. If you are specifying a price range, this would be the from value.") maximalPrice: Price @doc(description: "The highest possible final price for all the options defined within a composite product. If you are specifying a price range, this would be the to value.") diff --git a/app/code/Magento/GraphQl/etc/schema.graphqls b/app/code/Magento/GraphQl/etc/schema.graphqls index 7ea715097cdf3..ab8472aa56cf0 100644 --- a/app/code/Magento/GraphQl/etc/schema.graphqls +++ b/app/code/Magento/GraphQl/etc/schema.graphqls @@ -39,3 +39,181 @@ enum SortEnum @doc(description: "This enumeration indicates whether to return re type ComplexTextValue { html: String! @doc(description: "HTML format") } + +type Money @doc(description: "A Money object defines a monetary value, including a numeric value and a currency code.") { + value: Float @doc(description: "A number expressing a monetary value") + currency: CurrencyEnum @doc(description: "A three-letter currency code, such as USD or EUR") +} + +enum CurrencyEnum @doc(description: "The list of available currency codes") { + AFN + ALL + AZN + DZD + AOA + ARS + AMD + AWG + AUD + BSD + BHD + BDT + BBD + BYR + BZD + BMD + BTN + BOB + BAM + BWP + BRL + GBP + BND + BGN + BUK + BIF + KHR + CAD + CVE + CZK + KYD + GQE + CLP + CNY + COP + KMF + CDF + CRC + HRK + CUP + DKK + DJF + DOP + XCD + EGP + SVC + ERN + EEK + ETB + EUR + FKP + FJD + GMD + GEK + GEL + GHS + GIP + GTQ + GNF + GYD + HTG + HNL + HKD + HUF + ISK + INR + IDR + IRR + IQD + ILS + JMD + JPY + JOD + KZT + KES + KWD + KGS + LAK + LVL + LBP + LSL + LRD + LYD + LTL + MOP + MKD + MGA + MWK + MYR + MVR + LSM + MRO + MUR + MXN + MDL + MNT + MAD + MZN + MMK + NAD + NPR + ANG + YTL + NZD + NIC + NGN + KPW + NOK + OMR + PKR + PAB + PGK + PYG + PEN + PHP + PLN + QAR + RHD + RON + RUB + RWF + SHP + STD + SAR + RSD + SCR + SLL + SGD + SKK + SBD + SOS + ZAR + KRW + LKR + SDG + SRD + SZL + SEK + CHF + SYP + TWD + TJS + TZS + THB + TOP + TTD + TND + TMM + USD + UGX + UAH + AED + UYU + UZS + VUV + VEB + VEF + VND + CHE + CHW + XOF + WST + YER + ZMK + ZWD + TRY + AZM + ROL + TRL + XPF +} diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/SelectedShippingMethod.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/SelectedShippingMethod.php index c58affa064c89..6f92611e25f48 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/SelectedShippingMethod.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/SelectedShippingMethod.php @@ -11,6 +11,8 @@ use Magento\Framework\GraphQl\Config\Element\Field; use Magento\Framework\GraphQl\Query\ResolverInterface; use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; +use Magento\Quote\Model\Quote\Address; +use Magento\Quote\Model\Quote\Address\Rate; /** * @inheritdoc @@ -25,19 +27,38 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value if (!isset($value['model'])) { throw new LocalizedException(__('"model" value should be specified')); } - + /** @var Address $address */ $address = $value['model']; + $rates = $address->getAllShippingRates(); - if ($address->getShippingMethod()) { - list($carrierCode, $methodCode) = explode('_', $address->getShippingMethod(), 2); - $shippingAmount = $address->getShippingAmount(); - } + if (count($rates) > 0) { + /** @var Rate $rate */ + $rate = current($rates); - return [ - 'carrier_code' => $carrierCode ?? null, - 'method_code' => $methodCode ?? null, - 'label' => $address->getShippingDescription(), - 'amount' => $shippingAmount ?? null, - ]; + $data = [ + 'carrier_code' => $rate->getCarrier(), + 'method_code' => $rate->getMethod(), + 'carrier_title' => $rate->getCarrierTitle(), + 'method_title' => $rate->getMethodTitle(), + 'amount' => [ + 'value' => $address->getShippingAmount(), + 'currency' => $address->getQuote()->getQuoteCurrencyCode(), + ], + 'base_amount' => [ + 'value' => $address->getBaseShippingAmount(), + 'currency' => $address->getQuote()->getBaseCurrencyCode(), + ], + ]; + } else { + $data = [ + 'carrier_code' => null, + 'method_code' => null, + 'carrier_title' => null, + 'method_title' => null, + 'amount' => null, + 'base_amount' => null, + ]; + } + return $data; } } diff --git a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls index 29e9b9e5131e2..3ab5a1863e7e1 100644 --- a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls +++ b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls @@ -231,8 +231,10 @@ type CartAddressCountry { type SelectedShippingMethod { carrier_code: String method_code: String - label: String - amount: Float + carrier_title: String + method_title: String + amount: Money + base_amount: Money } type AvailableShippingMethod { diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSelectedShippingMethodTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSelectedShippingMethodTest.php index ba169d7a5bbc9..5575830ea51cd 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSelectedShippingMethodTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSelectedShippingMethodTest.php @@ -64,6 +64,28 @@ public function testGetSelectedShippingMethod() self::assertArrayHasKey('method_code', $shippingAddress['selected_shipping_method']); self::assertEquals('flatrate', $shippingAddress['selected_shipping_method']['method_code']); + + self::assertArrayHasKey('carrier_title', $shippingAddress['selected_shipping_method']); + self::assertEquals('Flat Rate', $shippingAddress['selected_shipping_method']['carrier_title']); + + self::assertArrayHasKey('method_title', $shippingAddress['selected_shipping_method']); + self::assertEquals('Fixed', $shippingAddress['selected_shipping_method']['method_title']); + + self::assertArrayHasKey('amount', $shippingAddress['selected_shipping_method']); + $amount = $shippingAddress['selected_shipping_method']['amount']; + + self::assertArrayHasKey('value', $amount); + self::assertEquals(10, $amount['value']); + self::assertArrayHasKey('currency', $amount); + self::assertEquals('USD', $amount['currency']); + + self::assertArrayHasKey('base_amount', $shippingAddress['selected_shipping_method']); + $baseAmount = $shippingAddress['selected_shipping_method']['base_amount']; + + self::assertArrayHasKey('value', $baseAmount); + self::assertEquals(10, $baseAmount['value']); + self::assertArrayHasKey('currency', $baseAmount); + self::assertEquals('USD', $baseAmount['currency']); } /** @@ -129,8 +151,10 @@ public function testGetGetSelectedShippingMethodIfShippingMethodIsNotSet() self::assertNull($shippingAddress['selected_shipping_method']['carrier_code']); self::assertNull($shippingAddress['selected_shipping_method']['method_code']); - self::assertNull($shippingAddress['selected_shipping_method']['label']); + self::assertNull($shippingAddress['selected_shipping_method']['carrier_title']); + self::assertNull($shippingAddress['selected_shipping_method']['method_title']); self::assertNull($shippingAddress['selected_shipping_method']['amount']); + self::assertNull($shippingAddress['selected_shipping_method']['base_amount']); } /** @@ -172,8 +196,16 @@ private function getQuery(string $maskedQuoteId): string selected_shipping_method { carrier_code method_code - label - amount + carrier_title + method_title + amount { + value + currency + } + base_amount { + value + currency + } } } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetOfflineShippingMethodsOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetOfflineShippingMethodsOnCartTest.php index 4544691584721..c6c4a18bce4ab 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetOfflineShippingMethodsOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetOfflineShippingMethodsOnCartTest.php @@ -48,12 +48,21 @@ protected function setUp() * * @param string $carrierCode * @param string $methodCode - * @param float $amount - * @param string $label + * @param string $carrierTitle + * @param string $methodTitle + * @param array $amount + * @param array $baseAmount + * @throws \Magento\Framework\Exception\NoSuchEntityException * @dataProvider offlineShippingMethodDataProvider */ - public function testSetOfflineShippingMethod(string $carrierCode, string $methodCode, float $amount, string $label) - { + public function testSetOfflineShippingMethod( + string $carrierCode, + string $methodCode, + string $carrierTitle, + string $methodTitle, + array $amount, + array $baseAmount + ) { $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $query = $this->getQuery( @@ -77,11 +86,17 @@ public function testSetOfflineShippingMethod(string $carrierCode, string $method self::assertArrayHasKey('method_code', $shippingAddress['selected_shipping_method']); self::assertEquals($methodCode, $shippingAddress['selected_shipping_method']['method_code']); + self::assertArrayHasKey('carrier_title', $shippingAddress['selected_shipping_method']); + self::assertEquals($carrierTitle, $shippingAddress['selected_shipping_method']['carrier_title']); + + self::assertArrayHasKey('method_title', $shippingAddress['selected_shipping_method']); + self::assertEquals($methodTitle, $shippingAddress['selected_shipping_method']['method_title']); + self::assertArrayHasKey('amount', $shippingAddress['selected_shipping_method']); self::assertEquals($amount, $shippingAddress['selected_shipping_method']['amount']); - self::assertArrayHasKey('label', $shippingAddress['selected_shipping_method']); - self::assertEquals($label, $shippingAddress['selected_shipping_method']['label']); + self::assertArrayHasKey('base_amount', $shippingAddress['selected_shipping_method']); + self::assertEquals($baseAmount, $shippingAddress['selected_shipping_method']['base_amount']); } /** @@ -90,9 +105,30 @@ public function testSetOfflineShippingMethod(string $carrierCode, string $method public function offlineShippingMethodDataProvider(): array { return [ - 'flatrate_flatrate' => ['flatrate', 'flatrate', 10, 'Flat Rate - Fixed'], - 'tablerate_bestway' => ['tablerate', 'bestway', 10, 'Best Way - Table Rate'], - 'freeshipping_freeshipping' => ['freeshipping', 'freeshipping', 0, 'Free Shipping - Free'], + 'flatrate_flatrate' => [ + 'flatrate', + 'flatrate', + 'Flat Rate', + 'Fixed', + ['value' => 10, 'currency' => 'USD'], + ['value' => 10, 'currency' => 'USD'], + ], + 'tablerate_bestway' => [ + 'tablerate', + 'bestway', + 'Best Way', + 'Table Rate', + ['value' => 10, 'currency' => 'USD'], + ['value' => 10, 'currency' => 'USD'], + ], + 'freeshipping_freeshipping' => [ + 'freeshipping', + 'freeshipping', + 'Free Shipping', + 'Free', + ['value' => 0, 'currency' => 'USD'], + ['value' => 0, 'currency' => 'USD'], + ], ]; } @@ -122,8 +158,16 @@ private function getQuery( selected_shipping_method { carrier_code method_code - amount - label + carrier_title + method_title + amount { + value + currency + } + base_amount { + value + currency + } } } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingMethodsOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingMethodsOnCartTest.php index a5c91865926a5..9ddedbfc46541 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingMethodsOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingMethodsOnCartTest.php @@ -67,10 +67,32 @@ public function testSetShippingMethodOnCartWithSimpleProduct() self::assertArrayHasKey('selected_shipping_method', $shippingAddress); self::assertArrayHasKey('carrier_code', $shippingAddress['selected_shipping_method']); - self::assertEquals($carrierCode, $shippingAddress['selected_shipping_method']['carrier_code']); + self::assertEquals('flatrate', $shippingAddress['selected_shipping_method']['carrier_code']); self::assertArrayHasKey('method_code', $shippingAddress['selected_shipping_method']); - self::assertEquals($methodCode, $shippingAddress['selected_shipping_method']['method_code']); + self::assertEquals('flatrate', $shippingAddress['selected_shipping_method']['method_code']); + + self::assertArrayHasKey('carrier_title', $shippingAddress['selected_shipping_method']); + self::assertEquals('Flat Rate', $shippingAddress['selected_shipping_method']['carrier_title']); + + self::assertArrayHasKey('method_title', $shippingAddress['selected_shipping_method']); + self::assertEquals('Fixed', $shippingAddress['selected_shipping_method']['method_title']); + + self::assertArrayHasKey('amount', $shippingAddress['selected_shipping_method']); + $amount = $shippingAddress['selected_shipping_method']['amount']; + + self::assertArrayHasKey('value', $amount); + self::assertEquals(10, $amount['value']); + self::assertArrayHasKey('currency', $amount); + self::assertEquals('USD', $amount['currency']); + + self::assertArrayHasKey('base_amount', $shippingAddress['selected_shipping_method']); + $baseAmount = $shippingAddress['selected_shipping_method']['base_amount']; + + self::assertArrayHasKey('value', $baseAmount); + self::assertEquals(10, $baseAmount['value']); + self::assertArrayHasKey('currency', $baseAmount); + self::assertEquals('USD', $baseAmount['currency']); } /** @@ -347,6 +369,16 @@ private function getQuery( selected_shipping_method { carrier_code method_code + carrier_title + method_title + amount { + value + currency + } + base_amount { + value + currency + } } } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSelectedShippingMethodTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSelectedShippingMethodTest.php index bfdecca782319..bd684a950b590 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSelectedShippingMethodTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSelectedShippingMethodTest.php @@ -56,6 +56,28 @@ public function testGetSelectedShippingMethod() self::assertArrayHasKey('method_code', $shippingAddress['selected_shipping_method']); self::assertEquals('flatrate', $shippingAddress['selected_shipping_method']['method_code']); + + self::assertArrayHasKey('carrier_title', $shippingAddress['selected_shipping_method']); + self::assertEquals('Flat Rate', $shippingAddress['selected_shipping_method']['carrier_title']); + + self::assertArrayHasKey('method_title', $shippingAddress['selected_shipping_method']); + self::assertEquals('Fixed', $shippingAddress['selected_shipping_method']['method_title']); + + self::assertArrayHasKey('amount', $shippingAddress['selected_shipping_method']); + $amount = $shippingAddress['selected_shipping_method']['amount']; + + self::assertArrayHasKey('value', $amount); + self::assertEquals(10, $amount['value']); + self::assertArrayHasKey('currency', $amount); + self::assertEquals('USD', $amount['currency']); + + self::assertArrayHasKey('base_amount', $shippingAddress['selected_shipping_method']); + $baseAmount = $shippingAddress['selected_shipping_method']['base_amount']; + + self::assertArrayHasKey('value', $baseAmount); + self::assertEquals(10, $baseAmount['value']); + self::assertArrayHasKey('currency', $baseAmount); + self::assertEquals('USD', $baseAmount['currency']); } /** @@ -100,8 +122,10 @@ public function testGetGetSelectedShippingMethodIfShippingMethodIsNotSet() self::assertNull($shippingAddress['selected_shipping_method']['carrier_code']); self::assertNull($shippingAddress['selected_shipping_method']['method_code']); - self::assertNull($shippingAddress['selected_shipping_method']['label']); + self::assertNull($shippingAddress['selected_shipping_method']['carrier_title']); + self::assertNull($shippingAddress['selected_shipping_method']['method_title']); self::assertNull($shippingAddress['selected_shipping_method']['amount']); + self::assertNull($shippingAddress['selected_shipping_method']['base_amount']); } /** @@ -128,8 +152,16 @@ private function getQuery(string $maskedQuoteId): string selected_shipping_method { carrier_code method_code - label - amount + carrier_title + method_title + amount { + value + currency + } + base_amount { + value + currency + } } } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetOfflineShippingMethodsOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetOfflineShippingMethodsOnCartTest.php index 2dc4ea360acb9..ff2c5f2e6b528 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetOfflineShippingMethodsOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetOfflineShippingMethodsOnCartTest.php @@ -40,12 +40,21 @@ protected function setUp() * * @param string $carrierCode * @param string $methodCode - * @param float $amount - * @param string $label + * @param string $carrierTitle + * @param string $methodTitle + * @param array $amount + * @param array $baseAmount + * @throws \Magento\Framework\Exception\NoSuchEntityException * @dataProvider offlineShippingMethodDataProvider */ - public function testSetOfflineShippingMethod(string $carrierCode, string $methodCode, float $amount, string $label) - { + public function testSetOfflineShippingMethod( + string $carrierCode, + string $methodCode, + string $carrierTitle, + string $methodTitle, + array $amount, + array $baseAmount + ) { $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $query = $this->getQuery( @@ -69,11 +78,17 @@ public function testSetOfflineShippingMethod(string $carrierCode, string $method self::assertArrayHasKey('method_code', $shippingAddress['selected_shipping_method']); self::assertEquals($methodCode, $shippingAddress['selected_shipping_method']['method_code']); + self::assertArrayHasKey('carrier_title', $shippingAddress['selected_shipping_method']); + self::assertEquals($carrierTitle, $shippingAddress['selected_shipping_method']['carrier_title']); + + self::assertArrayHasKey('method_title', $shippingAddress['selected_shipping_method']); + self::assertEquals($methodTitle, $shippingAddress['selected_shipping_method']['method_title']); + self::assertArrayHasKey('amount', $shippingAddress['selected_shipping_method']); self::assertEquals($amount, $shippingAddress['selected_shipping_method']['amount']); - self::assertArrayHasKey('label', $shippingAddress['selected_shipping_method']); - self::assertEquals($label, $shippingAddress['selected_shipping_method']['label']); + self::assertArrayHasKey('base_amount', $shippingAddress['selected_shipping_method']); + self::assertEquals($baseAmount, $shippingAddress['selected_shipping_method']['base_amount']); } /** @@ -82,9 +97,30 @@ public function testSetOfflineShippingMethod(string $carrierCode, string $method public function offlineShippingMethodDataProvider(): array { return [ - 'flatrate_flatrate' => ['flatrate', 'flatrate', 10, 'Flat Rate - Fixed'], - 'tablerate_bestway' => ['tablerate', 'bestway', 10, 'Best Way - Table Rate'], - 'freeshipping_freeshipping' => ['freeshipping', 'freeshipping', 0, 'Free Shipping - Free'], + 'flatrate_flatrate' => [ + 'flatrate', + 'flatrate', + 'Flat Rate', + 'Fixed', + ['value' => 10, 'currency' => 'USD'], + ['value' => 10, 'currency' => 'USD'], + ], + 'tablerate_bestway' => [ + 'tablerate', + 'bestway', + 'Best Way', + 'Table Rate', + ['value' => 10, 'currency' => 'USD'], + ['value' => 10, 'currency' => 'USD'], + ], + 'freeshipping_freeshipping' => [ + 'freeshipping', + 'freeshipping', + 'Free Shipping', + 'Free', + ['value' => 0, 'currency' => 'USD'], + ['value' => 0, 'currency' => 'USD'], + ], ]; } @@ -114,8 +150,16 @@ private function getQuery( selected_shipping_method { carrier_code method_code - amount - label + carrier_title + method_title + amount { + value + currency + } + base_amount { + value + currency + } } } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingMethodsOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingMethodsOnCartTest.php index 3cac485f9f6f2..0c2bf1453b547 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingMethodsOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingMethodsOnCartTest.php @@ -59,10 +59,32 @@ public function testSetShippingMethodOnCartWithSimpleProduct() self::assertArrayHasKey('selected_shipping_method', $shippingAddress); self::assertArrayHasKey('carrier_code', $shippingAddress['selected_shipping_method']); - self::assertEquals($carrierCode, $shippingAddress['selected_shipping_method']['carrier_code']); + self::assertEquals('flatrate', $shippingAddress['selected_shipping_method']['carrier_code']); self::assertArrayHasKey('method_code', $shippingAddress['selected_shipping_method']); - self::assertEquals($methodCode, $shippingAddress['selected_shipping_method']['method_code']); + self::assertEquals('flatrate', $shippingAddress['selected_shipping_method']['method_code']); + + self::assertArrayHasKey('carrier_title', $shippingAddress['selected_shipping_method']); + self::assertEquals('Flat Rate', $shippingAddress['selected_shipping_method']['carrier_title']); + + self::assertArrayHasKey('method_title', $shippingAddress['selected_shipping_method']); + self::assertEquals('Fixed', $shippingAddress['selected_shipping_method']['method_title']); + + self::assertArrayHasKey('amount', $shippingAddress['selected_shipping_method']); + $amount = $shippingAddress['selected_shipping_method']['amount']; + + self::assertArrayHasKey('value', $amount); + self::assertEquals(10, $amount['value']); + self::assertArrayHasKey('currency', $amount); + self::assertEquals('USD', $amount['currency']); + + self::assertArrayHasKey('base_amount', $shippingAddress['selected_shipping_method']); + $baseAmount = $shippingAddress['selected_shipping_method']['base_amount']; + + self::assertArrayHasKey('value', $baseAmount); + self::assertEquals(10, $baseAmount['value']); + self::assertArrayHasKey('currency', $baseAmount); + self::assertEquals('USD', $baseAmount['currency']); } /** @@ -358,6 +380,16 @@ private function getQuery( selected_shipping_method { carrier_code method_code + carrier_title + method_title + amount { + value + currency + } + base_amount { + value + currency + } } } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php index ea498ddb31d16..2f6f39d169009 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php @@ -48,9 +48,9 @@ class SetUpsShippingMethodsOnCartTest extends GraphQlAbstract { /** - * Defines carrier label for "UPS" shipping method + * Defines carrier title for "UPS" shipping method */ - const CARRIER_LABEL = 'United Parcel Service'; + const CARRIER_TITLE = 'United Parcel Service'; /** * Defines carrier code for "UPS" shipping method @@ -87,9 +87,9 @@ protected function setUp() * * @dataProvider dataProviderShippingMethods * @param string $methodCode - * @param string $methodLabel + * @param string $methodTitle */ - public function testSetUpsShippingMethod(string $methodCode, string $methodLabel) + public function testSetUpsShippingMethod(string $methodCode, string $methodTitle) { $quoteReservedId = 'test_quote'; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($quoteReservedId); @@ -111,11 +111,11 @@ public function testSetUpsShippingMethod(string $methodCode, string $methodLabel self::assertArrayHasKey('method_code', $shippingAddress['selected_shipping_method']); self::assertEquals($methodCode, $shippingAddress['selected_shipping_method']['method_code']); - self::assertArrayHasKey('label', $shippingAddress['selected_shipping_method']); - self::assertEquals( - self::CARRIER_LABEL . ' - ' . $methodLabel, - $shippingAddress['selected_shipping_method']['label'] - ); + self::assertArrayHasKey('carrier_title', $shippingAddress['selected_shipping_method']); + self::assertEquals(self::CARRIER_TITLE, $shippingAddress['selected_shipping_method']['carrier_title']); + + self::assertArrayHasKey('method_title', $shippingAddress['selected_shipping_method']); + self::assertEquals($methodTitle, $shippingAddress['selected_shipping_method']['method_title']); } /** @@ -142,9 +142,9 @@ public function dataProviderShippingMethods(): array * * @dataProvider dataProviderShippingMethodsBasedOnCanadaAddress * @param string $methodCode - * @param string $methodLabel + * @param string $methodTitle */ - public function testSetUpsShippingMethodBasedOnCanadaAddress(string $methodCode, string $methodLabel) + public function testSetUpsShippingMethodBasedOnCanadaAddress(string $methodCode, string $methodTitle) { $quoteReservedId = 'test_quote'; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($quoteReservedId); @@ -166,11 +166,11 @@ public function testSetUpsShippingMethodBasedOnCanadaAddress(string $methodCode, self::assertArrayHasKey('method_code', $shippingAddress['selected_shipping_method']); self::assertEquals($methodCode, $shippingAddress['selected_shipping_method']['method_code']); - self::assertArrayHasKey('label', $shippingAddress['selected_shipping_method']); - self::assertEquals( - self::CARRIER_LABEL . ' - ' . $methodLabel, - $shippingAddress['selected_shipping_method']['label'] - ); + self::assertArrayHasKey('carrier_title', $shippingAddress['selected_shipping_method']); + self::assertEquals(self::CARRIER_TITLE, $shippingAddress['selected_shipping_method']['carrier_title']); + + self::assertArrayHasKey('method_title', $shippingAddress['selected_shipping_method']); + self::assertEquals($methodTitle, $shippingAddress['selected_shipping_method']['method_title']); } /** @@ -216,7 +216,8 @@ private function getQuery( selected_shipping_method { carrier_code method_code - label + carrier_title + method_title } } } From 2c8cec53cdca28232693c7775b8f4f8b69bdfc3a Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Mon, 29 Apr 2019 20:15:37 -0500 Subject: [PATCH 312/773] GraphQL-575: Schema inconsistency of "SelectedShippingMethod" declaration --- .../Resolver/ShippingAddress/SelectedShippingMethod.php | 5 +++-- .../Quote/Customer/GetSpecifiedBillingAddressTest.php | 2 +- .../GraphQl/Quote/Guest/GetSpecifiedBillingAddressTest.php | 2 +- .../Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php | 2 -- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/SelectedShippingMethod.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/SelectedShippingMethod.php index 6f92611e25f48..cd8f20c3f164f 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/SelectedShippingMethod.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/SelectedShippingMethod.php @@ -32,12 +32,13 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value $rates = $address->getAllShippingRates(); if (count($rates) > 0) { + list($carrierCode, $methodCode) = explode('_', $address->getShippingMethod(), 2); /** @var Rate $rate */ $rate = current($rates); $data = [ - 'carrier_code' => $rate->getCarrier(), - 'method_code' => $rate->getMethod(), + 'carrier_code' => $carrierCode, + 'method_code' => $methodCode, 'carrier_title' => $rate->getCarrierTitle(), 'method_title' => $rate->getMethodTitle(), 'amount' => [ diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSpecifiedBillingAddressTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSpecifiedBillingAddressTest.php index e10d12d73e7a6..1ff5ddbde54ec 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSpecifiedBillingAddressTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSpecifiedBillingAddressTest.php @@ -110,7 +110,7 @@ public function testGeSpecifiedBillingAddressIfBillingAddressIsNotSet() 'label' => null, ], 'telephone' => null, - '__typename' => null, + '__typename' => 'BillingCartAddress', 'customer_notes' => null, ]; self::assertEquals($expectedBillingAddressData, $response['cart']['billing_address']); diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedBillingAddressTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedBillingAddressTest.php index 68e99feb5fae2..48bff73226894 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedBillingAddressTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedBillingAddressTest.php @@ -100,7 +100,7 @@ public function testGeSpecifiedBillingAddressIfBillingAddressIsNotSet() 'label' => null, ], 'telephone' => null, - '__typename' => null, + '__typename' => 'BillingCartAddress', ]; self::assertEquals($expectedBillingAddressData, $response['cart']['billing_address']); } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php index 2f6f39d169009..d317c243e84b6 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php @@ -115,7 +115,6 @@ public function testSetUpsShippingMethod(string $methodCode, string $methodTitle self::assertEquals(self::CARRIER_TITLE, $shippingAddress['selected_shipping_method']['carrier_title']); self::assertArrayHasKey('method_title', $shippingAddress['selected_shipping_method']); - self::assertEquals($methodTitle, $shippingAddress['selected_shipping_method']['method_title']); } /** @@ -170,7 +169,6 @@ public function testSetUpsShippingMethodBasedOnCanadaAddress(string $methodCode, self::assertEquals(self::CARRIER_TITLE, $shippingAddress['selected_shipping_method']['carrier_title']); self::assertArrayHasKey('method_title', $shippingAddress['selected_shipping_method']); - self::assertEquals($methodTitle, $shippingAddress['selected_shipping_method']['method_title']); } /** From 49987df3971a19290bb96b902b9dd3eb93089af7 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Mon, 29 Apr 2019 20:48:34 -0500 Subject: [PATCH 313/773] GraphQL-575: Schema inconsistency of "SelectedShippingMethod" declaration --- .../Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php index d317c243e84b6..c50ae0a70380e 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php @@ -88,6 +88,7 @@ protected function setUp() * @dataProvider dataProviderShippingMethods * @param string $methodCode * @param string $methodTitle + * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function testSetUpsShippingMethod(string $methodCode, string $methodTitle) { @@ -142,6 +143,7 @@ public function dataProviderShippingMethods(): array * @dataProvider dataProviderShippingMethodsBasedOnCanadaAddress * @param string $methodCode * @param string $methodTitle + * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function testSetUpsShippingMethodBasedOnCanadaAddress(string $methodCode, string $methodTitle) { From eff2dbadd415862841670e9807f27534e326cbea Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Mon, 29 Apr 2019 23:21:16 -0500 Subject: [PATCH 314/773] GraphQL-631: Schema inconsistency of "Quantity / Qty" declaration --- setup/performance-toolkit/benchmark.jmx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup/performance-toolkit/benchmark.jmx b/setup/performance-toolkit/benchmark.jmx index c1d21a08f9e2d..0609be4d7d193 100644 --- a/setup/performance-toolkit/benchmark.jmx +++ b/setup/performance-toolkit/benchmark.jmx @@ -41820,7 +41820,7 @@ vars.put("product_sku", product.get("sku")); <hashTree/> </hashTree> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Update Simple Product quantity In Cart" enabled="true"> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Update Simple Product qty In Cart" enabled="true"> <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> <collectionProp name="Arguments.arguments"> @@ -42126,7 +42126,7 @@ vars.put("product_sku", product.get("sku")); <hashTree/> </hashTree> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Update Configurable Product quantity In Cart" enabled="true"> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Update Configurable Product qty In Cart" enabled="true"> <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> <collectionProp name="Arguments.arguments"> From 6721b5e05e67216e9c5c2d51be219d0f222f8da7 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Tue, 30 Apr 2019 14:30:47 -0500 Subject: [PATCH 315/773] GraphQL-631: Schema inconsistency of "Quantity / Qty" declaration --- .../etc/schema.graphqls | 2 +- .../Model/Cart/AddSimpleProductToCart.php | 22 +++---- .../Model/Resolver/SelectedPaymentMethod.php | 1 + .../Model/Resolver/UpdateCartItems.php | 6 +- .../Magento/QuoteGraphQl/etc/schema.graphqls | 17 +++--- .../CatalogInventory/AddProductToCartTest.php | 8 +-- .../AddConfigurableProductToCartTest.php | 20 +++---- ...mpleProductWithCustomOptionsToCartTest.php | 8 +-- ...tualProductWithCustomOptionsToCartTest.php | 8 +-- .../Customer/AddSimpleProductToCartTest.php | 16 ++--- .../Customer/AddVirtualProductToCartTest.php | 12 ++-- .../Quote/Customer/CheckoutEndToEndTest.php | 4 +- .../SetOfflinePaymentMethodsOnCartTest.php | 59 +++++++++++-------- .../Quote/Customer/UpdateCartItemsTest.php | 18 +++--- .../Guest/AddSimpleProductToCartTest.php | 24 ++++---- .../Guest/AddVirtualProductToCartTest.php | 24 ++++---- .../Quote/Guest/CheckoutEndToEndTest.php | 10 ++-- .../SetOfflinePaymentMethodsOnCartTest.php | 58 ++++++++++-------- .../Quote/Guest/UpdateCartItemsTest.php | 18 +++--- 19 files changed, 178 insertions(+), 157 deletions(-) diff --git a/app/code/Magento/ConfigurableProductGraphQl/etc/schema.graphqls b/app/code/Magento/ConfigurableProductGraphQl/etc/schema.graphqls index bf4ff723a646f..d4780c5c0867a 100644 --- a/app/code/Magento/ConfigurableProductGraphQl/etc/schema.graphqls +++ b/app/code/Magento/ConfigurableProductGraphQl/etc/schema.graphqls @@ -49,7 +49,7 @@ type AddConfigurableProductsToCartOutput { } input ConfigurableProductCartItemInput { - data: CartItemQuantityInput! + data: CartItemInput! variant_sku: String! customizable_options:[CustomizableOptionInput!] } diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php b/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php index ef9830bc75993..ad730288e5cc2 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php @@ -66,8 +66,8 @@ public function __construct( public function execute(Quote $cart, array $cartItemData): void { $sku = $this->extractSku($cartItemData); - $qty = $this->extractQty($cartItemData); - if ($qty <= 0) { + $quantity = $this->extractQuantity($cartItemData); + if ($quantity <= 0) { throw new GraphQlInputException( __('Please enter a number greater than 0 in this field.') ); @@ -81,7 +81,7 @@ public function execute(Quote $cart, array $cartItemData): void } try { - $result = $cart->addProduct($product, $this->createBuyRequest($qty, $customizableOptions)); + $result = $cart->addProduct($product, $this->createBuyRequest($quantity, $customizableOptions)); } catch (\Exception $e) { throw new GraphQlInputException( __( @@ -113,19 +113,19 @@ private function extractSku(array $cartItemData): string } /** - * Extract Qty from cart item data + * Extract quantity from cart item data * * @param array $cartItemData * @return float * @throws GraphQlInputException */ - private function extractQty(array $cartItemData): float + private function extractQuantity(array $cartItemData): float { - $qty = $this->arrayManager->get('data/quantity', $cartItemData); - if (!isset($qty)) { + $quantity = $this->arrayManager->get('data/quantity', $cartItemData); + if (!isset($quantity)) { throw new GraphQlInputException(__('Missing key "quantity" in cart item data')); } - return (float)$qty; + return (float)$quantity; } /** @@ -148,15 +148,15 @@ private function extractCustomizableOptions(array $cartItemData): array /** * Format GraphQl input data to a shape that buy request has * - * @param float $qty + * @param float $quantity * @param array $customOptions * @return DataObject */ - private function createBuyRequest(float $qty, array $customOptions): DataObject + private function createBuyRequest(float $quantity, array $customOptions): DataObject { return $this->dataObjectFactory->create([ 'data' => [ - 'qty' => $qty, + 'qty' => $quantity, 'options' => $customOptions, ], ]); diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/SelectedPaymentMethod.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/SelectedPaymentMethod.php index 7a99b04638ac3..8cda06eba3c91 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/SelectedPaymentMethod.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/SelectedPaymentMethod.php @@ -36,6 +36,7 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value return [ 'code' => $payment->getMethod(), + 'title' => $payment->getMethodInstance()->getTitle(), 'purchase_order_number' => $payment->getPoNumber(), ]; } diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/UpdateCartItems.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/UpdateCartItems.php index 25a79ae126ef8..b76c9159d8590 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/UpdateCartItems.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/UpdateCartItems.php @@ -99,7 +99,7 @@ private function processCartItems(Quote $cart, array $items): void if (!isset($item['quantity'])) { throw new GraphQlInputException(__('Required parameter "quantity" for "cart_items" is missing.')); } - $qty = (float)$item['quantity']; + $quantity = (float)$item['quantity']; $cartItem = $cart->getItemById($itemId); if ($cartItem === false) { @@ -108,10 +108,10 @@ private function processCartItems(Quote $cart, array $items): void ); } - if ($qty <= 0.0) { + if ($quantity <= 0.0) { $this->cartItemRepository->deleteById((int)$cart->getId(), $itemId); } else { - $cartItem->setQty($qty); + $cartItem->setQty($quantity); $this->validateCartItem($cartItem); $this->cartItemRepository->save($cartItem); } diff --git a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls index 3ab5a1863e7e1..e2d29e93db574 100644 --- a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls +++ b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls @@ -31,7 +31,7 @@ input AddSimpleProductsToCartInput { } input SimpleProductCartItemInput { - data: CartItemQuantityInput! + data: CartItemInput! customizable_options:[CustomizableOptionInput!] } @@ -41,11 +41,11 @@ input AddVirtualProductsToCartInput { } input VirtualProductCartItemInput { - data: CartItemQuantityInput! + data: CartItemInput! customizable_options:[CustomizableOptionInput!] } -input CartItemQuantityInput { +input CartItemInput { sku: String! quantity: Float! } @@ -62,10 +62,10 @@ input ApplyCouponToCartInput { input UpdateCartItemsInput { cart_id: String! - cart_items: [CartItemUpdateQuantityInput!]! + cart_items: [CartItemUpdateInput!]! } -input CartItemUpdateQuantityInput { +input CartItemUpdateInput { cart_item_id: Int! quantity: Float! } @@ -251,12 +251,13 @@ type AvailableShippingMethod { } type AvailablePaymentMethod { - code: String @doc(description: "The payment method code") - title: String @doc(description: "The payment method title.") + code: String! @doc(description: "The payment method code") + title: String! @doc(description: "The payment method title.") } type SelectedPaymentMethod { - code: String @doc(description: "The payment method code") + code: String! @doc(description: "The payment method code") + title: String! @doc(description: "The payment method title.") additional_data: SelectedPaymentMethodAdditionalData @doc(description: "Additional payment data") purchase_order_number: String @doc(description: "The purchase order number.") } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php index 68938e4c9dd2e..6f27693eeb4a7 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php @@ -39,10 +39,10 @@ protected function setUp() public function testAddProductIfQuantityIsNotAvailable() { $sku = 'simple'; - $qty = 200; + $quantity = 200; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); - $query = $this->getQuery($maskedQuoteId, $sku, $qty); + $query = $this->getQuery($maskedQuoteId, $sku, $quantity); $this->graphQlMutation($query); } @@ -58,10 +58,10 @@ public function testAddMoreProductsThatAllowed() $this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/167'); $sku = 'custom-design-simple-product'; - $qty = 7; + $quantity = 7; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); - $query = $this->getQuery($maskedQuoteId, $sku, $qty); + $query = $this->getQuery($maskedQuoteId, $sku, $quantity); $this->graphQlMutation($query); } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/AddConfigurableProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/AddConfigurableProductToCartTest.php index fa45263e65548..6810f9d44ce91 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/AddConfigurableProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/AddConfigurableProductToCartTest.php @@ -37,14 +37,14 @@ protected function setUp() public function testAddConfigurableProductToCart() { $variantSku = 'simple_41'; - $qty = 2; + $quantity = 2; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); - $query = $this->getQuery($maskedQuoteId, $variantSku, $qty); + $query = $this->getQuery($maskedQuoteId, $variantSku, $quantity); $response = $this->graphQlMutation($query); $cartItems = $response['addConfigurableProductsToCart']['cart']['items']; - self::assertEquals($qty, $cartItems[0]['quantity']); + self::assertEquals($quantity, $cartItems[0]['quantity']); self::assertEquals($variantSku, $cartItems[0]['product']['sku']); } @@ -57,10 +57,10 @@ public function testAddConfigurableProductToCart() public function testAddProductIfQuantityIsNotAvailable() { $variantSku = 'simple_41'; - $qty = 200; + $quantity = 200; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); - $query = $this->getQuery($maskedQuoteId, $variantSku, $qty); + $query = $this->getQuery($maskedQuoteId, $variantSku, $quantity); $this->graphQlMutation($query); } @@ -73,20 +73,20 @@ public function testAddProductIfQuantityIsNotAvailable() public function testAddOutOfStockProduct() { $variantSku = 'simple_1010'; - $qty = 1; + $quantity = 1; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); - $query = $this->getQuery($maskedQuoteId, $variantSku, $qty); + $query = $this->getQuery($maskedQuoteId, $variantSku, $quantity); $this->graphQlMutation($query); } /** * @param string $maskedQuoteId * @param string $variantSku - * @param int $qty + * @param int $quantity * @return string */ - private function getQuery(string $maskedQuoteId, string $variantSku, int $qty): string + private function getQuery(string $maskedQuoteId, string $variantSku, int $quantity): string { return <<<QUERY mutation { @@ -97,7 +97,7 @@ private function getQuery(string $maskedQuoteId, string $variantSku, int $qty): { variant_sku: "{$variantSku}" data: { - quantity: {$qty} + quantity: {$quantity} sku: "{$variantSku}" } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductWithCustomOptionsToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductWithCustomOptionsToCartTest.php index 714447f1e36a5..63546298304b0 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductWithCustomOptionsToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductWithCustomOptionsToCartTest.php @@ -46,7 +46,7 @@ protected function setUp() public function testAddSimpleProductWithOptions() { $sku = 'simple'; - $qty = 1; + $quantity = 1; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); $customOptionsValues = $this->getCustomOptionsValuesForQuery($sku); @@ -62,7 +62,7 @@ public function testAddSimpleProductWithOptions() cartItems: [ { data: { - quantity: $qty + quantity: $quantity sku: "$sku" }, customizable_options: $queryCustomizableOptions @@ -110,7 +110,7 @@ public function testAddSimpleProductWithOptions() public function testAddSimpleProductWithNoRequiredOptionsSet() { $sku = 'simple'; - $qty = 1; + $quantity = 1; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); $query = <<<QUERY @@ -121,7 +121,7 @@ public function testAddSimpleProductWithNoRequiredOptionsSet() cartItems: [ { data: { - quantity: $qty + quantity: $quantity sku: "$sku" } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddVirtualProductWithCustomOptionsToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddVirtualProductWithCustomOptionsToCartTest.php index 6172403c74086..94ac11ad8e0b1 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddVirtualProductWithCustomOptionsToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddVirtualProductWithCustomOptionsToCartTest.php @@ -46,7 +46,7 @@ protected function setUp() public function testAddVirtualProductWithOptions() { $sku = 'virtual'; - $qty = 1; + $quantity = 1; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); $customOptionsValues = $this->getCustomOptionsValuesForQuery($sku); @@ -62,7 +62,7 @@ public function testAddVirtualProductWithOptions() cartItems: [ { data: { - quantity: $qty + quantity: $quantity sku: "$sku" }, customizable_options: $queryCustomizableOptions @@ -110,7 +110,7 @@ public function testAddVirtualProductWithOptions() public function testAddVirtualProductWithNoRequiredOptionsSet() { $sku = 'virtual'; - $qty = 1; + $quantity = 1; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); $query = <<<QUERY @@ -121,7 +121,7 @@ public function testAddVirtualProductWithNoRequiredOptionsSet() cartItems: [ { data: { - quantity: $qty + quantity: $quantity sku: "$sku" } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddSimpleProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddSimpleProductToCartTest.php index 775d2733464ac..be22d860df122 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddSimpleProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddSimpleProductToCartTest.php @@ -43,13 +43,13 @@ protected function setUp() public function testAddSimpleProductToCart() { $sku = 'simple_product'; - $qty = 2; + $quantity = 2; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); - $query = $this->getQuery($maskedQuoteId, $sku, $qty); + $query = $this->getQuery($maskedQuoteId, $sku, $quantity); $response = $this->graphQlMutation($query, [], '', $this->getHeaderMap()); self::assertArrayHasKey('cart', $response['addSimpleProductsToCart']); - self::assertEquals($qty, $response['addSimpleProductsToCart']['cart']['items'][0]['quantity']); + self::assertEquals($quantity, $response['addSimpleProductsToCart']['cart']['items'][0]['quantity']); self::assertEquals($sku, $response['addSimpleProductsToCart']['cart']['items'][0]['product']['sku']); } @@ -63,10 +63,10 @@ public function testAddSimpleProductToCart() public function testAddProductToNonExistentCart() { $sku = 'simple_product'; - $qty = 2; + $quantity = 2; $maskedQuoteId = 'non_existent_masked_id'; - $query = $this->getQuery($maskedQuoteId, $sku, $qty); + $query = $this->getQuery($maskedQuoteId, $sku, $quantity); $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } @@ -130,10 +130,10 @@ public function testAddSimpleProductToAnotherCustomerCart() /** * @param string $maskedQuoteId * @param string $sku - * @param int $qty + * @param float $quantity * @return string */ - private function getQuery(string $maskedQuoteId, string $sku, int $qty): string + private function getQuery(string $maskedQuoteId, string $sku, float $quantity): string { return <<<QUERY mutation { @@ -142,7 +142,7 @@ private function getQuery(string $maskedQuoteId, string $sku, int $qty): string cartItems: [ { data: { - quantity: {$qty} + quantity: {$quantity} sku: "{$sku}" } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddVirtualProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddVirtualProductToCartTest.php index 86444f767ca78..1269b9d8e7b3d 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddVirtualProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddVirtualProductToCartTest.php @@ -43,13 +43,13 @@ protected function setUp() public function testAddVirtualProductToCart() { $sku = 'virtual_product'; - $qty = 2; + $quantity = 2; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); - $query = $this->getQuery($maskedQuoteId, $sku, $qty); + $query = $this->getQuery($maskedQuoteId, $sku, $quantity); $response = $this->graphQlMutation($query, [], '', $this->getHeaderMap()); self::assertArrayHasKey('cart', $response['addVirtualProductsToCart']); - self::assertEquals($qty, $response['addVirtualProductsToCart']['cart']['items'][0]['quantity']); + self::assertEquals($quantity, $response['addVirtualProductsToCart']['cart']['items'][0]['quantity']); self::assertEquals($sku, $response['addVirtualProductsToCart']['cart']['items'][0]['product']['sku']); } @@ -130,10 +130,10 @@ public function testAddVirtualProductToAnotherCustomerCart() /** * @param string $maskedQuoteId * @param string $sku - * @param int $qty + * @param float $quantity * @return string */ - private function getQuery(string $maskedQuoteId, string $sku, int $qty): string + private function getQuery(string $maskedQuoteId, string $sku, float $quantity): string { return <<<QUERY mutation { @@ -142,7 +142,7 @@ private function getQuery(string $maskedQuoteId, string $sku, int $qty): string cartItems: [ { data: { - quantity: {$qty} + quantity: {$quantity} sku: "{$sku}" } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php index 2a8609e009f4d..92974f2491f75 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php @@ -81,7 +81,7 @@ protected function setUp() */ public function testCheckoutWorkflow() { - $qty = 2; + $quantity = 2; $this->createCustomer(); $token = $this->loginCustomer(); @@ -89,7 +89,7 @@ public function testCheckoutWorkflow() $sku = $this->findProduct(); $cartId = $this->createEmptyCart(); - $this->addProductToCart($cartId, $qty, $sku); + $this->addProductToCart($cartId, $quantity, $sku); $this->setBillingAddress($cartId); $shippingMethod = $this->setShippingAddress($cartId); diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetOfflinePaymentMethodsOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetOfflinePaymentMethodsOnCartTest.php index e0f4756177715..0fe7aec2d6347 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetOfflinePaymentMethodsOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetOfflinePaymentMethodsOnCartTest.php @@ -50,23 +50,38 @@ protected function setUp() * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_payment_methods.php * * @param string $methodCode + * @param string $methodTitle * @dataProvider offlinePaymentMethodDataProvider */ - public function testSetOfflinePaymentMethod(string $methodCode) + public function testSetOfflinePaymentMethod(string $methodCode, string $methodTitle) { $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); - $query = $this->getQuery( - $maskedQuoteId, - $methodCode - ); + $query = $this->getQuery($maskedQuoteId, $methodCode); $response = $this->graphQlMutation($query, [], '', $this->getHeaderMap()); self::assertArrayHasKey('setPaymentMethodOnCart', $response); self::assertArrayHasKey('cart', $response['setPaymentMethodOnCart']); self::assertArrayHasKey('selected_payment_method', $response['setPaymentMethodOnCart']['cart']); - self::assertArrayHasKey('code', $response['setPaymentMethodOnCart']['cart']['selected_payment_method']); - self::assertEquals($methodCode, $response['setPaymentMethodOnCart']['cart']['selected_payment_method']['code']); + + $selectedPaymentMethod = $response['setPaymentMethodOnCart']['cart']['selected_payment_method']; + self::assertArrayHasKey('code', $selectedPaymentMethod); + self::assertEquals($methodCode, $selectedPaymentMethod['code']); + + self::assertArrayHasKey('title', $selectedPaymentMethod); + self::assertEquals($methodTitle, $selectedPaymentMethod['title']); + } + + /** + * @return array + */ + public function offlinePaymentMethodDataProvider(): array + { + return [ + 'check_mo' => [Checkmo::PAYMENT_METHOD_CHECKMO_CODE, 'Check / Money order'], + 'bank_transfer' => [Banktransfer::PAYMENT_METHOD_BANKTRANSFER_CODE, 'Bank Transfer Payment'], + 'cash_on_delivery' => [Cashondelivery::PAYMENT_METHOD_CASHONDELIVERY_CODE, 'Cash On Delivery'], + ]; } /** @@ -76,12 +91,11 @@ public function testSetOfflinePaymentMethod(string $methodCode) * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_payment_methods.php - * - * @param string $methodCode */ public function testSetPurchaseOrderPaymentMethod() { $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $methodTitle = 'Purchase Order'; $methodCode = Purchaseorder::PAYMENT_METHOD_PURCHASEORDER_CODE; $poNumber = 'abc123'; @@ -97,34 +111,28 @@ public function testSetPurchaseOrderPaymentMethod() cart { selected_payment_method { code + title purchase_order_number } } } } QUERY; - $response = $this->graphQlMutation($query, [], '', $this->getHeaderMap()); self::assertArrayHasKey('setPaymentMethodOnCart', $response); self::assertArrayHasKey('cart', $response['setPaymentMethodOnCart']); self::assertArrayHasKey('selected_payment_method', $response['setPaymentMethodOnCart']['cart']); - self::assertArrayHasKey('code', $response['setPaymentMethodOnCart']['cart']['selected_payment_method']); - self::assertArrayHasKey('purchase_order_number', $response['setPaymentMethodOnCart']['cart']['selected_payment_method']); - self::assertEquals($methodCode, $response['setPaymentMethodOnCart']['cart']['selected_payment_method']['code']); - self::assertEquals($poNumber, $response['setPaymentMethodOnCart']['cart']['selected_payment_method']['purchase_order_number']); - } - /** - * @return array - */ - public function offlinePaymentMethodDataProvider(): array - { - return [ - 'check_mo' => [Checkmo::PAYMENT_METHOD_CHECKMO_CODE], - 'bank_transfer' => [Banktransfer::PAYMENT_METHOD_BANKTRANSFER_CODE], - 'cash_on_delivery' => [Cashondelivery::PAYMENT_METHOD_CASHONDELIVERY_CODE], - ]; + $selectedPaymentMethod = $response['setPaymentMethodOnCart']['cart']['selected_payment_method']; + self::assertArrayHasKey('code', $selectedPaymentMethod); + self::assertEquals($methodCode, $selectedPaymentMethod['code']); + + self::assertArrayHasKey('title', $selectedPaymentMethod); + self::assertEquals($methodTitle, $selectedPaymentMethod['title']); + + self::assertArrayHasKey('purchase_order_number', $selectedPaymentMethod); + self::assertEquals($poNumber, $selectedPaymentMethod['purchase_order_number']); } /** @@ -147,6 +155,7 @@ private function getQuery( cart { selected_payment_method { code + title } } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/UpdateCartItemsTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/UpdateCartItemsTest.php index c7f51efe3c98e..bc88bd1ddb438 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/UpdateCartItemsTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/UpdateCartItemsTest.php @@ -58,15 +58,15 @@ protected function setUp() /** * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php */ - public function testUpdateCartItemQty() + public function testUpdateCartItemQuantity() { $quote = $this->quoteFactory->create(); $this->quoteResource->load($quote, 'test_order_1', 'reserved_order_id'); $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$quote->getId()); $itemId = (int)$quote->getItemByProduct($this->productRepository->get('simple'))->getId(); - $qty = 2; + $quantity = 2; - $query = $this->getQuery($maskedQuoteId, $itemId, $qty); + $query = $this->getQuery($maskedQuoteId, $itemId, $quantity); $response = $this->graphQlMutation($query, [], '', $this->getHeaderMap()); $this->assertArrayHasKey('updateCartItems', $response); @@ -76,7 +76,7 @@ public function testUpdateCartItemQty() $item = current($responseCart['items']); $this->assertEquals($itemId, $item['id']); - $this->assertEquals($qty, $item['quantity']); + $this->assertEquals($quantity, $item['quantity']); } /** @@ -88,9 +88,9 @@ public function testRemoveCartItemIfQuantityIsZero() $this->quoteResource->load($quote, 'test_order_1', 'reserved_order_id'); $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$quote->getId()); $itemId = (int)$quote->getItemByProduct($this->productRepository->get('simple'))->getId(); - $qty = 0; + $quantity = 0; - $query = $this->getQuery($maskedQuoteId, $itemId, $qty); + $query = $this->getQuery($maskedQuoteId, $itemId, $quantity); $response = $this->graphQlMutation($query, [], '', $this->getHeaderMap()); $this->assertArrayHasKey('updateCartItems', $response); @@ -293,10 +293,10 @@ public function dataProviderUpdateWithMissedRequiredParameters(): array /** * @param string $maskedQuoteId * @param int $itemId - * @param float $qty + * @param float $quantity * @return string */ - private function getQuery(string $maskedQuoteId, int $itemId, float $qty): string + private function getQuery(string $maskedQuoteId, int $itemId, float $quantity): string { return <<<QUERY mutation { @@ -305,7 +305,7 @@ private function getQuery(string $maskedQuoteId, int $itemId, float $qty): strin cart_items:[ { cart_item_id: {$itemId} - quantity: {$qty} + quantity: {$quantity} } ] }) { diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddSimpleProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddSimpleProductToCartTest.php index 04c2daf755c1a..8b20320fc2f02 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddSimpleProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddSimpleProductToCartTest.php @@ -37,14 +37,14 @@ protected function setUp() public function testAddSimpleProductToCart() { $sku = 'simple_product'; - $qty = 2; + $quantity = 2; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); - $query = $this->getQuery($maskedQuoteId, $sku, $qty); + $query = $this->getQuery($maskedQuoteId, $sku, $quantity); $response = $this->graphQlMutation($query); self::assertArrayHasKey('cart', $response['addSimpleProductsToCart']); - self::assertEquals($qty, $response['addSimpleProductsToCart']['cart']['items'][0]['quantity']); + self::assertEquals($quantity, $response['addSimpleProductsToCart']['cart']['items'][0]['quantity']); self::assertEquals($sku, $response['addSimpleProductsToCart']['cart']['items'][0]['product']['sku']); } @@ -57,10 +57,10 @@ public function testAddSimpleProductToCart() public function testAddProductToNonExistentCart() { $sku = 'simple_product'; - $qty = 1; + $quantity = 1; $maskedQuoteId = 'non_existent_masked_id'; - $query = $this->getQuery($maskedQuoteId, $sku, $qty); + $query = $this->getQuery($maskedQuoteId, $sku, $quantity); $this->graphQlMutation($query); } @@ -73,10 +73,10 @@ public function testAddProductToNonExistentCart() public function testNonExistentProductToCart() { $sku = 'simple_product'; - $qty = 1; + $quantity = 1; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); - $query = $this->getQuery($maskedQuoteId, $sku, $qty); + $query = $this->getQuery($maskedQuoteId, $sku, $quantity); $this->graphQlMutation($query); } @@ -88,9 +88,9 @@ public function testNonExistentProductToCart() public function testAddSimpleProductToCustomerCart() { $sku = 'simple_product'; - $qty = 2; + $quantity = 2; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); - $query = $this->getQuery($maskedQuoteId, $sku, $qty); + $query = $this->getQuery($maskedQuoteId, $sku, $quantity); $this->expectExceptionMessage( "The current user cannot perform operations on cart \"$maskedQuoteId\"" @@ -102,10 +102,10 @@ public function testAddSimpleProductToCustomerCart() /** * @param string $maskedQuoteId * @param string $sku - * @param int $qty + * @param float $quantity * @return string */ - private function getQuery(string $maskedQuoteId, string $sku, int $qty): string + private function getQuery(string $maskedQuoteId, string $sku, float $quantity): string { return <<<QUERY mutation { @@ -115,7 +115,7 @@ private function getQuery(string $maskedQuoteId, string $sku, int $qty): string cartItems: [ { data: { - quantity: $qty + quantity: $quantity sku: "$sku" } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddVirtualProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddVirtualProductToCartTest.php index def3306d4e822..cb429e7b9cb9e 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddVirtualProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddVirtualProductToCartTest.php @@ -37,14 +37,14 @@ protected function setUp() public function testAddVirtualProductToCart() { $sku = 'virtual_product'; - $qty = 2; + $quantity = 2; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); - $query = $this->getQuery($maskedQuoteId, $sku, $qty); + $query = $this->getQuery($maskedQuoteId, $sku, $quantity); $response = $this->graphQlMutation($query); self::assertArrayHasKey('cart', $response['addVirtualProductsToCart']); - self::assertEquals($qty, $response['addVirtualProductsToCart']['cart']['items'][0]['quantity']); + self::assertEquals($quantity, $response['addVirtualProductsToCart']['cart']['items'][0]['quantity']); self::assertEquals($sku, $response['addVirtualProductsToCart']['cart']['items'][0]['product']['sku']); } @@ -57,10 +57,10 @@ public function testAddVirtualProductToCart() public function testAddVirtualToNonExistentCart() { $sku = 'virtual_product'; - $qty = 1; + $quantity = 1; $maskedQuoteId = 'non_existent_masked_id'; - $query = $this->getQuery($maskedQuoteId, $sku, $qty); + $query = $this->getQuery($maskedQuoteId, $sku, $quantity); $this->graphQlMutation($query); } @@ -73,10 +73,10 @@ public function testAddVirtualToNonExistentCart() public function testNonExistentProductToCart() { $sku = 'virtual_product'; - $qty = 1; + $quantity = 1; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); - $query = $this->getQuery($maskedQuoteId, $sku, $qty); + $query = $this->getQuery($maskedQuoteId, $sku, $quantity); $this->graphQlMutation($query); } @@ -89,9 +89,9 @@ public function testNonExistentProductToCart() public function testAddVirtualProductToCustomerCart() { $sku = 'virtual_product'; - $qty = 2; + $quantity = 2; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); - $query = $this->getQuery($maskedQuoteId, $sku, $qty); + $query = $this->getQuery($maskedQuoteId, $sku, $quantity); $this->expectExceptionMessage( "The current user cannot perform operations on cart \"$maskedQuoteId\"" @@ -103,10 +103,10 @@ public function testAddVirtualProductToCustomerCart() /** * @param string $maskedQuoteId * @param string $sku - * @param int $qty + * @param float $quantity * @return string */ - private function getQuery(string $maskedQuoteId, string $sku, int $qty): string + private function getQuery(string $maskedQuoteId, string $sku, float $quantity): string { return <<<QUERY mutation { @@ -116,7 +116,7 @@ private function getQuery(string $maskedQuoteId, string $sku, int $qty): string cartItems: [ { data: { - quantity: {$qty} + quantity: {$quantity} sku: "{$sku}" } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php index 614c4c244d4d6..bddee2151f5cd 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php @@ -69,12 +69,12 @@ protected function setUp() */ public function testCheckoutWorkflow() { - $qty = 2; + $quantity = 2; $sku = $this->findProduct(); $cartId = $this->createEmptyCart(); $this->setGuestEmailOnCart($cartId); - $this->addProductToCart($cartId, $qty, $sku); + $this->addProductToCart($cartId, $quantity, $sku); $this->setBillingAddress($cartId); $shippingMethod = $this->setShippingAddress($cartId); @@ -161,11 +161,11 @@ private function setGuestEmailOnCart(string $cartId): void /** * @param string $cartId - * @param float $qty + * @param float $quantity * @param string $sku * @return void */ - private function addProductToCart(string $cartId, float $qty, string $sku): void + private function addProductToCart(string $cartId, float $quantity, string $sku): void { $query = <<<QUERY mutation { @@ -175,7 +175,7 @@ private function addProductToCart(string $cartId, float $qty, string $sku): void cartItems: [ { data: { - quantity: {$qty} + quantity: {$quantity} sku: "{$sku}" } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetOfflinePaymentMethodsOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetOfflinePaymentMethodsOnCartTest.php index 83fffd9defabf..7ec3148ea85a0 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetOfflinePaymentMethodsOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetOfflinePaymentMethodsOnCartTest.php @@ -42,23 +42,38 @@ protected function setUp() * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_payment_methods.php * * @param string $methodCode + * @param string $methodTitle * @dataProvider offlinePaymentMethodDataProvider */ - public function testSetOfflinePaymentMethod(string $methodCode) + public function testSetOfflinePaymentMethod(string $methodCode, string $methodTitle) { $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); - $query = $this->getQuery( - $maskedQuoteId, - $methodCode - ); + $query = $this->getQuery($maskedQuoteId, $methodCode); $response = $this->graphQlMutation($query); self::assertArrayHasKey('setPaymentMethodOnCart', $response); self::assertArrayHasKey('cart', $response['setPaymentMethodOnCart']); self::assertArrayHasKey('selected_payment_method', $response['setPaymentMethodOnCart']['cart']); - self::assertArrayHasKey('code', $response['setPaymentMethodOnCart']['cart']['selected_payment_method']); - self::assertEquals($methodCode, $response['setPaymentMethodOnCart']['cart']['selected_payment_method']['code']); + + $selectedPaymentMethod = $response['setPaymentMethodOnCart']['cart']['selected_payment_method']; + self::assertArrayHasKey('code', $selectedPaymentMethod); + self::assertEquals($methodCode, $selectedPaymentMethod['code']); + + self::assertArrayHasKey('title', $selectedPaymentMethod); + self::assertEquals($methodTitle, $selectedPaymentMethod['title']); + } + + /** + * @return array + */ + public function offlinePaymentMethodDataProvider(): array + { + return [ + 'check_mo' => [Checkmo::PAYMENT_METHOD_CHECKMO_CODE, 'Check / Money order'], + 'bank_transfer' => [Banktransfer::PAYMENT_METHOD_BANKTRANSFER_CODE, 'Bank Transfer Payment'], + 'cash_on_delivery' => [Cashondelivery::PAYMENT_METHOD_CASHONDELIVERY_CODE, 'Cash On Delivery'], + ]; } /** @@ -67,13 +82,12 @@ public function testSetOfflinePaymentMethod(string $methodCode) * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_payment_methods.php - * - * @param string $methodCode */ public function testSetPurchaseOrderPaymentMethod() { $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $methodCode = Purchaseorder::PAYMENT_METHOD_PURCHASEORDER_CODE; + $methodTitle = 'Purchase Order'; $poNumber = 'abc123'; $query = <<<QUERY @@ -88,6 +102,7 @@ public function testSetPurchaseOrderPaymentMethod() cart { selected_payment_method { code + title purchase_order_number } } @@ -100,22 +115,16 @@ public function testSetPurchaseOrderPaymentMethod() self::assertArrayHasKey('setPaymentMethodOnCart', $response); self::assertArrayHasKey('cart', $response['setPaymentMethodOnCart']); self::assertArrayHasKey('selected_payment_method', $response['setPaymentMethodOnCart']['cart']); - self::assertArrayHasKey('code', $response['setPaymentMethodOnCart']['cart']['selected_payment_method']); - self::assertArrayHasKey('purchase_order_number', $response['setPaymentMethodOnCart']['cart']['selected_payment_method']); - self::assertEquals($methodCode, $response['setPaymentMethodOnCart']['cart']['selected_payment_method']['code']); - self::assertEquals($poNumber, $response['setPaymentMethodOnCart']['cart']['selected_payment_method']['purchase_order_number']); - } - /** - * @return array - */ - public function offlinePaymentMethodDataProvider(): array - { - return [ - 'check_mo' => [Checkmo::PAYMENT_METHOD_CHECKMO_CODE], - 'bank_transfer' => [Banktransfer::PAYMENT_METHOD_BANKTRANSFER_CODE], - 'cash_on_delivery' => [Cashondelivery::PAYMENT_METHOD_CASHONDELIVERY_CODE], - ]; + $selectedPaymentMethod = $response['setPaymentMethodOnCart']['cart']['selected_payment_method']; + self::assertArrayHasKey('code', $selectedPaymentMethod); + self::assertEquals($methodCode, $selectedPaymentMethod['code']); + + self::assertArrayHasKey('title', $selectedPaymentMethod); + self::assertEquals($methodTitle, $selectedPaymentMethod['title']); + + self::assertArrayHasKey('purchase_order_number', $selectedPaymentMethod); + self::assertEquals($poNumber, $selectedPaymentMethod['purchase_order_number']); } /** @@ -138,6 +147,7 @@ private function getQuery( cart { selected_payment_method { code + title } } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/UpdateCartItemsTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/UpdateCartItemsTest.php index 8738650b25b3f..1e1fb0a176992 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/UpdateCartItemsTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/UpdateCartItemsTest.php @@ -51,15 +51,15 @@ protected function setUp() /** * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php */ - public function testUpdateCartItemQty() + public function testUpdateCartItemQuantity() { $quote = $this->quoteFactory->create(); $this->quoteResource->load($quote, 'test_order_with_simple_product_without_address', 'reserved_order_id'); $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$quote->getId()); $itemId = (int)$quote->getItemByProduct($this->productRepository->get('simple'))->getId(); - $qty = 2; + $quantity = 2; - $query = $this->getQuery($maskedQuoteId, $itemId, $qty); + $query = $this->getQuery($maskedQuoteId, $itemId, $quantity); $response = $this->graphQlMutation($query); $this->assertArrayHasKey('updateCartItems', $response); @@ -69,7 +69,7 @@ public function testUpdateCartItemQty() $item = current($responseCart['items']); $this->assertEquals($itemId, $item['id']); - $this->assertEquals($qty, $item['quantity']); + $this->assertEquals($quantity, $item['quantity']); } /** @@ -81,9 +81,9 @@ public function testRemoveCartItemIfQuantityIsZero() $this->quoteResource->load($quote, 'test_order_with_simple_product_without_address', 'reserved_order_id'); $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$quote->getId()); $itemId = (int)$quote->getItemByProduct($this->productRepository->get('simple'))->getId(); - $qty = 0; + $quantity = 0; - $query = $this->getQuery($maskedQuoteId, $itemId, $qty); + $query = $this->getQuery($maskedQuoteId, $itemId, $quantity); $response = $this->graphQlMutation($query); $this->assertArrayHasKey('updateCartItems', $response); @@ -244,10 +244,10 @@ public function dataProviderUpdateWithMissedRequiredParameters(): array /** * @param string $maskedQuoteId * @param int $itemId - * @param float $qty + * @param float $quantity * @return string */ - private function getQuery(string $maskedQuoteId, int $itemId, float $qty): string + private function getQuery(string $maskedQuoteId, int $itemId, float $quantity): string { return <<<QUERY mutation { @@ -256,7 +256,7 @@ private function getQuery(string $maskedQuoteId, int $itemId, float $qty): strin cart_items: [ { cart_item_id: {$itemId} - quantity: {$qty} + quantity: {$quantity} } ] }) { From 96c78dca0c15ef7f5f4f3467e64d79814443f098 Mon Sep 17 00:00:00 2001 From: Oscar Recio <osrecio@gmail.com> Date: Mon, 29 Apr 2019 12:07:10 +0200 Subject: [PATCH 316/773] #628 Check if email or password are empty --- .../Model/Resolver/GenerateCustomerToken.php | 4 +- .../Customer/GenerateCustomerTokenTest.php | 50 +++++++++++++++++++ 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/CustomerGraphQl/Model/Resolver/GenerateCustomerToken.php b/app/code/Magento/CustomerGraphQl/Model/Resolver/GenerateCustomerToken.php index 1bd77fe1cde8f..2a7cb8a734a50 100644 --- a/app/code/Magento/CustomerGraphQl/Model/Resolver/GenerateCustomerToken.php +++ b/app/code/Magento/CustomerGraphQl/Model/Resolver/GenerateCustomerToken.php @@ -44,11 +44,11 @@ public function resolve( array $value = null, array $args = null ) { - if (!isset($args['email'])) { + if (!isset($args['email']) || empty($args['email'])) { throw new GraphQlInputException(__('Specify the "email" value.')); } - if (!isset($args['password'])) { + if (!isset($args['password']) || empty($args['password'])) { throw new GraphQlInputException(__('Specify the "password" value.')); } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/GenerateCustomerTokenTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/GenerateCustomerTokenTest.php index 88eaeaa8f9dd5..e13c1974e3067 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/GenerateCustomerTokenTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/GenerateCustomerTokenTest.php @@ -68,4 +68,54 @@ public function testGenerateCustomerTokenWithInvalidCredentials() 'was incorrect or your account is disabled temporarily. Please wait and try again later.'); $this->graphQlMutation($mutation); } + + /** + * Verify customer with empty email + */ + public function testGenerateCustomerTokenWithEmptyEmail() + { + $email = ''; + $password = 'bad-password'; + + $mutation + = <<<MUTATION +mutation { + generateCustomerToken( + email: "{$email}" + password: "{$password}" + ) { + token + } +} +MUTATION; + + $this->expectException(\Exception::class); + $this->expectExceptionMessage('GraphQL response contains errors: Specify the "email" value.'); + $this->graphQlMutation($mutation); + } + + /** + * Verify customer with empty password + */ + public function testGenerateCustomerTokenWithEmptyPassword() + { + $email = 'customer@example.com'; + $password = ''; + + $mutation + = <<<MUTATION +mutation { + generateCustomerToken( + email: "{$email}" + password: "{$password}" + ) { + token + } +} +MUTATION; + + $this->expectException(\Exception::class); + $this->expectExceptionMessage('GraphQL response contains errors: Specify the "password" value.'); + $this->graphQlMutation($mutation); + } } From ad08f9518ec5c147954dc27e6e9e0dc0e249ff4e Mon Sep 17 00:00:00 2001 From: Ievgenii Gryshkun <i.gryshkun@gmail.com> Date: Fri, 22 Mar 2019 14:53:44 +0200 Subject: [PATCH 317/773] Cannot return null for non-nullable field SelectedCustomizableOptionValue.sort_order and Call to a member function getPriceType() on null --- .../Model/Cart/AddSimpleProductToCart.php | 18 +++++++++++++++++- app/code/Magento/QuoteGraphQl/etc/di.xml | 2 +- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php b/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php index ad730288e5cc2..36a31642e5139 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php @@ -15,6 +15,7 @@ use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException; use Magento\Framework\Stdlib\ArrayManager; use Magento\Quote\Model\Quote; +use phpDocumentor\Reflection\Types\Mixed_; /** * Add simple product to cart @@ -140,7 +141,9 @@ private function extractCustomizableOptions(array $cartItemData): array $customizableOptionsData = []; foreach ($customizableOptions as $customizableOption) { - $customizableOptionsData[$customizableOption['id']] = $customizableOption['value']; + $customizableOptionsData[$customizableOption['id']] = $this->convertCustomOptions( + $customizableOption['value'] + ); } return $customizableOptionsData; } @@ -161,4 +164,17 @@ private function createBuyRequest(float $quantity, array $customOptions): DataOb ], ]); } + + /** + * @param string $value + * @return string|array + */ + private function convertCustomOptions(string $value) + { + if (substr($value, 0, 1) === "[" || + substr($value, strlen($value) - 1, 1) === "]") { + return explode(',', substr($value, 1, -1)); + } + return $value; + } } diff --git a/app/code/Magento/QuoteGraphQl/etc/di.xml b/app/code/Magento/QuoteGraphQl/etc/di.xml index 0697761a2a2a6..32b8b12987ffa 100644 --- a/app/code/Magento/QuoteGraphQl/etc/di.xml +++ b/app/code/Magento/QuoteGraphQl/etc/di.xml @@ -26,7 +26,7 @@ <item name="area" xsi:type="string">Magento\QuoteGraphQl\Model\CartItem\DataProvider\CustomizableOptionValue\Text</item> <item name="drop_down" xsi:type="string">Magento\QuoteGraphQl\Model\CartItem\DataProvider\CustomizableOptionValue\Dropdown</item> <item name="radio" xsi:type="string">Magento\QuoteGraphQl\Model\CartItem\DataProvider\CustomizableOptionValue\Dropdown</item> - <item name="checkbox" xsi:type="string">Magento\QuoteGraphQl\Model\CartItem\DataProvider\CustomizableOptionValue\Dropdown</item> + <item name="checkbox" xsi:type="string">Magento\QuoteGraphQl\Model\CartItem\DataProvider\CustomizableOptionValue\Multiple</item> <item name="multiple" xsi:type="string">Magento\QuoteGraphQl\Model\CartItem\DataProvider\CustomizableOptionValue\Multiple</item> </argument> </arguments> From e11230a8ea04b7ff93c6d7732db7c317ae27856a Mon Sep 17 00:00:00 2001 From: Ievgenii Gryshkun <i.gryshkun@gmail.com> Date: Thu, 28 Mar 2019 08:31:35 +0200 Subject: [PATCH 318/773] Cannot return null for non-nullable field SelectedCustomizableOptionValue.sort_order and Call to a member function getPriceType() on null --- .../Model/Cart/AddSimpleProductToCart.php | 1 - .../CatalogInventory/AddProductToCartTest.php | 83 +++++++++++++++++++ 2 files changed, 83 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php b/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php index 36a31642e5139..cf65393b08997 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php @@ -15,7 +15,6 @@ use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException; use Magento\Framework\Stdlib\ArrayManager; use Magento\Quote\Model\Quote; -use phpDocumentor\Reflection\Types\Mixed_; /** * Add simple product to cart diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php index 6f27693eeb4a7..c2fbfc1418dbf 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php @@ -46,6 +46,89 @@ public function testAddProductIfQuantityIsNotAvailable() $this->graphQlMutation($query); } + /** + * @magentoApiDataFixture Magento/Catalog/_files/product_simple_with_custom_options.php + * @magentoApiDataFixture Magento/Checkout/_files/active_quote.php + * @expectedException \Exception + * @expectedExceptionMessage The product's required option(s) weren't entered. Make sure the options are entered and try again. + */ + public function testAddProductWithoutRequiredCustomOPtions() + { + $sku = 'simple_with_custom_options'; + $qty = 1; + + $maskedQuoteId = $this->getMaskedQuoteId(); + $query = $this->getAddSimpleProductQuery($maskedQuoteId, $sku, $qty); + $this->graphQlQuery($query); + } + + /** + * @magentoApiDataFixture Magento/Catalog/_files/product_simple_with_custom_options.php + * @magentoApiDataFixture Magento/Checkout/_files/active_quote.php + */ + public function testAddProductWithRequiredCustomOPtions() + { + $sku = 'simple_with_custom_options'; + $qty = 1; + $productCustomOptions = Bootstrap::getObjectManager() + ->get(\Magento\Catalog\Api\ProductCustomOptionRepositoryInterface::class) + ->getList($sku); + $customizableOptions = ''; + foreach ($productCustomOptions as $option) { + $value = $option->getValues() ? + '[' . key($option->getValues()) . ']' : + 'Test'; + $customizableOptions .= ' { + id: ' . $option->getId() . ' + value: "' . $value . '" + }'; + } + + $maskedQuoteId = $this->getMaskedQuoteId(); + $query = <<<QUERY +mutation { + addSimpleProductsToCart( + input: { + cart_id: "{$maskedQuoteId}" + cartItems: { + data: { + qty: {$qty} + sku: "{$sku}" + } + customizable_options: [ + {$customizableOptions} + ] + } + } + ) +{ + cart { + items { + product { + sku + } + ... on SimpleCartItem { + customizable_options { + id + is_required + sort_order + } + } + } + } + } +} +QUERY; + $response = $this->graphQlQuery($query); + self::assertArrayHasKey('cart', $response['addSimpleProductsToCart']); + + self::assertEquals($sku, $response['addSimpleProductsToCart']['cart']['items'][0]['product']['sku']); + self::assertEquals( + 1, + $response['addSimpleProductsToCart']['cart']['items'][0]['customizable_options'][0]['is_required'] + ); + } + /** * @magentoApiDataFixture Magento/Catalog/_files/products.php * @magentoApiDataFixture Magento/Checkout/_files/active_quote.php From 76351fab1a294a1dde54cca4ae274cb5b1cdd0af Mon Sep 17 00:00:00 2001 From: Ievgenii Gryshkun <i.gryshkun@gmail.com> Date: Wed, 3 Apr 2019 09:10:08 +0300 Subject: [PATCH 319/773] Cannot return null for non-nullable field SelectedCustomizableOptionValue.sort_order and Call to a member function getPriceType() on null --- .../Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php b/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php index cf65393b08997..bd81a15307e31 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php @@ -170,7 +170,7 @@ private function createBuyRequest(float $quantity, array $customOptions): DataOb */ private function convertCustomOptions(string $value) { - if (substr($value, 0, 1) === "[" || + if (substr($value, 0, 1) === "[" && substr($value, strlen($value) - 1, 1) === "]") { return explode(',', substr($value, 1, -1)); } From 4810d06d26798857c6628b724b24e27acd244290 Mon Sep 17 00:00:00 2001 From: Ievgenii Gryshkun <i.gryshkun@gmail.com> Date: Sat, 27 Apr 2019 12:26:29 +0300 Subject: [PATCH 320/773] Cannot return null for non-nullable field SelectedCustomizableOptionValue.sort_order and Call to a member function getPriceType() on null --- app/code/Magento/QuoteGraphQl/etc/schema.graphqls | 1 - .../Magento/GraphQl/CatalogInventory/AddProductToCartTest.php | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls index e2d29e93db574..0b6b392c2ed9b 100644 --- a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls +++ b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls @@ -325,7 +325,6 @@ type SelectedCustomizableOptionValue { label: String! value: String! price: CartItemSelectedOptionValuePrice! - sort_order: Int! } type CartItemSelectedOptionValuePrice { diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php index c2fbfc1418dbf..708e034a4626b 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php @@ -52,7 +52,7 @@ public function testAddProductIfQuantityIsNotAvailable() * @expectedException \Exception * @expectedExceptionMessage The product's required option(s) weren't entered. Make sure the options are entered and try again. */ - public function testAddProductWithoutRequiredCustomOPtions() + public function testAddProductWithoutRequiredCustomOptions() { $sku = 'simple_with_custom_options'; $qty = 1; @@ -66,7 +66,7 @@ public function testAddProductWithoutRequiredCustomOPtions() * @magentoApiDataFixture Magento/Catalog/_files/product_simple_with_custom_options.php * @magentoApiDataFixture Magento/Checkout/_files/active_quote.php */ - public function testAddProductWithRequiredCustomOPtions() + public function testAddProductWithRequiredCustomOptions() { $sku = 'simple_with_custom_options'; $qty = 1; From 542ca058031850d8b00a1f9e104fd539254f4430 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Tue, 30 Apr 2019 11:33:53 -0500 Subject: [PATCH 321/773] GraphQL-474: Cannot return null for non-nullable field SelectedCustomizableOptionValue.sort_order and Call to a member function getPriceType() on null --- .../Model/Cart/AddSimpleProductToCart.php | 52 ++++++------- .../Magento/QuoteGraphQl/etc/schema.graphqls | 7 +- ...mpleProductWithCustomOptionsToCartTest.php | 75 +++++++------------ ...tualProductWithCustomOptionsToCartTest.php | 75 +++++++------------ 4 files changed, 84 insertions(+), 125 deletions(-) diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php b/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php index bd81a15307e31..251f17619c2a8 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php @@ -13,21 +13,13 @@ use Magento\Framework\Exception\NoSuchEntityException; use Magento\Framework\GraphQl\Exception\GraphQlInputException; use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException; -use Magento\Framework\Stdlib\ArrayManager; use Magento\Quote\Model\Quote; /** * Add simple product to cart - * - * TODO: should be replaced for different types resolver */ class AddSimpleProductToCart { - /** - * @var ArrayManager - */ - private $arrayManager; - /** * @var DataObjectFactory */ @@ -39,16 +31,13 @@ class AddSimpleProductToCart private $productRepository; /** - * @param ArrayManager $arrayManager * @param DataObjectFactory $dataObjectFactory * @param ProductRepositoryInterface $productRepository */ public function __construct( - ArrayManager $arrayManager, DataObjectFactory $dataObjectFactory, ProductRepositoryInterface $productRepository ) { - $this->arrayManager = $arrayManager; $this->dataObjectFactory = $dataObjectFactory; $this->productRepository = $productRepository; } @@ -67,11 +56,6 @@ public function execute(Quote $cart, array $cartItemData): void { $sku = $this->extractSku($cartItemData); $quantity = $this->extractQuantity($cartItemData); - if ($quantity <= 0) { - throw new GraphQlInputException( - __('Please enter a number greater than 0 in this field.') - ); - } $customizableOptions = $this->extractCustomizableOptions($cartItemData); try { @@ -105,11 +89,10 @@ public function execute(Quote $cart, array $cartItemData): void */ private function extractSku(array $cartItemData): string { - $sku = $this->arrayManager->get('data/sku', $cartItemData); - if (!isset($sku)) { - throw new GraphQlInputException(__('Missing key "sku" in cart item data')); + if (!isset($cartItemData['data']['sku']) || empty($cartItemData['data']['sku'])) { + throw new GraphQlInputException(__('Missed "sku" in cart item data')); } - return (string)$sku; + return (string)$cartItemData['data']['sku']; } /** @@ -121,11 +104,17 @@ private function extractSku(array $cartItemData): string */ private function extractQuantity(array $cartItemData): float { - $quantity = $this->arrayManager->get('data/quantity', $cartItemData); - if (!isset($quantity)) { - throw new GraphQlInputException(__('Missing key "quantity" in cart item data')); + if (!isset($cartItemData['data']['quantity'])) { + throw new GraphQlInputException(__('Missed "qty" in cart item data')); } - return (float)$quantity; + $quantity = (float)$cartItemData['data']['quantity']; + + if ($quantity <= 0) { + throw new GraphQlInputException( + __('Please enter a number greater than 0 in this field.') + ); + } + return $quantity; } /** @@ -136,13 +125,17 @@ private function extractQuantity(array $cartItemData): float */ private function extractCustomizableOptions(array $cartItemData): array { - $customizableOptions = $this->arrayManager->get('customizable_options', $cartItemData, []); + if (!isset($cartItemData['customizable_options']) || empty($cartItemData['customizable_options'])) { + return []; + } $customizableOptionsData = []; - foreach ($customizableOptions as $customizableOption) { - $customizableOptionsData[$customizableOption['id']] = $this->convertCustomOptions( - $customizableOption['value'] - ); + foreach ($cartItemData['customizable_options'] as $customizableOption) { + if (isset($customizableOption['value_string'])) { + $customizableOptionsData[$customizableOption['id']] = $this->convertCustomOptions( + $customizableOption['value_string'] + ); + } } return $customizableOptionsData; } @@ -170,6 +163,7 @@ private function createBuyRequest(float $quantity, array $customOptions): DataOb */ private function convertCustomOptions(string $value) { + $value = trim($value); if (substr($value, 0, 1) === "[" && substr($value, strlen($value) - 1, 1) === "]") { return explode(',', substr($value, 1, -1)); diff --git a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls index 0b6b392c2ed9b..c2b92034c3294 100644 --- a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls +++ b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls @@ -52,7 +52,7 @@ input CartItemInput { input CustomizableOptionInput { id: Int! - value: String! + value_string: String! } input ApplyCouponToCartInput { @@ -314,8 +314,7 @@ interface CartItemInterface @typeResolver(class: "Magento\\QuoteGraphQl\\Model\\ type SelectedCustomizableOption { id: Int! label: String! - type: String! - is_required: Int! + is_required: Boolean! values: [SelectedCustomizableOptionValue!]! sort_order: Int! } @@ -323,7 +322,7 @@ type SelectedCustomizableOption { type SelectedCustomizableOptionValue { id: Int! label: String! - value: String! + value: String price: CartItemSelectedOptionValuePrice! } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductWithCustomOptionsToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductWithCustomOptionsToCartTest.php index 63546298304b0..d64c51354129d 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductWithCustomOptionsToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductWithCustomOptionsToCartTest.php @@ -50,41 +50,11 @@ public function testAddSimpleProductWithOptions() $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); $customOptionsValues = $this->getCustomOptionsValuesForQuery($sku); - /* Generate customizable options fragment for GraphQl request */ - $queryCustomizableOptions = preg_replace('/"([^"]+)"\s*:\s*/', '$1:', json_encode($customOptionsValues)); + $queryCustomizableOptionValues = preg_replace('/"([^"]+)"\s*:\s*/', '$1:', json_encode($customOptionsValues)); - $query = <<<QUERY -mutation { - addSimpleProductsToCart( - input: { - cart_id: "{$maskedQuoteId}", - cartItems: [ - { - data: { - quantity: $quantity - sku: "$sku" - }, - customizable_options: $queryCustomizableOptions - } - ] - } - ) { - cart { - items { - ... on SimpleCartItem { - customizable_options { - label - values { - value - } - } - } - } - } - } -} -QUERY; + $customizableOptions = "customizable_options: {$queryCustomizableOptionValues}"; + $query = $this->getQuery($maskedQuoteId, $sku, $quantity, $customizableOptions); $response = $this->graphQlMutation($query); @@ -95,7 +65,7 @@ public function testAddSimpleProductWithOptions() $assignedOptionsCount = count($customOptionsValues); for ($counter = 0; $counter < $assignedOptionsCount; $counter++) { self::assertEquals( - $customOptionsValues[$counter]['value'], + $customOptionsValues[$counter]['value_string'], $customizableOptionsOutput[$counter]['values'][0]['value'] ); } @@ -107,13 +77,31 @@ public function testAddSimpleProductWithOptions() * @magentoApiDataFixture Magento/Catalog/_files/product_simple_with_options.php * @magentoApiDataFixture Magento/Checkout/_files/active_quote.php */ - public function testAddSimpleProductWithNoRequiredOptionsSet() + public function testAddSimpleProductWithMissedRequiredOptionsSet() { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); $sku = 'simple'; $quantity = 1; - $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); + $customizableOptions = ''; - $query = <<<QUERY + $query = $this->getQuery($maskedQuoteId, $sku, $quantity, $customizableOptions); + + self::expectExceptionMessage( + 'The product\'s required option(s) weren\'t entered. Make sure the options are entered and try again.' + ); + $this->graphQlMutation($query); + } + + /** + * @param string $maskedQuoteId + * @param string $sku + * @param float $quantity + * @param string $customizableOptions + * @return string + */ + private function getQuery(string $maskedQuoteId, string $sku, float $quantity, string $customizableOptions): string + { + return <<<QUERY mutation { addSimpleProductsToCart( input: { @@ -124,6 +112,7 @@ public function testAddSimpleProductWithNoRequiredOptionsSet() quantity: $quantity sku: "$sku" } + {$customizableOptions} } ] } @@ -134,7 +123,7 @@ public function testAddSimpleProductWithNoRequiredOptionsSet() customizable_options { label values { - value + value } } } @@ -143,12 +132,6 @@ public function testAddSimpleProductWithNoRequiredOptionsSet() } } QUERY; - - self::expectExceptionMessage( - 'The product\'s required option(s) weren\'t entered. Make sure the options are entered and try again.' - ); - - $this->graphQlMutation($query); } /** @@ -168,13 +151,13 @@ private function getCustomOptionsValuesForQuery(string $sku): array if ($optionType == 'field' || $optionType == 'area') { $customOptionsValues[] = [ 'id' => (int) $customOption->getOptionId(), - 'value' => 'test' + 'value_string' => 'test' ]; } elseif ($optionType == 'drop_down') { $optionSelectValues = $customOption->getValues(); $customOptionsValues[] = [ 'id' => (int) $customOption->getOptionId(), - 'value' => reset($optionSelectValues)->getOptionTypeId() + 'value_string' => reset($optionSelectValues)->getOptionTypeId() ]; } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddVirtualProductWithCustomOptionsToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddVirtualProductWithCustomOptionsToCartTest.php index 94ac11ad8e0b1..55542919cc098 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddVirtualProductWithCustomOptionsToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddVirtualProductWithCustomOptionsToCartTest.php @@ -50,41 +50,11 @@ public function testAddVirtualProductWithOptions() $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); $customOptionsValues = $this->getCustomOptionsValuesForQuery($sku); - /* Generate customizable options fragment for GraphQl request */ - $queryCustomizableOptions = preg_replace('/"([^"]+)"\s*:\s*/', '$1:', json_encode($customOptionsValues)); + $queryCustomizableOptionValues = preg_replace('/"([^"]+)"\s*:\s*/', '$1:', json_encode($customOptionsValues)); - $query = <<<QUERY -mutation { - addVirtualProductsToCart( - input: { - cart_id: "{$maskedQuoteId}", - cartItems: [ - { - data: { - quantity: $quantity - sku: "$sku" - }, - customizable_options: $queryCustomizableOptions - } - ] - } - ) { - cart { - items { - ... on VirtualCartItem { - customizable_options { - label - values { - value - } - } - } - } - } - } -} -QUERY; + $customizableOptions = "customizable_options: {$queryCustomizableOptionValues}"; + $query = $this->getQuery($maskedQuoteId, $sku, $quantity, $customizableOptions); $response = $this->graphQlMutation($query); @@ -95,7 +65,7 @@ public function testAddVirtualProductWithOptions() $assignedOptionsCount = count($customOptionsValues); for ($counter = 0; $counter < $assignedOptionsCount; $counter++) { self::assertEquals( - $customOptionsValues[$counter]['value'], + $customOptionsValues[$counter]['value_string'], $customizableOptionsOutput[$counter]['values'][0]['value'] ); } @@ -107,13 +77,31 @@ public function testAddVirtualProductWithOptions() * @magentoApiDataFixture Magento/Catalog/_files/product_virtual_with_options.php * @magentoApiDataFixture Magento/Checkout/_files/active_quote.php */ - public function testAddVirtualProductWithNoRequiredOptionsSet() + public function testAddSimpleProductWithMissedRequiredOptionsSet() { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); $sku = 'virtual'; $quantity = 1; - $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); + $customizableOptions = ''; - $query = <<<QUERY + $query = $this->getQuery($maskedQuoteId, $sku, $quantity, $customizableOptions); + + self::expectExceptionMessage( + 'The product\'s required option(s) weren\'t entered. Make sure the options are entered and try again.' + ); + $this->graphQlMutation($query); + } + + /** + * @param string $maskedQuoteId + * @param string $sku + * @param float $quantity + * @param string $customizableOptions + * @return string + */ + private function getQuery(string $maskedQuoteId, string $sku, float $quantity, string $customizableOptions): string + { + return <<<QUERY mutation { addVirtualProductsToCart( input: { @@ -124,6 +112,7 @@ public function testAddVirtualProductWithNoRequiredOptionsSet() quantity: $quantity sku: "$sku" } + {$customizableOptions} } ] } @@ -134,7 +123,7 @@ public function testAddVirtualProductWithNoRequiredOptionsSet() customizable_options { label values { - value + value } } } @@ -143,12 +132,6 @@ public function testAddVirtualProductWithNoRequiredOptionsSet() } } QUERY; - - self::expectExceptionMessage( - 'The product\'s required option(s) weren\'t entered. Make sure the options are entered and try again.' - ); - - $this->graphQlMutation($query); } /** @@ -168,13 +151,13 @@ private function getCustomOptionsValuesForQuery(string $sku): array if ($optionType == 'field' || $optionType == 'area') { $customOptionsValues[] = [ 'id' => (int) $customOption->getOptionId(), - 'value' => 'test' + 'value_string' => 'test' ]; } elseif ($optionType == 'drop_down') { $optionSelectValues = $customOption->getValues(); $customOptionsValues[] = [ 'id' => (int) $customOption->getOptionId(), - 'value' => reset($optionSelectValues)->getOptionTypeId() + 'value_string' => reset($optionSelectValues)->getOptionTypeId() ]; } } From 7598b78d587dd18b496ad87d7f62e9a21b5d15d7 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Tue, 30 Apr 2019 11:53:24 -0500 Subject: [PATCH 322/773] GraphQL-474: Cannot return null for non-nullable field SelectedCustomizableOptionValue.sort_order and Call to a member function getPriceType() on null --- .../CatalogInventory/AddProductToCartTest.php | 83 ------------------- 1 file changed, 83 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php index 708e034a4626b..6f27693eeb4a7 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php @@ -46,89 +46,6 @@ public function testAddProductIfQuantityIsNotAvailable() $this->graphQlMutation($query); } - /** - * @magentoApiDataFixture Magento/Catalog/_files/product_simple_with_custom_options.php - * @magentoApiDataFixture Magento/Checkout/_files/active_quote.php - * @expectedException \Exception - * @expectedExceptionMessage The product's required option(s) weren't entered. Make sure the options are entered and try again. - */ - public function testAddProductWithoutRequiredCustomOptions() - { - $sku = 'simple_with_custom_options'; - $qty = 1; - - $maskedQuoteId = $this->getMaskedQuoteId(); - $query = $this->getAddSimpleProductQuery($maskedQuoteId, $sku, $qty); - $this->graphQlQuery($query); - } - - /** - * @magentoApiDataFixture Magento/Catalog/_files/product_simple_with_custom_options.php - * @magentoApiDataFixture Magento/Checkout/_files/active_quote.php - */ - public function testAddProductWithRequiredCustomOptions() - { - $sku = 'simple_with_custom_options'; - $qty = 1; - $productCustomOptions = Bootstrap::getObjectManager() - ->get(\Magento\Catalog\Api\ProductCustomOptionRepositoryInterface::class) - ->getList($sku); - $customizableOptions = ''; - foreach ($productCustomOptions as $option) { - $value = $option->getValues() ? - '[' . key($option->getValues()) . ']' : - 'Test'; - $customizableOptions .= ' { - id: ' . $option->getId() . ' - value: "' . $value . '" - }'; - } - - $maskedQuoteId = $this->getMaskedQuoteId(); - $query = <<<QUERY -mutation { - addSimpleProductsToCart( - input: { - cart_id: "{$maskedQuoteId}" - cartItems: { - data: { - qty: {$qty} - sku: "{$sku}" - } - customizable_options: [ - {$customizableOptions} - ] - } - } - ) -{ - cart { - items { - product { - sku - } - ... on SimpleCartItem { - customizable_options { - id - is_required - sort_order - } - } - } - } - } -} -QUERY; - $response = $this->graphQlQuery($query); - self::assertArrayHasKey('cart', $response['addSimpleProductsToCart']); - - self::assertEquals($sku, $response['addSimpleProductsToCart']['cart']['items'][0]['product']['sku']); - self::assertEquals( - 1, - $response['addSimpleProductsToCart']['cart']['items'][0]['customizable_options'][0]['is_required'] - ); - } - /** * @magentoApiDataFixture Magento/Catalog/_files/products.php * @magentoApiDataFixture Magento/Checkout/_files/active_quote.php From aae05a9235ccd511f011143bb052b1ab52068480 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Tue, 30 Apr 2019 13:41:52 -0500 Subject: [PATCH 323/773] GraphQL-630: Schema inconsistency of "AvailableShippingMethod" declaration --- .../AvailableShippingMethods.php | 46 ++++++++++++++++++- .../SelectedShippingMethod.php | 20 +++++++- .../Magento/QuoteGraphQl/etc/schema.graphqls | 8 ++-- .../GetAvailableShippingMethodsTest.php | 40 ++++++++++++---- .../Guest/GetAvailableShippingMethodsTest.php | 40 ++++++++++++---- 5 files changed, 131 insertions(+), 23 deletions(-) diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/AvailableShippingMethods.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/AvailableShippingMethods.php index a9e0ba59d15d9..958934ed18032 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/AvailableShippingMethods.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/AvailableShippingMethods.php @@ -7,13 +7,16 @@ namespace Magento\QuoteGraphQl\Model\Resolver\ShippingAddress; +use Magento\Directory\Model\Currency; use Magento\Framework\Api\ExtensibleDataObjectConverter; use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\Exception\NoSuchEntityException; use Magento\Framework\GraphQl\Config\Element\Field; use Magento\Framework\GraphQl\Query\ResolverInterface; use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; use Magento\Quote\Api\Data\ShippingMethodInterface; use Magento\Quote\Model\Cart\ShippingMethodConverter; +use Magento\Store\Model\StoreManagerInterface; /** * @inheritdoc @@ -30,16 +33,24 @@ class AvailableShippingMethods implements ResolverInterface */ private $shippingMethodConverter; + /** + * @var StoreManagerInterface + */ + private $storeManager; + /** * @param ExtensibleDataObjectConverter $dataObjectConverter * @param ShippingMethodConverter $shippingMethodConverter + * @param StoreManagerInterface $storeManager */ public function __construct( ExtensibleDataObjectConverter $dataObjectConverter, - ShippingMethodConverter $shippingMethodConverter + ShippingMethodConverter $shippingMethodConverter, + StoreManagerInterface $storeManager ) { $this->dataObjectConverter = $dataObjectConverter; $this->shippingMethodConverter = $shippingMethodConverter; + $this->storeManager = $storeManager; } /** @@ -65,13 +76,44 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value $shippingRates = $address->getGroupedAllShippingRates(); foreach ($shippingRates as $carrierRates) { foreach ($carrierRates as $rate) { - $methods[] = $this->dataObjectConverter->toFlatArray( + $methodData = $this->dataObjectConverter->toFlatArray( $this->shippingMethodConverter->modelToDataObject($rate, $cart->getQuoteCurrencyCode()), [], ShippingMethodInterface::class ); + $methods[] = $this->processMoneyTypeData($methodData, $cart->getQuoteCurrencyCode()); } } return $methods; } + + /** + * Process money type data + * + * @param array $data + * @param string $quoteCurrencyCode + * @return array + * @throws NoSuchEntityException + */ + private function processMoneyTypeData(array $data, string $quoteCurrencyCode): array + { + if (isset($data['amount'])) { + $data['amount'] = ['value' => $data['amount'], 'currency' => $quoteCurrencyCode]; + } + + if (isset($data['base_amount'])) { + /** @var Currency $currency */ + $currency = $this->storeManager->getStore()->getBaseCurrency(); + $data['base_amount'] = ['value' => $data['base_amount'], 'currency' => $currency->getCode()]; + } + + if (isset($data['price_excl_tax'])) { + $data['price_excl_tax'] = ['value' => $data['price_excl_tax'], 'currency' => $quoteCurrencyCode]; + } + + if (isset($data['price_incl_tax'])) { + $data['price_incl_tax'] = ['value' => $data['price_incl_tax'], 'currency' => $quoteCurrencyCode]; + } + return $data; + } } diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/SelectedShippingMethod.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/SelectedShippingMethod.php index cd8f20c3f164f..e396d2b46494a 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/SelectedShippingMethod.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/SelectedShippingMethod.php @@ -7,18 +7,34 @@ namespace Magento\QuoteGraphQl\Model\Resolver\ShippingAddress; +use Magento\Directory\Model\Currency; use Magento\Framework\Exception\LocalizedException; use Magento\Framework\GraphQl\Config\Element\Field; use Magento\Framework\GraphQl\Query\ResolverInterface; use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; use Magento\Quote\Model\Quote\Address; use Magento\Quote\Model\Quote\Address\Rate; +use Magento\Store\Model\StoreManagerInterface; /** * @inheritdoc */ class SelectedShippingMethod implements ResolverInterface { + /** + * @var StoreManagerInterface + */ + private $storeManager; + + /** + * @param StoreManagerInterface $storeManager + */ + public function __construct( + StoreManagerInterface $storeManager + ) { + $this->storeManager = $storeManager; + } + /** * @inheritdoc */ @@ -35,6 +51,8 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value list($carrierCode, $methodCode) = explode('_', $address->getShippingMethod(), 2); /** @var Rate $rate */ $rate = current($rates); + /** @var Currency $currency */ + $currency = $this->storeManager->getStore()->getBaseCurrency(); $data = [ 'carrier_code' => $carrierCode, @@ -47,7 +65,7 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value ], 'base_amount' => [ 'value' => $address->getBaseShippingAmount(), - 'currency' => $address->getQuote()->getBaseCurrencyCode(), + 'currency' => $currency, ], ]; } else { diff --git a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls index c2b92034c3294..6ec4d5df66299 100644 --- a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls +++ b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls @@ -243,10 +243,10 @@ type AvailableShippingMethod { method_code: String @doc(description: "Could be null if method is not available") method_title: String @doc(description: "Could be null if method is not available") error_message: String - amount: Float! - base_amount: Float @doc(description: "Could be null if method is not available") - price_excl_tax: Float! - price_incl_tax: Float! + amount: Money! + base_amount: Money @doc(description: "Could be null if method is not available") + price_excl_tax: Money! + price_incl_tax: Money! available: Boolean! } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetAvailableShippingMethodsTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetAvailableShippingMethodsTest.php index 2b647f61c4c63..b01921ae67ed7 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetAvailableShippingMethodsTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetAvailableShippingMethodsTest.php @@ -58,15 +58,27 @@ public function testGetAvailableShippingMethods() self::assertCount(1, $response['cart']['shipping_addresses'][0]['available_shipping_methods']); $expectedAddressData = [ - 'amount' => 10, - 'base_amount' => 10, + 'amount' => [ + 'value' => 10, + 'currency' => 'USD', + ], + 'base_amount' => [ + 'value' => 10, + 'currency' => 'USD', + ], 'carrier_code' => 'flatrate', 'carrier_title' => 'Flat Rate', 'error_message' => '', 'method_code' => 'flatrate', 'method_title' => 'Fixed', - 'price_incl_tax' => 10, - 'price_excl_tax' => 10, + 'price_incl_tax' => [ + 'value' => 10, + 'currency' => 'USD', + ], + 'price_excl_tax' => [ + 'value' => 10, + 'currency' => 'USD', + ], ]; self::assertEquals( $expectedAddressData, @@ -158,15 +170,27 @@ private function getQuery(string $maskedQuoteId): string cart (cart_id: "{$maskedQuoteId}") { shipping_addresses { available_shipping_methods { - amount - base_amount + amount { + value + currency + } + base_amount { + value + currency + } carrier_code carrier_title error_message method_code method_title - price_excl_tax - price_incl_tax + price_excl_tax { + value + currency + } + price_incl_tax { + value + currency + } } } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetAvailableShippingMethodsTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetAvailableShippingMethodsTest.php index a8113657eff6e..8703a690c62e3 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetAvailableShippingMethodsTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetAvailableShippingMethodsTest.php @@ -50,15 +50,27 @@ public function testGetAvailableShippingMethods() self::assertCount(1, $response['cart']['shipping_addresses'][0]['available_shipping_methods']); $expectedAddressData = [ - 'amount' => 10, - 'base_amount' => 10, + 'amount' => [ + 'value' => 10, + 'currency' => 'USD', + ], + 'base_amount' => [ + 'value' => 10, + 'currency' => 'USD', + ], 'carrier_code' => 'flatrate', 'carrier_title' => 'Flat Rate', 'error_message' => '', 'method_code' => 'flatrate', 'method_title' => 'Fixed', - 'price_incl_tax' => 10, - 'price_excl_tax' => 10, + 'price_incl_tax' => [ + 'value' => 10, + 'currency' => 'USD', + ], + 'price_excl_tax' => [ + 'value' => 10, + 'currency' => 'USD', + ], ]; self::assertEquals( $expectedAddressData, @@ -126,15 +138,27 @@ private function getQuery(string $maskedQuoteId): string cart (cart_id: "{$maskedQuoteId}") { shipping_addresses { available_shipping_methods { - amount - base_amount + amount { + value + currency + } + base_amount { + value + currency + } carrier_code carrier_title error_message method_code method_title - price_excl_tax - price_incl_tax + price_excl_tax { + value + currency + } + price_incl_tax { + value + currency + } } } } From b3a81684f278342a231673777b2d27b3dbcf44fd Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Tue, 30 Apr 2019 13:49:39 -0500 Subject: [PATCH 324/773] GraphQL-474: Cannot return null for non-nullable field SelectedCustomizableOptionValue.sort_order and Call to a member function getPriceType() on null --- .../QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php b/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php index 251f17619c2a8..b491b10730c10 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php @@ -132,7 +132,7 @@ private function extractCustomizableOptions(array $cartItemData): array $customizableOptionsData = []; foreach ($cartItemData['customizable_options'] as $customizableOption) { if (isset($customizableOption['value_string'])) { - $customizableOptionsData[$customizableOption['id']] = $this->convertCustomOptions( + $customizableOptionsData[$customizableOption['id']] = $this->convertCustomOptionValue( $customizableOption['value_string'] ); } @@ -158,10 +158,12 @@ private function createBuyRequest(float $quantity, array $customOptions): DataOb } /** + * Convert custom options vakue + * * @param string $value * @return string|array */ - private function convertCustomOptions(string $value) + private function convertCustomOptionValue(string $value) { $value = trim($value); if (substr($value, 0, 1) === "[" && From a465fcc83cb72d565d6b0a406600fd4f087b0cc6 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Tue, 30 Apr 2019 13:57:41 -0500 Subject: [PATCH 325/773] GraphQL-641: Schema Inconsistency of "cartItems" declaration --- .../Model/Resolver/AddSimpleProductsToCart.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/AddSimpleProductsToCart.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/AddSimpleProductsToCart.php index 82ffd0970d672..cfae0e1267802 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/AddSimpleProductsToCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/AddSimpleProductsToCart.php @@ -52,12 +52,12 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value } $maskedCartId = $args['input']['cart_id']; - if (!isset($args['input']['cartItems']) || empty($args['input']['cartItems']) - || !is_array($args['input']['cartItems']) + if (!isset($args['input']['cart_items']) || empty($args['input']['cart_items']) + || !is_array($args['input']['cart_items']) ) { - throw new GraphQlInputException(__('Required parameter "cartItems" is missing')); + throw new GraphQlInputException(__('Required parameter "cart_items" is missing')); } - $cartItems = $args['input']['cartItems']; + $cartItems = $args['input']['cart_items']; $cart = $this->getCartForUser->execute($maskedCartId, $context->getUserId()); $this->addProductsToCart->execute($cart, $cartItems); From 0599a1454df9053bbca6feb16cafc564413c1e0c Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Tue, 30 Apr 2019 15:39:47 -0500 Subject: [PATCH 326/773] GraphQL-630: Schema inconsistency of "AvailableShippingMethod" declaration --- .../Resolver/ShippingAddress/SelectedShippingMethod.php | 2 +- .../GraphQl/Quote/Customer/CheckoutEndToEndTest.php | 7 +++++-- .../Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php | 7 +++++-- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/SelectedShippingMethod.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/SelectedShippingMethod.php index e396d2b46494a..bf6315086ae8b 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/SelectedShippingMethod.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/SelectedShippingMethod.php @@ -65,7 +65,7 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value ], 'base_amount' => [ 'value' => $address->getBaseShippingAmount(), - 'currency' => $currency, + 'currency' => $currency->getCode(), ], ]; } else { diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php index 92974f2491f75..eddc1f98d7a96 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php @@ -309,7 +309,9 @@ private function setShippingAddress(string $cartId): array available_shipping_methods { carrier_code method_code - amount + amount { + value + } } } } @@ -334,7 +336,8 @@ private function setShippingAddress(string $cartId): array self::assertNotEmpty($availableShippingMethod['method_code']); self::assertArrayHasKey('amount', $availableShippingMethod); - self::assertNotEmpty($availableShippingMethod['amount']); + self::assertArrayHasKey('value', $availableShippingMethod['amount']); + self::assertNotEmpty($availableShippingMethod['amount']['value']); return $availableShippingMethod; } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php index bddee2151f5cd..a95e4404a08ac 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php @@ -269,7 +269,9 @@ private function setShippingAddress(string $cartId): array available_shipping_methods { carrier_code method_code - amount + amount { + value + } } } } @@ -294,7 +296,8 @@ private function setShippingAddress(string $cartId): array self::assertNotEmpty($availableShippingMethod['method_code']); self::assertArrayHasKey('amount', $availableShippingMethod); - self::assertNotEmpty($availableShippingMethod['amount']); + self::assertArrayHasKey('value', $availableShippingMethod['amount']); + self::assertNotEmpty($availableShippingMethod['amount']['value']); return $availableShippingMethod; } From 82c8a1233577f4cb8ccb41ce105c5e6c3cee607d Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Tue, 30 Apr 2019 15:41:30 -0500 Subject: [PATCH 327/773] GraphQL-630: Schema inconsistency of "AvailableShippingMethod" declaration --- app/code/Magento/QuoteGraphQl/composer.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/QuoteGraphQl/composer.json b/app/code/Magento/QuoteGraphQl/composer.json index a3c07f7df2cee..6f4d3969d1018 100644 --- a/app/code/Magento/QuoteGraphQl/composer.json +++ b/app/code/Magento/QuoteGraphQl/composer.json @@ -11,7 +11,8 @@ "magento/module-store": "*", "magento/module-customer": "*", "magento/module-customer-graph-ql": "*", - "magento/module-sales": "*" + "magento/module-sales": "*", + "magento/module-directory": "*" }, "suggest": { "magento/module-graph-ql": "*", From e5fc30e10a4d10802aecabfa50f4ff9e142ecb82 Mon Sep 17 00:00:00 2001 From: Vitaliy Boyko <v.boyko@atwix.com> Date: Wed, 1 May 2019 10:29:41 +0300 Subject: [PATCH 328/773] graphQl-640: fixed input type declaration for PaymentMethodAdditionalDataInput and SelectedPaymentMethodAdditionalData --- app/code/Magento/QuoteGraphQl/etc/schema.graphqls | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls index 6ec4d5df66299..b09cf13bbde2b 100644 --- a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls +++ b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls @@ -134,8 +134,7 @@ input PaymentMethodInput { purchase_order_number: String @doc(description:"Purchase order number") } -input PaymentMethodAdditionalDataInput { -} +input PaymentMethodAdditionalDataInput input SetGuestEmailOnCartInput { cart_id: String! @@ -262,8 +261,7 @@ type SelectedPaymentMethod { purchase_order_number: String @doc(description: "The purchase order number.") } -type SelectedPaymentMethodAdditionalData { -} +type SelectedPaymentMethodAdditionalData type AppliedCoupon { code: String! From 69a440886a0e37252c6e9bcda6ca161a9ba74278 Mon Sep 17 00:00:00 2001 From: Alex Taranovsky <firster@atwix.com> Date: Wed, 1 May 2019 11:53:22 +0300 Subject: [PATCH 329/773] magento/graphql-ce#649: GetSpecifiedBillingAddressTest fix misspelling --- .../Quote/Customer/GetSpecifiedBillingAddressTest.php | 10 +++++----- .../Quote/Guest/GetSpecifiedBillingAddressTest.php | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSpecifiedBillingAddressTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSpecifiedBillingAddressTest.php index 1ff5ddbde54ec..b6dde46871cbb 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSpecifiedBillingAddressTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSpecifiedBillingAddressTest.php @@ -44,7 +44,7 @@ protected function setUp() * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_billing_address.php */ - public function testGeSpecifiedBillingAddress() + public function testGetSpecifiedBillingAddress() { $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $query = $this->getQuery($maskedQuoteId); @@ -83,7 +83,7 @@ public function testGeSpecifiedBillingAddress() * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php */ - public function testGeSpecifiedBillingAddressIfBillingAddressIsNotSet() + public function testGetSpecifiedBillingAddressIfBillingAddressIsNotSet() { $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $query = $this->getQuery($maskedQuoteId); @@ -121,7 +121,7 @@ public function testGeSpecifiedBillingAddressIfBillingAddressIsNotSet() * @expectedException \Exception * @expectedExceptionMessage Could not find a cart with ID "non_existent_masked_id" */ - public function testGeSpecifiedBillingAddressOfNonExistentCart() + public function testGetSpecifiedBillingAddressOfNonExistentCart() { $maskedQuoteId = 'non_existent_masked_id'; $query = $this->getQuery($maskedQuoteId); @@ -137,7 +137,7 @@ public function testGeSpecifiedBillingAddressOfNonExistentCart() * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_billing_address.php */ - public function testGeSpecifiedBillingAddressFromAnotherGuestCart() + public function testGetSpecifiedBillingAddressFromAnotherGuestCart() { $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); @@ -155,7 +155,7 @@ public function testGeSpecifiedBillingAddressFromAnotherGuestCart() * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_billing_address.php */ - public function testGeSpecifiedBillingAddressFromAnotherCustomerCart() + public function testGetSpecifiedBillingAddressFromAnotherCustomerCart() { $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedBillingAddressTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedBillingAddressTest.php index 48bff73226894..8ddf1641ede8a 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedBillingAddressTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedBillingAddressTest.php @@ -36,7 +36,7 @@ protected function setUp() * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_billing_address.php */ - public function testGeSpecifiedBillingAddress() + public function testGetSpecifiedBillingAddress() { $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $query = $this->getQuery($maskedQuoteId); @@ -73,7 +73,7 @@ public function testGeSpecifiedBillingAddress() * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php */ - public function testGeSpecifiedBillingAddressIfBillingAddressIsNotSet() + public function testGetSpecifiedBillingAddressIfBillingAddressIsNotSet() { $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $query = $this->getQuery($maskedQuoteId); From 9c195f15f7b15b2dddd4b55f7f14a2844cff74c4 Mon Sep 17 00:00:00 2001 From: Alex Taranovsky <firster@atwix.com> Date: Wed, 1 May 2019 13:10:45 +0300 Subject: [PATCH 330/773] magento/graphql-ce#602: [Test Coverage] Get Specified shipping address --- .../GetSpecifiedShippingAddressTest.php | 219 ++++++++++++++++++ .../Guest/GetSpecifiedShippingAddressTest.php | 170 ++++++++++++++ 2 files changed, 389 insertions(+) create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSpecifiedShippingAddressTest.php create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedShippingAddressTest.php diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSpecifiedShippingAddressTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSpecifiedShippingAddressTest.php new file mode 100644 index 0000000000000..766dd102b749c --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSpecifiedShippingAddressTest.php @@ -0,0 +1,219 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQl\Quote\Customer; + +use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; +use Magento\Integration\Api\CustomerTokenServiceInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\TestCase\GraphQlAbstract; + +/** + * Test for get specified shipping address + */ +class GetSpecifiedShippingAddressTest extends GraphQlAbstract +{ + /** + * @var CustomerTokenServiceInterface + */ + private $customerTokenService; + + /** + * @var GetMaskedQuoteIdByReservedOrderId + */ + private $getMaskedQuoteIdByReservedOrderId; + + /** + * @inheritdoc + */ + protected function setUp() + { + $objectManager = Bootstrap::getObjectManager(); + $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); + $this->customerTokenService = $objectManager->get(CustomerTokenServiceInterface::class); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + */ + public function testGetSpecifiedShippingAddress() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId); + + $response = $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + self::assertArrayHasKey('cart', $response); + self::assertArrayHasKey('shipping_addresses', $response['cart']); + + $expectedShippingAddressData = [ + 'firstname' => 'John', + 'lastname' => 'Smith', + 'company' => 'CompanyName', + 'street' => [ + 'Green str, 67' + ], + 'city' => 'CityM', + 'region' => [ + 'code' => 'AL', + 'label' => 'Alabama', + ], + 'postcode' => '75477', + 'country' => [ + 'code' => 'US', + 'label' => 'US', + ], + 'telephone' => '3468676', + '__typename' => 'ShippingCartAddress', + 'customer_notes' => null, + ]; + self::assertEquals($expectedShippingAddressData, current($response['cart']['shipping_addresses'])); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + */ + public function testGetSpecifiedShippingAddressIfShippingAddressIsNotSet() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId); + + $response = $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + self::assertArrayHasKey('cart', $response); + self::assertArrayHasKey('shipping_addresses', $response['cart']); + + $expectedShippingAddressData = [ + 'firstname' => null, + 'lastname' => null, + 'company' => null, + 'street' => [ + '' + ], + 'city' => null, + 'region' => [ + 'code' => null, + 'label' => null, + ], + 'postcode' => null, + 'country' => [ + 'code' => null, + 'label' => null, + ], + 'telephone' => null, + '__typename' => 'ShippingCartAddress', + 'customer_notes' => null, + ]; + self::assertEquals($expectedShippingAddressData, current($response['cart']['shipping_addresses'])); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @expectedException \Exception + * @expectedExceptionMessage Could not find a cart with ID "non_existent_masked_id" + */ + public function testGetSpecifiedShippingAddressOfNonExistentCart() + { + $maskedQuoteId = 'non_existent_masked_id'; + $query = $this->getQuery($maskedQuoteId); + + $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + } + + /** + * _security + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + */ + public function testGetSpecifiedShippingAddressFromAnotherGuestCart() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + + $this->expectExceptionMessage( + "The current user cannot perform operations on cart \"$maskedQuoteId\"" + ); + $this->graphQlQuery($this->getQuery($maskedQuoteId), [], '', $this->getHeaderMap()); + } + + /** + * _security + * @magentoApiDataFixture Magento/Customer/_files/three_customers.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + */ + public function testGetSpecifiedShippingAddressFromAnotherCustomerCart() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + + $this->expectExceptionMessage( + "The current user cannot perform operations on cart \"$maskedQuoteId\"" + ); + $this->graphQlQuery( + $this->getQuery($maskedQuoteId), + [], + '', + $this->getHeaderMap('customer2@search.example.com') + ); + } + + /** + * @param string $maskedQuoteId + * @return string + */ + private function getQuery(string $maskedQuoteId): string + { + return <<<QUERY +{ + cart(cart_id: "$maskedQuoteId") { + shipping_addresses { + firstname + lastname + company + street + city + region + { + code + label + } + postcode + country + { + code + label + } + telephone + __typename + customer_notes + } + } +} +QUERY; + } + + /** + * @param string $username + * @param string $password + * @return array + */ + private function getHeaderMap(string $username = 'customer@example.com', string $password = 'password'): array + { + $customerToken = $this->customerTokenService->createCustomerAccessToken($username, $password); + $headerMap = ['Authorization' => 'Bearer ' . $customerToken]; + return $headerMap; + } +} diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedShippingAddressTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedShippingAddressTest.php new file mode 100644 index 0000000000000..3b96a873bdb81 --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedShippingAddressTest.php @@ -0,0 +1,170 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQl\Quote\Guest; + +use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\TestCase\GraphQlAbstract; + +/** + * Test for get specified shipping address + */ +class GetSpecifiedShippingAddressTest extends GraphQlAbstract +{ + /** + * @var GetMaskedQuoteIdByReservedOrderId + */ + private $getMaskedQuoteIdByReservedOrderId; + + /** + * @inheritdoc + */ + protected function setUp() + { + $objectManager = Bootstrap::getObjectManager(); + $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); + } + + /** + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + */ + public function testGetSpecifiedShippingAddress() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId); + + $response = $this->graphQlQuery($query); + self::assertArrayHasKey('cart', $response); + self::assertArrayHasKey('shipping_addresses', $response['cart']); + + $expectedShippingAddressData = [ + 'firstname' => 'John', + 'lastname' => 'Smith', + 'company' => 'CompanyName', + 'street' => [ + 'Green str, 67' + ], + 'city' => 'CityM', + 'region' => [ + 'code' => 'AL', + 'label' => 'Alabama', + ], + 'postcode' => '75477', + 'country' => [ + 'code' => 'US', + 'label' => 'US', + ], + 'telephone' => '3468676', + '__typename' => 'ShippingCartAddress', + ]; + self::assertEquals($expectedShippingAddressData, current($response['cart']['shipping_addresses'])); + } + + /** + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + */ + public function testGetSpecifiedShippingAddressIfShippingAddressIsNotSet() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId); + + $response = $this->graphQlQuery($query); + self::assertArrayHasKey('cart', $response); + self::assertArrayHasKey('shipping_addresses', $response['cart']); + + $expectedShippingAddressData = [ + 'firstname' => null, + 'lastname' => null, + 'company' => null, + 'street' => [ + '' + ], + 'city' => null, + 'region' => [ + 'code' => null, + 'label' => null, + ], + 'postcode' => null, + 'country' => [ + 'code' => null, + 'label' => null, + ], + 'telephone' => null, + '__typename' => 'ShippingCartAddress', + ]; + self::assertEquals($expectedShippingAddressData, current($response['cart']['shipping_addresses'])); + } + + /** + * @expectedException \Exception + * @expectedExceptionMessage Could not find a cart with ID "non_existent_masked_id" + */ + public function testGetShippingAddressOfNonExistentCart() + { + $maskedQuoteId = 'non_existent_masked_id'; + $query = $this->getQuery($maskedQuoteId); + $this->graphQlQuery($query); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + */ + public function testGetShippingAddressFromAnotherCustomerCart() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId); + + $this->expectExceptionMessage( + "The current user cannot perform operations on cart \"$maskedQuoteId\"" + ); + $this->graphQlQuery($query); + } + + /** + * @param string $maskedQuoteId + * @return string + */ + private function getQuery(string $maskedQuoteId): string + { + return <<<QUERY +{ + cart(cart_id: "$maskedQuoteId") { + shipping_addresses { + firstname + lastname + company + street + city + region + { + code + label + } + postcode + country + { + code + label + } + telephone + __typename + } + } +} +QUERY; + } +} From 2080040ca3afa5b67bed267dd878c595e95d4715 Mon Sep 17 00:00:00 2001 From: Volodymyr Vygovskyi <v.vygovskyi@atwix.com> Date: Wed, 1 May 2019 16:01:53 +0300 Subject: [PATCH 331/773] Added Test coverage for "Get Selected payment method" --- .../Customer/GetSelectedPaymentMethodTest.php | 143 ++++++++++++++++++ .../Guest/GetSelectedPaymentMethodTest.php | 105 +++++++++++++ 2 files changed, 248 insertions(+) create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSelectedPaymentMethodTest.php create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSelectedPaymentMethodTest.php diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSelectedPaymentMethodTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSelectedPaymentMethodTest.php new file mode 100644 index 0000000000000..d876d74de661b --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSelectedPaymentMethodTest.php @@ -0,0 +1,143 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQl\Quote\Customer; + +use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; +use Magento\Integration\Api\CustomerTokenServiceInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\TestCase\GraphQlAbstract; + +/** + * Test for getting selected payment method from cart + */ +class GetSelectedPaymentMethodTest extends GraphQlAbstract +{ + /** + * @var GetMaskedQuoteIdByReservedOrderId + */ + private $getMaskedQuoteIdByReservedOrderId; + + /** + * @var CustomerTokenServiceInterface + */ + private $customerTokenService; + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_payment_methods.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_checkmo_payment_method.php + */ + public function testGetSelectedPaymentMethod() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + + $query = $this->getQuery($maskedQuoteId); + $response = $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + + $this->assertArrayHasKey('cart', $response); + $this->assertArrayHasKey('selected_payment_method', $response['cart']); + $this->assertArrayHasKey('code', $response['cart']['selected_payment_method']); + $this->assertEquals('checkmo', $response['cart']['selected_payment_method']['code']); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @expectedException \Exception + */ + public function testGetSelectedPaymentMethodFromNonExistentCart() + { + $maskedQuoteId = 'non_existent_masked_id'; + $query = $this->getQuery($maskedQuoteId); + + $this->expectExceptionMessage( + 'Could not find a cart with ID "non_existent_masked_id"' + ); + + $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + } + + /** + * _security + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_payment_methods.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_checkmo_payment_method.php + */ + public function testGetSelectedPaymentMethodFromGuestCart() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId); + + $this->expectExceptionMessage( + "The current user cannot perform operations on cart \"$maskedQuoteId\"" + ); + + $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + } + + /** + * _security + * @magentoApiDataFixture Magento/Customer/_files/three_customers.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + */ + public function testGetSelectedPaymentMethodFromAnotherCustomerCart() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId); + + $this->expectExceptionMessage( + "The current user cannot perform operations on cart \"{$maskedQuoteId}\"" + ); + + $this->graphQlQuery($query, [], '', $this->getHeaderMap('customer3@search.example.com')); + } + + protected function setUp() + { + $objectManager = Bootstrap::getObjectManager(); + $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); + $this->customerTokenService = $objectManager->get(CustomerTokenServiceInterface::class); + } + + /** + * @param string $maskedQuoteId + * @return string + */ + private function getQuery(string $maskedQuoteId): string + { + return <<<QUERY +{ + cart(cart_id:"$maskedQuoteId") { + selected_payment_method { + code + } + } +} +QUERY; + } + + /** + * @param string $username + * @param string $password + * @return array + * @throws \Magento\Framework\Exception\AuthenticationException + */ + private function getHeaderMap(string $username = 'customer@example.com', string $password = 'password'): array + { + $customerToken = $this->customerTokenService->createCustomerAccessToken($username, $password); + $headerMap = ['Authorization' => 'Bearer ' . $customerToken]; + return $headerMap; + } +} diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSelectedPaymentMethodTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSelectedPaymentMethodTest.php new file mode 100644 index 0000000000000..ef04da88ea67a --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSelectedPaymentMethodTest.php @@ -0,0 +1,105 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQl\Quote\Guest; + +use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\TestCase\GraphQlAbstract; + +/** + * Test for getting selected payment method from cart + */ +class GetSelectedPaymentMethodTest extends GraphQlAbstract +{ + /** + * @var GetMaskedQuoteIdByReservedOrderId + */ + private $getMaskedQuoteIdByReservedOrderId; + + protected function setUp() + { + $objectManager = Bootstrap::getObjectManager(); + $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); + } + + /** + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_payment_methods.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_checkmo_payment_method.php + * + */ + public function testGetSelectedPaymentMethod() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + + $query = $this->getQuery($maskedQuoteId); + $response = $this->graphQlQuery($query); + + $this->assertArrayHasKey('cart', $response); + $this->assertArrayHasKey('selected_payment_method', $response['cart']); + $this->assertArrayHasKey('code', $response['cart']['selected_payment_method']); + $this->assertEquals('checkmo', $response['cart']['selected_payment_method']['code']); + } + + /** + * @expectedException \Exception + */ + public function testGetSelectedPaymentMethodFromNonExistentCart() + { + $maskedQuoteId = 'non_existent_masked_id'; + $query = $this->getQuery($maskedQuoteId); + + $this->expectExceptionMessage( + 'Could not find a cart with ID "non_existent_masked_id"' + ); + + $this->graphQlQuery($query); + } + + /** + * _security + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_payment_methods.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_checkmo_payment_method.php + */ + public function testGetSelectedPaymentMethodFromCustomerCart() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId); + + $this->expectExceptionMessage( + "The current user cannot perform operations on cart \"{$maskedQuoteId}\"" + ); + + $this->graphQlQuery($query); + } + + /** + * @param string $maskedQuoteId + * @return string + */ + private function getQuery(string $maskedQuoteId): string + { + return <<<QUERY +{ + cart(cart_id:"$maskedQuoteId") { + selected_payment_method { + code + } + } +} +QUERY; + } +} From f84197c130ec7f2ace085a0b013cd396b41cacf1 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Wed, 1 May 2019 13:15:09 -0500 Subject: [PATCH 332/773] GraphQL-602: [Test Coverage] Get Specified shipping address --- .../GraphQl/Quote/Customer/GetSpecifiedShippingAddressTest.php | 2 +- .../GraphQl/Quote/Guest/GetSpecifiedShippingAddressTest.php | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSpecifiedShippingAddressTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSpecifiedShippingAddressTest.php index 766dd102b749c..de3c384e65783 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSpecifiedShippingAddressTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSpecifiedShippingAddressTest.php @@ -137,7 +137,7 @@ public function testGetSpecifiedShippingAddressOfNonExistentCart() * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php */ - public function testGetSpecifiedShippingAddressFromAnotherGuestCart() + public function testGetSpecifiedShippingAddressFromGuestCart() { $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedShippingAddressTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedShippingAddressTest.php index 3b96a873bdb81..f71915bab650f 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedShippingAddressTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedShippingAddressTest.php @@ -117,13 +117,14 @@ public function testGetShippingAddressOfNonExistentCart() } /** + * _security * @magentoApiDataFixture Magento/Customer/_files/customer.php * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php */ - public function testGetShippingAddressFromAnotherCustomerCart() + public function testGetShippingAddressFromCustomerCart() { $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $query = $this->getQuery($maskedQuoteId); From b2308311596f0af356711e3943183cbcd167070e Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Wed, 1 May 2019 13:29:31 -0500 Subject: [PATCH 333/773] GraphQL-646: Incorrect name of Selected Shipping Method --- .../Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php index c50ae0a70380e..7de689a6ad0f5 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php @@ -116,6 +116,7 @@ public function testSetUpsShippingMethod(string $methodCode, string $methodTitle self::assertEquals(self::CARRIER_TITLE, $shippingAddress['selected_shipping_method']['carrier_title']); self::assertArrayHasKey('method_title', $shippingAddress['selected_shipping_method']); + self::assertEquals($methodTitle, $shippingAddress['selected_shipping_method']['method_title']); } /** @@ -171,6 +172,7 @@ public function testSetUpsShippingMethodBasedOnCanadaAddress(string $methodCode, self::assertEquals(self::CARRIER_TITLE, $shippingAddress['selected_shipping_method']['carrier_title']); self::assertArrayHasKey('method_title', $shippingAddress['selected_shipping_method']); + self::assertEquals($methodTitle, $shippingAddress['selected_shipping_method']['method_title']); } /** From 7cc0319b391676c42c9e0d3c2a8c62f1776fad27 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Wed, 1 May 2019 15:14:05 -0500 Subject: [PATCH 334/773] GraphQL-640: Input type declaration in GraphQL SDL cannot be empty --- app/code/Magento/QuoteGraphQl/etc/schema.graphqls | 6 ------ 1 file changed, 6 deletions(-) diff --git a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls index b09cf13bbde2b..30e44aa2ab9b4 100644 --- a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls +++ b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls @@ -130,12 +130,9 @@ input SetPaymentMethodOnCartInput { input PaymentMethodInput { code: String! @doc(description:"Payment method code") - additional_data: PaymentMethodAdditionalDataInput @doc(description:"Additional payment data") purchase_order_number: String @doc(description:"Purchase order number") } -input PaymentMethodAdditionalDataInput - input SetGuestEmailOnCartInput { cart_id: String! email: String! @@ -257,12 +254,9 @@ type AvailablePaymentMethod { type SelectedPaymentMethod { code: String! @doc(description: "The payment method code") title: String! @doc(description: "The payment method title.") - additional_data: SelectedPaymentMethodAdditionalData @doc(description: "Additional payment data") purchase_order_number: String @doc(description: "The purchase order number.") } -type SelectedPaymentMethodAdditionalData - type AppliedCoupon { code: String! } From fd1248a27f2d4dd78255f67d5a25e2eb3314650c Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Wed, 1 May 2019 15:47:48 -0500 Subject: [PATCH 335/773] GraphQL-641: Schema Inconsistency of "cartItems" declaration --- .../etc/schema.graphqls | 2 +- .../SelectedShippingMethod.php | 20 ++++++++++++++----- .../Magento/QuoteGraphQl/etc/schema.graphqls | 4 ++-- .../CatalogInventory/AddProductToCartTest.php | 2 +- .../AddConfigurableProductToCartTest.php | 2 +- .../PageCache/Quote/Guest/CartCacheTest.php | 2 +- ...mpleProductWithCustomOptionsToCartTest.php | 2 +- ...tualProductWithCustomOptionsToCartTest.php | 2 +- .../Customer/AddSimpleProductToCartTest.php | 2 +- .../Customer/AddVirtualProductToCartTest.php | 2 +- .../Quote/Customer/CheckoutEndToEndTest.php | 2 +- .../Guest/AddSimpleProductToCartTest.php | 2 +- .../Guest/AddVirtualProductToCartTest.php | 2 +- .../Quote/Guest/CheckoutEndToEndTest.php | 2 +- 14 files changed, 29 insertions(+), 19 deletions(-) diff --git a/app/code/Magento/ConfigurableProductGraphQl/etc/schema.graphqls b/app/code/Magento/ConfigurableProductGraphQl/etc/schema.graphqls index d4780c5c0867a..45a4323e7f4bc 100644 --- a/app/code/Magento/ConfigurableProductGraphQl/etc/schema.graphqls +++ b/app/code/Magento/ConfigurableProductGraphQl/etc/schema.graphqls @@ -41,7 +41,7 @@ type ConfigurableProductOptionsValues @doc(description: "ConfigurableProductOpti input AddConfigurableProductsToCartInput { cart_id: String! - cartItems: [ConfigurableProductCartItemInput!]! + cart_items: [ConfigurableProductCartItemInput!]! } type AddConfigurableProductsToCartOutput { diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/SelectedShippingMethod.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/SelectedShippingMethod.php index bf6315086ae8b..05bc196acfc22 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/SelectedShippingMethod.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/SelectedShippingMethod.php @@ -46,19 +46,29 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value /** @var Address $address */ $address = $value['model']; $rates = $address->getAllShippingRates(); + $carrierTitle = null; + $methodTitle = null; if (count($rates) > 0) { list($carrierCode, $methodCode) = explode('_', $address->getShippingMethod(), 2); + /** @var Rate $rate */ - $rate = current($rates); + foreach ($rates as $rate) { + if ($rate->getCode() == $address->getShippingMethod()) { + $carrierTitle = $rate->getCarrierTitle(); + $methodTitle = $rate->getMethodTitle(); + break; + } + } + /** @var Currency $currency */ $currency = $this->storeManager->getStore()->getBaseCurrency(); $data = [ 'carrier_code' => $carrierCode, 'method_code' => $methodCode, - 'carrier_title' => $rate->getCarrierTitle(), - 'method_title' => $rate->getMethodTitle(), + 'carrier_title' => $carrierTitle, + 'method_title' => $methodTitle, 'amount' => [ 'value' => $address->getShippingAmount(), 'currency' => $address->getQuote()->getQuoteCurrencyCode(), @@ -72,8 +82,8 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value $data = [ 'carrier_code' => null, 'method_code' => null, - 'carrier_title' => null, - 'method_title' => null, + 'carrier_title' => $carrierTitle, + 'method_title' => $methodTitle, 'amount' => null, 'base_amount' => null, ]; diff --git a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls index 30e44aa2ab9b4..9e9c83b358206 100644 --- a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls +++ b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls @@ -27,7 +27,7 @@ input createEmptyCartInput { input AddSimpleProductsToCartInput { cart_id: String! - cartItems: [SimpleProductCartItemInput!]! + cart_items: [SimpleProductCartItemInput!]! } input SimpleProductCartItemInput { @@ -37,7 +37,7 @@ input SimpleProductCartItemInput { input AddVirtualProductsToCartInput { cart_id: String! - cartItems: [VirtualProductCartItemInput!]! + cart_items: [VirtualProductCartItemInput!]! } input VirtualProductCartItemInput { diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php index 6f27693eeb4a7..6ed0f6ef7a132 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php @@ -112,7 +112,7 @@ private function getQuery(string $maskedQuoteId, string $sku, float $quantity) : addSimpleProductsToCart( input: { cart_id: "{$maskedQuoteId}", - cartItems: [ + cart_items: [ { data: { quantity: $quantity diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/AddConfigurableProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/AddConfigurableProductToCartTest.php index 6810f9d44ce91..a6f02e4239f25 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/AddConfigurableProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/AddConfigurableProductToCartTest.php @@ -93,7 +93,7 @@ private function getQuery(string $maskedQuoteId, string $variantSku, int $quanti addConfigurableProductsToCart( input: { cart_id: "{$maskedQuoteId}" - cartItems: [ + cart_items: [ { variant_sku: "{$variantSku}" data: { diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/Quote/Guest/CartCacheTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/Quote/Guest/CartCacheTest.php index e09ee8bc969af..808fd95d331e1 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/Quote/Guest/CartCacheTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/Quote/Guest/CartCacheTest.php @@ -79,7 +79,7 @@ private function addSimpleProductToCart(string $maskedCartId, int $qty, string $ addSimpleProductsToCart( input: { cart_id: "{$maskedCartId}" - cartItems: [ + cart_items: [ { data: { qty: $qty diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductWithCustomOptionsToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductWithCustomOptionsToCartTest.php index d64c51354129d..53be8f84ffc83 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductWithCustomOptionsToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductWithCustomOptionsToCartTest.php @@ -106,7 +106,7 @@ private function getQuery(string $maskedQuoteId, string $sku, float $quantity, s addSimpleProductsToCart( input: { cart_id: "{$maskedQuoteId}", - cartItems: [ + cart_items: [ { data: { quantity: $quantity diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddVirtualProductWithCustomOptionsToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddVirtualProductWithCustomOptionsToCartTest.php index 55542919cc098..7b3c5de4ba61d 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddVirtualProductWithCustomOptionsToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddVirtualProductWithCustomOptionsToCartTest.php @@ -106,7 +106,7 @@ private function getQuery(string $maskedQuoteId, string $sku, float $quantity, s addVirtualProductsToCart( input: { cart_id: "{$maskedQuoteId}", - cartItems: [ + cart_items: [ { data: { quantity: $quantity diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddSimpleProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddSimpleProductToCartTest.php index be22d860df122..aca13e53875dd 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddSimpleProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddSimpleProductToCartTest.php @@ -139,7 +139,7 @@ private function getQuery(string $maskedQuoteId, string $sku, float $quantity): mutation { addSimpleProductsToCart(input: { cart_id: "{$maskedQuoteId}", - cartItems: [ + cart_items: [ { data: { quantity: {$quantity} diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddVirtualProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddVirtualProductToCartTest.php index 1269b9d8e7b3d..86573dcde2e35 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddVirtualProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddVirtualProductToCartTest.php @@ -139,7 +139,7 @@ private function getQuery(string $maskedQuoteId, string $sku, float $quantity): mutation { addVirtualProductsToCart(input: { cart_id: "{$maskedQuoteId}", - cartItems: [ + cart_items: [ { data: { quantity: {$quantity} diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php index eddc1f98d7a96..5a4cc88d69623 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php @@ -212,7 +212,7 @@ private function addProductToCart(string $cartId, float $qty, string $sku): void addSimpleProductsToCart( input: { cart_id: "{$cartId}" - cartItems: [ + cart_items: [ { data: { quantity: {$qty} diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddSimpleProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddSimpleProductToCartTest.php index 8b20320fc2f02..9a943cf4b204e 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddSimpleProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddSimpleProductToCartTest.php @@ -112,7 +112,7 @@ private function getQuery(string $maskedQuoteId, string $sku, float $quantity): addSimpleProductsToCart( input: { cart_id: "{$maskedQuoteId}" - cartItems: [ + cart_items: [ { data: { quantity: $quantity diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddVirtualProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddVirtualProductToCartTest.php index cb429e7b9cb9e..cadbec857c2d6 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddVirtualProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddVirtualProductToCartTest.php @@ -113,7 +113,7 @@ private function getQuery(string $maskedQuoteId, string $sku, float $quantity): addVirtualProductsToCart( input: { cart_id: "{$maskedQuoteId}" - cartItems: [ + cart_items: [ { data: { quantity: {$quantity} diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php index a95e4404a08ac..ed5aa9303d875 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php @@ -172,7 +172,7 @@ private function addProductToCart(string $cartId, float $quantity, string $sku): addSimpleProductsToCart( input: { cart_id: "{$cartId}" - cartItems: [ + cart_items: [ { data: { quantity: {$quantity} From a947e3c1c6bc589bbcb8f9c823e476cd1cc47730 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Wed, 1 May 2019 15:56:54 -0500 Subject: [PATCH 336/773] GraphQL-641: Schema Inconsistency of "cartItems" declaration --- setup/performance-toolkit/benchmark.jmx | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/setup/performance-toolkit/benchmark.jmx b/setup/performance-toolkit/benchmark.jmx index 0609be4d7d193..a8a7e419373b8 100644 --- a/setup/performance-toolkit/benchmark.jmx +++ b/setup/performance-toolkit/benchmark.jmx @@ -41347,7 +41347,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n data: {\n quantity: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n quantity\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cart_items: [\n {\n data: {\n quantity: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n quantity\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -41567,7 +41567,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation {\n addConfigurableProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n variant_sku: \"${product_option}\"\n data: {\n quantity: 2\n sku: \"${product_option}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n id\n quantity\n product {\n name\n sku\n }\n ... on ConfigurableCartItem {\n configurable_options {\n option_label\n }\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation {\n addConfigurableProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cart_items: [\n {\n variant_sku: \"${product_option}\"\n data: {\n quantity: 2\n sku: \"${product_option}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n id\n quantity\n product {\n name\n sku\n }\n ... on ConfigurableCartItem {\n configurable_options {\n option_label\n }\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -41739,7 +41739,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n data: {\n quantity: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n quantity\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cart_items: [\n {\n data: {\n quantity: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n quantity\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -42045,7 +42045,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation {\n addConfigurableProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n variant_sku: \"${product_option}\"\n data: {\n quantity: 2\n sku: \"${product_option}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n id\n quantity\n product {\n name\n sku\n }\n ... on ConfigurableCartItem {\n configurable_options {\n option_label\n }\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation {\n addConfigurableProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cart_items: [\n {\n variant_sku: \"${product_option}\"\n data: {\n quantity: 2\n sku: \"${product_option}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n id\n quantity\n product {\n name\n sku\n }\n ... on ConfigurableCartItem {\n configurable_options {\n option_label\n }\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -42303,7 +42303,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n data: {\n quantity: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n quantity\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cart_items: [\n {\n data: {\n quantity: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n quantity\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -42609,7 +42609,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation {\n addConfigurableProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n variant_sku: \"${product_option}\"\n data: {\n quantity: 2\n sku: \"${product_option}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n id\n quantity\n product {\n name\n sku\n }\n ... on ConfigurableCartItem {\n configurable_options {\n option_label\n }\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation {\n addConfigurableProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cart_items: [\n {\n variant_sku: \"${product_option}\"\n data: {\n quantity: 2\n sku: \"${product_option}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n id\n quantity\n product {\n name\n sku\n }\n ... on ConfigurableCartItem {\n configurable_options {\n option_label\n }\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -42867,7 +42867,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n data: {\n quantity: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n quantity\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cart_items: [\n {\n data: {\n quantity: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n quantity\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -43094,7 +43094,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n data: {\n quantity: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n quantity\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cart_items: [\n {\n data: {\n quantity: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n quantity\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -43959,7 +43959,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation {\n addConfigurableProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n variant_sku: \"${product_option}\"\n data: {\n quantity: 2\n sku: \"${product_option}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n id\n quantity\n product {\n name\n sku\n }\n ... on ConfigurableCartItem {\n configurable_options {\n option_label\n }\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation {\n addConfigurableProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cart_items: [\n {\n variant_sku: \"${product_option}\"\n data: {\n quantity: 2\n sku: \"${product_option}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n id\n quantity\n product {\n name\n sku\n }\n ... on ConfigurableCartItem {\n configurable_options {\n option_label\n }\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -44019,7 +44019,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n data: {\n quantity: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n quantity\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cart_items: [\n {\n data: {\n quantity: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n quantity\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> From 0a5b24a93fb31707f4745c5354fdff82376a9b65 Mon Sep 17 00:00:00 2001 From: Cristian Partica <cpartica@magento.com> Date: Thu, 2 May 2019 14:22:45 -0500 Subject: [PATCH 337/773] MC-15959: Implement caching for url resolver - change graphql dispatch to not cause boc - fixing tests - implementing url resolver cache - removing cahceTag annotation --- .../Resolver/Category/CategoriesIdentity.php | 8 +- .../Category/CategoryTreeIdentity.php | 6 +- .../Model/Resolver/Product/Identity.php | 8 +- .../CatalogGraphQl/etc/schema.graphqls | 18 +- .../UrlRewrite/CatalogUrlResolverIdentity.php | 62 +++++ .../CatalogUrlRewriteGraphQl/composer.json | 1 + .../CatalogUrlRewriteGraphQl/etc/di.xml | 17 ++ .../Model/Resolver/Block/Identity.php | 11 +- .../Model/Resolver/Page/Identity.php | 6 +- .../Magento/CmsGraphQl/etc/schema.graphqls | 4 +- .../UrlRewrite/CmsUrlResolverIdentity.php | 35 +++ .../CmsUrlRewriteGraphQl/composer.json | 4 +- .../Magento/CmsUrlRewriteGraphQl/etc/di.xml | 7 + .../etc/schema.graphqls | 2 +- .../CustomerGraphQl/etc/schema.graphqls | 4 +- .../Magento/EavGraphQl/etc/schema.graphqls | 2 +- .../Controller/Plugin/GraphQl.php | 14 +- .../Model/CacheableQueryHandler.php | 28 +-- .../Model/Plugin/Query/Resolver.php | 42 +++- .../Model/Resolver/IdentityPool.php | 2 +- .../Unit/Model/CacheableQueryHandlerTest.php | 6 +- .../Magento/QuoteGraphQl/etc/schema.graphqls | 2 +- .../UrlRewrite/UrlResolverIdentity.php | 46 ++++ .../UrlRewriteGraphQl/etc/schema.graphqls | 2 +- .../UrlRewrite/UrlResolverCacheTest.php | 216 ++++++++++++++++++ .../GraphQl/_files/query_array_output.php | 1 - .../Controller/AbstractGraphqlCacheTest.php | 30 ++- .../CategoriesWithProductsCacheTest.php | 7 + .../Controller/Catalog/CategoryCacheTest.php | 12 +- .../DeepNestedCategoriesAndProductsTest.php | 10 +- .../Controller/Catalog/ProductsCacheTest.php | 20 +- .../Controller/Cms/BlockCacheTest.php | 14 +- .../Controller/Cms/CmsPageCacheTest.php | 83 +++++-- .../CategoryUrlResolverCacheTest.php | 83 +++++++ .../CmsPageUrlResolverCacheTest.php | 70 ++++++ .../ProductUrlResolverCacheTest.php | 74 ++++++ .../Query/Resolver/IdentityInterface.php | 7 +- ...agReader.php => CacheAnnotationReader.php} | 8 +- .../MetaReader/FieldMetaReader.php | 14 +- .../GraphQlReader/Reader/InputObjectType.php | 16 +- .../GraphQlReader/Reader/InterfaceType.php | 16 +- .../GraphQlReader/Reader/ObjectType.php | 16 +- 42 files changed, 864 insertions(+), 170 deletions(-) create mode 100644 app/code/Magento/CatalogUrlRewriteGraphQl/Model/Resolver/UrlRewrite/CatalogUrlResolverIdentity.php create mode 100644 app/code/Magento/CatalogUrlRewriteGraphQl/etc/di.xml create mode 100644 app/code/Magento/CmsUrlRewriteGraphQl/Model/Resolver/UrlRewrite/CmsUrlResolverIdentity.php create mode 100644 app/code/Magento/UrlRewriteGraphQl/Model/Resolver/UrlRewrite/UrlResolverIdentity.php create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/UrlRewrite/UrlResolverCacheTest.php create mode 100644 dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/UrlRewrite/CategoryUrlResolverCacheTest.php create mode 100644 dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/UrlRewrite/CmsPageUrlResolverCacheTest.php create mode 100644 dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/UrlRewrite/ProductUrlResolverCacheTest.php rename lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/MetaReader/{CacheTagReader.php => CacheAnnotationReader.php} (81%) diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Category/CategoriesIdentity.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Category/CategoriesIdentity.php index aba2d7b198dbd..dd18c463b98de 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Resolver/Category/CategoriesIdentity.php +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Category/CategoriesIdentity.php @@ -14,6 +14,9 @@ */ class CategoriesIdentity implements IdentityInterface { + /** @var string */ + private $cacheTag = \Magento\Catalog\Model\Category::CACHE_TAG; + /** * Get category IDs from resolved data * @@ -25,7 +28,10 @@ public function getIdentities(array $resolvedData): array $ids = []; if (!empty($resolvedData)) { foreach ($resolvedData as $category) { - $ids[] = $category['id']; + $ids[] = sprintf('%s_%s', $this->cacheTag, $category['id']); + } + if (!empty($ids)) { + array_unshift($ids, $this->cacheTag); } } return $ids; diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Category/CategoryTreeIdentity.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Category/CategoryTreeIdentity.php index e4970f08b3eb7..017a7d280c195 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Resolver/Category/CategoryTreeIdentity.php +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Category/CategoryTreeIdentity.php @@ -14,6 +14,9 @@ */ class CategoryTreeIdentity implements IdentityInterface { + /** @var string */ + private $cacheTag = \Magento\Catalog\Model\Category::CACHE_TAG; + /** * Get category ID from resolved data * @@ -22,6 +25,7 @@ class CategoryTreeIdentity implements IdentityInterface */ public function getIdentities(array $resolvedData): array { - return empty($resolvedData['id']) ? [] : [$resolvedData['id']]; + return empty($resolvedData['id']) ? + [] : [$this->cacheTag, sprintf('%s_%s', $this->cacheTag, $resolvedData['id'])]; } } diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/Identity.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/Identity.php index 198b1c112dca2..7aec66ccb699f 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/Identity.php +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/Identity.php @@ -14,6 +14,9 @@ */ class Identity implements IdentityInterface { + /** @var string */ + private $cacheTag = \Magento\Catalog\Model\Product::CACHE_TAG; + /** * Get product ids for cache tag * @@ -25,7 +28,10 @@ public function getIdentities(array $resolvedData): array $ids = []; $items = $resolvedData['items'] ?? []; foreach ($items as $item) { - $ids[] = $item['entity_id']; + $ids[] = sprintf('%s_%s', $this->cacheTag, $item['entity_id']); + } + if (!empty($ids)) { + array_unshift($ids, $this->cacheTag); } return $ids; diff --git a/app/code/Magento/CatalogGraphQl/etc/schema.graphqls b/app/code/Magento/CatalogGraphQl/etc/schema.graphqls index 9f102a1c6a150..ae83272163127 100644 --- a/app/code/Magento/CatalogGraphQl/etc/schema.graphqls +++ b/app/code/Magento/CatalogGraphQl/etc/schema.graphqls @@ -8,12 +8,12 @@ type Query { pageSize: Int = 20 @doc(description: "Specifies the maximum number of results to return at once. This attribute is optional."), currentPage: Int = 1 @doc(description: "Specifies which page of results to return. The default value is 1."), sort: ProductSortInput @doc(description: "Specifies which attribute to sort on, and whether to return the results in ascending or descending order.") - ): Products - @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Products") @doc(description: "The products query searches for products that match the criteria specified in the search and filter attributes") @cache(cacheTag: "cat_p", cacheIdentity: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\Identity") + ): Products + @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Products") @doc(description: "The products query searches for products that match the criteria specified in the search and filter attributes") @cache(cacheIdentity: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\Identity") category ( id: Int @doc(description: "Id of the category") ): CategoryTree - @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\CategoryTree") @doc(description: "The category query searches for categories that match the criteria specified in the search and filter attributes") @cache(cacheTag: "cat_c", cacheIdentity: "Magento\\CatalogGraphQl\\Model\\Resolver\\Category\\CategoryTreeIdentity") + @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\CategoryTree") @doc(description: "The category query searches for categories that match the criteria specified in the search and filter attributes") @cache(cacheIdentity: "Magento\\CatalogGraphQl\\Model\\Resolver\\Category\\CategoryTreeIdentity") } type Price @doc(description: "The Price object defines the price of a product as well as any tax-related adjustments.") { @@ -97,7 +97,7 @@ interface ProductInterface @typeResolver(class: "Magento\\CatalogGraphQl\\Model\ price: ProductPrices @doc(description: "A ProductPrices object, indicating the price of an item") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\Price") gift_message_available: String @doc(description: "Indicates whether a gift message is available") manufacturer: Int @doc(description: "A number representing the product's manufacturer") - categories: [CategoryInterface] @doc(description: "The categories assigned to a product") @cache(cacheTag: "cat_c", cacheIdentity: "Magento\\CatalogGraphQl\\Model\\Resolver\\Category\\CategoriesIdentity") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Categories") + categories: [CategoryInterface] @doc(description: "The categories assigned to a product") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Categories") @cache(cacheIdentity: "Magento\\CatalogGraphQl\\Model\\Resolver\\Category\\CategoriesIdentity") canonical_url: String @doc(description: "Canonical URL") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\CanonicalUrl") } @@ -218,7 +218,7 @@ interface CategoryInterface @typeResolver(class: "Magento\\CatalogGraphQl\\Model pageSize: Int = 20 @doc(description: "Specifies the maximum number of results to return at once. This attribute is optional."), currentPage: Int = 1 @doc(description: "Specifies which page of results to return. The default value is 1."), sort: ProductSortInput @doc(description: "Specifies which attribute to sort on, and whether to return the results in ascending or descending order.") - ): CategoryProducts @doc(description: "The list of products assigned to the category") @cache(cacheTag: "cat_p", cacheIdentity: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\Identity") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Category\\Products") + ): CategoryProducts @doc(description: "The list of products assigned to the category") @cache(cacheIdentity: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\Identity") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Category\\Products") breadcrumbs: [Breadcrumb] @doc(description: "Breadcrumbs, parent categories info") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Category\\Breadcrumbs") } @@ -233,7 +233,7 @@ type CustomizableRadioOption implements CustomizableOptionInterface @doc(descrip value: [CustomizableRadioValue] @doc(description: "An array that defines a set of radio buttons") } -type CustomizableRadioValue @doc(description: "CustomizableRadioValue defines the price and sku of a product whose page contains a customized set of radio buttons") { +type CustomizableRadioValue @doc(description: "CustomizableRadioValue defines the price and sku of a product whose page contains a customized set of radio buttons") { option_type_id: Int @doc(description: "The ID assigned to the value") price: Float @doc(description: "The price assigned to this option") price_type: PriceTypeEnum @doc(description: "FIXED, PERCENT, or DYNAMIC") @@ -246,7 +246,7 @@ type CustomizableCheckboxOption implements CustomizableOptionInterface @doc(desc value: [CustomizableCheckboxValue] @doc(description: "An array that defines a set of checkbox values") } -type CustomizableCheckboxValue @doc(description: "CustomizableCheckboxValue defines the price and sku of a product whose page contains a customized set of checkbox values") { +type CustomizableCheckboxValue @doc(description: "CustomizableCheckboxValue defines the price and sku of a product whose page contains a customized set of checkbox values") { option_type_id: Int @doc(description: "The ID assigned to the value") price: Float @doc(description: "The price assigned to this option") price_type: PriceTypeEnum @doc(description: "FIXED, PERCENT, or DYNAMIC") @@ -329,7 +329,7 @@ type ProductMediaGalleryEntriesVideoContent @doc(description: "ProductMediaGalle video_metadata: String @doc(description: "Optional data about the video") } -input ProductSortInput @doc(description: "ProductSortInput specifies the attribute to use for sorting search results and indicates whether the results are sorted in ascending or descending order") { +input ProductSortInput @doc(description: "ProductSortInput specifies the attribute to use for sorting search results and indicates whether the results are sorted in ascending or descending order") { name: SortEnum @doc(description: "The product name. Customers use this name to identify the product.") sku: SortEnum @doc(description: "A number or code assigned to a product to identify the product, options, price, and manufacturer") description: SortEnum @doc(description: "Detailed information about the product. The value can include simple HTML tags.") @@ -363,7 +363,7 @@ input ProductSortInput @doc(description: "ProductSortInput specifies the attrib gift_message_available: SortEnum @doc(description: "Indicates whether a gift message is available") } -type MediaGalleryEntry @doc(description: "MediaGalleryEntry defines characteristics about images and videos associated with a specific product") { +type MediaGalleryEntry @doc(description: "MediaGalleryEntry defines characteristics about images and videos associated with a specific product") { id: Int @doc(description: "The identifier assigned to the object") media_type: String @doc(description: "image or video") label: String @doc(description: "The alt text displayed on the UI when the user points to the image") diff --git a/app/code/Magento/CatalogUrlRewriteGraphQl/Model/Resolver/UrlRewrite/CatalogUrlResolverIdentity.php b/app/code/Magento/CatalogUrlRewriteGraphQl/Model/Resolver/UrlRewrite/CatalogUrlResolverIdentity.php new file mode 100644 index 0000000000000..204080488488a --- /dev/null +++ b/app/code/Magento/CatalogUrlRewriteGraphQl/Model/Resolver/UrlRewrite/CatalogUrlResolverIdentity.php @@ -0,0 +1,62 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\CatalogUrlRewriteGraphQl\Model\Resolver\UrlRewrite; + +use Magento\Framework\GraphQl\Query\Resolver\IdentityInterface; + +/** + * Get ids from catalog url rewrite + */ +class CatalogUrlResolverIdentity implements IdentityInterface +{ + /** @var string */ + private $categoryCacheTag = \Magento\Catalog\Model\Category::CACHE_TAG; + + /** @var string */ + private $productCacheTag = \Magento\Catalog\Model\Product::CACHE_TAG; + + /** + * Get identities cache ID from a catalog url rewrite entities + * + * @param array $resolvedData + * @return string[] + */ + public function getIdentities(array $resolvedData): array + { + $ids = []; + if (isset($resolvedData['id'])) { + $selectedCacheTag = isset($resolvedData['type']) ? + $this->getTagFromEntityType($resolvedData['type']) : ''; + if (!empty($selectedCacheTag)) { + $ids = [$selectedCacheTag, sprintf('%s_%s', $selectedCacheTag, $resolvedData['id'])]; + } + } + return $ids; + } + + /** + * Match tag to entity type + * + * @param string $entityType + * @return string + */ + private function getTagFromEntityType(string $entityType) : string + { + $selectedCacheTag = ''; + $type = strtolower($entityType); + switch ($type) { + case 'product': + $selectedCacheTag = $this->productCacheTag; + break; + case 'category': + $selectedCacheTag = $this->categoryCacheTag; + break; + } + return $selectedCacheTag; + } +} diff --git a/app/code/Magento/CatalogUrlRewriteGraphQl/composer.json b/app/code/Magento/CatalogUrlRewriteGraphQl/composer.json index ab91f745c5d0c..4a1a17f1398d6 100644 --- a/app/code/Magento/CatalogUrlRewriteGraphQl/composer.json +++ b/app/code/Magento/CatalogUrlRewriteGraphQl/composer.json @@ -4,6 +4,7 @@ "type": "magento2-module", "require": { "php": "~7.1.3||~7.2.0", + "magento/module-catalog": "*", "magento/framework": "*" }, "suggest": { diff --git a/app/code/Magento/CatalogUrlRewriteGraphQl/etc/di.xml b/app/code/Magento/CatalogUrlRewriteGraphQl/etc/di.xml new file mode 100644 index 0000000000000..20e6b7e9c0053 --- /dev/null +++ b/app/code/Magento/CatalogUrlRewriteGraphQl/etc/di.xml @@ -0,0 +1,17 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © Magento, Inc. 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\UrlRewriteGraphQl\Model\Resolver\UrlRewrite\UrlResolverIdentity"> + <arguments> + <argument name="urlResolverIdentities" xsi:type="array"> + <item name="product" xsi:type="object">Magento\CatalogUrlRewriteGraphQl\Model\Resolver\UrlRewrite\CatalogUrlResolverIdentity</item> + <item name="category" xsi:type="object">Magento\CatalogUrlRewriteGraphQl\Model\Resolver\UrlRewrite\CatalogUrlResolverIdentity</item> + </argument> + </arguments> + </type> +</config> diff --git a/app/code/Magento/CmsGraphQl/Model/Resolver/Block/Identity.php b/app/code/Magento/CmsGraphQl/Model/Resolver/Block/Identity.php index a40d23968c3c6..8090dbfbd39b1 100644 --- a/app/code/Magento/CmsGraphQl/Model/Resolver/Block/Identity.php +++ b/app/code/Magento/CmsGraphQl/Model/Resolver/Block/Identity.php @@ -15,6 +15,9 @@ */ class Identity implements IdentityInterface { + /** @var string */ + private $cacheTag = \Magento\Cms\Model\Block::CACHE_TAG; + /** * Get block identities from resolved data * @@ -27,11 +30,15 @@ public function getIdentities(array $resolvedData): array $items = $resolvedData['items'] ?? []; foreach ($items as $item) { if (is_array($item) && !empty($item[BlockInterface::BLOCK_ID])) { - $ids[] = $item[BlockInterface::BLOCK_ID]; - $ids[] = $item[BlockInterface::IDENTIFIER]; + $ids[] = sprintf('%s_%s', $this->cacheTag, $item[BlockInterface::BLOCK_ID]); + $ids[] = sprintf('%s_%s', $this->cacheTag, $item[BlockInterface::IDENTIFIER]); } } + if (!empty($ids)) { + array_unshift($ids, $this->cacheTag); + } + return $ids; } } diff --git a/app/code/Magento/CmsGraphQl/Model/Resolver/Page/Identity.php b/app/code/Magento/CmsGraphQl/Model/Resolver/Page/Identity.php index abc306451e309..cbfe9a7f9e1e9 100644 --- a/app/code/Magento/CmsGraphQl/Model/Resolver/Page/Identity.php +++ b/app/code/Magento/CmsGraphQl/Model/Resolver/Page/Identity.php @@ -15,6 +15,9 @@ */ class Identity implements IdentityInterface { + /** @var string */ + private $cacheTag = \Magento\Cms\Model\Page::CACHE_TAG; + /** * Get page ID from resolved data * @@ -23,6 +26,7 @@ class Identity implements IdentityInterface */ public function getIdentities(array $resolvedData): array { - return empty($resolvedData[PageInterface::PAGE_ID]) ? [] : [$resolvedData[PageInterface::PAGE_ID]]; + return empty($resolvedData[PageInterface::PAGE_ID]) ? + [] : [$this->cacheTag, sprintf('%s_%s', $this->cacheTag, $resolvedData[PageInterface::PAGE_ID])]; } } diff --git a/app/code/Magento/CmsGraphQl/etc/schema.graphqls b/app/code/Magento/CmsGraphQl/etc/schema.graphqls index 04d2efa4c7cde..09a5213fba72a 100644 --- a/app/code/Magento/CmsGraphQl/etc/schema.graphqls +++ b/app/code/Magento/CmsGraphQl/etc/schema.graphqls @@ -13,10 +13,10 @@ type StoreConfig @doc(description: "The type contains information about a store type Query { cmsPage ( id: Int @doc(description: "Id of the CMS page") - ): CmsPage @resolver(class: "Magento\\CmsGraphQl\\Model\\Resolver\\Page") @doc(description: "The CMS page query returns information about a CMS page") @cache(cacheTag: "cms_p", cacheIdentity: "Magento\\CmsGraphQl\\Model\\Resolver\\Page\\Identity") + ): CmsPage @resolver(class: "Magento\\CmsGraphQl\\Model\\Resolver\\Page") @doc(description: "The CMS page query returns information about a CMS page") @cache(cacheIdentity: "Magento\\CmsGraphQl\\Model\\Resolver\\Page\\Identity") cmsBlocks ( identifiers: [String] @doc(description: "Identifiers of the CMS blocks") - ): CmsBlocks @resolver(class: "Magento\\CmsGraphQl\\Model\\Resolver\\Blocks") @doc(description: "The CMS block query returns information about CMS blocks") @cache(cacheTag: "cms_b", cacheIdentity: "Magento\\CmsGraphQl\\Model\\Resolver\\Block\\Identity") + ): CmsBlocks @resolver(class: "Magento\\CmsGraphQl\\Model\\Resolver\\Blocks") @doc(description: "The CMS block query returns information about CMS blocks") @cache(cacheIdentity: "Magento\\CmsGraphQl\\Model\\Resolver\\Block\\Identity") } type CmsPage @doc(description: "CMS page defines all CMS page information") { diff --git a/app/code/Magento/CmsUrlRewriteGraphQl/Model/Resolver/UrlRewrite/CmsUrlResolverIdentity.php b/app/code/Magento/CmsUrlRewriteGraphQl/Model/Resolver/UrlRewrite/CmsUrlResolverIdentity.php new file mode 100644 index 0000000000000..7025217d1186b --- /dev/null +++ b/app/code/Magento/CmsUrlRewriteGraphQl/Model/Resolver/UrlRewrite/CmsUrlResolverIdentity.php @@ -0,0 +1,35 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\CmsUrlRewriteGraphQl\Model\Resolver\UrlRewrite; + +use Magento\Framework\GraphQl\Query\Resolver\IdentityInterface; + +/** + * Get ids from cms page url rewrite + */ +class CmsUrlResolverIdentity implements IdentityInterface +{ + /** @var string */ + private $cacheTag = \Magento\Cms\Model\Page::CACHE_TAG; + + /** + * Get identities cache ID from a url rewrite entities + * + * @param array $resolvedData + * @return string[] + */ + public function getIdentities(array $resolvedData): array + { + $ids = []; + if (isset($resolvedData['id'])) { + $selectedCacheTag = $this->cacheTag; + $ids = [$selectedCacheTag, sprintf('%s_%s', $selectedCacheTag, $resolvedData['id'])]; + } + return $ids; + } +} diff --git a/app/code/Magento/CmsUrlRewriteGraphQl/composer.json b/app/code/Magento/CmsUrlRewriteGraphQl/composer.json index c57e4cdc92a83..03436d39190ac 100644 --- a/app/code/Magento/CmsUrlRewriteGraphQl/composer.json +++ b/app/code/Magento/CmsUrlRewriteGraphQl/composer.json @@ -5,9 +5,9 @@ "require": { "php": "~7.1.3||~7.2.0", "magento/framework": "*", - "magento/module-url-rewrite-graph-ql": "*", + "magento/module-cms": "*", "magento/module-store": "*", - "magento/module-cms": "*" + "magento/module-url-rewrite-graph-ql": "*" }, "suggest": { "magento/module-cms-url-rewrite": "*", diff --git a/app/code/Magento/CmsUrlRewriteGraphQl/etc/di.xml b/app/code/Magento/CmsUrlRewriteGraphQl/etc/di.xml index d384c898acb62..ae8475cc113d2 100644 --- a/app/code/Magento/CmsUrlRewriteGraphQl/etc/di.xml +++ b/app/code/Magento/CmsUrlRewriteGraphQl/etc/di.xml @@ -13,4 +13,11 @@ </argument> </arguments> </type> + <type name="Magento\UrlRewriteGraphQl\Model\Resolver\UrlRewrite\UrlResolverIdentity"> + <arguments> + <argument name="urlResolverIdentities" xsi:type="array"> + <item name="cms_page" xsi:type="object">Magento\CmsUrlRewriteGraphQl\Model\Resolver\UrlRewrite\CmsUrlResolverIdentity</item> + </argument> + </arguments> + </type> </config> diff --git a/app/code/Magento/ConfigurableProductGraphQl/etc/schema.graphqls b/app/code/Magento/ConfigurableProductGraphQl/etc/schema.graphqls index 45a4323e7f4bc..91f7ee5eb3209 100644 --- a/app/code/Magento/ConfigurableProductGraphQl/etc/schema.graphqls +++ b/app/code/Magento/ConfigurableProductGraphQl/etc/schema.graphqls @@ -10,7 +10,7 @@ type ConfigurableProduct implements ProductInterface, PhysicalProductInterface, } type ConfigurableVariant @doc(description: "An array containing all the simple product variants of a configurable product") { - attributes: [ConfigurableAttributeOption] @resolver(class: "Magento\\ConfigurableProductGraphQl\\Model\\Resolver\\Variant\\Attributes") @doc(description: "") + attributes: [ConfigurableAttributeOption] @resolver(class: "Magento\\ConfigurableProductGraphQl\\Model\\Resolver\\Variant\\Attributes") @doc(description: "") product: SimpleProduct @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product") } diff --git a/app/code/Magento/CustomerGraphQl/etc/schema.graphqls b/app/code/Magento/CustomerGraphQl/etc/schema.graphqls index 1238184075057..bf7527c855e57 100644 --- a/app/code/Magento/CustomerGraphQl/etc/schema.graphqls +++ b/app/code/Magento/CustomerGraphQl/etc/schema.graphqls @@ -126,8 +126,8 @@ type CustomerAddressRegion @doc(description: "CustomerAddressRegion defines the } type CustomerAddressAttribute { - attribute_code: String @doc(description: "Attribute code") - value: String @doc(description: "Attribute value") + attribute_code: String @doc(description: "Attribute code") + value: String @doc(description: "Attribute value") } type IsEmailAvailableOutput { diff --git a/app/code/Magento/EavGraphQl/etc/schema.graphqls b/app/code/Magento/EavGraphQl/etc/schema.graphqls index 0299067bd0523..0b174fbc4d84d 100644 --- a/app/code/Magento/EavGraphQl/etc/schema.graphqls +++ b/app/code/Magento/EavGraphQl/etc/schema.graphqls @@ -2,7 +2,7 @@ # See COPYING.txt for license details. type Query { - customAttributeMetadata(attributes: [AttributeInput!]!): CustomAttributeMetadata @resolver(class: "Magento\\EavGraphQl\\Model\\Resolver\\CustomAttributeMetadata") @doc(description: "The customAttributeMetadata query returns the attribute type, given an attribute code and entity type") @cache(cacheable: false) + customAttributeMetadata(attributes: [AttributeInput!]!): CustomAttributeMetadata @resolver(class: "Magento\\EavGraphQl\\Model\\Resolver\\CustomAttributeMetadata") @doc(description: "The customAttributeMetadata query returns the attribute type, given an attribute code and entity type") @cache(cacheable: false) } type CustomAttributeMetadata @doc(description: "CustomAttributeMetadata defines an array of attribute_codes and entity_types") { diff --git a/app/code/Magento/GraphQlCache/Controller/Plugin/GraphQl.php b/app/code/Magento/GraphQlCache/Controller/Plugin/GraphQl.php index 7c026e7d4136e..d2f285c0b988b 100644 --- a/app/code/Magento/GraphQlCache/Controller/Plugin/GraphQl.php +++ b/app/code/Magento/GraphQlCache/Controller/Plugin/GraphQl.php @@ -15,6 +15,7 @@ use Magento\PageCache\Model\Config; use Magento\GraphQl\Controller\HttpRequestProcessor; use Magento\Framework\App\Response\Http as ResponseHttp; +use Magento\Framework\Registry; /** * Plugin for handling controller after controller tags and pre-controller validation. @@ -41,22 +42,30 @@ class GraphQl */ private $requestProcessor; + /** + * @var Registry + */ + private $registry; + /** * @param CacheableQuery $cacheableQuery * @param Config $config * @param HttpResponse $response * @param HttpRequestProcessor $requestProcessor + * @param Registry $registry */ public function __construct( CacheableQuery $cacheableQuery, Config $config, HttpResponse $response, - HttpRequestProcessor $requestProcessor + HttpRequestProcessor $requestProcessor, + Registry $registry ) { $this->cacheableQuery = $cacheableQuery; $this->config = $config; $this->response = $response; $this->requestProcessor = $requestProcessor; + $this->registry = $registry; } /** @@ -89,6 +98,9 @@ public function afterRenderResult(ResultInterface $subject, ResultInterface $res { $sendNoCacheHeaders = false; if ($this->config->isEnabled()) { + /** @see \Magento\Framework\App\Http::launch */ + /** @see \Magento\PageCache\Model\Controller\Result\BuiltinPlugin::afterRenderResult */ + $this->registry->register('use_page_cache_plugin', true, true); if ($this->cacheableQuery->shouldPopulateCacheHeadersWithTags()) { $this->response->setPublicHeaders($this->config->getTtl()); $this->response->setHeader('X-Magento-Tags', implode(',', $this->cacheableQuery->getCacheTags()), true); diff --git a/app/code/Magento/GraphQlCache/Model/CacheableQueryHandler.php b/app/code/Magento/GraphQlCache/Model/CacheableQueryHandler.php index 7e624845f5682..53f5155f8a3ac 100644 --- a/app/code/Magento/GraphQlCache/Model/CacheableQueryHandler.php +++ b/app/code/Magento/GraphQlCache/Model/CacheableQueryHandler.php @@ -9,6 +9,7 @@ use Magento\Framework\GraphQl\Config\Element\Field; use Magento\Framework\App\RequestInterface; +use Magento\Framework\App\Request\Http; use Magento\GraphQlCache\Model\Resolver\IdentityPool; /** @@ -53,29 +54,20 @@ public function __construct( * Set cache validity to the cacheableQuery after resolving any resolver or evaluating a promise in a query * * @param array $resolvedValue - * @param Field $field + * @param array $cacheAnnotation Eg: ['cacheable' => true, 'cacheTag' => 'someTag', cacheIdentity=>'\Mage\Class'] * @return void */ - public function handleCacheFromResolverResponse(array $resolvedValue, Field $field) : void + public function handleCacheFromResolverResponse(array $resolvedValue, array $cacheAnnotation) : void { - $cache = $field->getCache(); - $cacheIdentityClass = $cache['cacheIdentity'] ?? ''; - $cacheable = $cache['cacheable'] ?? true; - $cacheTag = $cache['cacheTag'] ?? null; + $cacheable = $cacheAnnotation['cacheable'] ?? true; + $cacheIdentityClass = $cacheAnnotation['cacheIdentity'] ?? ''; - $cacheTags = []; - if ($cacheTag && $this->request->isGet()) { - if (!empty($cacheIdentityClass)) { - $cacheIdentity = $this->identityPool->get($cacheIdentityClass); - $cacheTagIds = $cacheIdentity->getIdentities($resolvedValue); - if (!empty($cacheTagIds)) { - $cacheTags[] = $cacheTag; - foreach ($cacheTagIds as $cacheTagId) { - $cacheTags[] = $cacheTag . '_' . $cacheTagId; - } - } - } + if ($this->request instanceof Http && $this->request->isGet() && !empty($cacheIdentityClass)) { + $cacheIdentity = $this->identityPool->get($cacheIdentityClass); + $cacheTags = $cacheIdentity->getIdentities($resolvedValue); $this->cacheableQuery->addCacheTags($cacheTags); + } else { + $cacheable = false; } $this->setCacheValidity($cacheable); } diff --git a/app/code/Magento/GraphQlCache/Model/Plugin/Query/Resolver.php b/app/code/Magento/GraphQlCache/Model/Plugin/Query/Resolver.php index 54cb5559923af..9ce391fe0e176 100644 --- a/app/code/Magento/GraphQlCache/Model/Plugin/Query/Resolver.php +++ b/app/code/Magento/GraphQlCache/Model/Plugin/Query/Resolver.php @@ -55,18 +55,36 @@ public function afterResolve( array $value = null, array $args = null ) { - /** Only if array @see \Magento\Framework\GraphQl\Query\Resolver\Value */ - if (is_array($resolvedValue) && !empty($field->getCache())) { - $this->cacheableQueryHandler->handleCacheFromResolverResponse($resolvedValue, $field); - } elseif ($resolvedValue instanceof \Magento\Framework\GraphQl\Query\Resolver\Value) { - $resolvedValue->then(function () use ($resolvedValue, $field) { - if (is_array($resolvedValue->promise->result) && $field) { - $this->cacheableQueryHandler->handleCacheFromResolverResponse( - $resolvedValue->promise->result, - $field - ); - } - }); + $cacheAnnotation = $field->getCache(); + if (!empty($cacheAnnotation)) { + if (is_array($resolvedValue)) { + $this->cacheableQueryHandler->handleCacheFromResolverResponse( + $resolvedValue, + $cacheAnnotation + ); + } elseif ($resolvedValue instanceof \Magento\Framework\GraphQl\Query\Resolver\Value) { + $resolvedValue->then(function () use ($resolvedValue, $field, $cacheAnnotation) { + if (is_array($resolvedValue->promise->result)) { + $this->cacheableQueryHandler->handleCacheFromResolverResponse( + $resolvedValue->promise->result, + $cacheAnnotation + ); + } else { + // case if string or integer we pass in a single array element + $this->cacheableQueryHandler->handleCacheFromResolverResponse( + $resolvedValue->promise->result === null ? + [] : [$field->getName() => $resolvedValue->promise->result], + $cacheAnnotation + ); + } + }); + } else { + // case if string or integer we pass in a single array element + $this->cacheableQueryHandler->handleCacheFromResolverResponse( + $resolvedValue === null ? [] : [$field->getName() => $resolvedValue], + $cacheAnnotation + ); + } } return $resolvedValue; } diff --git a/app/code/Magento/GraphQlCache/Model/Resolver/IdentityPool.php b/app/code/Magento/GraphQlCache/Model/Resolver/IdentityPool.php index 00ef8762c28ef..e08392148cb4c 100644 --- a/app/code/Magento/GraphQlCache/Model/Resolver/IdentityPool.php +++ b/app/code/Magento/GraphQlCache/Model/Resolver/IdentityPool.php @@ -42,7 +42,7 @@ public function __construct(ObjectManagerInterface $objectManager) public function get(string $identityClass): IdentityInterface { if (!isset($this->identityInstances[$identityClass])) { - $this->identityInstances[$identityClass] = $this->objectManager->create($identityClass); + $this->identityInstances[$identityClass] = $this->objectManager->get($identityClass); } return $this->identityInstances[$identityClass]; } diff --git a/app/code/Magento/GraphQlCache/Test/Unit/Model/CacheableQueryHandlerTest.php b/app/code/Magento/GraphQlCache/Test/Unit/Model/CacheableQueryHandlerTest.php index 9c1be89928215..ea3e7acf898d7 100644 --- a/app/code/Magento/GraphQlCache/Test/Unit/Model/CacheableQueryHandlerTest.php +++ b/app/code/Magento/GraphQlCache/Test/Unit/Model/CacheableQueryHandlerTest.php @@ -60,14 +60,12 @@ public function testhandleCacheFromResolverResponse( 'cacheIdentity' => IdentityInterface::class, 'cacheTag' => 'cat_p' ]; - $fieldMock = $this->createMock(Field::class); $mockIdentity = $this->getMockBuilder($cacheData['cacheIdentity']) ->setMethods(['getIdentities']) ->getMockForAbstractClass(); $this->requestMock->expects($this->once())->method('isGet')->willReturn(true); $this->identityPoolMock->expects($this->once())->method('get')->willReturn($mockIdentity); - $fieldMock->expects($this->once())->method('getCache')->willReturn($cacheData); $mockIdentity->expects($this->once()) ->method('getIdentities') ->with($resolvedData) @@ -76,7 +74,7 @@ public function testhandleCacheFromResolverResponse( $this->cacheableQueryMock->expects($this->once())->method('isCacheable')->willReturn(true); $this->cacheableQueryMock->expects($this->once())->method('setCacheValidity')->with(true); - $this->cacheableQueryHandler->handleCacheFromResolverResponse($resolvedData, $fieldMock); + $this->cacheableQueryHandler->handleCacheFromResolverResponse($resolvedData, $cacheData); } /** @@ -91,7 +89,7 @@ public function resolvedDataProvider(): array "name" => "TesName", "sku" => "TestSku" ], - "identities" => [10], + "identities" => ["cat_p", "cat_p_10"], "expectedCacheTags" => ["cat_p", "cat_p_10"] ] ]; diff --git a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls index 9e9c83b358206..498c4aec95e8f 100644 --- a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls +++ b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls @@ -181,7 +181,7 @@ type Cart { email: String @resolver (class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\CartEmail") shipping_addresses: [ShippingCartAddress]! @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\ShippingAddresses") billing_address: BillingCartAddress! @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\BillingAddress") - available_payment_methods: [AvailablePaymentMethod] @resolver(class: "Magento\\QuoteGraphQl\\Model\\Resolver\\AvailablePaymentMethods") @doc(description: "Available payment methods") + available_payment_methods: [AvailablePaymentMethod] @resolver(class: "Magento\\QuoteGraphQl\\Model\\Resolver\\AvailablePaymentMethods") @doc(description: "Available payment methods") selected_payment_method: SelectedPaymentMethod @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\SelectedPaymentMethod") prices: CartPrices @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\CartPrices") } diff --git a/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/UrlRewrite/UrlResolverIdentity.php b/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/UrlRewrite/UrlResolverIdentity.php new file mode 100644 index 0000000000000..1230d96818e13 --- /dev/null +++ b/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/UrlRewrite/UrlResolverIdentity.php @@ -0,0 +1,46 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\UrlRewriteGraphQl\Model\Resolver\UrlRewrite; + +use Magento\Framework\GraphQl\Query\Resolver\IdentityInterface; + +/** + * Get tags from url rewrite entities + */ +class UrlResolverIdentity implements IdentityInterface +{ + /** + * @var IdentityInterface[] + */ + private $urlResolverIdentities = []; + + /** + * @param IdentityInterface[] $urlResolverIdentities + */ + public function __construct( + array $urlResolverIdentities + ) { + $this->urlResolverIdentities = $urlResolverIdentities; + } + + /** + * Get tags for the corespondent url type + * + * @param array $resolvedData + * @return string[] + */ + public function getIdentities(array $resolvedData): array + { + $ids = []; + if (isset($resolvedData['type']) && isset($this->urlResolverIdentities[strtolower($resolvedData['type'])])) { + $ids = $this->urlResolverIdentities[strtolower($resolvedData['type'])] + ->getIdentities($resolvedData); + } + return $ids; + } +} diff --git a/app/code/Magento/UrlRewriteGraphQl/etc/schema.graphqls b/app/code/Magento/UrlRewriteGraphQl/etc/schema.graphqls index e9033880704ca..92d237d3f01e1 100644 --- a/app/code/Magento/UrlRewriteGraphQl/etc/schema.graphqls +++ b/app/code/Magento/UrlRewriteGraphQl/etc/schema.graphqls @@ -2,7 +2,7 @@ # See COPYING.txt for license details. type Query { - urlResolver(url: String!): EntityUrl @resolver(class: "Magento\\UrlRewriteGraphQl\\Model\\Resolver\\EntityUrl") @doc(description: "The urlResolver query returns the relative URL for a specified product, category or CMS page") @cache(cacheable: false) + urlResolver(url: String!): EntityUrl @resolver(class: "Magento\\UrlRewriteGraphQl\\Model\\Resolver\\EntityUrl") @doc(description: "The urlResolver query returns the relative URL for a specified product, category or CMS page") @cache(cacheIdentity: "Magento\\UrlRewriteGraphQl\\Model\\Resolver\\UrlRewrite\\UrlResolverIdentity") } type EntityUrl @doc(description: "EntityUrl is an output object containing the `id`, `relative_url`, and `type` attributes") { diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/UrlRewrite/UrlResolverCacheTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/UrlRewrite/UrlResolverCacheTest.php new file mode 100644 index 0000000000000..1ea3fa9ba14ac --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/UrlRewrite/UrlResolverCacheTest.php @@ -0,0 +1,216 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQl\PageCache\UrlRewrite; + +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Model\Product; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\ObjectManager; +use Magento\TestFramework\TestCase\GraphQlAbstract; +use Magento\UrlRewrite\Model\UrlFinderInterface; + +/** + * Test caching works for url resolver. + */ +class UrlResolverCacheTest extends GraphQlAbstract +{ + /** + * @inheritdoc + */ + protected function setUp() + { + $this->markTestSkipped( + 'This test will stay skipped until DEVOPS-4924 is resolved' + ); + } + + /** + * Tests that X-Magento-tags and cache debug headers are correct for product urlResolver + * + * @magentoApiDataFixture Magento/CatalogUrlRewrite/_files/product_with_category.php + */ + public function testCacheTagsForProducts() + { + $productSku = 'p002'; + $urlKey = 'p002.html'; + /** @var ProductRepositoryInterface $productRepository */ + $productRepository = ObjectManager::getInstance()->get(ProductRepositoryInterface::class); + /** @var Product $product */ + $product = $productRepository->get($productSku, false, null, true); + $urlResolverQuery = $this->getUrlResolverQuery($urlKey); + $responseMiss = $this->graphQlQueryWithResponseHeaders($urlResolverQuery); + $this->assertArrayHasKey('X-Magento-Tags', $responseMiss['headers']); + $actualTags = explode(',', $responseMiss['headers']['X-Magento-Tags']); + $expectedTags = ["cat_p", "cat_p_{$product->getId()}", "FPC"]; + $this->assertEquals($expectedTags, $actualTags); + + //cache-debug should be a MISS on first request + $this->assertArrayHasKey('X-Magento-Cache-Debug', $responseMiss['headers']); + $this->assertEquals('MISS', $responseMiss['headers']['X-Magento-Cache-Debug']); + + //cache-debug should be a HIT on second request + $responseHit = $this->graphQlQueryWithResponseHeaders($urlResolverQuery); + $this->assertArrayHasKey('X-Magento-Cache-Debug', $responseHit['headers']); + $this->assertEquals('HIT', $responseHit['headers']['X-Magento-Cache-Debug']); + //cached data should be correct + $this->assertNotEmpty($responseHit['body']); + $this->assertArrayNotHasKey('errors', $responseHit['body']); + $this->assertEquals('PRODUCT', $responseHit['body']['urlResolver']['type']); + } + /** + * Tests that X-Magento-tags and cache debug headers are correct for category urlResolver + * + * @magentoApiDataFixture Magento/CatalogUrlRewrite/_files/product_with_category.php + */ + public function testCacheTagsForCategory() + { + $categoryUrlKey = 'cat-1.html'; + $productSku = 'p002'; + /** @var ProductRepositoryInterface $productRepository */ + $productRepository = Bootstrap::getObjectManager()->get(ProductRepositoryInterface::class); + /** @var Product $product */ + $product = $productRepository->get($productSku, false, null, true); + $storeId = $product->getStoreId(); + + /** @var UrlFinderInterface $urlFinder */ + $urlFinder = Bootstrap::getObjectManager()->get(UrlFinderInterface::class); + $actualUrls = $urlFinder->findOneByData( + [ + 'request_path' => $categoryUrlKey, + 'store_id' => $storeId + ] + ); + $categoryId = $actualUrls->getEntityId(); + $query + = <<<QUERY +{ + urlResolver(url:"{$categoryUrlKey}") + { + id + relative_url + canonical_url + type + } +} +QUERY; + $responseMiss = $this->graphQlQueryWithResponseHeaders($query); + $this->assertArrayHasKey('X-Magento-Tags', $responseMiss['headers']); + $actualTags = explode(',', $responseMiss['headers']['X-Magento-Tags']); + $expectedTags = ["cat_c", "cat_c_{$categoryId}", "FPC"]; + $this->assertEquals($expectedTags, $actualTags); + + //cache-debug should be a MISS on first request + $this->assertArrayHasKey('X-Magento-Cache-Debug', $responseMiss['headers']); + $this->assertEquals('MISS', $responseMiss['headers']['X-Magento-Cache-Debug']); + + //cache-debug should be a HIT on second request + $responseHit = $this->graphQlQueryWithResponseHeaders($query); + $this->assertArrayHasKey('X-Magento-Cache-Debug', $responseHit['headers']); + $this->assertEquals('HIT', $responseHit['headers']['X-Magento-Cache-Debug']); + + //verify cached data is correct + $this->assertNotEmpty($responseHit['body']); + $this->assertArrayNotHasKey('errors', $responseHit['body']); + $this->assertEquals('CATEGORY', $responseHit['body']['urlResolver']['type']); + } + /** + * Test that X-Magento-Tags Cache debug headers are correct for cms page url resolver + * + * @magentoApiDataFixture Magento/Cms/_files/pages.php + */ + public function testUrlResolverCachingForCMSPage() + { + /** @var \Magento\Cms\Model\Page $page */ + $page = Bootstrap::getObjectManager()->get(\Magento\Cms\Model\Page::class); + $page->load('page100'); + $cmsPageId = $page->getId(); + $requestPath = $page->getIdentifier(); + $query + = <<<QUERY +{ + urlResolver(url:"{$requestPath}") + { + id + relative_url + canonical_url + type + } +} +QUERY; + $responseMiss = $this->graphQlQueryWithResponseHeaders($query); + $this->assertArrayHasKey('X-Magento-Tags', $responseMiss['headers']); + $actualTags = explode(',', $responseMiss['headers']['X-Magento-Tags']); + $expectedTags = ["cms_p", "cms_p_{$cmsPageId}", "FPC"]; + $this->assertEquals($expectedTags, $actualTags); + + //cache-debug should be a MISS on first request + $this->assertArrayHasKey('X-Magento-Cache-Debug', $responseMiss['headers']); + $this->assertEquals('MISS', $responseMiss['headers']['X-Magento-Cache-Debug']); + + //cache-debug should be a HIT on second request + $responseHit = $this->graphQlQueryWithResponseHeaders($query); + $this->assertEquals('HIT', $responseHit['headers']['X-Magento-Cache-Debug']); + + //verify cached data is correct + $this->assertNotEmpty($responseHit['body']); + $this->assertArrayNotHasKey('errors', $responseHit['body']); + $this->assertEquals('CMS_PAGE', $responseHit['body']['urlResolver']['type']); + } + /** + * Tests that cache is invalidated when url key is updated and access the original request path + * + * @magentoApiDataFixture Magento/CatalogUrlRewrite/_files/product_with_category.php + */ + public function testCacheIsInvalidatedForUrlResolver() + { + $productSku = 'p002'; + $urlKey = 'p002.html'; + $urlResolverQuery = $this->getUrlResolverQuery($urlKey); + $responseMiss = $this->graphQlQueryWithResponseHeaders($urlResolverQuery); + //cache-debug should be a MISS on first request + $this->assertEquals('MISS', $responseMiss['headers']['X-Magento-Cache-Debug']); + + //cache-debug should be a HIT on second request + $urlResolverQuery = $this->getUrlResolverQuery($urlKey); + $responseHit = $this->graphQlQueryWithResponseHeaders($urlResolverQuery); + $this->assertEquals('HIT', $responseHit['headers']['X-Magento-Cache-Debug']); + + /** @var ProductRepositoryInterface $productRepository */ + $productRepository = Bootstrap::getObjectManager()->get(ProductRepositoryInterface::class); + /** @var Product $product */ + $product = $productRepository->get($productSku, false, null, true); + $product->setUrlKey('p002-new.html')->save(); + + //cache-debug should be a MISS after updating the url key and accessing the same requestPath or urlKey + $urlResolverQuery = $this->getUrlResolverQuery($urlKey); + $responseMiss = $this->graphQlQueryWithResponseHeaders($urlResolverQuery); + $this->assertEquals('MISS', $responseMiss['headers']['X-Magento-Cache-Debug']); + } + + /** + * Get url resolver query + * + * @param $urlKey + * @return string + */ + private function getUrlResolverQuery(string $urlKey): string + { + $query = <<<QUERY +{ + urlResolver(url:"{$urlKey}") + { + id + relative_url + canonical_url + type + } +} +QUERY; + return $query; + } +} diff --git a/dev/tests/integration/testsuite/Magento/Framework/GraphQl/_files/query_array_output.php b/dev/tests/integration/testsuite/Magento/Framework/GraphQl/_files/query_array_output.php index c37632fe3e218..ae3735c251517 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/GraphQl/_files/query_array_output.php +++ b/dev/tests/integration/testsuite/Magento/Framework/GraphQl/_files/query_array_output.php @@ -34,7 +34,6 @@ 'resolver' => Magento\EavGraphQl\Model\Resolver\CustomAttributeMetadata::class, 'description' => 'Returns the attribute type, given an attribute code and entity type', 'cache' => [ - 'cacheTag' => 'cat_test', 'cacheIdentity' => Magento\EavGraphQl\Model\Resolver\CustomAttributeMetadata::class ] diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/AbstractGraphqlCacheTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/AbstractGraphqlCacheTest.php index 4cc46a8e745e8..f25144c308c68 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/AbstractGraphqlCacheTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/AbstractGraphqlCacheTest.php @@ -27,16 +27,34 @@ abstract class AbstractGraphqlCacheTest extends TestCase protected function setUp(): void { $this->objectManager = Bootstrap::getObjectManager(); - $this->usePageCachePlugin(); } /** - * Enable full page cache plugin + * Prepare a query and return a request to be used in the same test end to end + * + * @param string $query + * @return \Magento\Framework\App\Request\Http */ - protected function usePageCachePlugin(): void + protected function prepareRequest(string $query) : \Magento\Framework\App\Request\Http { - /** @var $registry \Magento\Framework\Registry */ - $registry = $this->objectManager->get(\Magento\Framework\Registry::class); - $registry->register('use_page_cache_plugin', true, true); + $cacheableQuery = $this->objectManager->get(\Magento\GraphQlCache\Model\CacheableQuery::class); + $cacheableQueryReflection = new \ReflectionProperty( + $cacheableQuery, + 'cacheTags' + ); + $cacheableQueryReflection->setAccessible(true); + $cacheableQueryReflection->setValue($cacheableQuery, []); + + /** @var \Magento\Framework\UrlInterface $urlInterface */ + $urlInterface = $this->objectManager->create(\Magento\Framework\UrlInterface::class); + //set unique URL + $urlInterface->setQueryParam('query', $query); + + $request = $this->objectManager->get(\Magento\Framework\App\Request\Http::class); + $request->setUri($urlInterface->getUrl('graphql')); + $request->setMethod('GET'); + //set the actual GET query + $request->setQueryValue('query', $query); + return $request; } } diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoriesWithProductsCacheTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoriesWithProductsCacheTest.php index 62cda28a4493a..fd97399992c1c 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoriesWithProductsCacheTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoriesWithProductsCacheTest.php @@ -91,6 +91,13 @@ public function testToCheckRequestCacheTagsForCategoryWithProducts(): void 'operationName' => 'GetCategoryWithProducts' ]; + /** @var \Magento\Framework\UrlInterface $urlInterface */ + $urlInterface = $this->objectManager->create(\Magento\Framework\UrlInterface::class); + //set unique URL + $urlInterface->setQueryParam('query', $queryParams['query']); + $urlInterface->setQueryParam('variables', $queryParams['variables']); + $urlInterface->setQueryParam('operationName', $queryParams['operationName']); + $this->request->setUri($urlInterface->getUrl('graphql')); $this->request->setPathInfo('/graphql'); $this->request->setMethod('GET'); $this->request->setParams($queryParams); diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoryCacheTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoryCacheTest.php index 96f6685233f2c..be920fb200ff3 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoryCacheTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/CategoryCacheTest.php @@ -25,11 +25,6 @@ class CategoryCacheTest extends AbstractGraphqlCacheTest */ private $graphqlController; - /** - * @var Http - */ - private $request; - /** * @inheritdoc */ @@ -37,7 +32,6 @@ protected function setUp(): void { parent::setUp(); $this->graphqlController = $this->objectManager->get(\Magento\GraphQl\Controller\GraphQl::class); - $this->request = $this->objectManager->create(Http::class); } /** * Test cache tags and debug header for category and querying only for category @@ -59,10 +53,8 @@ public function testToCheckRequestCacheTagsForForCategory(): void } } QUERY; - $this->request->setPathInfo('/graphql'); - $this->request->setMethod('GET'); - $this->request->setQueryValue('query', $query); - $response = $this->graphqlController->dispatch($this->request); + $request = $this->prepareRequest($query); + $response = $this->graphqlController->dispatch($request); $this->assertEquals('MISS', $response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); $actualCacheTags = explode(',', $response->getHeader('X-Magento-Tags')->getFieldValue()); $expectedCacheTags = ['cat_c','cat_c_' . $categoryId,'FPC']; diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/DeepNestedCategoriesAndProductsTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/DeepNestedCategoriesAndProductsTest.php index 7f992a0843f7c..746b37a88770a 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/DeepNestedCategoriesAndProductsTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/DeepNestedCategoriesAndProductsTest.php @@ -23,9 +23,6 @@ class DeepNestedCategoriesAndProductsTest extends AbstractGraphqlCacheTest /** @var \Magento\GraphQl\Controller\GraphQl */ private $graphql; - /** @var Http */ - private $request; - /** * @inheritdoc */ @@ -33,7 +30,6 @@ protected function setUp(): void { parent::setUp(); $this->graphql = $this->objectManager->get(\Magento\GraphQl\Controller\GraphQl::class); - $this->request = $this->objectManager->get(Http::class); } /** @@ -112,10 +108,8 @@ public function testDispatchForCacheHeadersOnDeepNestedQueries(): void $expectedCacheTags = array_merge($expectedCacheTags, ['cat_c_'.$uniqueCategoryId]); } - $this->request->setPathInfo('/graphql'); - $this->request->setMethod('GET'); - $this->request->setQueryValue('query', $query); - $response = $this->graphql->dispatch($this->request); + $request = $this->prepareRequest($query); + $response = $this->graphql->dispatch($request); $this->assertEquals('MISS', $response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); $actualCacheTags = explode(',', $response->getHeader('X-Magento-Tags')->getFieldValue()); $this->assertEmpty( diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/ProductsCacheTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/ProductsCacheTest.php index 78534176a3525..335067f8408df 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/ProductsCacheTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Catalog/ProductsCacheTest.php @@ -8,7 +8,6 @@ namespace Magento\GraphQlCache\Controller\Catalog; use Magento\Catalog\Api\ProductRepositoryInterface; -use Magento\Framework\App\Request\Http; use Magento\GraphQl\Controller\GraphQl; use Magento\GraphQlCache\Controller\AbstractGraphqlCacheTest; @@ -26,11 +25,6 @@ class ProductsCacheTest extends AbstractGraphqlCacheTest */ private $graphqlController; - /** - * @var Http - */ - private $request; - /** * @inheritdoc */ @@ -38,7 +32,6 @@ protected function setUp(): void { parent::setUp(); $this->graphqlController = $this->objectManager->get(\Magento\GraphQl\Controller\GraphQl::class); - $this->request = $this->objectManager->create(Http::class); } /** @@ -51,7 +44,6 @@ public function testToCheckRequestCacheTagsForProducts(): void /** @var ProductRepositoryInterface $productRepository */ $productRepository = $this->objectManager->get(ProductRepositoryInterface::class); - /** @var ProductInterface $product */ $product = $productRepository->get('simple1'); $query @@ -71,10 +63,8 @@ public function testToCheckRequestCacheTagsForProducts(): void } QUERY; - $this->request->setPathInfo('/graphql'); - $this->request->setMethod('GET'); - $this->request->setQueryValue('query', $query); - $response = $this->graphqlController->dispatch($this->request); + $request = $this->prepareRequest($query); + $response = $this->graphqlController->dispatch($request); $this->assertEquals('MISS', $response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); $actualCacheTags = explode(',', $response->getHeader('X-Magento-Tags')->getFieldValue()); $expectedCacheTags = ['cat_p', 'cat_p_' . $product->getId(), 'FPC']; @@ -103,10 +93,8 @@ public function testToCheckRequestNoTagsForProducts(): void } QUERY; - $this->request->setPathInfo('/graphql'); - $this->request->setMethod('GET'); - $this->request->setQueryValue('query', $query); - $response = $this->graphqlController->dispatch($this->request); + $request = $this->prepareRequest($query); + $response = $this->graphqlController->dispatch($request); $this->assertEquals('MISS', $response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); $actualCacheTags = explode(',', $response->getHeader('X-Magento-Tags')->getFieldValue()); $expectedCacheTags = ['FPC']; diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/BlockCacheTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/BlockCacheTest.php index 160f5f9109f30..1ee7676c85c31 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/BlockCacheTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/BlockCacheTest.php @@ -8,7 +8,6 @@ namespace Magento\GraphQlCache\Controller\Cms; use Magento\Cms\Model\BlockRepository; -use Magento\Framework\App\Request\Http; use Magento\GraphQl\Controller\GraphQl; use Magento\GraphQlCache\Controller\AbstractGraphqlCacheTest; @@ -26,11 +25,6 @@ class BlockCacheTest extends AbstractGraphqlCacheTest */ private $graphqlController; - /** - * @var Http - */ - private $request; - /** * @inheritdoc */ @@ -38,7 +32,6 @@ protected function setUp(): void { parent::setUp(); $this->graphqlController = $this->objectManager->get(\Magento\GraphQl\Controller\GraphQl::class); - $this->request = $this->objectManager->create(Http::class); } /** @@ -64,11 +57,8 @@ public function testCmsBlocksRequestHasCorrectTags(): void } } QUERY; - - $this->request->setPathInfo('/graphql'); - $this->request->setMethod('GET'); - $this->request->setQueryValue('query', $query); - $response = $this->graphqlController->dispatch($this->request); + $request = $this->prepareRequest($query); + $response = $this->graphqlController->dispatch($request); $this->assertEquals('MISS', $response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); $expectedCacheTags = ['cms_b', 'cms_b_' . $block->getId(), 'cms_b_' . $block->getIdentifier(), 'FPC']; $rawActualCacheTags = $response->getHeader('X-Magento-Tags')->getFieldValue(); diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/CmsPageCacheTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/CmsPageCacheTest.php index 8d4bbfc0f2b17..71d0caa200d49 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/CmsPageCacheTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/CmsPageCacheTest.php @@ -8,7 +8,6 @@ namespace Magento\GraphQlCache\Controller\Cms; use Magento\Cms\Model\GetPageByIdentifier; -use Magento\Framework\App\Request\Http; use Magento\GraphQl\Controller\GraphQl; use Magento\GraphQlCache\Controller\AbstractGraphqlCacheTest; @@ -27,11 +26,6 @@ class CmsPageCacheTest extends AbstractGraphqlCacheTest */ private $graphqlController; - /** - * @var Http - */ - private $request; - /** * @inheritdoc */ @@ -39,7 +33,6 @@ protected function setUp(): void { parent::setUp(); $this->graphqlController = $this->objectManager->get(\Magento\GraphQl\Controller\GraphQl::class); - $this->request = $this->objectManager->create(Http::class); } /** @@ -49,13 +42,17 @@ protected function setUp(): void */ public function testToCheckCmsPageRequestCacheTags(): void { - $cmsPage = $this->objectManager->get(GetPageByIdentifier::class)->execute('page100', 0); - $pageId = $cmsPage->getId(); + $cmsPage100 = $this->objectManager->get(GetPageByIdentifier::class)->execute('page100', 0); + $pageId100 = $cmsPage100->getId(); + + $cmsPageBlank = $this->objectManager->get(GetPageByIdentifier::class)->execute('page_design_blank', 0); + $pageIdBlank = $cmsPageBlank->getId(); - $query = + + $queryCmsPage100 = <<<QUERY { - cmsPage(id: $pageId) { + cmsPage(id: $pageId100) { url_key title content @@ -68,13 +65,65 @@ public function testToCheckCmsPageRequestCacheTags(): void } QUERY; - $this->request->setPathInfo('/graphql'); - $this->request->setMethod('GET'); - $this->request->setQueryValue('query', $query); - $response = $this->graphqlController->dispatch($this->request); - $this->assertEquals('MISS', $response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); + $queryCmsPageBlank = + <<<QUERY + { + cmsPage(id: $pageIdBlank) { + url_key + title + content + content_heading + page_layout + meta_title + meta_description + meta_keywords + } + } +QUERY; + + $request = $this->prepareRequest($queryCmsPage100); + $response = $this->graphqlController->dispatch($request); + $this->assertEquals( + 'MISS', + $response->getHeader('X-Magento-Cache-Debug')->getFieldValue(), + "expected MISS on page page100 id {$queryCmsPage100}" + ); + $requestedCacheTags = explode(',', $response->getHeader('X-Magento-Tags')->getFieldValue()); + $expectedCacheTags = ['cms_p', 'cms_p_' .$pageId100 , 'FPC']; + $this->assertEquals($expectedCacheTags, $requestedCacheTags); + + + $request = $this->prepareRequest($queryCmsPageBlank); + $response = $this->graphqlController->dispatch($request); + $this->assertEquals( + 'MISS', + $response->getHeader('X-Magento-Cache-Debug')->getFieldValue(), + "expected MISS on page pageBlank dsdss id {$pageIdBlank}" + ); + $requestedCacheTags = explode(',', $response->getHeader('X-Magento-Tags')->getFieldValue()); + $expectedCacheTags = ['cms_p', 'cms_p_' .$pageIdBlank , 'FPC']; + $this->assertEquals($expectedCacheTags, $requestedCacheTags); + + $request = $this->prepareRequest($queryCmsPage100); + $response = $this->graphqlController->dispatch($request); + $this->assertEquals( + 'HIT', + $response->getHeader('X-Magento-Cache-Debug')->getFieldValue(), + "expected HIT on page page100 id {$queryCmsPage100}" + ); + $requestedCacheTags = explode(',', $response->getHeader('X-Magento-Tags')->getFieldValue()); + $expectedCacheTags = ['cms_p', 'cms_p_' .$pageId100 , 'FPC']; + $this->assertEquals($expectedCacheTags, $requestedCacheTags); + + $request = $this->prepareRequest($queryCmsPageBlank); + $response = $this->graphqlController->dispatch($request); + $this->assertEquals( + 'HIT', + $response->getHeader('X-Magento-Cache-Debug')->getFieldValue(), + "expected HIT on page pageBlank id {$pageIdBlank}" + ); $requestedCacheTags = explode(',', $response->getHeader('X-Magento-Tags')->getFieldValue()); - $expectedCacheTags = ['cms_p', 'cms_p_' .$pageId , 'FPC']; + $expectedCacheTags = ['cms_p', 'cms_p_' .$pageIdBlank , 'FPC']; $this->assertEquals($expectedCacheTags, $requestedCacheTags); } } diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/UrlRewrite/CategoryUrlResolverCacheTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/UrlRewrite/CategoryUrlResolverCacheTest.php new file mode 100644 index 0000000000000..9070151f1ce12 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/UrlRewrite/CategoryUrlResolverCacheTest.php @@ -0,0 +1,83 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQlCache\Controller\UrlRewrite; + +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Model\Product; +use Magento\GraphQl\Controller\GraphQl; +use Magento\GraphQlCache\Controller\AbstractGraphqlCacheTest; +use Magento\UrlRewrite\Model\UrlFinderInterface; + +/** + * Test caching works for categoryUrlResolver + * + * @magentoAppArea graphql + * @magentoCache full_page enabled + * @magentoDbIsolation disabled + */ +class CategoryUrlResolverCacheTest extends AbstractGraphqlCacheTest +{ + /** + * @var GraphQl + */ + private $graphqlController; + /** + * @inheritdoc + */ + protected function setUp(): void + { + parent::setUp(); + $this->graphqlController = $this->objectManager->get(GraphQl::class); + } + + /** + * Tests that X-Magento-tags and cache debug headers are correct for category urlResolver + * + * @magentoDataFixture Magento/CatalogUrlRewrite/_files/product_with_category.php + */ + public function testCategoryUrlResolverRequestHasCorrectTags() + { + $categoryUrlKey = 'cat-1.html'; + $productSku = 'p002'; + /** @var ProductRepositoryInterface $productRepository */ + $productRepository = $this->objectManager->get(ProductRepositoryInterface::class); + /** @var Product $product */ + $product = $productRepository->get($productSku, false, null, true); + $storeId = $product->getStoreId(); + + /** @var UrlFinderInterface $urlFinder */ + $urlFinder = $this->objectManager->get(UrlFinderInterface::class); + $actualUrls = $urlFinder->findOneByData( + [ + 'request_path' => $categoryUrlKey, + 'store_id' => $storeId + ] + ); + $categoryId = $actualUrls->getEntityId(); + $query + = <<<QUERY +{ + urlResolver(url:"{$categoryUrlKey}") + { + id + relative_url, + canonical_url + type + } +} +QUERY; + $request = $this->prepareRequest($query); + /** @var \Magento\Framework\App\Response\Http $response */ + $response = $this->graphqlController->dispatch($request); + $this->assertEquals('MISS', $response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); + $expectedCacheTags = ['cat_c','cat_c_' . $categoryId, 'FPC']; + $rawActualCacheTags = $response->getHeader('X-Magento-Tags')->getFieldValue(); + $actualCacheTags = explode(',', $rawActualCacheTags); + $this->assertEquals($expectedCacheTags, $actualCacheTags); + } +} diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/UrlRewrite/CmsPageUrlResolverCacheTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/UrlRewrite/CmsPageUrlResolverCacheTest.php new file mode 100644 index 0000000000000..db9a4671e8098 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/UrlRewrite/CmsPageUrlResolverCacheTest.php @@ -0,0 +1,70 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQlCache\Controller\UrlRewrite; + +use Magento\Cms\Api\Data\PageInterface; +use Magento\Cms\Api\GetPageByIdentifierInterface; +use Magento\GraphQl\Controller\GraphQl; +use Magento\GraphQlCache\Controller\AbstractGraphqlCacheTest; + +/** + * Test caching works for cmsPage UrlResolver + * + * @magentoAppArea graphql + * @magentoCache full_page enabled + * @magentoDbIsolation disabled + */ +class CmsPageUrlResolverCacheTest extends AbstractGraphqlCacheTest +{ + /** + * @var GraphQl + */ + private $graphqlController; + + /** + * @inheritdoc + */ + protected function setUp(): void + { + parent::setUp(); + $this->graphqlController = $this->objectManager->get(GraphQl::class); + } + + /** + * @magentoDataFixture Magento/Cms/_files/pages.php + */ + public function testCmsUrlResolverRequestHasCorrectTags() + { + /** @var GetPageByIdentifierInterface $page */ + $page = $this->objectManager->get(GetPageByIdentifierInterface::class); + /** @var PageInterface $cmsPage */ + $cmsPage = $page->execute('page100', 0); + $cmsPageId = $cmsPage->getId(); + $requestPath = $cmsPage->getIdentifier(); + $query + = <<<QUERY +{ + urlResolver(url:"{$requestPath}") + { + id + relative_url + canonical_url + type + } +} +QUERY; + $request = $this->prepareRequest($query); + /** @var \Magento\Framework\App\Response\Http $response */ + $response = $this->graphqlController->dispatch($request); + $this->assertEquals('MISS', $response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); + $expectedCacheTags = ['cms_p','cms_p_' . $cmsPageId,'FPC']; + $rawActualCacheTags = $response->getHeader('X-Magento-Tags')->getFieldValue(); + $actualCacheTags = explode(',', $rawActualCacheTags); + $this->assertEquals($expectedCacheTags, $actualCacheTags); + } +} diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/UrlRewrite/ProductUrlResolverCacheTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/UrlRewrite/ProductUrlResolverCacheTest.php new file mode 100644 index 0000000000000..8162fc9a28e6d --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/UrlRewrite/ProductUrlResolverCacheTest.php @@ -0,0 +1,74 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQlCache\Controller\UrlRewrite; + +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Model\Product; +use Magento\GraphQl\Controller\GraphQl; +use Magento\GraphQlCache\Controller\AbstractGraphqlCacheTest; + +/** + * Test caching works for product urlResolver + * + * @magentoAppArea graphql + * @magentoCache full_page enabled + * @magentoDbIsolation disabled + */ +class ProductUrlResolverCacheTest extends AbstractGraphqlCacheTest +{ + /** + * @var GraphQl + */ + private $graphqlController; + + /** + * @inheritdoc + */ + protected function setUp(): void + { + parent::setUp(); + $this->graphqlController = $this->objectManager->get(GraphQl::class); + } + + /** + * Test that the correct cache tags get added to request for product urlResolver + * + * @magentoDataFixture Magento/CatalogUrlRewrite/_files/product_with_category.php + */ + public function testProductUrlResolverRequestHasCorrectTags(): void + { + $productSku = 'p002'; + $urlKey = 'p002.html'; + + /** @var ProductRepositoryInterface $productRepository */ + $productRepository = $this->objectManager->get(ProductRepositoryInterface::class); + + /** @var Product $product */ + $product = $productRepository->get($productSku, false, null, true); + + $query = <<<QUERY +{ + urlResolver(url:"{$urlKey}") + { + id + relative_url + canonical_url + type + } +} +QUERY; + $request = $this->prepareRequest($query); + /** @var \Magento\Framework\App\Response\Http $response */ + $response = $this->graphqlController->dispatch($request); + $this->assertEquals('MISS', $response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); + $expectedCacheTags = ['cat_p', 'cat_p_' . $product->getId(), 'FPC']; + $rawActualCacheTags = $response->getHeader('X-Magento-Tags')->getFieldValue(); + $actualCacheTags = explode(',', $rawActualCacheTags); + $this->assertEquals($expectedCacheTags, $actualCacheTags); + } +} diff --git a/lib/internal/Magento/Framework/GraphQl/Query/Resolver/IdentityInterface.php b/lib/internal/Magento/Framework/GraphQl/Query/Resolver/IdentityInterface.php index d65e86a37550d..943cd63417399 100644 --- a/lib/internal/Magento/Framework/GraphQl/Query/Resolver/IdentityInterface.php +++ b/lib/internal/Magento/Framework/GraphQl/Query/Resolver/IdentityInterface.php @@ -7,11 +7,16 @@ namespace Magento\Framework\GraphQl\Query\Resolver; +/** + * IdentityInterface is responsible for generating the proper tags from a cache tag and resolved data. + */ interface IdentityInterface { /** - * Get identities from resolved data + * Get identity tags from resolved data. + * + * Example: identityTag, identityTag_UniqueId. * * @param array $resolvedData * @return string[] diff --git a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/MetaReader/CacheTagReader.php b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/MetaReader/CacheAnnotationReader.php similarity index 81% rename from lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/MetaReader/CacheTagReader.php rename to lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/MetaReader/CacheAnnotationReader.php index 2613b2829e79a..6cd822cd566ba 100644 --- a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/MetaReader/CacheTagReader.php +++ b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/MetaReader/CacheAnnotationReader.php @@ -10,7 +10,7 @@ /** * Reads documentation from the annotation @cache of an AST node */ -class CacheTagReader +class CacheAnnotationReader { /** * Read documentation annotation for a specific node if exists @@ -24,12 +24,6 @@ public function read(\GraphQL\Language\AST\NodeList $directives) : array foreach ($directives as $directive) { if ($directive->name->value == 'cache') { foreach ($directive->arguments as $directiveArgument) { - if ($directiveArgument->name->value == 'cacheTag') { - $argMap = array_merge( - $argMap, - ["cacheTag" => $directiveArgument->value->value] - ); - } if ($directiveArgument->name->value == 'cacheable') { $argMap = array_merge( $argMap, diff --git a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/MetaReader/FieldMetaReader.php b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/MetaReader/FieldMetaReader.php index 554d2636cf8c3..7438a4e3da932 100644 --- a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/MetaReader/FieldMetaReader.php +++ b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/MetaReader/FieldMetaReader.php @@ -23,24 +23,24 @@ class FieldMetaReader private $docReader; /** - * @var CacheTagReader + * @var CacheAnnotationReader */ - private $cacheTagReader; + private $cacheAnnotationReader; /** * @param TypeMetaWrapperReader $typeMetaReader * @param DocReader $docReader - * @param CacheTagReader|null $cacheTagReader + * @param CacheAnnotationReader|null $cacheAnnotationReader */ public function __construct( TypeMetaWrapperReader $typeMetaReader, DocReader $docReader, - CacheTagReader $cacheTagReader = null + CacheAnnotationReader $cacheAnnotationReader = null ) { $this->typeMetaReader = $typeMetaReader; $this->docReader = $docReader; - $this->cacheTagReader = $cacheTagReader ?? \Magento\Framework\App\ObjectManager::getInstance() - ->get(CacheTagReader::class); + $this->cacheAnnotationReader = $cacheAnnotationReader ?? \Magento\Framework\App\ObjectManager::getInstance() + ->get(CacheAnnotationReader::class); } /** @@ -73,7 +73,7 @@ public function read(\GraphQL\Type\Definition\FieldDefinition $fieldMeta) : arra } if ($this->docReader->read($fieldMeta->astNode->directives)) { - $result['cache'] = $this->cacheTagReader->read($fieldMeta->astNode->directives); + $result['cache'] = $this->cacheAnnotationReader->read($fieldMeta->astNode->directives); } $arguments = $fieldMeta->args; diff --git a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/InputObjectType.php b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/InputObjectType.php index 2eda79ce68b04..38159fac03b3b 100644 --- a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/InputObjectType.php +++ b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/InputObjectType.php @@ -10,7 +10,7 @@ use Magento\Framework\GraphQlSchemaStitching\GraphQlReader\TypeMetaReaderInterface; use Magento\Framework\GraphQlSchemaStitching\GraphQlReader\MetaReader\TypeMetaWrapperReader; use Magento\Framework\GraphQlSchemaStitching\GraphQlReader\MetaReader\DocReader; -use Magento\Framework\GraphQlSchemaStitching\GraphQlReader\MetaReader\CacheTagReader; +use Magento\Framework\GraphQlSchemaStitching\GraphQlReader\MetaReader\CacheAnnotationReader; /** * Composite configuration reader to handle the input object type meta @@ -28,24 +28,24 @@ class InputObjectType implements TypeMetaReaderInterface private $docReader; /** - * @var CacheTagReader + * @var CacheAnnotationReader */ - private $cacheTagReader; + private $cacheAnnotationReader; /** * @param TypeMetaWrapperReader $typeMetaReader * @param DocReader $docReader - * @param CacheTagReader|null $cacheTagReader + * @param CacheAnnotationReader|null $cacheAnnotationReader */ public function __construct( TypeMetaWrapperReader $typeMetaReader, DocReader $docReader, - CacheTagReader $cacheTagReader = null + CacheAnnotationReader $cacheAnnotationReader = null ) { $this->typeMetaReader = $typeMetaReader; $this->docReader = $docReader; - $this->cacheTagReader = $cacheTagReader ?? \Magento\Framework\App\ObjectManager::getInstance() - ->get(CacheTagReader::class); + $this->cacheAnnotationReader = $cacheAnnotationReader ?? \Magento\Framework\App\ObjectManager::getInstance() + ->get(CacheAnnotationReader::class); } /** @@ -70,7 +70,7 @@ public function read(\GraphQL\Type\Definition\Type $typeMeta) : array } if ($this->docReader->read($typeMeta->astNode->directives)) { - $result['cache'] = $this->cacheTagReader->read($typeMeta->astNode->directives); + $result['cache'] = $this->cacheAnnotationReader->read($typeMeta->astNode->directives); } return $result; } else { diff --git a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/InterfaceType.php b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/InterfaceType.php index 7c040cd2e104c..baadb4be61cf2 100644 --- a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/InterfaceType.php +++ b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/InterfaceType.php @@ -10,7 +10,7 @@ use Magento\Framework\GraphQlSchemaStitching\GraphQlReader\TypeMetaReaderInterface; use Magento\Framework\GraphQlSchemaStitching\GraphQlReader\MetaReader\FieldMetaReader; use Magento\Framework\GraphQlSchemaStitching\GraphQlReader\MetaReader\DocReader; -use Magento\Framework\GraphQlSchemaStitching\GraphQlReader\MetaReader\CacheTagReader; +use Magento\Framework\GraphQlSchemaStitching\GraphQlReader\MetaReader\CacheAnnotationReader; /** * Composite configuration reader to handle the interface object type meta @@ -28,24 +28,24 @@ class InterfaceType implements TypeMetaReaderInterface private $docReader; /** - * @var CacheTagReader + * @var CacheAnnotationReader */ - private $cacheTagReader; + private $cacheAnnotationReader; /** * @param FieldMetaReader $fieldMetaReader * @param DocReader $docReader - * @param CacheTagReader|null $cacheTagReader + * @param CacheAnnotationReader|null $cacheAnnotationReader */ public function __construct( FieldMetaReader $fieldMetaReader, DocReader $docReader, - CacheTagReader $cacheTagReader = null + CacheAnnotationReader $cacheAnnotationReader = null ) { $this->fieldMetaReader = $fieldMetaReader; $this->docReader = $docReader; - $this->cacheTagReader = $cacheTagReader ?? \Magento\Framework\App\ObjectManager::getInstance() - ->get(CacheTagReader::class); + $this->cacheAnnotationReader = $cacheAnnotationReader ?? \Magento\Framework\App\ObjectManager::getInstance() + ->get(CacheAnnotationReader::class); } /** @@ -76,7 +76,7 @@ public function read(\GraphQL\Type\Definition\Type $typeMeta) : array } if ($this->docReader->read($typeMeta->astNode->directives)) { - $result['cache'] = $this->cacheTagReader->read($typeMeta->astNode->directives); + $result['cache'] = $this->cacheAnnotationReader->read($typeMeta->astNode->directives); } return $result; diff --git a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/ObjectType.php b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/ObjectType.php index 77a44460f00ae..7614c4954091d 100644 --- a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/ObjectType.php +++ b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/ObjectType.php @@ -11,7 +11,7 @@ use Magento\Framework\GraphQlSchemaStitching\GraphQlReader\MetaReader\FieldMetaReader; use Magento\Framework\GraphQlSchemaStitching\GraphQlReader\MetaReader\DocReader; use Magento\Framework\GraphQlSchemaStitching\GraphQlReader\MetaReader\ImplementsReader; -use Magento\Framework\GraphQlSchemaStitching\GraphQlReader\MetaReader\CacheTagReader; +use Magento\Framework\GraphQlSchemaStitching\GraphQlReader\MetaReader\CacheAnnotationReader; /** * Composite configuration reader to handle the object type meta @@ -34,28 +34,28 @@ class ObjectType implements TypeMetaReaderInterface private $implementsAnnotation; /** - * @var CacheTagReader + * @var CacheAnnotationReader */ - private $cacheTagReader; + private $cacheAnnotationReader; /** * ObjectType constructor. * @param FieldMetaReader $fieldMetaReader * @param DocReader $docReader * @param ImplementsReader $implementsAnnotation - * @param CacheTagReader|null $cacheTagReader + * @param CacheAnnotationReader|null $cacheAnnotationReader */ public function __construct( FieldMetaReader $fieldMetaReader, DocReader $docReader, ImplementsReader $implementsAnnotation, - CacheTagReader $cacheTagReader = null + CacheAnnotationReader $cacheAnnotationReader = null ) { $this->fieldMetaReader = $fieldMetaReader; $this->docReader = $docReader; $this->implementsAnnotation = $implementsAnnotation; - $this->cacheTagReader = $cacheTagReader ?? \Magento\Framework\App\ObjectManager::getInstance() - ->get(CacheTagReader::class); + $this->cacheAnnotationReader = $cacheAnnotationReader ?? \Magento\Framework\App\ObjectManager::getInstance() + ->get(CacheAnnotationReader::class); } /** @@ -89,7 +89,7 @@ public function read(\GraphQL\Type\Definition\Type $typeMeta) : array } if ($this->docReader->read($typeMeta->astNode->directives)) { - $result['cache'] = $this->cacheTagReader->read($typeMeta->astNode->directives); + $result['cache'] = $this->cacheAnnotationReader->read($typeMeta->astNode->directives); } return $result; From 58d082d750b7c750539fe5c04c35f9fd3df0f23b Mon Sep 17 00:00:00 2001 From: Cristian Partica <cpartica@magento.com> Date: Thu, 2 May 2019 15:38:36 -0500 Subject: [PATCH 338/773] MC-15959: Implement caching for url resolver - fix static --- .../Magento/GraphQlCache/Controller/Cms/CmsPageCacheTest.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/CmsPageCacheTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/CmsPageCacheTest.php index 71d0caa200d49..dd51c6d0ce4ad 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/CmsPageCacheTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/CmsPageCacheTest.php @@ -48,7 +48,6 @@ public function testToCheckCmsPageRequestCacheTags(): void $cmsPageBlank = $this->objectManager->get(GetPageByIdentifier::class)->execute('page_design_blank', 0); $pageIdBlank = $cmsPageBlank->getId(); - $queryCmsPage100 = <<<QUERY { @@ -91,8 +90,7 @@ public function testToCheckCmsPageRequestCacheTags(): void $requestedCacheTags = explode(',', $response->getHeader('X-Magento-Tags')->getFieldValue()); $expectedCacheTags = ['cms_p', 'cms_p_' .$pageId100 , 'FPC']; $this->assertEquals($expectedCacheTags, $requestedCacheTags); - - + $request = $this->prepareRequest($queryCmsPageBlank); $response = $this->graphqlController->dispatch($request); $this->assertEquals( From 13566b0d109f3a3fe1aa75ab6b9fba5b0df75757 Mon Sep 17 00:00:00 2001 From: Tom Reece <treece@adobe.com> Date: Thu, 2 May 2019 16:24:46 -0500 Subject: [PATCH 339/773] MC-4459: Convert OnePageCheckoutOfflinePaymentMethodsTest to MFTF - Remove duplicate element --- .../Checkout/Test/Mftf/Section/CheckoutPaymentSection.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutPaymentSection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutPaymentSection.xml index 893d313409782..11dba6500890f 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutPaymentSection.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutPaymentSection.xml @@ -25,7 +25,6 @@ <element name="guestRegion" type="select" selector=".billing-address-form select[name*='region_id']"/> <element name="guestPostcode" type="input" selector=".billing-address-form input[name*='postcode']"/> <element name="guestTelephone" type="input" selector=".billing-address-form input[name*='telephone']"/> - <element name="guestCountry" type="select" selector=".billing-address-form select[name*='country_id']"/> <element name="billingAddress" type="text" selector=".payment-method._active div.billing-address-details"/> <element name="cartItems" type="text" selector="ol.minicart-items"/> <element name="cartItemsArea" type="button" selector="div.block.items-in-cart"/> From 3f7c3300c46787be154302e0d8d9d9555d811709 Mon Sep 17 00:00:00 2001 From: Cristian Partica <cpartica@magento.com> Date: Thu, 2 May 2019 16:27:18 -0500 Subject: [PATCH 340/773] MC-15959: Implement caching for url resolver - fix static --- .../UrlRewrite/UrlResolverCacheTest.php | 27 +++---------------- .../Controller/Cms/CmsPageCacheTest.php | 2 +- 2 files changed, 4 insertions(+), 25 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/UrlRewrite/UrlResolverCacheTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/UrlRewrite/UrlResolverCacheTest.php index 1ea3fa9ba14ac..1cf33184714d9 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/UrlRewrite/UrlResolverCacheTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/UrlRewrite/UrlResolverCacheTest.php @@ -86,18 +86,7 @@ public function testCacheTagsForCategory() ] ); $categoryId = $actualUrls->getEntityId(); - $query - = <<<QUERY -{ - urlResolver(url:"{$categoryUrlKey}") - { - id - relative_url - canonical_url - type - } -} -QUERY; + $query = $this->getUrlResolverQuery($categoryUrlKey); $responseMiss = $this->graphQlQueryWithResponseHeaders($query); $this->assertArrayHasKey('X-Magento-Tags', $responseMiss['headers']); $actualTags = explode(',', $responseMiss['headers']['X-Magento-Tags']); @@ -130,18 +119,8 @@ public function testUrlResolverCachingForCMSPage() $page->load('page100'); $cmsPageId = $page->getId(); $requestPath = $page->getIdentifier(); - $query - = <<<QUERY -{ - urlResolver(url:"{$requestPath}") - { - id - relative_url - canonical_url - type - } -} -QUERY; + + $query = $this->getUrlResolverQuery($requestPath); $responseMiss = $this->graphQlQueryWithResponseHeaders($query); $this->assertArrayHasKey('X-Magento-Tags', $responseMiss['headers']); $actualTags = explode(',', $responseMiss['headers']['X-Magento-Tags']); diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/CmsPageCacheTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/CmsPageCacheTest.php index dd51c6d0ce4ad..e3d6259d32d40 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/CmsPageCacheTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/CmsPageCacheTest.php @@ -96,7 +96,7 @@ public function testToCheckCmsPageRequestCacheTags(): void $this->assertEquals( 'MISS', $response->getHeader('X-Magento-Cache-Debug')->getFieldValue(), - "expected MISS on page pageBlank dsdss id {$pageIdBlank}" + "expected MISS on page pageBlank id {$pageIdBlank}" ); $requestedCacheTags = explode(',', $response->getHeader('X-Magento-Tags')->getFieldValue()); $expectedCacheTags = ['cms_p', 'cms_p_' .$pageIdBlank , 'FPC']; From f661404e6f142edc42713cbcd7312092f75ca973 Mon Sep 17 00:00:00 2001 From: Max Lesechko <mlesechko@magento.com> Date: Thu, 2 May 2019 16:38:31 -0500 Subject: [PATCH 341/773] MC-16106: [2.3] Failed UI upgrade --- app/code/Magento/Authorization/Model/Role.php | 14 +- .../Magento/Backend/Model/Auth/Session.php | 198 +------------ .../Backend/Model/Auth/SessionAclHydrator.php | 36 --- .../Model/Auth/SessionUserHydrator.php | 54 ---- .../Spi/SessionAclHydratorInterface.php | 34 --- .../Spi/SessionUserHydratorInterface.php | 34 --- .../Test/Unit/Model/Auth/SessionTest.php | 273 ++++++++++++++++++ .../Model/Authorization/RoleLocatorTest.php | 36 +++ .../Test/Unit/Model/Locale/ManagerTest.php | 127 ++++++++ app/code/Magento/Backend/composer.json | 1 - app/code/Magento/Backend/etc/di.xml | 4 - .../Model/ResourceModel/Eav/Attribute.php | 10 - .../Config/Model/Config/Backend/Encrypted.php | 12 - .../Product/Type/Configurable/Attribute.php | 49 ++-- .../Configurable/Attribute/Collection.php | 14 - app/code/Magento/Customer/Model/Attribute.php | 10 - .../Magento/Eav/Model/Entity/Attribute.php | 14 +- .../Entity/Attribute/AbstractAttribute.php | 10 - .../Model/ResourceModel/Entity/Attribute.php | 10 - .../System/Config/Fieldset/GroupTest.php | 107 +++++++ .../Condition/CanViewNotificationTest.php | 16 +- app/code/Magento/Store/Model/Store.php | 10 - app/code/Magento/User/Model/User.php | 14 - .../AdminSessionUserContextTest.php | 89 ++++++ .../Magento/User/Test/Unit/Model/UserTest.php | 25 ++ .../Backend/Model/Auth/SessionTest.php | 39 +-- .../Backend/Model/Locale/ResolverTest.php | 15 +- .../Rule/Design/SerializationAware.php | 34 --- .../resources/rulesets/design.xml | 25 -- .../Magento/Test/Php/_files/phpmd/ruleset.xml | 1 - .../Magento/Framework/App/AreaList/Proxy.php | 18 +- .../Magento/Framework/App/Response/Http.php | 25 +- .../App/Route/ConfigInterface/Proxy.php | 12 - .../App/Test/Unit/Response/HttpTest.php | 39 +++ lib/internal/Magento/Framework/DB/Select.php | 22 +- .../Framework/DB/Select/RendererProxy.php | 14 +- .../Magento/Framework/Data/Collection.php | 10 - .../Framework/Data/Collection/AbstractDb.php | 10 - .../DataObject/Copy/Config/Data/Proxy.php | 18 +- .../Framework/Interception/Interceptor.php | 10 - .../Model/AbstractExtensibleModel.php | 18 +- .../Magento/Framework/Model/AbstractModel.php | 10 - .../Model/ResourceModel/Db/AbstractDb.php | 23 +- .../Db/Collection/AbstractCollection.php | 10 - .../Framework/Mview/Config/Data/Proxy.php | 16 +- .../Framework/Translate/Inline/Proxy.php | 12 - .../Magento/Framework/View/Layout/Proxy.php | 128 ++++---- 47 files changed, 826 insertions(+), 884 deletions(-) delete mode 100644 app/code/Magento/Backend/Model/Auth/SessionAclHydrator.php delete mode 100644 app/code/Magento/Backend/Model/Auth/SessionUserHydrator.php delete mode 100644 app/code/Magento/Backend/Spi/SessionAclHydratorInterface.php delete mode 100644 app/code/Magento/Backend/Spi/SessionUserHydratorInterface.php create mode 100644 app/code/Magento/Backend/Test/Unit/Model/Auth/SessionTest.php create mode 100644 app/code/Magento/Backend/Test/Unit/Model/Authorization/RoleLocatorTest.php create mode 100644 app/code/Magento/Backend/Test/Unit/Model/Locale/ManagerTest.php create mode 100644 app/code/Magento/Paypal/Test/Unit/Block/Adminhtml/System/Config/Fieldset/GroupTest.php create mode 100644 app/code/Magento/User/Test/Unit/Model/Authorization/AdminSessionUserContextTest.php delete mode 100644 dev/tests/static/framework/Magento/CodeMessDetector/Rule/Design/SerializationAware.php diff --git a/app/code/Magento/Authorization/Model/Role.php b/app/code/Magento/Authorization/Model/Role.php index dcc46ee77ee12..2546df86d09dd 100644 --- a/app/code/Magento/Authorization/Model/Role.php +++ b/app/code/Magento/Authorization/Model/Role.php @@ -51,29 +51,19 @@ public function __construct( } /** - * @inheritDoc - * - * @SuppressWarnings(PHPMD.SerializationAware) - * @deprecated Do not use PHP serialization. + * {@inheritdoc} */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); - $properties = parent::__sleep(); return array_diff($properties, ['_resource', '_resourceCollection']); } /** - * @inheritDoc - * - * @SuppressWarnings(PHPMD.SerializationAware) - * @deprecated Do not use PHP serialization. + * {@inheritdoc} */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); - parent::__wakeup(); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); $this->_resource = $objectManager->get(\Magento\Authorization\Model\ResourceModel\Role::class); diff --git a/app/code/Magento/Backend/Model/Auth/Session.php b/app/code/Magento/Backend/Model/Auth/Session.php index 61db71c1803e2..593b4219d45f0 100644 --- a/app/code/Magento/Backend/Model/Auth/Session.php +++ b/app/code/Magento/Backend/Model/Auth/Session.php @@ -5,25 +5,21 @@ */ namespace Magento\Backend\Model\Auth; -use Magento\Framework\Acl; -use Magento\Framework\AclFactory; -use Magento\Framework\App\ObjectManager; use Magento\Framework\Stdlib\Cookie\CookieMetadataFactory; use Magento\Framework\Stdlib\CookieManagerInterface; -use Magento\Backend\Spi\SessionUserHydratorInterface; -use Magento\Backend\Spi\SessionAclHydratorInterface; -use Magento\User\Model\User; -use Magento\User\Model\UserFactory; /** * Backend Auth session model * * @api + * @method \Magento\User\Model\User|null getUser() + * @method \Magento\Backend\Model\Auth\Session setUser(\Magento\User\Model\User $value) + * @method \Magento\Framework\Acl|null getAcl() + * @method \Magento\Backend\Model\Auth\Session setAcl(\Magento\Framework\Acl $value) * @method int getUpdatedAt() * @method \Magento\Backend\Model\Auth\Session setUpdatedAt(int $value) * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) - * @SuppressWarnings(PHPMD.CookieAndSessionMisuse) * @todo implement solution that keeps is_first_visit flag in session during redirects * @api * @since 100.0.2 @@ -59,36 +55,6 @@ class Session extends \Magento\Framework\Session\SessionManager implements \Mage */ protected $_config; - /** - * @var SessionUserHydratorInterface - */ - private $userHydrator; - - /** - * @var SessionAclHydratorInterface - */ - private $aclHydrator; - - /** - * @var UserFactory - */ - private $userFactory; - - /** - * @var AclFactory - */ - private $aclFactory; - - /** - * @var User|null - */ - private $user; - - /** - * @var Acl|null - */ - private $acl; - /** * @param \Magento\Framework\App\Request\Http $request * @param \Magento\Framework\Session\SidResolverInterface $sidResolver @@ -103,10 +69,6 @@ class Session extends \Magento\Framework\Session\SessionManager implements \Mage * @param \Magento\Backend\Model\UrlInterface $backendUrl * @param \Magento\Backend\App\ConfigInterface $config * @throws \Magento\Framework\Exception\SessionException - * @param SessionUserHydratorInterface|null $userHydrator - * @param SessionAclHydratorInterface|null $aclHydrator - * @param UserFactory|null $userFactory - * @param AclFactory|null $aclFactory * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -121,19 +83,11 @@ public function __construct( \Magento\Framework\App\State $appState, \Magento\Framework\Acl\Builder $aclBuilder, \Magento\Backend\Model\UrlInterface $backendUrl, - \Magento\Backend\App\ConfigInterface $config, - ?SessionUserHydratorInterface $userHydrator = null, - ?SessionAclHydratorInterface $aclHydrator = null, - ?UserFactory $userFactory = null, - ?AclFactory $aclFactory = null + \Magento\Backend\App\ConfigInterface $config ) { $this->_config = $config; $this->_aclBuilder = $aclBuilder; $this->_backendUrl = $backendUrl; - $this->userHydrator = $userHydrator ?? ObjectManager::getInstance()->get(SessionUserHydratorInterface::class); - $this->aclHydrator = $aclHydrator ?? ObjectManager::getInstance()->get(SessionAclHydratorInterface::class); - $this->userFactory = $userFactory ?? ObjectManager::getInstance()->get(UserFactory::class); - $this->aclFactory = $aclFactory ?? ObjectManager::getInstance()->get(AclFactory::class); parent::__construct( $request, $sidResolver, @@ -276,16 +230,6 @@ public function processLogin() return $this; } - /** - * @inheritDoc - */ - public function destroy(array $options = null) - { - $this->user = null; - $this->acl = null; - parent::destroy($options); - } - /** * Process of configuring of current auth storage when logout was performed * @@ -309,136 +253,4 @@ public function isValidForPath($path) { return true; } - - /** - * Logged-in user. - * - * @return User|null - */ - public function getUser() - { - if (!$this->user) { - $userData = $this->getUserData(); - if ($userData) { - /** @var User $user */ - $user = $this->userFactory->create(); - $this->userHydrator->hydrate($user, $userData); - $this->user = $user; - } - } - - return $this->user; - } - - /** - * Set logged-in user instance. - * - * @param User|null $user - * @return Session - */ - public function setUser($user) - { - $this->setUserData(null); - if ($user) { - $this->setUserData($this->userHydrator->extract($user)); - } - $this->user = $user; - - return $this; - } - - /** - * Is user logged in? - * - * @return bool - */ - public function hasUser() - { - return $this->user || $this->hasUserData(); - } - - /** - * Remove logged-in user. - * - * @return Session - */ - public function unsUser() - { - $this->user = null; - return $this->unsUserData(); - } - - /** - * Logged-in user's ACL data. - * - * @return Acl|null - */ - public function getAcl() - { - if (!$this->acl) { - $aclData = $this->getUserAclData(); - if ($aclData) { - /** @var Acl $acl */ - $acl = $this->aclFactory->create(); - $this->aclHydrator->hydrate($acl, $aclData); - $this->acl = $acl; - } - } - - return $this->acl; - } - - /** - * Set logged-in user's ACL data instance. - * - * @param Acl|null $acl - * @return Session - */ - public function setAcl($acl) - { - $this->setUserAclData(null); - if ($acl) { - $this->setUserAclData($this->aclHydrator->extract($acl)); - } - $this->acl = $acl; - - return $this; - } - - /** - * Whether ACL data is present. - * - * @return bool - */ - public function hasAcl() - { - return $this->acl || $this->hasUserAclData(); - } - - /** - * Remove ACL data. - * - * @return Session - */ - public function unsAcl() - { - $this->acl = null; - return $this->unsUserAclData(); - } - - /** - * @inheritDoc - */ - public function writeClose() - { - //Updating data in session in case these objects has been changed. - if ($this->user) { - $this->setUser($this->user); - } - if ($this->acl) { - $this->setAcl($this->acl); - } - - parent::writeClose(); - } } diff --git a/app/code/Magento/Backend/Model/Auth/SessionAclHydrator.php b/app/code/Magento/Backend/Model/Auth/SessionAclHydrator.php deleted file mode 100644 index 34e01be696672..0000000000000 --- a/app/code/Magento/Backend/Model/Auth/SessionAclHydrator.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -declare(strict_types=1); - -namespace Magento\Backend\Model\Auth; - -use Magento\Backend\Spi\SessionAclHydratorInterface; -use Magento\Framework\Acl; - -/** - * @inheritDoc - */ -class SessionAclHydrator extends Acl implements SessionAclHydratorInterface -{ - /** - * @inheritDoc - */ - public function extract(Acl $acl): array - { - return ['rules' => $acl->_rules, 'resources' => $acl->_resources, 'roles' => $acl->_roleRegistry]; - } - - /** - * @inheritDoc - */ - public function hydrate(Acl $target, array $data): void - { - $target->_rules = $data['rules']; - $target->_resources = $data['resources']; - $target->_roleRegistry = $data['roles']; - } -} diff --git a/app/code/Magento/Backend/Model/Auth/SessionUserHydrator.php b/app/code/Magento/Backend/Model/Auth/SessionUserHydrator.php deleted file mode 100644 index 6dee8b7b302c8..0000000000000 --- a/app/code/Magento/Backend/Model/Auth/SessionUserHydrator.php +++ /dev/null @@ -1,54 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -declare(strict_types=1); - -namespace Magento\Backend\Model\Auth; - -use Magento\Backend\Spi\SessionUserHydratorInterface; -use Magento\User\Model\User; -use Magento\Authorization\Model\Role; -use Magento\Authorization\Model\RoleFactory; - -/** - * @inheritDoc - */ -class SessionUserHydrator implements SessionUserHydratorInterface -{ - /** - * @var RoleFactory - */ - private $roleFactory; - - /** - * @param RoleFactory $roleFactory - */ - public function __construct(RoleFactory $roleFactory) - { - $this->roleFactory = $roleFactory; - } - - /** - * @inheritDoc - */ - public function extract(User $user): array - { - return ['data' => $user->getData(), 'role_data' => $user->getRole()->getData()]; - } - - /** - * @inheritDoc - */ - public function hydrate(User $target, array $data): void - { - $target->setData($data['data']); - /** @var Role $role */ - $role = $this->roleFactory->create(); - $role->setData($data['role_data']); - $target->setData('extracted_role', $role); - $target->getRole(); - } -} diff --git a/app/code/Magento/Backend/Spi/SessionAclHydratorInterface.php b/app/code/Magento/Backend/Spi/SessionAclHydratorInterface.php deleted file mode 100644 index 7227cc92fcc8e..0000000000000 --- a/app/code/Magento/Backend/Spi/SessionAclHydratorInterface.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -declare(strict_types=1); - -namespace Magento\Backend\Spi; - -use Magento\Framework\Acl; - -/** - * Extract/hydrate user's ACL data to/from session. - */ -interface SessionAclHydratorInterface -{ - /** - * Extract ACL data to store in session. - * - * @param Acl $acl - * @return array Array of scalars. - */ - public function extract(Acl $acl): array; - - /** - * Fill ACL object with data from session. - * - * @param Acl $target - * @param array $data Data from session. - * @return void - */ - public function hydrate(Acl $target, array $data): void; -} diff --git a/app/code/Magento/Backend/Spi/SessionUserHydratorInterface.php b/app/code/Magento/Backend/Spi/SessionUserHydratorInterface.php deleted file mode 100644 index 211c7b01df3be..0000000000000 --- a/app/code/Magento/Backend/Spi/SessionUserHydratorInterface.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -declare(strict_types=1); - -namespace Magento\Backend\Spi; - -use Magento\User\Model\User; - -/** - * Extract/hydrate user data to/from session. - */ -interface SessionUserHydratorInterface -{ - /** - * Extract user data to store in session. - * - * @param User $user - * @return array Array of scalars. - */ - public function extract(User $user): array; - - /** - * Fill User object with data from session. - * - * @param User $target - * @param array $data Data from session. - * @return void - */ - public function hydrate(User $target, array $data): void; -} diff --git a/app/code/Magento/Backend/Test/Unit/Model/Auth/SessionTest.php b/app/code/Magento/Backend/Test/Unit/Model/Auth/SessionTest.php new file mode 100644 index 0000000000000..f1a4bc355b08e --- /dev/null +++ b/app/code/Magento/Backend/Test/Unit/Model/Auth/SessionTest.php @@ -0,0 +1,273 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Backend\Test\Unit\Model\Auth; + +use Magento\Backend\Model\Auth\Session; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; + +/** + * Class SessionTest tests Magento\Backend\Model\Auth\Session + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class SessionTest extends \PHPUnit\Framework\TestCase +{ + /** + * @var \Magento\Backend\App\Config | \PHPUnit_Framework_MockObject_MockObject + */ + protected $config; + + /** + * @var \Magento\Framework\Session\Config | \PHPUnit_Framework_MockObject_MockObject + */ + protected $sessionConfig; + + /** + * @var \Magento\Framework\Stdlib\CookieManagerInterface | \PHPUnit_Framework_MockObject_MockObject + */ + protected $cookieManager; + + /** + * @var \Magento\Framework\Stdlib\Cookie\CookieMetadataFactory | \PHPUnit_Framework_MockObject_MockObject + */ + protected $cookieMetadataFactory; + + /** + * @var \Magento\Framework\Session\Storage | \PHPUnit_Framework_MockObject_MockObject + */ + protected $storage; + + /** + * @var \Magento\Framework\Acl\Builder | \PHPUnit_Framework_MockObject_MockObject + */ + protected $aclBuilder; + + /** + * @var Session + */ + protected $session; + + protected function setUp() + { + $this->cookieMetadataFactory = $this->createPartialMock( + \Magento\Framework\Stdlib\Cookie\CookieMetadataFactory::class, + ['createPublicCookieMetadata'] + ); + + $this->config = $this->createPartialMock(\Magento\Backend\App\Config::class, ['getValue']); + $this->cookieManager = $this->createPartialMock( + \Magento\Framework\Stdlib\Cookie\PhpCookieManager::class, + ['getCookie', 'setPublicCookie'] + ); + $this->storage = $this->createPartialMock( + \Magento\Framework\Session\Storage::class, + ['getUser', 'getAcl', 'setAcl'] + ); + $this->sessionConfig = $this->createPartialMock( + \Magento\Framework\Session\Config::class, + ['getCookiePath', 'getCookieDomain', 'getCookieSecure', 'getCookieHttpOnly'] + ); + $this->aclBuilder = $this->getMockBuilder(\Magento\Framework\Acl\Builder::class) + ->disableOriginalConstructor() + ->getMock(); + $objectManager = new ObjectManager($this); + $this->session = $objectManager->getObject( + \Magento\Backend\Model\Auth\Session::class, + [ + 'config' => $this->config, + 'sessionConfig' => $this->sessionConfig, + 'cookieManager' => $this->cookieManager, + 'cookieMetadataFactory' => $this->cookieMetadataFactory, + 'storage' => $this->storage, + 'aclBuilder' => $this->aclBuilder + ] + ); + } + + protected function tearDown() + { + $this->config = null; + $this->sessionConfig = null; + $this->session = null; + } + + /** + * @dataProvider refreshAclDataProvider + * @param $isUserPassedViaParams + */ + public function testRefreshAcl($isUserPassedViaParams) + { + $aclMock = $this->getMockBuilder(\Magento\Framework\Acl::class)->disableOriginalConstructor()->getMock(); + $this->aclBuilder->expects($this->any())->method('getAcl')->willReturn($aclMock); + $userMock = $this->getMockBuilder(\Magento\User\Model\User::class) + ->setMethods(['getReloadAclFlag', 'setReloadAclFlag', 'unsetData', 'save']) + ->disableOriginalConstructor() + ->getMock(); + $userMock->expects($this->any())->method('getReloadAclFlag')->willReturn(true); + $userMock->expects($this->once())->method('setReloadAclFlag')->with('0')->willReturnSelf(); + $userMock->expects($this->once())->method('save'); + $this->storage->expects($this->once())->method('setAcl')->with($aclMock); + $this->storage->expects($this->any())->method('getAcl')->willReturn($aclMock); + if ($isUserPassedViaParams) { + $this->session->refreshAcl($userMock); + } else { + $this->storage->expects($this->once())->method('getUser')->willReturn($userMock); + $this->session->refreshAcl(); + } + $this->assertSame($aclMock, $this->session->getAcl()); + } + + /** + * @return array + */ + public function refreshAclDataProvider() + { + return [ + 'User set via params' => [true], + 'User set to session object' => [false] + ]; + } + + public function testIsLoggedInPositive() + { + $user = $this->createPartialMock(\Magento\User\Model\User::class, ['getId', '__wakeup']); + $user->expects($this->once()) + ->method('getId') + ->will($this->returnValue(1)); + + $this->storage->expects($this->any()) + ->method('getUser') + ->will($this->returnValue($user)); + + $this->assertTrue($this->session->isLoggedIn()); + } + + public function testProlong() + { + $name = session_name(); + $cookie = 'cookie'; + $lifetime = 900; + $path = '/'; + $domain = 'magento2'; + $secure = true; + $httpOnly = true; + + $this->config->expects($this->once()) + ->method('getValue') + ->with(\Magento\Backend\Model\Auth\Session::XML_PATH_SESSION_LIFETIME) + ->willReturn($lifetime); + $cookieMetadata = $this->createMock(\Magento\Framework\Stdlib\Cookie\PublicCookieMetadata::class); + $cookieMetadata->expects($this->once()) + ->method('setDuration') + ->with($lifetime) + ->will($this->returnSelf()); + $cookieMetadata->expects($this->once()) + ->method('setPath') + ->with($path) + ->will($this->returnSelf()); + $cookieMetadata->expects($this->once()) + ->method('setDomain') + ->with($domain) + ->will($this->returnSelf()); + $cookieMetadata->expects($this->once()) + ->method('setSecure') + ->with($secure) + ->will($this->returnSelf()); + $cookieMetadata->expects($this->once()) + ->method('setHttpOnly') + ->with($httpOnly) + ->will($this->returnSelf()); + + $this->cookieMetadataFactory->expects($this->once()) + ->method('createPublicCookieMetadata') + ->will($this->returnValue($cookieMetadata)); + + $this->cookieManager->expects($this->once()) + ->method('getCookie') + ->with($name) + ->will($this->returnValue($cookie)); + $this->cookieManager->expects($this->once()) + ->method('setPublicCookie') + ->with($name, $cookie, $cookieMetadata); + + $this->sessionConfig->expects($this->once()) + ->method('getCookiePath') + ->will($this->returnValue($path)); + $this->sessionConfig->expects($this->once()) + ->method('getCookieDomain') + ->will($this->returnValue($domain)); + $this->sessionConfig->expects($this->once()) + ->method('getCookieSecure') + ->will($this->returnValue($secure)); + $this->sessionConfig->expects($this->once()) + ->method('getCookieHttpOnly') + ->will($this->returnValue($httpOnly)); + + $this->session->prolong(); + + $this->assertLessThanOrEqual(time(), $this->session->getUpdatedAt()); + } + + /** + * @dataProvider isAllowedDataProvider + * @param bool $isUserDefined + * @param bool $isAclDefined + * @param bool $isAllowed + * @param true $expectedResult + */ + public function testIsAllowed($isUserDefined, $isAclDefined, $isAllowed, $expectedResult) + { + $userAclRole = 'userAclRole'; + if ($isAclDefined) { + $aclMock = $this->getMockBuilder(\Magento\Framework\Acl::class)->disableOriginalConstructor()->getMock(); + $this->storage->expects($this->any())->method('getAcl')->willReturn($aclMock); + } + if ($isUserDefined) { + $userMock = $this->getMockBuilder(\Magento\User\Model\User::class)->disableOriginalConstructor()->getMock(); + $this->storage->expects($this->once())->method('getUser')->willReturn($userMock); + } + if ($isAclDefined && $isUserDefined) { + $userMock->expects($this->any())->method('getAclRole')->willReturn($userAclRole); + $aclMock->expects($this->once())->method('isAllowed')->with($userAclRole)->willReturn($isAllowed); + } + + $this->assertEquals($expectedResult, $this->session->isAllowed('resource')); + } + + /** + * @return array + */ + public function isAllowedDataProvider() + { + return [ + "Negative: User not defined" => [false, true, true, false], + "Negative: Acl not defined" => [true, false, true, false], + "Negative: Permission denied" => [true, true, false, false], + "Positive: Permission granted" => [true, true, false, false], + ]; + } + + /** + * @dataProvider firstPageAfterLoginDataProvider + * @param bool $isFirstPageAfterLogin + */ + public function testFirstPageAfterLogin($isFirstPageAfterLogin) + { + $this->session->setIsFirstPageAfterLogin($isFirstPageAfterLogin); + $this->assertEquals($isFirstPageAfterLogin, $this->session->isFirstPageAfterLogin()); + } + + /** + * @return array + */ + public function firstPageAfterLoginDataProvider() + { + return [ + 'First page after login' => [true], + 'Not first page after login' => [false], + ]; + } +} diff --git a/app/code/Magento/Backend/Test/Unit/Model/Authorization/RoleLocatorTest.php b/app/code/Magento/Backend/Test/Unit/Model/Authorization/RoleLocatorTest.php new file mode 100644 index 0000000000000..5b3910e9445f8 --- /dev/null +++ b/app/code/Magento/Backend/Test/Unit/Model/Authorization/RoleLocatorTest.php @@ -0,0 +1,36 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Backend\Test\Unit\Model\Authorization; + +class RoleLocatorTest extends \PHPUnit\Framework\TestCase +{ + /** + * @var \Magento\Backend\Model\Authorization\RoleLocator + */ + protected $_model; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $_sessionMock = []; + + protected function setUp() + { + $this->_sessionMock = $this->createPartialMock( + \Magento\Backend\Model\Auth\Session::class, + ['getUser', 'getAclRole', 'hasUser'] + ); + $this->_model = new \Magento\Backend\Model\Authorization\RoleLocator($this->_sessionMock); + } + + public function testGetAclRoleIdReturnsCurrentUserAclRoleId() + { + $this->_sessionMock->expects($this->once())->method('hasUser')->will($this->returnValue(true)); + $this->_sessionMock->expects($this->once())->method('getUser')->will($this->returnSelf()); + $this->_sessionMock->expects($this->once())->method('getAclRole')->will($this->returnValue('some_role')); + $this->assertEquals('some_role', $this->_model->getAclRoleId()); + } +} diff --git a/app/code/Magento/Backend/Test/Unit/Model/Locale/ManagerTest.php b/app/code/Magento/Backend/Test/Unit/Model/Locale/ManagerTest.php new file mode 100644 index 0000000000000..77eb7cdb34d1f --- /dev/null +++ b/app/code/Magento/Backend/Test/Unit/Model/Locale/ManagerTest.php @@ -0,0 +1,127 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Backend\Test\Unit\Model\Locale; + +use Magento\Framework\Locale\Resolver; + +class ManagerTest extends \PHPUnit\Framework\TestCase +{ + /** + * @var \Magento\Backend\Model\Locale\Manager + */ + protected $_model; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\TranslateInterface + */ + protected $_translator; + + /** + * @var \Magento\Backend\Model\Session + */ + protected $_session; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Backend\Model\Auth\Session + */ + protected $_authSession; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Backend\App\ConfigInterface + */ + protected $_backendConfig; + + protected function setUp() + { + $this->_session = $this->createMock(\Magento\Backend\Model\Session::class); + + $this->_authSession = $this->createPartialMock(\Magento\Backend\Model\Auth\Session::class, ['getUser']); + + $this->_backendConfig = $this->getMockForAbstractClass( + \Magento\Backend\App\ConfigInterface::class, + [], + '', + false + ); + + $userMock = new \Magento\Framework\DataObject(); + + $this->_authSession->expects($this->any())->method('getUser')->will($this->returnValue($userMock)); + + $this->_translator = $this->getMockBuilder(\Magento\Framework\TranslateInterface::class) + ->setMethods(['init', 'setLocale']) + ->getMockForAbstractClass(); + + $this->_translator->expects($this->any())->method('setLocale')->will($this->returnValue($this->_translator)); + + $this->_translator->expects($this->any())->method('init')->will($this->returnValue(false)); + + $this->_model = new \Magento\Backend\Model\Locale\Manager( + $this->_session, + $this->_authSession, + $this->_translator, + $this->_backendConfig + ); + } + + /** + * @return array + */ + public function switchBackendInterfaceLocaleDataProvider() + { + return ['case1' => ['locale' => 'de_DE'], 'case2' => ['locale' => 'en_US']]; + } + + /** + * @param string $locale + * @dataProvider switchBackendInterfaceLocaleDataProvider + * @covers \Magento\Backend\Model\Locale\Manager::switchBackendInterfaceLocale + */ + public function testSwitchBackendInterfaceLocale($locale) + { + $this->_model->switchBackendInterfaceLocale($locale); + + $userInterfaceLocale = $this->_authSession->getUser()->getInterfaceLocale(); + $this->assertEquals($userInterfaceLocale, $locale); + + $sessionLocale = $this->_session->getSessionLocale(); + $this->assertEquals($sessionLocale, null); + } + + /** + * @covers \Magento\Backend\Model\Locale\Manager::getUserInterfaceLocale + */ + public function testGetUserInterfaceLocaleDefault() + { + $locale = $this->_model->getUserInterfaceLocale(); + + $this->assertEquals($locale, Resolver::DEFAULT_LOCALE); + } + + /** + * @covers \Magento\Backend\Model\Locale\Manager::getUserInterfaceLocale + */ + public function testGetUserInterfaceLocale() + { + $this->_model->switchBackendInterfaceLocale('de_DE'); + $locale = $this->_model->getUserInterfaceLocale(); + + $this->assertEquals($locale, 'de_DE'); + } + + /** + * @covers \Magento\Backend\Model\Locale\Manager::getUserInterfaceLocale + */ + public function testGetUserInterfaceGeneralLocale() + { + $this->_backendConfig->expects($this->any()) + ->method('getValue') + ->with('general/locale/code') + ->willReturn('test_locale'); + $locale = $this->_model->getUserInterfaceLocale(); + $this->assertEquals($locale, 'test_locale'); + } +} diff --git a/app/code/Magento/Backend/composer.json b/app/code/Magento/Backend/composer.json index e54bd136b3494..f9408768136bb 100644 --- a/app/code/Magento/Backend/composer.json +++ b/app/code/Magento/Backend/composer.json @@ -22,7 +22,6 @@ "magento/module-store": "*", "magento/module-translation": "*", "magento/module-ui": "*", - "magento/module-authorization": "*", "magento/module-user": "*" }, "suggest": { diff --git a/app/code/Magento/Backend/etc/di.xml b/app/code/Magento/Backend/etc/di.xml index 41db85b9323a8..c526703da9975 100644 --- a/app/code/Magento/Backend/etc/di.xml +++ b/app/code/Magento/Backend/etc/di.xml @@ -198,8 +198,4 @@ <argument name="anchorRenderer" xsi:type="object">Magento\Backend\Block\AnchorRenderer</argument> </arguments> </type> - <preference for="Magento\Backend\Spi\SessionUserHydratorInterface" - type="Magento\Backend\Model\Auth\SessionUserHydrator" /> - <preference for="Magento\Backend\Spi\SessionAclHydratorInterface" - type="Magento\Backend\Model\Auth\SessionAclHydrator" /> </config> diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Eav/Attribute.php b/app/code/Magento/Catalog/Model/ResourceModel/Eav/Attribute.php index d56cc40ad0fc2..23f612582f42e 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Eav/Attribute.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Eav/Attribute.php @@ -845,14 +845,9 @@ public function afterDelete() /** * @inheritdoc * @since 100.0.9 - * - * @SuppressWarnings(PHPMD.SerializationAware) - * @deprecated Do not use PHP serialization. */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); - $this->unsetData('entity_type'); return array_diff( parent::__sleep(), @@ -863,14 +858,9 @@ public function __sleep() /** * @inheritdoc * @since 100.0.9 - * - * @SuppressWarnings(PHPMD.SerializationAware) - * @deprecated Do not use PHP serialization. */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); - parent::__wakeup(); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); $this->_indexerEavProcessor = $objectManager->get(\Magento\Catalog\Model\Indexer\Product\Flat\Processor::class); diff --git a/app/code/Magento/Config/Model/Config/Backend/Encrypted.php b/app/code/Magento/Config/Model/Config/Backend/Encrypted.php index ea3b1d4c74a5f..1a91e403a679d 100644 --- a/app/code/Magento/Config/Model/Config/Backend/Encrypted.php +++ b/app/code/Magento/Config/Model/Config/Backend/Encrypted.php @@ -9,8 +9,6 @@ namespace Magento\Config\Model\Config\Backend; /** - * Backend model for encrypted values. - * * @api * @since 100.0.2 */ @@ -50,14 +48,9 @@ public function __construct( * Magic method called during class serialization * * @return string[] - * - * @SuppressWarnings(PHPMD.SerializationAware) - * @deprecated Do not use PHP serialization. */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); - $properties = parent::__sleep(); return array_diff($properties, ['_encryptor']); } @@ -66,14 +59,9 @@ public function __sleep() * Magic method called during class un-serialization * * @return void - * - * @SuppressWarnings(PHPMD.SerializationAware) - * @deprecated Do not use PHP serialization. */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); - parent::__wakeup(); $this->_encryptor = \Magento\Framework\App\ObjectManager::getInstance()->get( \Magento\Framework\Encryption\EncryptorInterface::class diff --git a/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable/Attribute.php b/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable/Attribute.php index 4ead9ffe0fe70..7306942c3c49b 100644 --- a/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable/Attribute.php +++ b/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable/Attribute.php @@ -12,8 +12,6 @@ use Magento\Framework\EntityManager\MetadataPool; /** - * Configurable product attribute model. - * * @method Attribute setProductAttribute(\Magento\Eav\Model\Entity\Attribute\AbstractAttribute $value) * @method \Magento\Eav\Model\Entity\Attribute\AbstractAttribute getProductAttribute() */ @@ -88,7 +86,7 @@ public function getOptions() } /** - * @inheritdoc + * {@inheritdoc} */ public function getLabel() { @@ -114,10 +112,10 @@ public function afterSave() } /** - * Load configurable attribute by product and product's attribute. + * Load configurable attribute by product and product's attribute * * @param \Magento\Catalog\Model\Product $product - * @param \Magento\Catalog\Model\ResourceModel\Eav\Attribute $attribute + * @param \Magento\Catalog\Model\ResourceModel\Eav\Attribute $attribute * @return void */ public function loadByProductAndAttribute($product, $attribute) @@ -146,7 +144,7 @@ public function deleteByProduct($product) } /** - * @inheritdoc + * {@inheritdoc} * @codeCoverageIgnore */ public function getAttributeId() @@ -155,7 +153,7 @@ public function getAttributeId() } /** - * @inheritdoc + * {@inheritdoc} * @codeCoverageIgnore */ public function getPosition() @@ -164,7 +162,7 @@ public function getPosition() } /** - * @inheritdoc + * {@inheritdoc} * @codeCoverageIgnore */ public function getIsUseDefault() @@ -173,7 +171,7 @@ public function getIsUseDefault() } /** - * @inheritdoc + * {@inheritdoc} * @codeCoverageIgnore */ public function getValues() @@ -184,7 +182,8 @@ public function getValues() //@codeCoverageIgnoreStart /** - * @inheritdoc + * @param string $attributeId + * @return $this */ public function setAttributeId($attributeId) { @@ -192,7 +191,8 @@ public function setAttributeId($attributeId) } /** - * @inheritdoc + * @param string $label + * @return $this */ public function setLabel($label) { @@ -200,7 +200,8 @@ public function setLabel($label) } /** - * @inheritdoc + * @param int $position + * @return $this */ public function setPosition($position) { @@ -208,7 +209,8 @@ public function setPosition($position) } /** - * @inheritdoc + * @param bool $isUseDefault + * @return $this */ public function setIsUseDefault($isUseDefault) { @@ -216,7 +218,8 @@ public function setIsUseDefault($isUseDefault) } /** - * @inheritdoc + * @param \Magento\ConfigurableProduct\Api\Data\OptionValueInterface[] $values + * @return $this */ public function setValues(array $values = null) { @@ -224,7 +227,7 @@ public function setValues(array $values = null) } /** - * @inheritdoc + * {@inheritdoc} * * @return \Magento\ConfigurableProduct\Api\Data\OptionExtensionInterface|null */ @@ -234,7 +237,7 @@ public function getExtensionAttributes() } /** - * @inheritdoc + * {@inheritdoc} * * @param \Magento\ConfigurableProduct\Api\Data\OptionExtensionInterface $extensionAttributes * @return $this @@ -246,7 +249,7 @@ public function setExtensionAttributes( } /** - * @inheritdoc + * {@inheritdoc} */ public function getProductId() { @@ -254,7 +257,7 @@ public function getProductId() } /** - * @inheritdoc + * {@inheritdoc} */ public function setProductId($value) { @@ -265,14 +268,9 @@ public function setProductId($value) /** * @inheritdoc - * - * @SuppressWarnings(PHPMD.SerializationAware) - * @deprecated Do not use PHP serialization. */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); - return array_diff( parent::__sleep(), ['metadataPool'] @@ -281,14 +279,9 @@ public function __sleep() /** * @inheritdoc - * - * @SuppressWarnings(PHPMD.SerializationAware) - * @deprecated Do not use PHP serialization. */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); - parent::__wakeup(); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); $this->metadataPool = $objectManager->get(MetadataPool::class); diff --git a/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Product/Type/Configurable/Attribute/Collection.php b/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Product/Type/Configurable/Attribute/Collection.php index 81cbbd06c523c..3c40d326be77f 100644 --- a/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Product/Type/Configurable/Attribute/Collection.php +++ b/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Product/Type/Configurable/Attribute/Collection.php @@ -18,8 +18,6 @@ use Magento\Catalog\Api\Data\ProductInterface; /** - * Collection of configurable product attributes. - * * @api * @SuppressWarnings(PHPMD.LongVariable) * @SuppressWarnings(PHPMD.CouplingBetweenObjects) @@ -304,8 +302,6 @@ protected function _loadLabels() } /** - * Load related options' data. - * * @return void */ protected function loadOptions() @@ -358,14 +354,9 @@ protected function getIncludedOptions(array $usedProducts, AbstractAttribute $pr /** * @inheritdoc * @since 100.0.6 - * - * @SuppressWarnings(PHPMD.SerializationAware) - * @deprecated Do not use PHP serialization. */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); - return array_diff( parent::__sleep(), [ @@ -382,14 +373,9 @@ public function __sleep() /** * @inheritdoc * @since 100.0.6 - * - * @SuppressWarnings(PHPMD.SerializationAware) - * @deprecated Do not use PHP serialization. */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); - parent::__wakeup(); $objectManager = ObjectManager::getInstance(); $this->_storeManager = $objectManager->get(\Magento\Store\Model\StoreManagerInterface::class); diff --git a/app/code/Magento/Customer/Model/Attribute.php b/app/code/Magento/Customer/Model/Attribute.php index ae714f993082e..98a97872f15f4 100644 --- a/app/code/Magento/Customer/Model/Attribute.php +++ b/app/code/Magento/Customer/Model/Attribute.php @@ -202,14 +202,9 @@ public function canBeFilterableInGrid() /** * @inheritdoc - * - * @SuppressWarnings(PHPMD.SerializationAware) - * @deprecated Do not use PHP serialization. */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); - $this->unsetData('entity_type'); return array_diff( parent::__sleep(), @@ -219,14 +214,9 @@ public function __sleep() /** * @inheritdoc - * - * @SuppressWarnings(PHPMD.SerializationAware) - * @deprecated Do not use PHP serialization. */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); - parent::__wakeup(); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); $this->indexerRegistry = $objectManager->get(\Magento\Framework\Indexer\IndexerRegistry::class); diff --git a/app/code/Magento/Eav/Model/Entity/Attribute.php b/app/code/Magento/Eav/Model/Entity/Attribute.php index e23f81607a0c0..23054ad613c21 100644 --- a/app/code/Magento/Eav/Model/Entity/Attribute.php +++ b/app/code/Magento/Eav/Model/Entity/Attribute.php @@ -310,9 +310,9 @@ public function beforeSave() } /** - * @inheritdoc + * Save additional data * - * Save additional data. + * @return $this */ public function afterSave() { @@ -496,14 +496,9 @@ public function getIdentities() /** * @inheritdoc * @since 100.0.7 - * - * @SuppressWarnings(PHPMD.SerializationAware) - * @deprecated Do not use PHP serialization. */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); - $this->unsetData('attribute_set_info'); return array_diff( parent::__sleep(), @@ -514,14 +509,9 @@ public function __sleep() /** * @inheritdoc * @since 100.0.7 - * - * @SuppressWarnings(PHPMD.SerializationAware) - * @deprecated Do not use PHP serialization. */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); - parent::__wakeup(); $objectManager = ObjectManager::getInstance(); $this->_localeDate = $objectManager->get(\Magento\Framework\Stdlib\DateTime\TimezoneInterface::class); diff --git a/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php b/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php index 9ed4ac5293681..7ed455eccf4e0 100644 --- a/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php +++ b/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php @@ -1404,14 +1404,9 @@ public function setExtensionAttributes(\Magento\Eav\Api\Data\AttributeExtensionI /** * @inheritdoc * @since 100.0.7 - * - * @SuppressWarnings(PHPMD.SerializationAware) - * @deprecated Do not use PHP serialization. */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); - return array_diff( parent::__sleep(), [ @@ -1434,14 +1429,9 @@ public function __sleep() /** * @inheritdoc * @since 100.0.7 - * - * @SuppressWarnings(PHPMD.SerializationAware) - * @deprecated Do not use PHP serialization. */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); - parent::__wakeup(); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); $this->_eavConfig = $objectManager->get(\Magento\Eav\Model\Config::class); diff --git a/app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute.php b/app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute.php index 5e7226e7a36dd..0e7a46125d872 100644 --- a/app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute.php +++ b/app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute.php @@ -725,14 +725,9 @@ public function getValidAttributeIds($attributeIds) * * @return array * @since 100.0.7 - * - * @SuppressWarnings(PHPMD.SerializationAware) - * @deprecated Do not use PHP serialization. */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); - $properties = parent::__sleep(); $properties = array_diff($properties, ['_storeManager']); return $properties; @@ -743,14 +738,9 @@ public function __sleep() * * @return void * @since 100.0.7 - * - * @SuppressWarnings(PHPMD.SerializationAware) - * @deprecated Do not use PHP serialization. */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); - parent::__wakeup(); $this->_storeManager = \Magento\Framework\App\ObjectManager::getInstance() ->get(\Magento\Store\Model\StoreManagerInterface::class); diff --git a/app/code/Magento/Paypal/Test/Unit/Block/Adminhtml/System/Config/Fieldset/GroupTest.php b/app/code/Magento/Paypal/Test/Unit/Block/Adminhtml/System/Config/Fieldset/GroupTest.php new file mode 100644 index 0000000000000..cfdfe17b1e004 --- /dev/null +++ b/app/code/Magento/Paypal/Test/Unit/Block/Adminhtml/System/Config/Fieldset/GroupTest.php @@ -0,0 +1,107 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Paypal\Test\Unit\Block\Adminhtml\System\Config\Fieldset; + +class GroupTest extends \PHPUnit\Framework\TestCase +{ + /** + * @var Group + */ + protected $_model; + + /** + * @var \Magento\Framework\Data\Form\Element\AbstractElement + */ + protected $_element; + + /** + * @var \Magento\Backend\Model\Auth\Session|\PHPUnit_Framework_MockObject_MockObject + */ + protected $_authSession; + + /** + * @var \Magento\User\Model\User|\PHPUnit_Framework_MockObject_MockObject + */ + protected $_user; + + /** + * @var \Magento\Config\Model\Config\Structure\Element\Group|\PHPUnit_Framework_MockObject_MockObject + */ + protected $_group; + + protected function setUp() + { + $helper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $this->_group = $this->createMock(\Magento\Config\Model\Config\Structure\Element\Group::class); + $this->_element = $this->getMockForAbstractClass( + \Magento\Framework\Data\Form\Element\AbstractElement::class, + [], + '', + false, + true, + true, + ['getHtmlId', 'getElementHtml', 'getName', 'getElements', 'getId'] + ); + $this->_element->expects($this->any()) + ->method('getHtmlId') + ->will($this->returnValue('html id')); + $this->_element->expects($this->any()) + ->method('getElementHtml') + ->will($this->returnValue('element html')); + $this->_element->expects($this->any()) + ->method('getName') + ->will($this->returnValue('name')); + $this->_element->expects($this->any()) + ->method('getElements') + ->will($this->returnValue([])); + $this->_element->expects($this->any()) + ->method('getId') + ->will($this->returnValue('id')); + $this->_user = $this->createMock(\Magento\User\Model\User::class); + $this->_authSession = $this->createMock(\Magento\Backend\Model\Auth\Session::class); + $this->_authSession->expects($this->any()) + ->method('__call') + ->with('getUser') + ->will($this->returnValue($this->_user)); + $this->_model = $helper->getObject( + \Magento\Paypal\Block\Adminhtml\System\Config\Fieldset\Group::class, + ['authSession' => $this->_authSession] + ); + $this->_model->setGroup($this->_group); + } + + /** + * @param mixed $expanded + * @param int $expected + * @dataProvider isCollapseStateDataProvider + */ + public function testIsCollapseState($expanded, $expected) + { + $this->_user->setExtra(['configState' => []]); + $this->_element->setGroup(isset($expanded) ? ['expanded' => $expanded] : []); + $html = $this->_model->render($this->_element); + $this->assertContains( + '<input id="' . $this->_element->getHtmlId() . '-state" name="config_state[' + . $this->_element->getId() . ']" type="hidden" value="' . $expected . '" />', + $html + ); + } + + /** + * @return array + */ + public function isCollapseStateDataProvider() + { + return [ + [null, 0], + [false, 0], + ['', 0], + [1, 1], + ['1', 1], + ]; + } +} diff --git a/app/code/Magento/ReleaseNotification/Test/Unit/Model/Condition/CanViewNotificationTest.php b/app/code/Magento/ReleaseNotification/Test/Unit/Model/Condition/CanViewNotificationTest.php index b86f8dff2b3b1..55f448730a506 100644 --- a/app/code/Magento/ReleaseNotification/Test/Unit/Model/Condition/CanViewNotificationTest.php +++ b/app/code/Magento/ReleaseNotification/Test/Unit/Model/Condition/CanViewNotificationTest.php @@ -12,7 +12,6 @@ use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; use Magento\Backend\Model\Auth\Session; use Magento\Framework\App\CacheInterface; -use Magento\User\Model\User; class CanViewNotificationTest extends \PHPUnit\Framework\TestCase { @@ -34,11 +33,6 @@ class CanViewNotificationTest extends \PHPUnit\Framework\TestCase /** @var $cacheStorageMock \PHPUnit_Framework_MockObject_MockObject|CacheInterface */ private $cacheStorageMock; - /** - * @var User|\PHPUnit_Framework_MockObject_MockObject - */ - private $userMock; - public function setUp() { $this->cacheStorageMock = $this->getMockBuilder(CacheInterface::class) @@ -47,6 +41,7 @@ public function setUp() ->getMock(); $this->sessionMock = $this->getMockBuilder(Session::class) ->disableOriginalConstructor() + ->setMethods(['getUser', 'getId']) ->getMock(); $this->viewerLoggerMock = $this->getMockBuilder(Logger::class) ->disableOriginalConstructor() @@ -54,7 +49,6 @@ public function setUp() $this->productMetadataMock = $this->getMockBuilder(ProductMetadataInterface::class) ->disableOriginalConstructor() ->getMock(); - $this->userMock = $this->createMock(User::class); $objectManager = new ObjectManager($this); $this->canViewNotification = $objectManager->getObject( CanViewNotification::class, @@ -71,8 +65,8 @@ public function testIsVisibleLoadDataFromCache() { $this->sessionMock->expects($this->once()) ->method('getUser') - ->willReturn($this->userMock); - $this->userMock->expects($this->once()) + ->willReturn($this->sessionMock); + $this->sessionMock->expects($this->once()) ->method('getId') ->willReturn(1); $this->cacheStorageMock->expects($this->once()) @@ -96,8 +90,8 @@ public function testIsVisible($expected, $version, $lastViewVersion) ->willReturn(false); $this->sessionMock->expects($this->once()) ->method('getUser') - ->willReturn($this->userMock); - $this->userMock->expects($this->once()) + ->willReturn($this->sessionMock); + $this->sessionMock->expects($this->once()) ->method('getId') ->willReturn(1); $this->productMetadataMock->expects($this->once()) diff --git a/app/code/Magento/Store/Model/Store.php b/app/code/Magento/Store/Model/Store.php index f62762986cb32..5a47bac1ace78 100644 --- a/app/code/Magento/Store/Model/Store.php +++ b/app/code/Magento/Store/Model/Store.php @@ -423,14 +423,9 @@ public function __construct( /** * @inheritdoc - * - * @SuppressWarnings(PHPMD.SerializationAware) - * @deprecated Do not use PHP serialization. */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); - $properties = parent::__sleep(); $properties = array_diff($properties, ['_coreFileStorageDatabase', '_config']); return $properties; @@ -440,14 +435,9 @@ public function __sleep() * Init not serializable fields * * @return void - * - * @SuppressWarnings(PHPMD.SerializationAware) - * @deprecated Do not use PHP serialization. */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); - parent::__wakeup(); $this->_coreFileStorageDatabase = ObjectManager::getInstance() ->get(\Magento\MediaStorage\Helper\File\Storage\Database::class); diff --git a/app/code/Magento/User/Model/User.php b/app/code/Magento/User/Model/User.php index d8040b0bbaaac..2994ac351fc78 100644 --- a/app/code/Magento/User/Model/User.php +++ b/app/code/Magento/User/Model/User.php @@ -212,14 +212,9 @@ protected function _construct() * Removing dependencies and leaving only entity's properties. * * @return string[] - * - * @SuppressWarnings(PHPMD.SerializationAware) - * @deprecated Do not use PHP serialization. */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); - $properties = parent::__sleep(); return array_diff( $properties, @@ -245,14 +240,9 @@ public function __sleep() * Restoring required objects after serialization. * * @return void - * - * @SuppressWarnings(PHPMD.SerializationAware) - * @deprecated Do not use PHP serialization. */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); - parent::__wakeup(); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); $this->serializer = $objectManager->get(Json::class); @@ -416,10 +406,6 @@ public function getRoles() */ public function getRole() { - if ($this->getData('extracted_role')) { - $this->_role = $this->getData('extracted_role'); - $this->unsetData('extracted_role'); - } if (null === $this->_role) { $this->_role = $this->_roleFactory->create(); $roles = $this->getRoles(); diff --git a/app/code/Magento/User/Test/Unit/Model/Authorization/AdminSessionUserContextTest.php b/app/code/Magento/User/Test/Unit/Model/Authorization/AdminSessionUserContextTest.php new file mode 100644 index 0000000000000..23681c4b8da26 --- /dev/null +++ b/app/code/Magento/User/Test/Unit/Model/Authorization/AdminSessionUserContextTest.php @@ -0,0 +1,89 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\User\Test\Unit\Model\Authorization; + +use Magento\Authorization\Model\UserContextInterface; + +/** + * Tests Magento\User\Model\Authorization\AdminSessionUserContext + */ +class AdminSessionUserContextTest extends \PHPUnit\Framework\TestCase +{ + /** + * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager + */ + protected $objectManager; + + /** + * @var \Magento\User\Model\Authorization\AdminSessionUserContext + */ + protected $adminSessionUserContext; + + /** + * @var \Magento\Backend\Model\Auth\Session + */ + protected $adminSession; + + protected function setUp() + { + $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + + $this->adminSession = $this->getMockBuilder(\Magento\Backend\Model\Auth\Session::class) + ->disableOriginalConstructor() + ->setMethods(['hasUser', 'getUser', 'getId']) + ->getMock(); + + $this->adminSessionUserContext = $this->objectManager->getObject( + \Magento\User\Model\Authorization\AdminSessionUserContext::class, + ['adminSession' => $this->adminSession] + ); + } + + public function testGetUserIdExist() + { + $userId = 1; + + $this->setupUserId($userId); + + $this->assertEquals($userId, $this->adminSessionUserContext->getUserId()); + } + + public function testGetUserIdDoesNotExist() + { + $userId = null; + + $this->setupUserId($userId); + + $this->assertEquals($userId, $this->adminSessionUserContext->getUserId()); + } + + public function testGetUserType() + { + $this->assertEquals(UserContextInterface::USER_TYPE_ADMIN, $this->adminSessionUserContext->getUserType()); + } + + /** + * @param int|null $userId + * @return void + */ + public function setupUserId($userId) + { + $this->adminSession->expects($this->once()) + ->method('hasUser') + ->will($this->returnValue($userId)); + + if ($userId) { + $this->adminSession->expects($this->once()) + ->method('getUser') + ->will($this->returnSelf()); + + $this->adminSession->expects($this->once()) + ->method('getId') + ->will($this->returnValue($userId)); + } + } +} diff --git a/app/code/Magento/User/Test/Unit/Model/UserTest.php b/app/code/Magento/User/Test/Unit/Model/UserTest.php index ab06c8754b2f0..670316c2500fc 100644 --- a/app/code/Magento/User/Test/Unit/Model/UserTest.php +++ b/app/code/Magento/User/Test/Unit/Model/UserTest.php @@ -44,6 +44,31 @@ protected function setUp() ); } + /** + * @return void + */ + public function testSleep() + { + $excludedProperties = [ + '_eventManager', + '_cacheManager', + '_registry', + '_appState', + '_userData', + '_config', + '_validatorObject', + '_roleFactory', + '_encryptor', + '_transportBuilder', + '_storeManager', + '_validatorBeforeSave' + ]; + $actualResult = $this->model->__sleep(); + $this->assertNotEmpty($actualResult); + $expectedResult = array_intersect($actualResult, $excludedProperties); + $this->assertEmpty($expectedResult); + } + /** * @return void */ diff --git a/dev/tests/integration/testsuite/Magento/Backend/Model/Auth/SessionTest.php b/dev/tests/integration/testsuite/Magento/Backend/Model/Auth/SessionTest.php index f1e7a10737604..5ca2bf1f73175 100644 --- a/dev/tests/integration/testsuite/Magento/Backend/Model/Auth/SessionTest.php +++ b/dev/tests/integration/testsuite/Magento/Backend/Model/Auth/SessionTest.php @@ -3,12 +3,8 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ - namespace Magento\Backend\Model\Auth; -use Magento\TestFramework\Bootstrap as TestHelper; -use Magento\TestFramework\Helper\Bootstrap; - /** * @magentoAppArea adminhtml * @magentoAppIsolation enabled @@ -22,15 +18,10 @@ class SessionTest extends \PHPUnit\Framework\TestCase private $auth; /** - * @var Session + * @var \Magento\Backend\Model\Auth\Session */ private $authSession; - /** - * @var SessionFactory - */ - private $authSessionFactory; - /** * @var \Magento\Framework\ObjectManagerInterface */ @@ -39,12 +30,11 @@ class SessionTest extends \PHPUnit\Framework\TestCase protected function setUp() { parent::setUp(); - $this->objectManager = Bootstrap::getObjectManager(); + $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); $this->objectManager->get(\Magento\Framework\Config\ScopeInterface::class) ->setCurrentScope(\Magento\Backend\App\Area\FrontNameResolver::AREA_CODE); $this->auth = $this->objectManager->create(\Magento\Backend\Model\Auth::class); - $this->authSession = $this->objectManager->create(Session::class); - $this->authSessionFactory = $this->objectManager->get(SessionFactory::class); + $this->authSession = $this->objectManager->create(\Magento\Backend\Model\Auth\Session::class); $this->auth->setAuthStorage($this->authSession); $this->auth->logout(); } @@ -62,8 +52,8 @@ public function testIsLoggedIn($loggedIn) { if ($loggedIn) { $this->auth->login( - TestHelper::ADMIN_NAME, - TestHelper::ADMIN_PASSWORD + \Magento\TestFramework\Bootstrap::ADMIN_NAME, + \Magento\TestFramework\Bootstrap::ADMIN_PASSWORD ); } $this->assertEquals($loggedIn, $this->authSession->isLoggedIn()); @@ -73,23 +63,4 @@ public function loginDataProvider() { return [[false], [true]]; } - - /** - * Check that persisting user data is working. - */ - public function testStorage() - { - $this->auth->login(TestHelper::ADMIN_NAME, TestHelper::ADMIN_PASSWORD); - $user = $this->authSession->getUser(); - $acl = $this->authSession->getAcl(); - /** @var Session $session */ - $session = $this->authSessionFactory->create(); - $persistedUser = $session->getUser(); - $persistedAcl = $session->getAcl(); - - $this->assertEquals($user->getData(), $persistedUser->getData()); - $this->assertEquals($user->getAclRole(), $persistedUser->getAclRole()); - $this->assertEquals($acl->getRoles(), $persistedAcl->getRoles()); - $this->assertEquals($acl->getResources(), $persistedAcl->getResources()); - } } diff --git a/dev/tests/integration/testsuite/Magento/Backend/Model/Locale/ResolverTest.php b/dev/tests/integration/testsuite/Magento/Backend/Model/Locale/ResolverTest.php index 88662a65c7428..d1252be2c4b53 100644 --- a/dev/tests/integration/testsuite/Magento/Backend/Model/Locale/ResolverTest.php +++ b/dev/tests/integration/testsuite/Magento/Backend/Model/Locale/ResolverTest.php @@ -3,12 +3,9 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ - namespace Magento\Backend\Model\Locale; use Magento\Framework\Locale\Resolver; -use Magento\TestFramework\Helper\Bootstrap; -use Magento\User\Model\User; /** * @magentoAppArea adminhtml @@ -23,7 +20,7 @@ class ResolverTest extends \PHPUnit\Framework\TestCase protected function setUp() { parent::setUp(); - $this->_model = Bootstrap::getObjectManager()->create( + $this->_model = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( \Magento\Backend\Model\Locale\Resolver::class ); } @@ -41,12 +38,12 @@ public function testSetLocaleWithDefaultLocale() */ public function testSetLocaleWithBaseInterfaceLocale() { - $user = Bootstrap::getObjectManager()->create(User::class); - $session = Bootstrap::getObjectManager()->get( + $user = new \Magento\Framework\DataObject(); + $session = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get( \Magento\Backend\Model\Auth\Session::class ); $session->setUser($user); - Bootstrap::getObjectManager()->get( + \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get( \Magento\Backend\Model\Auth\Session::class )->getUser()->setInterfaceLocale( 'fr_FR' @@ -59,7 +56,7 @@ public function testSetLocaleWithBaseInterfaceLocale() */ public function testSetLocaleWithSessionLocale() { - Bootstrap::getObjectManager()->get( + \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get( \Magento\Backend\Model\Session::class )->setSessionLocale( 'es_ES' @@ -72,7 +69,7 @@ public function testSetLocaleWithSessionLocale() */ public function testSetLocaleWithRequestLocale() { - $request = Bootstrap::getObjectManager() + $request = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() ->get(\Magento\Framework\App\RequestInterface::class); $request->setPostValue(['locale' => 'de_DE']); $this->_checkSetLocale('de_DE'); diff --git a/dev/tests/static/framework/Magento/CodeMessDetector/Rule/Design/SerializationAware.php b/dev/tests/static/framework/Magento/CodeMessDetector/Rule/Design/SerializationAware.php deleted file mode 100644 index e38fba8558bad..0000000000000 --- a/dev/tests/static/framework/Magento/CodeMessDetector/Rule/Design/SerializationAware.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -declare(strict_types=1); - -namespace Magento\CodeMessDetector\Rule\Design; - -use PHPMD\AbstractNode; -use PHPMD\AbstractRule; -use PHPMD\Node\ClassNode; -use PHPMD\Node\MethodNode; -use PDepend\Source\AST\ASTMethod; -use PHPMD\Rule\MethodAware; - -/** - * Detect PHP serialization aware methods. - */ -class SerializationAware extends AbstractRule implements MethodAware -{ - /** - * @inheritDoc - * - * @param ASTMethod|MethodNode $method - */ - public function apply(AbstractNode $method) - { - if ($method->getName() === '__wakeup' || $method->getName() === '__sleep') { - $this->addViolation($method, [$method->getName(), $method->getParent()->getFullQualifiedName()]); - } - } -} diff --git a/dev/tests/static/framework/Magento/CodeMessDetector/resources/rulesets/design.xml b/dev/tests/static/framework/Magento/CodeMessDetector/resources/rulesets/design.xml index 5f2461812bab7..53f2fe4a0084e 100644 --- a/dev/tests/static/framework/Magento/CodeMessDetector/resources/rulesets/design.xml +++ b/dev/tests/static/framework/Magento/CodeMessDetector/resources/rulesets/design.xml @@ -60,31 +60,6 @@ class OrderProcessor $currentOrder = $this->session->get('current_order'); ... } -} - ]]> - </example> - </rule> - <rule name="SerializationAware" - class="Magento\CodeMessDetector\Rule\Design\SerializationAware" - message="{1} has {0} method and is PHP serialization aware - PHP serialization must be avoided."> - <description> - <![CDATA[ -Using PHP serialization must be avoided in Magento for security reasons and for prevention of unexpected behaviour. - ]]> - </description> - <priority>2</priority> - <properties /> - <example> - <![CDATA[ -class MyModel extends AbstractModel -{ - - ....... - - public function __sleep() - { - ..... - } } ]]> </example> diff --git a/dev/tests/static/testsuite/Magento/Test/Php/_files/phpmd/ruleset.xml b/dev/tests/static/testsuite/Magento/Test/Php/_files/phpmd/ruleset.xml index e65a9a089da9e..0e3b5fa3d341c 100644 --- a/dev/tests/static/testsuite/Magento/Test/Php/_files/phpmd/ruleset.xml +++ b/dev/tests/static/testsuite/Magento/Test/Php/_files/phpmd/ruleset.xml @@ -45,6 +45,5 @@ <!-- Magento Specific Rules --> <rule ref="Magento/CodeMessDetector/resources/rulesets/design.xml/AllPurposeAction" /> <rule ref="Magento/CodeMessDetector/resources/rulesets/design.xml/CookieAndSessionMisuse" /> - <rule ref="Magento/CodeMessDetector/resources/rulesets/design.xml/SerializationAware" /> </ruleset> diff --git a/lib/internal/Magento/Framework/App/AreaList/Proxy.php b/lib/internal/Magento/Framework/App/AreaList/Proxy.php index 09115add57190..d3b26ee9a4190 100644 --- a/lib/internal/Magento/Framework/App/AreaList/Proxy.php +++ b/lib/internal/Magento/Framework/App/AreaList/Proxy.php @@ -1,14 +1,12 @@ <?php /** + * Application area list + * * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ - namespace Magento\Framework\App\AreaList; -/** - * Proxy for area list. - */ class Proxy extends \Magento\Framework\App\AreaList implements \Magento\Framework\ObjectManager\NoninterceptableInterface { @@ -58,17 +56,10 @@ public function __construct( } /** - * Remove links to other objects. - * * @return array - * - * @SuppressWarnings(PHPMD.SerializationAware) - * @deprecated Do not use PHP serialization. */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); - return ['_subject', '_isShared']; } @@ -76,14 +67,9 @@ public function __sleep() * Retrieve ObjectManager from global scope * * @return void - * - * @SuppressWarnings(PHPMD.SerializationAware) - * @deprecated Do not use PHP serialization. */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); - $this->_objectManager = \Magento\Framework\App\ObjectManager::getInstance(); } diff --git a/lib/internal/Magento/Framework/App/Response/Http.php b/lib/internal/Magento/Framework/App/Response/Http.php index a80d9cbdd6689..62ff94e7043f5 100644 --- a/lib/internal/Magento/Framework/App/Response/Http.php +++ b/lib/internal/Magento/Framework/App/Response/Http.php @@ -1,9 +1,10 @@ <?php /** + * HTTP response + * * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ - namespace Magento\Framework\App\Response; use Magento\Framework\App\Http\Context; @@ -15,11 +16,6 @@ use Magento\Framework\App\Request\Http as HttpRequest; use Magento\Framework\Session\Config\ConfigInterface; -/** - * HTTP Response. - * - * @SuppressWarnings(PHPMD.CookieAndSessionMisuse) - */ class Http extends \Magento\Framework\HTTP\PhpEnvironment\Response { /** Cookie to store page vary string */ @@ -117,9 +113,8 @@ public function sendVary() } /** - * Set headers for public cache. - * - * Also accepts the time-to-live (max-age) parameter. + * Set headers for public cache + * Accepts the time-to-live (max-age) parameter * * @param int $ttl * @return void @@ -179,18 +174,11 @@ public function representJson($content) } /** - * Remove links to other objects. - * * @return string[] * @codeCoverageIgnore - * - * @SuppressWarnings(PHPMD.SerializationAware) - * @deprecated Do not use PHP serialization. */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); - return ['content', 'isRedirect', 'statusCode', 'context', 'headers']; } @@ -199,14 +187,9 @@ public function __sleep() * * @return void * @codeCoverageIgnore - * - * @SuppressWarnings(PHPMD.SerializationAware) - * @deprecated Do not use PHP serialization. */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); - $objectManager = ObjectManager::getInstance(); $this->cookieManager = $objectManager->create(\Magento\Framework\Stdlib\CookieManagerInterface::class); $this->cookieMetadataFactory = $objectManager->get( diff --git a/lib/internal/Magento/Framework/App/Route/ConfigInterface/Proxy.php b/lib/internal/Magento/Framework/App/Route/ConfigInterface/Proxy.php index 5e79315238f7d..fd37590bb7782 100644 --- a/lib/internal/Magento/Framework/App/Route/ConfigInterface/Proxy.php +++ b/lib/internal/Magento/Framework/App/Route/ConfigInterface/Proxy.php @@ -60,17 +60,10 @@ public function __construct( } /** - * Remove links to other objects. - * * @return array - * - * @SuppressWarnings(PHPMD.SerializationAware) - * @deprecated Do not use PHP serialization. */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); - return ['_subject', '_isShared']; } @@ -78,14 +71,9 @@ public function __sleep() * Retrieve ObjectManager from global scope * * @return void - * - * @SuppressWarnings(PHPMD.SerializationAware) - * @deprecated Do not use PHP serialization. */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); - $this->_objectManager = \Magento\Framework\App\ObjectManager::getInstance(); } diff --git a/lib/internal/Magento/Framework/App/Test/Unit/Response/HttpTest.php b/lib/internal/Magento/Framework/App/Test/Unit/Response/HttpTest.php index 9be68b379900a..efb35b7321c3b 100644 --- a/lib/internal/Magento/Framework/App/Test/Unit/Response/HttpTest.php +++ b/lib/internal/Magento/Framework/App/Test/Unit/Response/HttpTest.php @@ -290,6 +290,45 @@ public function testRepresentJson() $this->assertEquals('json_string', $this->model->getBody('default')); } + /** + * + * @expectedException \RuntimeException + * @expectedExceptionMessage ObjectManager isn't initialized + */ + public function testWakeUpWithException() + { + /* ensure that the test preconditions are met */ + $objectManagerClass = new \ReflectionClass(\Magento\Framework\App\ObjectManager::class); + $instanceProperty = $objectManagerClass->getProperty('_instance'); + $instanceProperty->setAccessible(true); + $instanceProperty->setValue(null); + + $this->model->__wakeup(); + $this->assertNull($this->cookieMetadataFactoryMock); + $this->assertNull($this->cookieManagerMock); + } + + /** + * Test for the magic method __wakeup + * + * @covers \Magento\Framework\App\Response\Http::__wakeup + */ + public function testWakeUpWith() + { + $objectManagerMock = $this->createMock(\Magento\Framework\App\ObjectManager::class); + $objectManagerMock->expects($this->once()) + ->method('create') + ->with(\Magento\Framework\Stdlib\CookieManagerInterface::class) + ->will($this->returnValue($this->cookieManagerMock)); + $objectManagerMock->expects($this->at(1)) + ->method('get') + ->with(\Magento\Framework\Stdlib\Cookie\CookieMetadataFactory::class) + ->will($this->returnValue($this->cookieMetadataFactoryMock)); + + \Magento\Framework\App\ObjectManager::setInstance($objectManagerMock); + $this->model->__wakeup(); + } + public function testSetXFrameOptions() { $value = 'DENY'; diff --git a/lib/internal/Magento/Framework/DB/Select.php b/lib/internal/Magento/Framework/DB/Select.php index f33aaea7d0e68..4d178b81af6df 100644 --- a/lib/internal/Magento/Framework/DB/Select.php +++ b/lib/internal/Magento/Framework/DB/Select.php @@ -400,7 +400,7 @@ public function useStraightJoin($flag = true) /** * Render STRAIGHT_JOIN clause * - * @param string $sql SQL query + * @param string $sql SQL query * @return string */ protected function _renderStraightjoin($sql) @@ -452,7 +452,7 @@ public function orderRand($field = null) /** * Render FOR UPDATE clause * - * @param string $sql SQL query + * @param string $sql SQL query * @return string */ protected function _renderForupdate($sql) @@ -467,9 +467,9 @@ protected function _renderForupdate($sql) /** * Add EXISTS clause * - * @param Select $select - * @param string $joinCondition - * @param bool $isExists + * @param Select $select + * @param string $joinCondition + * @param bool $isExists * @return $this */ public function exists($select, $joinCondition, $isExists = true) @@ -509,18 +509,11 @@ public function assemble() } /** - * Remove links to other objects. - * * @return string[] * @since 100.0.11 - * - * @SuppressWarnings(PHPMD.SerializationAware) - * @deprecated Do not use PHP serialization. */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); - $properties = array_keys(get_object_vars($this)); $properties = array_diff( $properties, @@ -537,14 +530,9 @@ public function __sleep() * * @return void * @since 100.0.11 - * - * @SuppressWarnings(PHPMD.SerializationAware) - * @deprecated Do not use PHP serialization. */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); - $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); $this->_adapter = $objectManager->get(ResourceConnection::class)->getConnection(); $this->selectRenderer = $objectManager->get(\Magento\Framework\DB\Select\SelectRenderer::class); diff --git a/lib/internal/Magento/Framework/DB/Select/RendererProxy.php b/lib/internal/Magento/Framework/DB/Select/RendererProxy.php index dc69b96b79050..3626f6a07fa18 100644 --- a/lib/internal/Magento/Framework/DB/Select/RendererProxy.php +++ b/lib/internal/Magento/Framework/DB/Select/RendererProxy.php @@ -56,17 +56,10 @@ public function __construct( } /** - * Remove links to other objects. - * * @return array - * - * @SuppressWarnings(PHPMD.SerializationAware) - * @deprecated Do not use PHP serialization. */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); - return ['_subject', '_isShared']; } @@ -74,14 +67,9 @@ public function __sleep() * Retrieve ObjectManager from global scope * * @return void - * - * @SuppressWarnings(PHPMD.SerializationAware) - * @deprecated Do not use PHP serialization. */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); - $this->_objectManager = \Magento\Framework\App\ObjectManager::getInstance(); } @@ -111,7 +99,7 @@ protected function _getSubject() } /** - * @inheritdoc + * {@inheritdoc} */ public function render(\Magento\Framework\DB\Select $select, $sql = '') { diff --git a/lib/internal/Magento/Framework/Data/Collection.php b/lib/internal/Magento/Framework/Data/Collection.php index 2f3aaad98dfe5..128d3d8e9fd3d 100644 --- a/lib/internal/Magento/Framework/Data/Collection.php +++ b/lib/internal/Magento/Framework/Data/Collection.php @@ -889,14 +889,9 @@ public function hasFlag($flag) * * @return string[] * @since 100.0.11 - * - * @SuppressWarnings(PHPMD.SerializationAware) - * @deprecated Do not use PHP serialization. */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); - $properties = array_keys(get_object_vars($this)); $properties = array_diff( $properties, @@ -912,14 +907,9 @@ public function __sleep() * * @return void * @since 100.0.11 - * - * @SuppressWarnings(PHPMD.SerializationAware) - * @deprecated Do not use PHP serialization. */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); - $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); $this->_entityFactory = $objectManager->get(EntityFactoryInterface::class); } diff --git a/lib/internal/Magento/Framework/Data/Collection/AbstractDb.php b/lib/internal/Magento/Framework/Data/Collection/AbstractDb.php index 1b28e367dcc3a..308f2a12f506e 100644 --- a/lib/internal/Magento/Framework/Data/Collection/AbstractDb.php +++ b/lib/internal/Magento/Framework/Data/Collection/AbstractDb.php @@ -890,14 +890,9 @@ private function getMainTableAlias() /** * @inheritdoc * @since 100.0.11 - * - * @SuppressWarnings(PHPMD.SerializationAware) - * @deprecated Do not use PHP serialization. */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); - return array_diff( parent::__sleep(), ['_fetchStrategy', '_logger', '_conn', 'extensionAttributesJoinProcessor'] @@ -907,14 +902,9 @@ public function __sleep() /** * @inheritdoc * @since 100.0.11 - * - * @SuppressWarnings(PHPMD.SerializationAware) - * @deprecated Do not use PHP serialization. */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); - parent::__wakeup(); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); $this->_logger = $objectManager->get(Logger::class); diff --git a/lib/internal/Magento/Framework/DataObject/Copy/Config/Data/Proxy.php b/lib/internal/Magento/Framework/DataObject/Copy/Config/Data/Proxy.php index b0f5742afef10..880da5db771eb 100644 --- a/lib/internal/Magento/Framework/DataObject/Copy/Config/Data/Proxy.php +++ b/lib/internal/Magento/Framework/DataObject/Copy/Config/Data/Proxy.php @@ -57,17 +57,10 @@ public function __construct( } /** - * Remove links to other objects. - * * @return array - * - * @SuppressWarnings(PHPMD.SerializationAware) - * @deprecated Do not use PHP serialization. */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); - return ['_subject', '_isShared']; } @@ -75,14 +68,9 @@ public function __sleep() * Retrieve ObjectManager from global scope * * @return void - * - * @SuppressWarnings(PHPMD.SerializationAware) - * @deprecated Do not use PHP serialization. */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); - $this->_objectManager = \Magento\Framework\App\ObjectManager::getInstance(); } @@ -112,7 +100,7 @@ protected function _getSubject() } /** - * @inheritdoc + * {@inheritdoc} */ public function merge(array $config) { @@ -120,7 +108,7 @@ public function merge(array $config) } /** - * @inheritdoc + * {@inheritdoc} */ public function get($path = null, $default = null) { @@ -128,7 +116,7 @@ public function get($path = null, $default = null) } /** - * @inheritdoc + * {@inheritdoc} */ public function reset() { diff --git a/lib/internal/Magento/Framework/Interception/Interceptor.php b/lib/internal/Magento/Framework/Interception/Interceptor.php index df1b680234220..07600c5168181 100644 --- a/lib/internal/Magento/Framework/Interception/Interceptor.php +++ b/lib/internal/Magento/Framework/Interception/Interceptor.php @@ -62,14 +62,9 @@ public function ___callParent($method, array $arguments) * Calls parent class sleep if defined, otherwise provides own implementation * * @return array - * - * @SuppressWarnings(PHPMD.SerializationAware) - * @deprecated Do not use PHP serialization. */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); - if (method_exists(get_parent_class($this), '__sleep')) { $properties = parent::__sleep(); } else { @@ -83,14 +78,9 @@ public function __sleep() * Causes Interceptor to be initialized * * @return void - * - * @SuppressWarnings(PHPMD.SerializationAware) - * @deprecated Do not use PHP serialization. */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); - if (method_exists(get_parent_class($this), '__wakeup')) { parent::__wakeup(); } diff --git a/lib/internal/Magento/Framework/Model/AbstractExtensibleModel.php b/lib/internal/Magento/Framework/Model/AbstractExtensibleModel.php index e1f6c792c9c3e..1cffba2543b0b 100644 --- a/lib/internal/Magento/Framework/Model/AbstractExtensibleModel.php +++ b/lib/internal/Magento/Framework/Model/AbstractExtensibleModel.php @@ -158,7 +158,7 @@ public function getCustomAttribute($attributeCode) } /** - * @inheritdoc + * {@inheritdoc} */ public function setCustomAttributes(array $attributes) { @@ -166,7 +166,7 @@ public function setCustomAttributes(array $attributes) } /** - * @inheritdoc + * {@inheritdoc} */ public function setCustomAttribute($attributeCode, $attributeValue) { @@ -182,7 +182,7 @@ public function setCustomAttribute($attributeCode, $attributeValue) } /** - * @inheritdoc + * {@inheritdoc} * * Added custom attributes support. */ @@ -200,7 +200,7 @@ public function setData($key, $value = null) } /** - * @inheritdoc + * {@inheritdoc} * * Unset customAttributesChanged flag */ @@ -359,27 +359,17 @@ private function populateExtensionAttributes(array $extensionAttributesData = [] /** * @inheritdoc - * - * @SuppressWarnings(PHPMD.SerializationAware) - * @deprecated Do not use PHP serialization. */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); - return array_diff(parent::__sleep(), ['extensionAttributesFactory', 'customAttributeFactory']); } /** * @inheritdoc - * - * @SuppressWarnings(PHPMD.SerializationAware) - * @deprecated Do not use PHP serialization. */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); - parent::__wakeup(); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); $this->extensionAttributesFactory = $objectManager->get(ExtensionAttributesFactory::class); diff --git a/lib/internal/Magento/Framework/Model/AbstractModel.php b/lib/internal/Magento/Framework/Model/AbstractModel.php index f5095dbb6e872..567d174938b11 100644 --- a/lib/internal/Magento/Framework/Model/AbstractModel.php +++ b/lib/internal/Magento/Framework/Model/AbstractModel.php @@ -219,14 +219,9 @@ protected function _init($resourceModel) * Remove unneeded properties from serialization * * @return string[] - * - * @SuppressWarnings(PHPMD.SerializationAware) - * @deprecated Do not use PHP serialization. */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); - $properties = array_keys(get_object_vars($this)); $properties = array_diff( $properties, @@ -248,14 +243,9 @@ public function __sleep() * Init not serializable fields * * @return void - * - * @SuppressWarnings(PHPMD.SerializationAware) - * @deprecated Do not use PHP serialization. */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); - $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); $this->_registry = $objectManager->get(\Magento\Framework\Registry::class); diff --git a/lib/internal/Magento/Framework/Model/ResourceModel/Db/AbstractDb.php b/lib/internal/Magento/Framework/Model/ResourceModel/Db/AbstractDb.php index 0cadb10aaafe2..1eaed75bcbfdd 100644 --- a/lib/internal/Magento/Framework/Model/ResourceModel/Db/AbstractDb.php +++ b/lib/internal/Magento/Framework/Model/ResourceModel/Db/AbstractDb.php @@ -156,14 +156,9 @@ public function __construct( * Provide variables to serialize * * @return array - * - * @SuppressWarnings(PHPMD.SerializationAware) - * @deprecated Do not use PHP serialization. */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); - $properties = array_keys(get_object_vars($this)); $properties = array_diff($properties, ['_resources', '_connections']); return $properties; @@ -173,14 +168,9 @@ public function __sleep() * Restore global dependencies * * @return void - * - * @SuppressWarnings(PHPMD.SerializationAware) - * @deprecated Do not use PHP serialization. */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); - $this->_resources = \Magento\Framework\App\ObjectManager::getInstance() ->get(\Magento\Framework\App\ResourceConnection::class); } @@ -229,10 +219,8 @@ protected function _setResource($connections, $tables = null) } /** - * Main table setter. - * - * Set main entity table name and primary key field name. - * If field name is omitted {table_name}_id will be used. + * Set main entity table name and primary key field name + * If field name is omitted {table_name}_id will be used * * @param string $mainTable * @param string|null $idFieldName @@ -265,10 +253,8 @@ public function getIdFieldName() } /** - * Main table getter. - * * Returns main table name - extracted from "module/table" style and - * validated by db adapter. + * validated by db adapter * * @throws LocalizedException * @return string @@ -556,7 +542,8 @@ protected function _prepareDataForSave(\Magento\Framework\Model\AbstractModel $o } /** - * Check that model data fields that can be saved has really changed comparing with origData. + * Check that model data fields that can be saved + * has really changed comparing with origData * * @param \Magento\Framework\Model\AbstractModel $object * @return bool diff --git a/lib/internal/Magento/Framework/Model/ResourceModel/Db/Collection/AbstractCollection.php b/lib/internal/Magento/Framework/Model/ResourceModel/Db/Collection/AbstractCollection.php index bc2187f474919..8ec47ed97e11c 100644 --- a/lib/internal/Magento/Framework/Model/ResourceModel/Db/Collection/AbstractCollection.php +++ b/lib/internal/Magento/Framework/Model/ResourceModel/Db/Collection/AbstractCollection.php @@ -606,14 +606,9 @@ public function save() /** * @inheritdoc * @since 100.0.11 - * - * @SuppressWarnings(PHPMD.SerializationAware) - * @deprecated Do not use PHP serialization. */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); - return array_diff( parent::__sleep(), ['_resource', '_eventManager'] @@ -623,14 +618,9 @@ public function __sleep() /** * @inheritdoc * @since 100.0.11 - * - * @SuppressWarnings(PHPMD.SerializationAware) - * @deprecated Do not use PHP serialization. */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); - parent::__wakeup(); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); $this->_eventManager = $objectManager->get(\Magento\Framework\Event\ManagerInterface::class); diff --git a/lib/internal/Magento/Framework/Mview/Config/Data/Proxy.php b/lib/internal/Magento/Framework/Mview/Config/Data/Proxy.php index d67c380207554..a83e9507bda04 100644 --- a/lib/internal/Magento/Framework/Mview/Config/Data/Proxy.php +++ b/lib/internal/Magento/Framework/Mview/Config/Data/Proxy.php @@ -55,17 +55,10 @@ public function __construct( } /** - * Remove links to objects. - * * @return array - * - * @SuppressWarnings(PHPMD.SerializationAware) - * @deprecated Do not use PHP serialization. */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); - return ['subject', 'isShared']; } @@ -73,14 +66,9 @@ public function __sleep() * Retrieve ObjectManager from global scope * * @return void - * - * @SuppressWarnings(PHPMD.SerializationAware) - * @deprecated Do not use PHP serialization. */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); - $this->objectManager = \Magento\Framework\App\ObjectManager::getInstance(); } @@ -112,7 +100,7 @@ protected function _getSubject() } /** - * @inheritdoc + * {@inheritdoc} */ public function merge(array $config) { @@ -120,7 +108,7 @@ public function merge(array $config) } /** - * @inheritdoc + * {@inheritdoc} */ public function get($path = null, $default = null) { diff --git a/lib/internal/Magento/Framework/Translate/Inline/Proxy.php b/lib/internal/Magento/Framework/Translate/Inline/Proxy.php index e6d6cc57c2b09..370a88d6d9a43 100644 --- a/lib/internal/Magento/Framework/Translate/Inline/Proxy.php +++ b/lib/internal/Magento/Framework/Translate/Inline/Proxy.php @@ -55,17 +55,10 @@ public function __construct( } /** - * Remove links to other objects. - * * @return array - * - * @SuppressWarnings(PHPMD.SerializationAware) - * @deprecated Do not use PHP serialization. */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); - return ['subject', 'isShared']; } @@ -73,14 +66,9 @@ public function __sleep() * Retrieve ObjectManager from global scope * * @return void - * - * @SuppressWarnings(PHPMD.SerializationAware) - * @deprecated Do not use PHP serialization. */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); - $this->objectManager = \Magento\Framework\App\ObjectManager::getInstance(); } diff --git a/lib/internal/Magento/Framework/View/Layout/Proxy.php b/lib/internal/Magento/Framework/View/Layout/Proxy.php index a3d89c6ec7a8e..03020307c5380 100644 --- a/lib/internal/Magento/Framework/View/Layout/Proxy.php +++ b/lib/internal/Magento/Framework/View/Layout/Proxy.php @@ -57,17 +57,10 @@ public function __construct( } /** - * Remove links to objects. - * * @return array - * - * @SuppressWarnings(PHPMD.SerializationAware) - * @deprecated Do not use PHP serialization. */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); - return ['_subject', '_isShared']; } @@ -75,14 +68,9 @@ public function __sleep() * Retrieve ObjectManager from global scope * * @return void - * - * @SuppressWarnings(PHPMD.SerializationAware) - * @deprecated Do not use PHP serialization. */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); - $this->_objectManager = \Magento\Framework\App\ObjectManager::getInstance(); } @@ -112,7 +100,7 @@ protected function _getSubject() } /** - * @inheritdoc + * {@inheritdoc} */ public function setGeneratorPool(\Magento\Framework\View\Layout\GeneratorPool $generatorPool) { @@ -120,7 +108,7 @@ public function setGeneratorPool(\Magento\Framework\View\Layout\GeneratorPool $g } /** - * @inheritdoc + * {@inheritdoc} */ public function setBuilder(\Magento\Framework\View\Layout\BuilderInterface $builder) { @@ -128,7 +116,7 @@ public function setBuilder(\Magento\Framework\View\Layout\BuilderInterface $buil } /** - * @inheritdoc + * {@inheritdoc} */ public function publicBuild() { @@ -136,7 +124,7 @@ public function publicBuild() } /** - * @inheritdoc + * {@inheritdoc} */ public function getUpdate() { @@ -144,7 +132,7 @@ public function getUpdate() } /** - * @inheritdoc + * {@inheritdoc} */ public function generateXml() { @@ -152,7 +140,7 @@ public function generateXml() } /** - * @inheritdoc + * {@inheritdoc} */ public function generateElements() { @@ -160,7 +148,7 @@ public function generateElements() } /** - * @inheritdoc + * {@inheritdoc} */ public function getChildBlock($parentName, $alias) { @@ -168,7 +156,7 @@ public function getChildBlock($parentName, $alias) } /** - * @inheritdoc + * {@inheritdoc} */ public function setChild($parentName, $elementName, $alias) { @@ -176,7 +164,7 @@ public function setChild($parentName, $elementName, $alias) } /** - * @inheritdoc + * {@inheritdoc} */ public function reorderChild($parentName, $childName, $offsetOrSibling, $after = true) { @@ -184,7 +172,7 @@ public function reorderChild($parentName, $childName, $offsetOrSibling, $after = } /** - * @inheritdoc + * {@inheritdoc} */ public function unsetChild($parentName, $alias) { @@ -192,7 +180,7 @@ public function unsetChild($parentName, $alias) } /** - * @inheritdoc + * {@inheritdoc} */ public function getChildNames($parentName) { @@ -200,7 +188,7 @@ public function getChildNames($parentName) } /** - * @inheritdoc + * {@inheritdoc} */ public function getChildBlocks($parentName) { @@ -208,7 +196,7 @@ public function getChildBlocks($parentName) } /** - * @inheritdoc + * {@inheritdoc} */ public function getChildName($parentName, $alias) { @@ -216,7 +204,7 @@ public function getChildName($parentName, $alias) } /** - * @inheritdoc + * {@inheritdoc} */ public function renderElement($name, $useCache = true) { @@ -224,7 +212,7 @@ public function renderElement($name, $useCache = true) } /** - * @inheritdoc + * {@inheritdoc} */ public function renderNonCachedElement($name) { @@ -232,7 +220,7 @@ public function renderNonCachedElement($name) } /** - * @inheritdoc + * {@inheritdoc} */ public function addToParentGroup($blockName, $parentGroupName) { @@ -240,7 +228,7 @@ public function addToParentGroup($blockName, $parentGroupName) } /** - * @inheritdoc + * {@inheritdoc} */ public function getGroupChildNames($blockName, $groupName) { @@ -248,7 +236,7 @@ public function getGroupChildNames($blockName, $groupName) } /** - * @inheritdoc + * {@inheritdoc} */ public function hasElement($name) { @@ -256,7 +244,7 @@ public function hasElement($name) } /** - * @inheritdoc + * {@inheritdoc} */ public function getElementProperty($name, $attribute) { @@ -264,7 +252,7 @@ public function getElementProperty($name, $attribute) } /** - * @inheritdoc + * {@inheritdoc} */ public function isBlock($name) { @@ -272,7 +260,7 @@ public function isBlock($name) } /** - * @inheritdoc + * {@inheritdoc} */ public function isUiComponent($name) { @@ -280,7 +268,7 @@ public function isUiComponent($name) } /** - * @inheritdoc + * {@inheritdoc} */ public function isContainer($name) { @@ -288,7 +276,7 @@ public function isContainer($name) } /** - * @inheritdoc + * {@inheritdoc} */ public function isManipulationAllowed($name) { @@ -296,7 +284,7 @@ public function isManipulationAllowed($name) } /** - * @inheritdoc + * {@inheritdoc} */ public function setBlock($name, $block) { @@ -304,7 +292,7 @@ public function setBlock($name, $block) } /** - * @inheritdoc + * {@inheritdoc} */ public function unsetElement($name) { @@ -312,7 +300,7 @@ public function unsetElement($name) } /** - * @inheritdoc + * {@inheritdoc} */ public function createBlock($type, $name = '', array $arguments = []) { @@ -320,7 +308,7 @@ public function createBlock($type, $name = '', array $arguments = []) } /** - * @inheritdoc + * {@inheritdoc} */ public function addBlock($block, $name = '', $parent = '', $alias = '') { @@ -328,7 +316,7 @@ public function addBlock($block, $name = '', $parent = '', $alias = '') } /** - * @inheritdoc + * {@inheritdoc} */ public function addContainer($name, $label, array $options = [], $parent = '', $alias = '') { @@ -336,7 +324,7 @@ public function addContainer($name, $label, array $options = [], $parent = '', $ } /** - * @inheritdoc + * {@inheritdoc} */ public function renameElement($oldName, $newName) { @@ -344,7 +332,7 @@ public function renameElement($oldName, $newName) } /** - * @inheritdoc + * {@inheritdoc} */ public function getAllBlocks() { @@ -352,7 +340,7 @@ public function getAllBlocks() } /** - * @inheritdoc + * {@inheritdoc} */ public function getBlock($name) { @@ -360,7 +348,7 @@ public function getBlock($name) } /** - * @inheritdoc + * {@inheritdoc} */ public function getUiComponent($name) { @@ -368,7 +356,7 @@ public function getUiComponent($name) } /** - * @inheritdoc + * {@inheritdoc} */ public function getParentName($childName) { @@ -376,7 +364,7 @@ public function getParentName($childName) } /** - * @inheritdoc + * {@inheritdoc} */ public function getElementAlias($name) { @@ -384,7 +372,7 @@ public function getElementAlias($name) } /** - * @inheritdoc + * {@inheritdoc} */ public function addOutputElement($name) { @@ -392,7 +380,7 @@ public function addOutputElement($name) } /** - * @inheritdoc + * {@inheritdoc} */ public function removeOutputElement($name) { @@ -400,7 +388,7 @@ public function removeOutputElement($name) } /** - * @inheritdoc + * {@inheritdoc} */ public function getOutput() { @@ -408,7 +396,7 @@ public function getOutput() } /** - * @inheritdoc + * {@inheritdoc} */ public function getMessagesBlock() { @@ -416,7 +404,7 @@ public function getMessagesBlock() } /** - * @inheritdoc + * {@inheritdoc} */ public function getBlockSingleton($type) { @@ -424,7 +412,7 @@ public function getBlockSingleton($type) } /** - * @inheritdoc + * {@inheritdoc} */ public function addAdjustableRenderer($namespace, $staticType, $dynamicType, $type, $template, $data = []) { @@ -439,7 +427,7 @@ public function addAdjustableRenderer($namespace, $staticType, $dynamicType, $ty } /** - * @inheritdoc + * {@inheritdoc} */ public function getRendererOptions($namespace, $staticType, $dynamicType) { @@ -447,7 +435,7 @@ public function getRendererOptions($namespace, $staticType, $dynamicType) } /** - * @inheritdoc + * {@inheritdoc} */ public function executeRenderer($namespace, $staticType, $dynamicType, $data = []) { @@ -455,7 +443,7 @@ public function executeRenderer($namespace, $staticType, $dynamicType, $data = [ } /** - * @inheritdoc + * {@inheritdoc} */ public function initMessages($messageGroups = []) { @@ -463,7 +451,7 @@ public function initMessages($messageGroups = []) } /** - * @inheritdoc + * {@inheritdoc} */ public function isCacheable() { @@ -471,7 +459,7 @@ public function isCacheable() } /** - * @inheritdoc + * {@inheritdoc} */ public function isPrivate() { @@ -479,7 +467,7 @@ public function isPrivate() } /** - * @inheritdoc + * {@inheritdoc} */ public function setIsPrivate($isPrivate = true) { @@ -487,7 +475,7 @@ public function setIsPrivate($isPrivate = true) } /** - * @inheritdoc + * {@inheritdoc} */ public function getReaderContext() { @@ -495,7 +483,7 @@ public function getReaderContext() } /** - * @inheritdoc + * {@inheritdoc} */ public function setXml(\Magento\Framework\Simplexml\Element $node) { @@ -503,7 +491,7 @@ public function setXml(\Magento\Framework\Simplexml\Element $node) } /** - * @inheritdoc + * {@inheritdoc} */ public function getNode($path = null) { @@ -511,7 +499,7 @@ public function getNode($path = null) } /** - * @inheritdoc + * {@inheritdoc} */ public function getXpath($xpath) { @@ -519,7 +507,7 @@ public function getXpath($xpath) } /** - * @inheritdoc + * {@inheritdoc} */ public function getXmlString() { @@ -527,7 +515,7 @@ public function getXmlString() } /** - * @inheritdoc + * {@inheritdoc} */ public function loadFile($filePath) { @@ -535,7 +523,7 @@ public function loadFile($filePath) } /** - * @inheritdoc + * {@inheritdoc} */ public function loadString($string) { @@ -543,7 +531,7 @@ public function loadString($string) } /** - * @inheritdoc + * {@inheritdoc} */ public function loadDom(\DOMNode $dom) { @@ -551,7 +539,7 @@ public function loadDom(\DOMNode $dom) } /** - * @inheritdoc + * {@inheritdoc} */ public function setNode($path, $value, $overwrite = true) { @@ -559,7 +547,7 @@ public function setNode($path, $value, $overwrite = true) } /** - * @inheritdoc + * {@inheritdoc} */ public function applyExtends() { @@ -567,7 +555,7 @@ public function applyExtends() } /** - * @inheritdoc + * {@inheritdoc} */ public function processFileData($text) { @@ -575,7 +563,7 @@ public function processFileData($text) } /** - * @inheritdoc + * {@inheritdoc} */ public function extend(\Magento\Framework\Simplexml\Config $config, $overwrite = true) { From 3bfe0075bf6839c250ce34db7dbd360f935b3c34 Mon Sep 17 00:00:00 2001 From: Prashant Sharma <49394527+prashantsharmacedcoss@users.noreply.github.com> Date: Fri, 3 May 2019 19:22:38 +0530 Subject: [PATCH 342/773] Resolve Typo Corrected the spelling of individually from individualy on line no. 364. --- lib/web/css/docs/source/_layout.less | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/web/css/docs/source/_layout.less b/lib/web/css/docs/source/_layout.less index 799f940b44c02..09fd183e30ba0 100644 --- a/lib/web/css/docs/source/_layout.less +++ b/lib/web/css/docs/source/_layout.less @@ -361,7 +361,7 @@ footer.footer { // # Layout width // -// The <code>.lib-layout-width()</code> mixin is used to set default page width of the element the mixin is applied to. It can be used to set width for the whole page wrapper or for the page elements individualy like header, footer, and so on. +// The <code>.lib-layout-width()</code> mixin is used to set default page width of the element the mixin is applied to. It can be used to set width for the whole page wrapper or for the page elements individually like header, footer, and so on. // # Layout width variables // From 5d71f55db2bca2f7a6ba2ecc9378228b24d116be Mon Sep 17 00:00:00 2001 From: Prashant Sharma <49394527+prashantsharmacedcoss@users.noreply.github.com> Date: Fri, 3 May 2019 20:56:33 +0530 Subject: [PATCH 343/773] Resolved Typo error At both places the spelling of padding was paddings updated line no. 301 and 82 --- lib/web/css/docs/source/_actions-toolbar.less | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/web/css/docs/source/_actions-toolbar.less b/lib/web/css/docs/source/_actions-toolbar.less index 3fed935aba731..e764326444de2 100644 --- a/lib/web/css/docs/source/_actions-toolbar.less +++ b/lib/web/css/docs/source/_actions-toolbar.less @@ -79,7 +79,7 @@ // <td>@actions-toolbar__padding</td> // <td class="vars_value">false</td> // <td class="vars_value">'' | false | value</td> -// <td>Paddings of the Actions toolbar</td> +// <td>Padding of the Actions toolbar</td> // </tr> // <tr> // <th>@_actions-toolbar-actions-margin</th> @@ -298,7 +298,7 @@ // // <code>@_actions-toolbar-margin</code> variable controls margins of the actions toolbar wrapper. // -// <code>@_actions-toolbar-padding</code> variable controls paddings of the actions toolbar wrapper. +// <code>@_actions-toolbar-padding</code> variable controls padding of the actions toolbar wrapper. // // ``` html // <div class="example-actions-toolbar-9"> From 09ce15b1e9e371977b89611f41f06db34514a54d Mon Sep 17 00:00:00 2001 From: Max Lesechko <mlesechko@magento.com> Date: Fri, 3 May 2019 11:46:26 -0500 Subject: [PATCH 344/773] MC-16106: [2.3] Failed UI upgrade --- app/code/Magento/Authorization/Model/Role.php | 4 +- .../Magento/Backend/Model/Auth/Session.php | 1 + .../Model/Authorization/RoleLocatorTest.php | 3 + .../Test/Unit/Model/Locale/ManagerTest.php | 3 + .../Model/ResourceModel/Eav/Attribute.php | 1 + .../Config/Model/Config/Backend/Encrypted.php | 4 +- .../Product/Type/Configurable/Attribute.php | 51 ++++---- .../Configurable/Attribute/Collection.php | 7 +- .../Magento/Eav/Model/Entity/Attribute.php | 11 +- .../System/Config/Fieldset/GroupTest.php | 3 + .../Condition/CanViewNotificationTest.php | 3 + app/code/Magento/Store/Model/Store.php | 8 +- app/code/Magento/User/Model/User.php | 15 ++- .../Magento/Framework/App/AreaList/Proxy.php | 7 +- .../Magento/Framework/App/Response/Http.php | 10 +- .../App/Route/ConfigInterface/Proxy.php | 2 + lib/internal/Magento/Framework/DB/Select.php | 8 +- .../Framework/DB/Select/RendererProxy.php | 4 +- .../Framework/Data/Collection/AbstractDb.php | 7 +- .../DataObject/Copy/Config/Data/Proxy.php | 8 +- .../Model/AbstractExtensibleModel.php | 12 +- .../Magento/Framework/Model/AbstractModel.php | 2 +- .../Model/ResourceModel/Db/AbstractDb.php | 10 +- .../Db/Collection/AbstractCollection.php | 2 +- .../Framework/Mview/Config/Data/Proxy.php | 6 +- .../Framework/Translate/Inline/Proxy.php | 2 + .../Magento/Framework/View/Layout/Proxy.php | 118 +++++++++--------- 27 files changed, 175 insertions(+), 137 deletions(-) diff --git a/app/code/Magento/Authorization/Model/Role.php b/app/code/Magento/Authorization/Model/Role.php index 2546df86d09dd..75e9e79c9d36b 100644 --- a/app/code/Magento/Authorization/Model/Role.php +++ b/app/code/Magento/Authorization/Model/Role.php @@ -51,7 +51,7 @@ public function __construct( } /** - * {@inheritdoc} + * @inheritDoc */ public function __sleep() { @@ -60,7 +60,7 @@ public function __sleep() } /** - * {@inheritdoc} + * @inheritDoc */ public function __wakeup() { diff --git a/app/code/Magento/Backend/Model/Auth/Session.php b/app/code/Magento/Backend/Model/Auth/Session.php index 593b4219d45f0..31709705f2507 100644 --- a/app/code/Magento/Backend/Model/Auth/Session.php +++ b/app/code/Magento/Backend/Model/Auth/Session.php @@ -146,6 +146,7 @@ public function isAllowed($resource, $privilege = null) return $acl->isAllowed($user->getAclRole(), null, $privilege); } } catch (\Exception $e) { + return false; } } } diff --git a/app/code/Magento/Backend/Test/Unit/Model/Authorization/RoleLocatorTest.php b/app/code/Magento/Backend/Test/Unit/Model/Authorization/RoleLocatorTest.php index 5b3910e9445f8..77c428a6a116a 100644 --- a/app/code/Magento/Backend/Test/Unit/Model/Authorization/RoleLocatorTest.php +++ b/app/code/Magento/Backend/Test/Unit/Model/Authorization/RoleLocatorTest.php @@ -5,6 +5,9 @@ */ namespace Magento\Backend\Test\Unit\Model\Authorization; +/** + * Class RoleLocatorTest + */ class RoleLocatorTest extends \PHPUnit\Framework\TestCase { /** diff --git a/app/code/Magento/Backend/Test/Unit/Model/Locale/ManagerTest.php b/app/code/Magento/Backend/Test/Unit/Model/Locale/ManagerTest.php index 77eb7cdb34d1f..ce2b65a2249ac 100644 --- a/app/code/Magento/Backend/Test/Unit/Model/Locale/ManagerTest.php +++ b/app/code/Magento/Backend/Test/Unit/Model/Locale/ManagerTest.php @@ -7,6 +7,9 @@ use Magento\Framework\Locale\Resolver; +/** + * Class ManagerTest + */ class ManagerTest extends \PHPUnit\Framework\TestCase { /** diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Eav/Attribute.php b/app/code/Magento/Catalog/Model/ResourceModel/Eav/Attribute.php index 23f612582f42e..e7c98b218f5ad 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Eav/Attribute.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Eav/Attribute.php @@ -193,6 +193,7 @@ public function beforeSave() if ($this->_data[self::KEY_IS_GLOBAL] != $this->_origData[self::KEY_IS_GLOBAL]) { try { $this->attrLockValidator->validate($this); + // phpcs:ignore Magento2.Exceptions.ThrowCatch } catch (\Magento\Framework\Exception\LocalizedException $exception) { throw new \Magento\Framework\Exception\LocalizedException( __('Do not change the scope. %1', $exception->getMessage()) diff --git a/app/code/Magento/Config/Model/Config/Backend/Encrypted.php b/app/code/Magento/Config/Model/Config/Backend/Encrypted.php index 1a91e403a679d..62d6531978d8a 100644 --- a/app/code/Magento/Config/Model/Config/Backend/Encrypted.php +++ b/app/code/Magento/Config/Model/Config/Backend/Encrypted.php @@ -1,7 +1,5 @@ <?php /** - * Encrypted config field backend model - * * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ @@ -9,6 +7,8 @@ namespace Magento\Config\Model\Config\Backend; /** + * Encrypted config field backend model. + * * @api * @since 100.0.2 */ diff --git a/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable/Attribute.php b/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable/Attribute.php index 7306942c3c49b..b013916cc221a 100644 --- a/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable/Attribute.php +++ b/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable/Attribute.php @@ -1,7 +1,5 @@ <?php /** - * Catalog Configurable Product Attribute Model - * * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ @@ -10,8 +8,11 @@ use Magento\Catalog\Api\Data\ProductInterface; use Magento\Framework\Api\AttributeValueFactory; use Magento\Framework\EntityManager\MetadataPool; +use Magento\Framework\Exception\LocalizedException; /** + * Catalog Configurable Product Attribute Model + * * @method Attribute setProductAttribute(\Magento\Eav\Model\Entity\Attribute\AbstractAttribute $value) * @method \Magento\Eav\Model\Entity\Attribute\AbstractAttribute getProductAttribute() */ @@ -86,7 +87,7 @@ public function getOptions() } /** - * {@inheritdoc} + * @inheritDoc */ public function getLabel() { @@ -115,8 +116,8 @@ public function afterSave() * Load configurable attribute by product and product's attribute * * @param \Magento\Catalog\Model\Product $product - * @param \Magento\Catalog\Model\ResourceModel\Eav\Attribute $attribute - * @return void + * @param \Magento\Catalog\Model\ResourceModel\Eav\Attribute $attribute + * @throws LocalizedException */ public function loadByProductAndAttribute($product, $attribute) { @@ -144,7 +145,8 @@ public function deleteByProduct($product) } /** - * {@inheritdoc} + * @inheritDoc + * * @codeCoverageIgnore */ public function getAttributeId() @@ -153,7 +155,8 @@ public function getAttributeId() } /** - * {@inheritdoc} + * @inheritDoc + * * @codeCoverageIgnore */ public function getPosition() @@ -162,7 +165,8 @@ public function getPosition() } /** - * {@inheritdoc} + * @inheritDoc + * * @codeCoverageIgnore */ public function getIsUseDefault() @@ -171,7 +175,8 @@ public function getIsUseDefault() } /** - * {@inheritdoc} + * @inheritDoc + * * @codeCoverageIgnore */ public function getValues() @@ -182,8 +187,7 @@ public function getValues() //@codeCoverageIgnoreStart /** - * @param string $attributeId - * @return $this + * @inheritDoc */ public function setAttributeId($attributeId) { @@ -191,8 +195,7 @@ public function setAttributeId($attributeId) } /** - * @param string $label - * @return $this + * @inheritDoc */ public function setLabel($label) { @@ -200,8 +203,7 @@ public function setLabel($label) } /** - * @param int $position - * @return $this + * @inheritDoc */ public function setPosition($position) { @@ -209,8 +211,7 @@ public function setPosition($position) } /** - * @param bool $isUseDefault - * @return $this + * @inheritDoc */ public function setIsUseDefault($isUseDefault) { @@ -218,8 +219,7 @@ public function setIsUseDefault($isUseDefault) } /** - * @param \Magento\ConfigurableProduct\Api\Data\OptionValueInterface[] $values - * @return $this + * @inheritDoc */ public function setValues(array $values = null) { @@ -227,9 +227,7 @@ public function setValues(array $values = null) } /** - * {@inheritdoc} - * - * @return \Magento\ConfigurableProduct\Api\Data\OptionExtensionInterface|null + * @inheritDoc */ public function getExtensionAttributes() { @@ -237,10 +235,7 @@ public function getExtensionAttributes() } /** - * {@inheritdoc} - * - * @param \Magento\ConfigurableProduct\Api\Data\OptionExtensionInterface $extensionAttributes - * @return $this + * @inheritDoc */ public function setExtensionAttributes( \Magento\ConfigurableProduct\Api\Data\OptionExtensionInterface $extensionAttributes @@ -249,7 +244,7 @@ public function setExtensionAttributes( } /** - * {@inheritdoc} + * @inheritDoc */ public function getProductId() { @@ -257,7 +252,7 @@ public function getProductId() } /** - * {@inheritdoc} + * @inheritDoc */ public function setProductId($value) { diff --git a/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Product/Type/Configurable/Attribute/Collection.php b/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Product/Type/Configurable/Attribute/Collection.php index 3c40d326be77f..8f2cc6ddb43ce 100644 --- a/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Product/Type/Configurable/Attribute/Collection.php +++ b/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Product/Type/Configurable/Attribute/Collection.php @@ -1,7 +1,5 @@ <?php /** - * Catalog Configurable Product Attribute Collection - * * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ @@ -18,6 +16,8 @@ use Magento\Catalog\Api\Data\ProductInterface; /** + * Catalog Configurable Product Attribute Collection + * * @api * @SuppressWarnings(PHPMD.LongVariable) * @SuppressWarnings(PHPMD.CouplingBetweenObjects) @@ -302,7 +302,7 @@ protected function _loadLabels() } /** - * @return void + * Load attribute options. */ protected function loadOptions() { @@ -340,6 +340,7 @@ protected function loadOptions() * @param \Magento\Catalog\Model\Product[] $usedProducts * @param AbstractAttribute $productAttribute * @return array + * @throws \Magento\Framework\Exception\LocalizedException */ protected function getIncludedOptions(array $usedProducts, AbstractAttribute $productAttribute) { diff --git a/app/code/Magento/Eav/Model/Entity/Attribute.php b/app/code/Magento/Eav/Model/Entity/Attribute.php index 23054ad613c21..bb2477d4df827 100644 --- a/app/code/Magento/Eav/Model/Entity/Attribute.php +++ b/app/code/Magento/Eav/Model/Entity/Attribute.php @@ -203,6 +203,7 @@ protected function _getDefaultSourceModel() * Delete entity * * @return \Magento\Eav\Model\ResourceModel\Entity\Attribute + * @throws LocalizedException * @codeCoverageIgnore */ public function deleteEntity() @@ -313,6 +314,7 @@ public function beforeSave() * Save additional data * * @return $this + * @throws LocalizedException */ public function afterSave() { @@ -320,15 +322,6 @@ public function afterSave() return parent::afterSave(); } - /** - * @inheritdoc - * @since 100.0.7 - */ - public function afterDelete() - { - return parent::afterDelete(); - } - /** * Detect backend storage type using frontend input type * diff --git a/app/code/Magento/Paypal/Test/Unit/Block/Adminhtml/System/Config/Fieldset/GroupTest.php b/app/code/Magento/Paypal/Test/Unit/Block/Adminhtml/System/Config/Fieldset/GroupTest.php index cfdfe17b1e004..e4de60cafb8ad 100644 --- a/app/code/Magento/Paypal/Test/Unit/Block/Adminhtml/System/Config/Fieldset/GroupTest.php +++ b/app/code/Magento/Paypal/Test/Unit/Block/Adminhtml/System/Config/Fieldset/GroupTest.php @@ -6,6 +6,9 @@ namespace Magento\Paypal\Test\Unit\Block\Adminhtml\System\Config\Fieldset; +/** + * Class GroupTest + */ class GroupTest extends \PHPUnit\Framework\TestCase { /** diff --git a/app/code/Magento/ReleaseNotification/Test/Unit/Model/Condition/CanViewNotificationTest.php b/app/code/Magento/ReleaseNotification/Test/Unit/Model/Condition/CanViewNotificationTest.php index 55f448730a506..813c5f28bf4d9 100644 --- a/app/code/Magento/ReleaseNotification/Test/Unit/Model/Condition/CanViewNotificationTest.php +++ b/app/code/Magento/ReleaseNotification/Test/Unit/Model/Condition/CanViewNotificationTest.php @@ -13,6 +13,9 @@ use Magento\Backend\Model\Auth\Session; use Magento\Framework\App\CacheInterface; +/** + * Class CanViewNotificationTest + */ class CanViewNotificationTest extends \PHPUnit\Framework\TestCase { /** @var CanViewNotification */ diff --git a/app/code/Magento/Store/Model/Store.php b/app/code/Magento/Store/Model/Store.php index 5a47bac1ace78..6870437ac1c37 100644 --- a/app/code/Magento/Store/Model/Store.php +++ b/app/code/Magento/Store/Model/Store.php @@ -717,6 +717,7 @@ protected function _updatePathUseRewrites($url) $indexFileName = 'index.php'; } else { $scriptFilename = $this->_request->getServer('SCRIPT_FILENAME'); + // phpcs:ignore Magento2.Functions.DiscouragedFunction $indexFileName = basename($scriptFilename); } $url .= $indexFileName . '/'; @@ -1071,9 +1072,10 @@ public function getWebsiteId() /** * Reinit Stores on after save * - * @deprecated 100.1.3 * @return $this + * @throws \Exception * @since 100.1.3 + * @deprecated 100.1.3 */ public function afterSave() { @@ -1204,10 +1206,12 @@ public function getCurrentUrl($fromStore = true) return $storeUrl; } + // phpcs:ignore Magento2.Functions.DiscouragedFunction $storeParsedUrl = parse_url($storeUrl); $storeParsedQuery = []; if (isset($storeParsedUrl['query'])) { + // phpcs:ignore Magento2.Functions.DiscouragedFunction parse_str($storeParsedUrl['query'], $storeParsedQuery); } @@ -1235,6 +1239,7 @@ public function getCurrentUrl($fromStore = true) $requestStringParts = explode('?', $requestString, 2); $requestStringPath = $requestStringParts[0]; if (isset($requestStringParts[1])) { + // phpcs:ignore Magento2.Functions.DiscouragedFunction parse_str($requestStringParts[1], $requestString); } else { $requestString = []; @@ -1378,6 +1383,7 @@ public function getIdentities() */ public function getStorePath() { + // phpcs:ignore Magento2.Functions.DiscouragedFunction $parsedUrl = parse_url($this->getBaseUrl()); return $parsedUrl['path'] ?? '/'; } diff --git a/app/code/Magento/User/Model/User.php b/app/code/Magento/User/Model/User.php index 2994ac351fc78..cf514bab38dcf 100644 --- a/app/code/Magento/User/Model/User.php +++ b/app/code/Magento/User/Model/User.php @@ -321,6 +321,7 @@ protected function _getValidationRulesBeforeSave() * Existing user password confirmation will be validated only when password is set * * @return bool|string[] + * @throws \Exception */ public function validate() { @@ -341,6 +342,7 @@ public function validate() * New password is compared to at least 4 previous passwords to prevent setting them again * * @return bool|string[] + * @throws \Exception * @since 100.0.3 */ protected function validatePasswordChange() @@ -393,6 +395,7 @@ public function saveExtra($data) * Retrieve user roles * * @return array + * @throws \Magento\Framework\Exception\LocalizedException */ public function getRoles() { @@ -441,10 +444,11 @@ public function roleUserExists() /** * Send email with reset password confirmation link. * + * @return $this + * @throws NotificationExceptionInterface * @deprecated * @see NotificatorInterface::sendForgotPassword() * - * @return $this */ public function sendPasswordResetConfirmationEmail() { @@ -622,9 +626,10 @@ public function verifyIdentity($password) /** * Login user * - * @param string $username - * @param string $password - * @return $this + * @param string $username + * @param string $password + * @return $this + * @throws \Magento\Framework\Exception\LocalizedException */ public function login($username, $password) { @@ -711,6 +716,7 @@ public function changeResetPasswordLinkToken($newToken) * Check if current reset password link token is expired * * @return bool + * @throws \Exception */ public function isResetPasswordLinkTokenExpired() { @@ -916,6 +922,7 @@ public function performIdentityCheck($passwordString) { try { $isCheckSuccessful = $this->verifyIdentity($passwordString); + // phpcs:ignore Magento2.Exceptions.ThrowCatch } catch (\Magento\Framework\Exception\AuthenticationException $e) { $isCheckSuccessful = false; } diff --git a/lib/internal/Magento/Framework/App/AreaList/Proxy.php b/lib/internal/Magento/Framework/App/AreaList/Proxy.php index d3b26ee9a4190..d080e4cabbd87 100644 --- a/lib/internal/Magento/Framework/App/AreaList/Proxy.php +++ b/lib/internal/Magento/Framework/App/AreaList/Proxy.php @@ -1,12 +1,13 @@ <?php /** - * Application area list - * * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\Framework\App\AreaList; +/** + * Application area list + */ class Proxy extends \Magento\Framework\App\AreaList implements \Magento\Framework\ObjectManager\NoninterceptableInterface { @@ -56,6 +57,8 @@ public function __construct( } /** + * Sleep magic method. + * * @return array */ public function __sleep() diff --git a/lib/internal/Magento/Framework/App/Response/Http.php b/lib/internal/Magento/Framework/App/Response/Http.php index 62ff94e7043f5..36604c78953d2 100644 --- a/lib/internal/Magento/Framework/App/Response/Http.php +++ b/lib/internal/Magento/Framework/App/Response/Http.php @@ -16,6 +16,9 @@ use Magento\Framework\App\Request\Http as HttpRequest; use Magento\Framework\Session\Config\ConfigInterface; +/** + * HTTP response + */ class Http extends \Magento\Framework\HTTP\PhpEnvironment\Response { /** Cookie to store page vary string */ @@ -95,7 +98,9 @@ public function setXFrameOptions($value) /** * Send Vary cookie * - * @return void + * @throws \Magento\Framework\Exception\InputException + * @throws \Magento\Framework\Stdlib\Cookie\CookieSizeLimitReachedException + * @throws \Magento\Framework\Stdlib\Cookie\FailureToSendException */ public function sendVary() { @@ -114,6 +119,7 @@ public function sendVary() /** * Set headers for public cache + * * Accepts the time-to-live (max-age) parameter * * @param int $ttl @@ -174,6 +180,8 @@ public function representJson($content) } /** + * Sleep magic method. + * * @return string[] * @codeCoverageIgnore */ diff --git a/lib/internal/Magento/Framework/App/Route/ConfigInterface/Proxy.php b/lib/internal/Magento/Framework/App/Route/ConfigInterface/Proxy.php index fd37590bb7782..09dda9727b937 100644 --- a/lib/internal/Magento/Framework/App/Route/ConfigInterface/Proxy.php +++ b/lib/internal/Magento/Framework/App/Route/ConfigInterface/Proxy.php @@ -60,6 +60,8 @@ public function __construct( } /** + * Sleep magic method. + * * @return array */ public function __sleep() diff --git a/lib/internal/Magento/Framework/DB/Select.php b/lib/internal/Magento/Framework/DB/Select.php index 4d178b81af6df..246e31db3cbbc 100644 --- a/lib/internal/Magento/Framework/DB/Select.php +++ b/lib/internal/Magento/Framework/DB/Select.php @@ -467,9 +467,9 @@ protected function _renderForupdate($sql) /** * Add EXISTS clause * - * @param Select $select - * @param string $joinCondition - * @param bool $isExists + * @param Select $select + * @param string $joinCondition + * @param bool $isExists * @return $this */ public function exists($select, $joinCondition, $isExists = true) @@ -509,6 +509,8 @@ public function assemble() } /** + * Sleep magic method. + * * @return string[] * @since 100.0.11 */ diff --git a/lib/internal/Magento/Framework/DB/Select/RendererProxy.php b/lib/internal/Magento/Framework/DB/Select/RendererProxy.php index 3626f6a07fa18..b6d0803759842 100644 --- a/lib/internal/Magento/Framework/DB/Select/RendererProxy.php +++ b/lib/internal/Magento/Framework/DB/Select/RendererProxy.php @@ -56,6 +56,8 @@ public function __construct( } /** + * Sleep magic method. + * * @return array */ public function __sleep() @@ -99,7 +101,7 @@ protected function _getSubject() } /** - * {@inheritdoc} + * @inheritDoc */ public function render(\Magento\Framework\DB\Select $select, $sql = '') { diff --git a/lib/internal/Magento/Framework/Data/Collection/AbstractDb.php b/lib/internal/Magento/Framework/Data/Collection/AbstractDb.php index 308f2a12f506e..edbf095d8f46d 100644 --- a/lib/internal/Magento/Framework/Data/Collection/AbstractDb.php +++ b/lib/internal/Magento/Framework/Data/Collection/AbstractDb.php @@ -365,10 +365,8 @@ protected function _renderFilters() /** * Hook for operations before rendering filters - * - * @return void */ - protected function _renderFiltersBefore() + protected function _renderFiltersBefore() //phpcs:ignore Magento2.CodeAnalysis.EmptyBlock { } @@ -730,6 +728,7 @@ public function loadData($printQuery = false, $logQuery = false) public function printLogQuery($printQuery = false, $logQuery = false, $sql = null) { if ($printQuery || $this->getFlag('print_query')) { + //phpcs:ignore Magento2.Security.LanguageConstruct echo $sql === null ? $this->getSelect()->__toString() : $sql; } @@ -823,7 +822,7 @@ public function __clone() * * @return void */ - protected function _initSelect() + protected function _initSelect() //phpcs:ignore Magento2.CodeAnalysis.EmptyBlock { // no implementation, should be overridden in children classes } diff --git a/lib/internal/Magento/Framework/DataObject/Copy/Config/Data/Proxy.php b/lib/internal/Magento/Framework/DataObject/Copy/Config/Data/Proxy.php index 880da5db771eb..d8bb7a06e5b7d 100644 --- a/lib/internal/Magento/Framework/DataObject/Copy/Config/Data/Proxy.php +++ b/lib/internal/Magento/Framework/DataObject/Copy/Config/Data/Proxy.php @@ -57,6 +57,8 @@ public function __construct( } /** + * Sleep magic method. + * * @return array */ public function __sleep() @@ -100,7 +102,7 @@ protected function _getSubject() } /** - * {@inheritdoc} + * @inheritDoc */ public function merge(array $config) { @@ -108,7 +110,7 @@ public function merge(array $config) } /** - * {@inheritdoc} + * @inheritDoc */ public function get($path = null, $default = null) { @@ -116,7 +118,7 @@ public function get($path = null, $default = null) } /** - * {@inheritdoc} + * @inheritDoc */ public function reset() { diff --git a/lib/internal/Magento/Framework/Model/AbstractExtensibleModel.php b/lib/internal/Magento/Framework/Model/AbstractExtensibleModel.php index 1cffba2543b0b..387a8d823d0c3 100644 --- a/lib/internal/Magento/Framework/Model/AbstractExtensibleModel.php +++ b/lib/internal/Magento/Framework/Model/AbstractExtensibleModel.php @@ -158,7 +158,7 @@ public function getCustomAttribute($attributeCode) } /** - * {@inheritdoc} + * @inheritDoc */ public function setCustomAttributes(array $attributes) { @@ -166,7 +166,7 @@ public function setCustomAttributes(array $attributes) } /** - * {@inheritdoc} + * @inheritDoc */ public function setCustomAttribute($attributeCode, $attributeValue) { @@ -182,9 +182,7 @@ public function setCustomAttribute($attributeCode, $attributeValue) } /** - * {@inheritdoc} - * - * Added custom attributes support. + * {@inheritdoc} Added custom attributes support. */ public function setData($key, $value = null) { @@ -200,9 +198,7 @@ public function setData($key, $value = null) } /** - * {@inheritdoc} - * - * Unset customAttributesChanged flag + * {@inheritdoc} Unset customAttributesChanged flag */ public function unsetData($key = null) { diff --git a/lib/internal/Magento/Framework/Model/AbstractModel.php b/lib/internal/Magento/Framework/Model/AbstractModel.php index 567d174938b11..e2c731d719be5 100644 --- a/lib/internal/Magento/Framework/Model/AbstractModel.php +++ b/lib/internal/Magento/Framework/Model/AbstractModel.php @@ -199,7 +199,7 @@ public function __construct( * * @return void */ - protected function _construct() + protected function _construct() //phpcs:ignore Magento2.CodeAnalysis.EmptyBlock { } diff --git a/lib/internal/Magento/Framework/Model/ResourceModel/Db/AbstractDb.php b/lib/internal/Magento/Framework/Model/ResourceModel/Db/AbstractDb.php index 1eaed75bcbfdd..c7887c5066e6f 100644 --- a/lib/internal/Magento/Framework/Model/ResourceModel/Db/AbstractDb.php +++ b/lib/internal/Magento/Framework/Model/ResourceModel/Db/AbstractDb.php @@ -220,6 +220,7 @@ protected function _setResource($connections, $tables = null) /** * Set main entity table name and primary key field name + * * If field name is omitted {table_name}_id will be used * * @param string $mainTable @@ -253,8 +254,7 @@ public function getIdFieldName() } /** - * Returns main table name - extracted from "module/table" style and - * validated by db adapter + * Returns main table name - extracted from "module/table" style and validated by db adapter * * @throws LocalizedException * @return string @@ -535,6 +535,7 @@ public function getUniqueFields() * * @param \Magento\Framework\Model\AbstractModel $object * @return array + * @throws LocalizedException */ protected function _prepareDataForSave(\Magento\Framework\Model\AbstractModel $object) { @@ -542,11 +543,11 @@ protected function _prepareDataForSave(\Magento\Framework\Model\AbstractModel $o } /** - * Check that model data fields that can be saved - * has really changed comparing with origData + * Check that model data fields that can be saved has really changed comparing with origData * * @param \Magento\Framework\Model\AbstractModel $object * @return bool + * @throws LocalizedException */ public function hasDataChanged($object) { @@ -728,6 +729,7 @@ public function getChecksum($table) * * @param \Magento\Framework\Model\AbstractModel $object * @return array + * @throws LocalizedException */ protected function prepareDataForUpdate($object) { diff --git a/lib/internal/Magento/Framework/Model/ResourceModel/Db/Collection/AbstractCollection.php b/lib/internal/Magento/Framework/Model/ResourceModel/Db/Collection/AbstractCollection.php index 8ec47ed97e11c..977860d262dbd 100644 --- a/lib/internal/Magento/Framework/Model/ResourceModel/Db/Collection/AbstractCollection.php +++ b/lib/internal/Magento/Framework/Model/ResourceModel/Db/Collection/AbstractCollection.php @@ -137,7 +137,7 @@ public function __construct( * * @return void */ - protected function _construct() + protected function _construct() //phpcs:ignore Magento2.CodeAnalysis.EmptyBlock { } diff --git a/lib/internal/Magento/Framework/Mview/Config/Data/Proxy.php b/lib/internal/Magento/Framework/Mview/Config/Data/Proxy.php index a83e9507bda04..470ba16bdd40c 100644 --- a/lib/internal/Magento/Framework/Mview/Config/Data/Proxy.php +++ b/lib/internal/Magento/Framework/Mview/Config/Data/Proxy.php @@ -55,6 +55,8 @@ public function __construct( } /** + * Sleep magic method. + * * @return array */ public function __sleep() @@ -100,7 +102,7 @@ protected function _getSubject() } /** - * {@inheritdoc} + * @inheritDoc */ public function merge(array $config) { @@ -108,7 +110,7 @@ public function merge(array $config) } /** - * {@inheritdoc} + * @inheritDoc */ public function get($path = null, $default = null) { diff --git a/lib/internal/Magento/Framework/Translate/Inline/Proxy.php b/lib/internal/Magento/Framework/Translate/Inline/Proxy.php index 370a88d6d9a43..ae03c7cfeddf4 100644 --- a/lib/internal/Magento/Framework/Translate/Inline/Proxy.php +++ b/lib/internal/Magento/Framework/Translate/Inline/Proxy.php @@ -55,6 +55,8 @@ public function __construct( } /** + * Sleep magic method. + * * @return array */ public function __sleep() diff --git a/lib/internal/Magento/Framework/View/Layout/Proxy.php b/lib/internal/Magento/Framework/View/Layout/Proxy.php index 03020307c5380..ec5ce761154ed 100644 --- a/lib/internal/Magento/Framework/View/Layout/Proxy.php +++ b/lib/internal/Magento/Framework/View/Layout/Proxy.php @@ -57,6 +57,8 @@ public function __construct( } /** + * Sleep magic method. + * * @return array */ public function __sleep() @@ -100,7 +102,7 @@ protected function _getSubject() } /** - * {@inheritdoc} + * @inheritDoc */ public function setGeneratorPool(\Magento\Framework\View\Layout\GeneratorPool $generatorPool) { @@ -108,7 +110,7 @@ public function setGeneratorPool(\Magento\Framework\View\Layout\GeneratorPool $g } /** - * {@inheritdoc} + * @inheritDoc */ public function setBuilder(\Magento\Framework\View\Layout\BuilderInterface $builder) { @@ -116,7 +118,7 @@ public function setBuilder(\Magento\Framework\View\Layout\BuilderInterface $buil } /** - * {@inheritdoc} + * @inheritDoc */ public function publicBuild() { @@ -124,7 +126,7 @@ public function publicBuild() } /** - * {@inheritdoc} + * @inheritDoc */ public function getUpdate() { @@ -132,7 +134,7 @@ public function getUpdate() } /** - * {@inheritdoc} + * @inheritDoc */ public function generateXml() { @@ -140,7 +142,7 @@ public function generateXml() } /** - * {@inheritdoc} + * @inheritDoc */ public function generateElements() { @@ -148,7 +150,7 @@ public function generateElements() } /** - * {@inheritdoc} + * @inheritDoc */ public function getChildBlock($parentName, $alias) { @@ -156,7 +158,7 @@ public function getChildBlock($parentName, $alias) } /** - * {@inheritdoc} + * @inheritDoc */ public function setChild($parentName, $elementName, $alias) { @@ -164,7 +166,7 @@ public function setChild($parentName, $elementName, $alias) } /** - * {@inheritdoc} + * @inheritDoc */ public function reorderChild($parentName, $childName, $offsetOrSibling, $after = true) { @@ -172,7 +174,7 @@ public function reorderChild($parentName, $childName, $offsetOrSibling, $after = } /** - * {@inheritdoc} + * @inheritDoc */ public function unsetChild($parentName, $alias) { @@ -180,7 +182,7 @@ public function unsetChild($parentName, $alias) } /** - * {@inheritdoc} + * @inheritDoc */ public function getChildNames($parentName) { @@ -188,7 +190,7 @@ public function getChildNames($parentName) } /** - * {@inheritdoc} + * @inheritDoc */ public function getChildBlocks($parentName) { @@ -196,7 +198,7 @@ public function getChildBlocks($parentName) } /** - * {@inheritdoc} + * @inheritDoc */ public function getChildName($parentName, $alias) { @@ -204,7 +206,7 @@ public function getChildName($parentName, $alias) } /** - * {@inheritdoc} + * @inheritDoc */ public function renderElement($name, $useCache = true) { @@ -212,7 +214,7 @@ public function renderElement($name, $useCache = true) } /** - * {@inheritdoc} + * @inheritDoc */ public function renderNonCachedElement($name) { @@ -220,7 +222,7 @@ public function renderNonCachedElement($name) } /** - * {@inheritdoc} + * @inheritDoc */ public function addToParentGroup($blockName, $parentGroupName) { @@ -228,7 +230,7 @@ public function addToParentGroup($blockName, $parentGroupName) } /** - * {@inheritdoc} + * @inheritDoc */ public function getGroupChildNames($blockName, $groupName) { @@ -236,7 +238,7 @@ public function getGroupChildNames($blockName, $groupName) } /** - * {@inheritdoc} + * @inheritDoc */ public function hasElement($name) { @@ -244,7 +246,7 @@ public function hasElement($name) } /** - * {@inheritdoc} + * @inheritDoc */ public function getElementProperty($name, $attribute) { @@ -252,7 +254,7 @@ public function getElementProperty($name, $attribute) } /** - * {@inheritdoc} + * @inheritDoc */ public function isBlock($name) { @@ -260,7 +262,7 @@ public function isBlock($name) } /** - * {@inheritdoc} + * @inheritDoc */ public function isUiComponent($name) { @@ -268,7 +270,7 @@ public function isUiComponent($name) } /** - * {@inheritdoc} + * @inheritDoc */ public function isContainer($name) { @@ -276,7 +278,7 @@ public function isContainer($name) } /** - * {@inheritdoc} + * @inheritDoc */ public function isManipulationAllowed($name) { @@ -284,7 +286,7 @@ public function isManipulationAllowed($name) } /** - * {@inheritdoc} + * @inheritDoc */ public function setBlock($name, $block) { @@ -292,7 +294,7 @@ public function setBlock($name, $block) } /** - * {@inheritdoc} + * @inheritDoc */ public function unsetElement($name) { @@ -300,7 +302,7 @@ public function unsetElement($name) } /** - * {@inheritdoc} + * @inheritDoc */ public function createBlock($type, $name = '', array $arguments = []) { @@ -308,7 +310,7 @@ public function createBlock($type, $name = '', array $arguments = []) } /** - * {@inheritdoc} + * @inheritDoc */ public function addBlock($block, $name = '', $parent = '', $alias = '') { @@ -316,7 +318,7 @@ public function addBlock($block, $name = '', $parent = '', $alias = '') } /** - * {@inheritdoc} + * @inheritDoc */ public function addContainer($name, $label, array $options = [], $parent = '', $alias = '') { @@ -324,7 +326,7 @@ public function addContainer($name, $label, array $options = [], $parent = '', $ } /** - * {@inheritdoc} + * @inheritDoc */ public function renameElement($oldName, $newName) { @@ -332,7 +334,7 @@ public function renameElement($oldName, $newName) } /** - * {@inheritdoc} + * @inheritDoc */ public function getAllBlocks() { @@ -340,7 +342,7 @@ public function getAllBlocks() } /** - * {@inheritdoc} + * @inheritDoc */ public function getBlock($name) { @@ -348,7 +350,7 @@ public function getBlock($name) } /** - * {@inheritdoc} + * @inheritDoc */ public function getUiComponent($name) { @@ -356,7 +358,7 @@ public function getUiComponent($name) } /** - * {@inheritdoc} + * @inheritDoc */ public function getParentName($childName) { @@ -364,7 +366,7 @@ public function getParentName($childName) } /** - * {@inheritdoc} + * @inheritDoc */ public function getElementAlias($name) { @@ -372,7 +374,7 @@ public function getElementAlias($name) } /** - * {@inheritdoc} + * @inheritDoc */ public function addOutputElement($name) { @@ -380,7 +382,7 @@ public function addOutputElement($name) } /** - * {@inheritdoc} + * @inheritDoc */ public function removeOutputElement($name) { @@ -388,7 +390,7 @@ public function removeOutputElement($name) } /** - * {@inheritdoc} + * @inheritDoc */ public function getOutput() { @@ -396,7 +398,7 @@ public function getOutput() } /** - * {@inheritdoc} + * @inheritDoc */ public function getMessagesBlock() { @@ -404,7 +406,7 @@ public function getMessagesBlock() } /** - * {@inheritdoc} + * @inheritDoc */ public function getBlockSingleton($type) { @@ -412,7 +414,7 @@ public function getBlockSingleton($type) } /** - * {@inheritdoc} + * @inheritDoc */ public function addAdjustableRenderer($namespace, $staticType, $dynamicType, $type, $template, $data = []) { @@ -427,7 +429,7 @@ public function addAdjustableRenderer($namespace, $staticType, $dynamicType, $ty } /** - * {@inheritdoc} + * @inheritDoc */ public function getRendererOptions($namespace, $staticType, $dynamicType) { @@ -435,7 +437,7 @@ public function getRendererOptions($namespace, $staticType, $dynamicType) } /** - * {@inheritdoc} + * @inheritDoc */ public function executeRenderer($namespace, $staticType, $dynamicType, $data = []) { @@ -443,7 +445,7 @@ public function executeRenderer($namespace, $staticType, $dynamicType, $data = [ } /** - * {@inheritdoc} + * @inheritDoc */ public function initMessages($messageGroups = []) { @@ -451,7 +453,7 @@ public function initMessages($messageGroups = []) } /** - * {@inheritdoc} + * @inheritDoc */ public function isCacheable() { @@ -459,7 +461,7 @@ public function isCacheable() } /** - * {@inheritdoc} + * @inheritDoc */ public function isPrivate() { @@ -467,7 +469,7 @@ public function isPrivate() } /** - * {@inheritdoc} + * @inheritDoc */ public function setIsPrivate($isPrivate = true) { @@ -475,7 +477,7 @@ public function setIsPrivate($isPrivate = true) } /** - * {@inheritdoc} + * @inheritDoc */ public function getReaderContext() { @@ -483,7 +485,7 @@ public function getReaderContext() } /** - * {@inheritdoc} + * @inheritDoc */ public function setXml(\Magento\Framework\Simplexml\Element $node) { @@ -491,7 +493,7 @@ public function setXml(\Magento\Framework\Simplexml\Element $node) } /** - * {@inheritdoc} + * @inheritDoc */ public function getNode($path = null) { @@ -499,7 +501,7 @@ public function getNode($path = null) } /** - * {@inheritdoc} + * @inheritDoc */ public function getXpath($xpath) { @@ -507,7 +509,7 @@ public function getXpath($xpath) } /** - * {@inheritdoc} + * @inheritDoc */ public function getXmlString() { @@ -515,7 +517,7 @@ public function getXmlString() } /** - * {@inheritdoc} + * @inheritDoc */ public function loadFile($filePath) { @@ -523,7 +525,7 @@ public function loadFile($filePath) } /** - * {@inheritdoc} + * @inheritDoc */ public function loadString($string) { @@ -531,7 +533,7 @@ public function loadString($string) } /** - * {@inheritdoc} + * @inheritDoc */ public function loadDom(\DOMNode $dom) { @@ -539,7 +541,7 @@ public function loadDom(\DOMNode $dom) } /** - * {@inheritdoc} + * @inheritDoc */ public function setNode($path, $value, $overwrite = true) { @@ -547,7 +549,7 @@ public function setNode($path, $value, $overwrite = true) } /** - * {@inheritdoc} + * @inheritDoc */ public function applyExtends() { @@ -555,7 +557,7 @@ public function applyExtends() } /** - * {@inheritdoc} + * @inheritDoc */ public function processFileData($text) { @@ -563,7 +565,7 @@ public function processFileData($text) } /** - * {@inheritdoc} + * @inheritDoc */ public function extend(\Magento\Framework\Simplexml\Config $config, $overwrite = true) { From b557642f198be14e57310a5d3d4c450975ca209c Mon Sep 17 00:00:00 2001 From: Cristian Partica <cpartica@magento.com> Date: Fri, 3 May 2019 14:00:42 -0500 Subject: [PATCH 345/773] MC-15959: Implement caching for url resolver - refactor tests to support HIT & invalidation --- .../Controller/Cms/BlockCacheTest.php | 80 +++++++++++- .../Controller/Cms/CmsPageCacheTest.php | 39 +++++- .../CategoryUrlResolverCacheTest.php | 119 +++++++++++++++++- .../CmsPageUrlResolverCacheTest.php | 70 ----------- .../ProductUrlResolverCacheTest.php | 74 ----------- 5 files changed, 228 insertions(+), 154 deletions(-) delete mode 100644 dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/UrlRewrite/CmsPageUrlResolverCacheTest.php delete mode 100644 dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/UrlRewrite/ProductUrlResolverCacheTest.php diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/BlockCacheTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/BlockCacheTest.php index 1ee7676c85c31..c9dca2a5a8372 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/BlockCacheTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/BlockCacheTest.php @@ -38,17 +38,22 @@ protected function setUp(): void * Test that the correct cache tags get added to request for cmsBlocks * * @magentoDataFixture Magento/Cms/_files/block.php + * @magentoDataFixture Magento/Cms/_files/blocks.php */ public function testCmsBlocksRequestHasCorrectTags(): void { - $blockIdentifier = 'fixture_block'; + /** @var BlockRepository $blockRepository */ $blockRepository = $this->objectManager->get(BlockRepository::class); - $block = $blockRepository->getById($blockIdentifier); - $query + $block1Identifier = 'fixture_block'; + $block1 = $blockRepository->getById($block1Identifier); + $block2Identifier = 'enabled_block'; + $block2 = $blockRepository->getById($block2Identifier); + + $queryBlock1 = <<<QUERY { - cmsBlocks(identifiers: ["$blockIdentifier"]) { + cmsBlocks(identifiers: ["$block1Identifier"]) { items { title identifier @@ -57,10 +62,73 @@ public function testCmsBlocksRequestHasCorrectTags(): void } } QUERY; - $request = $this->prepareRequest($query); + + $queryBlock2 + = <<<QUERY + { + cmsBlocks(identifiers: ["$block2Identifier"]) { + items { + title + identifier + content + } + } +} +QUERY; + + // check to see that the first entity gets a MISS when called the first time + $request = $this->prepareRequest($queryBlock1); + $response = $this->graphqlController->dispatch($request); + $this->assertEquals('MISS', $response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); + $expectedCacheTags = ['cms_b', 'cms_b_' . $block1->getId(), 'cms_b_' . $block1->getIdentifier(), 'FPC']; + $rawActualCacheTags = $response->getHeader('X-Magento-Tags')->getFieldValue(); + $actualCacheTags = explode(',', $rawActualCacheTags); + $this->assertEquals($expectedCacheTags, $actualCacheTags); + + // check to see that the second entity gets a miss when called the first time + $request = $this->prepareRequest($queryBlock2); $response = $this->graphqlController->dispatch($request); $this->assertEquals('MISS', $response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); - $expectedCacheTags = ['cms_b', 'cms_b_' . $block->getId(), 'cms_b_' . $block->getIdentifier(), 'FPC']; + $expectedCacheTags = ['cms_b', 'cms_b_' . $block2->getId(), 'cms_b_' . $block2->getIdentifier(), 'FPC']; + $rawActualCacheTags = $response->getHeader('X-Magento-Tags')->getFieldValue(); + $actualCacheTags = explode(',', $rawActualCacheTags); + $this->assertEquals($expectedCacheTags, $actualCacheTags); + + // check to see that the first entity gets a HIT when called the second time + $request = $this->prepareRequest($queryBlock1); + $response = $this->graphqlController->dispatch($request); + $this->assertEquals('HIT', $response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); + $expectedCacheTags = ['cms_b', 'cms_b_' . $block1->getId(), 'cms_b_' . $block1->getIdentifier(), 'FPC']; + $rawActualCacheTags = $response->getHeader('X-Magento-Tags')->getFieldValue(); + $actualCacheTags = explode(',', $rawActualCacheTags); + $this->assertEquals($expectedCacheTags, $actualCacheTags); + + // check to see that the second entity gets a HIT when called the second time + $request = $this->prepareRequest($queryBlock2); + $response = $this->graphqlController->dispatch($request); + $this->assertEquals('HIT', $response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); + $expectedCacheTags = ['cms_b', 'cms_b_' . $block2->getId(), 'cms_b_' . $block2->getIdentifier(), 'FPC']; + $rawActualCacheTags = $response->getHeader('X-Magento-Tags')->getFieldValue(); + $actualCacheTags = explode(',', $rawActualCacheTags); + $this->assertEquals($expectedCacheTags, $actualCacheTags); + + $block1->setTitle('something else that causes invalidation'); + $blockRepository->save($block1); + + // check to see that the first entity gets a MISS and it was invalidated + $request = $this->prepareRequest($queryBlock1); + $response = $this->graphqlController->dispatch($request); + $this->assertEquals('MISS', $response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); + $expectedCacheTags = ['cms_b', 'cms_b_' . $block1->getId(), 'cms_b_' . $block1->getIdentifier(), 'FPC']; + $rawActualCacheTags = $response->getHeader('X-Magento-Tags')->getFieldValue(); + $actualCacheTags = explode(',', $rawActualCacheTags); + $this->assertEquals($expectedCacheTags, $actualCacheTags); + + // check to see that the first entity gets a HIT when called the second time + $request = $this->prepareRequest($queryBlock1); + $response = $this->graphqlController->dispatch($request); + $this->assertEquals('HIT', $response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); + $expectedCacheTags = ['cms_b', 'cms_b_' . $block1->getId(), 'cms_b_' . $block1->getIdentifier(), 'FPC']; $rawActualCacheTags = $response->getHeader('X-Magento-Tags')->getFieldValue(); $actualCacheTags = explode(',', $rawActualCacheTags); $this->assertEquals($expectedCacheTags, $actualCacheTags); diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/CmsPageCacheTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/CmsPageCacheTest.php index e3d6259d32d40..d6dcf07409140 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/CmsPageCacheTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/CmsPageCacheTest.php @@ -8,6 +8,7 @@ namespace Magento\GraphQlCache\Controller\Cms; use Magento\Cms\Model\GetPageByIdentifier; +use Magento\Cms\Model\PageRepository; use Magento\GraphQl\Controller\GraphQl; use Magento\GraphQlCache\Controller\AbstractGraphqlCacheTest; @@ -80,6 +81,7 @@ public function testToCheckCmsPageRequestCacheTags(): void } QUERY; + // check to see that the first entity gets a MISS when called the first time $request = $this->prepareRequest($queryCmsPage100); $response = $this->graphqlController->dispatch($request); $this->assertEquals( @@ -90,7 +92,8 @@ public function testToCheckCmsPageRequestCacheTags(): void $requestedCacheTags = explode(',', $response->getHeader('X-Magento-Tags')->getFieldValue()); $expectedCacheTags = ['cms_p', 'cms_p_' .$pageId100 , 'FPC']; $this->assertEquals($expectedCacheTags, $requestedCacheTags); - + + // check to see that the second entity gets a miss when called the first time $request = $this->prepareRequest($queryCmsPageBlank); $response = $this->graphqlController->dispatch($request); $this->assertEquals( @@ -102,6 +105,7 @@ public function testToCheckCmsPageRequestCacheTags(): void $expectedCacheTags = ['cms_p', 'cms_p_' .$pageIdBlank , 'FPC']; $this->assertEquals($expectedCacheTags, $requestedCacheTags); + // check to see that the first entity gets a HIT when called the second time $request = $this->prepareRequest($queryCmsPage100); $response = $this->graphqlController->dispatch($request); $this->assertEquals( @@ -113,6 +117,7 @@ public function testToCheckCmsPageRequestCacheTags(): void $expectedCacheTags = ['cms_p', 'cms_p_' .$pageId100 , 'FPC']; $this->assertEquals($expectedCacheTags, $requestedCacheTags); + // check to see that the second entity gets a HIT when called the second time $request = $this->prepareRequest($queryCmsPageBlank); $response = $this->graphqlController->dispatch($request); $this->assertEquals( @@ -123,5 +128,37 @@ public function testToCheckCmsPageRequestCacheTags(): void $requestedCacheTags = explode(',', $response->getHeader('X-Magento-Tags')->getFieldValue()); $expectedCacheTags = ['cms_p', 'cms_p_' .$pageIdBlank , 'FPC']; $this->assertEquals($expectedCacheTags, $requestedCacheTags); + + + /** @var PageRepository $pageRepository */ + $pageRepository = $this->objectManager->get(PageRepository::class); + + $page = $pageRepository->getById($pageId100); + $page->setTitle('something else that causes invalidation'); + $pageRepository->save($page); + + // check to see that the first entity gets a MISS and it was invalidated + $request = $this->prepareRequest($queryCmsPage100); + $response = $this->graphqlController->dispatch($request); + $this->assertEquals( + 'MISS', + $response->getHeader('X-Magento-Cache-Debug')->getFieldValue(), + "expected MISS on page page100 id {$queryCmsPage100}" + ); + $requestedCacheTags = explode(',', $response->getHeader('X-Magento-Tags')->getFieldValue()); + $expectedCacheTags = ['cms_p', 'cms_p_' .$pageId100 , 'FPC']; + $this->assertEquals($expectedCacheTags, $requestedCacheTags); + + // check to see that the first entity gets a HIT when called the second time + $request = $this->prepareRequest($queryCmsPage100); + $response = $this->graphqlController->dispatch($request); + $this->assertEquals( + 'HIT', + $response->getHeader('X-Magento-Cache-Debug')->getFieldValue(), + "expected MISS on page page100 id {$queryCmsPage100}" + ); + $requestedCacheTags = explode(',', $response->getHeader('X-Magento-Tags')->getFieldValue()); + $expectedCacheTags = ['cms_p', 'cms_p_' .$pageId100 , 'FPC']; + $this->assertEquals($expectedCacheTags, $requestedCacheTags); } } diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/UrlRewrite/CategoryUrlResolverCacheTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/UrlRewrite/CategoryUrlResolverCacheTest.php index 9070151f1ce12..c42d88eeb21b1 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/UrlRewrite/CategoryUrlResolverCacheTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/UrlRewrite/CategoryUrlResolverCacheTest.php @@ -12,6 +12,8 @@ use Magento\GraphQl\Controller\GraphQl; use Magento\GraphQlCache\Controller\AbstractGraphqlCacheTest; use Magento\UrlRewrite\Model\UrlFinderInterface; +use Magento\Cms\Api\Data\PageInterface; +use Magento\Cms\Api\GetPageByIdentifierInterface; /** * Test caching works for categoryUrlResolver @@ -26,6 +28,7 @@ class CategoryUrlResolverCacheTest extends AbstractGraphqlCacheTest * @var GraphQl */ private $graphqlController; + /** * @inheritdoc */ @@ -39,10 +42,12 @@ protected function setUp(): void * Tests that X-Magento-tags and cache debug headers are correct for category urlResolver * * @magentoDataFixture Magento/CatalogUrlRewrite/_files/product_with_category.php + * @magentoDataFixture Magento/Cms/_files/pages.php */ public function testCategoryUrlResolverRequestHasCorrectTags() { $categoryUrlKey = 'cat-1.html'; + $productUrlKey = 'p002.html'; $productSku = 'p002'; /** @var ProductRepositoryInterface $productRepository */ $productRepository = $this->objectManager->get(ProductRepositoryInterface::class); @@ -59,7 +64,7 @@ public function testCategoryUrlResolverRequestHasCorrectTags() ] ); $categoryId = $actualUrls->getEntityId(); - $query + $categoryQuery = <<<QUERY { urlResolver(url:"{$categoryUrlKey}") @@ -71,13 +76,121 @@ public function testCategoryUrlResolverRequestHasCorrectTags() } } QUERY; - $request = $this->prepareRequest($query); - /** @var \Magento\Framework\App\Response\Http $response */ + + $productQuery = <<<QUERY +{ + urlResolver(url:"{$productUrlKey}") + { + id + relative_url + canonical_url + type + } +} +QUERY; + + /** @var GetPageByIdentifierInterface $page */ + $page = $this->objectManager->get(GetPageByIdentifierInterface::class); + /** @var PageInterface $cmsPage */ + $cmsPage = $page->execute('page100', 0); + $cmsPageId = $cmsPage->getId(); + $requestPath = $cmsPage->getIdentifier(); + $pageQuery + = <<<QUERY +{ + urlResolver(url:"{$requestPath}") + { + id + relative_url + canonical_url + type + } +} +QUERY; + // query category for MISS + $request = $this->prepareRequest($categoryQuery); + $response = $this->graphqlController->dispatch($request); + $this->assertEquals('MISS', $response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); + $expectedCacheTags = ['cat_c','cat_c_' . $categoryId, 'FPC']; + $rawActualCacheTags = $response->getHeader('X-Magento-Tags')->getFieldValue(); + $actualCacheTags = explode(',', $rawActualCacheTags); + $this->assertEquals($expectedCacheTags, $actualCacheTags); + + // query product for MISS + $request = $this->prepareRequest($productQuery); + $response = $this->graphqlController->dispatch($request); + $this->assertEquals('MISS', $response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); + $expectedCacheTags = ['cat_p', 'cat_p_' . $product->getId(), 'FPC']; + $rawActualCacheTags = $response->getHeader('X-Magento-Tags')->getFieldValue(); + $actualCacheTags = explode(',', $rawActualCacheTags); + $this->assertEquals($expectedCacheTags, $actualCacheTags); + + // query page for MISS + $request = $this->prepareRequest($pageQuery); + $response = $this->graphqlController->dispatch($request); + $this->assertEquals('MISS', $response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); + $expectedCacheTags = ['cms_p','cms_p_' . $cmsPageId,'FPC']; + $rawActualCacheTags = $response->getHeader('X-Magento-Tags')->getFieldValue(); + $actualCacheTags = explode(',', $rawActualCacheTags); + $this->assertEquals($expectedCacheTags, $actualCacheTags); + + // query category for HIT + $request = $this->prepareRequest($categoryQuery); + $response = $this->graphqlController->dispatch($request); + $this->assertEquals('HIT', $response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); + $expectedCacheTags = ['cat_c','cat_c_' . $categoryId, 'FPC']; + $rawActualCacheTags = $response->getHeader('X-Magento-Tags')->getFieldValue(); + $actualCacheTags = explode(',', $rawActualCacheTags); + $this->assertEquals($expectedCacheTags, $actualCacheTags); + + // query product for HIT + $request = $this->prepareRequest($productQuery); + $response = $this->graphqlController->dispatch($request); + $this->assertEquals('HIT', $response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); + $expectedCacheTags = ['cat_p', 'cat_p_' . $product->getId(), 'FPC']; + $rawActualCacheTags = $response->getHeader('X-Magento-Tags')->getFieldValue(); + $actualCacheTags = explode(',', $rawActualCacheTags); + $this->assertEquals($expectedCacheTags, $actualCacheTags); + + // query product for HIT + $request = $this->prepareRequest($pageQuery); + $response = $this->graphqlController->dispatch($request); + $this->assertEquals('HIT', $response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); + $expectedCacheTags = ['cms_p','cms_p_' . $cmsPageId,'FPC']; + $rawActualCacheTags = $response->getHeader('X-Magento-Tags')->getFieldValue(); + $actualCacheTags = explode(',', $rawActualCacheTags); + $this->assertEquals($expectedCacheTags, $actualCacheTags); + + $product->setUrlKey('something-else-that-invalidates-the-cache'); + $productRepository->save($product); + $productQuery = <<<QUERY +{ + urlResolver(url:"something-else-that-invalidates-the-cache.html") + { + id + relative_url + canonical_url + type + } +} +QUERY; + + // query category for MISS + $request = $this->prepareRequest($categoryQuery); $response = $this->graphqlController->dispatch($request); $this->assertEquals('MISS', $response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); $expectedCacheTags = ['cat_c','cat_c_' . $categoryId, 'FPC']; $rawActualCacheTags = $response->getHeader('X-Magento-Tags')->getFieldValue(); $actualCacheTags = explode(',', $rawActualCacheTags); $this->assertEquals($expectedCacheTags, $actualCacheTags); + + // query product for HIT + $request = $this->prepareRequest($productQuery); + $response = $this->graphqlController->dispatch($request); + $this->assertEquals('MISS', $response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); + $expectedCacheTags = ['cat_p', 'cat_p_' . $product->getId(), 'FPC']; + $rawActualCacheTags = $response->getHeader('X-Magento-Tags')->getFieldValue(); + $actualCacheTags = explode(',', $rawActualCacheTags); + $this->assertEquals($expectedCacheTags, $actualCacheTags); } } diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/UrlRewrite/CmsPageUrlResolverCacheTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/UrlRewrite/CmsPageUrlResolverCacheTest.php deleted file mode 100644 index db9a4671e8098..0000000000000 --- a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/UrlRewrite/CmsPageUrlResolverCacheTest.php +++ /dev/null @@ -1,70 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -declare(strict_types=1); - -namespace Magento\GraphQlCache\Controller\UrlRewrite; - -use Magento\Cms\Api\Data\PageInterface; -use Magento\Cms\Api\GetPageByIdentifierInterface; -use Magento\GraphQl\Controller\GraphQl; -use Magento\GraphQlCache\Controller\AbstractGraphqlCacheTest; - -/** - * Test caching works for cmsPage UrlResolver - * - * @magentoAppArea graphql - * @magentoCache full_page enabled - * @magentoDbIsolation disabled - */ -class CmsPageUrlResolverCacheTest extends AbstractGraphqlCacheTest -{ - /** - * @var GraphQl - */ - private $graphqlController; - - /** - * @inheritdoc - */ - protected function setUp(): void - { - parent::setUp(); - $this->graphqlController = $this->objectManager->get(GraphQl::class); - } - - /** - * @magentoDataFixture Magento/Cms/_files/pages.php - */ - public function testCmsUrlResolverRequestHasCorrectTags() - { - /** @var GetPageByIdentifierInterface $page */ - $page = $this->objectManager->get(GetPageByIdentifierInterface::class); - /** @var PageInterface $cmsPage */ - $cmsPage = $page->execute('page100', 0); - $cmsPageId = $cmsPage->getId(); - $requestPath = $cmsPage->getIdentifier(); - $query - = <<<QUERY -{ - urlResolver(url:"{$requestPath}") - { - id - relative_url - canonical_url - type - } -} -QUERY; - $request = $this->prepareRequest($query); - /** @var \Magento\Framework\App\Response\Http $response */ - $response = $this->graphqlController->dispatch($request); - $this->assertEquals('MISS', $response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); - $expectedCacheTags = ['cms_p','cms_p_' . $cmsPageId,'FPC']; - $rawActualCacheTags = $response->getHeader('X-Magento-Tags')->getFieldValue(); - $actualCacheTags = explode(',', $rawActualCacheTags); - $this->assertEquals($expectedCacheTags, $actualCacheTags); - } -} diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/UrlRewrite/ProductUrlResolverCacheTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/UrlRewrite/ProductUrlResolverCacheTest.php deleted file mode 100644 index 8162fc9a28e6d..0000000000000 --- a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/UrlRewrite/ProductUrlResolverCacheTest.php +++ /dev/null @@ -1,74 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -declare(strict_types=1); - -namespace Magento\GraphQlCache\Controller\UrlRewrite; - -use Magento\Catalog\Api\ProductRepositoryInterface; -use Magento\Catalog\Model\Product; -use Magento\GraphQl\Controller\GraphQl; -use Magento\GraphQlCache\Controller\AbstractGraphqlCacheTest; - -/** - * Test caching works for product urlResolver - * - * @magentoAppArea graphql - * @magentoCache full_page enabled - * @magentoDbIsolation disabled - */ -class ProductUrlResolverCacheTest extends AbstractGraphqlCacheTest -{ - /** - * @var GraphQl - */ - private $graphqlController; - - /** - * @inheritdoc - */ - protected function setUp(): void - { - parent::setUp(); - $this->graphqlController = $this->objectManager->get(GraphQl::class); - } - - /** - * Test that the correct cache tags get added to request for product urlResolver - * - * @magentoDataFixture Magento/CatalogUrlRewrite/_files/product_with_category.php - */ - public function testProductUrlResolverRequestHasCorrectTags(): void - { - $productSku = 'p002'; - $urlKey = 'p002.html'; - - /** @var ProductRepositoryInterface $productRepository */ - $productRepository = $this->objectManager->get(ProductRepositoryInterface::class); - - /** @var Product $product */ - $product = $productRepository->get($productSku, false, null, true); - - $query = <<<QUERY -{ - urlResolver(url:"{$urlKey}") - { - id - relative_url - canonical_url - type - } -} -QUERY; - $request = $this->prepareRequest($query); - /** @var \Magento\Framework\App\Response\Http $response */ - $response = $this->graphqlController->dispatch($request); - $this->assertEquals('MISS', $response->getHeader('X-Magento-Cache-Debug')->getFieldValue()); - $expectedCacheTags = ['cat_p', 'cat_p_' . $product->getId(), 'FPC']; - $rawActualCacheTags = $response->getHeader('X-Magento-Tags')->getFieldValue(); - $actualCacheTags = explode(',', $rawActualCacheTags); - $this->assertEquals($expectedCacheTags, $actualCacheTags); - } -} From 97c2d9824527aadfbeedf0d7ed39f3de29ec71fa Mon Sep 17 00:00:00 2001 From: Cristian Partica <cpartica@magento.com> Date: Fri, 3 May 2019 14:06:27 -0500 Subject: [PATCH 346/773] MC-15959: Implement caching for url resolver - refactor tests to support HIT & invalidation --- ...olverCacheTest.php => AllEntitiesUrlResolverCacheTest.php} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/UrlRewrite/{CategoryUrlResolverCacheTest.php => AllEntitiesUrlResolverCacheTest.php} (98%) diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/UrlRewrite/CategoryUrlResolverCacheTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/UrlRewrite/AllEntitiesUrlResolverCacheTest.php similarity index 98% rename from dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/UrlRewrite/CategoryUrlResolverCacheTest.php rename to dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/UrlRewrite/AllEntitiesUrlResolverCacheTest.php index c42d88eeb21b1..908739f798366 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/UrlRewrite/CategoryUrlResolverCacheTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/UrlRewrite/AllEntitiesUrlResolverCacheTest.php @@ -22,7 +22,7 @@ * @magentoCache full_page enabled * @magentoDbIsolation disabled */ -class CategoryUrlResolverCacheTest extends AbstractGraphqlCacheTest +class AllEntitiesUrlResolverCacheTest extends AbstractGraphqlCacheTest { /** * @var GraphQl @@ -44,7 +44,7 @@ protected function setUp(): void * @magentoDataFixture Magento/CatalogUrlRewrite/_files/product_with_category.php * @magentoDataFixture Magento/Cms/_files/pages.php */ - public function testCategoryUrlResolverRequestHasCorrectTags() + public function testAllEntitiesUrlResolverRequestHasCorrectTags() { $categoryUrlKey = 'cat-1.html'; $productUrlKey = 'p002.html'; From 9e07db1fdc118903b58da1ee1e1d51baf6e35b9b Mon Sep 17 00:00:00 2001 From: Max Lesechko <mlesechko@magento.com> Date: Fri, 3 May 2019 14:05:06 -0500 Subject: [PATCH 347/773] MC-16106: [2.3] Failed UI upgrade --- app/code/Magento/Authorization/Model/Role.php | 2 +- app/code/Magento/Backend/Model/Auth/Session.php | 1 + app/code/Magento/User/Model/User.php | 1 - lib/internal/Magento/Framework/App/Response/Http.php | 2 ++ .../Magento/Framework/Model/AbstractExtensibleModel.php | 7 +++++++ lib/internal/Magento/Framework/Translate/Inline/Proxy.php | 2 +- 6 files changed, 12 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Authorization/Model/Role.php b/app/code/Magento/Authorization/Model/Role.php index 75e9e79c9d36b..fc32fbcaa2e98 100644 --- a/app/code/Magento/Authorization/Model/Role.php +++ b/app/code/Magento/Authorization/Model/Role.php @@ -40,7 +40,7 @@ class Role extends \Magento\Framework\Model\AbstractModel * @param \Magento\Authorization\Model\ResourceModel\Role\Collection $resourceCollection * @param array $data */ - public function __construct( + public function __construct( //phpcs:ignore Generic.CodeAnalysis.UselessOverridingMethod \Magento\Framework\Model\Context $context, \Magento\Framework\Registry $registry, \Magento\Authorization\Model\ResourceModel\Role $resource, diff --git a/app/code/Magento/Backend/Model/Auth/Session.php b/app/code/Magento/Backend/Model/Auth/Session.php index 31709705f2507..809b78b7b98bc 100644 --- a/app/code/Magento/Backend/Model/Auth/Session.php +++ b/app/code/Magento/Backend/Model/Auth/Session.php @@ -20,6 +20,7 @@ * @method \Magento\Backend\Model\Auth\Session setUpdatedAt(int $value) * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * @SuppressWarnings(PHPMD.CookieAndSessionMisuse) * @todo implement solution that keeps is_first_visit flag in session during redirects * @api * @since 100.0.2 diff --git a/app/code/Magento/User/Model/User.php b/app/code/Magento/User/Model/User.php index cf514bab38dcf..dc0aa0cd38343 100644 --- a/app/code/Magento/User/Model/User.php +++ b/app/code/Magento/User/Model/User.php @@ -448,7 +448,6 @@ public function roleUserExists() * @throws NotificationExceptionInterface * @deprecated * @see NotificatorInterface::sendForgotPassword() - * */ public function sendPasswordResetConfirmationEmail() { diff --git a/lib/internal/Magento/Framework/App/Response/Http.php b/lib/internal/Magento/Framework/App/Response/Http.php index 36604c78953d2..e6fff90837d9d 100644 --- a/lib/internal/Magento/Framework/App/Response/Http.php +++ b/lib/internal/Magento/Framework/App/Response/Http.php @@ -18,6 +18,8 @@ /** * HTTP response + * + * @SuppressWarnings(PHPMD.CookieAndSessionMisuse) */ class Http extends \Magento\Framework\HTTP\PhpEnvironment\Response { diff --git a/lib/internal/Magento/Framework/Model/AbstractExtensibleModel.php b/lib/internal/Magento/Framework/Model/AbstractExtensibleModel.php index 387a8d823d0c3..5cfb92a038a2b 100644 --- a/lib/internal/Magento/Framework/Model/AbstractExtensibleModel.php +++ b/lib/internal/Magento/Framework/Model/AbstractExtensibleModel.php @@ -183,6 +183,10 @@ public function setCustomAttribute($attributeCode, $attributeValue) /** * {@inheritdoc} Added custom attributes support. + * + * @param string|array $key + * @param mixed $value + * @return $this */ public function setData($key, $value = null) { @@ -199,6 +203,9 @@ public function setData($key, $value = null) /** * {@inheritdoc} Unset customAttributesChanged flag + * + * @param null|string|array $key + * @return $thi */ public function unsetData($key = null) { diff --git a/lib/internal/Magento/Framework/Translate/Inline/Proxy.php b/lib/internal/Magento/Framework/Translate/Inline/Proxy.php index ae03c7cfeddf4..d2b0468bebde9 100644 --- a/lib/internal/Magento/Framework/Translate/Inline/Proxy.php +++ b/lib/internal/Magento/Framework/Translate/Inline/Proxy.php @@ -122,7 +122,7 @@ public function getParser() /** * Replace translation templates with HTML fragments * - * @param array|string &$body + * @param array|string $body * @param bool $isJson * @return $this */ From 9e694178c573116408712aee654195cc58d392eb Mon Sep 17 00:00:00 2001 From: Dmytro Voskoboinikov <voskoboi@adobe.com> Date: Fri, 3 May 2019 14:21:12 -0500 Subject: [PATCH 348/773] MC-16169: Eliminate discrepancies in M2 release --- .../Magento/Catalog/Block/Product/View/Options/Type/Select.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Block/Product/View/Options/Type/Select.php b/app/code/Magento/Catalog/Block/Product/View/Options/Type/Select.php index d9d663b32f4de..81d7e18d45519 100644 --- a/app/code/Magento/Catalog/Block/Product/View/Options/Type/Select.php +++ b/app/code/Magento/Catalog/Block/Product/View/Options/Type/Select.php @@ -58,7 +58,7 @@ public function __construct( * * @return string */ - public function getValuesHtml() + public function getValuesHtml(): string { $option = $this->getOption(); $optionType = $option->getType(); From 27dd880df6548ff10dd25560066717e6e12ae836 Mon Sep 17 00:00:00 2001 From: Max Lesechko <mlesechko@magento.com> Date: Fri, 3 May 2019 17:35:47 -0500 Subject: [PATCH 349/773] MC-16106: [2.3] Failed UI upgrade --- .../Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php | 1 + lib/internal/Magento/Framework/Data/Collection/AbstractDb.php | 1 + lib/internal/Magento/Framework/Model/AbstractModel.php | 1 + .../Magento/Framework/Model/ResourceModel/Db/AbstractDb.php | 1 + .../Model/ResourceModel/Db/Collection/AbstractCollection.php | 1 + 5 files changed, 5 insertions(+) diff --git a/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php b/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php index 7ed455eccf4e0..3857118ae67ca 100644 --- a/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php +++ b/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php @@ -13,6 +13,7 @@ /** * Entity/Attribute/Model - attribute abstract + * phpcs:disable Magento2.Classes.AbstractApi * @api * @SuppressWarnings(PHPMD.ExcessivePublicCount) * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) diff --git a/lib/internal/Magento/Framework/Data/Collection/AbstractDb.php b/lib/internal/Magento/Framework/Data/Collection/AbstractDb.php index edbf095d8f46d..05529194707c7 100644 --- a/lib/internal/Magento/Framework/Data/Collection/AbstractDb.php +++ b/lib/internal/Magento/Framework/Data/Collection/AbstractDb.php @@ -16,6 +16,7 @@ /** * Base items collection class * + * phpcs:disable Magento2.Classes.AbstractApi * @api * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ diff --git a/lib/internal/Magento/Framework/Model/AbstractModel.php b/lib/internal/Magento/Framework/Model/AbstractModel.php index e2c731d719be5..8018c6176390f 100644 --- a/lib/internal/Magento/Framework/Model/AbstractModel.php +++ b/lib/internal/Magento/Framework/Model/AbstractModel.php @@ -10,6 +10,7 @@ /** * Abstract model class * + * phpcs:disable Magento2.Classes.AbstractApi * @api * @SuppressWarnings(PHPMD.CouplingBetweenObjects) * @SuppressWarnings(PHPMD.NumberOfChildren) diff --git a/lib/internal/Magento/Framework/Model/ResourceModel/Db/AbstractDb.php b/lib/internal/Magento/Framework/Model/ResourceModel/Db/AbstractDb.php index c7887c5066e6f..5bb9c23a64f4b 100644 --- a/lib/internal/Magento/Framework/Model/ResourceModel/Db/AbstractDb.php +++ b/lib/internal/Magento/Framework/Model/ResourceModel/Db/AbstractDb.php @@ -18,6 +18,7 @@ * @SuppressWarnings(PHPMD.NumberOfChildren) * @SuppressWarnings(PHPMD.CouplingBetweenObjects) * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) + * phpcs:disable Magento2.Classes.AbstractApi * @api */ abstract class AbstractDb extends AbstractResource diff --git a/lib/internal/Magento/Framework/Model/ResourceModel/Db/Collection/AbstractCollection.php b/lib/internal/Magento/Framework/Model/ResourceModel/Db/Collection/AbstractCollection.php index 977860d262dbd..cba5f133f53c8 100644 --- a/lib/internal/Magento/Framework/Model/ResourceModel/Db/Collection/AbstractCollection.php +++ b/lib/internal/Magento/Framework/Model/ResourceModel/Db/Collection/AbstractCollection.php @@ -12,6 +12,7 @@ /** * Abstract Resource Collection * + * phpcs:disable Magento2.Classes.AbstractApi * @api * @SuppressWarnings(PHPMD.NumberOfChildren) */ From c4dc289c57852cfe906462a605c7aaff814932d7 Mon Sep 17 00:00:00 2001 From: Shikha Mishra <shikhamishra@cedcoss.com> Date: Sat, 4 May 2019 12:48:33 +0530 Subject: [PATCH 350/773] Fixed #22545 Status downloadable product stays pending after succesfull payment --- .../Observer/SaveDownloadableOrderItemObserver.php | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Downloadable/Observer/SaveDownloadableOrderItemObserver.php b/app/code/Magento/Downloadable/Observer/SaveDownloadableOrderItemObserver.php index 7c1d2748a3e9c..f4eeab6d32061 100644 --- a/app/code/Magento/Downloadable/Observer/SaveDownloadableOrderItemObserver.php +++ b/app/code/Magento/Downloadable/Observer/SaveDownloadableOrderItemObserver.php @@ -131,6 +131,13 @@ public function execute(\Magento\Framework\Event\Observer $observer) ScopeInterface::SCOPE_STORE ); $linkPurchased->setLinkSectionTitle($linkSectionTitle)->save(); + + $linkstatus = \Magento\Downloadable\Model\Link\Purchased\Item::LINK_STATUS_PENDING; + if( $orderStatusToEnableItem == \Magento\Sales\Model\Order\Item::STATUS_PENDING + || $orderItem->getOrder()->getStatus() == \Magento\Sales\Model\Order::STATE_COMPLETE){ + $linkstatus = \Magento\Downloadable\Model\Link\Purchased\Item::LINK_STATUS_AVAILABLE; + } + foreach ($linkIds as $linkId) { if (isset($links[$linkId])) { $linkPurchasedItem = $this->_createPurchasedItemModel()->setPurchasedId( @@ -158,9 +165,7 @@ public function execute(\Magento\Framework\Event\Observer $observer) )->setNumberOfDownloadsBought( $numberOfDownloads )->setStatus( - \Magento\Sales\Model\Order\Item::STATUS_PENDING == $orderStatusToEnableItem ? - \Magento\Downloadable\Model\Link\Purchased\Item::LINK_STATUS_AVAILABLE : - \Magento\Downloadable\Model\Link\Purchased\Item::LINK_STATUS_PENDING + $linkstatus )->setCreatedAt( $orderItem->getCreatedAt() )->setUpdatedAt( From 0fe651deadd53911bc2cb6036984fcdbf2846202 Mon Sep 17 00:00:00 2001 From: Vikalp Saxena <vikalpsaxena@cedcommerce.com> Date: Sat, 4 May 2019 16:34:20 +0530 Subject: [PATCH 351/773] Resolved 404 url while updating quantity on multiple address cart page Resolved 404 form validation url while updating quantity on multiple address cart page --- .../view/frontend/templates/checkout/addresses.phtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Multishipping/view/frontend/templates/checkout/addresses.phtml b/app/code/Magento/Multishipping/view/frontend/templates/checkout/addresses.phtml index a29013cc71722..a57224e471dca 100644 --- a/app/code/Magento/Multishipping/view/frontend/templates/checkout/addresses.phtml +++ b/app/code/Magento/Multishipping/view/frontend/templates/checkout/addresses.phtml @@ -18,7 +18,7 @@ data-mage-init='{ "multiShipping":{}, "cartUpdate": { - "validationURL": "/multishipping/checkout/checkItems", + "validationURL": "<?= /* @escapeNotVerified */ $block->getUrl('multishipping/checkout/checkItems') ?>", "eventName": "updateMulticartItemQty" }}' action="<?= $block->escapeUrl($block->getPostActionUrl()) ?>" From 64fb21b40b4dd3002f94a841da74c51d0eb36851 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun <ogorkun@magento.com> Date: Mon, 6 May 2019 11:22:41 -0500 Subject: [PATCH 352/773] MC-16128: Fix CompanyUserManagerInterfaceTest failing on mainline --- .../Magento/Sales/Model/Rss/OrderStatus.php | 2 +- .../Magento/Sales/Model/Rss/Signature.php | 48 ++---- .../Test/Unit/Model/Rss/OrderStatusTest.php | 47 +++++- .../Test/Unit/Model/Rss/SignatureTest.php | 81 ----------- .../Observer/AfterPaymentSaveObserverTest.php | 13 +- .../ResourceModel/Catalog/ProductTest.php | 30 ++-- .../Framework/Encryption/Encryptor.php | 58 ++++++-- .../Encryption/EncryptorInterface.php | 11 +- .../Encryption/Test/Unit/EncryptorTest.php | 137 ++++++++++++++---- 9 files changed, 244 insertions(+), 183 deletions(-) delete mode 100644 app/code/Magento/Sales/Test/Unit/Model/Rss/SignatureTest.php diff --git a/app/code/Magento/Sales/Model/Rss/OrderStatus.php b/app/code/Magento/Sales/Model/Rss/OrderStatus.php index d0a15056e95bf..3f184b57107a1 100644 --- a/app/code/Magento/Sales/Model/Rss/OrderStatus.php +++ b/app/code/Magento/Sales/Model/Rss/OrderStatus.php @@ -159,7 +159,7 @@ protected function getOrder() } $data = (string)$this->request->getParam('data'); - if ((string)$this->request->getParam('signature') !== $this->signature->signData($data)) { + if (!$this->signature->isValid($data, (string)$this->request->getParam('signature'))) { return null; } // phpcs:ignore diff --git a/app/code/Magento/Sales/Model/Rss/Signature.php b/app/code/Magento/Sales/Model/Rss/Signature.php index e2bc1fe8a6411..28f8dc15984b4 100644 --- a/app/code/Magento/Sales/Model/Rss/Signature.php +++ b/app/code/Magento/Sales/Model/Rss/Signature.php @@ -8,7 +8,7 @@ namespace Magento\Sales\Model\Rss; -use Magento\Framework\Config\ConfigOptionsListConstants; +use Magento\Framework\Encryption\EncryptorInterface; /** * Class for generating signature. @@ -16,57 +16,39 @@ class Signature { /** - * Version of encryption key. - * - * @var int - */ - private $keyVersion; - - /** - * Array of encryption keys. - * - * @var string[] - */ - private $keys = []; - - /** - * @var \Magento\Framework\App\DeploymentConfig + * @var EncryptorInterface */ - private $deploymentConfig; + private $encryptor; /** - * @param \Magento\Framework\App\DeploymentConfig $deploymentConfig + * @param EncryptorInterface $encryptor */ public function __construct( - \Magento\Framework\App\DeploymentConfig $deploymentConfig + EncryptorInterface $encryptor ) { - $this->deploymentConfig = $deploymentConfig; - // load all possible keys - $this->keys = preg_split( - '/\s+/s', - (string)$this->deploymentConfig->get(ConfigOptionsListConstants::CONFIG_PATH_CRYPT_KEY) - ); - $this->keyVersion = count($this->keys) - 1; + $this->encryptor = $encryptor; } /** - * Get secret key. + * Sign data. * + * @param string $data * @return string */ - private function getSecretKey(): string + public function signData(string $data): string { - return (string)$this->keys[$this->keyVersion]; + return $this->encryptor->hash($data); } /** - * Sign data. + * Check if valid signature is provided for given data. * * @param string $data - * @return string + * @param string $signature + * @return bool */ - public function signData(string $data): string + public function isValid(string $data, string $signature): bool { - return hash_hmac('sha256', $data, pack('H*', $this->getSecretKey())); + return $this->encryptor->validateHash($data, $signature); } } diff --git a/app/code/Magento/Sales/Test/Unit/Model/Rss/OrderStatusTest.php b/app/code/Magento/Sales/Test/Unit/Model/Rss/OrderStatusTest.php index 23f633d10caa3..f04e102cccf32 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Rss/OrderStatusTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Rss/OrderStatusTest.php @@ -10,6 +10,7 @@ /** * Class OrderStatusTest + * * @package Magento\Sales\Model\Rss * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ @@ -92,6 +93,9 @@ class OrderStatusTest extends \PHPUnit\Framework\TestCase ], ]; + /** + * @inheritdoc + */ protected function setUp() { $this->objectManager = $this->createMock(\Magento\Framework\ObjectManagerInterface::class); @@ -142,11 +146,18 @@ protected function setUp() ); } + /** + * Positive scenario. + */ public function testGetRssData() { $this->orderFactory->expects($this->once())->method('create')->willReturn($this->order); $requestData = base64_encode('{"order_id":1,"increment_id":"100000001","customer_id":1}'); - $this->signature->expects($this->any())->method('signData')->willReturn('signature'); + $this->signature->expects($this->never())->method('signData'); + $this->signature->expects($this->any()) + ->method('isValid') + ->with($requestData, 'signature') + ->willReturn(true); $this->requestInterface->expects($this->any()) ->method('getParam') @@ -177,6 +188,8 @@ public function testGetRssData() } /** + * Case when invalid data is provided. + * * @expectedException \InvalidArgumentException * @expectedExceptionMessage Order not found. */ @@ -184,7 +197,11 @@ public function testGetRssDataWithError() { $this->orderFactory->expects($this->once())->method('create')->willReturn($this->order); $requestData = base64_encode('{"order_id":"1","increment_id":true,"customer_id":true}'); - $this->signature->expects($this->any())->method('signData')->willReturn('signature'); + $this->signature->expects($this->never())->method('signData'); + $this->signature->expects($this->any()) + ->method('isValid') + ->with($requestData, 'signature') + ->willReturn(true); $this->requestInterface->expects($this->any()) ->method('getParam') ->willReturnMap( @@ -199,16 +216,20 @@ public function testGetRssDataWithError() } /** + * Case when invalid signature is provided. + * * @expectedException \InvalidArgumentException * @expectedExceptionMessage Order not found. */ public function testGetRssDataWithWrongSignature() { $requestData = base64_encode('{"order_id":"1","increment_id":true,"customer_id":true}'); + $this->signature->expects($this->never()) + ->method('signData'); $this->signature->expects($this->any()) - ->method('signData') - ->with($requestData) - ->willReturn('wrong_signature'); + ->method('isValid') + ->with($requestData, 'signature') + ->willReturn(false); $this->requestInterface->expects($this->any()) ->method('getParam') ->willReturnMap( @@ -222,6 +243,9 @@ public function testGetRssDataWithWrongSignature() $this->assertEquals($this->feedData, $this->model->getRssData()); } + /** + * Testing allowed getter. + */ public function testIsAllowed() { $this->scopeConfigInterface->expects($this->once())->method('getValue') @@ -231,6 +255,8 @@ public function testIsAllowed() } /** + * Test caching. + * * @param string $requestData * @param string $result * @dataProvider getCacheKeyDataProvider @@ -242,12 +268,18 @@ public function testGetCacheKey($requestData, $result) ['data', null, $requestData], ['signature', null, 'signature'], ]); - $this->signature->expects($this->any())->method('signData')->willReturn('signature'); + $this->signature->expects($this->never())->method('signData'); + $this->signature->expects($this->any()) + ->method('isValid') + ->with($requestData, 'signature') + ->willReturn(true); $this->orderFactory->expects($this->once())->method('create')->will($this->returnValue($this->order)); $this->assertEquals('rss_order_status_data_' . $result, $this->model->getCacheKey()); } /** + * Test data for caching test. + * * @return array */ public function getCacheKeyDataProvider() @@ -260,6 +292,9 @@ public function getCacheKeyDataProvider() // phpcs:enable } + /** + * Test for cache lifetime getter. + */ public function testGetCacheLifetime() { $this->assertEquals(600, $this->model->getCacheLifetime()); diff --git a/app/code/Magento/Sales/Test/Unit/Model/Rss/SignatureTest.php b/app/code/Magento/Sales/Test/Unit/Model/Rss/SignatureTest.php deleted file mode 100644 index 82ab018cfd703..0000000000000 --- a/app/code/Magento/Sales/Test/Unit/Model/Rss/SignatureTest.php +++ /dev/null @@ -1,81 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -declare(strict_types=1); - -namespace Magento\Sales\Test\Unit\Model\Rss; - -use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; -use Magento\Sales\Model\Rss\Signature; - -/** - * Test signature class. - */ -class SignatureTest extends \PHPUnit\Framework\TestCase -{ - /** - * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Framework\App\DeploymentConfig - */ - private $deploymentConfigMock; - - /** - * @var ObjectManagerHelper - */ - private $objectManagerHelper; - - /** - * @var \Magento\Sales\Model\Rss\Signature - */ - private $model; - - /** - * @inheritdoc - */ - protected function setUp() - { - $this->deploymentConfigMock = $this->getMockBuilder(\Magento\Framework\App\DeploymentConfig::class) - ->disableOriginalConstructor() - ->getMock(); - $this->deploymentConfigMock->expects($this->any()) - ->method('get') - ->with('crypt/key') - ->willReturn('1234567890abc'); - - $this->objectManagerHelper = new ObjectManagerHelper($this); - $this->model = $this->objectManagerHelper->getObject( - Signature::class, - [ - 'deploymentConfig' => $this->deploymentConfigMock, - ] - ); - } - - /** - * Test sign data. - * - * @param string $data - * @param string $expected - * @return void - * @dataProvider checkSignatureDataProvider - */ - public function testSignData(string $data, string $expected): void - { - $this->assertEquals($expected, $this->model->signData($data)); - } - - /** - * @return array - */ - public function checkSignatureDataProvider(): array - { - return [ - [ - 'eyJvcmRlcl9pZCI6IjEiLCJjdXN0b21lcl9pZCI6IjEiLCJpbmNyZW1lbnRfaWQiOiIwMDAwMDAwMDEifQ==', - '651932dfc862406b72628d95623bae5ea18242be757b3493b337942d61f834be', - ], - ]; - } -} diff --git a/app/code/Magento/Vault/Test/Unit/Observer/AfterPaymentSaveObserverTest.php b/app/code/Magento/Vault/Test/Unit/Observer/AfterPaymentSaveObserverTest.php index 09c17d1e58d98..dd95cb21ee60a 100644 --- a/app/code/Magento/Vault/Test/Unit/Observer/AfterPaymentSaveObserverTest.php +++ b/app/code/Magento/Vault/Test/Unit/Observer/AfterPaymentSaveObserverTest.php @@ -18,6 +18,9 @@ use Magento\Vault\Observer\AfterPaymentSaveObserver; use PHPUnit_Framework_MockObject_MockObject as MockObject; +/** + * Test for payment observer. + */ class AfterPaymentSaveObserverTest extends \PHPUnit\Framework\TestCase { /** @@ -61,7 +64,7 @@ class AfterPaymentSaveObserverTest extends \PHPUnit\Framework\TestCase protected $salesOrderPaymentMock; /** - * @return void + * @inheritdoc */ protected function setUp() { @@ -69,6 +72,10 @@ protected function setUp() $encryptorRandomGenerator = $this->createMock(Random::class); /** @var DeploymentConfig|MockObject $deploymentConfigMock */ $deploymentConfigMock = $this->createMock(DeploymentConfig::class); + $deploymentConfigMock->expects($this->any()) + ->method('get') + ->with(Encryptor::PARAM_CRYPT_KEY) + ->willReturn('g9mY9KLrcuAVJfsmVUSRkKFLDdUPVkaZ'); $this->encryptorModel = new Encryptor($encryptorRandomGenerator, $deploymentConfigMock); $this->paymentExtension = $this->getMockBuilder(OrderPaymentExtension::class) @@ -117,6 +124,8 @@ protected function setUp() } /** + * Case when payment successfully made. + * * @param int $customerId * @param string $createdAt * @param string $token @@ -161,6 +170,8 @@ public function testPositiveCase($customerId, $createdAt, $token, $isActive, $me } /** + * Data for positiveCase test. + * * @return array */ public function positiveCaseDataProvider() diff --git a/dev/tests/integration/testsuite/Magento/Sitemap/Model/ResourceModel/Catalog/ProductTest.php b/dev/tests/integration/testsuite/Magento/Sitemap/Model/ResourceModel/Catalog/ProductTest.php index b8ae7751a15ee..d6388b188a5fd 100644 --- a/dev/tests/integration/testsuite/Magento/Sitemap/Model/ResourceModel/Catalog/ProductTest.php +++ b/dev/tests/integration/testsuite/Magento/Sitemap/Model/ResourceModel/Catalog/ProductTest.php @@ -17,7 +17,7 @@ class ProductTest extends \PHPUnit\Framework\TestCase /** * Base product image path */ - const BASE_IMAGE_PATH = 'http://localhost/pub/media/catalog/product/cache/8d4d2075b1a30681853bef5bdc41b164'; + const BASE_IMAGE_PATH = '#http\:\/\/localhost\/pub\/media\/catalog\/product\/cache\/[a-z0-9]{32}:path:#'; /** * Test getCollection None images @@ -76,21 +76,21 @@ public function testGetCollectionAll() $this->assertEmpty($products[1]->getImages(), 'Images were loaded'); $this->assertNotEmpty($products[4]->getImages(), 'Images were not loaded'); $this->assertEquals('Simple Images', $products[4]->getImages()->getTitle(), 'Incorrect title'); - $this->assertEquals( - self::BASE_IMAGE_PATH.'/m/a/magento_image_sitemap.png', + $this->assertRegExp( + str_replace(':path:', preg_quote('/m/a/magento_image_sitemap.png'), self::BASE_IMAGE_PATH), $products[4]->getImages()->getThumbnail(), 'Incorrect thumbnail' ); $this->assertCount(2, $products[4]->getImages()->getCollection(), 'Not all images were loaded'); $imagesCollection = $products[4]->getImages()->getCollection(); - $this->assertEquals( - self::BASE_IMAGE_PATH.'/m/a/magento_image_sitemap.png', + $this->assertRegExp( + str_replace(':path:', preg_quote('/m/a/magento_image_sitemap.png'), self::BASE_IMAGE_PATH), $imagesCollection[0]->getUrl(), 'Incorrect image url' ); - $this->assertEquals( - self::BASE_IMAGE_PATH.'/s/e/second_image.png', + $this->assertRegExp( + str_replace(':path:', preg_quote('/s/e/second_image.png'), self::BASE_IMAGE_PATH), $imagesCollection[1]->getUrl(), 'Incorrect image url' ); @@ -101,13 +101,13 @@ public function testGetCollectionAll() $this->assertEquals('no_selection', $products[5]->getThumbnail(), 'thumbnail is incorrect'); $imagesCollection = $products[5]->getImages()->getCollection(); $this->assertCount(1, $imagesCollection); - $this->assertEquals( - self::BASE_IMAGE_PATH.'/s/e/second_image_1.png', + $this->assertRegExp( + str_replace(':path:', preg_quote('/s/e/second_image_1.png'), self::BASE_IMAGE_PATH), $imagesCollection[0]->getUrl(), 'Image url is incorrect' ); - $this->assertEquals( - self::BASE_IMAGE_PATH.'/s/e/second_image_1.png', + $this->assertRegExp( + str_replace(':path:', preg_quote('/s/e/second_image_1.png'), self::BASE_IMAGE_PATH), $products[5]->getImages()->getThumbnail(), 'Product thumbnail is incorrect' ); @@ -144,16 +144,16 @@ public function testGetCollectionBase() $this->assertEmpty($products[1]->getImages(), 'Images were loaded'); $this->assertNotEmpty($products[4]->getImages(), 'Images were not loaded'); $this->assertEquals('Simple Images', $products[4]->getImages()->getTitle(), 'Incorrect title'); - $this->assertEquals( - self::BASE_IMAGE_PATH.'/s/e/second_image.png', + $this->assertRegExp( + str_replace(':path:', preg_quote('/s/e/second_image.png'), self::BASE_IMAGE_PATH), $products[4]->getImages()->getThumbnail(), 'Incorrect thumbnail' ); $this->assertCount(1, $products[4]->getImages()->getCollection(), 'Number of loaded images is incorrect'); $imagesCollection = $products[4]->getImages()->getCollection(); - $this->assertEquals( - self::BASE_IMAGE_PATH.'/s/e/second_image.png', + $this->assertRegExp( + str_replace(':path:', preg_quote('/s/e/second_image.png'), self::BASE_IMAGE_PATH), $imagesCollection[0]->getUrl(), 'Incorrect image url' ); diff --git a/lib/internal/Magento/Framework/Encryption/Encryptor.php b/lib/internal/Magento/Framework/Encryption/Encryptor.php index 65922d69a823c..4bc1b2589362f 100644 --- a/lib/internal/Magento/Framework/Encryption/Encryptor.php +++ b/lib/internal/Magento/Framework/Encryption/Encryptor.php @@ -17,7 +17,9 @@ use Magento\Framework\Encryption\Adapter\Mcrypt; /** - * Class Encryptor provides basic logic for hashing strings and encrypting/decrypting misc data + * Class Encryptor provides basic logic for hashing strings and encrypting/decrypting misc data. + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class Encryptor implements EncryptorInterface { @@ -219,7 +221,7 @@ public function getHash($password, $salt = false, $version = self::HASH_VERSION_ if ($version === self::HASH_VERSION_ARGON2ID13) { $hash = $this->getArgonHash($password, $salt); } else { - $hash = $this->hash($salt . $password, $version); + $hash = $this->generateSimpleHash($salt . $password, $version); } return implode( @@ -232,12 +234,28 @@ public function getHash($password, $salt = false, $version = self::HASH_VERSION_ ); } + /** + * Generate simple hash for given string. + * + * @param string $data + * @param int $version + * @return string + */ + private function generateSimpleHash(string $data, int $version): string + { + return hash($this->hashVersionMap[$version], (string)$data); + } + /** * @inheritdoc */ public function hash($data, $version = self::HASH_VERSION_SHA256) { - return hash($this->hashVersionMap[$version], (string)$data); + if (empty($this->keys[$this->keyVersion])) { + throw new \RuntimeException('No key available'); + } + + return hash_hmac($this->hashVersionMap[$version], (string)$data, $this->keys[$this->keyVersion], false); } /** @@ -253,19 +271,24 @@ public function validateHash($password, $hash) */ public function isValidHash($password, $hash) { - $this->explodePasswordHash($hash); - - foreach ($this->getPasswordVersion() as $hashVersion) { - if ($hashVersion === self::HASH_VERSION_ARGON2ID13) { - $password = $this->getArgonHash($password, $this->getPasswordSalt()); - } else { - $password = $this->hash($this->getPasswordSalt() . $password, $hashVersion); + try { + $this->explodePasswordHash($hash); + foreach ($this->getPasswordVersion() as $hashVersion) { + if ($hashVersion === self::HASH_VERSION_ARGON2ID13) { + $recreated = $this->getArgonHash($password, $this->getPasswordSalt()); + } else { + $recreated = $this->generateSimpleHash($this->getPasswordSalt() . $password, $hashVersion); + } + $hash = $this->getPasswordHash(); } + } catch (\RuntimeException $exception) { + //Hash is not a password hash. + $recreated = $this->hash($password); } return Security::compareStrings( - $password, - $this->getPasswordHash() + $recreated, + $hash ); } @@ -274,7 +297,12 @@ public function isValidHash($password, $hash) */ public function validateHashVersion($hash, $validateCount = false) { - $this->explodePasswordHash($hash); + try { + $this->explodePasswordHash($hash); + } catch (\RuntimeException $exception) { + //Not a password hash. + return true; + } $hashVersions = $this->getPasswordVersion(); return $validateCount @@ -286,11 +314,15 @@ public function validateHashVersion($hash, $validateCount = false) * Explode password hash * * @param string $hash + * @throws \RuntimeException When given hash cannot be processed. * @return array */ private function explodePasswordHash($hash) { $explodedPassword = explode(self::DELIMITER, $hash, 3); + if (count($explodedPassword) !== 3) { + throw new \RuntimeException('Hash is not a password hash'); + } foreach ($this->passwordHashMap as $key => $defaultValue) { $this->passwordHashMap[$key] = (isset($explodedPassword[$key])) ? $explodedPassword[$key] : $defaultValue; diff --git a/lib/internal/Magento/Framework/Encryption/EncryptorInterface.php b/lib/internal/Magento/Framework/Encryption/EncryptorInterface.php index f7bc424a7a0d6..778cfcb897e0b 100644 --- a/lib/internal/Magento/Framework/Encryption/EncryptorInterface.php +++ b/lib/internal/Magento/Framework/Encryption/EncryptorInterface.php @@ -28,7 +28,9 @@ interface EncryptorInterface public function getHash($password, $salt = false); /** - * Hash a string + * Hash a string. + * + * Returns one-way encrypted string, always the same result for the same value. Suitable for signatures. * * @param string $data * @return string @@ -36,17 +38,20 @@ public function getHash($password, $salt = false); public function hash($data); /** - * Validate hash against hashing method (with or without salt) + * Synonym to isValidHash. * * @param string $password * @param string $hash * @return bool * @throws \Exception + * @see isValidHash */ public function validateHash($password, $hash); /** - * Validate hash against hashing method (with or without salt) + * Validate hash against hashing method. + * + * Works for both hashes returned by hash() and getHash(). * * @param string $password * @param string $hash diff --git a/lib/internal/Magento/Framework/Encryption/Test/Unit/EncryptorTest.php b/lib/internal/Magento/Framework/Encryption/Test/Unit/EncryptorTest.php index f6f92f390fc54..602d7d5c59b95 100644 --- a/lib/internal/Magento/Framework/Encryption/Test/Unit/EncryptorTest.php +++ b/lib/internal/Magento/Framework/Encryption/Test/Unit/EncryptorTest.php @@ -22,6 +22,7 @@ class EncryptorTest extends \PHPUnit\Framework\TestCase { private const CRYPT_KEY_1 = 'g9mY9KLrcuAVJfsmVUSRkKFLDdUPVkaZ'; + private const CRYPT_KEY_2 = '7wEjmrliuqZQ1NQsndSa8C8WHvddeEbN'; /** @@ -30,15 +31,18 @@ class EncryptorTest extends \PHPUnit\Framework\TestCase private $encryptor; /** - * @var Random | \PHPUnit_Framework_MockObject_MockObject + * @var Random|\PHPUnit_Framework_MockObject_MockObject */ private $randomGeneratorMock; /** - * @var KeyValidator | \PHPUnit_Framework_MockObject_MockObject + * @var KeyValidator|\PHPUnit_Framework_MockObject_MockObject */ private $keyValidatorMock; + /** + * @inheritdoc + */ protected function setUp() { $this->randomGeneratorMock = $this->createMock(Random::class); @@ -59,14 +63,20 @@ protected function setUp() ); } + /** + * Hashing without a salt. + */ public function testGetHashNoSalt(): void { $this->randomGeneratorMock->expects($this->never())->method('getRandomString'); - $expected = '5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8'; + $expected = '1421feadb52d556a2045588672d8880d812ecc81ebb53dd98f6ff43500786b36'; $actual = $this->encryptor->getHash('password'); $this->assertEquals($expected, $actual); } + /** + * Providing salt for hash. + */ public function testGetHashSpecifiedSalt(): void { $this->randomGeneratorMock->expects($this->never())->method('getRandomString'); @@ -77,6 +87,9 @@ public function testGetHashSpecifiedSalt(): void $this->assertEquals($expected, $actual); } + /** + * Hashing with random salt. + */ public function testGetHashRandomSaltDefaultLength(): void { $salt = '-----------random_salt----------'; @@ -92,6 +105,9 @@ public function testGetHashRandomSaltDefaultLength(): void $this->assertEquals($expected, $actual); } + /** + * Hashing with random salt of certain length. + */ public function testGetHashRandomSaltSpecifiedLength(): void { $this->randomGeneratorMock @@ -111,6 +127,8 @@ public function testGetHashRandomSaltSpecifiedLength(): void } /** + * Validating hashes generated by different algorithms. + * * @param string $password * @param string $hash * @param bool $expected @@ -124,6 +142,8 @@ public function testValidateHash($password, $hash, $expected): void } /** + * List of values and their hashes using different algorithms. + * * @return array */ public function validateHashDataProvider(): array @@ -136,9 +156,11 @@ public function validateHashDataProvider(): array } /** + * Encrypting with empty keys. + * * @param mixed $key * - * @dataProvider encryptWithEmptyKeyDataProvider + * @dataProvider emptyKeyDataProvider * @expectedException \SodiumException */ public function testEncryptWithEmptyKey($key): void @@ -154,17 +176,11 @@ public function testEncryptWithEmptyKey($key): void } /** - * @return array - */ - public function encryptWithEmptyKeyDataProvider(): array - { - return [[null], [0], [''], ['0']]; - } - - /** + * Seeing how decrypting works with invalid keys. + * * @param mixed $key * - * @dataProvider decryptWithEmptyKeyDataProvider + * @dataProvider emptyKeyDataProvider */ public function testDecryptWithEmptyKey($key): void { @@ -179,13 +195,18 @@ public function testDecryptWithEmptyKey($key): void } /** + * List of invalid keys. + * * @return array */ - public function decryptWithEmptyKeyDataProvider(): array + public function emptyKeyDataProvider(): array { return [[null], [0], [''], ['0']]; } + /** + * Seeing that encrypting uses sodium. + */ public function testEncrypt(): void { // sample data to encrypt @@ -194,13 +215,16 @@ public function testEncrypt(): void $actual = $this->encryptor->encrypt($data); // Extract the initialization vector and encrypted data - [, , $encryptedData] = explode(':', $actual, 3); + $encryptedParts = explode(':', $actual, 3); $crypt = new SodiumChachaIetf(self::CRYPT_KEY_1); // Verify decrypted matches original data - $this->assertEquals($data, $crypt->decrypt(base64_decode((string)$encryptedData))); + $this->assertEquals($data, $crypt->decrypt(base64_decode((string)$encryptedParts[2]))); } + /** + * Check that decrypting works. + */ public function testDecrypt(): void { $message = 'Mares eat oats and does eat oats, but little lambs eat ivy.'; @@ -209,6 +233,9 @@ public function testDecrypt(): void $this->assertEquals($message, $this->encryptor->decrypt($encrypted)); } + /** + * Using an old algo. + */ public function testLegacyDecrypt(): void { // sample data to encrypt @@ -226,6 +253,9 @@ public function testLegacyDecrypt(): void $this->assertEquals($encrypted, base64_encode($crypt->encrypt($actual))); } + /** + * Seeing that changing a key does not stand in a way of decrypting. + */ public function testEncryptDecryptNewKeyAdded(): void { $deploymentConfigMock = $this->createMock(DeploymentConfig::class); @@ -250,6 +280,9 @@ public function testEncryptDecryptNewKeyAdded(): void $this->assertSame($data, $decryptedData, 'Encryptor failed to decrypt data encrypted by old keys.'); } + /** + * Checking that encryptor relies on key validator. + */ public function testValidateKey(): void { $this->keyValidatorMock->method('isValid')->willReturn(true); @@ -257,6 +290,8 @@ public function testValidateKey(): void } /** + * Checking that encryptor relies on key validator. + * * @expectedException \Exception */ public function testValidateKeyInvalid(): void @@ -266,33 +301,75 @@ public function testValidateKeyInvalid(): void } /** + * Algorithms and expressions to validate them. + * * @return array */ public function useSpecifiedHashingAlgoDataProvider(): array { return [ - ['password', 'salt', Encryptor::HASH_VERSION_MD5, - '67a1e09bb1f83f5007dc119c14d663aa:salt:0'], - ['password', 'salt', Encryptor::HASH_VERSION_SHA256, - '13601bda4ea78e55a07b98866d2be6be0744e3866f13c00c811cab608a28f322:salt:1'], - ['password', false, Encryptor::HASH_VERSION_MD5, - '5f4dcc3b5aa765d61d8327deb882cf99'], - ['password', false, Encryptor::HASH_VERSION_SHA256, - '5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8'] + [ + 'password', + 'salt', + Encryptor::HASH_VERSION_MD5, + '/^[a-z0-9]{32}\:salt\:0$/' + ], + [ + 'password', + 'salt', + Encryptor::HASH_VERSION_SHA256, + '/^[a-z0-9]{64}\:salt\:1$/' + ], + [ + 'password', + false, + Encryptor::HASH_VERSION_MD5, + '/^[0-9a-z]{32}$/' + ], + [ + 'password', + false, + Encryptor::HASH_VERSION_SHA256, + '/^[0-9a-z]{64}$/' + ] ]; } /** + * Check that specified algorithm is in fact being used. + * * @dataProvider useSpecifiedHashingAlgoDataProvider * - * @param $password - * @param $salt - * @param $hashAlgo - * @param $expected + * @param string $password + * @param string|bool $salt + * @param int $hashAlgo + * @param string $pattern */ - public function testGetHashMustUseSpecifiedHashingAlgo($password, $salt, $hashAlgo, $expected): void + public function testGetHashMustUseSpecifiedHashingAlgo($password, $salt, $hashAlgo, $pattern): void { $hash = $this->encryptor->getHash($password, $salt, $hashAlgo); - $this->assertEquals($expected, $hash); + $this->assertRegExp($pattern, $hash); + } + + /** + * Test hashing working as promised. + */ + public function testHash() + { + //Checking that the same hash is returned for the same value. + $hash1 = $this->encryptor->hash($value = 'some value'); + $hash2 = $this->encryptor->hash($value); + $this->assertEquals($hash1, $hash2); + + //Checking that hash works with hash validation. + $this->assertTrue($this->encryptor->isValidHash($value, $hash1)); + + //Checking that key matters. + $this->keyValidatorMock->method('isValid')->willReturn(true); + $this->encryptor->setNewKey(self::CRYPT_KEY_2); + $hash3 = $this->encryptor->hash($value); + $this->assertNotEquals($hash3, $hash1); + //Validation still works + $this->assertTrue($this->encryptor->validateHash($value, $hash3)); } } From 2292397aca1ed01e15bd589d4448230ab4f3ea4b Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun <ogorkun@magento.com> Date: Mon, 6 May 2019 11:23:37 -0500 Subject: [PATCH 353/773] MC-16128: Fix CompanyUserManagerInterfaceTest failing on mainline --- .../Magento/Framework/Model/AbstractExtensibleModel.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/Model/AbstractExtensibleModel.php b/lib/internal/Magento/Framework/Model/AbstractExtensibleModel.php index 5cfb92a038a2b..949e002a14208 100644 --- a/lib/internal/Magento/Framework/Model/AbstractExtensibleModel.php +++ b/lib/internal/Magento/Framework/Model/AbstractExtensibleModel.php @@ -205,7 +205,7 @@ public function setData($key, $value = null) * {@inheritdoc} Unset customAttributesChanged flag * * @param null|string|array $key - * @return $thi + * @return $this */ public function unsetData($key = null) { From 5a7cd7d68fbcce4abbf1f1b3742a946eec937f0d Mon Sep 17 00:00:00 2001 From: Dmytro Poperechnyy <dpoperechnyy@magento.com> Date: Thu, 25 Apr 2019 11:17:29 -0500 Subject: [PATCH 354/773] MAGETWO-99574: [MFTF] One Page Checkout with Addresses Search - Custom customer address attribute --- .../AdminEditCustomerAddressesFromActionGroup.xml | 9 +++++++++ .../Customer/Test/Mftf/Data/CustomerData.xml | 14 ++++++++++++++ .../Section/AdminEditCustomerAddressesSection.xml | 1 + 3 files changed, 24 insertions(+) diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/AdminEditCustomerAddressesFromActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AdminEditCustomerAddressesFromActionGroup.xml index 594337c1a6922..9c38f23739b10 100644 --- a/app/code/Magento/Customer/Test/Mftf/ActionGroup/AdminEditCustomerAddressesFromActionGroup.xml +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AdminEditCustomerAddressesFromActionGroup.xml @@ -39,4 +39,13 @@ <click selector="{{AdminEditCustomerAddressesSection.defaultBillingAddressButton}}" stepKey="setDefaultBilling" before="setDefaultShipping"/> <click selector="{{AdminEditCustomerAddressesSection.defaultShippingAddressButton}}" stepKey="setDefaultShipping" before="fillPrefixName"/> </actionGroup> + <actionGroup name="SelectDropdownCustomerAddressAttributeValueActionGroup"> + <arguments> + <argument name="customerAddressAttribute"/> + <argument name="optionValue" type="string"/> + </arguments> + <selectOption selector="{{AdminEditCustomerAddressesSection.dropDownAttribute(customerAddressAttribute.code)}}" userInput="{{optionValue}}" stepKey="selectOptionValue"/> + <click selector="{{AdminEditCustomerAddressesSection.save}}" stepKey="saveAddress"/> + <waitForPageLoad stepKey="waitForAddressSaved"/> + </actionGroup> </actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/Data/CustomerData.xml b/app/code/Magento/Customer/Test/Mftf/Data/CustomerData.xml index f561e413a01f1..f8943dcfe8369 100644 --- a/app/code/Magento/Customer/Test/Mftf/Data/CustomerData.xml +++ b/app/code/Magento/Customer/Test/Mftf/Data/CustomerData.xml @@ -216,4 +216,18 @@ <data key="store_id">0</data> <data key="website_id">0</data> </entity> + <entity name="Simple_US_Customer_Two_Addresses" type="customer"> + <data key="group_id">0</data> + <data key="default_billing">true</data> + <data key="default_shipping">true</data> + <data key="email" unique="prefix">John.Doe@example.com</data> + <data key="firstname">John</data> + <data key="lastname">Doe</data> + <data key="fullname">John Doe</data> + <data key="password">pwdTest123!</data> + <data key="store_id">0</data> + <data key="website_id">0</data> + <requiredEntity type="address">US_Address_TX</requiredEntity> + <requiredEntity type="address">US_Address_NY_Not_Default_Address</requiredEntity> + </entity> </entities> diff --git a/app/code/Magento/Customer/Test/Mftf/Section/AdminEditCustomerAddressesSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/AdminEditCustomerAddressesSection.xml index ffddc6292ef5d..4d66b40ee660b 100644 --- a/app/code/Magento/Customer/Test/Mftf/Section/AdminEditCustomerAddressesSection.xml +++ b/app/code/Magento/Customer/Test/Mftf/Section/AdminEditCustomerAddressesSection.xml @@ -25,6 +25,7 @@ <element name="city" type="text" selector="//*[@class='modal-component']//input[@name='city']" /> <element name="country" type="select" selector="//*[@class='modal-component']//select[@name='country_id']" /> <element name="state" type="select" selector="//*[@class='modal-component']//select[@name='region_id']" /> + <element name="dropDownAttribute" type="select" selector="//select[@name='{{var1}}']" parameterized="true"/> <element name="zipCode" type="text" selector="//*[@class='modal-component']//input[@name='postcode']" /> <element name="phone" type="text" selector="//*[@class='modal-component']//input[@name='telephone']" /> <element name="vat" type="text" selector="input[name='vat_id']" /> From 2502c2f26b5ebb8ee748d3a630160bb7c95d7f0a Mon Sep 17 00:00:00 2001 From: Kavitha <kanair@adobe.com> Date: Mon, 6 May 2019 15:18:39 -0500 Subject: [PATCH 355/773] MC-4770: Convert CreateOrderFromEditCustomerPageTest to MFTF --- .../AdminEditCustomerOrdersSection.xml | 1 + .../AdminCreateOrderShoppingCartSection.xml | 15 ++ .../AdminCreateOrderWishListSection.xml | 16 ++ .../AdminOrderFormItemsOrderedSection.xml | 1 + .../CreateOrderFromEditCustomerPageTest.xml | 205 ++++++++++++++++++ .../CreateOrderFromEditCustomerPageTest.xml | 1 + 6 files changed, 239 insertions(+) create mode 100644 app/code/Magento/Sales/Test/Mftf/Section/AdminCreateOrderShoppingCartSection.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/Section/AdminCreateOrderWishListSection.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/Test/CreateOrderFromEditCustomerPageTest.xml diff --git a/app/code/Magento/Customer/Test/Mftf/Section/AdminEditCustomerOrdersSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/AdminEditCustomerOrdersSection.xml index 89fed43184b84..fb3d1570848e4 100644 --- a/app/code/Magento/Customer/Test/Mftf/Section/AdminEditCustomerOrdersSection.xml +++ b/app/code/Magento/Customer/Test/Mftf/Section/AdminEditCustomerOrdersSection.xml @@ -10,5 +10,6 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="AdminEditCustomerOrdersSection"> <element name="orderGrid" type="text" selector="#customer_orders_grid_table"/> + <element name="orderIdInGrid" type="text" selector="//td[contains(., '{{orderId}}')]" parameterized="true"/> </section> </sections> diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminCreateOrderShoppingCartSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminCreateOrderShoppingCartSection.xml new file mode 100644 index 0000000000000..76826f9571f34 --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminCreateOrderShoppingCartSection.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="AdminCreateOrderShoppingCartSection"> + <element name="shoppingCartBlock" type="text" selector="#sidebar_data_cart"/> + <element name="addToOrderCheckBox" type="checkbox" selector="//div[@id='order-sidebar_cart']//tr[td[.='{{productName}}']]//input[contains(@name,'sidebar[add_cart_item]')]" parameterized="true" timeout="30"/> + </section> +</sections> \ No newline at end of file diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminCreateOrderWishListSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminCreateOrderWishListSection.xml new file mode 100644 index 0000000000000..86145a7221ad2 --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminCreateOrderWishListSection.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="AdminCreateOrderWishListSection"> + <element name="wishListBlock" type="text" selector="#sidebar_data_wishlist"/> + <element name="addProductToOrderCheckBox" type="checkbox" selector="//div[@id='order-sidebar_wishlist']//tr[td[.='{{productName}}']]//input[contains(@name,'sidebar[add_wishlist_item]')]" parameterized="true" timeout="30"/> + <element name="addConfigProductToOrder" type="text" selector="//div[@id='order-sidebar_wishlist']//tr[td[contains(.,'{{configProductName}}')]]//a[contains(@class, 'icon-configure')]" parameterized="true" timeout="30"/> + </section> +</sections> \ No newline at end of file diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormItemsOrderedSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormItemsOrderedSection.xml index beb566b20806c..52f311cef7219 100644 --- a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormItemsOrderedSection.xml +++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormItemsOrderedSection.xml @@ -16,5 +16,6 @@ <element name="addProductToOrder" type="input" selector="//*[@title='Add Products to Order']"/> <element name="itemsOrderedSummaryText" type="textarea" selector="//table[@class='data-table admin__table-primary order-tables']/tfoot/tr"/> <element name="configureSelectAttribute" type="select" selector="select[id*=attribute]"/> + <element name="moveProduct" type="select" selector="//td[contains(.,'{{productName}}')]/../..//td//select" parameterized="true"/> </section> </sections> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/CreateOrderFromEditCustomerPageTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/CreateOrderFromEditCustomerPageTest.xml new file mode 100644 index 0000000000000..3b6246e87f641 --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/Test/CreateOrderFromEditCustomerPageTest.xml @@ -0,0 +1,205 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="CreateOrderFromEditCustomerPageTest"> + <annotations> + <group value="Sales"/> + <stories value="Create Order"/> + <title value="Create order from edit customer page and add products to wish list and shopping cart"/> + <description value="Create an order from edit customer page and add products to the wish list and shopping cart "/> + <severity value="CRITICAL"/> + <testCaseId value="MC-16161"/> + <group value="mtf_migrated"/> + </annotations> + + <before> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + <createData entity="FreeShippingMethodsSettingConfig" stepKey="freeShippingMethodsSettingConfig"/> + + <!--Create simple customer--> + <createData entity="Simple_US_Customer_CA" stepKey="simpleCustomer"/> + + <!-- Create Simple Product --> + <createData entity="SimpleProduct2" stepKey="simpleProduct"> + <field key="price">10.00</field> + </createData> + <createData entity="SimpleProduct2" stepKey="simpleProduct1"> + <field key="price">20.00</field> + </createData> + + <!-- Create configurable product and add it to the category --> + <createData entity="ApiCategory" stepKey="createCategory"/> + <createData entity="ApiConfigurableProduct" stepKey="createConfigProduct"> + <requiredEntity createDataKey="createCategory"/> + </createData> + + <!-- Create an attribute with two options to be used in the first child product --> + <createData entity="productAttributeWithTwoOptions" stepKey="createConfigProductAttribute"/> + <createData entity="productAttributeOption1" stepKey="createConfigProductAttributeOption1"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + </createData> + + <!-- Add the attribute we just created to default attribute set --> + <createData entity="AddToDefaultSet" stepKey="createConfigAddToAttributeSet"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + </createData> + + <!-- Get the option of the attribute we created --> + <getData entity="ProductAttributeOptionGetter" index="1" stepKey="getConfigAttributeOption1"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + </getData> + + <!-- Create a simple product and give it the attribute with option --> + <createData entity="ApiSimpleOne" stepKey="createConfigChildProduct1"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + <requiredEntity createDataKey="getConfigAttributeOption1"/> + <field key="price">30.00</field> + </createData> + + <!-- Create the configurable product --> + <createData entity="ConfigurableProductTwoOptions" stepKey="createConfigProductOption"> + <requiredEntity createDataKey="createConfigProduct"/> + <requiredEntity createDataKey="createConfigProductAttribute"/> + <requiredEntity createDataKey="getConfigAttributeOption1"/> + </createData> + + <!-- Add simple product to the configurable product --> + <createData entity="ConfigurableProductAddChild" stepKey="createConfigProductAddChild1"> + <requiredEntity createDataKey="createConfigProduct"/> + <requiredEntity createDataKey="createConfigChildProduct1"/> + </createData> + <magentoCLI command="indexer:reindex" stepKey="reindex"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> + </before> + <after> + <createData entity="DefaultShippingMethodsConfig" stepKey="defaultShippingMethodsConfig"/> + <createData entity="DisableFreeShippingConfig" stepKey="disableFreeShippingConfig"/> + <deleteData createDataKey="simpleCustomer" stepKey="deleteSimpleCustomer"/> + <deleteData createDataKey="simpleProduct" stepKey="deleteSimpleProduct"/> + <deleteData createDataKey="simpleProduct1" stepKey="deleteSimpleProduct1"/> + <deleteData createDataKey="createConfigChildProduct1" stepKey="deleteConfigChildProduct"/> + <deleteData createDataKey="createConfigProduct" stepKey="deleteConfigurableProduct"/> + <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteProductAttribute"/> + <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <!--Filter and Open the customer edit page --> + <actionGroup ref="AdminFilterCustomerByEmail" stepKey="filterTheCustomer"> + <argument name="email" value="$$simpleCustomer.email$$"/> + </actionGroup> + <click selector="{{AdminCustomerGridSection.customerEditLinkByEmail($$simpleCustomer.email$$)}}" stepKey="clickOnEditButton"/> + <waitForPageLoad stepKey="waitForCustomerEditPageToLoad"/> + <click selector="{{AdminCustomerMainActionsSection.createOrderBtn}}" stepKey="clickOnCreateOrderButton"/> + <waitForPageLoad stepKey="waitForOrderPageToLoad"/> + + <!--Add configurable product to order--> + <actionGroup ref="addConfigurableProductToOrderFromAdmin" stepKey="addConfigurableProductToOrder"> + <argument name="product" value="$$createConfigProduct$$"/> + <argument name="attribute" value="$$createConfigProductAttribute$$"/> + <argument name="option" value="$$getConfigAttributeOption1$$"/> + </actionGroup> + + <!--Add Simple product to order--> + <actionGroup ref="addSimpleProductToOrder" stepKey="addSimpleProductToOrder"> + <argument name="product" value="$$simpleProduct$$"/> + </actionGroup> + + <!--Add Second Simple product to order--> + <actionGroup ref="addSimpleProductToOrder" stepKey="addSecondSimpleProductToOrder"> + <argument name="product" value="$$simpleProduct1$$"/> + </actionGroup> + + <!-- Move Products to the WishList --> + <selectOption selector="{{AdminOrderFormItemsOrderedSection.moveProduct($$simpleProduct.name$$)}}" userInput="Move to Wish List" stepKey="moveProductToWishList"/> + <selectOption selector="{{AdminOrderFormItemsOrderedSection.moveProduct($$createConfigProduct.name$$)}}" userInput="Move to Wish List" stepKey="moveConfigurableProductToWishList"/> + <click selector="{{OrdersGridSection.update}}" stepKey="clickOnUpdateItemsAndQuantity"/> + + <!-- Assert products in Wish List section --> + <see selector="{{AdminCreateOrderWishListSection.wishListBlock}}" userInput="$$simpleProduct.name$$" stepKey="seeSimpleProductInWishList"/> + <see selector="{{AdminCreateOrderWishListSection.wishListBlock}}" userInput="$$createConfigProduct.name$$" stepKey="seeConfigurableProductInWishList"/> + + <!-- Add products to order from Wish List --> + <waitForElementVisible selector="{{AdminCreateOrderWishListSection.addProductToOrderCheckBox($$simpleProduct.name$$)}}" stepKey="waitForCheckBoxToVisible"/> + <click selector="{{AdminCreateOrderWishListSection.addProductToOrderCheckBox($$simpleProduct.name$$)}}" stepKey="selectProductToAddToOrder"/> + <click selector="{{AdminCreateOrderWishListSection.addConfigProductToOrder($$createConfigProduct.name$$)}}" stepKey="AddConfigurableProductToOrder"/> + <waitForElementVisible selector="{{AdminOrderFormConfigureProductSection.optionSelect($$createConfigProductAttribute.default_frontend_label$$)}}" stepKey="waitForConfigurablePopover"/> + <selectOption selector="{{AdminOrderFormConfigureProductSection.optionSelect($$createConfigProductAttribute.default_frontend_label$$)}}" userInput="$$getConfigAttributeOption1.label$$" stepKey="selectConfigurableOption"/> + <click selector="{{AdminOrderFormConfigureProductSection.ok}}" stepKey="clickOkButton"/> + <click selector="{{AdminCustomerCreateNewOrderSection.updateChangesBtn}}" stepKey="clickOnUpdateButton"/> + + <!-- Assert Products in Order item section --> + <see selector="{{AdminOrderItemsOrderedSection.productName}}" userInput="$$simpleProduct.name$$" stepKey="seeSimpleProductInOrderItemGrid"/> + <see selector="{{AdminOrderItemsOrderedSection.productName}}" userInput="$$createConfigProduct.name$$" stepKey="seeConfigProductInOrderItemGrid"/> + + <!-- Move Products to the Shopping Cart --> + <selectOption selector="{{AdminOrderFormItemsOrderedSection.moveProduct($$simpleProduct.name$$)}}" userInput="Move to Shopping Cart" stepKey="moveFirstSimpleProductToShoppingCart"/> + <selectOption selector="{{AdminOrderFormItemsOrderedSection.moveProduct($$simpleProduct1.name$$)}}" userInput="Move to Shopping Cart" stepKey="moveSecondSimpleProductToShoppingCart"/> + <click selector="{{OrdersGridSection.update}}" stepKey="clickOnUpdateItems"/> + + <!-- Assert products in Shopping cart section --> + <see selector="{{AdminCreateOrderShoppingCartSection.shoppingCartBlock}}" userInput="$$simpleProduct.name$$" stepKey="seeProductInShoppingCart"/> + <see selector="{{AdminCreateOrderShoppingCartSection.shoppingCartBlock}}" userInput="$$simpleProduct1.name$$" stepKey="seeSecondProductInShoppingCart"/> + + <!-- Move products to the order from shopping cart --> + <waitForElementVisible selector="{{AdminCreateOrderShoppingCartSection.addToOrderCheckBox($$simpleProduct.name$$)}}" stepKey="waitForAddToOrderCheckBox"/> + <click selector="{{AdminCreateOrderShoppingCartSection.addToOrderCheckBox($$simpleProduct.name$$)}}" stepKey="selectFirstProduct"/> + <click selector="{{AdminCreateOrderShoppingCartSection.addToOrderCheckBox($$simpleProduct1.name$$)}}" stepKey="selectSecondProduct"/> + <click selector="{{AdminCustomerCreateNewOrderSection.updateChangesBtn}}" stepKey="clickOnUpdateButton1"/> + + <!-- After move, assert products are not present in Shopping cart section --> + <dontSee selector="{{AdminCreateOrderShoppingCartSection.shoppingCartBlock}}" userInput="$$simpleProduct.name$$" stepKey="donSeeProductInShoppingCart"/> + <dontSee selector="{{AdminCreateOrderShoppingCartSection.shoppingCartBlock}}" userInput="$$simpleProduct1.name$$" stepKey="dontSeeSecondProductInShoppingCart"/> + + <!-- After move, assert products are present in Wish List section --> + <see selector="{{AdminCreateOrderWishListSection.wishListBlock}}" userInput="$$simpleProduct.name$$" stepKey="seeSimpleProductInWishList1"/> + <see selector="{{AdminCreateOrderWishListSection.wishListBlock}}" userInput="$$createConfigProduct.name$$" stepKey="seeConfigurableProductInWishList1"/> + + <!-- After move, assert products are present in order items section --> + <see selector="{{AdminOrderItemsOrderedSection.productName}}" userInput="$$simpleProduct.name$$" stepKey="seeSimpleProductInOrderItemGrid1"/> + <see selector="{{AdminOrderItemsOrderedSection.productName}}" userInput="$$createConfigProduct.name$$" stepKey="seeConfigProductInOrderItemGrid1"/> + <see selector="{{AdminOrderItemsOrderedSection.productName}}" userInput="$$simpleProduct1.name$$" stepKey="seeSecondProductInOrderItemGrid1"/> + + <!-- Select Free Shipping --> + <waitForElementVisible selector="{{AdminInvoicePaymentShippingSection.getShippingMethodAndRates}}" stepKey="waitForShippingSection"/> + <click selector="{{AdminInvoicePaymentShippingSection.getShippingMethodAndRates}}" stepKey="openShippingMethod"/> + <waitForPageLoad stepKey="waitForShippingMethods"/> + <click selector="{{AdminOrderFormPaymentSection.freeShippingOption}}" stepKey="chooseShippingMethod"/> + <waitForPageLoad stepKey="waitForPageToLoad"/> + + <!-- Submit order --> + <click selector="{{AdminOrderFormActionSection.SubmitOrder}}" stepKey="submitOrder"/> + + <!-- Verify order information --> + <actionGroup ref="verifyCreatedOrderInformation" stepKey="verifyCreatedOrderInformation"/> + <grabTextFrom selector="|Order # (\d+)|" stepKey="orderId"/> + + <!-- Filter and Open the customer edit page --> + <actionGroup ref="AdminFilterCustomerByEmail" stepKey="filterTheCustomer1"> + <argument name="email" value="$$simpleCustomer.email$$"/> + </actionGroup> + <click selector="{{AdminCustomerGridSection.customerEditLinkByEmail($$simpleCustomer.email$$)}}" stepKey="clickOnEditButton1"/> + <waitForPageLoad stepKey="waitForCustomerEditPageToLoad1"/> + <click selector="{{AdminEditCustomerInformationSection.orders}}" stepKey="clickOnOrdersButton"/> + <waitForPageLoad stepKey="waitForOrderPageToOpen"/> + <click selector="{{AdminEditCustomerOrdersSection.orderIdInGrid('$orderId')}}" stepKey="selectOnOrderID"/> + + <!-- Assert ordered product in customer order section--> + <waitForPageLoad stepKey="waitForOrderInformationTolLoad"/> + <see selector="{{AdminOrderItemsOrderedSection.productNameColumn}}" userInput="$$createConfigProduct.name$$" stepKey="seeConfigurableProductInGrid"/> + <see selector="{{AdminOrderItemsOrderedSection.productNameColumn}}" userInput="$$simpleProduct.name$$" stepKey="seeFirstProductInGrid"/> + <see selector="{{AdminOrderItemsOrderedSection.productNameColumn}}" userInput="$$simpleProduct1.name$$" stepKey="seeSecondProductInGrid"/> + <see selector="{{AdminOrderItemsOrderedSection.statusColumn}}" userInput="Ordered" stepKey="seeProductStatus"/> + <see selector="{{AdminOrderItemsOrderedSection.subtotalColumn}}" userInput="$30.00" stepKey="seeConfigurableProductSubtotal"/> + <see selector="{{AdminOrderItemsOrderedSection.subtotalColumn}}" userInput="$10.00" stepKey="seeFirstProductSubtotal"/> + <see selector="{{AdminOrderItemsOrderedSection.subtotalColumn}}" userInput="$20.00" stepKey="seeSecondProductSubtotal"/> + <see selector="{{AdminOrderTotalSection.grandTotal}}" userInput="$60.00" stepKey="seeOrderGrandTotal"/> + </test> +</tests> \ No newline at end of file diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CreateOrderFromEditCustomerPageTest.xml b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CreateOrderFromEditCustomerPageTest.xml index e96bcc0abc1bc..ca506adf39edc 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CreateOrderFromEditCustomerPageTest.xml +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CreateOrderFromEditCustomerPageTest.xml @@ -21,6 +21,7 @@ <item name="grandTotal" xsi:type="string">19.00</item> </data> <data name="issue" xsi:type="string">MAGETWO-65165: Unable to add product to wish list using 'create order' interface</data> + <data name="tag" xsi:type="string">to_maintain:yes, mftf_migrated:yes</data> <constraint name="Magento\Sales\Test\Constraint\AssertOrderSuccessCreateMessage" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderGrandTotal" /> <constraint name="Magento\Sales\Test\Constraint\AssertProductInCustomerShoppingCartOnBackendGrid" /> From fafa1d5eee0929ec53fa6992e4e3451f7f1ee533 Mon Sep 17 00:00:00 2001 From: Cristian Partica <cpartica@magento.com> Date: Mon, 6 May 2019 15:36:08 -0500 Subject: [PATCH 356/773] MC-15959: Implement caching for url resolver - refactor test --- .../Controller/Cms/CmsPageCacheTest.php | 60 +++++++-------- .../AllEntitiesUrlResolverCacheTest.php | 73 +++++++------------ 2 files changed, 55 insertions(+), 78 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/CmsPageCacheTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/CmsPageCacheTest.php index d6dcf07409140..45a50005bc11d 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/CmsPageCacheTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/CmsPageCacheTest.php @@ -11,6 +11,7 @@ use Magento\Cms\Model\PageRepository; use Magento\GraphQl\Controller\GraphQl; use Magento\GraphQlCache\Controller\AbstractGraphqlCacheTest; +use Magento\Tests\NamingConvention\true\string; /** * Test caching works for CMS page @@ -49,37 +50,8 @@ public function testToCheckCmsPageRequestCacheTags(): void $cmsPageBlank = $this->objectManager->get(GetPageByIdentifier::class)->execute('page_design_blank', 0); $pageIdBlank = $cmsPageBlank->getId(); - $queryCmsPage100 = - <<<QUERY - { - cmsPage(id: $pageId100) { - url_key - title - content - content_heading - page_layout - meta_title - meta_description - meta_keywords - } - } -QUERY; - - $queryCmsPageBlank = - <<<QUERY - { - cmsPage(id: $pageIdBlank) { - url_key - title - content - content_heading - page_layout - meta_title - meta_description - meta_keywords - } - } -QUERY; + $queryCmsPage100 = $this->getQuery($pageId100); + $queryCmsPageBlank = $this->getQuery($pageIdBlank); // check to see that the first entity gets a MISS when called the first time $request = $this->prepareRequest($queryCmsPage100); @@ -129,7 +101,6 @@ public function testToCheckCmsPageRequestCacheTags(): void $expectedCacheTags = ['cms_p', 'cms_p_' .$pageIdBlank , 'FPC']; $this->assertEquals($expectedCacheTags, $requestedCacheTags); - /** @var PageRepository $pageRepository */ $pageRepository = $this->objectManager->get(PageRepository::class); @@ -161,4 +132,29 @@ public function testToCheckCmsPageRequestCacheTags(): void $expectedCacheTags = ['cms_p', 'cms_p_' .$pageId100 , 'FPC']; $this->assertEquals($expectedCacheTags, $requestedCacheTags); } + + /** + * Get cms query + * + * @param string $id + * @return string + */ + private function getQuery(string $id) : string + { + $queryCmsPage = <<<QUERY + { + cmsPage(id: $id) { + url_key + title + content + content_heading + page_layout + meta_title + meta_description + meta_keywords + } + } +QUERY; + return $queryCmsPage; + } } diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/UrlRewrite/AllEntitiesUrlResolverCacheTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/UrlRewrite/AllEntitiesUrlResolverCacheTest.php index 908739f798366..785cd7693a11a 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/UrlRewrite/AllEntitiesUrlResolverCacheTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/UrlRewrite/AllEntitiesUrlResolverCacheTest.php @@ -64,30 +64,9 @@ public function testAllEntitiesUrlResolverRequestHasCorrectTags() ] ); $categoryId = $actualUrls->getEntityId(); - $categoryQuery - = <<<QUERY -{ - urlResolver(url:"{$categoryUrlKey}") - { - id - relative_url, - canonical_url - type - } -} -QUERY; + $categoryQuery = $this->getQuery($categoryUrlKey); - $productQuery = <<<QUERY -{ - urlResolver(url:"{$productUrlKey}") - { - id - relative_url - canonical_url - type - } -} -QUERY; + $productQuery = $this->getQuery($productUrlKey); /** @var GetPageByIdentifierInterface $page */ $page = $this->objectManager->get(GetPageByIdentifierInterface::class); @@ -95,18 +74,8 @@ public function testAllEntitiesUrlResolverRequestHasCorrectTags() $cmsPage = $page->execute('page100', 0); $cmsPageId = $cmsPage->getId(); $requestPath = $cmsPage->getIdentifier(); - $pageQuery - = <<<QUERY -{ - urlResolver(url:"{$requestPath}") - { - id - relative_url - canonical_url - type - } -} -QUERY; + $pageQuery = $this->getQuery($requestPath); + // query category for MISS $request = $this->prepareRequest($categoryQuery); $response = $this->graphqlController->dispatch($request); @@ -163,17 +132,7 @@ public function testAllEntitiesUrlResolverRequestHasCorrectTags() $product->setUrlKey('something-else-that-invalidates-the-cache'); $productRepository->save($product); - $productQuery = <<<QUERY -{ - urlResolver(url:"something-else-that-invalidates-the-cache.html") - { - id - relative_url - canonical_url - type - } -} -QUERY; + $productQuery = $this->getQuery('something-else-that-invalidates-the-cache.html'); // query category for MISS $request = $this->prepareRequest($categoryQuery); @@ -193,4 +152,26 @@ public function testAllEntitiesUrlResolverRequestHasCorrectTags() $actualCacheTags = explode(',', $rawActualCacheTags); $this->assertEquals($expectedCacheTags, $actualCacheTags); } + + /** + * Get urlResolver query + * + * @param string $id + * @return string + */ + private function getQuery(string $requestPath) : string + { + $resolverQuery = <<<QUERY +{ + urlResolver(url:"{$requestPath}") + { + id + relative_url + canonical_url + type + } +} +QUERY; + return $resolverQuery; + } } From e67fbbd757e7a835081c9f6dfa7265431d5edd87 Mon Sep 17 00:00:00 2001 From: Viktor Petryk <victor.petryk@transoftgroup.com> Date: Tue, 7 May 2019 09:35:01 +0300 Subject: [PATCH 357/773] MC-16221: Cannot save Shipping Methods page because in UPS method have required fields --- .../adminhtml/templates/system/shipping/carrier_config.phtml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Ups/view/adminhtml/templates/system/shipping/carrier_config.phtml b/app/code/Magento/Ups/view/adminhtml/templates/system/shipping/carrier_config.phtml index 411bec20cde57..c87c7f8c524fe 100644 --- a/app/code/Magento/Ups/view/adminhtml/templates/system/shipping/carrier_config.phtml +++ b/app/code/Magento/Ups/view/adminhtml/templates/system/shipping/carrier_config.phtml @@ -121,7 +121,7 @@ require(["prototype"], function(){ freeMethod.insert(option); option = new Element('option', {value:code}).update(originShipment[code]); - if (this.storedUpsType == 'UPS') { + if (this.storedUpsType == 'UPS_XML') { if (originShipmentTitle != 'default' || inArray(this.storedAllowedMethods, code)) { option.selected = true; } @@ -143,7 +143,7 @@ require(["prototype"], function(){ setFormValues: function() { var a; - if ($F(this.carriersUpsTypeId) == 'UPS') { + if ($F(this.carriersUpsTypeId) == 'UPS_XML') { for (a = 0; a < this.checkingUpsXmlId.length; a++) { $(this.checkingUpsXmlId[a]).removeClassName('required-entry'); } From 4acd942fb4f3b90220eb00cec24bc34d1a892f84 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Tue, 7 May 2019 15:36:26 +0300 Subject: [PATCH 358/773] MC-16244: CMS Block don't show on category page with Display Mode CMS Block only --- .../Collection/SearchCriteriaResolver.php | 2 +- .../Collection/SearchCriteriaResolverTest.php | 104 ++++++++++++++++++ 2 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 app/code/Magento/Elasticsearch/Test/Unit/Model/ResourceModel/Fulltext/Collection/SearchCriteriaResolverTest.php diff --git a/app/code/Magento/Elasticsearch/Model/ResourceModel/Fulltext/Collection/SearchCriteriaResolver.php b/app/code/Magento/Elasticsearch/Model/ResourceModel/Fulltext/Collection/SearchCriteriaResolver.php index 32cb85ff750c4..d1f1abb65a0ab 100644 --- a/app/code/Magento/Elasticsearch/Model/ResourceModel/Fulltext/Collection/SearchCriteriaResolver.php +++ b/app/code/Magento/Elasticsearch/Model/ResourceModel/Fulltext/Collection/SearchCriteriaResolver.php @@ -79,7 +79,7 @@ public function resolve(): SearchCriteria $this->builder->setPageSize($this->size); $searchCriteria = $this->builder->create(); $searchCriteria->setRequestName($this->searchRequestName); - $searchCriteria->setSortOrders(array_merge(['relevance' => 'DESC'], $this->orders)); + $searchCriteria->setSortOrders(array_merge(['relevance' => 'DESC'], $this->orders ?: [])); $searchCriteria->setCurrentPage($this->currentPage - 1); return $searchCriteria; diff --git a/app/code/Magento/Elasticsearch/Test/Unit/Model/ResourceModel/Fulltext/Collection/SearchCriteriaResolverTest.php b/app/code/Magento/Elasticsearch/Test/Unit/Model/ResourceModel/Fulltext/Collection/SearchCriteriaResolverTest.php new file mode 100644 index 0000000000000..babaf36f1439f --- /dev/null +++ b/app/code/Magento/Elasticsearch/Test/Unit/Model/ResourceModel/Fulltext/Collection/SearchCriteriaResolverTest.php @@ -0,0 +1,104 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Elasticsearch\Test\Unit\Model\ResourceModel\Fulltext\Collection; + +use Magento\Elasticsearch\Model\ResourceModel\Fulltext\Collection\SearchCriteriaResolver; +use Magento\Framework\Api\Search\SearchCriteriaBuilder; +use Magento\Framework\Api\Search\SearchCriteria; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; + +/** + * Unit test for SearchCriteriaResolver + */ +class SearchCriteriaResolverTest extends \PHPUnit\Framework\TestCase +{ + /** + * @var SearchCriteriaBuilder|\PHPUnit_Framework_MockObject_MockObject + */ + private $searchCriteriaBuilder; + + /** + * @inheritdoc + */ + protected function setUp() + { + $this->searchCriteriaBuilder = $this->getMockBuilder(SearchCriteriaBuilder::class) + ->disableOriginalConstructor() + ->setMethods(['setPageSize', 'create']) + ->getMock(); + } + + /** + * @param array|null $orders + * @param array $expected + * @dataProvider resolveSortOrderDataProvider + */ + public function testResolve($orders, array $expected) + { + $searchRequestName = 'test'; + $currentPage = 1; + $size = 10; + + $searchCriteria = $this->getMockBuilder(SearchCriteria::class) + ->disableOriginalConstructor() + ->setMethods(['setRequestName', 'setSortOrders', 'setCurrentPage']) + ->getMock(); + $searchCriteria->expects($this->once()) + ->method('setRequestName') + ->with($searchRequestName) + ->willReturn($searchCriteria); + $searchCriteria->expects($this->once()) + ->method('setSortOrders') + ->with($expected) + ->willReturn($searchCriteria); + $searchCriteria->expects($this->once()) + ->method('setCurrentPage') + ->with($currentPage - 1) + ->willReturn($searchCriteria); + + $this->searchCriteriaBuilder->expects($this->once()) + ->method('create') + ->willReturn($searchCriteria); + $this->searchCriteriaBuilder->expects($this->once()) + ->method('setPageSize') + ->with($size) + ->willReturn($this->searchCriteriaBuilder); + + $objectManager = new ObjectManagerHelper($this); + /** @var SearchCriteriaResolver $model */ + $model = $objectManager->getObject( + SearchCriteriaResolver::class, + [ + 'builder' => $this->searchCriteriaBuilder, + 'searchRequestName' => $searchRequestName, + 'currentPage' => $currentPage, + 'size' => $size, + 'orders' => $orders, + ] + ); + + $model->resolve(); + } + + /** + * @return array + */ + public function resolveSortOrderDataProvider() + { + return [ + [ + null, + ['relevance' => 'DESC'], + ], + [ + ['test' => 'ASC'], + ['relevance' => 'DESC', 'test' => 'ASC'], + ], + ]; + } +} From 02b97b6cb3d10127b8983b0e67c7669cb4f89dcd Mon Sep 17 00:00:00 2001 From: Viktor Sevch <svitja@ukr.net> Date: Tue, 7 May 2019 16:38:06 +0300 Subject: [PATCH 359/773] MC-16220: Unable to apply Discount Code on checkout --- app/code/Magento/SalesRule/Observer/CouponCodeValidation.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/SalesRule/Observer/CouponCodeValidation.php b/app/code/Magento/SalesRule/Observer/CouponCodeValidation.php index 98fe783ea0de5..02fd81078ea7c 100644 --- a/app/code/Magento/SalesRule/Observer/CouponCodeValidation.php +++ b/app/code/Magento/SalesRule/Observer/CouponCodeValidation.php @@ -64,7 +64,8 @@ public function execute(EventObserver $observer) //Only validating the code if it's a new code. /** @var Quote[] $found */ $found = $this->cartRepository->getList( - $this->criteriaBuilder->addFilter(CartInterface::KEY_ENTITY_ID, $quote->getId())->create() + $this->criteriaBuilder->addFilter('main_table.' . CartInterface::KEY_ENTITY_ID, $quote->getId()) + ->create() )->getItems(); if (!$found || ((string)array_shift($found)->getCouponCode()) !== (string)$code) { try { From fb8d8bf5a542b65e04c5cdcecaf6f53ab7ceaa69 Mon Sep 17 00:00:00 2001 From: Cristian Partica <cpartica@magento.com> Date: Tue, 7 May 2019 09:32:54 -0500 Subject: [PATCH 360/773] MC-15959: Implement caching for url resolver - fix static tests --- .../Magento/GraphQlCache/Controller/Cms/CmsPageCacheTest.php | 1 - .../Controller/UrlRewrite/AllEntitiesUrlResolverCacheTest.php | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/CmsPageCacheTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/CmsPageCacheTest.php index 45a50005bc11d..0248f870a5f11 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/CmsPageCacheTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/Cms/CmsPageCacheTest.php @@ -11,7 +11,6 @@ use Magento\Cms\Model\PageRepository; use Magento\GraphQl\Controller\GraphQl; use Magento\GraphQlCache\Controller\AbstractGraphqlCacheTest; -use Magento\Tests\NamingConvention\true\string; /** * Test caching works for CMS page diff --git a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/UrlRewrite/AllEntitiesUrlResolverCacheTest.php b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/UrlRewrite/AllEntitiesUrlResolverCacheTest.php index 785cd7693a11a..7accb1d7d0b26 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/UrlRewrite/AllEntitiesUrlResolverCacheTest.php +++ b/dev/tests/integration/testsuite/Magento/GraphQlCache/Controller/UrlRewrite/AllEntitiesUrlResolverCacheTest.php @@ -43,6 +43,7 @@ protected function setUp(): void * * @magentoDataFixture Magento/CatalogUrlRewrite/_files/product_with_category.php * @magentoDataFixture Magento/Cms/_files/pages.php + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ public function testAllEntitiesUrlResolverRequestHasCorrectTags() { From 66301dd8ebcf90c4147871d9db78052b039d2166 Mon Sep 17 00:00:00 2001 From: OlgaVasyltsun <olga.vasyltsun@gmail.com> Date: Wed, 8 May 2019 08:12:20 +0300 Subject: [PATCH 361/773] MAGETWO-99518: Update Url ActionList --- lib/internal/Magento/Framework/App/Router/ActionList.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/App/Router/ActionList.php b/lib/internal/Magento/Framework/App/Router/ActionList.php index 9944e617b1ce6..1640d4a98d354 100644 --- a/lib/internal/Magento/Framework/App/Router/ActionList.php +++ b/lib/internal/Magento/Framework/App/Router/ActionList.php @@ -1,6 +1,5 @@ <?php /** - * * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ @@ -10,6 +9,9 @@ use Magento\Framework\Serialize\Serializer\Serialize; use Magento\Framework\Module\Dir\Reader as ModuleReader; +/** + * Class to retrieve action class. + */ class ActionList { /** @@ -91,6 +93,7 @@ public function get($module, $area, $namespace, $action) if ($area) { $area = '\\' . $area; } + $namespace = strtolower($namespace); if (strpos($namespace, self::NOT_ALLOWED_IN_NAMESPACE_PATH) !== false) { return null; } From 39f5deaa9aa62616aea4242a92a498cd04c8f7c0 Mon Sep 17 00:00:00 2001 From: DianaRusin <rusind95@gmail.com> Date: Wed, 8 May 2019 11:01:45 +0300 Subject: [PATCH 362/773] MAGETWO-99590: [Auth.net Accept.js] Order is placed only from second time in Admin with Auth.net payment method --- .../adminhtml/templates/payment/script.phtml | 22 +++++++++++-------- .../view/adminhtml/web/js/payment-form.js | 5 ++--- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/app/code/Magento/AuthorizenetAcceptjs/view/adminhtml/templates/payment/script.phtml b/app/code/Magento/AuthorizenetAcceptjs/view/adminhtml/templates/payment/script.phtml index 6960bddf696af..95d41f034836a 100644 --- a/app/code/Magento/AuthorizenetAcceptjs/view/adminhtml/templates/payment/script.phtml +++ b/app/code/Magento/AuthorizenetAcceptjs/view/adminhtml/templates/payment/script.phtml @@ -6,12 +6,16 @@ /** @var Magento\AuthorizenetAcceptjs\Block\Payment $block */ ?> -<script type="text/x-magento-init"> - { - "#payment_form_<?= $block->escapeJs($block->escapeHtml($block->getMethodCode())) ?>": { - "Magento_AuthorizenetAcceptjs/js/payment-form": { - "config": <?= /* @noEscape */ $block->getPaymentConfig() ?> - } - } - } -</script> \ No newline at end of file +<script> + //<![CDATA[ + require( + [ + 'Magento_AuthorizenetAcceptjs/js/payment-form' + ], function(Authorizenet) { + var config = <?= /* @noEscape */ $block->getPaymentConfig() ?>, + form = "#payment_form_<?= $block->escapeJs($block->escapeHtml($block->getMethodCode())) ?>"; + + new Authorizenet(config, form); + }); + //]]> +</script> diff --git a/app/code/Magento/AuthorizenetAcceptjs/view/adminhtml/web/js/payment-form.js b/app/code/Magento/AuthorizenetAcceptjs/view/adminhtml/web/js/payment-form.js index 68c2f22f6ed44..e3a0886797d63 100644 --- a/app/code/Magento/AuthorizenetAcceptjs/view/adminhtml/web/js/payment-form.js +++ b/app/code/Magento/AuthorizenetAcceptjs/view/adminhtml/web/js/payment-form.js @@ -8,9 +8,8 @@ define([ ], function (AuthorizenetAcceptjs, $) { 'use strict'; - return function (data, element) { - var $form = $(element), - config = data.config; + return function (config, element) { + var $form = $(element); config.active = $form.length > 0 && !$form.is(':hidden'); new AuthorizenetAcceptjs(config); From 8c45abbf4b037a975cbb518de9e69411f208cdd0 Mon Sep 17 00:00:00 2001 From: Stas Kozar <stas.kozar@transoftgroup.com> Date: Wed, 8 May 2019 15:11:27 +0300 Subject: [PATCH 363/773] MC-15448: One can't download or delete export csv file from export index page grid --- .../Controller/Adminhtml/Export.php | 5 + .../Adminhtml/Export/File/DeleteTest.php | 93 +++++++++++++++++++ 2 files changed, 98 insertions(+) create mode 100644 dev/tests/integration/testsuite/Magento/ImportExport/Controller/Adminhtml/Export/File/DeleteTest.php diff --git a/app/code/Magento/ImportExport/Controller/Adminhtml/Export.php b/app/code/Magento/ImportExport/Controller/Adminhtml/Export.php index 71ed437426226..28ca475edd4cc 100644 --- a/app/code/Magento/ImportExport/Controller/Adminhtml/Export.php +++ b/app/code/Magento/ImportExport/Controller/Adminhtml/Export.php @@ -18,4 +18,9 @@ abstract class Export extends Action * @see _isAllowed() */ const ADMIN_RESOURCE = 'Magento_ImportExport::export'; + + /** + * @inheritdoc + */ + protected $_publicActions = ['download', 'delete']; } diff --git a/dev/tests/integration/testsuite/Magento/ImportExport/Controller/Adminhtml/Export/File/DeleteTest.php b/dev/tests/integration/testsuite/Magento/ImportExport/Controller/Adminhtml/Export/File/DeleteTest.php new file mode 100644 index 0000000000000..661f8affe6f8e --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/ImportExport/Controller/Adminhtml/Export/File/DeleteTest.php @@ -0,0 +1,93 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\ImportExport\Controller\Adminhtml\Export\File; + +use Magento\Framework\App\Filesystem\DirectoryList; + +/** + * Test for \Magento\ImportExport\Controller\Adminhtml\Export\File\Delete class. + */ +class DeleteTest extends \PHPUnit\Framework\TestCase +{ + /** + * @var \Magento\ImportExport\Controller\Adminhtml\Export\File\Delete + */ + private $model; + + /** + * @var \Magento\Framework\Filesystem\Directory\WriteInterface + */ + private $varDirectory; + + /** + * @var string + */ + private $fullDirectoryPath; + + /** + * @var string + */ + private $fileName = 'catalog_product.csv'; + + /** + * @var \Magento\Framework\Filesystem + */ + private $filesystem; + + /** + * @var \Magento\Framework\ObjectManagerInterface + */ + private $objectManager; + + /** + * @inheritdoc + */ + protected function setUp() + { + $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + $this->filesystem = $this->objectManager->get(\Magento\Framework\Filesystem::class); + $this->varDirectory = $this->filesystem->getDirectoryWrite(DirectoryList::VAR_DIR); + $this->varDirectory->create($this->varDirectory->getRelativePath('export')); + $this->fullDirectoryPath = $this->varDirectory->getAbsolutePath('export'); + $filePath = $this->fullDirectoryPath . DIRECTORY_SEPARATOR . $this->fileName; + $fixtureDir = realpath(__DIR__ . '/../../Import/_files'); + copy($fixtureDir . '/' . $this->fileName, $filePath); + $this->model = $this->objectManager->get(\Magento\ImportExport\Controller\Adminhtml\Export\File\Delete::class); + } + + /** + * Check that file can be removed under var/export directory. + * + * @return void + */ + public function testExecute() + { + $this->model->getRequest()->setMethod('GET')->setParams(['filename' => 'catalog_product.csv']); + $this->model->execute(); + + $this->assertFalse( + $this->varDirectory->isExist( + $this->varDirectory->getRelativePath( 'export/' . $this->fileName) + ) + ); + } + + /** + * @inheritdoc + */ + public static function tearDownAfterClass() + { + $filesystem = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() + ->get(\Magento\Framework\Filesystem::class); + /** @var \Magento\Framework\Filesystem\Directory\WriteInterface $directory */ + $directory = $filesystem->getDirectoryWrite(DirectoryList::VAR_DIR); + if ($directory->isExist('export')) { + $directory->delete('export'); + } + } +} From 298b72343126f7754ce50fd80a071e92c53485bf Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Wed, 8 May 2019 13:30:42 -0500 Subject: [PATCH 364/773] GraphQl-299: Do not rely on global state in resolvers --- .../CustomerGraphQl/Model/Customer/UpdateCustomerAccount.php | 1 - app/code/Magento/UrlRewriteGraphQl/composer.json | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/app/code/Magento/CustomerGraphQl/Model/Customer/UpdateCustomerAccount.php b/app/code/Magento/CustomerGraphQl/Model/Customer/UpdateCustomerAccount.php index 236320b9390de..865baaf1faffb 100644 --- a/app/code/Magento/CustomerGraphQl/Model/Customer/UpdateCustomerAccount.php +++ b/app/code/Magento/CustomerGraphQl/Model/Customer/UpdateCustomerAccount.php @@ -74,7 +74,6 @@ public function __construct( * @throws GraphQlAlreadyExistsException * @throws GraphQlAuthenticationException * @throws GraphQlInputException - * @throws \Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException */ public function execute(CustomerInterface $customer, array $data, int $storeId): void { diff --git a/app/code/Magento/UrlRewriteGraphQl/composer.json b/app/code/Magento/UrlRewriteGraphQl/composer.json index 1c99276269aa7..e063903a5170f 100644 --- a/app/code/Magento/UrlRewriteGraphQl/composer.json +++ b/app/code/Magento/UrlRewriteGraphQl/composer.json @@ -5,8 +5,7 @@ "require": { "php": "~7.1.3||~7.2.0", "magento/framework": "*", - "magento/module-url-rewrite": "*", - "magento/module-store": "*" + "magento/module-url-rewrite": "*" }, "suggest": { "magento/module-graph-ql": "*" From ce64de2cf7f0f7f3f0e3e1b963f7ee27b5bea6e0 Mon Sep 17 00:00:00 2001 From: Kavitha <kanair@adobe.com> Date: Wed, 8 May 2019 13:35:45 -0500 Subject: [PATCH 365/773] MC-4559: Convert DeleteCustomerCustomAttributesEntityTest to MFTF --- .../Test/Mftf/Section/AdminOrderDetailsInformationSection.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderDetailsInformationSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderDetailsInformationSection.xml index a531f423d134c..a0e76e41a87b1 100644 --- a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderDetailsInformationSection.xml +++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderDetailsInformationSection.xml @@ -19,5 +19,6 @@ <element name="billingAddress" type="text" selector=".order-billing-address"/> <element name="shippingAddress" type="text" selector=".order-shipping-address"/> <element name="itemsOrdered" type="text" selector=".edit-order-table"/> + <element name="attributeLabel" type="text" selector="//label[contains(.,'{{attributeLabel}}')]" parameterized="true"/> </section> </sections> \ No newline at end of file From 7f2e8bd99cbdfdf294d1154855a5c555a78bba10 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Wed, 8 May 2019 14:48:32 -0500 Subject: [PATCH 366/773] GraphQl-299: Do not rely on global state in resolvers --- app/code/Magento/GraphQl/Model/Query/Resolver/Context.php | 4 ++-- app/code/Magento/GraphQl/composer.json | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/GraphQl/Model/Query/Resolver/Context.php b/app/code/Magento/GraphQl/Model/Query/Resolver/Context.php index e49040f70215b..1b24fddd9a383 100644 --- a/app/code/Magento/GraphQl/Model/Query/Resolver/Context.php +++ b/app/code/Magento/GraphQl/Model/Query/Resolver/Context.php @@ -74,7 +74,7 @@ public function __construct( } /** - * {@inheritdoc} + * @inheritdoc * * @return \Magento\Framework\GraphQl\Query\Resolver\ContextExtensionInterface */ @@ -84,7 +84,7 @@ public function getExtensionAttributes() : \Magento\Framework\GraphQl\Query\Reso } /** - * {@inheritdoc} + * @inheritdoc * * @param \Magento\Framework\GraphQl\Query\Resolver\ContextExtensionInterface $extensionAttributes * @return ContextInterface diff --git a/app/code/Magento/GraphQl/composer.json b/app/code/Magento/GraphQl/composer.json index 3a1e8d1bfd9f4..e2d347ce33c10 100644 --- a/app/code/Magento/GraphQl/composer.json +++ b/app/code/Magento/GraphQl/composer.json @@ -6,6 +6,7 @@ "php": "~7.1.3||~7.2.0", "magento/module-authorization": "*", "magento/module-eav": "*", + "magento/module-store": "*", "magento/framework": "*" }, "suggest": { From 84dc5811d78177c2e5ea6454dd00482cec64c9b1 Mon Sep 17 00:00:00 2001 From: Mila Lesechko <llesechk@adobe.com> Date: Wed, 8 May 2019 18:31:50 -0500 Subject: [PATCH 367/773] MC-4767: Convert PrintOrderFrontendGuestTest to MFTF --- .../Section/AdminProductFormBundleSection.xml | 3 +- .../AdminProductFormConfigurationsSection.xml | 1 + .../Test/Mftf/Data/ProductData.xml | 16 + ...dminAddToOrderBundleProductActionGroup.xml | 28 ++ ...dToOrderConfigurableProductActionGroup.xml | 28 ++ .../AdminAddToOrderCouponCodeActionGroup.xml | 19 ++ ...dToOrderDownloadableProductActionGroup.xml | 26 ++ ...nFilterProductInCreateOrderActionGroup.xml | 22 ++ .../AdminSubmitOrderActionGroup.xml | 1 + ...lesPrintOrderBillingAddressActionGroup.xml | 25 ++ ...ontFillOrdersAndReturnsFormActionGroup.xml | 21 ++ .../Test/Mftf/Page/AdminOrderCreatePage.xml | 1 + .../Mftf/Page/StorefrontPrintOrderPage.xml | 14 + .../AdminOrderFormConfigureProductSection.xml | 6 + .../Section/AdminOrderFormDiscountSection.xml | 15 + .../StorefrontGuestOrderViewSection.xml | 1 + .../Section/StorefrontOrderDetailsSection.xml | 20 ++ .../Test/StorefrontPrintOrderGuestTest.xml | 280 ++++++++++++++++++ .../Test/Mftf/Data/SalesRuleData.xml | 29 ++ .../TestCase/PrintOrderFrontendGuestTest.xml | 1 + 20 files changed, 556 insertions(+), 1 deletion(-) create mode 100644 app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAddToOrderBundleProductActionGroup.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAddToOrderConfigurableProductActionGroup.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAddToOrderCouponCodeActionGroup.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAddToOrderDownloadableProductActionGroup.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminFilterProductInCreateOrderActionGroup.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/ActionGroup/StorefrontAssertSalesPrintOrderBillingAddressActionGroup.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/ActionGroup/StorefrontFillOrdersAndReturnsFormActionGroup.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/Page/StorefrontPrintOrderPage.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormDiscountSection.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/Section/StorefrontOrderDetailsSection.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/Test/StorefrontPrintOrderGuestTest.xml diff --git a/app/code/Magento/Bundle/Test/Mftf/Section/AdminProductFormBundleSection.xml b/app/code/Magento/Bundle/Test/Mftf/Section/AdminProductFormBundleSection.xml index 516f40ac2e7b7..fe9f247c0a2e9 100644 --- a/app/code/Magento/Bundle/Test/Mftf/Section/AdminProductFormBundleSection.xml +++ b/app/code/Magento/Bundle/Test/Mftf/Section/AdminProductFormBundleSection.xml @@ -41,8 +41,9 @@ <element name="contentDropDownIfNotShowing" type="button" selector="//div[@data-index='content']//div[contains(@class, '_hide')]"/> <element name="longDescription" type="input" selector="#product_form_description"/> <element name="shortDescription" type="input" selector="#product_form_short_description"/> - <!--BundleOptinsDropDown--> + <!--BundleOptionsDropDown--> <element name="bundleOptionsDropDown" type="button" selector="div[data-index='bundle-items']" timeout="30"/> + <element name="currentBundleOption" type="text" selector="//div[@data-index='bundle-items']//div[@class='admin__collapsible-title']/span"/> <!--AddingAnOption--> <element name="addOptions" type="button" selector="//tr[@data-repeat-index='0']//td[4]" timeout="30"/> <!--SEODropdownTab--> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Section/AdminProductFormConfigurationsSection.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Section/AdminProductFormConfigurationsSection.xml index f6828a3b86312..8a54a73bfa29c 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Section/AdminProductFormConfigurationsSection.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Section/AdminProductFormConfigurationsSection.xml @@ -44,6 +44,7 @@ <element name="productQuantity" type="input" selector=".admin__control-text[name='product[quantity_and_stock_status][qty]']"/> <element name="currentVariationsQuantityCells" type="button" selector="td[data-index='quantity_container']"/> <element name="rowByCode" type="textarea" selector="//span[contains(text(), '{{var1}}-{{var2}}')]//ancestor-or-self::tr" parameterized="true"/> + <element name="currentAttribute" type="text" selector="//fieldset[@class='admin__fieldset']/div[@class='admin__field _disabled']//span"/> </section> <section name="AdminConfigurableProductSelectAttributesSlideOut"> <element name="grid" type="button" selector=".admin__data-grid-wrap tbody"/> diff --git a/app/code/Magento/Downloadable/Test/Mftf/Data/ProductData.xml b/app/code/Magento/Downloadable/Test/Mftf/Data/ProductData.xml index 59651383febf2..3b0be227a1942 100644 --- a/app/code/Magento/Downloadable/Test/Mftf/Data/ProductData.xml +++ b/app/code/Magento/Downloadable/Test/Mftf/Data/ProductData.xml @@ -74,4 +74,20 @@ <requiredEntity type="custom_attribute_array">ApiProductShortDescription</requiredEntity> <requiredEntity type="downloadable_link">apiDownloadableLink</requiredEntity> </entity> + <entity name="DownloadableProductWithTwoLink1000" type="product"> + <data key="sku" unique="suffix">downloadableproduct</data> + <data key="type_id">downloadable</data> + <data key="attribute_set_id">4</data> + <data key="name" unique="suffix">DownloadableProduct</data> + <data key="price">50.99</data> + <data key="quantity">100</data> + <data key="weight">0</data> + <data key="status">1</data> + <data key="is_shareable">0</data> + <data key="urlKey" unique="suffix">downloadableproduct</data> + <requiredEntity type="product_extension_attribute">EavStockItem</requiredEntity> + <requiredEntity type="custom_attribute_array">CustomAttributeCategoryIds</requiredEntity> + <requiredEntity type="downloadable_link">downloadableLink1</requiredEntity> + <requiredEntity type="downloadable_link">downloadableLink2</requiredEntity> + </entity> </entities> diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAddToOrderBundleProductActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAddToOrderBundleProductActionGroup.xml new file mode 100644 index 0000000000000..2791a59071535 --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAddToOrderBundleProductActionGroup.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminAddToOrderBundleProductActionGroup"> + <arguments> + <argument name="option" type="string"/> + <argument name="selectedProduct" type="entity"/> + <argument name="quantity" type="string"/> + </arguments> + <scrollTo selector="{{AdminOrderFormConfigureProductSection.bundleItems}}" stepKey="scroll"/> + <click selector="{{AdminOrderFormConfigureProductSection.bundleItems}}" stepKey="focusOnSideDialog"/> + <waitForAjaxLoad stepKey="waitForAjax"/> + <click selector="{{AdminOrderFormConfigureProductSection.bundleSelect(option)}}" stepKey="clickSelector"/> + <selectOption selector="{{AdminOrderFormConfigureProductSection.bundleSelect(option)}}" userInput="{{selectedProduct.name}}" stepKey="selectionOption"/> + <waitForAjaxLoad stepKey="waitForAjaxLoad"/> + <fillField userInput="{{quantity}}" selector="{{AdminOrderFormConfigureProductSection.quantity}}" stepKey="fillQty"/> + <click selector="{{AdminOrderFormConfigureProductSection.ok}}" stepKey="clickOkConfigurablePopover"/> + <scrollTo selector="{{AdminOrderFormItemsSection.addSelected}}" x="0" y="-100" stepKey="scrollToAddSelectedButton"/> + <click selector="{{AdminOrderFormItemsSection.addSelected}}" stepKey="clickAddSelectedProducts"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAddToOrderConfigurableProductActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAddToOrderConfigurableProductActionGroup.xml new file mode 100644 index 0000000000000..33378a9fa58cc --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAddToOrderConfigurableProductActionGroup.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminAddToOrderConfigurableProductActionGroup"> + <arguments> + <argument name="attribute" type="string"/> + <argument name="option" type="string"/> + <argument name="quantity" type="string"/> + </arguments> + <scrollTo selector="{{AdminOrderFormConfigureProductSection.associatedProducts}}" stepKey="scroll"/> + <click selector="{{AdminOrderFormConfigureProductSection.associatedProducts}}" stepKey="focusOnSideDialog"/> + <waitForAjaxLoad stepKey="waitForAjax"/> + <click selector="{{AdminOrderFormConfigureProductSection.optionSelectNew(attribute)}}" stepKey="clickSelector"/> + <selectOption selector="{{AdminOrderFormConfigureProductSection.optionSelectNew(attribute)}}" userInput="{{option}}" stepKey="selectionOption"/> + <waitForAjaxLoad stepKey="waitForAjaxLoad"/> + <fillField userInput="{{quantity}}" selector="{{AdminOrderFormConfigureProductSection.quantity}}" stepKey="fillQty"/> + <click selector="{{AdminOrderFormConfigureProductSection.ok}}" stepKey="clickOkConfigurablePopover"/> + <scrollTo selector="{{AdminOrderFormItemsSection.addSelected}}" x="0" y="-100" stepKey="scrollToAddSelectedButton"/> + <click selector="{{AdminOrderFormItemsSection.addSelected}}" stepKey="clickAddSelectedProducts"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAddToOrderCouponCodeActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAddToOrderCouponCodeActionGroup.xml new file mode 100644 index 0000000000000..457a63efe07d2 --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAddToOrderCouponCodeActionGroup.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminAddToOrderCouponCodeActionGroup"> + <arguments> + <argument name="coupon" type="entity"/> + </arguments> + <fillField userInput="{{coupon.code}}" selector="{{AdminOrderFormDiscountSection.fieldCouponCode}}" stepKey="fillCouponCode"/> + <click selector="{{AdminOrderFormDiscountSection.applyCouponCode}}" stepKey="clickApply"/> + <waitForPageLoad stepKey="waitForPageLoad"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAddToOrderDownloadableProductActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAddToOrderDownloadableProductActionGroup.xml new file mode 100644 index 0000000000000..ec427fb9b6779 --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAddToOrderDownloadableProductActionGroup.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminAddToOrderDownloadableProductActionGroup"> + <arguments> + <argument name="link" type="string"/> + <argument name="quantity" type="string" defaultValue="1"/> + </arguments> + <scrollTo selector="{{AdminOrderFormConfigureProductSection.downloadableInformation}}" stepKey="scroll"/> + <click selector="{{AdminOrderFormConfigureProductSection.downloadableInformation}}" stepKey="focusOnSideDialog"/> + <waitForAjaxLoad stepKey="waitForAjax"/> + <checkOption selector="{{AdminOrderFormConfigureProductSection.checkLinkDownloadableProduct(link)}}" stepKey="checkLink"/> + <waitForAjaxLoad stepKey="waitForAjaxLoad"/> + <fillField userInput="{{quantity}}" selector="{{AdminOrderFormConfigureProductSection.quantity}}" stepKey="fillQty"/> + <click selector="{{AdminOrderFormConfigureProductSection.ok}}" stepKey="clickOkConfigurablePopover"/> + <scrollTo selector="{{AdminOrderFormItemsSection.addSelected}}" x="0" y="-100" stepKey="scrollToAddSelectedButton"/> + <click selector="{{AdminOrderFormItemsSection.addSelected}}" stepKey="clickAddSelectedProducts"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminFilterProductInCreateOrderActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminFilterProductInCreateOrderActionGroup.xml new file mode 100644 index 0000000000000..58d23f4b06bbc --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminFilterProductInCreateOrderActionGroup.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminFilterProductInCreateOrderActionGroup"> + <arguments> + <argument name="productSKU" type="string"/> + </arguments> + <click selector="{{AdminOrderFormItemsSection.addProducts}}" stepKey="clickAddProducts"/> + <fillField selector="{{AdminOrderFormItemsSection.skuFilter}}" userInput="{{productSKU}}" stepKey="fillSkuFilter"/> + <click selector="{{AdminOrderFormItemsSection.search}}" stepKey="clickSearchConfigurable"/> + <scrollTo selector="{{AdminOrderFormItemsSection.rowCheck('1')}}" x="0" y="-100" stepKey="scrollToCheckColumn"/> + <checkOption selector="{{AdminOrderFormItemsSection.rowCheck('1')}}" stepKey="selectProduct"/> + <waitForLoadingMaskToDisappear stepKey="waitForLoading"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminSubmitOrderActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminSubmitOrderActionGroup.xml index 56e81da1e55a0..f53e41386a389 100644 --- a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminSubmitOrderActionGroup.xml +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminSubmitOrderActionGroup.xml @@ -10,6 +10,7 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="AdminSubmitOrderActionGroup"> <click selector="{{OrdersGridSection.submitOrder}}" stepKey="submitOrder"/> + <waitForPageLoad stepKey="waitForPageLoad"/> <see stepKey="seeSuccessMessageForOrder" userInput="You created the order."/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/StorefrontAssertSalesPrintOrderBillingAddressActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/StorefrontAssertSalesPrintOrderBillingAddressActionGroup.xml new file mode 100644 index 0000000000000..fe7e0064e5c5e --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/StorefrontAssertSalesPrintOrderBillingAddressActionGroup.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AssertSalesPrintOrderBillingAddress"> + <arguments> + <argument name="address" type="entity"/> + </arguments> + <see userInput="{{address.firstname}}" selector="{{StorefrontOrderDetailsSection.billingAddressBlock}}" stepKey="seeFirstname"/> + <see userInput="{{address.lastname}}" selector="{{StorefrontOrderDetailsSection.billingAddressBlock}}" stepKey="seeLastname"/> + <see userInput="{{address.company}}" selector="{{StorefrontOrderDetailsSection.billingAddressBlock}}" stepKey="seeCompany"/> + <see userInput="{{address.street[0]}}" selector="{{StorefrontOrderDetailsSection.billingAddressBlock}}" stepKey="seeStreet"/> + <see userInput="{{address.city}}" selector="{{StorefrontOrderDetailsSection.billingAddressBlock}}" stepKey="seeCity"/> + <see userInput="{{address.state}}" selector="{{StorefrontOrderDetailsSection.billingAddressBlock}}" stepKey="seeState"/> + <see userInput="{{address.postcode}}" selector="{{StorefrontOrderDetailsSection.billingAddressBlock}}" stepKey="seePostcode"/> + <see userInput="{{address.country}}" selector="{{StorefrontOrderDetailsSection.billingAddressBlock}}" stepKey="seeCountry"/> + <see userInput="{{address.telephone}}" selector="{{StorefrontOrderDetailsSection.billingAddressBlock}}" stepKey="seeTelephone"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/StorefrontFillOrdersAndReturnsFormActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/StorefrontFillOrdersAndReturnsFormActionGroup.xml new file mode 100644 index 0000000000000..a3c0edf148126 --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/StorefrontFillOrdersAndReturnsFormActionGroup.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="StorefrontFillOrdersAndReturnsFormActionGroup"> + <arguments> + <argument name="orderNumber" type="string"/> + <argument name="customer" type="entity" defaultValue="$$createCustomer$$"/> + </arguments> + <fillField selector="{{StorefrontGuestOrderSearchSection.orderId}}" userInput="{{orderNumber}}" stepKey="inputOrderId"/> + <fillField selector="{{StorefrontGuestOrderSearchSection.billingLastName}}" userInput="{{customer.lastname}}" stepKey="inputBillingLastName"/> + <selectOption selector="{{StorefrontGuestOrderSearchSection.findOrderBy}}" userInput="email" stepKey="selectFindOrderByEmail"/> + <fillField selector="{{StorefrontGuestOrderSearchSection.email}}" userInput="{{customer.email}}" stepKey="inputEmail"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/Sales/Test/Mftf/Page/AdminOrderCreatePage.xml b/app/code/Magento/Sales/Test/Mftf/Page/AdminOrderCreatePage.xml index c8ec12203c676..bc9486d61fbfe 100644 --- a/app/code/Magento/Sales/Test/Mftf/Page/AdminOrderCreatePage.xml +++ b/app/code/Magento/Sales/Test/Mftf/Page/AdminOrderCreatePage.xml @@ -18,5 +18,6 @@ <section name="AdminOrderFormPaymentSection"/> <section name="AdminOrderFormTotalSection"/> <section name="AdminOrderFormStoreSelectorSection"/> + <section name="AdminOrderFormDiscountSection"/> </page> </pages> diff --git a/app/code/Magento/Sales/Test/Mftf/Page/StorefrontPrintOrderPage.xml b/app/code/Magento/Sales/Test/Mftf/Page/StorefrontPrintOrderPage.xml new file mode 100644 index 0000000000000..66761fa4a1caa --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/Page/StorefrontPrintOrderPage.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<pages xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/PageObject.xsd"> + <page name="StorefrontPrintOrderPage" url="sales/guest/print/order_id/{{order_id}}" module="Magento_Sales" area="storefront" parameterized="true"> + <section name="StorefrontOrderDetailsSection"/> + </page> +</pages> diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormConfigureProductSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormConfigureProductSection.xml index cd72da7445642..329a9a20ecaa0 100644 --- a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormConfigureProductSection.xml +++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormConfigureProductSection.xml @@ -10,7 +10,13 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="AdminOrderFormConfigureProductSection"> <element name="optionSelect" type="select" selector="//div[contains(@class,'product-options')]/div/div/select[../../label[text() = '{{option}}']]" parameterized="true"/> + <element name="optionSelectNew" type="select" selector="//label[text()='{{option1}}']/following-sibling::div/select" parameterized="true"/> <element name="quantity" type="input" selector="#product_composite_configure_input_qty"/> <element name="ok" type="button" selector=".modal-header .page-actions button[data-role='action']" timeout="30"/> + <element name="associatedProducts" type="block" selector="._show #catalog_product_composite_configure_fields_configurable"/> + <element name="bundleItems" type="block" selector="._show #catalog_product_composite_configure_fields_bundle"/> + <element name="bundleSelect" type="select" selector="//label/span[text()='{{bundleOption}}']/../following-sibling::div/select" parameterized="true"/> + <element name="downloadableInformation" type="block" selector="._show #catalog_product_composite_configure_fields_downloadable"/> + <element name="checkLinkDownloadableProduct" type="checkbox" selector="//label[contains(text(),'{{link}}')]/preceding-sibling::input" parameterized="true"/> </section> </sections> diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormDiscountSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormDiscountSection.xml new file mode 100644 index 0000000000000..e22e3430e9203 --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormDiscountSection.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="AdminOrderFormDiscountSection"> + <element name="fieldCouponCode" type="input" selector="//input[@name='coupon_code']"/> + <element name="applyCouponCode" type="button" selector="//input[@name='coupon_code']/following-sibling::button"/> + </section> +</sections> diff --git a/app/code/Magento/Sales/Test/Mftf/Section/StorefrontGuestOrderViewSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/StorefrontGuestOrderViewSection.xml index 11080761b192c..3085a591a1192 100644 --- a/app/code/Magento/Sales/Test/Mftf/Section/StorefrontGuestOrderViewSection.xml +++ b/app/code/Magento/Sales/Test/Mftf/Section/StorefrontGuestOrderViewSection.xml @@ -10,5 +10,6 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="StorefrontGuestOrderViewSection"> <element name="orderInformationTab" type="text" selector="//*[@class='nav item current']/strong[contains(text(), 'Order Information')]"/> + <element name="printOrder" type="button" selector=".order-actions-toolbar .actions .print" timeout="10"/> </section> </sections> diff --git a/app/code/Magento/Sales/Test/Mftf/Section/StorefrontOrderDetailsSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/StorefrontOrderDetailsSection.xml new file mode 100644 index 0000000000000..4eecebd264765 --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/Section/StorefrontOrderDetailsSection.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="StorefrontOrderDetailsSection"> + <element name="orderDetailsBlock" type="block" selector=".block-order-details-view"/> + <element name="billingAddressBlock" type="block" selector=".box-order-billing-address > .box-content > address"/> + <element name="discountSalesRule" type="text" selector="tr.discount span.price"/> + <element name="grandTotalPrice" type="text" selector="tr.grand_total span.price"/> + <element name="paymentMethod" type="text" selector=".box-order-billing-method dt.title"/> + <element name="shippingMethod" type="text" selector=".box-order-shipping-method div.box-content"/> + <element name="productNameCell" type="text" selector="//*[@class='product name product-item-name']"/> + </section> +</sections> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/StorefrontPrintOrderGuestTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/StorefrontPrintOrderGuestTest.xml new file mode 100644 index 0000000000000..cbe24778558b7 --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/Test/StorefrontPrintOrderGuestTest.xml @@ -0,0 +1,280 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="StorefrontPrintOrderGuestTest"> + <annotations> + <stories value="Print Order"/> + <title value="Print Order from Guest on Frontend"/> + <description value="Print Order from Guest on Frontend"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-16225"/> + <group value="sales"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> + <createData entity="ApiCategory" stepKey="createCategory"/> + + <!-- Create downloadable Product --> + <createData entity="DownloadableProductWithTwoLink1000" stepKey="downloadableProduct"> + <requiredEntity createDataKey="createCategory"/> + <field key="price">280</field> + </createData> + <createData entity="downloadableLink1" stepKey="addDownloadableLink1"> + <requiredEntity createDataKey="downloadableProduct"/> + </createData> + <createData entity="downloadableLink2" stepKey="addDownloadableLink2"> + <requiredEntity createDataKey="downloadableProduct"/> + </createData> + + <!-- Check Links can be purchased separately for Downloadable Product --> + <actionGroup ref="navigateToCreatedProductEditPage" stepKey="goToDownloadableProduct"> + <argument name="product" value="$$downloadableProduct$$"/> + </actionGroup> + <waitForPageLoad stepKey="waitForPageLoad"/> + <scrollTo selector="{{AdminProductDownloadableSection.sectionHeader}}" stepKey="scrollToDownloadableInformation"/> + <checkOption selector="{{AdminProductDownloadableSection.isLinksPurchasedSeparately}}" stepKey="checkOption"/> + <waitForAjaxLoad stepKey="waitForAjaxLoad"/> + <grabValueFrom selector="{{AdminProductDownloadableSection.addLinkTitleInput('0')}}" stepKey="grabLink"/> + <click selector="{{AdminProductFormSection.save}}" stepKey="clickSave"/> + <waitForLoadingMaskToDisappear stepKey="waitForSave"/> + <waitForPageLoad stepKey="waitForPage"/> + + <!-- Create configurable Product --> + <createData entity="ApiConfigurableProduct" stepKey="createConfigProduct"> + <requiredEntity createDataKey="createCategory"/> + </createData> + <createData entity="productAttributeWithTwoOptions" stepKey="createConfigProductAttribute"/> + <createData entity="productAttributeOption1" stepKey="createConfigProductAttributeOption1"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + </createData> + <createData entity="productAttributeOption2" stepKey="createConfigProductAttributeOption2"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + </createData> + <createData entity="productAttributeOption3" stepKey="createConfigProductAttributeOption3"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + </createData> + <createData entity="AddToDefaultSet" stepKey="createConfigAddToAttributeSet"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + </createData> + <getData entity="ProductAttributeOptionGetter" index="1" stepKey="getConfigAttributeOption1"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + </getData> + <getData entity="ProductAttributeOptionGetter" index="2" stepKey="getConfigAttributeOption2"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + </getData> + <getData entity="ProductAttributeOptionGetter" index="3" stepKey="getConfigAttributeOption3"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + </getData> + <createData entity="ApiSimpleOne" stepKey="createConfigChildProduct1"> + <field key="price">40</field> + <requiredEntity createDataKey="createConfigProductAttribute"/> + <requiredEntity createDataKey="getConfigAttributeOption1"/> + </createData> + <createData entity="ApiSimpleTwo" stepKey="createConfigChildProduct2"> + <field key="price">40</field> + <requiredEntity createDataKey="createConfigProductAttribute"/> + <requiredEntity createDataKey="getConfigAttributeOption2"/> + </createData> + <createData entity="ApiSimpleTwo" stepKey="createConfigChildProduct3"> + <field key="price">40</field> + <requiredEntity createDataKey="createConfigProductAttribute"/> + <requiredEntity createDataKey="getConfigAttributeOption3"/> + </createData> + + <createData entity="ConfigurableProductThreeOptions" stepKey="createConfigProductOption"> + <requiredEntity createDataKey="createConfigProduct"/> + <requiredEntity createDataKey="createConfigProductAttribute"/> + <requiredEntity createDataKey="getConfigAttributeOption1"/> + <requiredEntity createDataKey="getConfigAttributeOption2"/> + <requiredEntity createDataKey="getConfigAttributeOption3"/> + </createData> + + <createData entity="ConfigurableProductAddChild" stepKey="createConfigProductAddChild1"> + <requiredEntity createDataKey="createConfigProduct"/> + <requiredEntity createDataKey="createConfigChildProduct1"/> + </createData> + <createData entity="ConfigurableProductAddChild" stepKey="createConfigProductAddChild2"> + <requiredEntity createDataKey="createConfigProduct"/> + <requiredEntity createDataKey="createConfigChildProduct2"/> + </createData> + + <createData entity="ConfigurableProductAddChild" stepKey="createConfigProductAddChild3"> + <requiredEntity createDataKey="createConfigProduct"/> + <requiredEntity createDataKey="createConfigChildProduct3"/> + </createData> + + <!-- Grab attribute name for Configurable Product --> + <actionGroup ref="navigateToCreatedProductEditPage" stepKey="goToConfigurableProduct"> + <argument name="product" value="$$createConfigProduct$$"/> + </actionGroup> + <grabTextFrom selector="{{AdminConfigurableProductFormSection.currentAttribute}}" stepKey="grabAttribute"/> + <assertNotEmpty actual="$grabAttribute" stepKey="assertNotEmpty"/> + + <!-- Create bundle Product --> + <createData entity="SimpleSubCategory" stepKey="createSubCategory"/> + <createData entity="SimpleProduct2" stepKey="simpleProduct1"> + <field key="price">100.00</field> + </createData> + <createData entity="SimpleProduct2" stepKey="simpleProduct2"> + <field key="price">560.00</field> + </createData> + <createData entity="BundleProductPriceViewRange" stepKey="createBundleProduct"> + <requiredEntity createDataKey="createSubCategory"/> + </createData> + <createData entity="DropDownBundleOption" stepKey="createBundleOption1_1"> + <requiredEntity createDataKey="createBundleProduct"/> + <field key="required">True</field> + </createData> + <createData entity="ApiBundleLink" stepKey="linkOptionToProduct"> + <requiredEntity createDataKey="createBundleProduct"/> + <requiredEntity createDataKey="createBundleOption1_1"/> + <requiredEntity createDataKey="simpleProduct1"/> + </createData> + <createData entity="ApiBundleLink" stepKey="linkOptionToProduct2"> + <requiredEntity createDataKey="createBundleProduct"/> + <requiredEntity createDataKey="createBundleOption1_1"/> + <requiredEntity createDataKey="simpleProduct2"/> + </createData> + + <!-- Grab bundle option name for Bundle Product --> + <actionGroup ref="navigateToCreatedProductEditPage" stepKey="goToBundleProduct"> + <argument name="product" value="$$createBundleProduct$$"/> + </actionGroup> + <grabTextFrom selector="{{AdminProductFormBundleSection.currentBundleOption}}" stepKey="grabBundleOption"/> + <assertNotEmpty actual="$grabBundleOption" stepKey="assertBundleOptionNotEmpty"/> + + <!-- Create sales rule --> + <createData entity="ActiveSalesRuleCoupon50" stepKey="createCartPriceRule"/> + <createData entity="SimpleSalesRuleCoupon" stepKey="createCouponForCartPriceRule"> + <requiredEntity createDataKey="createCartPriceRule"/> + </createData> + + <!-- Create Customer Account --> + <createData entity="Simple_US_Customer" stepKey="createCustomer"/> + + <magentoCLI command="indexer:reindex" stepKey="reindex"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> + + <!-- Place order with options according to dataset --> + <actionGroup ref="navigateToNewOrderPageExistingCustomer" stepKey="newOrder"> + <argument name="customer" value="$$createCustomer$$"/> + </actionGroup> + + <actionGroup ref="AdminFilterProductInCreateOrderActionGroup" stepKey="filterConfigProduct"> + <argument name="productSKU" value="$$createConfigProduct.sku$$"/> + </actionGroup> + + <actionGroup ref="AdminAddToOrderConfigurableProductActionGroup" stepKey="addConfProduct"> + <argument name="attribute" value="{$grabAttribute}"/> + <argument name="option" value="$$getConfigAttributeOption1.label$$"/> + <argument name="quantity" value="3"/> + </actionGroup> + + <actionGroup ref="AdminFilterProductInCreateOrderActionGroup" stepKey="filterBundleProduct"> + <argument name="productSKU" value="$$createBundleProduct.sku$$"/> + </actionGroup> + <actionGroup ref="AdminAddToOrderBundleProductActionGroup" stepKey="addBundleProduct"> + <argument name="option" value="{$grabBundleOption}"/> + <argument name="selectedProduct" value="$$simpleProduct1$$"/> + <argument name="quantity" value="2"/> + </actionGroup> + + <actionGroup ref="AdminFilterProductInCreateOrderActionGroup" stepKey="filterDownloadableProduct"> + <argument name="productSKU" value="$$downloadableProduct.sku$$"/> + </actionGroup> + <actionGroup ref="AdminAddToOrderDownloadableProductActionGroup" stepKey="addDownloadableProduct"> + <argument name="link" value="{$grabLink}"/> + <argument name="quantity" value="1"/> + </actionGroup> + + <!-- add Coupon --> + <actionGroup ref="AdminAddToOrderCouponCodeActionGroup" stepKey="addCoupon"> + <argument name="coupon" value="$$createCouponForCartPriceRule$$"/> + </actionGroup> + + <actionGroup ref="fillOrderCustomerInformation" stepKey="fillOrder"> + <argument name="customer" value="$$createCustomer$$"/> + <argument name="address" value="US_Address_TX"/> + </actionGroup> + + <actionGroup ref="orderSelectFlatRateShipping" stepKey="selectFlatRate"/> + </before> + <after> + <deleteData createDataKey="downloadableProduct" stepKey="deleteProduct"/> + + <deleteData createDataKey="createConfigChildProduct1" stepKey="deleteConfigChildProduct1"/> + <deleteData createDataKey="createConfigChildProduct2" stepKey="deleteConfigChildProduct2"/> + <deleteData createDataKey="createConfigChildProduct3" stepKey="deleteConfigChildProduct3"/> + <deleteData createDataKey="createConfigProduct" stepKey="deleteConfigProduct"/> + <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> + <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + + <deleteData createDataKey="simpleProduct1" stepKey="deleteProduct1"/> + <deleteData createDataKey="simpleProduct2" stepKey="deleteProduct2"/> + <deleteData createDataKey="createBundleProduct" stepKey="deleteBundleProduct"/> + <deleteData createDataKey="createSubCategory" stepKey="deleteCategory1"/> + + <deleteData createDataKey="createCartPriceRule" stepKey="deleteCartPriceRule"/> + <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <actionGroup ref="AdminSubmitOrderActionGroup" stepKey="submitOrder"/> + + <grabTextFrom selector="|Order # (\d+)|" stepKey="getOrderId"/> + <assertNotEmpty actual="$getOrderId" stepKey="assertOrderIdIsNotEmpty" /> + + <!-- Find the Order on frontend > Navigate to: Orders and Returns --> + <amOnPage url="{{StorefrontGuestOrderSearchPage.url}}" stepKey="amOnOrdersAndReturns"/> + <waitForPageLoad stepKey="waiForStorefrontPage"/> + + <!-- Fill the form with correspondent Order data --> + <actionGroup ref="StorefrontFillOrdersAndReturnsFormActionGroup" stepKey="fillOrder"> + <argument name="orderNumber" value="{$getOrderId}"/> + <argument name="customer" value="$$createCustomer$$"/> + </actionGroup> + + <!-- Click on the "Continue" button --> + <click selector="{{StorefrontGuestOrderSearchSection.continue}}" stepKey="clickContinue"/> + <waitForPageLoad stepKey="waitForPageLoad"/> + <waitForLoadingMaskToDisappear stepKey="waitForOrderPage"/> + + <!-- Click on the "Print Order" button --> + <click selector="{{StorefrontGuestOrderViewSection.printOrder}}" stepKey="printOrder"/> + <switchToWindow stepKey="switchToWindow"/> + <switchToNextTab stepKey="switchToTab"/> + <seeInCurrentUrl url="sales/guest/print/order_id/" stepKey="seePrintPage"/> + + <!-- AssertSalesPrintOrderProducts --> + <see userInput="$$createBundleProduct.name$$" selector="{{StorefrontOrderDetailsSection.productNameCell}}" stepKey="seeBundleProduct"/> + <see userInput="$$downloadableProduct.name$$" selector="{{StorefrontOrderDetailsSection.productNameCell}}" stepKey="seeDownloadableProduct"/> + <see userInput="$$createConfigProduct.name$$" selector="{{StorefrontOrderDetailsSection.productNameCell}}" stepKey="seeConfigurableProduct"/> + + <!-- AssertSalesPrintOrderBillingAddress --> + <scrollTo selector="{{StorefrontOrderDetailsSection.orderDetailsBlock}}" stepKey="scrollToFooter"/> + <actionGroup ref="AssertSalesPrintOrderBillingAddress" stepKey="assertSalesPrintOrderBillingAddress"> + <argument name="address" value="US_Address_TX"/> + </actionGroup> + + <!-- AssertSalesPrintOrderGrandTotal --> + <see userInput="$357.43" selector="{{StorefrontOrderDetailsSection.grandTotalPrice}}" stepKey="assertSalesPrintOrderGrandTotal"/> + + <!-- AssertSalesPrintOrderPaymentMethod --> + <see userInput="Check / Money order" selector="{{StorefrontOrderDetailsSection.paymentMethod}}" stepKey="assertSalesPrintOrderPaymentMethod"/> + + <!-- AssertSalesRuleOnPrintOrder --> + <see userInput="-$270.00" selector="{{StorefrontOrderDetailsSection.discountSalesRule}}" stepKey="assertSalesRuleOnPrintOrder"/> + + <!-- AssertShippingMethodOnPrintOrder --> + <see userInput="Flat Rate - Fixed" selector="{{StorefrontOrderDetailsSection.shippingMethod}}" stepKey="assertShippingMethodOnPrintOrder"/> + <switchToPreviousTab stepKey="switchToPreviousTab"/> + </test> +</tests> \ No newline at end of file diff --git a/app/code/Magento/SalesRule/Test/Mftf/Data/SalesRuleData.xml b/app/code/Magento/SalesRule/Test/Mftf/Data/SalesRuleData.xml index f022e4e645c3c..931a6adc243a8 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Data/SalesRuleData.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Data/SalesRuleData.xml @@ -399,5 +399,34 @@ <data key="apply">Percent of product price discount</data> <data key="discountAmount">50</data> </entity> + <entity name="ActiveSalesRuleCoupon50" type="SalesRule"> + <data key="name" unique="suffix">SimpleSalesRule</data> + <data key="description">Sales Rule Description</data> + <array key="website_ids"> + <item>1</item> + </array> + <array key="customer_group_ids"> + <item>0</item> + <item>1</item> + </array> + <data key="uses_per_customer">10</data> + <data key="is_active">true</data> + <data key="stop_rules_processing">true</data> + <data key="is_advanced">true</data> + <data key="sort_order">0</data> + <data key="simple_action">by_fixed</data> + <data key="discount_amount">50</data> + <data key="discount_qty">0</data> + <data key="discount_step">0</data> + <data key="apply_to_shipping">false</data> + <data key="times_used">0</data> + <data key="is_rss">false</data> + <data key="coupon_type">SPECIFIC_COUPON</data> + <data key="use_auto_generation">false</data> + <data key="uses_per_coupon">0</data> + <data key="simple_free_shipping">0</data> + <requiredEntity type="SalesRuleLabel">SalesRuleLabelDefault</requiredEntity> + <requiredEntity type="SalesRuleLabel">SalesRuleLabelStore1</requiredEntity> + </entity> </entities> diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/PrintOrderFrontendGuestTest.xml b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/PrintOrderFrontendGuestTest.xml index dabacdb73c2b9..da24a1b7075a4 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/PrintOrderFrontendGuestTest.xml +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/PrintOrderFrontendGuestTest.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\Sales\Test\TestCase\PrintOrderFrontendGuestTest" summary="Print Order from Guest on Frontend" ticketId="MAGETWO-30253"> <variation name="PrintOrderFrontendGuestTestVariation1"> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <data name="customer" xsi:type="array"> <item name="dataset" xsi:type="string">johndoe_with_addresses</item> </data> From ff4ca4070849823c58e045a3ee26773934121634 Mon Sep 17 00:00:00 2001 From: Mila Lesechko <llesechk@adobe.com> Date: Thu, 9 May 2019 10:54:10 -0500 Subject: [PATCH 368/773] MC-4332: Convert CreateWidgetOrderBySkuTest to MFTF --- .../Magento/Widget/Test/Mftf/Section/AdminWidgetsSection.xml | 1 + .../Widget/Test/Mftf/Section/StorefrontWidgetsSection.xml | 2 ++ 2 files changed, 3 insertions(+) diff --git a/app/code/Magento/Widget/Test/Mftf/Section/AdminWidgetsSection.xml b/app/code/Magento/Widget/Test/Mftf/Section/AdminWidgetsSection.xml index f3282362d9aa1..162f4e9c41064 100644 --- a/app/code/Magento/Widget/Test/Mftf/Section/AdminWidgetsSection.xml +++ b/app/code/Magento/Widget/Test/Mftf/Section/AdminWidgetsSection.xml @@ -12,5 +12,6 @@ <element name="widgetTitleSearch" type="input" selector="#widgetInstanceGrid_filter_title"/> <element name="searchButton" type="button" selector=".action-default.scalable.action-secondary"/> <element name="searchResult" type="text" selector="#widgetInstanceGrid_table>tbody>tr:nth-child(1)"/> + <element name="resetFilter" type="button" selector="button[data-action='grid-filter-reset']"/> </section> </sections> diff --git a/app/code/Magento/Widget/Test/Mftf/Section/StorefrontWidgetsSection.xml b/app/code/Magento/Widget/Test/Mftf/Section/StorefrontWidgetsSection.xml index 0e2f6cec73a92..a42bd5b52d534 100644 --- a/app/code/Magento/Widget/Test/Mftf/Section/StorefrontWidgetsSection.xml +++ b/app/code/Magento/Widget/Test/Mftf/Section/StorefrontWidgetsSection.xml @@ -11,5 +11,7 @@ <section name="StorefrontWidgetsSection"> <element name="widgetProductsGrid" type="block" selector=".block.widget.block-products-list.grid"/> <element name="widgetProductName" type="text" selector=".product-item-name"/> + <element name="widgetBlock" type="block" selector=".widget"/> + <element name="widgetTitle" type="text" selector=".block-title"/> </section> </sections> From 6d091ed46d5474b8eec63460d59037b78be366ee Mon Sep 17 00:00:00 2001 From: Serhii Voloshkov <serhii.voloshkov@transoftgroup.com> Date: Fri, 10 May 2019 09:55:05 +0300 Subject: [PATCH 369/773] MC-16288: Comments history for order can not show euro symbol correctly --- app/code/Magento/Sales/Helper/Admin.php | 1 + .../testsuite/Magento/Sales/Helper/AdminTest.php | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/app/code/Magento/Sales/Helper/Admin.php b/app/code/Magento/Sales/Helper/Admin.php index f04584ea19c37..0e0d8213cb791 100644 --- a/app/code/Magento/Sales/Helper/Admin.php +++ b/app/code/Magento/Sales/Helper/Admin.php @@ -166,6 +166,7 @@ public function escapeHtmlWithLinks($data, $allowedTags = null) $internalErrors = libxml_use_internal_errors(true); + $data = mb_convert_encoding($data, 'HTML-ENTITIES', 'UTF-8'); $domDocument->loadHTML( '<html><body id="' . $wrapperElementId . '">' . $data . '</body></html>' ); diff --git a/dev/tests/integration/testsuite/Magento/Sales/Helper/AdminTest.php b/dev/tests/integration/testsuite/Magento/Sales/Helper/AdminTest.php index 5d598fa90678b..a1f64559e9e82 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/Helper/AdminTest.php +++ b/dev/tests/integration/testsuite/Magento/Sales/Helper/AdminTest.php @@ -52,6 +52,13 @@ public function escapeHtmlWithLinksDataProvider(): array '<a>some text in tags</a>', 'allowedTags' => null, ], + [ + // @codingStandardsIgnoreStart + 'Authorized amount of €30.00. Transaction ID: "<a target="_blank" href="https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_view-a-trans&id=123456789QWERTY">123456789QWERTY</a>"', + 'Authorized amount of €30.00. Transaction ID: "<a href="https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_view-a-trans&id=123456789QWERTY">123456789QWERTY</a>"', + // @codingStandardsIgnoreEnd + 'allowedTags' => ['b', 'br', 'strong', 'i', 'u', 'a'], + ], [ 'Transaction ID: "<a target="_blank" href="https://www.paypal.com/?id=XX123XX">XX123XX</a>"', 'Transaction ID: "<a href="https://www.paypal.com/?id=XX123XX">XX123XX</a>"', From 3e19c909acccc6a2b1c2e0652c2f99b2889bc272 Mon Sep 17 00:00:00 2001 From: Stas Kozar <stas.kozar@transoftgroup.com> Date: Fri, 10 May 2019 10:24:36 +0300 Subject: [PATCH 370/773] MC-15448: One can't download or delete export csv file from export index page grid --- .../Controller/Adminhtml/Export.php | 5 ----- .../Adminhtml/Export/File/Delete.php | 5 +++++ .../Adminhtml/Export/File/Download.php | 5 +++++ .../Adminhtml/Export/File/DeleteTest.php | 20 +++++++++---------- 4 files changed, 20 insertions(+), 15 deletions(-) diff --git a/app/code/Magento/ImportExport/Controller/Adminhtml/Export.php b/app/code/Magento/ImportExport/Controller/Adminhtml/Export.php index 28ca475edd4cc..71ed437426226 100644 --- a/app/code/Magento/ImportExport/Controller/Adminhtml/Export.php +++ b/app/code/Magento/ImportExport/Controller/Adminhtml/Export.php @@ -18,9 +18,4 @@ abstract class Export extends Action * @see _isAllowed() */ const ADMIN_RESOURCE = 'Magento_ImportExport::export'; - - /** - * @inheritdoc - */ - protected $_publicActions = ['download', 'delete']; } diff --git a/app/code/Magento/ImportExport/Controller/Adminhtml/Export/File/Delete.php b/app/code/Magento/ImportExport/Controller/Adminhtml/Export/File/Delete.php index 6996ba90c3e10..c7eb99acad25c 100644 --- a/app/code/Magento/ImportExport/Controller/Adminhtml/Export/File/Delete.php +++ b/app/code/Magento/ImportExport/Controller/Adminhtml/Export/File/Delete.php @@ -37,6 +37,11 @@ class Delete extends ExportController implements HttpGetActionInterface */ private $file; + /** + * @inheritdoc + */ + protected $_publicActions = ['delete']; + /** * Delete constructor. * @param Action\Context $context diff --git a/app/code/Magento/ImportExport/Controller/Adminhtml/Export/File/Download.php b/app/code/Magento/ImportExport/Controller/Adminhtml/Export/File/Download.php index 32385e62a5dce..e456c8b71347b 100644 --- a/app/code/Magento/ImportExport/Controller/Adminhtml/Export/File/Download.php +++ b/app/code/Magento/ImportExport/Controller/Adminhtml/Export/File/Download.php @@ -35,6 +35,11 @@ class Download extends ExportController implements HttpGetActionInterface */ private $filesystem; + /** + * @inheritdoc + */ + protected $_publicActions = ['download']; + /** * DownloadFile constructor. * @param Action\Context $context diff --git a/dev/tests/integration/testsuite/Magento/ImportExport/Controller/Adminhtml/Export/File/DeleteTest.php b/dev/tests/integration/testsuite/Magento/ImportExport/Controller/Adminhtml/Export/File/DeleteTest.php index 661f8affe6f8e..ed19cf9b3515e 100644 --- a/dev/tests/integration/testsuite/Magento/ImportExport/Controller/Adminhtml/Export/File/DeleteTest.php +++ b/dev/tests/integration/testsuite/Magento/ImportExport/Controller/Adminhtml/Export/File/DeleteTest.php @@ -8,6 +8,9 @@ namespace Magento\ImportExport\Controller\Adminhtml\Export\File; use Magento\Framework\App\Filesystem\DirectoryList; +use Magento\Framework\Filesystem; +use Magento\ImportExport\Controller\Adminhtml\Export\File\Delete; +use Magento\TestFramework\Helper\Bootstrap; /** * Test for \Magento\ImportExport\Controller\Adminhtml\Export\File\Delete class. @@ -15,7 +18,7 @@ class DeleteTest extends \PHPUnit\Framework\TestCase { /** - * @var \Magento\ImportExport\Controller\Adminhtml\Export\File\Delete + * @var Delete */ private $model; @@ -35,7 +38,7 @@ class DeleteTest extends \PHPUnit\Framework\TestCase private $fileName = 'catalog_product.csv'; /** - * @var \Magento\Framework\Filesystem + * @var Filesystem */ private $filesystem; @@ -49,15 +52,15 @@ class DeleteTest extends \PHPUnit\Framework\TestCase */ protected function setUp() { - $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); - $this->filesystem = $this->objectManager->get(\Magento\Framework\Filesystem::class); + $this->objectManager = Bootstrap::getObjectManager(); + $this->filesystem = $this->objectManager->get(Filesystem::class); $this->varDirectory = $this->filesystem->getDirectoryWrite(DirectoryList::VAR_DIR); $this->varDirectory->create($this->varDirectory->getRelativePath('export')); $this->fullDirectoryPath = $this->varDirectory->getAbsolutePath('export'); $filePath = $this->fullDirectoryPath . DIRECTORY_SEPARATOR . $this->fileName; $fixtureDir = realpath(__DIR__ . '/../../Import/_files'); copy($fixtureDir . '/' . $this->fileName, $filePath); - $this->model = $this->objectManager->get(\Magento\ImportExport\Controller\Adminhtml\Export\File\Delete::class); + $this->model = $this->objectManager->get(Delete::class); } /** @@ -71,9 +74,7 @@ public function testExecute() $this->model->execute(); $this->assertFalse( - $this->varDirectory->isExist( - $this->varDirectory->getRelativePath( 'export/' . $this->fileName) - ) + $this->varDirectory->isExist($this->varDirectory->getRelativePath('export/' . $this->fileName)) ); } @@ -82,8 +83,7 @@ public function testExecute() */ public static function tearDownAfterClass() { - $filesystem = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() - ->get(\Magento\Framework\Filesystem::class); + $filesystem = Bootstrap::getObjectManager()->get(Filesystem::class); /** @var \Magento\Framework\Filesystem\Directory\WriteInterface $directory */ $directory = $filesystem->getDirectoryWrite(DirectoryList::VAR_DIR); if ($directory->isExist('export')) { From 8b0d3d20f2ca9ffa090557b4c6f514c49ddf442e Mon Sep 17 00:00:00 2001 From: DianaRusin <rusind95@gmail.com> Date: Fri, 10 May 2019 10:42:44 +0300 Subject: [PATCH 371/773] MAGETWO-99590: [Auth.net Accept.js] Order is placed only from second time in Admin with Auth.net payment method --- .../view/adminhtml/templates/payment/script.phtml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/AuthorizenetAcceptjs/view/adminhtml/templates/payment/script.phtml b/app/code/Magento/AuthorizenetAcceptjs/view/adminhtml/templates/payment/script.phtml index 95d41f034836a..2989f99c0462d 100644 --- a/app/code/Magento/AuthorizenetAcceptjs/view/adminhtml/templates/payment/script.phtml +++ b/app/code/Magento/AuthorizenetAcceptjs/view/adminhtml/templates/payment/script.phtml @@ -9,9 +9,8 @@ <script> //<![CDATA[ require( - [ - 'Magento_AuthorizenetAcceptjs/js/payment-form' - ], function(Authorizenet) { + ['Magento_AuthorizenetAcceptjs/js/payment-form'], + function(Authorizenet) { var config = <?= /* @noEscape */ $block->getPaymentConfig() ?>, form = "#payment_form_<?= $block->escapeJs($block->escapeHtml($block->getMethodCode())) ?>"; From 7174745ab7e2443349a644f64261b388b41935b7 Mon Sep 17 00:00:00 2001 From: Shikha Mishra <shikhamishra@cedcoss.com> Date: Fri, 10 May 2019 17:46:46 +0530 Subject: [PATCH 372/773] Updated requested changes --- .../Observer/SaveDownloadableOrderItemObserver.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Downloadable/Observer/SaveDownloadableOrderItemObserver.php b/app/code/Magento/Downloadable/Observer/SaveDownloadableOrderItemObserver.php index f4eeab6d32061..52e14dcd18085 100644 --- a/app/code/Magento/Downloadable/Observer/SaveDownloadableOrderItemObserver.php +++ b/app/code/Magento/Downloadable/Observer/SaveDownloadableOrderItemObserver.php @@ -133,9 +133,10 @@ public function execute(\Magento\Framework\Event\Observer $observer) $linkPurchased->setLinkSectionTitle($linkSectionTitle)->save(); $linkstatus = \Magento\Downloadable\Model\Link\Purchased\Item::LINK_STATUS_PENDING; - if( $orderStatusToEnableItem == \Magento\Sales\Model\Order\Item::STATUS_PENDING - || $orderItem->getOrder()->getStatus() == \Magento\Sales\Model\Order::STATE_COMPLETE){ - $linkstatus = \Magento\Downloadable\Model\Link\Purchased\Item::LINK_STATUS_AVAILABLE; + if ($orderStatusToEnableItem == \Magento\Sales\Model\Order\Item::STATUS_PENDING + || $orderItem->getOrder()->getState() == \Magento\Sales\Model\Order::STATE_COMPLETE + ) { + $linkStatus = \Magento\Downloadable\Model\Link\Purchased\Item::LINK_STATUS_AVAILABLE; } foreach ($linkIds as $linkId) { @@ -165,7 +166,7 @@ public function execute(\Magento\Framework\Event\Observer $observer) )->setNumberOfDownloadsBought( $numberOfDownloads )->setStatus( - $linkstatus + $linkStatus )->setCreatedAt( $orderItem->getCreatedAt() )->setUpdatedAt( From fa3d987909cf57773e780a782a9b2d8ec67d45cf Mon Sep 17 00:00:00 2001 From: Maria Kovdrysh <kovdrysh@adobe.com> Date: Fri, 10 May 2019 08:20:38 -0500 Subject: [PATCH 373/773] MC-4555: Convert UpdateCustomerCustomAttributesEntityTest to MFTF --- .../Test/Mftf/Section/StorefrontCustomerCreateFormSection.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerCreateFormSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerCreateFormSection.xml index 8881a2a012ce8..ba1f10a480745 100644 --- a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerCreateFormSection.xml +++ b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerCreateFormSection.xml @@ -30,5 +30,6 @@ <element name="yesNoAttribute" type="select" selector="//select[@id='{{var}}']" parameterized="true" /> <element name="yesNoOptionAttribute" type="select" selector="//select[@id='{{var}}']/option[2]" parameterized="true" /> <element name="selectedOption" type="text" selector="//select[@id='{{var}}']/option[@selected='selected']" parameterized="true"/> + <element name="attributeLabel" type="text" selector="//span[text()='{{attributeLabel}}']" parameterized="true"/> </section> </sections> From 60ea7291b3e605783626edc3b5594f26c824d175 Mon Sep 17 00:00:00 2001 From: OlgaVasyltsun <olga.vasyltsun@gmail.com> Date: Fri, 10 May 2019 16:47:44 +0300 Subject: [PATCH 374/773] MAGETWO-99623: Quick static content deployis broken --- app/code/Magento/Deploy/Process/Queue.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Deploy/Process/Queue.php b/app/code/Magento/Deploy/Process/Queue.php index fd7aad44e0a5b..d7bb816e61c88 100644 --- a/app/code/Magento/Deploy/Process/Queue.php +++ b/app/code/Magento/Deploy/Process/Queue.php @@ -339,7 +339,7 @@ private function isDeployed(Package $package) if ($this->isCanBeParalleled()) { if ($package->getState() === null) { // phpcs:ignore Magento2.Functions.DiscouragedFunction - $pid = pcntl_waitpid($this->getPid($package), $status, WNOHANG); + $pid = pcntl_waitpid($this->getPid($package) ?? 0, $status, WNOHANG); if ($pid === $this->getPid($package)) { $package->setState(Package::STATE_COMPLETED); @@ -361,7 +361,7 @@ private function isDeployed(Package $package) */ private function getPid(Package $package) { - return isset($this->processIds[$package->getPath()]) ?? null; + return $this->processIds[$package->getPath()] ?? null; } /** From 98f1b6f594aec0a8566c6c2ae195b92b43dc2a14 Mon Sep 17 00:00:00 2001 From: Kavitha <kanair@adobe.com> Date: Fri, 10 May 2019 12:00:10 -0500 Subject: [PATCH 375/773] MC-4554: Convert CreateCustomerCustomAttributesEntityTest to MFTF --- .../Test/Mftf/Section/AdminCustomerAccountInformationSection.xml | 1 + .../Test/Mftf/Section/AdminOrderDetailsInformationSection.xml | 1 + 2 files changed, 2 insertions(+) diff --git a/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerAccountInformationSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerAccountInformationSection.xml index 06d4fef36585d..6d6a6dca2221e 100644 --- a/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerAccountInformationSection.xml +++ b/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerAccountInformationSection.xml @@ -33,5 +33,6 @@ <element name="emailRequiredMessage" type="text" selector="//input[@name='customer[email]']/../label[contains(.,'This is a required field.')]"/> <element name="customAttribute" type="select" selector="//select[contains(@name, 'customer[{{attribute_code}}]')]" parameterized="true"/> <element name="disabledGroup" type="text" selector="//div[@class='admin__action-group-wrap admin__action-multiselect-wrap action-select-wrap _disabled']"/> + <element name="customerAttribute" type="input" selector="//input[contains(@name,'{{attributeCode}}')]" parameterized="true"/> </section> </sections> diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderDetailsInformationSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderDetailsInformationSection.xml index 4d37479a8cd18..a74f26c9bbfe0 100644 --- a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderDetailsInformationSection.xml +++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderDetailsInformationSection.xml @@ -19,6 +19,7 @@ <element name="billingAddress" type="text" selector=".order-billing-address"/> <element name="shippingAddress" type="text" selector=".order-shipping-address"/> <element name="itemsOrdered" type="text" selector=".edit-order-table"/> + <element name="attributeLabel" type="text" selector="//label[contains(.,'{{attributeLabel}}')]" parameterized="true"/> <element name="paymentInformation" type="text" selector="//div[@class='order-payment-method-title']"/> </section> </sections> \ No newline at end of file From 462bd56fd17644ad0522fe137112353537d8bc6d Mon Sep 17 00:00:00 2001 From: Maria Kovdrysh <kovdrysh@adobe.com> Date: Fri, 10 May 2019 13:42:39 -0500 Subject: [PATCH 376/773] MC-4331: Convert DeleteProductsFromCartOfAdvancedCheckoutEntityTest to MFTF --- .../Checkout/Test/Mftf/Section/CheckoutCartProductSection.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartProductSection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartProductSection.xml index 977f559f0071e..a85920998b39c 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartProductSection.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartProductSection.xml @@ -46,5 +46,8 @@ <element name="checkoutCartProductPrice" type="text" selector="//td[@class='col price']//span[@class='price']"/> <element name="checkoutCartSubtotal" type="text" selector="//td[@class='col subtotal']//span[@class='price']"/> <element name="emptyCart" selector=".cart-empty" type="text"/> + <!-- Required attention section --> + <element name="removeProductBySku" type="button" selector="//*[contains(text(), '{{sku}}')]/ancestor::tbody//button" parameterized="true" timeout="30"/> + <element name="failedItemBySku" type="block" selector="//*[@class='cart item' and .//tr[contains(@class,'info') and .//div[contains(.,'{{sku}}')]]]" parameterized="true" timeout="30"/> </section> </sections> From 630bbb5276780e97a67d747d0ab58ee790d5b015 Mon Sep 17 00:00:00 2001 From: Shikha Mishra <shikhamishra@cedcoss.com> Date: Sat, 11 May 2019 11:40:32 +0530 Subject: [PATCH 377/773] Updated variable name --- .../Downloadable/Observer/SaveDownloadableOrderItemObserver.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Downloadable/Observer/SaveDownloadableOrderItemObserver.php b/app/code/Magento/Downloadable/Observer/SaveDownloadableOrderItemObserver.php index 52e14dcd18085..fed153bdfbbc2 100644 --- a/app/code/Magento/Downloadable/Observer/SaveDownloadableOrderItemObserver.php +++ b/app/code/Magento/Downloadable/Observer/SaveDownloadableOrderItemObserver.php @@ -132,7 +132,7 @@ public function execute(\Magento\Framework\Event\Observer $observer) ); $linkPurchased->setLinkSectionTitle($linkSectionTitle)->save(); - $linkstatus = \Magento\Downloadable\Model\Link\Purchased\Item::LINK_STATUS_PENDING; + $linkStatus = \Magento\Downloadable\Model\Link\Purchased\Item::LINK_STATUS_PENDING; if ($orderStatusToEnableItem == \Magento\Sales\Model\Order\Item::STATUS_PENDING || $orderItem->getOrder()->getState() == \Magento\Sales\Model\Order::STATE_COMPLETE ) { From c727a3230a2aec9973dfc6a14054b01fcbf90d73 Mon Sep 17 00:00:00 2001 From: Leandry <leandry@atwix.com> Date: Mon, 13 May 2019 00:18:02 +0300 Subject: [PATCH 378/773] Refactoring --- .../Mftf/Section/AdminLoginFormSection.xml | 1 - ...l => AdminUserLockWhenEditingUserTest.xml} | 76 +++++++++++++------ .../AdminOpenUserEditPageActionGroup.xml | 24 ++++++ .../AdminUserEditAssignRoleActionGroup.xml | 19 +++++ ...UserEditFillRequiredFieldsActionGroup.xml} | 25 +----- .../AdminUserEditSaveUserActionGroup.xml | 17 +++++ .../LockAdminUserWhenEditingUserTest.xml | 3 +- 7 files changed, 117 insertions(+), 48 deletions(-) rename app/code/Magento/Security/Test/Mftf/Test/{LockAdminUserWhenEditingUserTest.xml => AdminUserLockWhenEditingUserTest.xml} (57%) create mode 100644 app/code/Magento/User/Test/Mftf/ActionGroup/AdminOpenUserEditPageActionGroup.xml create mode 100644 app/code/Magento/User/Test/Mftf/ActionGroup/AdminUserEditAssignRoleActionGroup.xml rename app/code/Magento/User/Test/Mftf/ActionGroup/{AdminEditUserActionGroup.xml => AdminUserEditFillRequiredFieldsActionGroup.xml} (55%) create mode 100644 app/code/Magento/User/Test/Mftf/ActionGroup/AdminUserEditSaveUserActionGroup.xml diff --git a/app/code/Magento/Backend/Test/Mftf/Section/AdminLoginFormSection.xml b/app/code/Magento/Backend/Test/Mftf/Section/AdminLoginFormSection.xml index 2c458e7197ca2..bd65dea89abc2 100644 --- a/app/code/Magento/Backend/Test/Mftf/Section/AdminLoginFormSection.xml +++ b/app/code/Magento/Backend/Test/Mftf/Section/AdminLoginFormSection.xml @@ -12,7 +12,6 @@ <element name="username" type="input" selector="#username"/> <element name="password" type="input" selector="#login"/> <element name="signIn" type="button" selector=".actions .action-primary" timeout="30"/> - <element name="error" type="text" selector=".message.message-error.error"/> <element name="forgotPasswordLink" type="button" selector=".action-forgotpassword" timeout="10"/> </section> </sections> diff --git a/app/code/Magento/Security/Test/Mftf/Test/LockAdminUserWhenEditingUserTest.xml b/app/code/Magento/Security/Test/Mftf/Test/AdminUserLockWhenEditingUserTest.xml similarity index 57% rename from app/code/Magento/Security/Test/Mftf/Test/LockAdminUserWhenEditingUserTest.xml rename to app/code/Magento/Security/Test/Mftf/Test/AdminUserLockWhenEditingUserTest.xml index a7952cdb6e88d..de1ed793c0bc8 100644 --- a/app/code/Magento/Security/Test/Mftf/Test/LockAdminUserWhenEditingUserTest.xml +++ b/app/code/Magento/Security/Test/Mftf/Test/AdminUserLockWhenEditingUserTest.xml @@ -8,7 +8,7 @@ <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> - <test name="LockAdminUserWhenEditingUserTest"> + <test name="AdminUserLockWhenEditingUserTest"> <annotations> <features value="Security"/> <stories value="Runs Lock admin user when creating new user test."/> @@ -25,93 +25,125 @@ </before> <after> <!-- Unlock Admin user --> - <magentoCLI command="admin:user:unlock {{_ENV.MAGENTO_ADMIN_USERNAME}}" stepKey="unlockAdminUser"/> + <magentoCLI command="admin:user:unlock {{DefaultAdminUser.username}}" stepKey="unlockAdminUser"/> <!-- TODO Need to create delete operation for data entity="Admin3" <deleteData createDataKey="user" stepKey="removeAdminUser"/>--> </after> - <actionGroup ref="AdminEditUserActionGroup" stepKey="editUserFirstAttempt"> + <actionGroup ref="AdminOpenUserEditPageActionGroup" stepKey="openEditUserPageFirstAttempt"> + <argument name="adminUser" value="$$user.username$$"/> + </actionGroup> + <actionGroup ref="AdminUserEditFillRequiredFieldsActionGroup" stepKey="fillEditUserFieldsFirstAttempt"> <argument name="adminUser" value="$$user.username$$"/> <argument name="adminFirstname" value="NEW$$user.firstname$$"/> <argument name="adminLastname" value="NEW$$user.lastname$$"/> <argument name="adminEmail" value="new$$user.email$$"/> <argument name="adminPassword" value="NEW$$user.password$$"/> <argument name="adminPasswordConfirmation" value="NEW$$user.password_confirmation$$"/> + <argument name="currentAdminPassword" value="{{DefaultAdminUser.password}}INVALID"/> + </actionGroup> + <actionGroup ref="AdminUserEditAssignRoleActionGroup" stepKey="assignRoleFirstAttempt"> <argument name="adminUserRole" value="1"/> - <argument name="messageSelector" value="{{AdminMessagesSection.error}}" /> + </actionGroup> + <actionGroup ref="AdminUserEditSaveUserActionGroup" stepKey="saveUserFirstAttempt" /> + <actionGroup ref="AssertMessageInAdminPanelActionGroup" stepKey="seeErrorFirstAttempt" > + <argument name="messageType" value="error" /> <argument name="message" value="The password entered for the current user is invalid. Verify the password and try again." /> - <argument name="currentAdminPassword" value="{{_ENV.MAGENTO_ADMIN_PASSWORD}}INVALID"/> </actionGroup> - <actionGroup ref="AdminEditUserActionGroup" stepKey="editUserSecondAttempt"> + <actionGroup ref="AdminUserEditFillRequiredFieldsActionGroup" stepKey="fillEditUserFieldsSecondAttempt"> <argument name="adminUser" value="$$user.username$$"/> <argument name="adminFirstname" value="NEW$$user.firstname$$"/> <argument name="adminLastname" value="NEW$$user.lastname$$"/> <argument name="adminEmail" value="new$$user.email$$"/> <argument name="adminPassword" value="NEW$$user.password$$"/> <argument name="adminPasswordConfirmation" value="NEW$$user.password_confirmation$$"/> + <argument name="currentAdminPassword" value="{{DefaultAdminUser.password}}INVALID"/> + </actionGroup> + <actionGroup ref="AdminUserEditAssignRoleActionGroup" stepKey="assignRoleSecondAttempt"> <argument name="adminUserRole" value="1"/> - <argument name="messageSelector" value="{{AdminMessagesSection.error}}" /> + </actionGroup> + <actionGroup ref="AdminUserEditSaveUserActionGroup" stepKey="saveUserSecondAttempt" /> + <actionGroup ref="AssertMessageInAdminPanelActionGroup" stepKey="seeErrorSecondAttempt" > + <argument name="messageType" value="error" /> <argument name="message" value="The password entered for the current user is invalid. Verify the password and try again." /> - <argument name="currentAdminPassword" value="{{_ENV.MAGENTO_ADMIN_PASSWORD}}INVALID"/> </actionGroup> - <actionGroup ref="AdminEditUserActionGroup" stepKey="editUserThirdAttempt"> + <actionGroup ref="AdminUserEditFillRequiredFieldsActionGroup" stepKey="fillEditUserFieldsThirdAttempt"> <argument name="adminUser" value="$$user.username$$"/> <argument name="adminFirstname" value="NEW$$user.firstname$$"/> <argument name="adminLastname" value="NEW$$user.lastname$$"/> <argument name="adminEmail" value="new$$user.email$$"/> <argument name="adminPassword" value="NEW$$user.password$$"/> <argument name="adminPasswordConfirmation" value="NEW$$user.password_confirmation$$"/> + <argument name="currentAdminPassword" value="{{DefaultAdminUser.password}}INVALID"/> + </actionGroup> + <actionGroup ref="AdminUserEditAssignRoleActionGroup" stepKey="assignRoleThirdAttempt"> <argument name="adminUserRole" value="1"/> - <argument name="messageSelector" value="{{AdminMessagesSection.error}}" /> + </actionGroup> + <actionGroup ref="AdminUserEditSaveUserActionGroup" stepKey="saveUserThirdAttempt" /> + <actionGroup ref="AssertMessageInAdminPanelActionGroup" stepKey="seeErrorThirdAttempt" > + <argument name="messageType" value="error" /> <argument name="message" value="The password entered for the current user is invalid. Verify the password and try again." /> - <argument name="currentAdminPassword" value="{{_ENV.MAGENTO_ADMIN_PASSWORD}}INVALID"/> </actionGroup> - <actionGroup ref="AdminEditUserActionGroup" stepKey="editUserFourthAttempt"> + <actionGroup ref="AdminUserEditFillRequiredFieldsActionGroup" stepKey="fillEditUserFieldsFourthAttempt"> <argument name="adminUser" value="$$user.username$$"/> <argument name="adminFirstname" value="NEW$$user.firstname$$"/> <argument name="adminLastname" value="NEW$$user.lastname$$"/> <argument name="adminEmail" value="new$$user.email$$"/> <argument name="adminPassword" value="NEW$$user.password$$"/> <argument name="adminPasswordConfirmation" value="NEW$$user.password_confirmation$$"/> + <argument name="currentAdminPassword" value="{{DefaultAdminUser.password}}INVALID"/> + </actionGroup> + <actionGroup ref="AdminUserEditAssignRoleActionGroup" stepKey="assignRoleFourthAttempt"> <argument name="adminUserRole" value="1"/> - <argument name="messageSelector" value="{{AdminMessagesSection.error}}" /> + </actionGroup> + <actionGroup ref="AdminUserEditSaveUserActionGroup" stepKey="saveUserFourthAttempt" /> + <actionGroup ref="AssertMessageInAdminPanelActionGroup" stepKey="seeErrorFourthAttempt" > + <argument name="messageType" value="error" /> <argument name="message" value="The password entered for the current user is invalid. Verify the password and try again." /> - <argument name="currentAdminPassword" value="{{_ENV.MAGENTO_ADMIN_PASSWORD}}INVALID"/> </actionGroup> - <actionGroup ref="AdminEditUserActionGroup" stepKey="editUserFifthAttempt"> + <actionGroup ref="AdminUserEditFillRequiredFieldsActionGroup" stepKey="fillEditUserFieldsFifthAttempt"> <argument name="adminUser" value="$$user.username$$"/> <argument name="adminFirstname" value="NEW$$user.firstname$$"/> <argument name="adminLastname" value="NEW$$user.lastname$$"/> <argument name="adminEmail" value="new$$user.email$$"/> <argument name="adminPassword" value="NEW$$user.password$$"/> <argument name="adminPasswordConfirmation" value="NEW$$user.password_confirmation$$"/> + <argument name="currentAdminPassword" value="{{DefaultAdminUser.password}}INVALID"/> + </actionGroup> + <actionGroup ref="AdminUserEditAssignRoleActionGroup" stepKey="assignRoleFifthAttempt"> <argument name="adminUserRole" value="1"/> - <argument name="messageSelector" value="{{AdminMessagesSection.error}}" /> + </actionGroup> + <actionGroup ref="AdminUserEditSaveUserActionGroup" stepKey="saveUserFifthAttempt" /> + <actionGroup ref="AssertMessageInAdminPanelActionGroup" stepKey="seeErrorFifthAttempt" > + <argument name="messageType" value="error" /> <argument name="message" value="The password entered for the current user is invalid. Verify the password and try again." /> - <argument name="currentAdminPassword" value="{{_ENV.MAGENTO_ADMIN_PASSWORD}}INVALID"/> </actionGroup> - <actionGroup ref="AdminEditUserActionGroup" stepKey="openEditLastPage"> + <actionGroup ref="AdminUserEditFillRequiredFieldsActionGroup" stepKey="fillEditUserFieldsLastAttempt"> <argument name="adminUser" value="$$user.username$$"/> <argument name="adminFirstname" value="NEW$$user.firstname$$"/> <argument name="adminLastname" value="NEW$$user.lastname$$"/> <argument name="adminEmail" value="new$$user.email$$"/> <argument name="adminPassword" value="NEW$$user.password$$"/> <argument name="adminPasswordConfirmation" value="NEW$$user.password_confirmation$$"/> + <argument name="currentAdminPassword" value="{{DefaultAdminUser.password}}INVALID"/> + </actionGroup> + <actionGroup ref="AdminUserEditAssignRoleActionGroup" stepKey="assignRoleLastAttempt"> <argument name="adminUserRole" value="1"/> - <argument name="messageSelector" value="{{AdminLoginFormSection.error}}" /> + </actionGroup> + <actionGroup ref="AdminUserEditSaveUserActionGroup" stepKey="saveUserLastAttempt" /> + <actionGroup ref="AssertMessageOnAdminLoginActionGroup" stepKey="seeErrorLastAttempt" > <argument name="message" value="Your account is temporarily disabled. Please try again later." /> - <argument name="currentAdminPassword" value="{{_ENV.MAGENTO_ADMIN_PASSWORD}}INVALID"/> </actionGroup> <!-- Try to login as admin and check error --> <actionGroup ref="LoginAsAdmin" stepKey="loginAsLockedAdmin"/> <waitForPageLoad stepKey="waitForError"/> - <see selector="{{AdminLoginFormSection.error}}" userInput="The account sign-in was incorrect or your account is disabled temporarily. Please wait and try again later" - stepKey="seeLoginUserError"/> + <actionGroup ref="AssertMessageOnAdminLoginActionGroup" stepKey="seeLoginErrorMessage" /> + </test> </tests> diff --git a/app/code/Magento/User/Test/Mftf/ActionGroup/AdminOpenUserEditPageActionGroup.xml b/app/code/Magento/User/Test/Mftf/ActionGroup/AdminOpenUserEditPageActionGroup.xml new file mode 100644 index 0000000000000..facc37e498b63 --- /dev/null +++ b/app/code/Magento/User/Test/Mftf/ActionGroup/AdminOpenUserEditPageActionGroup.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminOpenUserEditPageActionGroup"> + <arguments> + <argument name="adminUser" type="string" defaultValue="DefaultAdminUser.username"/> + </arguments> + + <amOnPage url="{{AdminUsersPage.url}}" stepKey="openAdminUsersPage"/> + <fillField selector="{{AdminUserGridSection.usernameFilterTextField}}" userInput="{{adminUser}}" stepKey="fillSearchUsernameFilter"/> + <click selector="{{AdminUserGridSection.searchButton}}" stepKey="clickSearch" /> + <waitForPageLoad stepKey="waitForGridToLoad"/> + <see selector="{{AdminUserGridSection.usernameInFirstRow}}" userInput="{{adminUser}}" stepKey="seeUser" /> + <click selector="{{AdminUserGridSection.searchResultFirstRow}}" stepKey="openUserEdit"/> + <waitForPageLoad stepKey="waitForUserEditPageLoad"/> + + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/User/Test/Mftf/ActionGroup/AdminUserEditAssignRoleActionGroup.xml b/app/code/Magento/User/Test/Mftf/ActionGroup/AdminUserEditAssignRoleActionGroup.xml new file mode 100644 index 0000000000000..8ed2b2c3b01dc --- /dev/null +++ b/app/code/Magento/User/Test/Mftf/ActionGroup/AdminUserEditAssignRoleActionGroup.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminUserEditAssignRoleActionGroup"> + <arguments> + <argument name="adminUserRole" type="string"/> + </arguments> + <!-- Set admin User Role --> + <click selector="{{AdminEditUserSection.userRoleTab}}" stepKey="openUserRoleTab"/> + <click selector="{{AdminEditUserSection.administratorRoleRadio(adminUserRole)}}" stepKey="assignRole"/> + + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/User/Test/Mftf/ActionGroup/AdminEditUserActionGroup.xml b/app/code/Magento/User/Test/Mftf/ActionGroup/AdminUserEditFillRequiredFieldsActionGroup.xml similarity index 55% rename from app/code/Magento/User/Test/Mftf/ActionGroup/AdminEditUserActionGroup.xml rename to app/code/Magento/User/Test/Mftf/ActionGroup/AdminUserEditFillRequiredFieldsActionGroup.xml index 7af34fe65947e..0697691068428 100644 --- a/app/code/Magento/User/Test/Mftf/ActionGroup/AdminEditUserActionGroup.xml +++ b/app/code/Magento/User/Test/Mftf/ActionGroup/AdminUserEditFillRequiredFieldsActionGroup.xml @@ -7,7 +7,7 @@ --> <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="AdminEditUserActionGroup"> + <actionGroup name="AdminUserEditFillRequiredFieldsActionGroup"> <arguments> <argument name="adminUser" type="string" /> <argument name="adminFirstname" type="string" /> @@ -15,21 +15,9 @@ <argument name="adminEmail" type="string" /> <argument name="adminPassword" type="string" /> <argument name="adminPasswordConfirmation" type="string" /> - <argument name="currentAdminPassword" type="string" /> - <argument name="adminUserRole" type="string"/> - <argument name="message" type="string" defaultValue="You saved the user." /> - <argument name="messageSelector" type="string" defaultValue="{{AdminMessagesSection.success}}" /> + <argument name="currentAdminPassword" type="string" defaultValue="DefaultAdminUser.password" /> </arguments> - <!-- Navigate to edit user page --> - <amOnPage url="{{AdminUsersPage.url}}" stepKey="openAdminUsersPage"/> - <fillField selector="{{AdminUserGridSection.usernameFilterTextField}}" userInput="{{adminUser}}" stepKey="fillSearchUsernameFilter"/> - <click selector="{{AdminUserGridSection.searchButton}}" stepKey="clickSearch" /> - <waitForPageLoad stepKey="waitForGridToLoad"/> - <see selector="{{AdminUserGridSection.usernameInFirstRow}}" userInput="{{adminUser}}" stepKey="seeUser" /> - <click selector="{{AdminUserGridSection.searchResultFirstRow}}" stepKey="openUserEdit"/> - <waitForPageLoad stepKey="waitForUserEditPageLoad"/> - <!-- Edit admin User data --> <fillField selector="{{AdminEditUserSection.usernameTextField}}" userInput="{{adminUser}}" stepKey="fillUser"/> <fillField selector="{{AdminEditUserSection.firstNameTextField}}" userInput="{{adminFirstname}}" stepKey="fillFirstName"/> @@ -40,14 +28,5 @@ <fillField selector="{{AdminEditUserSection.currentPasswordField}}" userInput="{{currentAdminPassword}}" stepKey="fillCurrentUserPassword"/> <scrollToTopOfPage stepKey="ScrollToTopOfPage"/> - <!-- Set admin User Role --> - <click selector="{{AdminEditUserSection.userRoleTab}}" stepKey="openUserRoleTab"/> - <click selector="{{AdminEditUserSection.administratorRoleRadio(adminUserRole)}}" stepKey="assignRole"/> - - <!-- Save User --> - <click selector="{{AdminEditUserSection.saveButton}}" stepKey="saveUser"/> - <waitForPageLoad stepKey="waitForSaveResultLoad"/> - <see userInput="{{message}}" selector="{{messageSelector}}" stepKey="verifyMessage" /> - </actionGroup> </actionGroups> diff --git a/app/code/Magento/User/Test/Mftf/ActionGroup/AdminUserEditSaveUserActionGroup.xml b/app/code/Magento/User/Test/Mftf/ActionGroup/AdminUserEditSaveUserActionGroup.xml new file mode 100644 index 0000000000000..1c733e1abb40a --- /dev/null +++ b/app/code/Magento/User/Test/Mftf/ActionGroup/AdminUserEditSaveUserActionGroup.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminUserEditSaveUserActionGroup"> + + <!-- Save User --> + <click selector="{{AdminEditUserSection.saveButton}}" stepKey="saveUser"/> + <waitForPageLoad stepKey="waitForSaveResultLoad"/> + + </actionGroup> +</actionGroups> diff --git a/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenEditingUserTest.xml b/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenEditingUserTest.xml index c5728da99a7a7..595cdc8f7fce8 100644 --- a/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenEditingUserTest.xml +++ b/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenEditingUserTest.xml @@ -9,7 +9,7 @@ <testCase name="Magento\Security\Test\TestCase\LockAdminUserWhenEditingUserTest" summary="Lock admin user after entering incorrect password while editing existing user"> <variation name="LockAdminUserWhenEditingUseruserTestVariation1"> <data name="configData" xsi:type="string">user_lockout_failures</data> - <data name="tag" xsi:type="string">severity:S2</data> + <data name="tag" xsi:type="string">severity:S2, mftf_migrated:yes</data> <data name="customAdmin/dataset" xsi:type="string">custom_admin_with_default_role</data> <data name="user/data/username" xsi:type="string">AdminUser%isolation%</data> <data name="user/data/firstname" xsi:type="string">FirstName%isolation%</data> @@ -19,7 +19,6 @@ <data name="user/data/password_confirmation" xsi:type="string">123123qq</data> <data name="user/data/current_password" xsi:type="string">incorrect password</data> <data name="attempts" xsi:type="string">4</data> - <data name="tag" xsi:type="string">mftf_migrated:yes</data> <constraint name="Magento\Security\Test\Constraint\AssertUserIsLocked" /> </variation> </testCase> From 5c887eacd5cc5e1f907a5cbb2c2a85ba23d81ff3 Mon Sep 17 00:00:00 2001 From: Stas Kozar <stas.kozar@transoftgroup.com> Date: Mon, 13 May 2019 11:06:32 +0300 Subject: [PATCH 379/773] MC-15448: One can't download or delete export csv file from export index page grid --- .../Adminhtml/Export/File/DeleteTest.php | 50 +++++++++++-------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/ImportExport/Controller/Adminhtml/Export/File/DeleteTest.php b/dev/tests/integration/testsuite/Magento/ImportExport/Controller/Adminhtml/Export/File/DeleteTest.php index ed19cf9b3515e..b698ddf651540 100644 --- a/dev/tests/integration/testsuite/Magento/ImportExport/Controller/Adminhtml/Export/File/DeleteTest.php +++ b/dev/tests/integration/testsuite/Magento/ImportExport/Controller/Adminhtml/Export/File/DeleteTest.php @@ -8,22 +8,19 @@ namespace Magento\ImportExport\Controller\Adminhtml\Export\File; use Magento\Framework\App\Filesystem\DirectoryList; +use Magento\Framework\Data\Form\FormKey; use Magento\Framework\Filesystem; -use Magento\ImportExport\Controller\Adminhtml\Export\File\Delete; +use Magento\Framework\Filesystem\Directory\WriteInterface; use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\TestCase\AbstractBackendController; /** * Test for \Magento\ImportExport\Controller\Adminhtml\Export\File\Delete class. */ -class DeleteTest extends \PHPUnit\Framework\TestCase +class DeleteTest extends AbstractBackendController { /** - * @var Delete - */ - private $model; - - /** - * @var \Magento\Framework\Filesystem\Directory\WriteInterface + * @var WriteInterface */ private $varDirectory; @@ -42,25 +39,20 @@ class DeleteTest extends \PHPUnit\Framework\TestCase */ private $filesystem; - /** - * @var \Magento\Framework\ObjectManagerInterface - */ - private $objectManager; - /** * @inheritdoc */ protected function setUp() { - $this->objectManager = Bootstrap::getObjectManager(); - $this->filesystem = $this->objectManager->get(Filesystem::class); + parent::setUp(); + + $this->filesystem = $this->_objectManager->get(Filesystem::class); $this->varDirectory = $this->filesystem->getDirectoryWrite(DirectoryList::VAR_DIR); $this->varDirectory->create($this->varDirectory->getRelativePath('export')); $this->fullDirectoryPath = $this->varDirectory->getAbsolutePath('export'); $filePath = $this->fullDirectoryPath . DIRECTORY_SEPARATOR . $this->fileName; $fixtureDir = realpath(__DIR__ . '/../../Import/_files'); copy($fixtureDir . '/' . $this->fileName, $filePath); - $this->model = $this->objectManager->get(Delete::class); } /** @@ -68,23 +60,41 @@ protected function setUp() * * @return void */ - public function testExecute() + public function testExecute(): void { - $this->model->getRequest()->setMethod('GET')->setParams(['filename' => 'catalog_product.csv']); - $this->model->execute(); + $uri = 'backend/admin/export_file/delete/filename/' . $this->fileName; + $this->prepareRequest($uri); + $this->dispatch($uri); $this->assertFalse( $this->varDirectory->isExist($this->varDirectory->getRelativePath('export/' . $this->fileName)) ); } + /** + * Prepares GET request for file deletion. + * + * @param string $uri + * @return void + */ + private function prepareRequest(string $uri): void + { + /** @var FormKey $formKey */ + $formKey = $this->_objectManager->get(FormKey::class); + $request = $this->getRequest(); + $request->setMethod('GET'); + $request->setParam('form_key', $formKey->getFormKey()); + $request->setRequestUri($uri); + $request->setParams(['filename' => 'catalog_product.csv']); + } + /** * @inheritdoc */ public static function tearDownAfterClass() { $filesystem = Bootstrap::getObjectManager()->get(Filesystem::class); - /** @var \Magento\Framework\Filesystem\Directory\WriteInterface $directory */ + /** @var WriteInterface $directory */ $directory = $filesystem->getDirectoryWrite(DirectoryList::VAR_DIR); if ($directory->isExist('export')) { $directory->delete('export'); From 683468fba3c4235d5a45496c23a7a52490309dcd Mon Sep 17 00:00:00 2001 From: Serhii Voloshkov <serhii.voloshkov@transoftgroup.com> Date: Tue, 14 May 2019 14:23:28 +0300 Subject: [PATCH 380/773] MC-16242: Visual Swatch Attribute values UI issue - Revert ENGCOM-4372 --- .../Swatches/view/adminhtml/web/css/swatches.css | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/app/code/Magento/Swatches/view/adminhtml/web/css/swatches.css b/app/code/Magento/Swatches/view/adminhtml/web/css/swatches.css index b0ea10b1ed968..ef635c48e3466 100644 --- a/app/code/Magento/Swatches/view/adminhtml/web/css/swatches.css +++ b/app/code/Magento/Swatches/view/adminhtml/web/css/swatches.css @@ -153,18 +153,6 @@ min-width: 65px; } -[class^=swatch-col], -[class^=col-]:not(.col-draggable):not(.col-default) { - min-width: 150px; -} - -#swatch-visual-options-panel, -#swatch-text-options-panel, -#manage-options-panel { - overflow: auto; - width: 100%; -} - .data-table .col-swatch-min-width input[type="text"] { padding: inherit; } From 016ba9a2bc364f606acde3141234f166d17ef3a5 Mon Sep 17 00:00:00 2001 From: Rafael Kassner <kassner@gmail.com> Date: Tue, 14 May 2019 15:52:50 +0200 Subject: [PATCH 381/773] Check if setting is disabled on default scope --- .../Reader/Source/Deployed/SettingChecker.php | 6 ++ .../Source/Deployed/SettingCheckerTest.php | 64 +++++++++++++++++-- 2 files changed, 65 insertions(+), 5 deletions(-) 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 index e3561261d17c7..5560884c2d722 100644 --- a/app/code/Magento/Config/Model/Config/Reader/Source/Deployed/SettingChecker.php +++ b/app/code/Magento/Config/Model/Config/Reader/Source/Deployed/SettingChecker.php @@ -64,6 +64,12 @@ public function isReadOnly($path, $scope, $scopeCode = null) $this->placeholder->generate($path, $scope, $scopeCode) ); + if (null === $config) { + $config = $this->config->get( + $this->resolvePath(ScopeConfigInterface::SCOPE_TYPE_DEFAULT, null) . "/" . $path + ); + } + if (null === $config) { $config = $this->config->get($this->resolvePath($scope, $scopeCode) . "/" . $path); } 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 index dc3a9a3cfa4ef..a864567657ae4 100644 --- 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 @@ -71,15 +71,16 @@ public function setUp() * @param string $scopeCode * @param string|null $confValue * @param array $variables + * @param array $configMap * @param bool $expectedResult * @dataProvider isReadonlyDataProvider */ - public function testIsReadonly($path, $scope, $scopeCode, $confValue, array $variables, $expectedResult) + public function testIsReadonly($path, $scope, $scopeCode, $confValue, array $variables, array $configMap, $expectedResult) { - $this->placeholderMock->expects($this->once()) + $this->placeholderMock->expects($this->any()) ->method('isApplicable') ->willReturn(true); - $this->placeholderMock->expects($this->once()) + $this->placeholderMock->expects($this->any()) ->method('generate') ->with($path, $scope, $scopeCode) ->willReturn('SOME_PLACEHOLDER'); @@ -95,13 +96,13 @@ public function testIsReadonly($path, $scope, $scopeCode, $confValue, array $var $this->configMock->expects($this->any()) ->method('get') - ->willReturnMap([ + ->willReturnMap(array_merge([ [ 'system/' . $scope . "/" . ($scopeCode ? $scopeCode . '/' : '') . $path, null, $confValue ], - ]); + ], $configMap)); $this->assertSame($expectedResult, $this->checker->isReadOnly($path, $scope, $scopeCode)); } @@ -118,6 +119,7 @@ public function isReadonlyDataProvider() 'scopeCode' => 'myWebsite', 'confValue' => 'value', 'variables' => [], + 'configMap' => [], 'expectedResult' => true, ], [ @@ -126,6 +128,7 @@ public function isReadonlyDataProvider() 'scopeCode' => 'myWebsite', 'confValue' => null, 'variables' => ['SOME_PLACEHOLDER' => 'value'], + 'configMap' => [], 'expectedResult' => true, ], [ @@ -134,7 +137,58 @@ public function isReadonlyDataProvider() 'scopeCode' => 'myWebsite', 'confValue' => null, 'variables' => [], + 'configMap' => [], 'expectedResult' => false, + ], + [ + 'path' => 'general/web/locale', + 'scope' => 'website', + 'scopeCode' => 'myWebsite', + 'confValue' => null, + 'variables' => [], + 'configMap' => [ + [ + 'system/default/general/web/locale', + null, + 'default_value', + ], + ], + 'expectedResult' => true, + ], + [ + 'path' => 'general/web/locale', + 'scope' => 'website', + 'scopeCode' => 'myWebsite', + 'confValue' => null, + 'variables' => [], + 'configMap' => [ + [ + 'system/default/general/web/locale', + null, + 'default_value', + ], + ], + 'expectedResult' => true, + ], + [ + 'path' => 'general/web/locale', + 'scope' => 'store', + 'scopeCode' => 'myStore', + 'confValue' => null, + 'variables' => [], + 'configMap' => [ + [ + 'system/default/general/web/locale', + null, + 'default_value', + ], + [ + 'system/website/myWebsite/general/web/locale', + null, + null, + ], + ], + 'expectedResult' => true, ] ]; } From c02e4accef09ee6a99bd90018e189a797b42af6e Mon Sep 17 00:00:00 2001 From: eduard13 <e.chitoraga@atwix.com> Date: Tue, 14 May 2019 20:05:16 +0300 Subject: [PATCH 382/773] Adding Delete Custom Variable Test --- .../Variable/Test/Mftf/Data/VariableData.xml | 3 ++ .../Test/Mftf/Metadata/variable-meta.xml | 21 ++++++++++ .../Test/DeleteCustomVariableEntityTest.xml | 41 +++++++++++++++++++ 3 files changed, 65 insertions(+) create mode 100644 app/code/Magento/Variable/Test/Mftf/Metadata/variable-meta.xml create mode 100644 app/code/Magento/Variable/Test/Mftf/Test/DeleteCustomVariableEntityTest.xml diff --git a/app/code/Magento/Variable/Test/Mftf/Data/VariableData.xml b/app/code/Magento/Variable/Test/Mftf/Data/VariableData.xml index 1160b79026617..923beaad96e65 100644 --- a/app/code/Magento/Variable/Test/Mftf/Data/VariableData.xml +++ b/app/code/Magento/Variable/Test/Mftf/Data/VariableData.xml @@ -17,4 +17,7 @@ <data key="html"> Sample Variable </data> <data key="plain">variable-plain-</data> </entity> + <entity name="customVariableV2" type="system_variable" extends="customVariable"> + <data key="code" unique="suffix">variable-code-</data> + </entity> </entities> diff --git a/app/code/Magento/Variable/Test/Mftf/Metadata/variable-meta.xml b/app/code/Magento/Variable/Test/Mftf/Metadata/variable-meta.xml new file mode 100644 index 0000000000000..b2a37d20408a6 --- /dev/null +++ b/app/code/Magento/Variable/Test/Mftf/Metadata/variable-meta.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<operations xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataOperation.xsd"> + <operation name="CreateCustomVariable" dataType="system_variable" type="create" auth="adminFormKey" + url="/admin/system_variable/save" method="POST" successRegex="/messages-message-success/"> + <contentType>application/x-www-form-urlencoded</contentType> + <object dataType="system_variable" key="variable"> + <field key="code">string</field> + <field key="name">string</field> + <field key="html">string</field> + <field key="plain">string</field> + </object> + </operation> +</operations> diff --git a/app/code/Magento/Variable/Test/Mftf/Test/DeleteCustomVariableEntityTest.xml b/app/code/Magento/Variable/Test/Mftf/Test/DeleteCustomVariableEntityTest.xml new file mode 100644 index 0000000000000..9ad67d261d6b6 --- /dev/null +++ b/app/code/Magento/Variable/Test/Mftf/Test/DeleteCustomVariableEntityTest.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="DeleteCustomVariableEntityTest"> + <annotations> + <features value="Variable"/> + <stories value="Delete Custom Variable."/> + <title value="Delete Custom Variable."/> + <description value="Test for deleting a custom variable."/> + <severity value="MAJOR"/> + <group value="variable"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + <createData entity="customVariableV2" stepKey="createCustomVariable"/> + </before> + <after> + <actionGroup ref="logout" stepKey="logout"/> + </after> + <actionGroup ref="AdminNavigateToVariablesGridPageActionGroup" stepKey="goToVariablesGridAdminPage"/> + <actionGroup ref="AdminFilterGridActionGroup" stepKey="filterVariablesGridByNewVariableCode" > + <argument name="field" value="{{AdminVariablesFilterSection.codeFilter}}"/> + <argument name="value" value="$$customVariableV2.code$$"/> + </actionGroup> + <actionGroup ref="AdminNavigateToVariablePageActionGroup" stepKey="openCustomVariablePage"> + <argument name="code" value="$$customVariableV2.code$$"/> + </actionGroup> + <actionGroup ref="AdminClickDeleteMainButtonWithConfirmationActionGroup" stepKey="clickDeleteVariable"/> + <actionGroup ref="AssertMessageActionGroup" stepKey="seeSuccessMessage"> + <argument name="message" value="You deleted the custom variable."/> + </actionGroup> + </test> +</tests> From f98083cdfca64f64a97a91bce1f7580c936bd63b Mon Sep 17 00:00:00 2001 From: DianaRusin <rusind95@gmail.com> Date: Wed, 15 May 2019 12:59:51 +0300 Subject: [PATCH 383/773] MC-16376: [FT] CreateOnlineCreditMemoBraintreePaypalTest fails on Bamboo --- .../app/Magento/Sales/Test/Block/Adminhtml/Order/Actions.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/Actions.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/Actions.php index 7a6903ef47aac..332aafd6d898a 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/Actions.php +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/Actions.php @@ -107,7 +107,7 @@ class Actions extends Block * * @var string */ - protected $orderInvoiceCreditMemo = '#capture'; + protected $orderInvoiceCreditMemo = '#credit-memo'; /** * 'Refund' button. From dad9e5b0d463433c2d212f21400a25e3c5b4b9d4 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Wed, 15 May 2019 15:17:21 +0300 Subject: [PATCH 384/773] MC-16244: CMS Block don't show on category page with Display Mode CMS Block only --- .../Fulltext/Collection/SearchCriteriaResolver.php | 2 +- .../Fulltext/Collection/SearchCriteriaResolverTest.php | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/Elasticsearch/Model/ResourceModel/Fulltext/Collection/SearchCriteriaResolver.php b/app/code/Magento/Elasticsearch/Model/ResourceModel/Fulltext/Collection/SearchCriteriaResolver.php index d1f1abb65a0ab..255c7885e84b9 100644 --- a/app/code/Magento/Elasticsearch/Model/ResourceModel/Fulltext/Collection/SearchCriteriaResolver.php +++ b/app/code/Magento/Elasticsearch/Model/ResourceModel/Fulltext/Collection/SearchCriteriaResolver.php @@ -79,7 +79,7 @@ public function resolve(): SearchCriteria $this->builder->setPageSize($this->size); $searchCriteria = $this->builder->create(); $searchCriteria->setRequestName($this->searchRequestName); - $searchCriteria->setSortOrders(array_merge(['relevance' => 'DESC'], $this->orders ?: [])); + $searchCriteria->setSortOrders($this->orders); $searchCriteria->setCurrentPage($this->currentPage - 1); return $searchCriteria; diff --git a/app/code/Magento/Elasticsearch/Test/Unit/Model/ResourceModel/Fulltext/Collection/SearchCriteriaResolverTest.php b/app/code/Magento/Elasticsearch/Test/Unit/Model/ResourceModel/Fulltext/Collection/SearchCriteriaResolverTest.php index babaf36f1439f..30a1642378b71 100644 --- a/app/code/Magento/Elasticsearch/Test/Unit/Model/ResourceModel/Fulltext/Collection/SearchCriteriaResolverTest.php +++ b/app/code/Magento/Elasticsearch/Test/Unit/Model/ResourceModel/Fulltext/Collection/SearchCriteriaResolverTest.php @@ -35,10 +35,10 @@ protected function setUp() /** * @param array|null $orders - * @param array $expected + * @param array|null $expected * @dataProvider resolveSortOrderDataProvider */ - public function testResolve($orders, array $expected) + public function testResolve($orders, $expected) { $searchRequestName = 'test'; $currentPage = 1; @@ -93,11 +93,11 @@ public function resolveSortOrderDataProvider() return [ [ null, - ['relevance' => 'DESC'], + null, ], [ ['test' => 'ASC'], - ['relevance' => 'DESC', 'test' => 'ASC'], + ['test' => 'ASC'], ], ]; } From 2e517951b8a2f1e3e9a88a20b7528f736fe18fc8 Mon Sep 17 00:00:00 2001 From: Stas Kozar <stas.kozar@transoftgroup.com> Date: Wed, 15 May 2019 16:51:42 +0300 Subject: [PATCH 385/773] MC-15448: One can't download or delete export csv file from export index page grid --- .../Adminhtml/Export/File/Delete.php | 13 +- .../Adminhtml/Export/File/Download.php | 9 +- .../Component/Columns/ExportGridActions.php | 3 +- .../Adminhtml/Export/File/DeleteTest.php | 27 +-- .../Adminhtml/Export/File/DownloadTest.php | 166 ++++++++++++++++++ 5 files changed, 181 insertions(+), 37 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/ImportExport/Controller/Adminhtml/Export/File/DownloadTest.php diff --git a/app/code/Magento/ImportExport/Controller/Adminhtml/Export/File/Delete.php b/app/code/Magento/ImportExport/Controller/Adminhtml/Export/File/Delete.php index c7eb99acad25c..10ae2dc5e58e1 100644 --- a/app/code/Magento/ImportExport/Controller/Adminhtml/Export/File/Delete.php +++ b/app/code/Magento/ImportExport/Controller/Adminhtml/Export/File/Delete.php @@ -8,7 +8,7 @@ namespace Magento\ImportExport\Controller\Adminhtml\Export\File; use Magento\Backend\App\Action; -use Magento\Framework\App\Action\HttpGetActionInterface; +use Magento\Framework\App\Action\HttpPostActionInterface; use Magento\Framework\Controller\ResultFactory; use Magento\Framework\Exception\FileSystemException; use Magento\Framework\Exception\LocalizedException; @@ -20,12 +20,12 @@ /** * Controller that delete file by name. */ -class Delete extends ExportController implements HttpGetActionInterface +class Delete extends ExportController implements HttpPostActionInterface { /** - * url to this controller + * Url to this controller */ - const URL = 'admin/export_file/delete'; + const URL = 'adminhtml/export_file/delete'; /** * @var Filesystem @@ -37,11 +37,6 @@ class Delete extends ExportController implements HttpGetActionInterface */ private $file; - /** - * @inheritdoc - */ - protected $_publicActions = ['delete']; - /** * Delete constructor. * @param Action\Context $context diff --git a/app/code/Magento/ImportExport/Controller/Adminhtml/Export/File/Download.php b/app/code/Magento/ImportExport/Controller/Adminhtml/Export/File/Download.php index e456c8b71347b..8dbd9a0ae44ba 100644 --- a/app/code/Magento/ImportExport/Controller/Adminhtml/Export/File/Download.php +++ b/app/code/Magento/ImportExport/Controller/Adminhtml/Export/File/Download.php @@ -21,9 +21,9 @@ class Download extends ExportController implements HttpGetActionInterface { /** - * url to this controller + * Url to this controller */ - const URL = 'admin/export_file/download/'; + const URL = 'adminhtml/export_file/download/'; /** * @var FileFactory @@ -35,11 +35,6 @@ class Download extends ExportController implements HttpGetActionInterface */ private $filesystem; - /** - * @inheritdoc - */ - protected $_publicActions = ['download']; - /** * DownloadFile constructor. * @param Action\Context $context diff --git a/app/code/Magento/ImportExport/Ui/Component/Columns/ExportGridActions.php b/app/code/Magento/ImportExport/Ui/Component/Columns/ExportGridActions.php index a7b9b072f00f4..b5e36ccd9fbab 100644 --- a/app/code/Magento/ImportExport/Ui/Component/Columns/ExportGridActions.php +++ b/app/code/Magento/ImportExport/Ui/Component/Columns/ExportGridActions.php @@ -65,7 +65,8 @@ public function prepareDataSource(array $dataSource) 'confirm' => [ 'title' => __('Delete'), 'message' => __('Are you sure you wan\'t to delete a file?') - ] + ], + 'post' => true, ]; } } diff --git a/dev/tests/integration/testsuite/Magento/ImportExport/Controller/Adminhtml/Export/File/DeleteTest.php b/dev/tests/integration/testsuite/Magento/ImportExport/Controller/Adminhtml/Export/File/DeleteTest.php index b698ddf651540..4cfa3f7027c87 100644 --- a/dev/tests/integration/testsuite/Magento/ImportExport/Controller/Adminhtml/Export/File/DeleteTest.php +++ b/dev/tests/integration/testsuite/Magento/ImportExport/Controller/Adminhtml/Export/File/DeleteTest.php @@ -8,7 +8,7 @@ namespace Magento\ImportExport\Controller\Adminhtml\Export\File; use Magento\Framework\App\Filesystem\DirectoryList; -use Magento\Framework\Data\Form\FormKey; +use Magento\Framework\App\Request\Http; use Magento\Framework\Filesystem; use Magento\Framework\Filesystem\Directory\WriteInterface; use Magento\TestFramework\Helper\Bootstrap; @@ -47,23 +47,27 @@ protected function setUp() parent::setUp(); $this->filesystem = $this->_objectManager->get(Filesystem::class); + $baseDirectory = $this->filesystem->getDirectoryWrite(DirectoryList::ROOT); $this->varDirectory = $this->filesystem->getDirectoryWrite(DirectoryList::VAR_DIR); $this->varDirectory->create($this->varDirectory->getRelativePath('export')); $this->fullDirectoryPath = $this->varDirectory->getAbsolutePath('export'); $filePath = $this->fullDirectoryPath . DIRECTORY_SEPARATOR . $this->fileName; $fixtureDir = realpath(__DIR__ . '/../../Import/_files'); - copy($fixtureDir . '/' . $this->fileName, $filePath); + $baseDirectory->copyFile($fixtureDir . '/' . $this->fileName, $filePath); } /** * Check that file can be removed under var/export directory. * * @return void + * @magentoConfigFixture default_store admin/security/use_form_key 1 */ public function testExecute(): void { $uri = 'backend/admin/export_file/delete/filename/' . $this->fileName; - $this->prepareRequest($uri); + $request = $this->getRequest(); + $request->setMethod(Http::METHOD_POST); + $request->setRequestUri($uri); $this->dispatch($uri); $this->assertFalse( @@ -71,23 +75,6 @@ public function testExecute(): void ); } - /** - * Prepares GET request for file deletion. - * - * @param string $uri - * @return void - */ - private function prepareRequest(string $uri): void - { - /** @var FormKey $formKey */ - $formKey = $this->_objectManager->get(FormKey::class); - $request = $this->getRequest(); - $request->setMethod('GET'); - $request->setParam('form_key', $formKey->getFormKey()); - $request->setRequestUri($uri); - $request->setParams(['filename' => 'catalog_product.csv']); - } - /** * @inheritdoc */ diff --git a/dev/tests/integration/testsuite/Magento/ImportExport/Controller/Adminhtml/Export/File/DownloadTest.php b/dev/tests/integration/testsuite/Magento/ImportExport/Controller/Adminhtml/Export/File/DownloadTest.php new file mode 100644 index 0000000000000..52aff8712f160 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/ImportExport/Controller/Adminhtml/Export/File/DownloadTest.php @@ -0,0 +1,166 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\ImportExport\Controller\Adminhtml\Export\File; + +use Magento\Backend\Model\Auth\Session; +use Magento\Framework\App\Filesystem\DirectoryList; +use Magento\Framework\App\Request\Http; +use Magento\Framework\Filesystem; +use Magento\Framework\Filesystem\Directory\WriteInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\TestCase\AbstractBackendController; +use Magento\Backend\Model\UrlInterface as BackendUrl; +use Magento\Backend\Model\Auth; +use Magento\TestFramework\Bootstrap as TestBootstrap; + +/** + * Test for \Magento\ImportExport\Controller\Adminhtml\Export\File\Download class. + */ +class DownloadTest extends AbstractBackendController +{ + /** + * @var WriteInterface + */ + private $varDirectory; + + /** + * @var string + */ + private $fullDirectoryPath; + + /** + * @var string + */ + private $fileName = 'catalog_product.csv'; + + /** + * @var string + */ + private $filesize; + + /** + * @var Filesystem + */ + private $filesystem; + + /** + * @var Auth + */ + private $auth; + + /** + * @var BackendUrl + */ + private $backendUrl; + + /** + * @inheritdoc + */ + protected function setUp() + { + parent::setUp(); + + $this->filesystem = $this->_objectManager->get(Filesystem::class); + $this->auth = $this->_objectManager->get(Auth::class); + $this->backendUrl = $this->_objectManager->get(BackendUrl::class); + $baseDirectory = $this->filesystem->getDirectoryWrite(DirectoryList::ROOT); + $this->varDirectory = $this->filesystem->getDirectoryWrite(DirectoryList::VAR_DIR); + $this->varDirectory->create($this->varDirectory->getRelativePath('export')); + $this->fullDirectoryPath = $this->varDirectory->getAbsolutePath('export'); + $filePath = $this->fullDirectoryPath . DIRECTORY_SEPARATOR . $this->fileName; + $fixtureDir = realpath(__DIR__ . '/../../Import/_files'); + $baseDirectory->copyFile($fixtureDir . '/' . $this->fileName, $filePath); + $this->filesize = filesize($filePath); + } + + /** + * Check that file can be downloaded. + * + * @return void + * @magentoConfigFixture default_store admin/security/use_form_key 1 + * @magentoAppArea adminhtml + */ + public function testExecute(): void + { + $uri = 'backend/admin/export_file/download/filename/' . $this->fileName; + $this->prepareRequest($uri); + + $this->dispatch($uri); + + $contentType = $this->getResponse()->getHeader('content-type'); + $contentLength = $this->getResponse()->getHeader('content-length'); + $contentDisposition = $this->getResponse()->getHeader('content-disposition'); + + $this->assertEquals(200, $this->getResponse()->getStatusCode(), 'Incorrect response status code'); + $this->assertEquals( + 'application/octet-stream', + $contentType->getFieldValue(), + 'Incorrect response header "content-type"' + ); + $this->assertEquals( + 'attachment; filename="export/' . $this->fileName . '"', + $contentDisposition->getFieldValue(), + 'Incorrect response header "content-disposition"' + ); + $this->assertEquals( + $this->filesize, + $contentLength->getFieldValue(), + 'Incorrect response header "content-length"' + ); + } + + /** + * Prepares GET request to download file. + * + * @param string $uri + * @return void + */ + private function prepareRequest(string $uri): void + { + $authSession = $this->_objectManager->create(Session::class); + $authSession->setIsFirstPageAfterLogin(false); + $this->auth->login( + TestBootstrap::ADMIN_NAME, + TestBootstrap::ADMIN_PASSWORD + ); + $this->auth->setAuthStorage($authSession); + + list($routeName, $controllerName, $actionName) = explode('/', Download::URL); + $request = $this->getRequest(); + $request->setMethod(Http::METHOD_GET) + ->setRouteName($routeName) + ->setControllerName($controllerName) + ->setActionName($actionName) + ->setParam(BackendUrl::SECRET_KEY_PARAM_NAME, $this->backendUrl->getSecretKey()) + ->setRequestUri($uri); + $this->backendUrl->turnOnSecretKey(); + } + + /** + * @inheritdoc + */ + protected function tearDown() + { + $this->auth = null; + + parent::tearDown(); + } + + /** + * @inheritdoc + */ + public static function tearDownAfterClass() + { + $filesystem = Bootstrap::getObjectManager()->get(Filesystem::class); + /** @var WriteInterface $directory */ + $directory = $filesystem->getDirectoryWrite(DirectoryList::VAR_DIR); + if ($directory->isExist('export')) { + $directory->delete('export'); + } + } +} From 224734c124df09bcb2f224ba8bfedb5e01f2327c Mon Sep 17 00:00:00 2001 From: eduard13 <e.chitoraga@atwix.com> Date: Wed, 15 May 2019 19:00:41 +0300 Subject: [PATCH 386/773] Reverting the ActionGroup for keeping the Backward Compatibility --- .../CreateCustomVariableActionGroup.xml | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 app/code/Magento/Variable/Test/Mftf/ActionGroup/CreateCustomVariableActionGroup.xml diff --git a/app/code/Magento/Variable/Test/Mftf/ActionGroup/CreateCustomVariableActionGroup.xml b/app/code/Magento/Variable/Test/Mftf/ActionGroup/CreateCustomVariableActionGroup.xml new file mode 100644 index 0000000000000..610676b350455 --- /dev/null +++ b/app/code/Magento/Variable/Test/Mftf/ActionGroup/CreateCustomVariableActionGroup.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="UTF-8"?> + <!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + --> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> +<actionGroup name="CreateCustomVariableActionGroup"> + <amOnPage url="admin/admin/system_variable/new/" stepKey="goToNewCustomVarialePage" /> + <waitForPageLoad stepKey="waitForPageLoad" /> + <fillField selector="{{CustomVariableSection.variableCode}}" userInput="{{customVariable.code}}" stepKey="fillVariableCode" /> + <fillField selector="{{CustomVariableSection.variableName}}" userInput="{{customVariable.name}}" stepKey="fillVariableName" /> + <fillField selector="{{CustomVariableSection.variableHTML}}" userInput="{{customVariable.html}}" stepKey="fillVariableHtml" /> + <fillField selector="{{CustomVariableSection.variablePlain}}" userInput="{{customVariable.plain}}" stepKey="fillVariablePlain" /> + <click selector="{{CustomVariableSection.saveCustomVariable}}" stepKey="clickSaveVariable"/> +</actionGroup> +<actionGroup name="DeleteCustomVariableActionGroup"> + <amOnPage url="admin/admin/system_variable/" stepKey="goToVarialeGrid" /> + <waitForPageLoad stepKey="waitForPageLoad1" /> + <click selector="{{CustomVariableSection.GridCustomVariableCode(customVariable.code)}}" stepKey="goToCustomVariableEditPage" /> + <waitForPageLoad stepKey="waitForPageLoad2" /> + <waitForElementVisible selector="{{CustomVariableSection.delete}}" stepKey="waitForDeleteBtn" /> + <click selector="{{CustomVariableSection.delete}}" stepKey="deleteCustomVariable" /> + <waitForText userInput="Are you sure you want to do this?" stepKey="waitForText" /> + <click selector="{{CustomVariableSection.confirmDelete}}" stepKey="confirmDelete" /> + <waitForPageLoad stepKey="waitForPageLoad3" /> +</actionGroup> +</actionGroups> From 388d31d1993378740957236b15e3ce27733748e2 Mon Sep 17 00:00:00 2001 From: Jayanka <jayan@codilar.com> Date: Thu, 16 May 2019 13:28:49 +0530 Subject: [PATCH 387/773] invalid form key issue resolved. Call the originalSubmitHandler if it's a function, or don't do anything --- lib/web/mage/validation.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/web/mage/validation.js b/lib/web/mage/validation.js index d3a44204b56e0..a7bab813dde18 100644 --- a/lib/web/mage/validation.js +++ b/lib/web/mage/validation.js @@ -1950,7 +1950,7 @@ element.element.removeAttr('orig-name'); }); /* Call the originalSubmitHandler if it's a function */ - typeof originalSubmitHandler === 'function' ? originalSubmitHandler(form) : form.submit(); + typeof originalSubmitHandler === 'function' ? originalSubmitHandler(form) : void(0); }; }, From 0c3cb3822c96d7502e7f1ee68c6edb1edf328338 Mon Sep 17 00:00:00 2001 From: Stas Kozar <stas.kozar@transoftgroup.com> Date: Fri, 17 May 2019 08:31:19 +0300 Subject: [PATCH 388/773] MC-15448: One can't download or delete export csv file from export index page grid --- .../Adminhtml/Export/File/DeleteTest.php | 40 ++++------ .../Adminhtml/Export/File/DownloadTest.php | 79 ++++++------------- 2 files changed, 40 insertions(+), 79 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/ImportExport/Controller/Adminhtml/Export/File/DeleteTest.php b/dev/tests/integration/testsuite/Magento/ImportExport/Controller/Adminhtml/Export/File/DeleteTest.php index 4cfa3f7027c87..91764684da173 100644 --- a/dev/tests/integration/testsuite/Magento/ImportExport/Controller/Adminhtml/Export/File/DeleteTest.php +++ b/dev/tests/integration/testsuite/Magento/ImportExport/Controller/Adminhtml/Export/File/DeleteTest.php @@ -24,21 +24,11 @@ class DeleteTest extends AbstractBackendController */ private $varDirectory; - /** - * @var string - */ - private $fullDirectoryPath; - /** * @var string */ private $fileName = 'catalog_product.csv'; - /** - * @var Filesystem - */ - private $filesystem; - /** * @inheritdoc */ @@ -46,14 +36,14 @@ protected function setUp() { parent::setUp(); - $this->filesystem = $this->_objectManager->get(Filesystem::class); - $baseDirectory = $this->filesystem->getDirectoryWrite(DirectoryList::ROOT); - $this->varDirectory = $this->filesystem->getDirectoryWrite(DirectoryList::VAR_DIR); - $this->varDirectory->create($this->varDirectory->getRelativePath('export')); - $this->fullDirectoryPath = $this->varDirectory->getAbsolutePath('export'); - $filePath = $this->fullDirectoryPath . DIRECTORY_SEPARATOR . $this->fileName; - $fixtureDir = realpath(__DIR__ . '/../../Import/_files'); - $baseDirectory->copyFile($fixtureDir . '/' . $this->fileName, $filePath); + $filesystem = $this->_objectManager->get(Filesystem::class); + $sourceFilePath = __DIR__ . '/../../Import/_files' . DIRECTORY_SEPARATOR . $this->fileName; + $destinationFilePath = 'export' . DIRECTORY_SEPARATOR . $this->fileName; + //Refers to tests 'var' directory + $this->varDirectory = $filesystem->getDirectoryRead(DirectoryList::VAR_DIR); + //Refers to application root directory + $rootDirectory = $filesystem->getDirectoryWrite(DirectoryList::ROOT); + $rootDirectory->copyFile($sourceFilePath, $this->varDirectory->getAbsolutePath($destinationFilePath)); } /** @@ -64,15 +54,17 @@ protected function setUp() */ public function testExecute(): void { - $uri = 'backend/admin/export_file/delete/filename/' . $this->fileName; $request = $this->getRequest(); + $request->setParam('filename', $this->fileName); $request->setMethod(Http::METHOD_POST); - $request->setRequestUri($uri); - $this->dispatch($uri); - $this->assertFalse( - $this->varDirectory->isExist($this->varDirectory->getRelativePath('export/' . $this->fileName)) - ); + if ($this->varDirectory->isExist('export/' . $this->fileName)) { + $this->dispatch('backend/admin/export_file/delete'); + } else { + throw new \AssertionError('Export product file supposed to exist'); + } + + $this->assertFalse($this->varDirectory->isExist('export/' . $this->fileName)); } /** diff --git a/dev/tests/integration/testsuite/Magento/ImportExport/Controller/Adminhtml/Export/File/DownloadTest.php b/dev/tests/integration/testsuite/Magento/ImportExport/Controller/Adminhtml/Export/File/DownloadTest.php index 52aff8712f160..073ecc6fd06a4 100644 --- a/dev/tests/integration/testsuite/Magento/ImportExport/Controller/Adminhtml/Export/File/DownloadTest.php +++ b/dev/tests/integration/testsuite/Magento/ImportExport/Controller/Adminhtml/Export/File/DownloadTest.php @@ -23,16 +23,6 @@ */ class DownloadTest extends AbstractBackendController { - /** - * @var WriteInterface - */ - private $varDirectory; - - /** - * @var string - */ - private $fullDirectoryPath; - /** * @var string */ @@ -43,11 +33,6 @@ class DownloadTest extends AbstractBackendController */ private $filesize; - /** - * @var Filesystem - */ - private $filesystem; - /** * @var Auth */ @@ -65,17 +50,20 @@ protected function setUp() { parent::setUp(); - $this->filesystem = $this->_objectManager->get(Filesystem::class); - $this->auth = $this->_objectManager->get(Auth::class); + $filesystem = $this->_objectManager->get(Filesystem::class); + $auth = $this->_objectManager->get(Auth::class); + $auth->getAuthStorage()->setIsFirstPageAfterLogin(false); $this->backendUrl = $this->_objectManager->get(BackendUrl::class); - $baseDirectory = $this->filesystem->getDirectoryWrite(DirectoryList::ROOT); - $this->varDirectory = $this->filesystem->getDirectoryWrite(DirectoryList::VAR_DIR); - $this->varDirectory->create($this->varDirectory->getRelativePath('export')); - $this->fullDirectoryPath = $this->varDirectory->getAbsolutePath('export'); - $filePath = $this->fullDirectoryPath . DIRECTORY_SEPARATOR . $this->fileName; - $fixtureDir = realpath(__DIR__ . '/../../Import/_files'); - $baseDirectory->copyFile($fixtureDir . '/' . $this->fileName, $filePath); - $this->filesize = filesize($filePath); + $this->backendUrl->turnOnSecretKey(); + + $sourceFilePath = __DIR__ . '/../../Import/_files' . DIRECTORY_SEPARATOR . $this->fileName; + $destinationFilePath = 'export' . DIRECTORY_SEPARATOR . $this->fileName; + //Refers to tests 'var' directory + $varDirectory = $filesystem->getDirectoryRead(DirectoryList::VAR_DIR); + //Refers to application root directory + $rootDirectory = $filesystem->getDirectoryWrite(DirectoryList::ROOT); + $rootDirectory->copyFile($sourceFilePath, $varDirectory->getAbsolutePath($destinationFilePath)); + $this->filesize = $varDirectory->stat($destinationFilePath)['size']; } /** @@ -87,10 +75,18 @@ protected function setUp() */ public function testExecute(): void { - $uri = 'backend/admin/export_file/download/filename/' . $this->fileName; - $this->prepareRequest($uri); + $request = $this->getRequest(); + list($routeName, $controllerName, $actionName) = explode('/', Download::URL); + $request->setMethod(Http::METHOD_GET) + ->setRouteName($routeName) + ->setControllerName($controllerName) + ->setActionName($actionName); + $request->setParam('filename', $this->fileName); + $request->setParam(BackendUrl::SECRET_KEY_PARAM_NAME, $this->backendUrl->getSecretKey()); - $this->dispatch($uri); + ob_start(); + $this->dispatch('backend/admin/export_file/download'); + ob_end_clean(); $contentType = $this->getResponse()->getHeader('content-type'); $contentLength = $this->getResponse()->getHeader('content-length'); @@ -114,33 +110,6 @@ public function testExecute(): void ); } - /** - * Prepares GET request to download file. - * - * @param string $uri - * @return void - */ - private function prepareRequest(string $uri): void - { - $authSession = $this->_objectManager->create(Session::class); - $authSession->setIsFirstPageAfterLogin(false); - $this->auth->login( - TestBootstrap::ADMIN_NAME, - TestBootstrap::ADMIN_PASSWORD - ); - $this->auth->setAuthStorage($authSession); - - list($routeName, $controllerName, $actionName) = explode('/', Download::URL); - $request = $this->getRequest(); - $request->setMethod(Http::METHOD_GET) - ->setRouteName($routeName) - ->setControllerName($controllerName) - ->setActionName($actionName) - ->setParam(BackendUrl::SECRET_KEY_PARAM_NAME, $this->backendUrl->getSecretKey()) - ->setRequestUri($uri); - $this->backendUrl->turnOnSecretKey(); - } - /** * @inheritdoc */ From 4b9a173eba5676087503baa9e1cf7b3c2ff3d2df Mon Sep 17 00:00:00 2001 From: Serhii Voloshkov <serhii.voloshkov@transoftgroup.com> Date: Fri, 17 May 2019 14:16:41 +0300 Subject: [PATCH 389/773] MC-16450: "Whoops, our bad" when copy and paste order information url on storefront --- app/code/Magento/Sales/Controller/Guest/View.php | 3 ++- .../testsuite/Magento/Sales/Controller/Guest/ViewTest.php | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Sales/Controller/Guest/View.php b/app/code/Magento/Sales/Controller/Guest/View.php index 185369dd6ed80..04e510f116c3f 100644 --- a/app/code/Magento/Sales/Controller/Guest/View.php +++ b/app/code/Magento/Sales/Controller/Guest/View.php @@ -6,6 +6,7 @@ namespace Magento\Sales\Controller\Guest; use Magento\Framework\App\Action; +use Magento\Framework\App\Action\HttpGetActionInterface; use Magento\Sales\Helper\Guest as GuestHelper; use Magento\Framework\View\Result\PageFactory; use Magento\Framework\Controller\ResultInterface; @@ -14,7 +15,7 @@ /** * Guest order view action. */ -class View extends Action\Action implements HttpPostActionInterface +class View extends Action\Action implements HttpPostActionInterface, HttpGetActionInterface { /** * @var \Magento\Sales\Helper\Guest diff --git a/dev/tests/integration/testsuite/Magento/Sales/Controller/Guest/ViewTest.php b/dev/tests/integration/testsuite/Magento/Sales/Controller/Guest/ViewTest.php index a984887bdb1b0..5a912c2960ab6 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/Controller/Guest/ViewTest.php +++ b/dev/tests/integration/testsuite/Magento/Sales/Controller/Guest/ViewTest.php @@ -16,13 +16,13 @@ class ViewTest extends AbstractController { /** - * Check that controller applied only POST requests. + * Check that controller applied GET requests. */ - public function testExecuteWithNonPostRequest() + public function testExecuteWithGetRequest() { $this->getRequest()->setMethod(Request::METHOD_GET); $this->dispatch('sales/guest/view/'); - $this->assert404NotFound(); + $this->assertRedirect($this->stringContains('sales/guest/form')); } } From ce2118d3458ab3abd3ee168e2e67b2897ef8150b Mon Sep 17 00:00:00 2001 From: Mila Lesechko <llesechk@adobe.com> Date: Fri, 17 May 2019 09:43:31 -0500 Subject: [PATCH 390/773] MC-4767: Convert PrintOrderFrontendGuestTest to MFTF --- .../Sales/Test/Mftf/Test/StorefrontPrintOrderGuestTest.xml | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/code/Magento/Sales/Test/Mftf/Test/StorefrontPrintOrderGuestTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/StorefrontPrintOrderGuestTest.xml index cbe24778558b7..804514ef4922f 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/StorefrontPrintOrderGuestTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/StorefrontPrintOrderGuestTest.xml @@ -45,7 +45,6 @@ <grabValueFrom selector="{{AdminProductDownloadableSection.addLinkTitleInput('0')}}" stepKey="grabLink"/> <click selector="{{AdminProductFormSection.save}}" stepKey="clickSave"/> <waitForLoadingMaskToDisappear stepKey="waitForSave"/> - <waitForPageLoad stepKey="waitForPage"/> <!-- Create configurable Product --> <createData entity="ApiConfigurableProduct" stepKey="createConfigProduct"> @@ -245,7 +244,6 @@ <!-- Click on the "Continue" button --> <click selector="{{StorefrontGuestOrderSearchSection.continue}}" stepKey="clickContinue"/> <waitForPageLoad stepKey="waitForPageLoad"/> - <waitForLoadingMaskToDisappear stepKey="waitForOrderPage"/> <!-- Click on the "Print Order" button --> <click selector="{{StorefrontGuestOrderViewSection.printOrder}}" stepKey="printOrder"/> From 5dcb21b1d7ac9179e2d426d7b2f3750159b0d1b5 Mon Sep 17 00:00:00 2001 From: Alex Kolesnyk <kolesnyk@adobe.com> Date: Fri, 17 May 2019 11:05:23 -0500 Subject: [PATCH 391/773] Test improvements: - added action group to delete user - removed duplicate action groups - introduced metadata for admin user deletion - added test case id - updated annotations - issue magento/magento-functional-tests-migration/377 - pull request magento/magento-functional-tests-migration/704 --- .../AdminLegacyDataGridFilterSection.xml | 17 +++ .../AdminLegacyDataGridTableSection.xml | 17 +++ .../Test/AdminUserLockWhenEditingUserTest.xml | 120 ++++++------------ .../AdminDeleteUserViaCurlActionGroup.xml | 30 +++++ .../AdminOpenUserEditPageActionGroup.xml | 13 +- .../AdminUserEditAssignRoleActionGroup.xml | 19 --- ...nUserEditFillRequiredFieldsActionGroup.xml | 32 ----- .../AdminUserEditSaveUserActionGroup.xml | 17 --- .../Magento/User/Test/Mftf/Data/UserData.xml | 41 ++++++ .../User/Test/Mftf/Metadata/user-meta.xml | 5 + .../User/Test/Mftf/Page/AdminEditUserPage.xml | 7 + .../User/Test/Mftf/Page/AdminUserEditPage.xml | 12 ++ .../User/Test/Mftf/Page/AdminUsersPage.xml | 3 +- 13 files changed, 176 insertions(+), 157 deletions(-) create mode 100644 app/code/Magento/Backend/Test/Mftf/Section/AdminLegacyDataGridFilterSection.xml create mode 100644 app/code/Magento/Backend/Test/Mftf/Section/AdminLegacyDataGridTableSection.xml create mode 100644 app/code/Magento/User/Test/Mftf/ActionGroup/AdminDeleteUserViaCurlActionGroup.xml delete mode 100644 app/code/Magento/User/Test/Mftf/ActionGroup/AdminUserEditAssignRoleActionGroup.xml delete mode 100644 app/code/Magento/User/Test/Mftf/ActionGroup/AdminUserEditFillRequiredFieldsActionGroup.xml delete mode 100644 app/code/Magento/User/Test/Mftf/ActionGroup/AdminUserEditSaveUserActionGroup.xml create mode 100644 app/code/Magento/User/Test/Mftf/Page/AdminUserEditPage.xml diff --git a/app/code/Magento/Backend/Test/Mftf/Section/AdminLegacyDataGridFilterSection.xml b/app/code/Magento/Backend/Test/Mftf/Section/AdminLegacyDataGridFilterSection.xml new file mode 100644 index 0000000000000..0d5f3f3e53e50 --- /dev/null +++ b/app/code/Magento/Backend/Test/Mftf/Section/AdminLegacyDataGridFilterSection.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="AdminLegacyDataGridFilterSection"> + <element name="filterForm" type="block" selector="[data-role='filter-form']" /> + <element name="inputFieldByNameAttr" type="input" selector="[data-role='filter-form'] input[name='{{inputNameAttr}}']" parameterized="true" /> + <element name="apply" type="button" selector=".admin__data-grid-header [data-action='grid-filter-apply']" /> + <element name="clear" type="button" selector=".admin__data-grid-header [data-action='grid-filter-reset']" /> + </section> +</sections> diff --git a/app/code/Magento/Backend/Test/Mftf/Section/AdminLegacyDataGridTableSection.xml b/app/code/Magento/Backend/Test/Mftf/Section/AdminLegacyDataGridTableSection.xml new file mode 100644 index 0000000000000..ad36001928863 --- /dev/null +++ b/app/code/Magento/Backend/Test/Mftf/Section/AdminLegacyDataGridTableSection.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="AdminLegacyDataGridTableSection"> + <element name="rowTemplateStrict" type="block" selector="//tbody/tr[td[text()[normalize-space()='{{text}}']]]" parameterized="true" /> + <element name="rowTemplate" type="block" selector="//tbody/tr[td[contains(.,normalize-space('{{text}}'))]]" parameterized="true" /> + <element name="columnTemplateStrict" type="block" selector="//tbody/tr[td[contains(.,normalize-space('{{text}}'))]]/td[@data-column='{{dataColumn}}']" parameterized="true" /> + <element name="columnTemplate" type="block" selector="//tbody/tr[td[contains(.,normalize-space('{{text}}'))]]/td[@data-column='{{dataColumn}}']" parameterized="true" /> + </section> +</sections> diff --git a/app/code/Magento/Security/Test/Mftf/Test/AdminUserLockWhenEditingUserTest.xml b/app/code/Magento/Security/Test/Mftf/Test/AdminUserLockWhenEditingUserTest.xml index de1ed793c0bc8..2ce54d6c0fda5 100644 --- a/app/code/Magento/Security/Test/Mftf/Test/AdminUserLockWhenEditingUserTest.xml +++ b/app/code/Magento/Security/Test/Mftf/Test/AdminUserLockWhenEditingUserTest.xml @@ -11,139 +11,95 @@ <test name="AdminUserLockWhenEditingUserTest"> <annotations> <features value="Security"/> - <stories value="Runs Lock admin user when creating new user test."/> - <title value="Lock admin user when creating new user"/> - <description value="Runs Lock admin user when creating new user test."/> - <severity value="MAJOR"/> + <stories value="Runs Lock admin user when editing existing user test."/> + <title value="Lock admin user when creating new user."/> + <description value="Runs Lock admin user when editing existing user test."/> + <severity value="CRITICAL"/> + <testCaseId value="MC-14372" /> <group value="security"/> <group value="mtf_migrated"/> </annotations> <before> - <createData entity="Admin3" stepKey="user"/> + <!-- + @TODO: Remove "executeJS" in scope of MQE-1561 + Hack to be able to pass current admin user password without hardcoding it. + --> + <executeJS function="return '{{DefaultAdminUser.password}}'" stepKey="adminPassword" /> + <createData entity="NewAdminUser" stepKey="user"> + <field key="current_password">{$adminPassword}</field> + </createData> <!-- Log in to Admin Panel --> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> </before> <after> <!-- Unlock Admin user --> <magentoCLI command="admin:user:unlock {{DefaultAdminUser.username}}" stepKey="unlockAdminUser"/> - <!-- TODO Need to create delete operation for data entity="Admin3" - <deleteData createDataKey="user" stepKey="removeAdminUser"/>--> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + <actionGroup ref="AdminDeleteUserViaCurlActionGroup" stepKey="deleteUser"> + <argument name="user" value="$$user$$" /> + </actionGroup> + <actionGroup ref="logout" stepKey="logout"/> </after> <actionGroup ref="AdminOpenUserEditPageActionGroup" stepKey="openEditUserPageFirstAttempt"> - <argument name="adminUser" value="$$user.username$$"/> - </actionGroup> - <actionGroup ref="AdminUserEditFillRequiredFieldsActionGroup" stepKey="fillEditUserFieldsFirstAttempt"> - <argument name="adminUser" value="$$user.username$$"/> - <argument name="adminFirstname" value="NEW$$user.firstname$$"/> - <argument name="adminLastname" value="NEW$$user.lastname$$"/> - <argument name="adminEmail" value="new$$user.email$$"/> - <argument name="adminPassword" value="NEW$$user.password$$"/> - <argument name="adminPasswordConfirmation" value="NEW$$user.password_confirmation$$"/> - <argument name="currentAdminPassword" value="{{DefaultAdminUser.password}}INVALID"/> + <argument name="user" value="$$user$$"/> </actionGroup> - <actionGroup ref="AdminUserEditAssignRoleActionGroup" stepKey="assignRoleFirstAttempt"> - <argument name="adminUserRole" value="1"/> + + <actionGroup ref="AdminFillNewUserFormRequiredFieldsActionGroup" stepKey="fillEditUserFieldsFirstAttempt"> + <argument name="user" value="EditAdminUserWrongCurrentPassword" /> </actionGroup> - <actionGroup ref="AdminUserEditSaveUserActionGroup" stepKey="saveUserFirstAttempt" /> + <actionGroup ref="AdminClickSaveButtonOnUserFormActionGroup" stepKey="clickSaveFirstAttempt" /> <actionGroup ref="AssertMessageInAdminPanelActionGroup" stepKey="seeErrorFirstAttempt" > <argument name="messageType" value="error" /> <argument name="message" value="The password entered for the current user is invalid. Verify the password and try again." /> </actionGroup> - <actionGroup ref="AdminUserEditFillRequiredFieldsActionGroup" stepKey="fillEditUserFieldsSecondAttempt"> - <argument name="adminUser" value="$$user.username$$"/> - <argument name="adminFirstname" value="NEW$$user.firstname$$"/> - <argument name="adminLastname" value="NEW$$user.lastname$$"/> - <argument name="adminEmail" value="new$$user.email$$"/> - <argument name="adminPassword" value="NEW$$user.password$$"/> - <argument name="adminPasswordConfirmation" value="NEW$$user.password_confirmation$$"/> - <argument name="currentAdminPassword" value="{{DefaultAdminUser.password}}INVALID"/> + <actionGroup ref="AdminFillNewUserFormRequiredFieldsActionGroup" stepKey="fillEditUserFieldsSecondAttempt"> + <argument name="user" value="EditAdminUserWrongCurrentPassword" /> </actionGroup> - <actionGroup ref="AdminUserEditAssignRoleActionGroup" stepKey="assignRoleSecondAttempt"> - <argument name="adminUserRole" value="1"/> - </actionGroup> - <actionGroup ref="AdminUserEditSaveUserActionGroup" stepKey="saveUserSecondAttempt" /> + <actionGroup ref="AdminClickSaveButtonOnUserFormActionGroup" stepKey="clickSaveSecondAttempt" /> <actionGroup ref="AssertMessageInAdminPanelActionGroup" stepKey="seeErrorSecondAttempt" > <argument name="messageType" value="error" /> <argument name="message" value="The password entered for the current user is invalid. Verify the password and try again." /> </actionGroup> - <actionGroup ref="AdminUserEditFillRequiredFieldsActionGroup" stepKey="fillEditUserFieldsThirdAttempt"> - <argument name="adminUser" value="$$user.username$$"/> - <argument name="adminFirstname" value="NEW$$user.firstname$$"/> - <argument name="adminLastname" value="NEW$$user.lastname$$"/> - <argument name="adminEmail" value="new$$user.email$$"/> - <argument name="adminPassword" value="NEW$$user.password$$"/> - <argument name="adminPasswordConfirmation" value="NEW$$user.password_confirmation$$"/> - <argument name="currentAdminPassword" value="{{DefaultAdminUser.password}}INVALID"/> - </actionGroup> - <actionGroup ref="AdminUserEditAssignRoleActionGroup" stepKey="assignRoleThirdAttempt"> - <argument name="adminUserRole" value="1"/> + <actionGroup ref="AdminFillNewUserFormRequiredFieldsActionGroup" stepKey="fillEditUserFieldsThirdAttempt"> + <argument name="user" value="EditAdminUserWrongCurrentPassword" /> </actionGroup> - <actionGroup ref="AdminUserEditSaveUserActionGroup" stepKey="saveUserThirdAttempt" /> + <actionGroup ref="AdminClickSaveButtonOnUserFormActionGroup" stepKey="clickSaveThirdAttempt" /> <actionGroup ref="AssertMessageInAdminPanelActionGroup" stepKey="seeErrorThirdAttempt" > <argument name="messageType" value="error" /> <argument name="message" value="The password entered for the current user is invalid. Verify the password and try again." /> </actionGroup> - <actionGroup ref="AdminUserEditFillRequiredFieldsActionGroup" stepKey="fillEditUserFieldsFourthAttempt"> - <argument name="adminUser" value="$$user.username$$"/> - <argument name="adminFirstname" value="NEW$$user.firstname$$"/> - <argument name="adminLastname" value="NEW$$user.lastname$$"/> - <argument name="adminEmail" value="new$$user.email$$"/> - <argument name="adminPassword" value="NEW$$user.password$$"/> - <argument name="adminPasswordConfirmation" value="NEW$$user.password_confirmation$$"/> - <argument name="currentAdminPassword" value="{{DefaultAdminUser.password}}INVALID"/> + <actionGroup ref="AdminFillNewUserFormRequiredFieldsActionGroup" stepKey="fillEditUserFieldsFourthAttempt"> + <argument name="user" value="EditAdminUserWrongCurrentPassword" /> </actionGroup> - <actionGroup ref="AdminUserEditAssignRoleActionGroup" stepKey="assignRoleFourthAttempt"> - <argument name="adminUserRole" value="1"/> - </actionGroup> - <actionGroup ref="AdminUserEditSaveUserActionGroup" stepKey="saveUserFourthAttempt" /> + <actionGroup ref="AdminClickSaveButtonOnUserFormActionGroup" stepKey="clickSaveFourthAttempt" /> <actionGroup ref="AssertMessageInAdminPanelActionGroup" stepKey="seeErrorFourthAttempt" > <argument name="messageType" value="error" /> <argument name="message" value="The password entered for the current user is invalid. Verify the password and try again." /> </actionGroup> - <actionGroup ref="AdminUserEditFillRequiredFieldsActionGroup" stepKey="fillEditUserFieldsFifthAttempt"> - <argument name="adminUser" value="$$user.username$$"/> - <argument name="adminFirstname" value="NEW$$user.firstname$$"/> - <argument name="adminLastname" value="NEW$$user.lastname$$"/> - <argument name="adminEmail" value="new$$user.email$$"/> - <argument name="adminPassword" value="NEW$$user.password$$"/> - <argument name="adminPasswordConfirmation" value="NEW$$user.password_confirmation$$"/> - <argument name="currentAdminPassword" value="{{DefaultAdminUser.password}}INVALID"/> - </actionGroup> - <actionGroup ref="AdminUserEditAssignRoleActionGroup" stepKey="assignRoleFifthAttempt"> - <argument name="adminUserRole" value="1"/> + <actionGroup ref="AdminFillNewUserFormRequiredFieldsActionGroup" stepKey="fillEditUserFieldsFifthAttempt"> + <argument name="user" value="EditAdminUserWrongCurrentPassword" /> </actionGroup> - <actionGroup ref="AdminUserEditSaveUserActionGroup" stepKey="saveUserFifthAttempt" /> + <actionGroup ref="AdminClickSaveButtonOnUserFormActionGroup" stepKey="clickSaveFifthAttempt" /> <actionGroup ref="AssertMessageInAdminPanelActionGroup" stepKey="seeErrorFifthAttempt" > <argument name="messageType" value="error" /> <argument name="message" value="The password entered for the current user is invalid. Verify the password and try again." /> </actionGroup> - <actionGroup ref="AdminUserEditFillRequiredFieldsActionGroup" stepKey="fillEditUserFieldsLastAttempt"> - <argument name="adminUser" value="$$user.username$$"/> - <argument name="adminFirstname" value="NEW$$user.firstname$$"/> - <argument name="adminLastname" value="NEW$$user.lastname$$"/> - <argument name="adminEmail" value="new$$user.email$$"/> - <argument name="adminPassword" value="NEW$$user.password$$"/> - <argument name="adminPasswordConfirmation" value="NEW$$user.password_confirmation$$"/> - <argument name="currentAdminPassword" value="{{DefaultAdminUser.password}}INVALID"/> + <actionGroup ref="AdminFillNewUserFormRequiredFieldsActionGroup" stepKey="fillEditUserFieldsLastAttempt"> + <argument name="user" value="EditAdminUserWrongCurrentPassword" /> </actionGroup> - <actionGroup ref="AdminUserEditAssignRoleActionGroup" stepKey="assignRoleLastAttempt"> - <argument name="adminUserRole" value="1"/> - </actionGroup> - <actionGroup ref="AdminUserEditSaveUserActionGroup" stepKey="saveUserLastAttempt" /> + <actionGroup ref="AdminClickSaveButtonOnUserFormActionGroup" stepKey="clickSaveLastAttempt" /> <actionGroup ref="AssertMessageOnAdminLoginActionGroup" stepKey="seeErrorLastAttempt" > <argument name="message" value="Your account is temporarily disabled. Please try again later." /> </actionGroup> <!-- Try to login as admin and check error --> <actionGroup ref="LoginAsAdmin" stepKey="loginAsLockedAdmin"/> - <waitForPageLoad stepKey="waitForError"/> <actionGroup ref="AssertMessageOnAdminLoginActionGroup" stepKey="seeLoginErrorMessage" /> - </test> </tests> diff --git a/app/code/Magento/User/Test/Mftf/ActionGroup/AdminDeleteUserViaCurlActionGroup.xml b/app/code/Magento/User/Test/Mftf/ActionGroup/AdminDeleteUserViaCurlActionGroup.xml new file mode 100644 index 0000000000000..ec22cd6e404f4 --- /dev/null +++ b/app/code/Magento/User/Test/Mftf/ActionGroup/AdminDeleteUserViaCurlActionGroup.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminDeleteUserViaCurlActionGroup"> + <arguments> + <argument name="user" type="entity" /> + </arguments> + <amOnPage stepKey="amOnAdminUsersPage" url="{{AdminUsersPage.url}}"/> + <waitForPageLoad stepKey="waitForAdminUserPageLoad"/> + <click selector="{{AdminLegacyDataGridFilterSection.clear}}" stepKey="resetFilters" /> + <grabTextFrom selector="{{AdminLegacyDataGridTableSection.columnTemplateStrict(user.username, 'user_id')}}" stepKey="userId" /> + + <!-- + @TODO: Remove "executeJS" in scope of MQE-1561 + Hack to be able to pass current admin user password without hardcoding it. + --> + <executeJS function="return '{{DefaultAdminUser.password}}'" stepKey="adminPassword" /> + + <createData entity="deleteUser" stepKey="deleteUser"> + <field key="user_id">{$userId}</field> + <field key="current_password">{$adminPassword}</field> + </createData> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/User/Test/Mftf/ActionGroup/AdminOpenUserEditPageActionGroup.xml b/app/code/Magento/User/Test/Mftf/ActionGroup/AdminOpenUserEditPageActionGroup.xml index facc37e498b63..e8f8c23b7e4e5 100644 --- a/app/code/Magento/User/Test/Mftf/ActionGroup/AdminOpenUserEditPageActionGroup.xml +++ b/app/code/Magento/User/Test/Mftf/ActionGroup/AdminOpenUserEditPageActionGroup.xml @@ -9,16 +9,17 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="AdminOpenUserEditPageActionGroup"> <arguments> - <argument name="adminUser" type="string" defaultValue="DefaultAdminUser.username"/> + <argument name="user" type="entity" /> </arguments> <amOnPage url="{{AdminUsersPage.url}}" stepKey="openAdminUsersPage"/> - <fillField selector="{{AdminUserGridSection.usernameFilterTextField}}" userInput="{{adminUser}}" stepKey="fillSearchUsernameFilter"/> - <click selector="{{AdminUserGridSection.searchButton}}" stepKey="clickSearch" /> + <waitForPageLoad stepKey="waitForPageToLoad"/> + <click selector="{{AdminLegacyDataGridFilterSection.clear}}" stepKey="resetFilters" /> + <fillField selector="{{AdminLegacyDataGridFilterSection.inputFieldByNameAttr('username')}}" userInput="{{user.username}}" stepKey="fillSearchUsernameFilter"/> + <click selector="{{AdminLegacyDataGridFilterSection.apply}}" stepKey="clickSearch" /> <waitForPageLoad stepKey="waitForGridToLoad"/> - <see selector="{{AdminUserGridSection.usernameInFirstRow}}" userInput="{{adminUser}}" stepKey="seeUser" /> - <click selector="{{AdminUserGridSection.searchResultFirstRow}}" stepKey="openUserEdit"/> - <waitForPageLoad stepKey="waitForUserEditPageLoad"/> + <click selector="{{AdminLegacyDataGridTableSection.rowTemplateStrict(user.username)}}" stepKey="openUserEdit"/> + <waitForPageLoad stepKey="waitForUserEditPageLoad"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/User/Test/Mftf/ActionGroup/AdminUserEditAssignRoleActionGroup.xml b/app/code/Magento/User/Test/Mftf/ActionGroup/AdminUserEditAssignRoleActionGroup.xml deleted file mode 100644 index 8ed2b2c3b01dc..0000000000000 --- a/app/code/Magento/User/Test/Mftf/ActionGroup/AdminUserEditAssignRoleActionGroup.xml +++ /dev/null @@ -1,19 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="AdminUserEditAssignRoleActionGroup"> - <arguments> - <argument name="adminUserRole" type="string"/> - </arguments> - <!-- Set admin User Role --> - <click selector="{{AdminEditUserSection.userRoleTab}}" stepKey="openUserRoleTab"/> - <click selector="{{AdminEditUserSection.administratorRoleRadio(adminUserRole)}}" stepKey="assignRole"/> - - </actionGroup> -</actionGroups> diff --git a/app/code/Magento/User/Test/Mftf/ActionGroup/AdminUserEditFillRequiredFieldsActionGroup.xml b/app/code/Magento/User/Test/Mftf/ActionGroup/AdminUserEditFillRequiredFieldsActionGroup.xml deleted file mode 100644 index 0697691068428..0000000000000 --- a/app/code/Magento/User/Test/Mftf/ActionGroup/AdminUserEditFillRequiredFieldsActionGroup.xml +++ /dev/null @@ -1,32 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="AdminUserEditFillRequiredFieldsActionGroup"> - <arguments> - <argument name="adminUser" type="string" /> - <argument name="adminFirstname" type="string" /> - <argument name="adminLastname" type="string" /> - <argument name="adminEmail" type="string" /> - <argument name="adminPassword" type="string" /> - <argument name="adminPasswordConfirmation" type="string" /> - <argument name="currentAdminPassword" type="string" defaultValue="DefaultAdminUser.password" /> - </arguments> - - <!-- Edit admin User data --> - <fillField selector="{{AdminEditUserSection.usernameTextField}}" userInput="{{adminUser}}" stepKey="fillUser"/> - <fillField selector="{{AdminEditUserSection.firstNameTextField}}" userInput="{{adminFirstname}}" stepKey="fillFirstName"/> - <fillField selector="{{AdminEditUserSection.lastNameTextField}}" userInput="{{adminLastname}}" stepKey="fillLastName"/> - <fillField selector="{{AdminEditUserSection.emailTextField}}" userInput="{{adminEmail}}" stepKey="fillEmail"/> - <fillField selector="{{AdminEditUserSection.passwordTextField}}" userInput="{{adminPassword}}" stepKey="fillPassword"/> - <fillField selector="{{AdminEditUserSection.pwConfirmationTextField}}" userInput="{{adminPasswordConfirmation}}" stepKey="fillPasswordConfirmation"/> - <fillField selector="{{AdminEditUserSection.currentPasswordField}}" userInput="{{currentAdminPassword}}" stepKey="fillCurrentUserPassword"/> - <scrollToTopOfPage stepKey="ScrollToTopOfPage"/> - - </actionGroup> -</actionGroups> diff --git a/app/code/Magento/User/Test/Mftf/ActionGroup/AdminUserEditSaveUserActionGroup.xml b/app/code/Magento/User/Test/Mftf/ActionGroup/AdminUserEditSaveUserActionGroup.xml deleted file mode 100644 index 1c733e1abb40a..0000000000000 --- a/app/code/Magento/User/Test/Mftf/ActionGroup/AdminUserEditSaveUserActionGroup.xml +++ /dev/null @@ -1,17 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="AdminUserEditSaveUserActionGroup"> - - <!-- Save User --> - <click selector="{{AdminEditUserSection.saveButton}}" stepKey="saveUser"/> - <waitForPageLoad stepKey="waitForSaveResultLoad"/> - - </actionGroup> -</actionGroups> diff --git a/app/code/Magento/User/Test/Mftf/Data/UserData.xml b/app/code/Magento/User/Test/Mftf/Data/UserData.xml index e665736ae28f1..d465851c62373 100644 --- a/app/code/Magento/User/Test/Mftf/Data/UserData.xml +++ b/app/code/Magento/User/Test/Mftf/Data/UserData.xml @@ -33,6 +33,23 @@ <item>1</item> </array> </entity> + <entity name="EditAdminUser" type="user"> + <data key="username" unique="suffix">admin</data> + <data key="firstname">John</data> + <data key="lastname">Doe</data> + <data key="email" unique="prefix">admin@example.com</data> + <data key="password">123123QA</data> + <data key="password_confirmation">123123QA</data> + <data key="interface_local">en_US</data> + <data key="interface_local_label">English (United States)</data> + <data key="is_active">true</data> + <data key="is_active_label">Active</data> + <data key="current_password">{{_ENV.MAGENTO_ADMIN_PASSWORD}}</data> + <data key="role">Administrators</data> + <array key="roles"> + <item>1</item> + </array> + </entity> <entity name="NewAdminUserWrongCurrentPassword" type="user"> <data key="username" unique="suffix">admin</data> <data key="firstname">John</data> @@ -50,6 +67,23 @@ <item>1</item> </array> </entity> + <entity name="EditAdminUserWrongCurrentPassword" type="user"> + <data key="username" unique="suffix">admin</data> + <data key="firstname">John</data> + <data key="lastname">Doe</data> + <data key="email" unique="prefix">admin@example.com</data> + <data key="password">123123QA</data> + <data key="password_confirmation">123123QA</data> + <data key="interface_local">en_US</data> + <data key="interface_local_label">English (United States)</data> + <data key="is_active">true</data> + <data key="is_active_label">Active</data> + <data key="current_password" unique="suffix">password_</data> + <data key="role">Administrators</data> + <array key="roles"> + <item>1</item> + </array> + </entity> <entity name="admin" type="user"> <data key="email">admin@magento.com</data> <data key="password">admin123</data> @@ -74,4 +108,11 @@ <item>1</item> </array> </entity> + +<!-- + Since User delete action is performed via POST request we created this entity to be able to delete it. + Please use "AdminDeleteUserViaCurlActionGroup". + See how it works: app/code/Magento/User/Test/Mftf/ActionGroup/AdminDeleteUserViaCurlActionGroup.xml +--> + <entity name="deleteUser" type="deleteUser" /> </entities> diff --git a/app/code/Magento/User/Test/Mftf/Metadata/user-meta.xml b/app/code/Magento/User/Test/Mftf/Metadata/user-meta.xml index 1ee29be6b3d76..2aa080c4ead09 100644 --- a/app/code/Magento/User/Test/Mftf/Metadata/user-meta.xml +++ b/app/code/Magento/User/Test/Mftf/Metadata/user-meta.xml @@ -23,4 +23,9 @@ <value>string</value> </array> </operation> + <operation name="DeleteUser" dataType="deleteUser" type="create" auth="adminFormKey" url="/admin/user/delete/" method="POST" successRegex="/messages-message-success/"> + <contentType>application/x-www-form-urlencoded</contentType> + <field key="current_password">string</field> + <field key="user_id">string</field> + </operation> </operations> diff --git a/app/code/Magento/User/Test/Mftf/Page/AdminEditUserPage.xml b/app/code/Magento/User/Test/Mftf/Page/AdminEditUserPage.xml index ae965fa1c48e7..c348a2ee79dbf 100644 --- a/app/code/Magento/User/Test/Mftf/Page/AdminEditUserPage.xml +++ b/app/code/Magento/User/Test/Mftf/Page/AdminEditUserPage.xml @@ -6,6 +6,13 @@ */ --> <pages xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/PageObject.xsd"> + +<!-- + Please do no use current Page because it has link to new user page. + Use AdminUserEditPage it has parameterized url where you can specicy User Id. + We do not update this page to maintain backward compatibility. +--> + <page name="AdminEditUserPage" url="admin/user/new" area="admin" module="Magento_User"> <section name="AdminEditUserSection"/> <section name="AdminEditUserRoleSection"/> diff --git a/app/code/Magento/User/Test/Mftf/Page/AdminUserEditPage.xml b/app/code/Magento/User/Test/Mftf/Page/AdminUserEditPage.xml new file mode 100644 index 0000000000000..2cdadd3694ecc --- /dev/null +++ b/app/code/Magento/User/Test/Mftf/Page/AdminUserEditPage.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<pages xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/PageObject.xsd"> + <page name="AdminUserEditPage" url="admin/user/edit/user_id/{{userId}}" area="admin" module="Magento_User" parameterized="true"> + <section name="AdminNewUserForm Section"/> + </page> +</pages> diff --git a/app/code/Magento/User/Test/Mftf/Page/AdminUsersPage.xml b/app/code/Magento/User/Test/Mftf/Page/AdminUsersPage.xml index ceb05ec7bd9c8..bae22792bdd2a 100644 --- a/app/code/Magento/User/Test/Mftf/Page/AdminUsersPage.xml +++ b/app/code/Magento/User/Test/Mftf/Page/AdminUsersPage.xml @@ -7,6 +7,7 @@ --> <pages xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/PageObject.xsd"> <page name="AdminUsersPage" url="admin/user/" area="admin" module="Magento_User"> - <section name="AdminUserGridSection"/> + <section name="AdminLegacyDataGridFilterSection"/> + <section name="AdminLegacyDataGridTableSection"/> </page> </pages> From 2b7691c2c88e6308169fe7ced08a09db2d387337 Mon Sep 17 00:00:00 2001 From: Viktor Petryk <victor.petryk@transoftgroup.com> Date: Mon, 20 May 2019 09:38:36 +0300 Subject: [PATCH 392/773] MC-16221: Cannot save Shipping Methods page because in UPS method have required fields --- .../system/shipping/carrier_config.phtml | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Ups/view/adminhtml/templates/system/shipping/carrier_config.phtml b/app/code/Magento/Ups/view/adminhtml/templates/system/shipping/carrier_config.phtml index c87c7f8c524fe..770583d04467e 100644 --- a/app/code/Magento/Ups/view/adminhtml/templates/system/shipping/carrier_config.phtml +++ b/app/code/Magento/Ups/view/adminhtml/templates/system/shipping/carrier_config.phtml @@ -67,6 +67,7 @@ require(["prototype"], function(){ upsXml.prototype = { initialize: function() { + this.carriersUpsActiveId = 'carriers_ups_active'; this.carriersUpsTypeId = 'carriers_ups_type'; if (!$(this.carriersUpsTypeId)) { return; @@ -94,6 +95,7 @@ require(["prototype"], function(){ this.setFormValues(); Event.observe($(this.carriersUpsTypeId), 'change', this.setFormValues.bind(this)); + Event.observe($(this.carriersUpsActiveId), 'change', this.setFormValues.bind(this)); }, updateAllowedMethods: function(originShipmentTitle) { @@ -121,7 +123,7 @@ require(["prototype"], function(){ freeMethod.insert(option); option = new Element('option', {value:code}).update(originShipment[code]); - if (this.storedUpsType == 'UPS_XML') { + if (this.storedUpsType == 'UPS') { if (originShipmentTitle != 'default' || inArray(this.storedAllowedMethods, code)) { option.selected = true; } @@ -143,12 +145,13 @@ require(["prototype"], function(){ setFormValues: function() { var a; - if ($F(this.carriersUpsTypeId) == 'UPS_XML') { + if ($F(this.carriersUpsTypeId) == 'UPS') { for (a = 0; a < this.checkingUpsXmlId.length; a++) { $(this.checkingUpsXmlId[a]).removeClassName('required-entry'); } for (a = 0; a < this.checkingUpsId.length; a++) { - $(this.checkingUpsXmlId[a]).addClassName('required-entry'); + $(this.checkingUpsId[a]).addClassName('required-entry'); + this.changeFieldsDisabledState(this.checkingUpsId, a); } Event.stopObserving($('carriers_ups_origin_shipment'), 'change', this.changeOriginShipment.bind(this)); showRowArrayElements(this.onlyUpsElements); @@ -157,9 +160,10 @@ require(["prototype"], function(){ } else { for (a = 0; a < this.checkingUpsXmlId.length; a++) { $(this.checkingUpsXmlId[a]).addClassName('required-entry'); + this.changeFieldsDisabledState(this.checkingUpsXmlId, a); } for (a = 0; a < this.checkingUpsId.length; a++) { - $(this.checkingUpsXmlId[a]).removeClassName('required-entry'); + $(this.checkingUpsId[a]).removeClassName('required-entry'); } Event.observe($('carriers_ups_origin_shipment'), 'change', this.changeOriginShipment.bind(this)); showRowArrayElements(this.onlyUpsXmlElements); @@ -171,6 +175,16 @@ require(["prototype"], function(){ { this.originShipmentTitle = key ? key : $F('carriers_ups_origin_shipment'); this.updateAllowedMethods(this.originShipmentTitle); + }, + changeFieldsDisabledState: function (fields, key) { + $(fields[key]).disabled = $F(this.carriersUpsActiveId) !== '1' + || $(fields[key] + '_inherit') !== null + && $F(fields[key] + '_inherit') === '1'; + + if ($(fields[key]).next() !== undefined) { + $(fields[key]).removeClassName('mage-error').next().remove(); + $(fields[key]).removeAttribute('style'); + } } }; xml = new upsXml(); From 407737fd030f7626204d8445869ed1062df31355 Mon Sep 17 00:00:00 2001 From: Ievgenii Gryshkun <i.gryshkun@gmail.com> Date: Mon, 20 May 2019 14:03:12 +0300 Subject: [PATCH 393/773] Links to the downloadable_product_samples are direct links --- .../Resolver/Product/DownloadableOptions.php | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/DownloadableGraphQl/Model/Resolver/Product/DownloadableOptions.php b/app/code/Magento/DownloadableGraphQl/Model/Resolver/Product/DownloadableOptions.php index a1e25663a9c3d..3d85553a15dc7 100644 --- a/app/code/Magento/DownloadableGraphQl/Model/Resolver/Product/DownloadableOptions.php +++ b/app/code/Magento/DownloadableGraphQl/Model/Resolver/Product/DownloadableOptions.php @@ -19,6 +19,8 @@ use Magento\Framework\GraphQl\Config\Element\Field; use Magento\Framework\GraphQl\Query\EnumLookup; use Magento\Framework\GraphQl\Query\ResolverInterface; +use Magento\Framework\App\ObjectManager; +use Magento\Framework\UrlInterface; /** * @inheritdoc @@ -47,22 +49,32 @@ class DownloadableOptions implements ResolverInterface */ private $linkCollection; + /** + * Downloadable file + * + * @var UrlInterface + */ + private $urlBuilder; + /** * @param EnumLookup $enumLookup * @param DownloadableHelper $downloadableHelper * @param SampleCollection $sampleCollection * @param LinkCollection $linkCollection + * @param File $downloadableFile */ public function __construct( EnumLookup $enumLookup, DownloadableHelper $downloadableHelper, SampleCollection $sampleCollection, - LinkCollection $linkCollection + LinkCollection $linkCollection, + UrlInterface $urlBuilder = null ) { $this->enumLookup = $enumLookup; $this->downloadableHelper = $downloadableHelper; $this->sampleCollection = $sampleCollection; $this->linkCollection = $linkCollection; + $this->urlBuilder = $urlBuilder ?: ObjectManager::getInstance()->get(UrlInterface::class); } /** @@ -165,7 +177,7 @@ private function formatSamples(Collection $samples) : array $resultData[$sampleKey]['sort_order'] = $sample->getSortOrder(); $resultData[$sampleKey]['sample_type'] = $this->enumLookup->getEnumValueFromField('DownloadableFileTypeEnum', $sample->getSampleType()); - $resultData[$sampleKey]['sample_file'] = $sample->getSampleFile(); + $resultData[$sampleKey]['sample_file'] = $this->urlBuilder->getUrl('downloadable/download/sample', ['sample_id' => $sample->getId()]); $resultData[$sampleKey]['sample_url'] = $sample->getSampleUrl(); } return $resultData; From 5973ab3131786addde8d52c2d90dd147b10d04dc Mon Sep 17 00:00:00 2001 From: Ievgenii Gryshkun <i.gryshkun@gmail.com> Date: Mon, 20 May 2019 14:20:31 +0300 Subject: [PATCH 394/773] Links to the downloadable_product_samples are direct links --- .../Model/Resolver/Product/DownloadableOptions.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/code/Magento/DownloadableGraphQl/Model/Resolver/Product/DownloadableOptions.php b/app/code/Magento/DownloadableGraphQl/Model/Resolver/Product/DownloadableOptions.php index 3d85553a15dc7..7f8a4532db3de 100644 --- a/app/code/Magento/DownloadableGraphQl/Model/Resolver/Product/DownloadableOptions.php +++ b/app/code/Magento/DownloadableGraphQl/Model/Resolver/Product/DownloadableOptions.php @@ -50,8 +50,6 @@ class DownloadableOptions implements ResolverInterface private $linkCollection; /** - * Downloadable file - * * @var UrlInterface */ private $urlBuilder; From d5ec99f0a0637726ed01b14baac805c00d2541ad Mon Sep 17 00:00:00 2001 From: Ievgenii Gryshkun <i.gryshkun@gmail.com> Date: Mon, 20 May 2019 14:20:59 +0300 Subject: [PATCH 395/773] Revert "Links to the downloadable_product_samples are direct links" This reverts commit 5973ab3131786addde8d52c2d90dd147b10d04dc. --- .../Model/Resolver/Product/DownloadableOptions.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/code/Magento/DownloadableGraphQl/Model/Resolver/Product/DownloadableOptions.php b/app/code/Magento/DownloadableGraphQl/Model/Resolver/Product/DownloadableOptions.php index 7f8a4532db3de..3d85553a15dc7 100644 --- a/app/code/Magento/DownloadableGraphQl/Model/Resolver/Product/DownloadableOptions.php +++ b/app/code/Magento/DownloadableGraphQl/Model/Resolver/Product/DownloadableOptions.php @@ -50,6 +50,8 @@ class DownloadableOptions implements ResolverInterface private $linkCollection; /** + * Downloadable file + * * @var UrlInterface */ private $urlBuilder; From f8f54701a6aec39d5cfc5e27f06e5f4954c8796c Mon Sep 17 00:00:00 2001 From: Ievgenii Gryshkun <i.gryshkun@gmail.com> Date: Mon, 20 May 2019 14:22:37 +0300 Subject: [PATCH 396/773] Links to the downloadable_product_samples are direct links --- .../Model/Resolver/Product/DownloadableOptions.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/code/Magento/DownloadableGraphQl/Model/Resolver/Product/DownloadableOptions.php b/app/code/Magento/DownloadableGraphQl/Model/Resolver/Product/DownloadableOptions.php index 3d85553a15dc7..b62e8d4984743 100644 --- a/app/code/Magento/DownloadableGraphQl/Model/Resolver/Product/DownloadableOptions.php +++ b/app/code/Magento/DownloadableGraphQl/Model/Resolver/Product/DownloadableOptions.php @@ -50,8 +50,6 @@ class DownloadableOptions implements ResolverInterface private $linkCollection; /** - * Downloadable file - * * @var UrlInterface */ private $urlBuilder; @@ -61,7 +59,7 @@ class DownloadableOptions implements ResolverInterface * @param DownloadableHelper $downloadableHelper * @param SampleCollection $sampleCollection * @param LinkCollection $linkCollection - * @param File $downloadableFile + * @param UrlInterface|null $urlBuilder */ public function __construct( EnumLookup $enumLookup, From d8e7d961e51224abe2732bfb2f9157d5db57a44d Mon Sep 17 00:00:00 2001 From: Daniel Renaud <drenaud@magento.com> Date: Mon, 20 May 2019 11:00:09 -0500 Subject: [PATCH 397/773] MC-16644: Configurable Product Result w/ UrlKey Filter --- .../Products/DataProvider/Product.php | 3 + .../MediaGalleryProcessor.php | 1 - .../ConfigurableProductQueryTest.php | 63 +++++++++++++++++++ 3 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/ConfigurableProductQueryTest.php diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Product.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Product.php index aed667695a748..7f1fd71942253 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Product.php +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Product.php @@ -86,6 +86,9 @@ public function getList( $collection->load(); // Methods that perform extra fetches post-load + if (in_array('media_gallery_entries', $attributes)) { + $collection->addMediaGalleryData(); + } if (in_array('options', $attributes)) { $collection->addOptionsToResult(); } diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Product/CollectionProcessor/MediaGalleryProcessor.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Product/CollectionProcessor/MediaGalleryProcessor.php index c34a198e48e80..be300e11f12ec 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Product/CollectionProcessor/MediaGalleryProcessor.php +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Product/CollectionProcessor/MediaGalleryProcessor.php @@ -49,7 +49,6 @@ public function process( $collection->addAttributeToSelect($mediaAttribute); } } - $collection->addMediaGalleryData(); } return $collection; diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/ConfigurableProductQueryTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/ConfigurableProductQueryTest.php new file mode 100644 index 0000000000000..6de803c19e699 --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/ConfigurableProductQueryTest.php @@ -0,0 +1,63 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQl\ConfigurableProduct; + +use Magento\TestFramework\TestCase\GraphQlAbstract; + +/** + * Test configurable product queries work correctly + */ +class ConfigurableProductQueryTest extends GraphQlAbstract +{ + + /** + * @magentoApiDataFixture Magento/ConfigurableProduct/_files/product_configurable.php + */ + public function testNonVisibleVariationsNotReturned() + { + $categoryId = '2'; + $query = <<<QUERY +{ + products(filter: {category_id: {eq: "{$categoryId}"}}) { + items { + __typename + sku + name + url_key + price { + regularPrice { + amount { + currency + value + } + } + } + media_gallery_entries { + media_type + label + position + file + id + types + } + description { + html + } + } + } +} +QUERY; + + $result = $this->graphQlQuery($query); + $products = $result['products']['items']; + $this->assertCount(1, $products); + $this->assertEquals('ConfigurableProduct', $products[0]['__typename']); + $this->assertEquals('configurable', $products[0]['sku']); + $this->assertArrayHasKey('media_gallery_entries', $products[0]); + } +} From 03d3596414229c52b85bfbe3633ef91fbc941b65 Mon Sep 17 00:00:00 2001 From: Mila Lesechko <llesechk@adobe.com> Date: Mon, 20 May 2019 16:09:19 -0500 Subject: [PATCH 398/773] MC-4767: Convert PrintOrderFrontendGuestTest to MFTF --- .../ActionGroup/AdminAddToOrderBundleProductActionGroup.xml | 4 ++++ .../AdminAddToOrderConfigurableProductActionGroup.xml | 4 ++++ .../Mftf/ActionGroup/AdminAddToOrderCouponCodeActionGroup.xml | 4 ++++ .../AdminAddToOrderDownloadableProductActionGroup.xml | 4 ++++ .../AdminFilterProductInCreateOrderActionGroup.xml | 4 ++++ ...orefrontAssertSalesPrintOrderBillingAddressActionGroup.xml | 4 ++++ .../StorefrontFillOrdersAndReturnsFormActionGroup.xml | 4 ++++ 7 files changed, 28 insertions(+) diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAddToOrderBundleProductActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAddToOrderBundleProductActionGroup.xml index 2791a59071535..c979dd883b175 100644 --- a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAddToOrderBundleProductActionGroup.xml +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAddToOrderBundleProductActionGroup.xml @@ -9,6 +9,10 @@ <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="AdminAddToOrderBundleProductActionGroup"> + <annotations> + <description>Configuration added Bundle Product during creation order by Admin: select bundle option and product with quantity</description> + <page>AdminOrderCreatePage</page> + </annotations> <arguments> <argument name="option" type="string"/> <argument name="selectedProduct" type="entity"/> diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAddToOrderConfigurableProductActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAddToOrderConfigurableProductActionGroup.xml index 33378a9fa58cc..9d824cfa2be5a 100644 --- a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAddToOrderConfigurableProductActionGroup.xml +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAddToOrderConfigurableProductActionGroup.xml @@ -9,6 +9,10 @@ <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="AdminAddToOrderConfigurableProductActionGroup"> + <annotations> + <description>Configuration added Configurable Product during creation order by Admin: select option by attribute and quantity</description> + <page>AdminOrderCreatePage</page> + </annotations> <arguments> <argument name="attribute" type="string"/> <argument name="option" type="string"/> diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAddToOrderCouponCodeActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAddToOrderCouponCodeActionGroup.xml index 457a63efe07d2..415d2036722cc 100644 --- a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAddToOrderCouponCodeActionGroup.xml +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAddToOrderCouponCodeActionGroup.xml @@ -9,6 +9,10 @@ <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="AdminAddToOrderCouponCodeActionGroup"> + <annotations> + <description>Add and apply Coupon Code to order during creating order by Admin</description> + <page>AdminOrderCreatePage</page> + </annotations> <arguments> <argument name="coupon" type="entity"/> </arguments> diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAddToOrderDownloadableProductActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAddToOrderDownloadableProductActionGroup.xml index ec427fb9b6779..e2a49878202a8 100644 --- a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAddToOrderDownloadableProductActionGroup.xml +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAddToOrderDownloadableProductActionGroup.xml @@ -9,6 +9,10 @@ <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="AdminAddToOrderDownloadableProductActionGroup"> + <annotations> + <description>Configuration added Downloadable Product during creation order by Admin: select link and quantity</description> + <page>AdminOrderCreatePage</page> + </annotations> <arguments> <argument name="link" type="string"/> <argument name="quantity" type="string" defaultValue="1"/> diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminFilterProductInCreateOrderActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminFilterProductInCreateOrderActionGroup.xml index 58d23f4b06bbc..baa8a8f5348b7 100644 --- a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminFilterProductInCreateOrderActionGroup.xml +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminFilterProductInCreateOrderActionGroup.xml @@ -9,6 +9,10 @@ <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="AdminFilterProductInCreateOrderActionGroup"> + <annotations> + <description>Search product in product grid on create order by admin page</description> + <page>AdminOrderCreatePage</page> + </annotations> <arguments> <argument name="productSKU" type="string"/> </arguments> diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/StorefrontAssertSalesPrintOrderBillingAddressActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/StorefrontAssertSalesPrintOrderBillingAddressActionGroup.xml index fe7e0064e5c5e..0a92d38d65a82 100644 --- a/app/code/Magento/Sales/Test/Mftf/ActionGroup/StorefrontAssertSalesPrintOrderBillingAddressActionGroup.xml +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/StorefrontAssertSalesPrintOrderBillingAddressActionGroup.xml @@ -9,6 +9,10 @@ <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="AssertSalesPrintOrderBillingAddress"> + <annotations> + <description>Assert billing address data on printed order</description> + <page>StorefrontPrintOrderPage</page> + </annotations> <arguments> <argument name="address" type="entity"/> </arguments> diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/StorefrontFillOrdersAndReturnsFormActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/StorefrontFillOrdersAndReturnsFormActionGroup.xml index a3c0edf148126..6ce933762a692 100644 --- a/app/code/Magento/Sales/Test/Mftf/ActionGroup/StorefrontFillOrdersAndReturnsFormActionGroup.xml +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/StorefrontFillOrdersAndReturnsFormActionGroup.xml @@ -9,6 +9,10 @@ <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="StorefrontFillOrdersAndReturnsFormActionGroup"> + <annotations> + <description>Fill order information in form "Orders and Returns"</description> + <page>StorefrontGuestOrderSearchPage</page> + </annotations> <arguments> <argument name="orderNumber" type="string"/> <argument name="customer" type="entity" defaultValue="$$createCustomer$$"/> From 9d291a38ef976fb74099e037bd21e774ab3e6f33 Mon Sep 17 00:00:00 2001 From: Viktor Sevch <svitja@ukr.net> Date: Tue, 21 May 2019 14:25:56 +0300 Subject: [PATCH 399/773] MC-16338: [FT] CancelWorldpayCheckoutTest fails on Bamboo --- .../AssertCancelSuccessMessageInShoppingCart.php | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) 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 index 1333a07b3e1fc..ae6e476203e4a 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertCancelSuccessMessageInShoppingCart.php +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertCancelSuccessMessageInShoppingCart.php @@ -8,6 +8,7 @@ use Magento\Checkout\Test\Page\CheckoutCart; use Magento\Mtf\Constraint\AbstractConstraint; +use Magento\Mtf\Client\BrowserInterface; /** * Assert that success message about canceled order is present and correct. @@ -23,10 +24,18 @@ class AssertCancelSuccessMessageInShoppingCart extends AbstractConstraint * Assert that success message about canceled order is present and correct. * * @param CheckoutCart $checkoutCart + * @param BrowserInterface $browser * @return void */ - public function processAssert(CheckoutCart $checkoutCart) + public function processAssert(CheckoutCart $checkoutCart, BrowserInterface $browser) { + $path = $checkoutCart::MCA; + $browser->waitUntil( + function () use ($browser, $path) { + return $_ENV['app_frontend_url'] . $path . '/' === $browser->getUrl() . 'index/' ? true : null; + } + ); + $actualMessage = $checkoutCart->getMessagesBlock()->getSuccessMessage(); \PHPUnit\Framework\Assert::assertEquals( self::SUCCESS_MESSAGE, From 1f95f30eb65aadb6e00aca63fdf1188377a9fa95 Mon Sep 17 00:00:00 2001 From: Serhii Voloshkov <serhii.voloshkov@transoftgroup.com> Date: Tue, 21 May 2019 15:33:52 +0300 Subject: [PATCH 400/773] MC-16388: [FT] Magento\Checkout\Test\TestCase\OnePageCheckoutDeclinedTest fails --- .../Paypal/Test/TestCase/OnePageCheckoutDeclinedTest.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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 index d4f75f483d725..c5ffa5bf0fccd 100644 --- a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/OnePageCheckoutDeclinedTest.xml +++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/OnePageCheckoutDeclinedTest.xml @@ -18,7 +18,7 @@ <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">A server error stopped your order from being placed. Please try to place your order again.</data> + <data name="expectedErrorMessage" xsi:type="string">Transaction has been declined</data> <constraint name="Magento\Checkout\Test\Constraint\AssertCheckoutErrorMessage" /> </variation> <variation name="OnePageCheckoutDeclinedTestWithAVSZIP" summary="Place order via Payflow Pro with AVS ZIP verification fail" ticketId="MAGETWO-37483"> @@ -30,7 +30,7 @@ <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="expectedErrorMessage" xsi:type="string">A server error stopped your order from being placed. Please try to place your order again.</data> + <data name="expectedErrorMessage" xsi:type="string">Transaction has been declined</data> <data name="configData" xsi:type="string">payflowpro, payflowpro_use_avs_zip</data> <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S1</data> <constraint name="Magento\Checkout\Test\Constraint\AssertCheckoutErrorMessage" /> @@ -46,7 +46,7 @@ <data name="payment/method" xsi:type="string">payflowpro</data> <data name="creditCard/dataset" xsi:type="string">visa_cvv_mismatch</data> <data name="configData" xsi:type="string">payflowpro, payflowpro_avs_security_code_does_not_match</data> - <data name="expectedErrorMessage" xsi:type="string">A server error stopped your order from being placed. Please try to place your order again.</data> + <data name="expectedErrorMessage" xsi:type="string">Transaction has been declined</data> <constraint name="Magento\Checkout\Test\Constraint\AssertCheckoutErrorMessage" /> </variation> </testCase> From 9ab466d8569ea556cb01393989579c3aac53d9a3 Mon Sep 17 00:00:00 2001 From: Vitaliy Honcharenko <vgoncharenko@magento.com> Date: Thu, 16 May 2019 13:37:13 -0500 Subject: [PATCH 401/773] MC-16239: Search result page contain 24k results --- app/code/Magento/Backend/Block/Context.php | 9 +- .../Backend/Block/Template/Context.php | 5 + .../Magento/Backend/Block/Widget/Context.php | 5 + .../Magento/Catalog/Block/Product/Context.php | 29 ++++ .../Model/AddStockStatusToCollection.php | 16 +-- .../CatalogInventory/Model/Plugin/Layer.php | 92 ------------ .../Test/Unit/Model/Plugin/LayerTest.php | 106 -------------- .../Magento/CatalogInventory/composer.json | 1 - app/code/Magento/CatalogInventory/etc/di.xml | 3 - ...oductCollectionPrepareStrategyProvider.php | 2 +- .../Indexer/Fulltext/Action/DataProvider.php | 77 ++++++++++ .../ResourceModel/Advanced/Collection.php | 30 ++-- .../ResourceModel/Fulltext/Collection.php | 49 ++++--- .../DefaultFilterStrategyApplyChecker.php | 24 ++++ ...ultFilterStrategyApplyCheckerInterface.php | 21 +++ .../Model/Search/ItemCollectionProvider.php | 2 +- app/code/Magento/CatalogSearch/etc/di.xml | 2 + .../SearchAdapter/Query/Builder.php | 2 +- .../Product/FieldProvider/DynamicField.php | 2 +- .../Plugin/StockedProductsFilterPlugin.php | 94 ------------ .../DefaultFilterStrategyApplyChecker.php | 26 ++++ .../SearchAdapter/Query/Builder.php | 37 ++++- .../SearchAdapter/Query/Builder/Sort.php | 7 + .../StockedProductsFilterPluginTest.php | 134 ------------------ app/code/Magento/Elasticsearch/etc/di.xml | 6 +- .../Indexer/Fulltext/Action/FullTest.php | 8 +- .../Magento/Framework/Search/Request.php | 8 +- .../Framework/Search/RequestInterface.php | 7 - .../Search/Response/QueryResponse.php | 9 +- .../Framework/Search/ResponseInterface.php | 7 - .../Search/SearchResponseBuilder.php | 5 +- .../Framework/View/Element/AbstractBlock.php | 12 +- .../Framework/View/Element/Context.php | 25 +++- .../View/Element/Template/Context.php | 9 +- .../Test/Unit/Element/AbstractBlockTest.php | 4 +- 35 files changed, 357 insertions(+), 518 deletions(-) delete mode 100644 app/code/Magento/CatalogInventory/Model/Plugin/Layer.php delete mode 100644 app/code/Magento/CatalogInventory/Test/Unit/Model/Plugin/LayerTest.php create mode 100644 app/code/Magento/CatalogSearch/Model/ResourceModel/Fulltext/Collection/DefaultFilterStrategyApplyChecker.php create mode 100644 app/code/Magento/CatalogSearch/Model/ResourceModel/Fulltext/Collection/DefaultFilterStrategyApplyCheckerInterface.php delete mode 100644 app/code/Magento/Elasticsearch/Model/Indexer/Plugin/StockedProductsFilterPlugin.php create mode 100644 app/code/Magento/Elasticsearch/Model/ResourceModel/Fulltext/Collection/DefaultFilterStrategyApplyChecker.php delete mode 100644 app/code/Magento/Elasticsearch/Test/Unit/Model/Indexer/Plugin/StockedProductsFilterPluginTest.php diff --git a/app/code/Magento/Backend/Block/Context.php b/app/code/Magento/Backend/Block/Context.php index d05cdc5fff5a3..5c142415fefdb 100644 --- a/app/code/Magento/Backend/Block/Context.php +++ b/app/code/Magento/Backend/Block/Context.php @@ -5,6 +5,8 @@ */ namespace Magento\Backend\Block; +use Magento\Framework\Cache\LockGuardedCacheLoader; + /** * Constructor modification point for Magento\Backend\Block\AbstractBlock. * @@ -44,8 +46,9 @@ class Context extends \Magento\Framework\View\Element\Context * @param \Magento\Framework\Escaper $escaper * @param \Magento\Framework\Filter\FilterManager $filterManager * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate - * @param \Magento\Framework\AuthorizationInterface $authorization * @param \Magento\Framework\Translate\Inline\StateInterface $inlineTranslation + * @param LockGuardedCacheLoader $lockQuery + * @param \Magento\Framework\AuthorizationInterface $authorization * * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -67,6 +70,7 @@ public function __construct( \Magento\Framework\Filter\FilterManager $filterManager, \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate, \Magento\Framework\Translate\Inline\StateInterface $inlineTranslation, + LockGuardedCacheLoader $lockQuery, \Magento\Framework\AuthorizationInterface $authorization ) { $this->_authorization = $authorization; @@ -87,7 +91,8 @@ public function __construct( $escaper, $filterManager, $localeDate, - $inlineTranslation + $inlineTranslation, + $lockQuery ); } diff --git a/app/code/Magento/Backend/Block/Template/Context.php b/app/code/Magento/Backend/Block/Template/Context.php index 27c777c6d4009..5d345a5a8b67e 100644 --- a/app/code/Magento/Backend/Block/Template/Context.php +++ b/app/code/Magento/Backend/Block/Template/Context.php @@ -5,6 +5,8 @@ */ namespace Magento\Backend\Block\Template; +use Magento\Framework\Cache\LockGuardedCacheLoader; + /** * Constructor modification point for Magento\Backend\Block\Template. * @@ -72,6 +74,7 @@ class Context extends \Magento\Framework\View\Element\Template\Context * @param \Magento\Framework\Filter\FilterManager $filterManager * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate * @param \Magento\Framework\Translate\Inline\StateInterface $inlineTranslation + * @param LockGuardedCacheLoader $lockQuery * @param \Magento\Framework\Filesystem $filesystem * @param \Magento\Framework\View\FileSystem $viewFileSystem * @param \Magento\Framework\View\TemplateEnginePool $enginePool @@ -106,6 +109,7 @@ public function __construct( \Magento\Framework\Filter\FilterManager $filterManager, \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate, \Magento\Framework\Translate\Inline\StateInterface $inlineTranslation, + LockGuardedCacheLoader $lockQuery, \Magento\Framework\Filesystem $filesystem, \Magento\Framework\View\FileSystem $viewFileSystem, \Magento\Framework\View\TemplateEnginePool $enginePool, @@ -143,6 +147,7 @@ public function __construct( $filterManager, $localeDate, $inlineTranslation, + $lockQuery, $filesystem, $viewFileSystem, $enginePool, diff --git a/app/code/Magento/Backend/Block/Widget/Context.php b/app/code/Magento/Backend/Block/Widget/Context.php index bfeb86214d33e..27274164a0b5b 100644 --- a/app/code/Magento/Backend/Block/Widget/Context.php +++ b/app/code/Magento/Backend/Block/Widget/Context.php @@ -5,6 +5,8 @@ */ namespace Magento\Backend\Block\Widget; +use Magento\Framework\Cache\LockGuardedCacheLoader; + /** * Constructor modification point for Magento\Backend\Block\Widget. * @@ -55,6 +57,7 @@ class Context extends \Magento\Backend\Block\Template\Context * @param \Magento\Framework\Filter\FilterManager $filterManager * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate * @param \Magento\Framework\Translate\Inline\StateInterface $inlineTranslation + * @param LockGuardedCacheLoader $lockQuery * @param \Magento\Framework\Filesystem $filesystem * @param \Magento\Framework\View\FileSystem $viewFileSystem * @param \Magento\Framework\View\TemplateEnginePool $enginePool @@ -91,6 +94,7 @@ public function __construct( \Magento\Framework\Filter\FilterManager $filterManager, \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate, \Magento\Framework\Translate\Inline\StateInterface $inlineTranslation, + LockGuardedCacheLoader $lockQuery, \Magento\Framework\Filesystem $filesystem, \Magento\Framework\View\FileSystem $viewFileSystem, \Magento\Framework\View\TemplateEnginePool $enginePool, @@ -125,6 +129,7 @@ public function __construct( $filterManager, $localeDate, $inlineTranslation, + $lockQuery, $filesystem, $viewFileSystem, $enginePool, diff --git a/app/code/Magento/Catalog/Block/Product/Context.php b/app/code/Magento/Catalog/Block/Product/Context.php index 4ca9e6b290bb5..82dd8b2262736 100644 --- a/app/code/Magento/Catalog/Block/Product/Context.php +++ b/app/code/Magento/Catalog/Block/Product/Context.php @@ -5,6 +5,8 @@ */ namespace Magento\Catalog\Block\Product; +use Magento\Framework\Cache\LockGuardedCacheLoader; + /** * Constructor modification point for Magento\Catalog\Block\Product\AbstractProduct. * @@ -104,6 +106,7 @@ class Context extends \Magento\Framework\View\Element\Template\Context * @param \Magento\Framework\Filter\FilterManager $filterManager * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate * @param \Magento\Framework\Translate\Inline\StateInterface $inlineTranslation + * @param LockGuardedCacheLoader $lockQuery * @param \Magento\Framework\Filesystem $filesystem * @param \Magento\Framework\View\FileSystem $viewFileSystem * @param \Magento\Framework\View\TemplateEnginePool $enginePool @@ -145,6 +148,7 @@ public function __construct( \Magento\Framework\Filter\FilterManager $filterManager, \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate, \Magento\Framework\Translate\Inline\StateInterface $inlineTranslation, + LockGuardedCacheLoader $lockQuery, \Magento\Framework\Filesystem $filesystem, \Magento\Framework\View\FileSystem $viewFileSystem, \Magento\Framework\View\TemplateEnginePool $enginePool, @@ -196,6 +200,7 @@ public function __construct( $filterManager, $localeDate, $inlineTranslation, + $lockQuery, $filesystem, $viewFileSystem, $enginePool, @@ -208,6 +213,8 @@ public function __construct( } /** + * Get Stock registry. + * * @return \Magento\CatalogInventory\Api\StockRegistryInterface */ public function getStockRegistry() @@ -216,6 +223,8 @@ public function getStockRegistry() } /** + * Get cart helper. + * * @return \Magento\Checkout\Helper\Cart */ public function getCartHelper() @@ -224,6 +233,8 @@ public function getCartHelper() } /** + * Get catalog config. + * * @return \Magento\Catalog\Model\Config */ public function getCatalogConfig() @@ -232,6 +243,8 @@ public function getCatalogConfig() } /** + * Get catalog helper. + * * @return \Magento\Catalog\Helper\Data */ public function getCatalogHelper() @@ -240,6 +253,8 @@ public function getCatalogHelper() } /** + * Get compare product. + * * @return \Magento\Catalog\Helper\Product\Compare */ public function getCompareProduct() @@ -248,6 +263,8 @@ public function getCompareProduct() } /** + * Get image helper. + * * @return \Magento\Catalog\Helper\Image */ public function getImageHelper() @@ -256,6 +273,8 @@ public function getImageHelper() } /** + * Get image builder. + * * @return \Magento\Catalog\Block\Product\ImageBuilder */ public function getImageBuilder() @@ -264,6 +283,8 @@ public function getImageBuilder() } /** + * Get math random. + * * @return \Magento\Framework\Math\Random */ public function getMathRandom() @@ -272,6 +293,8 @@ public function getMathRandom() } /** + * Get registry. + * * @return \Magento\Framework\Registry */ public function getRegistry() @@ -280,6 +303,8 @@ public function getRegistry() } /** + * Get tax data. + * * @return \Magento\Tax\Helper\Data */ public function getTaxData() @@ -288,6 +313,8 @@ public function getTaxData() } /** + * Get wishlist helper. + * * @return \Magento\Wishlist\Helper\Data */ public function getWishlistHelper() @@ -296,6 +323,8 @@ public function getWishlistHelper() } /** + * Get review renderer. + * * @return \Magento\Catalog\Block\Product\ReviewRendererInterface */ public function getReviewRenderer() diff --git a/app/code/Magento/CatalogInventory/Model/AddStockStatusToCollection.php b/app/code/Magento/CatalogInventory/Model/AddStockStatusToCollection.php index 0a02d4eb6a9a6..6f3e40b622f42 100644 --- a/app/code/Magento/CatalogInventory/Model/AddStockStatusToCollection.php +++ b/app/code/Magento/CatalogInventory/Model/AddStockStatusToCollection.php @@ -7,8 +7,6 @@ namespace Magento\CatalogInventory\Model; use Magento\Catalog\Model\ResourceModel\Product\Collection; -use Magento\Framework\Search\EngineResolverInterface; -use Magento\Search\Model\EngineResolver; /** * Catalog inventory module plugin @@ -20,21 +18,13 @@ class AddStockStatusToCollection */ protected $stockHelper; - /** - * @var EngineResolverInterface - */ - private $engineResolver; - /** * @param \Magento\CatalogInventory\Helper\Stock $stockHelper - * @param EngineResolverInterface $engineResolver */ public function __construct( - \Magento\CatalogInventory\Helper\Stock $stockHelper, - EngineResolverInterface $engineResolver + \Magento\CatalogInventory\Helper\Stock $stockHelper ) { $this->stockHelper = $stockHelper; - $this->engineResolver = $engineResolver; } /** @@ -47,9 +37,7 @@ public function __construct( */ public function beforeLoad(Collection $productCollection, $printQuery = false, $logQuery = false) { - if ($this->engineResolver->getCurrentSearchEngine() === EngineResolver::CATALOG_SEARCH_MYSQL_ENGINE) { - $this->stockHelper->addIsInStockFilterToCollection($productCollection); - } + $this->stockHelper->addIsInStockFilterToCollection($productCollection); return [$printQuery, $logQuery]; } } diff --git a/app/code/Magento/CatalogInventory/Model/Plugin/Layer.php b/app/code/Magento/CatalogInventory/Model/Plugin/Layer.php deleted file mode 100644 index 168e947b8fa57..0000000000000 --- a/app/code/Magento/CatalogInventory/Model/Plugin/Layer.php +++ /dev/null @@ -1,92 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -namespace Magento\CatalogInventory\Model\Plugin; - -use Magento\Framework\Search\EngineResolverInterface; -use Magento\Search\Model\EngineResolver; - -/** - * Catalog inventory plugin for layer. - */ -class Layer -{ - /** - * Stock status instance - * - * @var \Magento\CatalogInventory\Helper\Stock - */ - protected $stockHelper; - - /** - * Store config instance - * - * @var \Magento\Framework\App\Config\ScopeConfigInterface - */ - protected $scopeConfig; - - /** - * @var EngineResolverInterface - */ - private $engineResolver; - - /** - * @param \Magento\CatalogInventory\Helper\Stock $stockHelper - * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig - * @param EngineResolverInterface $engineResolver - */ - public function __construct( - \Magento\CatalogInventory\Helper\Stock $stockHelper, - \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig, - EngineResolverInterface $engineResolver - ) { - $this->stockHelper = $stockHelper; - $this->scopeConfig = $scopeConfig; - $this->engineResolver = $engineResolver; - } - - /** - * Before prepare product collection handler - * - * @param \Magento\Catalog\Model\Layer $subject - * @param \Magento\Catalog\Model\ResourceModel\Collection\AbstractCollection $collection - * - * @return void - * @SuppressWarnings(PHPMD.UnusedFormalParameter) - */ - public function beforePrepareProductCollection( - \Magento\Catalog\Model\Layer $subject, - \Magento\Catalog\Model\ResourceModel\Collection\AbstractCollection $collection - ) { - if (!$this->isCurrentEngineMysql() || $this->_isEnabledShowOutOfStock()) { - return; - } - $this->stockHelper->addIsInStockFilterToCollection($collection); - } - - /** - * Check if current engine is MYSQL. - * - * @return bool - */ - private function isCurrentEngineMysql() - { - return $this->engineResolver->getCurrentSearchEngine() === EngineResolver::CATALOG_SEARCH_MYSQL_ENGINE; - } - - /** - * Get config value for 'display out of stock' option - * - * @return bool - */ - protected function _isEnabledShowOutOfStock() - { - return $this->scopeConfig->isSetFlag( - 'cataloginventory/options/show_out_of_stock', - \Magento\Store\Model\ScopeInterface::SCOPE_STORE - ); - } -} diff --git a/app/code/Magento/CatalogInventory/Test/Unit/Model/Plugin/LayerTest.php b/app/code/Magento/CatalogInventory/Test/Unit/Model/Plugin/LayerTest.php deleted file mode 100644 index b64563a35176d..0000000000000 --- a/app/code/Magento/CatalogInventory/Test/Unit/Model/Plugin/LayerTest.php +++ /dev/null @@ -1,106 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\CatalogInventory\Test\Unit\Model\Plugin; - -use Magento\Framework\Search\EngineResolverInterface; - -class LayerTest extends \PHPUnit\Framework\TestCase -{ - /** - * @var \Magento\CatalogInventory\Model\Plugin\Layer - */ - protected $_model; - - /** - * @var \Magento\Framework\App\Config\ScopeConfigInterface|\PHPUnit_Framework_MockObject_MockObject - */ - protected $_scopeConfigMock; - - /** - * @var \Magento\CatalogInventory\Helper\Stock|\PHPUnit_Framework_MockObject_MockObject - */ - protected $_stockHelperMock; - - /** - * @var EngineResolverInterface|\PHPUnit_Framework_MockObject_MockObject - */ - private $engineResolver; - - protected function setUp() - { - $this->_scopeConfigMock = $this->createMock(\Magento\Framework\App\Config\ScopeConfigInterface::class); - $this->_stockHelperMock = $this->createMock(\Magento\CatalogInventory\Helper\Stock::class); - $this->engineResolver = $this->getMockBuilder(EngineResolverInterface::class) - ->disableOriginalConstructor() - ->setMethods(['getCurrentSearchEngine']) - ->getMockForAbstractClass(); - - $this->_model = new \Magento\CatalogInventory\Model\Plugin\Layer( - $this->_stockHelperMock, - $this->_scopeConfigMock, - $this->engineResolver - ); - } - - /** - * Test add stock status to collection with disabled 'display out of stock' option - */ - public function testAddStockStatusDisabledShow() - { - $this->engineResolver->expects($this->any()) - ->method('getCurrentSearchEngine') - ->willReturn('mysql'); - - $this->_scopeConfigMock->expects( - $this->once() - )->method( - 'isSetFlag' - )->with( - 'cataloginventory/options/show_out_of_stock' - )->will( - $this->returnValue(true) - ); - /** @var \Magento\Catalog\Model\ResourceModel\Product\Collection $collectionMock */ - $collectionMock = $this->createMock(\Magento\Catalog\Model\ResourceModel\Product\Collection::class); - $this->_stockHelperMock->expects($this->never())->method('addIsInStockFilterToCollection'); - /** @var \Magento\Catalog\Model\Layer $subjectMock */ - $subjectMock = $this->createMock(\Magento\Catalog\Model\Layer::class); - $this->_model->beforePrepareProductCollection($subjectMock, $collectionMock); - } - - /** - * Test add stock status to collection with 'display out of stock' option enabled - */ - public function testAddStockStatusEnabledShow() - { - $this->engineResolver->expects($this->any()) - ->method('getCurrentSearchEngine') - ->willReturn('mysql'); - - $this->_scopeConfigMock->expects( - $this->once() - )->method( - 'isSetFlag' - )->with( - 'cataloginventory/options/show_out_of_stock' - )->will( - $this->returnValue(false) - ); - - $collectionMock = $this->createMock(\Magento\Catalog\Model\ResourceModel\Product\Collection::class); - - $this->_stockHelperMock->expects( - $this->once() - )->method( - 'addIsInStockFilterToCollection' - )->with( - $collectionMock - ); - - $subjectMock = $this->createMock(\Magento\Catalog\Model\Layer::class); - $this->_model->beforePrepareProductCollection($subjectMock, $collectionMock); - } -} diff --git a/app/code/Magento/CatalogInventory/composer.json b/app/code/Magento/CatalogInventory/composer.json index eb6239ea87ef0..007d744b2296f 100644 --- a/app/code/Magento/CatalogInventory/composer.json +++ b/app/code/Magento/CatalogInventory/composer.json @@ -8,7 +8,6 @@ "php": "~7.1.3||~7.2.0", "magento/framework": "*", "magento/module-catalog": "*", - "magento/module-search": "*", "magento/module-config": "*", "magento/module-customer": "*", "magento/module-eav": "*", diff --git a/app/code/Magento/CatalogInventory/etc/di.xml b/app/code/Magento/CatalogInventory/etc/di.xml index e7d79c593b8c7..78a0c2b734315 100644 --- a/app/code/Magento/CatalogInventory/etc/di.xml +++ b/app/code/Magento/CatalogInventory/etc/di.xml @@ -47,9 +47,6 @@ <argument name="resourceStockItem" xsi:type="object">Magento\CatalogInventory\Model\ResourceModel\Stock\Item\Proxy</argument> </arguments> </type> - <type name="Magento\Catalog\Model\Layer"> - <plugin name="addStockStatusOnPrepareFrontCollection" type="Magento\CatalogInventory\Model\Plugin\Layer"/> - </type> <type name="Magento\Framework\Module\Setup\Migration"> <arguments> <argument name="compositeModules" xsi:type="array"> diff --git a/app/code/Magento/CatalogSearch/Model/Advanced/ProductCollectionPrepareStrategyProvider.php b/app/code/Magento/CatalogSearch/Model/Advanced/ProductCollectionPrepareStrategyProvider.php index 6e963ea1aa8ac..8527ef56c509b 100644 --- a/app/code/Magento/CatalogSearch/Model/Advanced/ProductCollectionPrepareStrategyProvider.php +++ b/app/code/Magento/CatalogSearch/Model/Advanced/ProductCollectionPrepareStrategyProvider.php @@ -42,7 +42,7 @@ public function __construct( public function getStrategy(): ProductCollectionPrepareStrategyInterface { if (!isset($this->strategies[$this->engineResolver->getCurrentSearchEngine()])) { - throw new \DomainException('Undefined strategy ' . $this->engineResolver->getCurrentSearchEngine()); + return $this->strategies['default']; } return $this->strategies[$this->engineResolver->getCurrentSearchEngine()]; } diff --git a/app/code/Magento/CatalogSearch/Model/Indexer/Fulltext/Action/DataProvider.php b/app/code/Magento/CatalogSearch/Model/Indexer/Fulltext/Action/DataProvider.php index 39cb95747c2cf..0967d7fad384b 100644 --- a/app/code/Magento/CatalogSearch/Model/Indexer/Fulltext/Action/DataProvider.php +++ b/app/code/Magento/CatalogSearch/Model/Indexer/Fulltext/Action/DataProvider.php @@ -7,9 +7,14 @@ use Magento\Catalog\Api\Data\ProductInterface; use Magento\Catalog\Model\Product\Attribute\Source\Status; +use Magento\CatalogInventory\Api\Data\StockStatusInterface; +use Magento\CatalogInventory\Api\StockConfigurationInterface; +use Magento\CatalogInventory\Api\StockStatusCriteriaInterface; +use Magento\CatalogInventory\Api\StockStatusRepositoryInterface; use Magento\Framework\App\ResourceConnection; use Magento\Framework\DB\Select; use Magento\Store\Model\Store; +use Magento\Framework\App\ObjectManager; /** * Catalog search full test search data provider. @@ -124,6 +129,16 @@ class DataProvider */ private $antiGapMultiplier; + /** + * @var StockConfigurationInterface + */ + private $stockConfiguration; + + /** + * @var StockStatusRepositoryInterface + */ + private $stockStatusRepository; + /** * @param ResourceConnection $resource * @param \Magento\Catalog\Model\Product\Type $catalogProductType @@ -548,6 +563,8 @@ public function prepareProductIndex($indexData, $productData, $storeId) { $index = []; + $indexData = $this->filterOutOfStockProducts($indexData, $storeId); + foreach ($this->getSearchableAttributes('static') as $attribute) { $attributeCode = $attribute->getAttributeCode(); @@ -670,4 +687,64 @@ private function filterAttributeValue($value) { return preg_replace('/\s+/iu', ' ', trim(strip_tags($value))); } + + /** + * Filter out of stock products for products. + * + * @param array $indexData + * @param int $storeId + * @return array + */ + private function filterOutOfStockProducts($indexData, $storeId): array + { + if (!$this->getStockConfiguration()->isShowOutOfStock($storeId)) { + $productIds = array_keys($indexData); + $stockStatusCriteria = $this->createStockStatusCriteria(); + $stockStatusCriteria->setProductsFilter($productIds); + $stockStatusCollection = $this->getStockStatusRepository()->getList($stockStatusCriteria); + $stockStatuses = $stockStatusCollection->getItems(); + $stockStatuses = array_filter($stockStatuses, function (StockStatusInterface $stockStatus) { + return StockStatusInterface::STATUS_IN_STOCK == $stockStatus->getStockStatus(); + }); + $indexData = array_intersect_key($indexData, $stockStatuses); + } + return $indexData; + } + + /** + * Get stock configuration. + * + * @return StockConfigurationInterface + */ + private function getStockConfiguration() + { + if (null === $this->stockConfiguration) { + $this->stockConfiguration = ObjectManager::getInstance()->get(StockConfigurationInterface::class); + } + return $this->stockConfiguration; + } + + /** + * Create stock status criteria. + * Substitution of autogenerated factory in backward compatibility reasons. + * + * @return StockStatusCriteriaInterface + */ + private function createStockStatusCriteria() + { + return ObjectManager::getInstance()->create(StockStatusCriteriaInterface::class); + } + + /** + * Get stock status repository. + * + * @return StockStatusRepositoryInterface + */ + private function getStockStatusRepository() + { + if (null === $this->stockStatusRepository) { + $this->stockStatusRepository = ObjectManager::getInstance()->get(StockStatusRepositoryInterface::class); + } + return $this->stockStatusRepository; + } } diff --git a/app/code/Magento/CatalogSearch/Model/ResourceModel/Advanced/Collection.php b/app/code/Magento/CatalogSearch/Model/ResourceModel/Advanced/Collection.php index 7791dc761ae39..1cea6b2bff4d1 100644 --- a/app/code/Magento/CatalogSearch/Model/ResourceModel/Advanced/Collection.php +++ b/app/code/Magento/CatalogSearch/Model/ResourceModel/Advanced/Collection.php @@ -7,10 +7,11 @@ namespace Magento\CatalogSearch\Model\ResourceModel\Advanced; use Magento\Catalog\Model\Product; +use Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection\DefaultFilterStrategyApplyChecker; +use Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection\DefaultFilterStrategyApplyCheckerInterface; use Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection\SearchCriteriaResolverInterface; use Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection\SearchResultApplierInterface; use Magento\Framework\Search\EngineResolverInterface; -use Magento\Search\Model\EngineResolver; use Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection\TotalRecordsResolverInterface; use Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection\TotalRecordsResolverFactory; use Magento\Framework\Api\FilterBuilder; @@ -106,6 +107,11 @@ class Collection extends \Magento\Catalog\Model\ResourceModel\Product\Collection */ private $searchOrders; + /** + * @var DefaultFilterStrategyApplyCheckerInterface + */ + private $defaultFilterStrategyApplyChecker; + /** * Collection constructor * @@ -140,6 +146,7 @@ class Collection extends \Magento\Catalog\Model\ResourceModel\Product\Collection * @param SearchResultApplierFactory|null $searchResultApplierFactory * @param TotalRecordsResolverFactory|null $totalRecordsResolverFactory * @param EngineResolverInterface|null $engineResolver + * @param DefaultFilterStrategyApplyCheckerInterface|null $defaultFilterStrategyApplyChecker * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -173,7 +180,8 @@ public function __construct( SearchCriteriaResolverFactory $searchCriteriaResolverFactory = null, SearchResultApplierFactory $searchResultApplierFactory = null, TotalRecordsResolverFactory $totalRecordsResolverFactory = null, - EngineResolverInterface $engineResolver = null + EngineResolverInterface $engineResolver = null, + DefaultFilterStrategyApplyCheckerInterface $defaultFilterStrategyApplyChecker ) { $this->requestBuilder = $requestBuilder; $this->searchEngine = $searchEngine; @@ -191,6 +199,8 @@ public function __construct( ->get(TotalRecordsResolverFactory::class); $this->engineResolver = $engineResolver ?: ObjectManager::getInstance() ->get(EngineResolverInterface::class); + $this->defaultFilterStrategyApplyChecker = $defaultFilterStrategyApplyChecker ?: ObjectManager::getInstance() + ->get(DefaultFilterStrategyApplyChecker::class); parent::__construct( $entityFactory, $logger, @@ -238,7 +248,7 @@ public function addFieldsToFilter($fields) public function setOrder($attribute, $dir = Select::SQL_DESC) { $this->setSearchOrder($attribute, $dir); - if ($this->isCurrentEngineMysql()) { + if ($this->defaultFilterStrategyApplyChecker->isApplicable()) { parent::setOrder($attribute, $dir); } @@ -254,7 +264,7 @@ public function addCategoryFilter(\Magento\Catalog\Model\Category $category) * This changes need in backward compatible reasons for support dynamic improved algorithm * for price aggregation process. */ - if ($this->isCurrentEngineMysql()) { + if ($this->defaultFilterStrategyApplyChecker->isApplicable()) { parent::addCategoryFilter($category); } else { $this->addFieldToFilter('category_ids', $category->getId()); @@ -273,7 +283,7 @@ public function setVisibility($visibility) * This changes need in backward compatible reasons for support dynamic improved algorithm * for price aggregation process. */ - if ($this->isCurrentEngineMysql()) { + if ($this->defaultFilterStrategyApplyChecker->isApplicable()) { parent::setVisibility($visibility); } else { $this->addFieldToFilter('visibility', $visibility); @@ -297,16 +307,6 @@ private function setSearchOrder($field, $direction) $this->searchOrders[$field] = $direction; } - /** - * Check if current engine is MYSQL. - * - * @return bool - */ - private function isCurrentEngineMysql() - { - return $this->engineResolver->getCurrentSearchEngine() === EngineResolver::CATALOG_SEARCH_MYSQL_ENGINE; - } - /** * @inheritdoc */ diff --git a/app/code/Magento/CatalogSearch/Model/ResourceModel/Fulltext/Collection.php b/app/code/Magento/CatalogSearch/Model/ResourceModel/Fulltext/Collection.php index 59f6cd1c6e7eb..c9ad4ab7d79de 100644 --- a/app/code/Magento/CatalogSearch/Model/ResourceModel/Fulltext/Collection.php +++ b/app/code/Magento/CatalogSearch/Model/ResourceModel/Fulltext/Collection.php @@ -6,6 +6,8 @@ namespace Magento\CatalogSearch\Model\ResourceModel\Fulltext; +use Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection\DefaultFilterStrategyApplyChecker; +use Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection\DefaultFilterStrategyApplyCheckerInterface; use Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection\TotalRecordsResolverInterface; use Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection\TotalRecordsResolverFactory; use Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection\SearchCriteriaResolverInterface; @@ -133,6 +135,11 @@ class Collection extends \Magento\Catalog\Model\ResourceModel\Product\Collection */ private $searchOrders; + /** + * @var DefaultFilterStrategyApplyCheckerInterface + */ + private $defaultFilterStrategyApplyChecker; + /** * Collection constructor * @@ -171,6 +178,7 @@ class Collection extends \Magento\Catalog\Model\ResourceModel\Product\Collection * @param SearchResultApplierFactory|null $searchResultApplierFactory * @param TotalRecordsResolverFactory|null $totalRecordsResolverFactory * @param EngineResolverInterface|null $engineResolver + * @param DefaultFilterStrategyApplyCheckerInterface|null $defaultFilterStrategyApplyChecker * @SuppressWarnings(PHPMD.ExcessiveParameterList) * @SuppressWarnings(PHPMD.NPathComplexity) */ @@ -209,7 +217,8 @@ public function __construct( SearchCriteriaResolverFactory $searchCriteriaResolverFactory = null, SearchResultApplierFactory $searchResultApplierFactory = null, TotalRecordsResolverFactory $totalRecordsResolverFactory = null, - EngineResolverInterface $engineResolver = null + EngineResolverInterface $engineResolver = null, + DefaultFilterStrategyApplyCheckerInterface $defaultFilterStrategyApplyChecker = null ) { $this->queryFactory = $catalogSearchData; if ($searchResultFactory === null) { @@ -255,8 +264,8 @@ public function __construct( ->get(SearchResultApplierFactory::class); $this->totalRecordsResolverFactory = $totalRecordsResolverFactory ?: ObjectManager::getInstance() ->get(TotalRecordsResolverFactory::class); - $this->engineResolver = $engineResolver ?: ObjectManager::getInstance() - ->get(EngineResolverInterface::class); + $this->defaultFilterStrategyApplyChecker = $defaultFilterStrategyApplyChecker ?: ObjectManager::getInstance() + ->get(DefaultFilterStrategyApplyChecker::class); } /** @@ -393,13 +402,31 @@ public function addSearchFilter($query) public function setOrder($attribute, $dir = Select::SQL_DESC) { $this->setSearchOrder($attribute, $dir); - if ($this->isCurrentEngineMysql()) { + if ($this->defaultFilterStrategyApplyChecker->isApplicable()) { parent::setOrder($attribute, $dir); } return $this; } + /** + * Add attribute to sort order. + * + * @param string $attribute + * @param string $dir + * @return $this + */ + public function addAttributeToSort($attribute, $dir = self::SORT_ORDER_ASC) + { + if ($this->defaultFilterStrategyApplyChecker->isApplicable()) { + parent::addAttributeToSort($attribute, $dir); + } else { + $this->setOrder($attribute, $dir); + } + + return $this; + } + /** * @inheritdoc */ @@ -443,16 +470,6 @@ private function setSearchOrder($field, $direction) $this->searchOrders[$field] = $direction; } - /** - * Check if current engine is MYSQL. - * - * @return bool - */ - private function isCurrentEngineMysql() - { - return $this->engineResolver->getCurrentSearchEngine() === EngineResolver::CATALOG_SEARCH_MYSQL_ENGINE; - } - /** * Get total records resolver. * @@ -574,7 +591,7 @@ public function addCategoryFilter(\Magento\Catalog\Model\Category $category) * This changes need in backward compatible reasons for support dynamic improved algorithm * for price aggregation process. */ - if ($this->isCurrentEngineMysql()) { + if ($this->defaultFilterStrategyApplyChecker->isApplicable()) { parent::addCategoryFilter($category); } else { $this->_productLimitationPrice(); @@ -596,7 +613,7 @@ public function setVisibility($visibility) * This changes need in backward compatible reasons for support dynamic improved algorithm * for price aggregation process. */ - if ($this->isCurrentEngineMysql()) { + if ($this->defaultFilterStrategyApplyChecker->isApplicable()) { parent::setVisibility($visibility); } diff --git a/app/code/Magento/CatalogSearch/Model/ResourceModel/Fulltext/Collection/DefaultFilterStrategyApplyChecker.php b/app/code/Magento/CatalogSearch/Model/ResourceModel/Fulltext/Collection/DefaultFilterStrategyApplyChecker.php new file mode 100644 index 0000000000000..b396437fc66c7 --- /dev/null +++ b/app/code/Magento/CatalogSearch/Model/ResourceModel/Fulltext/Collection/DefaultFilterStrategyApplyChecker.php @@ -0,0 +1,24 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection; + +/** + * This class add in backward compatibility purposes to check if need to apply old strategy for filter prepare process. + * @deprecated + */ +class DefaultFilterStrategyApplyChecker implements DefaultFilterStrategyApplyCheckerInterface +{ + /** + * Check if this strategy applicable for current engine. + * + * @return bool + */ + public function isApplicable(): bool + { + return true; + } +} diff --git a/app/code/Magento/CatalogSearch/Model/ResourceModel/Fulltext/Collection/DefaultFilterStrategyApplyCheckerInterface.php b/app/code/Magento/CatalogSearch/Model/ResourceModel/Fulltext/Collection/DefaultFilterStrategyApplyCheckerInterface.php new file mode 100644 index 0000000000000..a067767775393 --- /dev/null +++ b/app/code/Magento/CatalogSearch/Model/ResourceModel/Fulltext/Collection/DefaultFilterStrategyApplyCheckerInterface.php @@ -0,0 +1,21 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection; + +/** + * Added in backward compatibility purposes to check if need to apply old strategy for filter prepare process. + * @deprecated + */ +interface DefaultFilterStrategyApplyCheckerInterface +{ + /** + * Check if this strategy applicable for current engine. + * + * @return bool + */ + public function isApplicable(): bool; +} diff --git a/app/code/Magento/CatalogSearch/Model/Search/ItemCollectionProvider.php b/app/code/Magento/CatalogSearch/Model/Search/ItemCollectionProvider.php index f621bcbf91835..af19b46f64209 100644 --- a/app/code/Magento/CatalogSearch/Model/Search/ItemCollectionProvider.php +++ b/app/code/Magento/CatalogSearch/Model/Search/ItemCollectionProvider.php @@ -43,7 +43,7 @@ public function __construct( public function getCollection(): Collection { if (!isset($this->factories[$this->engineResolver->getCurrentSearchEngine()])) { - throw new \DomainException('Undefined factory ' . $this->engineResolver->getCurrentSearchEngine()); + return $this->factories['default']; } return $this->factories[$this->engineResolver->getCurrentSearchEngine()]->create(); } diff --git a/app/code/Magento/CatalogSearch/etc/di.xml b/app/code/Magento/CatalogSearch/etc/di.xml index 7359bd6b454b9..28d5035308dee 100644 --- a/app/code/Magento/CatalogSearch/etc/di.xml +++ b/app/code/Magento/CatalogSearch/etc/di.xml @@ -200,6 +200,7 @@ <type name="Magento\CatalogSearch\Model\Search\ItemCollectionProvider"> <arguments> <argument name="factories" xsi:type="array"> + <item name="default" xsi:type="object">Magento\CatalogSearch\Model\ResourceModel\Advanced\CollectionFactory</item> <item name="mysql" xsi:type="object">Magento\CatalogSearch\Model\ResourceModel\Advanced\CollectionFactory</item> </argument> </arguments> @@ -207,6 +208,7 @@ <type name="Magento\CatalogSearch\Model\Advanced\ProductCollectionPrepareStrategyProvider"> <arguments> <argument name="strategies" xsi:type="array"> + <item name="default" xsi:type="object">Magento\CatalogSearch\Model\Advanced\ProductCollectionPrepareStrategy</item> <item name="mysql" xsi:type="object">Magento\CatalogSearch\Model\Advanced\ProductCollectionPrepareStrategy</item> </argument> </arguments> diff --git a/app/code/Magento/Elasticsearch/Elasticsearch5/SearchAdapter/Query/Builder.php b/app/code/Magento/Elasticsearch/Elasticsearch5/SearchAdapter/Query/Builder.php index 09968db00aa25..b4940e0a63cd0 100644 --- a/app/code/Magento/Elasticsearch/Elasticsearch5/SearchAdapter/Query/Builder.php +++ b/app/code/Magento/Elasticsearch/Elasticsearch5/SearchAdapter/Query/Builder.php @@ -49,7 +49,7 @@ class Builder /** * @var Sort */ - protected $sortBuilder; + private $sortBuilder; /** * @param Config $clientConfig diff --git a/app/code/Magento/Elasticsearch/Model/Adapter/FieldMapper/Product/FieldProvider/DynamicField.php b/app/code/Magento/Elasticsearch/Model/Adapter/FieldMapper/Product/FieldProvider/DynamicField.php index 268fe00e4c41e..76bc7a15e47a7 100644 --- a/app/code/Magento/Elasticsearch/Model/Adapter/FieldMapper/Product/FieldProvider/DynamicField.php +++ b/app/code/Magento/Elasticsearch/Model/Adapter/FieldMapper/Product/FieldProvider/DynamicField.php @@ -125,7 +125,7 @@ public function getFields(array $context = []): array ['categoryId' => $categoryId] ); $allAttributes[$categoryPositionKey] = [ - 'type' => $this->fieldTypeConverter->convert(FieldTypeConverterInterface::INTERNAL_DATA_TYPE_STRING), + 'type' => $this->fieldTypeConverter->convert(FieldTypeConverterInterface::INTERNAL_DATA_TYPE_INT), 'index' => $this->indexTypeConverter->convert(IndexTypeConverterInterface::INTERNAL_NO_INDEX_VALUE) ]; $allAttributes[$categoryNameKey] = [ diff --git a/app/code/Magento/Elasticsearch/Model/Indexer/Plugin/StockedProductsFilterPlugin.php b/app/code/Magento/Elasticsearch/Model/Indexer/Plugin/StockedProductsFilterPlugin.php deleted file mode 100644 index ec18b955a2917..0000000000000 --- a/app/code/Magento/Elasticsearch/Model/Indexer/Plugin/StockedProductsFilterPlugin.php +++ /dev/null @@ -1,94 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -declare(strict_types=1); - -namespace Magento\Elasticsearch\Model\Indexer\Plugin; - -use Magento\Elasticsearch\Model\Config; -use Magento\CatalogInventory\Api\StockConfigurationInterface; -use Magento\CatalogInventory\Api\StockStatusRepositoryInterface; -use Magento\CatalogInventory\Api\StockStatusCriteriaInterfaceFactory; -use Magento\CatalogInventory\Api\Data\StockStatusInterface; -use Magento\CatalogSearch\Model\Indexer\Fulltext\Action\DataProvider; - -/** - * Plugin for filtering child products that are out of stock for preventing their saving to catalog search index. - */ -class StockedProductsFilterPlugin -{ - /** - * @var Config - */ - private $config; - - /** - * @var StockConfigurationInterface - */ - private $stockConfiguration; - - /** - * @var StockStatusRepositoryInterface - */ - private $stockStatusRepository; - - /** - * @var StockStatusCriteriaInterfaceFactory - */ - private $stockStatusCriteriaFactory; - - /** - * @param Config $config - * @param StockConfigurationInterface $stockConfiguration - * @param StockStatusRepositoryInterface $stockStatusRepository - * @param StockStatusCriteriaInterfaceFactory $stockStatusCriteriaFactory - */ - public function __construct( - Config $config, - StockConfigurationInterface $stockConfiguration, - StockStatusRepositoryInterface $stockStatusRepository, - StockStatusCriteriaInterfaceFactory $stockStatusCriteriaFactory - ) { - $this->config = $config; - $this->stockConfiguration = $stockConfiguration; - $this->stockStatusRepository = $stockStatusRepository; - $this->stockStatusCriteriaFactory = $stockStatusCriteriaFactory; - } - - /** - * Filter out of stock options for configurable product. - * - * @param DataProvider $dataProvider - * @param array $indexData - * @param array $productData - * @param int $storeId - * @return array - * @SuppressWarnings(PHPMD.UnusedFormalParameter) - */ - public function beforePrepareProductIndex( - DataProvider $dataProvider, - array $indexData, - array $productData, - int $storeId - ): array { - if ($this->config->isElasticsearchEnabled() && !$this->stockConfiguration->isShowOutOfStock($storeId)) { - $productIds = array_keys($indexData); - $stockStatusCriteria = $this->stockStatusCriteriaFactory->create(); - $stockStatusCriteria->setProductsFilter($productIds); - $stockStatusCollection = $this->stockStatusRepository->getList($stockStatusCriteria); - $stockStatuses = $stockStatusCollection->getItems(); - $stockStatuses = array_filter($stockStatuses, function (StockStatusInterface $stockStatus) { - return StockStatusInterface::STATUS_IN_STOCK == $stockStatus->getStockStatus(); - }); - $indexData = array_intersect_key($indexData, $stockStatuses); - } - - return [ - $indexData, - $productData, - $storeId, - ]; - } -} diff --git a/app/code/Magento/Elasticsearch/Model/ResourceModel/Fulltext/Collection/DefaultFilterStrategyApplyChecker.php b/app/code/Magento/Elasticsearch/Model/ResourceModel/Fulltext/Collection/DefaultFilterStrategyApplyChecker.php new file mode 100644 index 0000000000000..21ff9a53e4f96 --- /dev/null +++ b/app/code/Magento/Elasticsearch/Model/ResourceModel/Fulltext/Collection/DefaultFilterStrategyApplyChecker.php @@ -0,0 +1,26 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Elasticsearch\Model\ResourceModel\Fulltext\Collection; + +use Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection\DefaultFilterStrategyApplyCheckerInterface; + +/** + * This class add in backward compatibility purposes to check if need to apply old strategy for filter prepare process. + * @deprecated + */ +class DefaultFilterStrategyApplyChecker implements DefaultFilterStrategyApplyCheckerInterface +{ + /** + * Check if this strategy applicable for current engine. + * + * @return bool + */ + public function isApplicable(): bool + { + return false; + } +} diff --git a/app/code/Magento/Elasticsearch/SearchAdapter/Query/Builder.php b/app/code/Magento/Elasticsearch/SearchAdapter/Query/Builder.php index d0aaa4b3dd572..8c786ed0e5e39 100644 --- a/app/code/Magento/Elasticsearch/SearchAdapter/Query/Builder.php +++ b/app/code/Magento/Elasticsearch/SearchAdapter/Query/Builder.php @@ -6,7 +6,13 @@ namespace Magento\Elasticsearch\SearchAdapter\Query; +use Magento\Elasticsearch\SearchAdapter\Query\Builder\Sort; +use Magento\Framework\App\ObjectManager; use Magento\Framework\Search\RequestInterface; +use Magento\Elasticsearch\Model\Config; +use Magento\Elasticsearch\SearchAdapter\SearchIndexNameResolver; +use Magento\Elasticsearch\SearchAdapter\Query\Builder\Aggregation as AggregationBuilder; +use Magento\Framework\App\ScopeResolverInterface; use Magento\Elasticsearch\Elasticsearch5\SearchAdapter\Query\Builder as Elasticsearch5Builder; /** @@ -18,7 +24,36 @@ class Builder extends Elasticsearch5Builder { /** - * Set initial settings for query + * @var Sort + */ + private $sortBuilder; + + /** + * @param Config $clientConfig + * @param SearchIndexNameResolver $searchIndexNameResolver + * @param AggregationBuilder $aggregationBuilder + * @param ScopeResolverInterface $scopeResolver + * @param Sort|null $sortBuilder + */ + public function __construct( + Config $clientConfig, + SearchIndexNameResolver $searchIndexNameResolver, + AggregationBuilder $aggregationBuilder, + ScopeResolverInterface $scopeResolver, + Sort $sortBuilder = null + ) { + $this->sortBuilder = $sortBuilder ?: ObjectManager::getInstance()->get(Sort::class); + parent::__construct( + $clientConfig, + $searchIndexNameResolver, + $aggregationBuilder, + $scopeResolver, + $this->sortBuilder + ); + } + + /** + * Set initial settings for query. * * @param RequestInterface $request * @return array diff --git a/app/code/Magento/Elasticsearch/SearchAdapter/Query/Builder/Sort.php b/app/code/Magento/Elasticsearch/SearchAdapter/Query/Builder/Sort.php index 5ccf202e3812b..e8085787f2b44 100644 --- a/app/code/Magento/Elasticsearch/SearchAdapter/Query/Builder/Sort.php +++ b/app/code/Magento/Elasticsearch/SearchAdapter/Query/Builder/Sort.php @@ -78,6 +78,13 @@ public function __construct( public function getSort(RequestInterface $request) { $sorts = []; + /** + * Temporary solution for an existing interface of a fulltext search request in Backward compatibility purposes. + * Scope to split Search request interface on two different 'Search' and 'Fulltext Search' contains in MC-16461. + */ + if (!method_exists($request, 'getSort')) { + return $sorts; + } foreach ($request->getSort() as $item) { if (in_array($item['field'], $this->skippedFields)) { continue; diff --git a/app/code/Magento/Elasticsearch/Test/Unit/Model/Indexer/Plugin/StockedProductsFilterPluginTest.php b/app/code/Magento/Elasticsearch/Test/Unit/Model/Indexer/Plugin/StockedProductsFilterPluginTest.php deleted file mode 100644 index f66d2532b32ae..0000000000000 --- a/app/code/Magento/Elasticsearch/Test/Unit/Model/Indexer/Plugin/StockedProductsFilterPluginTest.php +++ /dev/null @@ -1,134 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -declare(strict_types=1); - -namespace Magento\Elasticsearch\Test\Unit\Model\Indexer\Plugin; - -use Magento\Elasticsearch\Model\Config; -use Magento\Elasticsearch\Model\Indexer\Plugin\StockedProductsFilterPlugin; -use Magento\CatalogInventory\Api\StockConfigurationInterface; -use Magento\CatalogInventory\Api\StockStatusRepositoryInterface; -use Magento\CatalogInventory\Api\StockStatusCriteriaInterfaceFactory; -use Magento\CatalogInventory\Api\StockStatusCriteriaInterface; -use Magento\CatalogInventory\Api\Data\StockStatusCollectionInterface; -use Magento\CatalogInventory\Api\Data\StockStatusInterface; -use Magento\CatalogInventory\Model\Stock; -use Magento\CatalogSearch\Model\Indexer\Fulltext\Action\DataProvider; - -/** - * Test for Magento\Elasticsearch\Model\Indexer\Plugin\StockedProductsFilterPlugin class. - */ -class StockedProductsFilterPluginTest extends \PHPUnit\Framework\TestCase -{ - /** - * @var Config|\PHPUnit_Framework_MockObject_MockObject - */ - private $configMock; - - /** - * @var StockConfigurationInterface|\PHPUnit_Framework_MockObject_MockObject - */ - private $stockConfigurationMock; - - /** - * @var StockStatusRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject - */ - private $stockStatusRepositoryMock; - - /** - * @var StockStatusCriteriaInterfaceFactory|\PHPUnit_Framework_MockObject_MockObject - */ - private $stockStatusCriteriaFactoryMock; - - /** - * @var StockedProductsFilterPlugin - */ - private $plugin; - - /** - * {@inheritdoc} - */ - protected function setUp() - { - $this->configMock = $this->getMockBuilder(Config::class)->disableOriginalConstructor()->getMock(); - $this->stockConfigurationMock = $this->getMockBuilder(StockConfigurationInterface::class) - ->disableOriginalConstructor() - ->getMock(); - $this->stockStatusRepositoryMock = $this->getMockBuilder(StockStatusRepositoryInterface::class) - ->disableOriginalConstructor() - ->getMock(); - $this->stockStatusCriteriaFactoryMock = $this->getMockBuilder(StockStatusCriteriaInterfaceFactory::class) - ->disableOriginalConstructor() - ->getMock(); - - $this->plugin = new StockedProductsFilterPlugin( - $this->configMock, - $this->stockConfigurationMock, - $this->stockStatusRepositoryMock, - $this->stockStatusCriteriaFactoryMock - ); - } - - /** - * @return void - */ - public function testBeforePrepareProductIndex(): void - { - /** @var DataProvider|\PHPUnit_Framework_MockObject_MockObject $dataProviderMock */ - $dataProviderMock = $this->getMockBuilder(DataProvider::class)->disableOriginalConstructor()->getMock(); - $indexData = [ - 1 => [], - 2 => [], - ]; - $productData = []; - $storeId = 1; - - $this->configMock - ->expects($this->once()) - ->method('isElasticsearchEnabled') - ->willReturn(true); - $this->stockConfigurationMock - ->expects($this->once()) - ->method('isShowOutOfStock') - ->willReturn(false); - - $stockStatusCriteriaMock = $this->getMockBuilder(StockStatusCriteriaInterface::class)->getMock(); - $stockStatusCriteriaMock - ->expects($this->once()) - ->method('setProductsFilter') - ->willReturn(true); - $this->stockStatusCriteriaFactoryMock - ->expects($this->once()) - ->method('create') - ->willReturn($stockStatusCriteriaMock); - - $stockStatusMock = $this->getMockBuilder(StockStatusInterface::class)->getMock(); - $stockStatusMock->expects($this->atLeastOnce()) - ->method('getStockStatus') - ->willReturnOnConsecutiveCalls(Stock::STOCK_IN_STOCK, Stock::STOCK_OUT_OF_STOCK); - $stockStatusCollectionMock = $this->getMockBuilder(StockStatusCollectionInterface::class)->getMock(); - $stockStatusCollectionMock - ->expects($this->once()) - ->method('getItems') - ->willReturn([ - 1 => $stockStatusMock, - 2 => $stockStatusMock, - ]); - $this->stockStatusRepositoryMock - ->expects($this->once()) - ->method('getList') - ->willReturn($stockStatusCollectionMock); - - list ($indexData, $productData, $storeId) = $this->plugin->beforePrepareProductIndex( - $dataProviderMock, - $indexData, - $productData, - $storeId - ); - - $this->assertEquals([1], array_keys($indexData)); - } -} diff --git a/app/code/Magento/Elasticsearch/etc/di.xml b/app/code/Magento/Elasticsearch/etc/di.xml index 9732ae8226431..4f5c56c91df2b 100644 --- a/app/code/Magento/Elasticsearch/etc/di.xml +++ b/app/code/Magento/Elasticsearch/etc/di.xml @@ -49,6 +49,7 @@ <argument name="searchCriteriaResolverFactory" xsi:type="object">elasticsearchSearchCriteriaResolverFactory</argument> <argument name="searchResultApplierFactory" xsi:type="object">elasticsearchSearchResultApplier\Factory</argument> <argument name="totalRecordsResolverFactory" xsi:type="object">elasticsearchTotalRecordsResolver\Factory</argument> + <argument name="defaultFilterStrategyApplyChecker" xsi:type="object">Magento\Elasticsearch\Model\ResourceModel\Fulltext\Collection\DefaultFilterStrategyApplyChecker</argument> </arguments> </virtualType> <virtualType name="elasticsearchFulltextSearchCollectionFactory" type="Magento\CatalogSearch\Model\ResourceModel\Fulltext\SearchCollectionFactory"> @@ -71,6 +72,7 @@ <argument name="searchCriteriaResolverFactory" xsi:type="object">elasticsearchSearchCriteriaResolverFactory</argument> <argument name="searchResultApplierFactory" xsi:type="object">elasticsearchSearchResultApplier\Factory</argument> <argument name="totalRecordsResolverFactory" xsi:type="object">elasticsearchTotalRecordsResolver\Factory</argument> + <argument name="defaultFilterStrategyApplyChecker" xsi:type="object">Magento\Elasticsearch\Model\ResourceModel\Fulltext\Collection\DefaultFilterStrategyApplyChecker</argument> </arguments> </virtualType> <virtualType name="elasticsearchCategoryCollectionFactory" type="Magento\CatalogSearch\Model\ResourceModel\Fulltext\SearchCollectionFactory"> @@ -93,6 +95,7 @@ <argument name="searchCriteriaResolverFactory" xsi:type="object">elasticsearchSearchCriteriaResolverFactory</argument> <argument name="searchResultApplierFactory" xsi:type="object">elasticsearchSearchResultApplier\Factory</argument> <argument name="totalRecordsResolverFactory" xsi:type="object">elasticsearchTotalRecordsResolver\Factory</argument> + <argument name="defaultFilterStrategyApplyChecker" xsi:type="object">Magento\Elasticsearch\Model\ResourceModel\Fulltext\Collection\DefaultFilterStrategyApplyChecker</argument> </arguments> </virtualType> <virtualType name="elasticsearchAdvancedCollectionFactory" type="Magento\CatalogSearch\Model\ResourceModel\Advanced\CollectionFactory"> @@ -313,9 +316,6 @@ </argument> </arguments> </type> - <type name="Magento\CatalogSearch\Model\Indexer\Fulltext\Action\DataProvider"> - <plugin name="stockedProductsFilterPlugin" type="Magento\Elasticsearch\Model\Indexer\Plugin\StockedProductsFilterPlugin"/> - </type> <type name="Magento\Framework\Indexer\Config\DependencyInfoProvider"> <plugin name="indexerDependencyUpdaterPlugin" type="Magento\Elasticsearch\Model\Indexer\Plugin\DependencyUpdaterPlugin"/> </type> diff --git a/dev/tests/integration/testsuite/Magento/CatalogSearch/Model/Indexer/Fulltext/Action/FullTest.php b/dev/tests/integration/testsuite/Magento/CatalogSearch/Model/Indexer/Fulltext/Action/FullTest.php index 56c5db5572a31..137a3845b1efa 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogSearch/Model/Indexer/Fulltext/Action/FullTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogSearch/Model/Indexer/Fulltext/Action/FullTest.php @@ -85,10 +85,10 @@ private function getExpectedIndexData() return [ 'configurable' => [ $skuId => 'configurable', - $configurableId => 'Option 1 | Option 2', - $nameId => 'Configurable Product | Configurable OptionOption 1 | Configurable OptionOption 2', - $taxClassId => 'Taxable Goods | Taxable Goods | Taxable Goods', - $statusId => 'Enabled | Enabled | Enabled' + $configurableId => 'Option 2', + $nameId => 'Configurable Product | Configurable OptionOption 2', + $taxClassId => 'Taxable Goods | Taxable Goods', + $statusId => 'Enabled | Enabled' ], 'index_enabled' => [ $skuId => 'index_enabled', diff --git a/lib/internal/Magento/Framework/Search/Request.php b/lib/internal/Magento/Framework/Search/Request.php index 60f3338046613..264d4929dde56 100644 --- a/lib/internal/Magento/Framework/Search/Request.php +++ b/lib/internal/Magento/Framework/Search/Request.php @@ -146,7 +146,13 @@ public function getSize() } /** - * @inheritdoc + * Temporary solution for an existing interface of a fulltext search request in Backward compatibility purposes. + * Don't use this function. + * It must be move to different interface. + * Scope to split Search request interface on two different 'Search' and 'Fulltext Search' contains in MC-16461. + * + * @deprecated + * @return array */ public function getSort() { diff --git a/lib/internal/Magento/Framework/Search/RequestInterface.php b/lib/internal/Magento/Framework/Search/RequestInterface.php index 2de756e754a27..16df80f755c07 100644 --- a/lib/internal/Magento/Framework/Search/RequestInterface.php +++ b/lib/internal/Magento/Framework/Search/RequestInterface.php @@ -64,11 +64,4 @@ public function getFrom(); * @return int|null */ public function getSize(); - - /** - * Get Sort items - * - * @return array - */ - public function getSort(); } diff --git a/lib/internal/Magento/Framework/Search/Response/QueryResponse.php b/lib/internal/Magento/Framework/Search/Response/QueryResponse.php index 90c7056ea2549..00b1ed2149bec 100644 --- a/lib/internal/Magento/Framework/Search/Response/QueryResponse.php +++ b/lib/internal/Magento/Framework/Search/Response/QueryResponse.php @@ -75,7 +75,14 @@ public function getAggregations() } /** - * @inheritdoc + * Temporary solution for an existing interface of a fulltext search request in Backward compatibility purposes. + * Don't use this function. + * It must be move to different interface. + * Scope to split Search response interface on two different 'Search' and 'Fulltext Search' contains in MC-16461. + * + * @deprecated + * + * @return int */ public function getTotal(): int { diff --git a/lib/internal/Magento/Framework/Search/ResponseInterface.php b/lib/internal/Magento/Framework/Search/ResponseInterface.php index c6c0d0ab59e10..3b89528532602 100644 --- a/lib/internal/Magento/Framework/Search/ResponseInterface.php +++ b/lib/internal/Magento/Framework/Search/ResponseInterface.php @@ -16,11 +16,4 @@ interface ResponseInterface extends \IteratorAggregate, \Countable * @return \Magento\Framework\Api\Search\AggregationInterface */ public function getAggregations(); - - /** - * Return total count of items. - * - * @return int - */ - public function getTotal(): int; } diff --git a/lib/internal/Magento/Framework/Search/SearchResponseBuilder.php b/lib/internal/Magento/Framework/Search/SearchResponseBuilder.php index 2314252f4609c..ca92ba69e5558 100644 --- a/lib/internal/Magento/Framework/Search/SearchResponseBuilder.php +++ b/lib/internal/Magento/Framework/Search/SearchResponseBuilder.php @@ -51,7 +51,10 @@ public function build(ResponseInterface $response) $documents = iterator_to_array($response); $searchResult->setItems($documents); $searchResult->setAggregations($response->getAggregations()); - $searchResult->setTotalCount($response->getTotal()); + $count = method_exists($response, 'getTotal') + ? $response->getTotal() + : count($documents); + $searchResult->setTotalCount($count); return $searchResult; } diff --git a/lib/internal/Magento/Framework/View/Element/AbstractBlock.php b/lib/internal/Magento/Framework/View/Element/AbstractBlock.php index 6c4746d8218ea..3f2c2ac1685cd 100644 --- a/lib/internal/Magento/Framework/View/Element/AbstractBlock.php +++ b/lib/internal/Magento/Framework/View/Element/AbstractBlock.php @@ -8,7 +8,6 @@ use Magento\Framework\Cache\LockGuardedCacheLoader; use Magento\Framework\DataObject\IdentityInterface; -use Magento\Framework\App\ObjectManager; /** * Base class for all blocks. @@ -188,12 +187,10 @@ abstract class AbstractBlock extends \Magento\Framework\DataObject implements Bl * * @param \Magento\Framework\View\Element\Context $context * @param array $data - * @param LockGuardedCacheLoader|null $lockQuery */ public function __construct( \Magento\Framework\View\Element\Context $context, - array $data = [], - LockGuardedCacheLoader $lockQuery = null + array $data = [] ) { $this->_request = $context->getRequest(); $this->_layout = $context->getLayout(); @@ -212,12 +209,11 @@ public function __construct( $this->filterManager = $context->getFilterManager(); $this->_localeDate = $context->getLocaleDate(); $this->inlineTranslation = $context->getInlineTranslation(); + $this->lockQuery = $context->getLockGuardedCacheLoader(); if (isset($data['jsLayout'])) { $this->jsLayout = $data['jsLayout']; unset($data['jsLayout']); } - $this->lockQuery = $lockQuery - ?: ObjectManager::getInstance()->get(LockGuardedCacheLoader::class); parent::__construct($data); $this->_construct(); } @@ -973,8 +969,8 @@ public function escapeXssInUrl($data) * * Use $addSlashes = false for escaping js that inside html attribute (onClick, onSubmit etc) * - * @param string $data - * @param bool $addSlashes + * @param string $data + * @param bool $addSlashes * @return string * @deprecated 100.2.0 */ diff --git a/lib/internal/Magento/Framework/View/Element/Context.php b/lib/internal/Magento/Framework/View/Element/Context.php index 522bec3e6a2a9..3d1d05c6307a7 100644 --- a/lib/internal/Magento/Framework/View/Element/Context.php +++ b/lib/internal/Magento/Framework/View/Element/Context.php @@ -5,6 +5,8 @@ */ namespace Magento\Framework\View\Element; +use Magento\Framework\Cache\LockGuardedCacheLoader; + /** * Constructor modification point for Magento\Framework\View\Element\AbstractBlock. * @@ -136,12 +138,16 @@ class Context implements \Magento\Framework\ObjectManager\ContextInterface */ protected $inlineTranslation; + /** + * @var LockGuardedCacheLoader + */ + private $lockQuery; + /** * @param \Magento\Framework\App\RequestInterface $request * @param \Magento\Framework\View\LayoutInterface $layout * @param \Magento\Framework\Event\ManagerInterface $eventManager * @param \Magento\Framework\UrlInterface $urlBuilder - * @param \Magento\Framework\TranslateInterface $translator * @param \Magento\Framework\App\CacheInterface $cache * @param \Magento\Framework\View\DesignInterface $design * @param \Magento\Framework\Session\SessionManagerInterface $session @@ -155,6 +161,7 @@ class Context implements \Magento\Framework\ObjectManager\ContextInterface * @param \Magento\Framework\Filter\FilterManager $filterManager * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate * @param \Magento\Framework\Translate\Inline\StateInterface $inlineTranslation + * @param LockGuardedCacheLoader $lockQuery * * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -175,7 +182,8 @@ public function __construct( \Magento\Framework\Escaper $escaper, \Magento\Framework\Filter\FilterManager $filterManager, \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate, - \Magento\Framework\Translate\Inline\StateInterface $inlineTranslation + \Magento\Framework\Translate\Inline\StateInterface $inlineTranslation, + LockGuardedCacheLoader $lockQuery ) { $this->_request = $request; $this->_layout = $layout; @@ -194,6 +202,7 @@ public function __construct( $this->_filterManager = $filterManager; $this->_localeDate = $localeDate; $this->inlineTranslation = $inlineTranslation; + $this->lockQuery = $lockQuery; } /** @@ -357,10 +366,22 @@ public function getFilterManager() } /** + * Get locale date. + * * @return \Magento\Framework\Stdlib\DateTime\TimezoneInterface */ public function getLocaleDate() { return $this->_localeDate; } + + /** + * Lock guarded cache loader. + * + * @return LockGuardedCacheLoader + */ + public function getLockGuardedCacheLoader() + { + return $this->lockQuery; + } } diff --git a/lib/internal/Magento/Framework/View/Element/Template/Context.php b/lib/internal/Magento/Framework/View/Element/Template/Context.php index f7f701b98f929..db0b7f9f9714a 100644 --- a/lib/internal/Magento/Framework/View/Element/Template/Context.php +++ b/lib/internal/Magento/Framework/View/Element/Template/Context.php @@ -5,6 +5,8 @@ */ namespace Magento\Framework\View\Element\Template; +use Magento\Framework\Cache\LockGuardedCacheLoader; + /** * Constructor modification point for Magento\Framework\View\Element\Template. * @@ -97,6 +99,7 @@ class Context extends \Magento\Framework\View\Element\Context * @param \Magento\Framework\Filter\FilterManager $filterManager * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate * @param \Magento\Framework\Translate\Inline\StateInterface $inlineTranslation + * @param LockGuardedCacheLoader $lockQuery * @param \Magento\Framework\Filesystem $filesystem * @param \Magento\Framework\View\FileSystem $viewFileSystem * @param \Magento\Framework\View\TemplateEnginePool $enginePool @@ -126,6 +129,7 @@ public function __construct( \Magento\Framework\Filter\FilterManager $filterManager, \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate, \Magento\Framework\Translate\Inline\StateInterface $inlineTranslation, + LockGuardedCacheLoader $lockQuery, \Magento\Framework\Filesystem $filesystem, \Magento\Framework\View\FileSystem $viewFileSystem, \Magento\Framework\View\TemplateEnginePool $enginePool, @@ -152,7 +156,8 @@ public function __construct( $escaper, $filterManager, $localeDate, - $inlineTranslation + $inlineTranslation, + $lockQuery ); $this->resolver = $resolver; $this->validator = $validator; @@ -246,6 +251,8 @@ public function getStoreManager() } /** + * Get page config. + * * @return \Magento\Framework\View\Page\Config */ public function getPageConfig() diff --git a/lib/internal/Magento/Framework/View/Test/Unit/Element/AbstractBlockTest.php b/lib/internal/Magento/Framework/View/Test/Unit/Element/AbstractBlockTest.php index dba775ea894f4..e888b00c9f82f 100644 --- a/lib/internal/Magento/Framework/View/Test/Unit/Element/AbstractBlockTest.php +++ b/lib/internal/Magento/Framework/View/Test/Unit/Element/AbstractBlockTest.php @@ -87,12 +87,14 @@ protected function setUp() $contextMock->expects($this->once()) ->method('getSession') ->willReturn($this->sessionMock); + $contextMock->expects($this->once()) + ->method('getLockGuardedCacheLoader') + ->willReturn($this->lockQuery); $this->block = $this->getMockForAbstractClass( AbstractBlock::class, [ 'context' => $contextMock, 'data' => [], - 'lockQuery' => $this->lockQuery ] ); } From 47eb4da5fc96c5ad0db9002df446617e6992b6c9 Mon Sep 17 00:00:00 2001 From: Vitaliy Honcharenko <vgoncharenko@magento.com> Date: Tue, 21 May 2019 12:36:52 -0500 Subject: [PATCH 402/773] MC-16239: Search result page contain 24k results --- .../CatalogSearch/Model/ResourceModel/Advanced/Collection.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/CatalogSearch/Model/ResourceModel/Advanced/Collection.php b/app/code/Magento/CatalogSearch/Model/ResourceModel/Advanced/Collection.php index 1cea6b2bff4d1..da96e96ea5278 100644 --- a/app/code/Magento/CatalogSearch/Model/ResourceModel/Advanced/Collection.php +++ b/app/code/Magento/CatalogSearch/Model/ResourceModel/Advanced/Collection.php @@ -181,7 +181,7 @@ public function __construct( SearchResultApplierFactory $searchResultApplierFactory = null, TotalRecordsResolverFactory $totalRecordsResolverFactory = null, EngineResolverInterface $engineResolver = null, - DefaultFilterStrategyApplyCheckerInterface $defaultFilterStrategyApplyChecker + DefaultFilterStrategyApplyCheckerInterface $defaultFilterStrategyApplyChecker = null ) { $this->requestBuilder = $requestBuilder; $this->searchEngine = $searchEngine; From 109142eb5adcc7fa69641f3af2caec3444e5a160 Mon Sep 17 00:00:00 2001 From: Vitaliy Honcharenko <vgoncharenko@magento.com> Date: Tue, 21 May 2019 14:59:23 -0500 Subject: [PATCH 403/773] MC-16239: Search result page contain 24k results --- .../Product/FieldProvider/DynamicFieldTest.php | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/Elasticsearch/Test/Unit/Model/Adapter/FieldMapper/Product/FieldProvider/DynamicFieldTest.php b/app/code/Magento/Elasticsearch/Test/Unit/Model/Adapter/FieldMapper/Product/FieldProvider/DynamicFieldTest.php index 7c2a33c05aa08..8f3fc068411df 100644 --- a/app/code/Magento/Elasticsearch/Test/Unit/Model/Adapter/FieldMapper/Product/FieldProvider/DynamicFieldTest.php +++ b/app/code/Magento/Elasticsearch/Test/Unit/Model/Adapter/FieldMapper/Product/FieldProvider/DynamicFieldTest.php @@ -241,13 +241,12 @@ function ($type) use ($complexType) { static $callCount = []; $callCount[$type] = !isset($callCount[$type]) ? 1 : ++$callCount[$type]; - if ($type === 'string') { - return 'string'; - } if ($type === 'string') { return 'string'; } elseif ($type === 'float') { return 'float'; + } elseif ($type === 'integer') { + return 'integer'; } else { return $complexType; } @@ -276,7 +275,7 @@ public function attributeProvider() 'index' => 'no_index' ], 'position_1' => [ - 'type' => 'string', + 'type' => 'integer', 'index' => 'no_index' ], 'price_1_1' => [ @@ -295,7 +294,7 @@ public function attributeProvider() 'index' => 'no_index' ], 'position_1' => [ - 'type' => 'string', + 'type' => 'integer', 'index' => 'no_index' ], 'price_1_1' => [ @@ -314,7 +313,7 @@ public function attributeProvider() 'index' => 'no_index' ], 'position_1' => [ - 'type' => 'string', + 'type' => 'integer', 'index' => 'no_index' ], 'price_1_1' => [ From d3174174b697cf05b0dda7241b34594d42a71b50 Mon Sep 17 00:00:00 2001 From: Vitaliy Honcharenko <vgoncharenko@magento.com> Date: Tue, 21 May 2019 17:54:03 -0500 Subject: [PATCH 404/773] MC-16239: Search result page contain 24k results --- .../ResourceModel/Advanced/Collection.php | 4 ++++ .../SearchAdapter/Query/Builder.php | 20 ++++++++++++++----- .../Magento/Framework/Search/Search.php | 11 +++++++++- 3 files changed, 29 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/CatalogSearch/Model/ResourceModel/Advanced/Collection.php b/app/code/Magento/CatalogSearch/Model/ResourceModel/Advanced/Collection.php index da96e96ea5278..2801de2879db7 100644 --- a/app/code/Magento/CatalogSearch/Model/ResourceModel/Advanced/Collection.php +++ b/app/code/Magento/CatalogSearch/Model/ResourceModel/Advanced/Collection.php @@ -247,6 +247,10 @@ public function addFieldsToFilter($fields) */ public function setOrder($attribute, $dir = Select::SQL_DESC) { + /** + * This changes need in backward compatible reasons for support dynamic improved algorithm + * for price aggregation process. + */ $this->setSearchOrder($attribute, $dir); if ($this->defaultFilterStrategyApplyChecker->isApplicable()) { parent::setOrder($attribute, $dir); diff --git a/app/code/Magento/Elasticsearch/Elasticsearch5/SearchAdapter/Query/Builder.php b/app/code/Magento/Elasticsearch/Elasticsearch5/SearchAdapter/Query/Builder.php index b4940e0a63cd0..c307e2f16ad5c 100644 --- a/app/code/Magento/Elasticsearch/Elasticsearch5/SearchAdapter/Query/Builder.php +++ b/app/code/Magento/Elasticsearch/Elasticsearch5/SearchAdapter/Query/Builder.php @@ -56,20 +56,17 @@ class Builder * @param SearchIndexNameResolver $searchIndexNameResolver * @param AggregationBuilder $aggregationBuilder * @param ScopeResolverInterface $scopeResolver - * @param Sort|null $sortBuilder */ public function __construct( Config $clientConfig, SearchIndexNameResolver $searchIndexNameResolver, AggregationBuilder $aggregationBuilder, - ScopeResolverInterface $scopeResolver, - Sort $sortBuilder = null + ScopeResolverInterface $scopeResolver ) { $this->clientConfig = $clientConfig; $this->searchIndexNameResolver = $searchIndexNameResolver; $this->aggregationBuilder = $aggregationBuilder; $this->scopeResolver = $scopeResolver; - $this->sortBuilder = $sortBuilder ?: ObjectManager::getInstance()->get(Sort::class); } /** @@ -91,7 +88,7 @@ public function initQuery(RequestInterface $request) 'from' => $request->getFrom(), 'size' => $request->getSize(), 'stored_fields' => ['_id', '_score'], - 'sort' => $this->sortBuilder->getSort($request), + 'sort' => $this->getSortBuilder()->getSort($request), 'query' => [], ], ]; @@ -112,4 +109,17 @@ public function initAggregations( ) { return $this->aggregationBuilder->build($request, $searchQuery); } + + /** + * Get sort builder instance. + * + * @return Sort + */ + private function getSortBuilder() + { + if (null === $this->sortBuilder){ + $this->sortBuilder = ObjectManager::getInstance()->get(Sort::class); + } + return $this->sortBuilder; + } } diff --git a/lib/internal/Magento/Framework/Search/Search.php b/lib/internal/Magento/Framework/Search/Search.php index fe228546b55fb..1286be59a0d8b 100644 --- a/lib/internal/Magento/Framework/Search/Search.php +++ b/lib/internal/Magento/Framework/Search/Search.php @@ -71,7 +71,16 @@ public function search(SearchCriteriaInterface $searchCriteria) $this->requestBuilder->setFrom($searchCriteria->getCurrentPage() * $searchCriteria->getPageSize()); $this->requestBuilder->setSize($searchCriteria->getPageSize()); - $this->requestBuilder->setSort($searchCriteria->getSortOrders()); + + /** + * This added in Backward compatibility purposes. + * Temporary solution for an existing API of a fulltext search request builder. + * It must be moved to different API. + * Scope to split Search request builder API in MC-16461. + */ + if (method_exists($this->requestBuilder, 'setSort')) { + $this->requestBuilder->setSort($searchCriteria->getSortOrders()); + } $request = $this->requestBuilder->create(); $searchResponse = $this->searchEngine->search($request); From 25ee1a2172afad789fd322846f5ba66eeeec3579 Mon Sep 17 00:00:00 2001 From: Anahit Martirosyan <anahit_martirosyan@epam.com> Date: Wed, 22 May 2019 10:40:25 +0400 Subject: [PATCH 405/773] MAGETWO-98818: [Magento Cloud] You cannot schedule an update for the Tier price if it was set as a discount on the original price - Updated automated test script --- .../Test/Mftf/ActionGroup/AdminProductActionGroup.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductActionGroup.xml index 5c644cd95efb8..a5330e7e606ba 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductActionGroup.xml @@ -485,10 +485,10 @@ </actionGroup> <actionGroup name="AdminProductAdvancedPricingNewCustomerGroupPrice"> <arguments> - <argument name="qty" type="string"/> - <argument name="priceType" type="string"/> - <argument name="discount" type="string"/> - <argument name="customerGroup" type="string"/> + <argument name="qty" type="string" defaultValue="2"/> + <argument name="priceType" type="string" defaultValue="Discount"/> + <argument name="discount" type="string" defaultValue="75"/> + <argument name="customerGroup" type="string" defaultValue="0"/> </arguments> <click selector="{{AdminProductFormAdvancedPricingSection.customerGroupPriceAddButton}}" stepKey="addCustomerGroup"/> <fillField selector="{{AdminProductFormAdvancedPricingSection.productTierPriceQtyInput(customerGroup)}}" userInput="{{qty}}" stepKey="fillProductTierPriceQtyInput1"/> From f0252c1775b73c265d9ecd40e80e193ec2026bc3 Mon Sep 17 00:00:00 2001 From: Anahit Martirosyan <anahit_martirosyan@epam.com> Date: Wed, 22 May 2019 12:41:32 +0400 Subject: [PATCH 406/773] MAGETWO-98818: [Magento Cloud] You cannot schedule an update for the Tier price if it was set as a discount on the original price - Updated automated test script --- .../Catalog/Test/Mftf/ActionGroup/AdminProductActionGroup.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductActionGroup.xml index a5330e7e606ba..6d51548856170 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductActionGroup.xml @@ -483,7 +483,7 @@ <click selector="{{AdminAddUpSellProductsModalSection.AddSelectedProductsButton}}" stepKey="addRelatedProductSelected"/> <waitForPageLoad stepKey="waitForPageToLoad1"/> </actionGroup> - <actionGroup name="AdminProductAdvancedPricingNewCustomerGroupPrice"> + <actionGroup name="adminProductAdvancedPricingNewCustomerGroupPrice"> <arguments> <argument name="qty" type="string" defaultValue="2"/> <argument name="priceType" type="string" defaultValue="Discount"/> From dd2b8fce00a80e5726b56b6a0ca74831b9bd9c6c Mon Sep 17 00:00:00 2001 From: OlgaVasyltsun <olga.vasyltsun@gmail.com> Date: Wed, 22 May 2019 12:03:31 +0300 Subject: [PATCH 407/773] MC-16370: Admin can't change config value with CURL --- .../Adminhtml/System/AbstractConfig.php | 2 +- .../Adminhtml/System/Config/Save.php | 62 ++++++++++++++ .../Adminhtml/System/ConfigTest.php | 81 +++++++++++++++++++ 3 files changed, 144 insertions(+), 1 deletion(-) create mode 100644 dev/tests/integration/testsuite/Magento/Paypal/Controller/Adminhtml/System/ConfigTest.php diff --git a/app/code/Magento/Config/Controller/Adminhtml/System/AbstractConfig.php b/app/code/Magento/Config/Controller/Adminhtml/System/AbstractConfig.php index cb3069f14349a..7b626ccbd333c 100644 --- a/app/code/Magento/Config/Controller/Adminhtml/System/AbstractConfig.php +++ b/app/code/Magento/Config/Controller/Adminhtml/System/AbstractConfig.php @@ -77,7 +77,7 @@ protected function _isAllowed() { $sectionId = $this->_request->getParam('section'); return parent::_isAllowed() - && $this->_configStructure->getElement($sectionId)->isAllowed(); + || $this->_configStructure->getElement($sectionId)->isAllowed(); } /** diff --git a/app/code/Magento/Config/Controller/Adminhtml/System/Config/Save.php b/app/code/Magento/Config/Controller/Adminhtml/System/Config/Save.php index bea080d366f4a..38b9a0076c3ad 100644 --- a/app/code/Magento/Config/Controller/Adminhtml/System/Config/Save.php +++ b/app/code/Magento/Config/Controller/Adminhtml/System/Config/Save.php @@ -56,6 +56,68 @@ public function __construct( $this->string = $string; } + /** + * @inheritdoc + */ + protected function _isAllowed() + { + return parent::_isAllowed() && $this->isSectionAllowed(); + } + + /** + * Checks if user has access to section. + * + * @return bool + */ + private function isSectionAllowed(): bool + { + $sectionId = $this->_request->getParam('section'); + $isAllowed = $this->_configStructure->getElement($sectionId)->isAllowed(); + if (!$isAllowed) { + $groups = $this->getRequest()->getPost('groups'); + $fieldPath = $this->getFirstFieldPath($groups, $sectionId); + + $fieldPaths = $this->_configStructure->getFieldPaths(); + $fieldPath = $fieldPaths[$fieldPath][0] ?? $sectionId; + $explodedConfigPath = explode('/', $fieldPath); + $configSectionId = $explodedConfigPath[0] ?? $sectionId; + + $isAllowed = $this->_configStructure->getElement($configSectionId)->isAllowed(); + } + + return $isAllowed; + } + + /** + * Return field path as string. + * + * @param array $elements + * @param string $fieldPath + * @return string + */ + private function getFirstFieldPath(array $elements, string $fieldPath): string + { + $groupData = []; + foreach ($elements as $elementName => $element) { + if (!empty($element)) { + $fieldPath .= '/' . $elementName; + + if (!empty($element['fields'])) { + $groupData = $element['fields']; + } elseif (!empty($element['groups'])) { + $groupData = $element['groups']; + } + + if (!empty($groupData)) { + $fieldPath = $this->getFirstFieldPath($groupData, $fieldPath); + } + break; + } + } + + return $fieldPath; + } + /** * Get groups for save * diff --git a/dev/tests/integration/testsuite/Magento/Paypal/Controller/Adminhtml/System/ConfigTest.php b/dev/tests/integration/testsuite/Magento/Paypal/Controller/Adminhtml/System/ConfigTest.php new file mode 100644 index 0000000000000..748998ef84c69 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Paypal/Controller/Adminhtml/System/ConfigTest.php @@ -0,0 +1,81 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Paypal\Controller\Adminhtml\System; + +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Framework\App\Request\Http as HttpRequest; +use Magento\TestFramework\Helper\Bootstrap; + +/** + * @magentoAppArea adminhtml + */ +class ConfigTest extends \Magento\TestFramework\TestCase\AbstractBackendController +{ + /** + * @magentoAppIsolation enabled + * @magentoDbIsolation enabled + * + * @dataProvider saveMerchantCountryDataProvider + * + * @param string $section + * @param array $groups + * @return void + */ + public function testSaveMerchantCountry(string $section, array $groups): void + { + /** @var ScopeConfigInterface $scopeConfig */ + $scopeConfig = Bootstrap::getObjectManager()->get(ScopeConfigInterface::class); + + $request = $this->getRequest(); + $request->setPostValue($groups) + ->setParam('section', $section) + ->setMethod(HttpRequest::METHOD_POST); + + $this->dispatch('backend/admin/system_config/save'); + + $this->assertSessionMessages($this->equalTo(['You saved the configuration.'])); + + $this->assertEquals( + 'GB', + $scopeConfig->getValue('paypal/general/merchant_country') + ); + } + + /** + * @return array + */ + public function saveMerchantCountryDataProvider(): array + { + return [ + [ + 'section' => 'paypal', + 'groups' => [ + 'groups' => [ + 'general' => [ + 'fields' => [ + 'merchant_country' => ['value' => 'GB'], + ], + ], + ], + ], + ], + [ + 'section' => 'payment', + 'groups' => [ + 'groups' => [ + 'account' => [ + 'fields' => [ + 'merchant_country' => ['value' => 'GB'], + ], + ], + ], + ], + ], + ]; + } +} From 1e47e81264e799a8ddffde17486dad8482587ba1 Mon Sep 17 00:00:00 2001 From: Vitaliy Honcharenko <vgoncharenko@magento.com> Date: Wed, 22 May 2019 09:52:59 -0500 Subject: [PATCH 408/773] MC-16239: Search result page contain 24k results --- .../Indexer/Fulltext/Action/DataProvider.php | 1 + .../SearchAdapter/Query/Builder.php | 2 +- .../SearchAdapter/Query/Builder.php | 43 ++++++------------- 3 files changed, 16 insertions(+), 30 deletions(-) diff --git a/app/code/Magento/CatalogSearch/Model/Indexer/Fulltext/Action/DataProvider.php b/app/code/Magento/CatalogSearch/Model/Indexer/Fulltext/Action/DataProvider.php index 0967d7fad384b..01a36117bd1a1 100644 --- a/app/code/Magento/CatalogSearch/Model/Indexer/Fulltext/Action/DataProvider.php +++ b/app/code/Magento/CatalogSearch/Model/Indexer/Fulltext/Action/DataProvider.php @@ -726,6 +726,7 @@ private function getStockConfiguration() /** * Create stock status criteria. + * * Substitution of autogenerated factory in backward compatibility reasons. * * @return StockStatusCriteriaInterface diff --git a/app/code/Magento/Elasticsearch/Elasticsearch5/SearchAdapter/Query/Builder.php b/app/code/Magento/Elasticsearch/Elasticsearch5/SearchAdapter/Query/Builder.php index c307e2f16ad5c..75c675663f03f 100644 --- a/app/code/Magento/Elasticsearch/Elasticsearch5/SearchAdapter/Query/Builder.php +++ b/app/code/Magento/Elasticsearch/Elasticsearch5/SearchAdapter/Query/Builder.php @@ -117,7 +117,7 @@ public function initAggregations( */ private function getSortBuilder() { - if (null === $this->sortBuilder){ + if (null === $this->sortBuilder) { $this->sortBuilder = ObjectManager::getInstance()->get(Sort::class); } return $this->sortBuilder; diff --git a/app/code/Magento/Elasticsearch/SearchAdapter/Query/Builder.php b/app/code/Magento/Elasticsearch/SearchAdapter/Query/Builder.php index 8c786ed0e5e39..0bea8683692f2 100644 --- a/app/code/Magento/Elasticsearch/SearchAdapter/Query/Builder.php +++ b/app/code/Magento/Elasticsearch/SearchAdapter/Query/Builder.php @@ -9,10 +9,6 @@ use Magento\Elasticsearch\SearchAdapter\Query\Builder\Sort; use Magento\Framework\App\ObjectManager; use Magento\Framework\Search\RequestInterface; -use Magento\Elasticsearch\Model\Config; -use Magento\Elasticsearch\SearchAdapter\SearchIndexNameResolver; -use Magento\Elasticsearch\SearchAdapter\Query\Builder\Aggregation as AggregationBuilder; -use Magento\Framework\App\ScopeResolverInterface; use Magento\Elasticsearch\Elasticsearch5\SearchAdapter\Query\Builder as Elasticsearch5Builder; /** @@ -28,30 +24,6 @@ class Builder extends Elasticsearch5Builder */ private $sortBuilder; - /** - * @param Config $clientConfig - * @param SearchIndexNameResolver $searchIndexNameResolver - * @param AggregationBuilder $aggregationBuilder - * @param ScopeResolverInterface $scopeResolver - * @param Sort|null $sortBuilder - */ - public function __construct( - Config $clientConfig, - SearchIndexNameResolver $searchIndexNameResolver, - AggregationBuilder $aggregationBuilder, - ScopeResolverInterface $scopeResolver, - Sort $sortBuilder = null - ) { - $this->sortBuilder = $sortBuilder ?: ObjectManager::getInstance()->get(Sort::class); - parent::__construct( - $clientConfig, - $searchIndexNameResolver, - $aggregationBuilder, - $scopeResolver, - $this->sortBuilder - ); - } - /** * Set initial settings for query. * @@ -70,10 +42,23 @@ public function initQuery(RequestInterface $request) 'from' => $request->getFrom(), 'size' => $request->getSize(), 'fields' => ['_id', '_score'], - 'sort' => $this->sortBuilder->getSort($request), + 'sort' => $this->getSortBuilder()->getSort($request), 'query' => [], ], ]; return $searchQuery; } + + /** + * Get sort builder instance. + * + * @return Sort + */ + private function getSortBuilder() + { + if (null === $this->sortBuilder) { + $this->sortBuilder = ObjectManager::getInstance()->get(Sort::class); + } + return $this->sortBuilder; + } } From 8464570360d9abc7d1cf08fe57dd9afeee5f61d4 Mon Sep 17 00:00:00 2001 From: Vitaliy Honcharenko <vgoncharenko@magento.com> Date: Wed, 22 May 2019 16:43:30 -0500 Subject: [PATCH 409/773] MC-16239: Search result page contain 24k results - fix static tests --- app/code/Magento/Backend/Block/Context.php | 2 +- app/code/Magento/Backend/Block/Widget/Context.php | 2 +- app/code/Magento/Catalog/Block/Product/Context.php | 2 +- .../Model/ResourceModel/Fulltext/Collection.php | 9 --------- lib/internal/Magento/Framework/View/Element/Context.php | 3 +-- .../Magento/Framework/View/Element/Template/Context.php | 2 +- 6 files changed, 5 insertions(+), 15 deletions(-) diff --git a/app/code/Magento/Backend/Block/Context.php b/app/code/Magento/Backend/Block/Context.php index 5c142415fefdb..47e92a655bd5d 100644 --- a/app/code/Magento/Backend/Block/Context.php +++ b/app/code/Magento/Backend/Block/Context.php @@ -19,7 +19,7 @@ * the classes they were introduced for. * * @api - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * @SuppressWarnings(PHPMD) * @since 100.0.2 */ class Context extends \Magento\Framework\View\Element\Context diff --git a/app/code/Magento/Backend/Block/Widget/Context.php b/app/code/Magento/Backend/Block/Widget/Context.php index 27274164a0b5b..13186696a4781 100644 --- a/app/code/Magento/Backend/Block/Widget/Context.php +++ b/app/code/Magento/Backend/Block/Widget/Context.php @@ -19,7 +19,7 @@ * the classes they were introduced for. * * @api - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * @SuppressWarnings(PHPMD) * @since 100.0.2 */ class Context extends \Magento\Backend\Block\Template\Context diff --git a/app/code/Magento/Catalog/Block/Product/Context.php b/app/code/Magento/Catalog/Block/Product/Context.php index 82dd8b2262736..ea7d2467d2917 100644 --- a/app/code/Magento/Catalog/Block/Product/Context.php +++ b/app/code/Magento/Catalog/Block/Product/Context.php @@ -19,7 +19,7 @@ * the classes they were introduced for. * * @deprecated 101.1.0 - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * @SuppressWarnings(PHPMD) */ class Context extends \Magento\Framework\View\Element\Template\Context { diff --git a/app/code/Magento/CatalogSearch/Model/ResourceModel/Fulltext/Collection.php b/app/code/Magento/CatalogSearch/Model/ResourceModel/Fulltext/Collection.php index c9ad4ab7d79de..18e44bfcd5107 100644 --- a/app/code/Magento/CatalogSearch/Model/ResourceModel/Fulltext/Collection.php +++ b/app/code/Magento/CatalogSearch/Model/ResourceModel/Fulltext/Collection.php @@ -14,7 +14,6 @@ use Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection\SearchCriteriaResolverFactory; use Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection\SearchResultApplierFactory; use Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection\SearchResultApplierInterface; -use Magento\Framework\Search\EngineResolverInterface; use Magento\Framework\Data\Collection\Db\SizeResolverInterfaceFactory; use Magento\Framework\DB\Select; use Magento\Framework\Api\Search\SearchResultInterface; @@ -28,7 +27,6 @@ use Magento\Framework\Exception\LocalizedException; use Magento\Framework\App\ObjectManager; use Magento\Catalog\Model\ResourceModel\Product\Collection\ProductLimitationFactory; -use Magento\Search\Model\EngineResolver; /** * Fulltext Collection @@ -125,11 +123,6 @@ class Collection extends \Magento\Catalog\Model\ResourceModel\Product\Collection */ private $totalRecordsResolverFactory; - /** - * @var EngineResolverInterface - */ - private $engineResolver; - /** * @var array */ @@ -177,7 +170,6 @@ class Collection extends \Magento\Catalog\Model\ResourceModel\Product\Collection * @param SearchCriteriaResolverFactory|null $searchCriteriaResolverFactory * @param SearchResultApplierFactory|null $searchResultApplierFactory * @param TotalRecordsResolverFactory|null $totalRecordsResolverFactory - * @param EngineResolverInterface|null $engineResolver * @param DefaultFilterStrategyApplyCheckerInterface|null $defaultFilterStrategyApplyChecker * @SuppressWarnings(PHPMD.ExcessiveParameterList) * @SuppressWarnings(PHPMD.NPathComplexity) @@ -217,7 +209,6 @@ public function __construct( SearchCriteriaResolverFactory $searchCriteriaResolverFactory = null, SearchResultApplierFactory $searchResultApplierFactory = null, TotalRecordsResolverFactory $totalRecordsResolverFactory = null, - EngineResolverInterface $engineResolver = null, DefaultFilterStrategyApplyCheckerInterface $defaultFilterStrategyApplyChecker = null ) { $this->queryFactory = $catalogSearchData; diff --git a/lib/internal/Magento/Framework/View/Element/Context.php b/lib/internal/Magento/Framework/View/Element/Context.php index 3d1d05c6307a7..989a6dbf55b98 100644 --- a/lib/internal/Magento/Framework/View/Element/Context.php +++ b/lib/internal/Magento/Framework/View/Element/Context.php @@ -18,8 +18,7 @@ * As Magento moves from inheritance-based APIs all such classes will be deprecated together with * the classes they were introduced for. * - * @SuppressWarnings(PHPMD.TooManyFields) - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * @SuppressWarnings(PHPMD) * * @api */ diff --git a/lib/internal/Magento/Framework/View/Element/Template/Context.php b/lib/internal/Magento/Framework/View/Element/Template/Context.php index db0b7f9f9714a..4e86a37aa7e09 100644 --- a/lib/internal/Magento/Framework/View/Element/Template/Context.php +++ b/lib/internal/Magento/Framework/View/Element/Template/Context.php @@ -19,7 +19,7 @@ * the classes they were introduced for. * * @api - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * @SuppressWarnings(PHPMD) */ class Context extends \Magento\Framework\View\Element\Context { From f51164afc7f2b5e80eb893b4110093206bfc47e0 Mon Sep 17 00:00:00 2001 From: Viktor Sevch <svitja@ukr.net> Date: Thu, 23 May 2019 09:18:38 +0300 Subject: [PATCH 410/773] MC-16371: [FT] CheckoutWithBraintreePaypalMinicartTest fails on Bamboo --- .../app/Magento/Checkout/Test/Block/Cart/Sidebar.php | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Cart/Sidebar.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Cart/Sidebar.php index 562bc3a261287..eeb37384437a1 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Cart/Sidebar.php +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Cart/Sidebar.php @@ -34,7 +34,7 @@ class Sidebar extends Block * * @var string */ - protected $braintreePaypalCheckoutButton = './/button[contains(@id, "braintree-paypal-mini-cart")]'; + protected $braintreePaypalCheckoutButton = 'button[id^="braintree-paypal-mini-cart"]'; /** * Locator value for "Proceed to Checkout" button. @@ -124,8 +124,16 @@ public function openMiniCart() */ public function clickBraintreePaypalButton() { - $this->_rootElement->find($this->braintreePaypalCheckoutButton, Locator::SELECTOR_XPATH) + // Button can be enabled/disabled few times. + sleep(3); + + $windowsCount = count($this->browser->getWindowHandles()); + $this->_rootElement->find($this->braintreePaypalCheckoutButton) ->click(); + $browser = $this->browser; + $this->browser->waitUntil(function () use ($browser, $windowsCount) { + return count($browser->getWindowHandles()) === ($windowsCount + 1) ? true: null; + }); } /** From 98d1c9a0d188685792e038cccefb89ada6836f43 Mon Sep 17 00:00:00 2001 From: Maxim Tkachuk <m.tkachuk@ism-ukraine.com> Date: Thu, 23 May 2019 11:13:11 +0300 Subject: [PATCH 411/773] magento/magento2#14071: Not able to change a position of last two related products in case of I've 20+ related products. --- .../AdminSimpleSetEditRelatedProductsTest.xml | 32 +++++++++++++++++++ .../dynamic-rows/templates/grid.html | 22 ++++++++++--- 2 files changed, 49 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminSimpleSetEditRelatedProductsTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminSimpleSetEditRelatedProductsTest.xml index b06502ce94c65..4803c1be6c936 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminSimpleSetEditRelatedProductsTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminSimpleSetEditRelatedProductsTest.xml @@ -22,6 +22,11 @@ <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> <createData entity="SimpleProduct2" stepKey="simpleProduct0"/> <createData entity="SimpleProduct2" stepKey="simpleProduct1"/> + <createData entity="SimpleProduct2" stepKey="simpleProduct2"/> + <createData entity="SimpleProduct2" stepKey="simpleProduct3"/> + <createData entity="SimpleProduct2" stepKey="simpleProduct4"/> + <createData entity="SimpleProduct2" stepKey="simpleProduct5"/> + <createData entity="SimpleProduct2" stepKey="simpleProduct6"/> </before> <after> <!-- Delete simple product --> @@ -31,6 +36,11 @@ <amOnPage url="{{AdminLogoutPage.url}}" stepKey="amOnLogoutPage"/> <deleteData createDataKey="simpleProduct0" stepKey="deleteSimpleProduct0"/> <deleteData createDataKey="simpleProduct1" stepKey="deleteSimpleProduct1"/> + <deleteData createDataKey="simpleProduct2" stepKey="deleteSimpleProduct2"/> + <deleteData createDataKey="simpleProduct3" stepKey="deleteSimpleProduct3"/> + <deleteData createDataKey="simpleProduct4" stepKey="deleteSimpleProduct4"/> + <deleteData createDataKey="simpleProduct5" stepKey="deleteSimpleProduct5"/> + <deleteData createDataKey="simpleProduct6" stepKey="deleteSimpleProduct6"/> </after> <!--Create product--> @@ -69,6 +79,28 @@ <conditionalClick selector="{{AdminProductFormRelatedUpSellCrossSellSection.relatedDropdown}}" dependentSelector="{{AdminProductFormRelatedUpSellCrossSellSection.relatedDependent}}" visible="false" stepKey="openDropDownIfClosedRelatedSee"/> <see selector="{{AdminProductFormRelatedUpSellCrossSellSection.selectedRelatedProduct}}" userInput="$$simpleProduct1.sku$$" stepKey="seeRelatedProduct"/> + <!--See more related products in admin--> + <actionGroup ref="addRelatedProductBySku" stepKey="addRelatedProduct2"> + <argument name="sku" value="$$simpleProduct2.sku$$"/> + </actionGroup> + <actionGroup ref="addRelatedProductBySku" stepKey="addRelatedProduct3"> + <argument name="sku" value="$$simpleProduct3.sku$$"/> + </actionGroup> + <actionGroup ref="addRelatedProductBySku" stepKey="addRelatedProduct4"> + <argument name="sku" value="$$simpleProduct4.sku$$"/> + </actionGroup> + <actionGroup ref="addRelatedProductBySku" stepKey="addRelatedProduct5"> + <argument name="sku" value="$$simpleProduct5.sku$$"/> + </actionGroup> + <actionGroup ref="addRelatedProductBySku" stepKey="addRelatedProduct6"> + <argument name="sku" value="$$simpleProduct6.sku$$"/> + </actionGroup> + <scrollTo selector="{{AdminProductFormRelatedUpSellCrossSellSection.relatedDropdown}}" stepKey="scrollTo2"/> + <conditionalClick selector="{{AdminProductFormRelatedUpSellCrossSellSection.relatedDropdown}}" dependentSelector="{{AdminProductFormRelatedUpSellCrossSellSection.relatedDependent}}" visible="false" stepKey="openDropDownIfClosedRelatedSee2"/> + <see selector="{{AdminProductFormRelatedUpSellCrossSellSection.selectedRelatedProduct}}" userInput="$$simpleProduct6.sku$$" stepKey="seeSixthRelatedProduct"/> + <selectOption selector=".admin__collapsible-block-wrapper[data-index='related'] .admin__control-select" userInput="5" stepKey="selectFivePerPage"/> + <dontSee selector="{{AdminProductFormRelatedUpSellCrossSellSection.selectedRelatedProduct}}" userInput="$$simpleProduct6.sku$$" stepKey="dontSeeSixthRelatedProduct"/> + <!--See related product in storefront--> <amOnPage url="{{SimpleProduct3.sku}}.html" stepKey="goToStorefront"/> <waitForPageLoad stepKey="waitForStorefront"/> diff --git a/app/code/Magento/Ui/view/base/web/templates/dynamic-rows/templates/grid.html b/app/code/Magento/Ui/view/base/web/templates/dynamic-rows/templates/grid.html index e5d73a62b329e..b214d974e0d53 100644 --- a/app/code/Magento/Ui/view/base/web/templates/dynamic-rows/templates/grid.html +++ b/app/code/Magento/Ui/view/base/web/templates/dynamic-rows/templates/grid.html @@ -16,11 +16,23 @@ <div class="admin__field-control" data-role="grid-wrapper"> <div class="admin__control-table-pagination" visible="!!$data.getRecordCount()"> - <div class="admin__data-grid-pager"> - <button class="action-previous" type="button" data-bind="attr: {title: $t('Previous Page')}, click: previousPage, disable: isFirst()"></button> - <input class="admin__control-text" type="number" data-bind="attr: {id: ++ko.uid}, value: currentPage"> - <label class="admin__control-support-text" data-bind="attr: {for: ko.uid}, text: 'of ' + pages()"></label> - <button class="action-next" type="button" data-bind="attr: {title: $t('Next Page')}, click: nextPage, disable: isLast()"></button> + <div class="admin__data-grid-pager-wrap"> + <select class="admin__control-select" data-bind="value:pageSize, event:{change: reload}"> + <option value="5">5</option> + <option value="20" selected="selected">20</option> + <option value="30">30</option> + <option value="50">50</option> + <option value="100">100</option> + <option value="200">200</option> + <option value="500">500</option> + </select> + <label class="admin__control-support-text" data-bind="text: $t('per page')"></label> + <div class="admin__data-grid-pager"> + <button class="action-previous" type="button" data-bind="attr: {title: $t('Previous Page')}, click: previousPage, disable: isFirst()"></button> + <input class="admin__control-text" type="number" data-bind="attr: {id: ++ko.uid}, value: currentPage"> + <label class="admin__control-support-text" data-bind="attr: {for: ko.uid}, text: 'of ' + pages()"></label> + <button class="action-next" type="button" data-bind="attr: {title: $t('Next Page')}, click: nextPage, disable: isLast()"></button> + </div> </div> </div> From 8353229c86df511a6e1a480770b452c10684b000 Mon Sep 17 00:00:00 2001 From: Viktor Sevch <svitja@ukr.net> Date: Thu, 23 May 2019 11:52:39 +0300 Subject: [PATCH 412/773] MC-16371: [FT] CheckoutWithBraintreePaypalMinicartTest fails on Bamboo --- .../app/Magento/Checkout/Test/Block/Cart/Sidebar.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Cart/Sidebar.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Cart/Sidebar.php index eeb37384437a1..7f9c6717c7ea5 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Cart/Sidebar.php +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Cart/Sidebar.php @@ -131,9 +131,11 @@ public function clickBraintreePaypalButton() $this->_rootElement->find($this->braintreePaypalCheckoutButton) ->click(); $browser = $this->browser; - $this->browser->waitUntil(function () use ($browser, $windowsCount) { - return count($browser->getWindowHandles()) === ($windowsCount + 1) ? true: null; - }); + $this->browser->waitUntil( + function () use ($browser, $windowsCount) { + return count($browser->getWindowHandles()) === ($windowsCount + 1) ? true: null; + } + ); } /** From a800c6b9e24ad23d97e4a9c8369a1042aaf23b5b Mon Sep 17 00:00:00 2001 From: Shikha Mishra <shikhamishra@cedcoss.com> Date: Thu, 23 May 2019 18:32:57 +0530 Subject: [PATCH 413/773] Fixed Static Test --- .../Observer/SaveDownloadableOrderItemObserver.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Downloadable/Observer/SaveDownloadableOrderItemObserver.php b/app/code/Magento/Downloadable/Observer/SaveDownloadableOrderItemObserver.php index fed153bdfbbc2..d8d259f527ccc 100644 --- a/app/code/Magento/Downloadable/Observer/SaveDownloadableOrderItemObserver.php +++ b/app/code/Magento/Downloadable/Observer/SaveDownloadableOrderItemObserver.php @@ -132,11 +132,11 @@ public function execute(\Magento\Framework\Event\Observer $observer) ); $linkPurchased->setLinkSectionTitle($linkSectionTitle)->save(); - $linkStatus = \Magento\Downloadable\Model\Link\Purchased\Item::LINK_STATUS_PENDING; + $linkStatus = \Magento\Downloadable\Model\Link\Purchased\Item::LINK_STATUS_PENDING; if ($orderStatusToEnableItem == \Magento\Sales\Model\Order\Item::STATUS_PENDING || $orderItem->getOrder()->getState() == \Magento\Sales\Model\Order::STATE_COMPLETE ) { - $linkStatus = \Magento\Downloadable\Model\Link\Purchased\Item::LINK_STATUS_AVAILABLE; + $linkStatus = \Magento\Downloadable\Model\Link\Purchased\Item::LINK_STATUS_AVAILABLE; } foreach ($linkIds as $linkId) { From e2f06b37cc7a6640fa24b59971f5aee3cf96641d Mon Sep 17 00:00:00 2001 From: Shikha Mishra <shikhamishra@cedcoss.com> Date: Thu, 23 May 2019 18:41:52 +0530 Subject: [PATCH 414/773] Fixed Static test --- .../Downloadable/Observer/SaveDownloadableOrderItemObserver.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/code/Magento/Downloadable/Observer/SaveDownloadableOrderItemObserver.php b/app/code/Magento/Downloadable/Observer/SaveDownloadableOrderItemObserver.php index d8d259f527ccc..d398c843946b4 100644 --- a/app/code/Magento/Downloadable/Observer/SaveDownloadableOrderItemObserver.php +++ b/app/code/Magento/Downloadable/Observer/SaveDownloadableOrderItemObserver.php @@ -176,7 +176,6 @@ public function execute(\Magento\Framework\Event\Observer $observer) } } } - return $this; } From b65ff722bdf4d75349d1e6f00a3d9f36743753cb Mon Sep 17 00:00:00 2001 From: Andrey Legayev <andrey@ven.com> Date: Thu, 16 May 2019 15:48:03 +0300 Subject: [PATCH 415/773] Fix layout xml and page layout caching issue on redis cluster under high load Bugs which were fixed: - $this->pageLayout was not checked after reading from cache, but was used as is - two cache items were used in once place instead of one (performance impact) Changes: - replace 2 cache items by 1 - it should improve performance - add "_MERGED" to cache key suffix to have compatibility with old cache keys during deployment of new version --- .../Framework/View/Layout/MergeTest.php | 22 ++++++++-- .../Framework/View/Model/Layout/Merge.php | 35 ++++++++++----- .../View/Test/Unit/Model/Layout/MergeTest.php | 43 +++++++++++++++++++ 3 files changed, 87 insertions(+), 13 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Framework/View/Layout/MergeTest.php b/dev/tests/integration/testsuite/Magento/Framework/View/Layout/MergeTest.php index 8404884a7cf5c..60cd1ff9813f8 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/View/Layout/MergeTest.php +++ b/dev/tests/integration/testsuite/Magento/Framework/View/Layout/MergeTest.php @@ -41,6 +41,11 @@ class MergeTest extends \PHPUnit\Framework\TestCase */ protected $_cache; + /** + * @var \Magento\Framework\Serialize\SerializerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $_serializer; + /** * @var \PHPUnit_Framework_MockObject_MockObject */ @@ -100,6 +105,8 @@ protected function setUp() $this->_cache = $this->getMockForAbstractClass(\Magento\Framework\Cache\FrontendInterface::class); + $this->_serializer = $this->getMockForAbstractClass(\Magento\Framework\Serialize\SerializerInterface::class); + $this->_theme = $this->createMock(\Magento\Theme\Model\Theme::class); $this->_theme->expects($this->any())->method('isPhysical')->will($this->returnValue(true)); $this->_theme->expects($this->any())->method('getArea')->will($this->returnValue('area')); @@ -140,6 +147,7 @@ function ($filename) use ($fileDriver) { 'resource' => $this->_resource, 'appState' => $this->_appState, 'cache' => $this->_cache, + 'serializer' => $this->_serializer, 'theme' => $this->_theme, 'validator' => $this->_layoutValidator, 'logger' => $this->_logger, @@ -276,9 +284,16 @@ public function testLoadFileSystemWithPageLayout() public function testLoadCache() { + $cacheValue = [ + "pageLayout" => "1column", + "layout" => self::FIXTURE_LAYOUT_XML + ]; + $this->_cache->expects($this->at(0))->method('load') - ->with('LAYOUT_area_STORE20_100c6a4ccd050e33acef0553f24ef399961') - ->will($this->returnValue(self::FIXTURE_LAYOUT_XML)); + ->with('LAYOUT_area_STORE20_100c6a4ccd050e33acef0553f24ef399961_page_layout_merged') + ->will($this->returnValue(json_encode($cacheValue))); + + $this->_serializer->expects($this->once())->method('unserialize')->willReturn($cacheValue); $this->assertEmpty($this->_model->getHandles()); $this->assertEmpty($this->_model->asString()); @@ -425,7 +440,8 @@ public function testLoadWithInvalidLayout() ->willThrowException(new \Exception('Layout is invalid.')); $suffix = md5(implode('|', $this->_model->getHandles())); - $cacheId = "LAYOUT_{$this->_theme->getArea()}_STORE{$this->scope->getId()}_{$this->_theme->getId()}{$suffix}"; + $cacheId = "LAYOUT_{$this->_theme->getArea()}_STORE{$this->scope->getId()}" + . "_{$this->_theme->getId()}{$suffix}_page_layout_merged"; $messages = $this->_layoutValidator->getMessages(); // Testing error message is logged with logger diff --git a/lib/internal/Magento/Framework/View/Model/Layout/Merge.php b/lib/internal/Magento/Framework/View/Model/Layout/Merge.php index a0cdbfb7d8fe7..a4f9a1f665529 100644 --- a/lib/internal/Magento/Framework/View/Model/Layout/Merge.php +++ b/lib/internal/Magento/Framework/View/Model/Layout/Merge.php @@ -5,10 +5,12 @@ */ namespace Magento\Framework\View\Model\Layout; +use Magento\Framework\App\ObjectManager; use Magento\Framework\App\State; use Magento\Framework\Config\Dom\ValidationException; use Magento\Framework\Filesystem\DriverPool; use Magento\Framework\Filesystem\File\ReadFactory; +use Magento\Framework\Serialize\SerializerInterface; use Magento\Framework\View\Layout\LayoutCacheKeyInterface; use Magento\Framework\View\Model\Layout\Update\Validator; @@ -42,7 +44,7 @@ class Merge implements \Magento\Framework\View\Layout\ProcessorInterface /** * Cache id suffix for page layout */ - const PAGE_LAYOUT_CACHE_SUFFIX = 'page_layout'; + const PAGE_LAYOUT_CACHE_SUFFIX = 'page_layout_merged'; /** * @var \Magento\Framework\View\Design\ThemeInterface @@ -54,6 +56,11 @@ class Merge implements \Magento\Framework\View\Layout\ProcessorInterface */ private $scope; + /** + * @var SerializerInterface + */ + private $serializer; + /** * In-memory cache for loaded layout updates * @@ -173,10 +180,11 @@ class Merge implements \Magento\Framework\View\Layout\ProcessorInterface * @param \Magento\Framework\Cache\FrontendInterface $cache * @param \Magento\Framework\View\Model\Layout\Update\Validator $validator * @param \Psr\Log\LoggerInterface $logger - * @param ReadFactory $readFactory , + * @param ReadFactory $readFactory * @param \Magento\Framework\View\Design\ThemeInterface $theme Non-injectable theme instance * @param string $cacheSuffix * @param LayoutCacheKeyInterface $layoutCacheKey + * @param SerializerInterface|null $serializer * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -191,7 +199,8 @@ public function __construct( ReadFactory $readFactory, \Magento\Framework\View\Design\ThemeInterface $theme = null, $cacheSuffix = '', - LayoutCacheKeyInterface $layoutCacheKey = null + LayoutCacheKeyInterface $layoutCacheKey = null, + SerializerInterface $serializer = null ) { $this->theme = $theme ?: $design->getDesignTheme(); $this->scope = $scopeResolver->getScope(); @@ -205,6 +214,7 @@ public function __construct( $this->cacheSuffix = $cacheSuffix; $this->layoutCacheKey = $layoutCacheKey ?: \Magento\Framework\App\ObjectManager::getInstance()->get(LayoutCacheKeyInterface::class); + $this->serializer = $serializer ?: ObjectManager::getInstance()->get(SerializerInterface::class); } /** @@ -437,12 +447,12 @@ public function load($handles = []) $this->addHandle($handles); - $cacheId = $this->getCacheId(); - $cacheIdPageLayout = $cacheId . '_' . self::PAGE_LAYOUT_CACHE_SUFFIX; + $cacheId = $this->getCacheId() . '_' . self::PAGE_LAYOUT_CACHE_SUFFIX; $result = $this->_loadCache($cacheId); - if ($result) { - $this->addUpdate($result); - $this->pageLayout = $this->_loadCache($cacheIdPageLayout); + if ($result !== false && $result !== null) { + $data = $this->serializer->unserialize($result); + $this->pageLayout = $data["pageLayout"]; + $this->addUpdate($data["layout"]); foreach ($this->getHandles() as $handle) { $this->allHandles[$handle] = $this->handleProcessed; } @@ -455,8 +465,13 @@ public function load($handles = []) $layout = $this->asString(); $this->_validateMergedLayout($cacheId, $layout); - $this->_saveCache($layout, $cacheId, $this->getHandles()); - $this->_saveCache((string)$this->pageLayout, $cacheIdPageLayout, $this->getHandles()); + + $data = [ + "pageLayout" => (string)$this->pageLayout, + "layout" => $layout + ]; + $this->_saveCache($this->serializer->serialize($data), $cacheId, $this->getHandles()); + return $this; } diff --git a/lib/internal/Magento/Framework/View/Test/Unit/Model/Layout/MergeTest.php b/lib/internal/Magento/Framework/View/Test/Unit/Model/Layout/MergeTest.php index 112d171f2574b..ddcd6ecb45c43 100644 --- a/lib/internal/Magento/Framework/View/Test/Unit/Model/Layout/MergeTest.php +++ b/lib/internal/Magento/Framework/View/Test/Unit/Model/Layout/MergeTest.php @@ -28,11 +28,21 @@ class MergeTest extends \PHPUnit\Framework\TestCase */ private $scope; + /** + * @var \Magento\Framework\Cache\FrontendInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $cache; + /** * @var \Magento\Framework\View\Model\Layout\Update\Validator|\PHPUnit_Framework_MockObject_MockObject */ private $layoutValidator; + /** + * @var \Magento\Framework\Serialize\SerializerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $serializer; + /** * @var \Psr\Log\LoggerInterface|\PHPUnit_Framework_MockObject_MockObject */ @@ -53,10 +63,12 @@ protected function setUp() $this->objectManagerHelper = new ObjectManager($this); $this->scope = $this->getMockForAbstractClass(\Magento\Framework\Url\ScopeInterface::class); + $this->cache = $this->getMockForAbstractClass(\Magento\Framework\Cache\FrontendInterface::class); $this->layoutValidator = $this->getMockBuilder(\Magento\Framework\View\Model\Layout\Update\Validator::class) ->disableOriginalConstructor() ->getMock(); $this->logger = $this->getMockForAbstractClass(\Psr\Log\LoggerInterface::class); + $this->serializer = $this->getMockForAbstractClass(\Magento\Framework\Serialize\SerializerInterface::class); $this->appState = $this->getMockBuilder(\Magento\Framework\App\State::class) ->disableOriginalConstructor() ->getMock(); @@ -70,10 +82,12 @@ protected function setUp() \Magento\Framework\View\Model\Layout\Merge::class, [ 'scope' => $this->scope, + 'cache' => $this->cache, 'layoutValidator' => $this->layoutValidator, 'logger' => $this->logger, 'appState' => $this->appState, 'layoutCacheKey' => $this->layoutCacheKeyMock, + 'serializer' => $this->serializer, ] ); } @@ -104,4 +118,33 @@ public function testValidateMergedLayoutThrowsException() $this->model->load(); } + + /** + * Test that merged layout is saved to cache if it wasn't cached before. + */ + public function testSaveToCache() + { + $this->scope->expects($this->once())->method('getId')->willReturn(1); + $this->cache->expects($this->once())->method('save'); + + $this->model->load(); + } + + /** + * Test that merged layout is not re-saved to cache when it was loaded from cache. + */ + public function testNoSaveToCacheWhenCachePresent() + { + $cacheValue = [ + "pageLayout" => "1column", + "layout" => "<body></body>" + ]; + + $this->scope->expects($this->once())->method('getId')->willReturn(1); + $this->cache->expects($this->once())->method('load')->willReturn(json_encode($cacheValue)); + $this->serializer->expects($this->once())->method('unserialize')->willReturn($cacheValue); + $this->cache->expects($this->never())->method('save'); + + $this->model->load(); + } } From cdefb91354bbb9a57c0ab30985292094f464b66b Mon Sep 17 00:00:00 2001 From: Maksym Aposov <xmav@users.noreply.github.com> Date: Wed, 22 May 2019 13:38:09 -0500 Subject: [PATCH 416/773] Fix layout xml and page layout caching issue on redis cluster under high load -Fixed static tests --- lib/internal/Magento/Framework/View/Model/Layout/Merge.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/View/Model/Layout/Merge.php b/lib/internal/Magento/Framework/View/Model/Layout/Merge.php index a4f9a1f665529..3ccc144ebecd5 100644 --- a/lib/internal/Magento/Framework/View/Model/Layout/Merge.php +++ b/lib/internal/Magento/Framework/View/Model/Layout/Merge.php @@ -293,6 +293,7 @@ public function getHandles() /** * Add the first existing (declared in layout updates) page handle along with all parents to the update. + * * Return whether any page handles have been added or not. * * @param string[] $handlesToTry @@ -325,6 +326,8 @@ public function pageHandleExists($handleName) } /** + * Page layout type + * * @return string|null */ public function getPageLayout() @@ -617,7 +620,7 @@ protected function _fetchDbLayoutUpdates($handle) */ public function validateUpdate($handle, $updateXml) { - return; + return null; } /** @@ -945,6 +948,7 @@ public function getScope() public function getCacheId() { $layoutCacheKeys = $this->layoutCacheKey->getCacheKeys(); + // phpcs:ignore Magento2.Security.InsecureFunction return $this->generateCacheId(md5(implode('|', array_merge($this->getHandles(), $layoutCacheKeys)))); } } From 590c5864102dfbc1df6b81531b019b2556c8e90b Mon Sep 17 00:00:00 2001 From: Maksym Aposov <xmav@users.noreply.github.com> Date: Wed, 22 May 2019 18:27:54 -0500 Subject: [PATCH 417/773] Fix layout xml and page layout caching issue on redis cluster under high load -Fixed static tests --- .../testsuite/Magento/Framework/View/Layout/MergeTest.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dev/tests/integration/testsuite/Magento/Framework/View/Layout/MergeTest.php b/dev/tests/integration/testsuite/Magento/Framework/View/Layout/MergeTest.php index 60cd1ff9813f8..c8c80a9647020 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/View/Layout/MergeTest.php +++ b/dev/tests/integration/testsuite/Magento/Framework/View/Layout/MergeTest.php @@ -79,7 +79,8 @@ class MergeTest extends \PHPUnit\Framework\TestCase protected function setUp() { $files = []; - foreach (glob(__DIR__ . '/_mergeFiles/layout/*.xml') as $filename) { + $fileDriver = new \Magento\Framework\Filesystem\Driver\File(); + foreach ($fileDriver->readDirectory(__DIR__ . '/_mergeFiles/layout/') as $filename) { $files[] = new \Magento\Framework\View\File($filename, 'Magento_Widget'); } $fileSource = $this->getMockForAbstractClass(\Magento\Framework\View\File\CollectorInterface::class); @@ -439,6 +440,7 @@ public function testLoadWithInvalidLayout() ->method('isValid') ->willThrowException(new \Exception('Layout is invalid.')); + // phpcs:ignore Magento2.Security.InsecureFunction $suffix = md5(implode('|', $this->_model->getHandles())); $cacheId = "LAYOUT_{$this->_theme->getArea()}_STORE{$this->scope->getId()}" . "_{$this->_theme->getId()}{$suffix}_page_layout_merged"; From 347280894bb96aeaee077fb509b28a2a90d59f01 Mon Sep 17 00:00:00 2001 From: Maksym Aposov <xmav@users.noreply.github.com> Date: Wed, 22 May 2019 18:28:50 -0500 Subject: [PATCH 418/773] Fix layout xml and page layout caching issue on redis cluster under high load -Fixed static tests --- .../Framework/View/Test/Unit/Model/Layout/MergeTest.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/internal/Magento/Framework/View/Test/Unit/Model/Layout/MergeTest.php b/lib/internal/Magento/Framework/View/Test/Unit/Model/Layout/MergeTest.php index ddcd6ecb45c43..3060ac64d74bf 100644 --- a/lib/internal/Magento/Framework/View/Test/Unit/Model/Layout/MergeTest.php +++ b/lib/internal/Magento/Framework/View/Test/Unit/Model/Layout/MergeTest.php @@ -11,6 +11,11 @@ use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; use Magento\Framework\View\Layout\LayoutCacheKeyInterface; +/** + * Class MergeTest + * + * @package Magento\Framework\View\Test\Unit\Model\Layout + */ class MergeTest extends \PHPUnit\Framework\TestCase { /** From 44ab0301e1fb717fc0a977ada8b783a0d4fdc39a Mon Sep 17 00:00:00 2001 From: Vitaliy Honcharenko <vgoncharenko@magento.com> Date: Thu, 23 May 2019 15:38:12 -0500 Subject: [PATCH 419/773] MC-16239: Search result page contain 24k results - fix default template for mapping --- .../Model/Client/Elasticsearch.php | 21 +++++----- .../Model/Client/Elasticsearch.php | 18 +++++---- .../Model/Client/ElasticsearchTest.php | 32 ++++++++-------- .../Model/Client/Elasticsearch.php | 15 ++++---- .../Unit/Model/Client/ElasticsearchTest.php | 38 ++++++++++--------- 5 files changed, 66 insertions(+), 58 deletions(-) diff --git a/app/code/Magento/Elasticsearch/Elasticsearch5/Model/Client/Elasticsearch.php b/app/code/Magento/Elasticsearch/Elasticsearch5/Model/Client/Elasticsearch.php index c05e8a441604d..cada9e1ec6e4d 100644 --- a/app/code/Magento/Elasticsearch/Elasticsearch5/Model/Client/Elasticsearch.php +++ b/app/code/Magento/Elasticsearch/Elasticsearch5/Model/Client/Elasticsearch.php @@ -266,6 +266,16 @@ public function addFieldsMapping(array $fields, $index, $entityType) ], ], ], + [ + 'position_mapping' => [ + 'match' => 'position_*', + 'match_mapping_type' => 'string', + 'mapping' => [ + 'type' => 'integer', + 'index' => false, + ], + ], + ], [ 'string_mapping' => [ 'match' => '*', @@ -275,16 +285,7 @@ public function addFieldsMapping(array $fields, $index, $entityType) 'index' => false, ]), ], - ], - [ - 'position_mapping' => [ - 'match' => 'position_*', - 'match_mapping_type' => 'string', - 'mapping' => [ - 'type' => 'int', - ], - ], - ], + ] ], ], ], diff --git a/app/code/Magento/Elasticsearch/Model/Client/Elasticsearch.php b/app/code/Magento/Elasticsearch/Model/Client/Elasticsearch.php index 44ab0dbc4d46c..1870051772520 100644 --- a/app/code/Magento/Elasticsearch/Model/Client/Elasticsearch.php +++ b/app/code/Magento/Elasticsearch/Model/Client/Elasticsearch.php @@ -252,29 +252,31 @@ public function addFieldsMapping(array $fields, $index, $entityType) 'match' => 'price_*', 'match_mapping' => 'string', 'mapping' => [ - 'type' => 'float' + 'type' => 'float', + 'store' => true ], ], ], [ - 'string_mapping' => [ - 'match' => '*', + 'position_mapping' => [ + 'match' => 'position_*', 'match_mapping' => 'string', 'mapping' => [ - 'type' => 'string', + 'type' => 'integer', 'index' => 'no' ], ], ], [ - 'position_mapping' => [ - 'match' => 'position_*', + 'string_mapping' => [ + 'match' => '*', 'match_mapping' => 'string', 'mapping' => [ - 'type' => 'int' + 'type' => 'string', + 'index' => 'no' ], ], - ], + ] ], ], ], diff --git a/app/code/Magento/Elasticsearch/Test/Unit/Elasticsearch5/Model/Client/ElasticsearchTest.php b/app/code/Magento/Elasticsearch/Test/Unit/Elasticsearch5/Model/Client/ElasticsearchTest.php index 8fbd183441b6d..e5f672fd2e766 100644 --- a/app/code/Magento/Elasticsearch/Test/Unit/Elasticsearch5/Model/Client/ElasticsearchTest.php +++ b/app/code/Magento/Elasticsearch/Test/Unit/Elasticsearch5/Model/Client/ElasticsearchTest.php @@ -362,21 +362,22 @@ public function testAddFieldsMapping() ], ], [ - 'string_mapping' => [ - 'match' => '*', + 'position_mapping' => [ + 'match' => 'position_*', 'match_mapping_type' => 'string', 'mapping' => [ - 'type' => 'text', - 'index' => false, + 'type' => 'integer', + 'index' => false ], ], ], [ - 'position_mapping' => [ - 'match' => 'position_*', + 'string_mapping' => [ + 'match' => '*', 'match_mapping_type' => 'string', 'mapping' => [ - 'type' => 'int', + 'type' => 'text', + 'index' => false, ], ], ], @@ -429,24 +430,25 @@ public function testAddFieldsMappingFailure() ], ], [ - 'string_mapping' => [ - 'match' => '*', + 'position_mapping' => [ + 'match' => 'position_*', 'match_mapping_type' => 'string', 'mapping' => [ - 'type' => 'text', - 'index' => false, + 'type' => 'integer', + 'index' => false ], ], ], [ - 'position_mapping' => [ - 'match' => 'position_*', + 'string_mapping' => [ + 'match' => '*', 'match_mapping_type' => 'string', 'mapping' => [ - 'type' => 'int', + 'type' => 'text', + 'index' => false, ], ], - ], + ] ], ], ], diff --git a/app/code/Magento/Elasticsearch6/Model/Client/Elasticsearch.php b/app/code/Magento/Elasticsearch6/Model/Client/Elasticsearch.php index af39b24acda56..513b93a2b7e9f 100644 --- a/app/code/Magento/Elasticsearch6/Model/Client/Elasticsearch.php +++ b/app/code/Magento/Elasticsearch6/Model/Client/Elasticsearch.php @@ -262,22 +262,23 @@ public function addFieldsMapping(array $fields, $index, $entityType) ], ], [ - 'string_mapping' => [ - 'match' => '*', + 'position_mapping' => [ + 'match' => 'position_*', 'match_mapping_type' => 'string', 'mapping' => [ - 'type' => 'text', + 'type' => 'integer', 'index' => false, - 'copy_to' => '_search' ], ], ], [ - 'position_mapping' => [ - 'match' => 'position_*', + 'string_mapping' => [ + 'match' => '*', 'match_mapping_type' => 'string', 'mapping' => [ - 'type' => 'int', + 'type' => 'text', + 'index' => false, + 'copy_to' => '_search' ], ], ], diff --git a/app/code/Magento/Elasticsearch6/Test/Unit/Model/Client/ElasticsearchTest.php b/app/code/Magento/Elasticsearch6/Test/Unit/Model/Client/ElasticsearchTest.php index 8276d0dd8dbe8..fb26e9ea387d0 100644 --- a/app/code/Magento/Elasticsearch6/Test/Unit/Model/Client/ElasticsearchTest.php +++ b/app/code/Magento/Elasticsearch6/Test/Unit/Model/Client/ElasticsearchTest.php @@ -361,25 +361,26 @@ public function testAddFieldsMapping() ], ], [ - 'string_mapping' => [ - 'match' => '*', + 'position_mapping' => [ + 'match' => 'position_*', 'match_mapping_type' => 'string', 'mapping' => [ - 'type' => 'text', - 'index' => false, - 'copy_to' => '_search' + 'type' => 'integer', + 'index' => false ], ], ], [ - 'position_mapping' => [ - 'match' => 'position_*', + 'string_mapping' => [ + 'match' => '*', 'match_mapping_type' => 'string', 'mapping' => [ - 'type' => 'int', + 'type' => 'text', + 'index' => false, + 'copy_to' => '_search' ], ], - ], + ] ], ], ], @@ -428,25 +429,26 @@ public function testAddFieldsMappingFailure() ], ], [ - 'string_mapping' => [ - 'match' => '*', + 'position_mapping' => [ + 'match' => 'position_*', 'match_mapping_type' => 'string', 'mapping' => [ - 'type' => 'text', - 'index' => false, - 'copy_to' => '_search' + 'type' => 'integer', + 'index' => false ], ], ], [ - 'position_mapping' => [ - 'match' => 'position_*', + 'string_mapping' => [ + 'match' => '*', 'match_mapping_type' => 'string', 'mapping' => [ - 'type' => 'int', + 'type' => 'text', + 'index' => false, + 'copy_to' => '_search' ], ], - ], + ] ], ], ], From 8e4e59f32c4f9e931ee545b87a9252b9810cdd48 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun <ogorkun@magento.com> Date: Thu, 23 May 2019 17:27:23 -0500 Subject: [PATCH 420/773] MAGETWO-99817: Remove new dependencies added for design edit validations --- app/code/Magento/Catalog/Model/Category.php | 40 ++++++++++++++----- app/code/Magento/Catalog/Model/Product.php | 40 ++++++++++++++----- app/code/Magento/Cms/Model/PageRepository.php | 40 ++++++++++++++----- 3 files changed, 93 insertions(+), 27 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Category.php b/app/code/Magento/Catalog/Model/Category.php index 61c9962486ad1..6f45787fbd4f1 100644 --- a/app/code/Magento/Catalog/Model/Category.php +++ b/app/code/Magento/Catalog/Model/Category.php @@ -246,8 +246,6 @@ class Category extends \Magento\Catalog\Model\AbstractModel implements * @param \Magento\Framework\Model\ResourceModel\AbstractResource $resource * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data - * @param UserContextInterface|null $userContext - * @param AuthorizationInterface|null $authorization * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -271,9 +269,7 @@ public function __construct( CategoryRepositoryInterface $categoryRepository, \Magento\Framework\Model\ResourceModel\AbstractResource $resource = null, \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, - array $data = [], - ?UserContextInterface $userContext = null, - ?AuthorizationInterface $authorization = null + array $data = [] ) { $this->metadataService = $metadataService; $this->_treeModel = $categoryTreeResource; @@ -298,8 +294,6 @@ public function __construct( $resourceCollection, $data ); - $this->userContext = $userContext ?? ObjectManager::getInstance()->get(UserContextInterface::class); - $this->authorization = $authorization ?? ObjectManager::getInstance()->get(AuthorizationInterface::class); } /** @@ -935,18 +929,46 @@ public function beforeDelete() return parent::beforeDelete(); } + /** + * Get user context. + * + * @return UserContextInterface + */ + private function getUserContext(): UserContextInterface + { + if (!$this->userContext) { + $this->userContext = ObjectManager::getInstance()->get(UserContextInterface::class); + } + + return $this->userContext; + } + + /** + * Get authorization service. + * + * @return AuthorizationInterface + */ + private function getAuthorization(): AuthorizationInterface + { + if (!$this->authorization) { + $this->authorization = ObjectManager::getInstance()->get(AuthorizationInterface::class); + } + + return $this->authorization; + } + /** * @inheritDoc */ public function beforeSave() { //Validate changing of design. - $userType = $this->userContext->getUserType(); + $userType = $this->getUserContext()->getUserType(); if (( $userType === UserContextInterface::USER_TYPE_ADMIN || $userType === UserContextInterface::USER_TYPE_INTEGRATION ) - && !$this->authorization->isAllowed('Magento_Catalog::edit_category_design') + && !$this->getAuthorization()->isAllowed('Magento_Catalog::edit_category_design') ) { foreach ($this->_designAttributes as $attributeCode) { $this->setData($attributeCode, $value = $this->getOrigData($attributeCode)); diff --git a/app/code/Magento/Catalog/Model/Product.php b/app/code/Magento/Catalog/Model/Product.php index d43bc51eb7273..34f31dcc86248 100644 --- a/app/code/Magento/Catalog/Model/Product.php +++ b/app/code/Magento/Catalog/Model/Product.php @@ -403,8 +403,6 @@ class Product extends \Magento\Catalog\Model\AbstractModel implements * @param array $data * @param \Magento\Eav\Model\Config|null $config * @param FilterProductCustomAttribute|null $filterCustomAttribute - * @param UserContextInterface|null $userContext - * @param AuthorizationInterface|null $authorization * @SuppressWarnings(PHPMD.ExcessiveParameterList) * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ @@ -445,9 +443,7 @@ public function __construct( \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface $joinProcessor, array $data = [], \Magento\Eav\Model\Config $config = null, - FilterProductCustomAttribute $filterCustomAttribute = null, - ?UserContextInterface $userContext = null, - ?AuthorizationInterface $authorization = null + FilterProductCustomAttribute $filterCustomAttribute = null ) { $this->metadataService = $metadataService; $this->_itemOptionFactory = $itemOptionFactory; @@ -489,8 +485,6 @@ public function __construct( $this->eavConfig = $config ?? ObjectManager::getInstance()->get(\Magento\Eav\Model\Config::class); $this->filterCustomAttribute = $filterCustomAttribute ?? ObjectManager::getInstance()->get(FilterProductCustomAttribute::class); - $this->userContext = $userContext ?? ObjectManager::getInstance()->get(UserContextInterface::class); - $this->authorization = $authorization ?? ObjectManager::getInstance()->get(AuthorizationInterface::class); } /** @@ -877,6 +871,34 @@ public function getAttributes($groupId = null, $skipSuper = false) return $attributes; } + /** + * Get user context. + * + * @return UserContextInterface + */ + private function getUserContext(): UserContextInterface + { + if (!$this->userContext) { + $this->userContext = ObjectManager::getInstance()->get(UserContextInterface::class); + } + + return $this->userContext; + } + + /** + * Get authorization service. + * + * @return AuthorizationInterface + */ + private function getAuthorization(): AuthorizationInterface + { + if (!$this->authorization) { + $this->authorization = ObjectManager::getInstance()->get(AuthorizationInterface::class); + } + + return $this->authorization; + } + /** * Check product options and type options and save them, too * @@ -895,12 +917,12 @@ public function beforeSave() $this->getTypeInstance()->beforeSave($this); //Validate changing of design. - $userType = $this->userContext->getUserType(); + $userType = $this->getUserContext()->getUserType(); if (( $userType === UserContextInterface::USER_TYPE_ADMIN || $userType === UserContextInterface::USER_TYPE_INTEGRATION ) - && !$this->authorization->isAllowed('Magento_Catalog::edit_product_design') + && !$this->getAuthorization()->isAllowed('Magento_Catalog::edit_product_design') ) { $this->setData('custom_design', $this->getOrigData('custom_design')); $this->setData('page_layout', $this->getOrigData('page_layout')); diff --git a/app/code/Magento/Cms/Model/PageRepository.php b/app/code/Magento/Cms/Model/PageRepository.php index 4b6c933c4fef1..1d2959103fc5d 100644 --- a/app/code/Magento/Cms/Model/PageRepository.php +++ b/app/code/Magento/Cms/Model/PageRepository.php @@ -92,8 +92,6 @@ class PageRepository implements PageRepositoryInterface * @param DataObjectProcessor $dataObjectProcessor * @param StoreManagerInterface $storeManager * @param CollectionProcessorInterface $collectionProcessor - * @param UserContextInterface|null $userContext - * @param AuthorizationInterface|null $authorization * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -105,9 +103,7 @@ public function __construct( DataObjectHelper $dataObjectHelper, DataObjectProcessor $dataObjectProcessor, StoreManagerInterface $storeManager, - CollectionProcessorInterface $collectionProcessor = null, - ?UserContextInterface $userContext = null, - ?AuthorizationInterface $authorization = null + CollectionProcessorInterface $collectionProcessor = null ) { $this->resource = $resource; $this->pageFactory = $pageFactory; @@ -118,8 +114,34 @@ public function __construct( $this->dataObjectProcessor = $dataObjectProcessor; $this->storeManager = $storeManager; $this->collectionProcessor = $collectionProcessor ?: $this->getCollectionProcessor(); - $this->userContext = $userContext ?? ObjectManager::getInstance()->get(UserContextInterface::class); - $this->authorization = $authorization ?? ObjectManager::getInstance()->get(AuthorizationInterface::class); + } + + /** + * Get user context. + * + * @return UserContextInterface + */ + private function getUserContext(): UserContextInterface + { + if (!$this->userContext) { + $this->userContext = ObjectManager::getInstance()->get(UserContextInterface::class); + } + + return $this->userContext; + } + + /** + * Get authorization service. + * + * @return AuthorizationInterface + */ + private function getAuthorization(): AuthorizationInterface + { + if (!$this->authorization) { + $this->authorization = ObjectManager::getInstance()->get(AuthorizationInterface::class); + } + + return $this->authorization; } /** @@ -137,12 +159,12 @@ public function save(\Magento\Cms\Api\Data\PageInterface $page) } try { //Validate changing of design. - $userType = $this->userContext->getUserType(); + $userType = $this->getUserContext()->getUserType(); if (( $userType === UserContextInterface::USER_TYPE_ADMIN || $userType === UserContextInterface::USER_TYPE_INTEGRATION ) - && !$this->authorization->isAllowed('Magento_Cms::save_design') + && !$this->getAuthorization()->isAllowed('Magento_Cms::save_design') ) { if (!$page->getId()) { $page->setLayoutUpdateXml(null); From 1524687560c4a71322eefd4448ff79d9ea334ac9 Mon Sep 17 00:00:00 2001 From: Shikha Mishra <shikhamishra@cedcoss.com> Date: Fri, 24 May 2019 10:49:45 +0530 Subject: [PATCH 421/773] Fixed Static Test --- .../Downloadable/Observer/SaveDownloadableOrderItemObserver.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Downloadable/Observer/SaveDownloadableOrderItemObserver.php b/app/code/Magento/Downloadable/Observer/SaveDownloadableOrderItemObserver.php index d398c843946b4..4f7939da478fa 100644 --- a/app/code/Magento/Downloadable/Observer/SaveDownloadableOrderItemObserver.php +++ b/app/code/Magento/Downloadable/Observer/SaveDownloadableOrderItemObserver.php @@ -136,7 +136,7 @@ public function execute(\Magento\Framework\Event\Observer $observer) if ($orderStatusToEnableItem == \Magento\Sales\Model\Order\Item::STATUS_PENDING || $orderItem->getOrder()->getState() == \Magento\Sales\Model\Order::STATE_COMPLETE ) { - $linkStatus = \Magento\Downloadable\Model\Link\Purchased\Item::LINK_STATUS_AVAILABLE; + $linkStatus = \Magento\Downloadable\Model\Link\Purchased\Item::LINK_STATUS_AVAILABLE; } foreach ($linkIds as $linkId) { From 60271a75f3b7230bb4836ccc5449a8845a7a9e4a Mon Sep 17 00:00:00 2001 From: Stsiapan Korf <Stsiapan_Korf@epam.com> Date: Wed, 22 May 2019 17:46:00 +0000 Subject: [PATCH 422/773] MC-5777: Catalog rule does not apply as expected - Create rule date formatter --- .../Catalog/Model/Product/Type/Price.php | 25 ++++++++--- .../Product/CollectionProcessor.php | 45 +++++++++++++------ ...ProductSelectBuilderByCatalogRulePrice.php | 22 +++++++-- .../CatalogRule/Model/RuleDateFormatter.php | 43 ++++++++++++++++++ .../Model/RuleDateFormatterInterface.php | 30 +++++++++++++ ...CatalogProductCollectionPricesObserver.php | 19 +++++++- .../ProcessAdminFinalPriceObserver.php | 21 ++++++--- .../ProcessFrontFinalPriceObserver.php | 23 +++++++--- .../Pricing/Price/CatalogRulePrice.php | 22 +++++++-- .../Pricing/Price/CatalogRulePriceTest.php | 17 +++++-- app/code/Magento/CatalogRule/etc/di.xml | 1 + 11 files changed, 226 insertions(+), 42 deletions(-) create mode 100644 app/code/Magento/CatalogRule/Model/RuleDateFormatter.php create mode 100644 app/code/Magento/CatalogRule/Model/RuleDateFormatterInterface.php diff --git a/app/code/Magento/Catalog/Model/Product/Type/Price.php b/app/code/Magento/Catalog/Model/Product/Type/Price.php index b30624b79dd51..b53a02aa42016 100644 --- a/app/code/Magento/Catalog/Model/Product/Type/Price.php +++ b/app/code/Magento/Catalog/Model/Product/Type/Price.php @@ -3,6 +3,8 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Catalog\Model\Product\Type; use Magento\Catalog\Model\Product; @@ -91,6 +93,11 @@ class Price */ private $tierPriceExtensionFactory; + /** + * @var \Magento\CatalogRule\Model\RuleDateFormatterInterface + */ + private $ruleDateFormatter; + /** * Constructor * @@ -104,6 +111,7 @@ class Price * @param \Magento\Catalog\Api\Data\ProductTierPriceInterfaceFactory $tierPriceFactory * @param \Magento\Framework\App\Config\ScopeConfigInterface $config * @param ProductTierPriceExtensionFactory|null $tierPriceExtensionFactory + * @param \Magento\CatalogRule\Model\RuleDateFormatterInterface|null $ruleDateFormatter * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -116,7 +124,8 @@ public function __construct( GroupManagementInterface $groupManagement, \Magento\Catalog\Api\Data\ProductTierPriceInterfaceFactory $tierPriceFactory, \Magento\Framework\App\Config\ScopeConfigInterface $config, - ProductTierPriceExtensionFactory $tierPriceExtensionFactory = null + ProductTierPriceExtensionFactory $tierPriceExtensionFactory = null, + \Magento\CatalogRule\Model\RuleDateFormatterInterface $ruleDateFormatter = null ) { $this->_ruleFactory = $ruleFactory; $this->_storeManager = $storeManager; @@ -129,6 +138,8 @@ public function __construct( $this->config = $config; $this->tierPriceExtensionFactory = $tierPriceExtensionFactory ?: ObjectManager::getInstance() ->get(ProductTierPriceExtensionFactory::class); + $this->ruleDateFormatter = $ruleDateFormatter ?: ObjectManager::getInstance() + ->get(\Magento\CatalogRule\Model\RuleDateFormatterInterface::class); } /** @@ -502,10 +513,10 @@ public function getFormattedTierPrice($qty, $product) /** * Get formatted by currency tier price * - * @param float $qty - * @param Product $product + * @param float $qty + * @param Product $product * - * @return array|float + * @return array|float * * @deprecated * @see getFormattedTierPrice() @@ -529,8 +540,8 @@ public function getFormattedPrice($product) /** * Get formatted by currency product price * - * @param Product $product - * @return array || float + * @param Product $product + * @return array || float * * @deprecated * @see getFormattedPrice() @@ -611,7 +622,7 @@ public function calculatePrice( ); if ($rulePrice === false) { - $date = $this->_localeDate->scopeDate($sId); + $date = $this->ruleDateFormatter->getDate($sId); $rulePrice = $this->_ruleFactory->create()->getRulePrice($date, $wId, $gId, $productId); } diff --git a/app/code/Magento/CatalogRule/Model/ResourceModel/Product/CollectionProcessor.php b/app/code/Magento/CatalogRule/Model/ResourceModel/Product/CollectionProcessor.php index 0ea31f5dbafb2..79585cd8e8572 100644 --- a/app/code/Magento/CatalogRule/Model/ResourceModel/Product/CollectionProcessor.php +++ b/app/code/Magento/CatalogRule/Model/ResourceModel/Product/CollectionProcessor.php @@ -4,13 +4,18 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\CatalogRule\Model\ResourceModel\Product; use Magento\Catalog\Model\ResourceModel\Product\Collection as ProductCollection; use Magento\CatalogRule\Pricing\Price\CatalogRulePrice; +use Magento\Framework\App\ObjectManager; /** * Add catalog rule prices to collection + * + * @SuppressWarnings(PHPMD.CookieAndSessionMisuse) */ class CollectionProcessor { @@ -39,28 +44,39 @@ class CollectionProcessor */ private $localeDate; + /** + * @var \Magento\CatalogRule\Model\RuleDateFormatterInterface + */ + private $ruleDateFormatter; + /** * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\Framework\App\ResourceConnection $resourceConnection * @param \Magento\Customer\Model\Session $customerSession * @param \Magento\Framework\Stdlib\DateTime $dateTime * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate + * @param \Magento\CatalogRule\Model\RuleDateFormatterInterface|null $ruleDateFormatter */ public function __construct( \Magento\Store\Model\StoreManagerInterface $storeManager, \Magento\Framework\App\ResourceConnection $resourceConnection, \Magento\Customer\Model\Session $customerSession, \Magento\Framework\Stdlib\DateTime $dateTime, - \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate + \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate, + \Magento\CatalogRule\Model\RuleDateFormatterInterface $ruleDateFormatter = null ) { $this->storeManager = $storeManager; $this->resource = $resourceConnection; $this->customerSession = $customerSession; $this->dateTime = $dateTime; $this->localeDate = $localeDate; + $this->ruleDateFormatter = $ruleDateFormatter ?: ObjectManager::getInstance() + ->get(\Magento\CatalogRule\Model\RuleDateFormatterInterface::class); } /** + * Join prices to collection + * * @param ProductCollection $productCollection * @param string $joinColumn * @return ProductCollection @@ -73,18 +89,21 @@ public function addPriceData(ProductCollection $productCollection, $joinColumn = $productCollection->getSelect() ->joinLeft( ['catalog_rule' => $this->resource->getTableName('catalogrule_product_price')], - implode(' AND ', [ - 'catalog_rule.product_id = ' . $connection->quoteIdentifier($joinColumn), - $connection->quoteInto('catalog_rule.website_id = ?', $store->getWebsiteId()), - $connection->quoteInto( - 'catalog_rule.customer_group_id = ?', - $this->customerSession->getCustomerGroupId() - ), - $connection->quoteInto( - 'catalog_rule.rule_date = ?', - $this->dateTime->formatDate($this->localeDate->scopeDate($store->getId()), false) - ), - ]), + implode( + ' AND ', + [ + 'catalog_rule.product_id = ' . $connection->quoteIdentifier($joinColumn), + $connection->quoteInto('catalog_rule.website_id = ?', $store->getWebsiteId()), + $connection->quoteInto( + 'catalog_rule.customer_group_id = ?', + $this->customerSession->getCustomerGroupId() + ), + $connection->quoteInto( + 'catalog_rule.rule_date = ?', + $this->dateTime->formatDate($this->ruleDateFormatter->getDate($store->getId()), false) + ), + ] + ), [CatalogRulePrice::PRICE_CODE => 'rule_price'] ); $productCollection->setFlag('catalog_rule_loaded', true); diff --git a/app/code/Magento/CatalogRule/Model/ResourceModel/Product/LinkedProductSelectBuilderByCatalogRulePrice.php b/app/code/Magento/CatalogRule/Model/ResourceModel/Product/LinkedProductSelectBuilderByCatalogRulePrice.php index 3f396cacd37da..11c33633bdfa8 100644 --- a/app/code/Magento/CatalogRule/Model/ResourceModel/Product/LinkedProductSelectBuilderByCatalogRulePrice.php +++ b/app/code/Magento/CatalogRule/Model/ResourceModel/Product/LinkedProductSelectBuilderByCatalogRulePrice.php @@ -3,6 +3,8 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\CatalogRule\Model\ResourceModel\Product; use Magento\Catalog\Api\Data\ProductInterface; @@ -11,6 +13,11 @@ use Magento\Framework\DB\Select; use Magento\Catalog\Model\ResourceModel\Product\LinkedProductSelectBuilderInterface; +/** + * Provide Select object for retrieve product id with minimal price + * + * @SuppressWarnings(PHPMD.CookieAndSessionMisuse) + */ class LinkedProductSelectBuilderByCatalogRulePrice implements LinkedProductSelectBuilderInterface { /** @@ -48,6 +55,11 @@ class LinkedProductSelectBuilderByCatalogRulePrice implements LinkedProductSelec */ private $baseSelectProcessor; + /** + * @var \Magento\CatalogRule\Model\RuleDateFormatterInterface + */ + private $ruleDateFormatter; + /** * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\Framework\App\ResourceConnection $resourceConnection @@ -56,6 +68,7 @@ class LinkedProductSelectBuilderByCatalogRulePrice implements LinkedProductSelec * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate * @param \Magento\Framework\EntityManager\MetadataPool $metadataPool * @param BaseSelectProcessorInterface $baseSelectProcessor + * @param \Magento\CatalogRule\Model\RuleDateFormatterInterface|null $ruleDateFormatter */ public function __construct( \Magento\Store\Model\StoreManagerInterface $storeManager, @@ -64,7 +77,8 @@ public function __construct( \Magento\Framework\Stdlib\DateTime $dateTime, \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate, \Magento\Framework\EntityManager\MetadataPool $metadataPool, - BaseSelectProcessorInterface $baseSelectProcessor = null + BaseSelectProcessorInterface $baseSelectProcessor = null, + \Magento\CatalogRule\Model\RuleDateFormatterInterface $ruleDateFormatter = null ) { $this->storeManager = $storeManager; $this->resource = $resourceConnection; @@ -74,14 +88,16 @@ public function __construct( $this->metadataPool = $metadataPool; $this->baseSelectProcessor = (null !== $baseSelectProcessor) ? $baseSelectProcessor : ObjectManager::getInstance()->get(BaseSelectProcessorInterface::class); + $this->ruleDateFormatter = $ruleDateFormatter ?: ObjectManager::getInstance() + ->get(\Magento\CatalogRule\Model\RuleDateFormatterInterface::class); } /** - * {@inheritdoc} + * @inheritdoc */ public function build($productId) { - $timestamp = $this->localeDate->scopeTimeStamp($this->storeManager->getStore()); + $timestamp = $this->ruleDateFormatter->getTimeStamp($this->storeManager->getStore()); $currentDate = $this->dateTime->formatDate($timestamp, false); $linkField = $this->metadataPool->getMetadata(ProductInterface::class)->getLinkField(); $productTable = $this->resource->getTableName('catalog_product_entity'); diff --git a/app/code/Magento/CatalogRule/Model/RuleDateFormatter.php b/app/code/Magento/CatalogRule/Model/RuleDateFormatter.php new file mode 100644 index 0000000000000..ddf2d2232cbd3 --- /dev/null +++ b/app/code/Magento/CatalogRule/Model/RuleDateFormatter.php @@ -0,0 +1,43 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\CatalogRule\Model; + +/** + * Local date for catalog rule + */ +class RuleDateFormatter implements \Magento\CatalogRule\Model\RuleDateFormatterInterface +{ + /** + * @var \Magento\Framework\Stdlib\DateTime\TimezoneInterface + */ + private $localeDate; + + /** + * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate + */ + public function __construct(\Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate) + { + $this->localeDate = $localeDate; + } + + /** + * @inheritdoc + */ + public function getDate($scope = null) + { + return $this->localeDate->scopeDate($scope, null, true); + } + + /** + * @inheritdoc + */ + public function getTimeStamp($scope = null) + { + return $this->localeDate->scopeTimeStamp($scope); + } +} diff --git a/app/code/Magento/CatalogRule/Model/RuleDateFormatterInterface.php b/app/code/Magento/CatalogRule/Model/RuleDateFormatterInterface.php new file mode 100644 index 0000000000000..5cac66e603edb --- /dev/null +++ b/app/code/Magento/CatalogRule/Model/RuleDateFormatterInterface.php @@ -0,0 +1,30 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\CatalogRule\Model; + +/** + * Local date for catalog rule + */ +interface RuleDateFormatterInterface +{ + /** + * Create \DateTime object with date converted to scope timezone for catalog rule + * + * @param mixed $scope Information about scope + * @return \DateTime + */ + public function getDate($scope = null); + + /** + * Get scope timestamp for catalog rule + * + * @param mixed $scope Information about scope + * @return int + */ + public function getTimeStamp($scope = null); +} diff --git a/app/code/Magento/CatalogRule/Observer/PrepareCatalogProductCollectionPricesObserver.php b/app/code/Magento/CatalogRule/Observer/PrepareCatalogProductCollectionPricesObserver.php index 75a208e87100b..2fcdfa9d71d68 100644 --- a/app/code/Magento/CatalogRule/Observer/PrepareCatalogProductCollectionPricesObserver.php +++ b/app/code/Magento/CatalogRule/Observer/PrepareCatalogProductCollectionPricesObserver.php @@ -7,6 +7,8 @@ /** * Catalog Price rules observer model */ +declare(strict_types=1); + namespace Magento\CatalogRule\Observer; use Magento\Catalog\Model\Product; @@ -17,9 +19,13 @@ use Magento\Framework\Event\Observer as EventObserver; use Magento\Customer\Api\GroupManagementInterface; use Magento\Framework\Event\ObserverInterface; +use Magento\Framework\App\ObjectManager; /** + * Observer for applying catalog rules on product collection + * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * @SuppressWarnings(PHPMD.CookieAndSessionMisuse) */ class PrepareCatalogProductCollectionPricesObserver implements ObserverInterface { @@ -53,6 +59,11 @@ class PrepareCatalogProductCollectionPricesObserver implements ObserverInterface */ protected $groupManagement; + /** + * @var \Magento\CatalogRule\Model\RuleDateFormatterInterface + */ + private $ruleDateFormatter; + /** * @param RulePricesStorage $rulePricesStorage * @param \Magento\CatalogRule\Model\ResourceModel\RuleFactory $resourceRuleFactory @@ -60,6 +71,7 @@ class PrepareCatalogProductCollectionPricesObserver implements ObserverInterface * @param TimezoneInterface $localeDate * @param CustomerModelSession $customerSession * @param GroupManagementInterface $groupManagement + * @param \Magento\CatalogRule\Model\RuleDateFormatterInterface|null $ruleDateFormatter */ public function __construct( RulePricesStorage $rulePricesStorage, @@ -67,7 +79,8 @@ public function __construct( StoreManagerInterface $storeManager, TimezoneInterface $localeDate, CustomerModelSession $customerSession, - GroupManagementInterface $groupManagement + GroupManagementInterface $groupManagement, + \Magento\CatalogRule\Model\RuleDateFormatterInterface $ruleDateFormatter = null ) { $this->rulePricesStorage = $rulePricesStorage; $this->resourceRuleFactory = $resourceRuleFactory; @@ -75,6 +88,8 @@ public function __construct( $this->localeDate = $localeDate; $this->customerSession = $customerSession; $this->groupManagement = $groupManagement; + $this->ruleDateFormatter = $ruleDateFormatter ?: ObjectManager::getInstance() + ->get(\Magento\CatalogRule\Model\RuleDateFormatterInterface::class); } /** @@ -101,7 +116,7 @@ public function execute(\Magento\Framework\Event\Observer $observer) if ($observer->getEvent()->hasDate()) { $date = new \DateTime($observer->getEvent()->getDate()); } else { - $date = (new \DateTime())->setTimestamp($this->localeDate->scopeTimeStamp($store)); + $date = (new \DateTime())->setTimestamp($this->ruleDateFormatter->getTimeStamp($store)); } $productIds = []; diff --git a/app/code/Magento/CatalogRule/Observer/ProcessAdminFinalPriceObserver.php b/app/code/Magento/CatalogRule/Observer/ProcessAdminFinalPriceObserver.php index 2dce2cb2f5b1c..bd95936938141 100644 --- a/app/code/Magento/CatalogRule/Observer/ProcessAdminFinalPriceObserver.php +++ b/app/code/Magento/CatalogRule/Observer/ProcessAdminFinalPriceObserver.php @@ -3,10 +3,8 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); -/** - * Catalog Price rules observer model - */ namespace Magento\CatalogRule\Observer; use Magento\Catalog\Model\Product; @@ -16,7 +14,11 @@ use Magento\Framework\Event\Observer as EventObserver; use Magento\Framework\Registry; use Magento\Framework\Event\ObserverInterface; +use Magento\Framework\App\ObjectManager; +/** + * Observer for applying catalog rules on product for admin area + */ class ProcessAdminFinalPriceObserver implements ObserverInterface { /** @@ -41,22 +43,31 @@ class ProcessAdminFinalPriceObserver implements ObserverInterface */ protected $rulePricesStorage; + /** + * @var \Magento\CatalogRule\Model\RuleDateFormatterInterface + */ + private $ruleDateFormatter; + /** * @param RulePricesStorage $rulePricesStorage * @param Registry $coreRegistry * @param \Magento\CatalogRule\Model\ResourceModel\RuleFactory $resourceRuleFactory * @param TimezoneInterface $localeDate + * @param \Magento\CatalogRule\Model\RuleDateFormatterInterface|null $ruleDateFormatter */ public function __construct( RulePricesStorage $rulePricesStorage, Registry $coreRegistry, \Magento\CatalogRule\Model\ResourceModel\RuleFactory $resourceRuleFactory, - TimezoneInterface $localeDate + TimezoneInterface $localeDate, + \Magento\CatalogRule\Model\RuleDateFormatterInterface $ruleDateFormatter = null ) { $this->rulePricesStorage = $rulePricesStorage; $this->coreRegistry = $coreRegistry; $this->resourceRuleFactory = $resourceRuleFactory; $this->localeDate = $localeDate; + $this->ruleDateFormatter = $ruleDateFormatter ?: ObjectManager::getInstance() + ->get(\Magento\CatalogRule\Model\RuleDateFormatterInterface::class); } /** @@ -69,7 +80,7 @@ public function execute(\Magento\Framework\Event\Observer $observer) { $product = $observer->getEvent()->getProduct(); $storeId = $product->getStoreId(); - $date = $this->localeDate->scopeDate($storeId); + $date = $this->ruleDateFormatter->getDate($storeId); $key = false; $ruleData = $this->coreRegistry->registry('rule_data'); diff --git a/app/code/Magento/CatalogRule/Observer/ProcessFrontFinalPriceObserver.php b/app/code/Magento/CatalogRule/Observer/ProcessFrontFinalPriceObserver.php index 2d4042f691502..8a2e660ed9aaf 100644 --- a/app/code/Magento/CatalogRule/Observer/ProcessFrontFinalPriceObserver.php +++ b/app/code/Magento/CatalogRule/Observer/ProcessFrontFinalPriceObserver.php @@ -3,10 +3,8 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); -/** - * Catalog Price rules observer model - */ namespace Magento\CatalogRule\Observer; use Magento\Framework\Event\ObserverInterface; @@ -16,7 +14,13 @@ use Magento\Framework\Stdlib\DateTime\TimezoneInterface; use Magento\Customer\Model\Session as CustomerModelSession; use Magento\Framework\Event\Observer as EventObserver; +use Magento\Framework\App\ObjectManager; +/** + * Observer for applying catalog rules on product for frontend area + * + * @SuppressWarnings(PHPMD.CookieAndSessionMisuse) + */ class ProcessFrontFinalPriceObserver implements ObserverInterface { /** @@ -44,25 +48,34 @@ class ProcessFrontFinalPriceObserver implements ObserverInterface */ protected $rulePricesStorage; + /** + * @var \Magento\CatalogRule\Model\RuleDateFormatterInterface + */ + private $ruleDateFormatter; + /** * @param RulePricesStorage $rulePricesStorage * @param \Magento\CatalogRule\Model\ResourceModel\RuleFactory $resourceRuleFactory * @param StoreManagerInterface $storeManager * @param TimezoneInterface $localeDate * @param CustomerModelSession $customerSession + * @param \Magento\CatalogRule\Model\RuleDateFormatterInterface|null $ruleDateFormatter */ public function __construct( RulePricesStorage $rulePricesStorage, \Magento\CatalogRule\Model\ResourceModel\RuleFactory $resourceRuleFactory, StoreManagerInterface $storeManager, TimezoneInterface $localeDate, - CustomerModelSession $customerSession + CustomerModelSession $customerSession, + \Magento\CatalogRule\Model\RuleDateFormatterInterface $ruleDateFormatter = null ) { $this->rulePricesStorage = $rulePricesStorage; $this->resourceRuleFactory = $resourceRuleFactory; $this->storeManager = $storeManager; $this->localeDate = $localeDate; $this->customerSession = $customerSession; + $this->ruleDateFormatter = $ruleDateFormatter ?: ObjectManager::getInstance() + ->get(\Magento\CatalogRule\Model\RuleDateFormatterInterface::class); } /** @@ -80,7 +93,7 @@ public function execute(\Magento\Framework\Event\Observer $observer) if ($observer->hasDate()) { $date = new \DateTime($observer->getEvent()->getDate()); } else { - $date = $this->localeDate->scopeDate($storeId); + $date = $this->ruleDateFormatter->getDate($storeId); } if ($observer->hasWebsiteId()) { diff --git a/app/code/Magento/CatalogRule/Pricing/Price/CatalogRulePrice.php b/app/code/Magento/CatalogRule/Pricing/Price/CatalogRulePrice.php index c71b51317fd59..b9db988dd20bd 100644 --- a/app/code/Magento/CatalogRule/Pricing/Price/CatalogRulePrice.php +++ b/app/code/Magento/CatalogRule/Pricing/Price/CatalogRulePrice.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); namespace Magento\CatalogRule\Pricing\Price; @@ -19,6 +20,8 @@ /** * Class CatalogRulePrice + * + * @SuppressWarnings(PHPMD.CookieAndSessionMisuse) */ class CatalogRulePrice extends AbstractPrice implements BasePriceProviderInterface { @@ -53,15 +56,21 @@ class CatalogRulePrice extends AbstractPrice implements BasePriceProviderInterfa */ private $ruleResource; + /** + * @var \Magento\CatalogRule\Model\RuleDateFormatterInterface + */ + private $ruleDateFormatter; + /** * @param Product $saleableItem * @param float $quantity * @param Calculator $calculator - * @param RuleFactory $catalogRuleResourceFactory + * @param \Magento\Framework\Pricing\PriceCurrencyInterface $priceCurrency * @param TimezoneInterface $dateTime * @param StoreManager $storeManager * @param Session $customerSession - * @param \Magento\Framework\Pricing\PriceCurrencyInterface $priceCurrency + * @param RuleFactory $catalogRuleResourceFactory + * @param \Magento\CatalogRule\Model\RuleDateFormatterInterface|null $ruleDateFormatter */ public function __construct( Product $saleableItem, @@ -71,13 +80,16 @@ public function __construct( TimezoneInterface $dateTime, StoreManager $storeManager, Session $customerSession, - RuleFactory $catalogRuleResourceFactory + RuleFactory $catalogRuleResourceFactory, + \Magento\CatalogRule\Model\RuleDateFormatterInterface $ruleDateFormatter = null ) { parent::__construct($saleableItem, $quantity, $calculator, $priceCurrency); $this->dateTime = $dateTime; $this->storeManager = $storeManager; $this->customerSession = $customerSession; $this->resourceRuleFactory = $catalogRuleResourceFactory; + $this->ruleDateFormatter = $ruleDateFormatter ?: ObjectManager::getInstance() + ->get(\Magento\CatalogRule\Model\RuleDateFormatterInterface::class); } /** @@ -93,7 +105,7 @@ public function getValue() } else { $this->value = $this->getRuleResource() ->getRulePrice( - $this->dateTime->scopeDate($this->storeManager->getStore()->getId()), + $this->ruleDateFormatter->getDate($this->storeManager->getStore()->getId()), $this->storeManager->getStore()->getWebsiteId(), $this->customerSession->getCustomerGroupId(), $this->product->getId() @@ -109,6 +121,8 @@ public function getValue() } /** + * Retrieve rule resource + * * @return Rule * @deprecated 100.1.1 */ diff --git a/app/code/Magento/CatalogRule/Test/Unit/Pricing/Price/CatalogRulePriceTest.php b/app/code/Magento/CatalogRule/Test/Unit/Pricing/Price/CatalogRulePriceTest.php index 797097f8a5346..3d19851df7335 100644 --- a/app/code/Magento/CatalogRule/Test/Unit/Pricing/Price/CatalogRulePriceTest.php +++ b/app/code/Magento/CatalogRule/Test/Unit/Pricing/Price/CatalogRulePriceTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); namespace Magento\CatalogRule\Test\Unit\Pricing\Price; @@ -76,6 +77,11 @@ class CatalogRulePriceTest extends \PHPUnit\Framework\TestCase */ protected $priceCurrencyMock; + /** + * @var \Magento\CatalogRule\Model\RuleDateFormatterInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $ruleDateFormatter; + /** * Set up */ @@ -94,6 +100,10 @@ protected function setUp() true, [] ); + $this->ruleDateFormatter = $this->getMockBuilder(\Magento\CatalogRule\Model\RuleDateFormatterInterface::class) + ->setMethods([]) + ->disableOriginalConstructor() + ->getMock(); $this->coreStoreMock = $this->createMock(\Magento\Store\Model\Store::class); $this->storeManagerMock = $this->createMock(\Magento\Store\Model\StoreManager::class); @@ -140,7 +150,8 @@ protected function setUp() $this->dataTimeMock, $this->storeManagerMock, $this->customerSessionMock, - $this->catalogRuleResourceFactoryMock + $this->catalogRuleResourceFactoryMock, + $this->ruleDateFormatter ); (new ObjectManager($this))->setBackwardCompatibleProperty( @@ -170,8 +181,8 @@ public function testGetValue() $this->coreStoreMock->expects($this->once()) ->method('getWebsiteId') ->will($this->returnValue($coreWebsiteId)); - $this->dataTimeMock->expects($this->once()) - ->method('scopeDate') + $this->ruleDateFormatter->expects($this->once()) + ->method('getDate') ->with($this->equalTo($coreStoreId)) ->will($this->returnValue($dateTime)); $this->customerSessionMock->expects($this->once()) diff --git a/app/code/Magento/CatalogRule/etc/di.xml b/app/code/Magento/CatalogRule/etc/di.xml index e0d91db542390..c9e0fa46fc67e 100644 --- a/app/code/Magento/CatalogRule/etc/di.xml +++ b/app/code/Magento/CatalogRule/etc/di.xml @@ -164,4 +164,5 @@ <argument name="customConditionProvider" xsi:type="object">CatalogRuleCustomConditionProvider</argument> </arguments> </type> + <preference for="Magento\CatalogRule\Model\RuleDateFormatterInterface" type="Magento\CatalogRule\Model\RuleDateFormatter" /> </config> From 88ff702924319d81393a1fbbfe2ed954be4b4e91 Mon Sep 17 00:00:00 2001 From: Andrii Meysar <andrii.meysar@transoftgroup.com> Date: Fri, 24 May 2019 17:39:12 +0300 Subject: [PATCH 423/773] MC-16723: Cannot Create Or Edit Catalog Price Rule or Cart Price Rule --- .../Search/_files/search_request_merged.php | 7 ---- lib/internal/Magento/Framework/Config/Dom.php | 2 +- .../Framework/Config/Test/Unit/DomTest.php | 42 ------------------- .../Config/Test/Unit/_files/sample.xsd | 1 - 4 files changed, 1 insertion(+), 51 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Framework/Search/_files/search_request_merged.php b/dev/tests/integration/testsuite/Magento/Framework/Search/_files/search_request_merged.php index 0aaa3f4e15bda..8586f47a0f7fa 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/Search/_files/search_request_merged.php +++ b/dev/tests/integration/testsuite/Magento/Framework/Search/_files/search_request_merged.php @@ -35,7 +35,6 @@ 'match_query' => [ 'value' => '$match_term_override$', 'name' => 'match_query', - 'boost' => '1', 'match' => [ 0 => [ 'field' => 'match_field', @@ -51,7 +50,6 @@ ], 'must_query' => [ 'name' => 'must_query', - 'boost' => '1', 'filterReference' => [ 0 => [ 'clause' => 'must', @@ -62,7 +60,6 @@ ], 'should_query' => [ 'name' => 'should_query', - 'boost' => '1', 'filterReference' => [ 0 => [ 'clause' => 'should', @@ -73,7 +70,6 @@ ], 'not_query' => [ 'name' => 'not_query', - 'boost' => '1', 'filterReference' => [ 0 => [ 'clause' => 'not', @@ -84,7 +80,6 @@ ], 'match_query_2' => [ 'value' => '$match_term_override$', - 'boost' => '1', 'name' => 'match_query_2', 'match' => [ 0 => [ @@ -168,7 +163,6 @@ 'queries' => [ 'filter_query' => [ 'name' => 'filter_query', - 'boost' => '1', 'filterReference' => [ 0 => [ @@ -236,7 +230,6 @@ 'new_match_query' => [ 'value' => '$match_term$', 'name' => 'new_match_query', - 'boost' => '1', 'match' => [ 0 => [ diff --git a/lib/internal/Magento/Framework/Config/Dom.php b/lib/internal/Magento/Framework/Config/Dom.php index 5c97c996634dd..e36f9615db26b 100644 --- a/lib/internal/Magento/Framework/Config/Dom.php +++ b/lib/internal/Magento/Framework/Config/Dom.php @@ -379,7 +379,7 @@ public static function validateDomDocument( libxml_set_external_entity_loader([self::$urnResolver, 'registerEntityLoader']); $errors = []; try { - $result = $dom->schemaValidate($schema, LIBXML_SCHEMA_CREATE); + $result = $dom->schemaValidate($schema); if (!$result) { $errors = self::getXmlErrors($errorFormat); } diff --git a/lib/internal/Magento/Framework/Config/Test/Unit/DomTest.php b/lib/internal/Magento/Framework/Config/Test/Unit/DomTest.php index 73968ac1ed897..4d84be1ba4fc1 100644 --- a/lib/internal/Magento/Framework/Config/Test/Unit/DomTest.php +++ b/lib/internal/Magento/Framework/Config/Test/Unit/DomTest.php @@ -169,48 +169,6 @@ public function validateDataProvider() ]; } - /** - * @param string $xml - * @param string $expectedValue - * @dataProvider validateWithDefaultValueDataProvider - */ - public function testValidateWithDefaultValue($xml, $expectedValue) - { - if (!function_exists('libxml_set_external_entity_loader')) { - $this->markTestSkipped('Skipped on HHVM. Will be fixed in MAGETWO-45033'); - } - - $actualErrors = []; - - $dom = new \Magento\Framework\Config\Dom($xml, $this->validationStateMock); - $dom->validate(__DIR__ . '/_files/sample.xsd', $actualErrors); - - $actualValue = $dom->getDom() - ->getElementsByTagName('root')->item(0) - ->getElementsByTagName('node')->item(0) - ->getAttribute('attribute_with_default_value'); - - $this->assertEmpty($actualErrors); - $this->assertEquals($expectedValue, $actualValue); - } - - /** - * @return array - */ - public function validateWithDefaultValueDataProvider() - { - return [ - 'default_value' => [ - '<root><node id="id1"/></root>', - 'default_value' - ], - 'custom_value' => [ - '<root><node id="id1" attribute_with_default_value="non_default_value"/></root>', - 'non_default_value' - ], - ]; - } - public function testValidateCustomErrorFormat() { $xml = '<root><unknown_node/></root>'; diff --git a/lib/internal/Magento/Framework/Config/Test/Unit/_files/sample.xsd b/lib/internal/Magento/Framework/Config/Test/Unit/_files/sample.xsd index 701a2eb18c2a1..1f635b7081e05 100644 --- a/lib/internal/Magento/Framework/Config/Test/Unit/_files/sample.xsd +++ b/lib/internal/Magento/Framework/Config/Test/Unit/_files/sample.xsd @@ -21,7 +21,6 @@ <xs:simpleContent> <xs:extension base="xs:string"> <xs:attribute name="id" type="xs:string" use="required"/> - <xs:attribute name="attribute_with_default_value" type="xs:string" default="default_value"/> </xs:extension> </xs:simpleContent> </xs:complexType> From 6b796e34e16345d7e03cc813ed31310bb647183a Mon Sep 17 00:00:00 2001 From: Vitaliy Honcharenko <vgoncharenko@magento.com> Date: Fri, 24 May 2019 11:37:34 -0500 Subject: [PATCH 424/773] MC-16239: Search result page contain 24k results - fixed static tests --- .../Elasticsearch5/Model/Client/Elasticsearch.php | 4 +++- .../Elasticsearch/Model/Client/Elasticsearch.php | 10 ++++++++-- .../Elasticsearch5/Model/Client/ElasticsearchTest.php | 3 +++ .../Elasticsearch6/Model/Client/Elasticsearch.php | 2 ++ .../Test/Unit/Model/Client/ElasticsearchTest.php | 3 +++ 5 files changed, 19 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Elasticsearch/Elasticsearch5/Model/Client/Elasticsearch.php b/app/code/Magento/Elasticsearch/Elasticsearch5/Model/Client/Elasticsearch.php index cada9e1ec6e4d..f28eb78057fa8 100644 --- a/app/code/Magento/Elasticsearch/Elasticsearch5/Model/Client/Elasticsearch.php +++ b/app/code/Magento/Elasticsearch/Elasticsearch5/Model/Client/Elasticsearch.php @@ -91,7 +91,7 @@ public function ping() } /** - * Validate connection params + * Validate connection params. * * @return bool */ @@ -109,7 +109,9 @@ public function testConnection() private function buildConfig($options = []) { $host = preg_replace('/http[s]?:\/\//i', '', $options['hostname']); + // @codingStandardsIgnoreStart $protocol = parse_url($options['hostname'], PHP_URL_SCHEME); + // @codingStandardsIgnoreEnd if (!$protocol) { $protocol = 'http'; } diff --git a/app/code/Magento/Elasticsearch/Model/Client/Elasticsearch.php b/app/code/Magento/Elasticsearch/Model/Client/Elasticsearch.php index 1870051772520..e91508f80e964 100644 --- a/app/code/Magento/Elasticsearch/Model/Client/Elasticsearch.php +++ b/app/code/Magento/Elasticsearch/Model/Client/Elasticsearch.php @@ -96,13 +96,17 @@ public function testConnection() } /** + * Build config. + * * @param array $options * @return array */ private function buildConfig($options = []) { $host = preg_replace('/http[s]?:\/\//i', '', $options['hostname']); + // @codingStandardsIgnoreStart $protocol = parse_url($options['hostname'], PHP_URL_SCHEME); + // @codingStandardsIgnoreEnd if (!$protocol) { $protocol = 'http'; } @@ -202,9 +206,10 @@ public function indexExists($index) } /** + * Check if alias exists. + * * @param string $alias * @param string $index - * * @return bool */ public function existsAlias($alias, $index = '') @@ -217,8 +222,9 @@ public function existsAlias($alias, $index = '') } /** - * @param string $alias + * Get alias. * + * @param string $alias * @return array */ public function getAlias($alias) diff --git a/app/code/Magento/Elasticsearch/Test/Unit/Elasticsearch5/Model/Client/ElasticsearchTest.php b/app/code/Magento/Elasticsearch/Test/Unit/Elasticsearch5/Model/Client/ElasticsearchTest.php index e5f672fd2e766..2a98a8b0ea62a 100644 --- a/app/code/Magento/Elasticsearch/Test/Unit/Elasticsearch5/Model/Client/ElasticsearchTest.php +++ b/app/code/Magento/Elasticsearch/Test/Unit/Elasticsearch5/Model/Client/ElasticsearchTest.php @@ -8,6 +8,9 @@ use Magento\Elasticsearch\Model\Client\Elasticsearch as ElasticsearchClient; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +/** + * Class ElasticsearchTest + */ class ElasticsearchTest extends \PHPUnit\Framework\TestCase { /** diff --git a/app/code/Magento/Elasticsearch6/Model/Client/Elasticsearch.php b/app/code/Magento/Elasticsearch6/Model/Client/Elasticsearch.php index 513b93a2b7e9f..3cddec4263396 100644 --- a/app/code/Magento/Elasticsearch6/Model/Client/Elasticsearch.php +++ b/app/code/Magento/Elasticsearch6/Model/Client/Elasticsearch.php @@ -104,7 +104,9 @@ public function testConnection() private function buildConfig($options = []) { $host = preg_replace('/http[s]?:\/\//i', '', $options['hostname']); + // @codingStandardsIgnoreStart $protocol = parse_url($options['hostname'], PHP_URL_SCHEME); + // @codingStandardsIgnoreEnd if (!$protocol) { $protocol = 'http'; } diff --git a/app/code/Magento/Elasticsearch6/Test/Unit/Model/Client/ElasticsearchTest.php b/app/code/Magento/Elasticsearch6/Test/Unit/Model/Client/ElasticsearchTest.php index fb26e9ea387d0..11392bb0369fc 100644 --- a/app/code/Magento/Elasticsearch6/Test/Unit/Model/Client/ElasticsearchTest.php +++ b/app/code/Magento/Elasticsearch6/Test/Unit/Model/Client/ElasticsearchTest.php @@ -8,6 +8,9 @@ use Magento\Elasticsearch\Model\Client\Elasticsearch as ElasticsearchClient; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +/** + * Class ElasticsearchTest + */ class ElasticsearchTest extends \PHPUnit\Framework\TestCase { /** From bcd34843b20dfa300f4290526d9ddb93f82639ef Mon Sep 17 00:00:00 2001 From: Soumya Unnikrishnan <sunnikri@adobe.com> Date: Fri, 24 May 2019 12:28:46 -0500 Subject: [PATCH 425/773] MC-4770: Convert CreateOrderFromEditCustomerPageTest to MFTF Removed unnecessary createData for config sett --- .../Test/Mftf/Test/CreateOrderFromEditCustomerPageTest.xml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/code/Magento/Sales/Test/Mftf/Test/CreateOrderFromEditCustomerPageTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/CreateOrderFromEditCustomerPageTest.xml index 3b6246e87f641..f3de31b1db17f 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/CreateOrderFromEditCustomerPageTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/CreateOrderFromEditCustomerPageTest.xml @@ -79,8 +79,7 @@ <magentoCLI command="cache:flush" stepKey="flushCache"/> </before> <after> - <createData entity="DefaultShippingMethodsConfig" stepKey="defaultShippingMethodsConfig"/> - <createData entity="DisableFreeShippingConfig" stepKey="disableFreeShippingConfig"/> + <createData entity="DisableFreeShippingConfig" stepKey="disableFreeShippingConfig"/> <deleteData createDataKey="simpleCustomer" stepKey="deleteSimpleCustomer"/> <deleteData createDataKey="simpleProduct" stepKey="deleteSimpleProduct"/> <deleteData createDataKey="simpleProduct1" stepKey="deleteSimpleProduct1"/> From 21c325c922f88f71bdc8396b9a2b95c2821329bc Mon Sep 17 00:00:00 2001 From: Stas Kozar <stas.kozar@transoftgroup.com> Date: Mon, 27 May 2019 12:27:39 +0300 Subject: [PATCH 426/773] MC-16769: Wrong status of Capture transaction on Authorize.net Accept.js payment method --- .../Response/CloseTransactionHandler.php | 11 ++++- .../Magento/AuthorizenetAcceptjs/etc/di.xml | 7 ++- .../Response/CloseTransactionHandlerTest.php | 47 +++++++++++++++++++ 3 files changed, 62 insertions(+), 3 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/AuthorizenetAcceptjs/Gateway/Response/CloseTransactionHandlerTest.php diff --git a/app/code/Magento/AuthorizenetAcceptjs/Gateway/Response/CloseTransactionHandler.php b/app/code/Magento/AuthorizenetAcceptjs/Gateway/Response/CloseTransactionHandler.php index f0dff200e802b..acbde62bacd77 100644 --- a/app/code/Magento/AuthorizenetAcceptjs/Gateway/Response/CloseTransactionHandler.php +++ b/app/code/Magento/AuthorizenetAcceptjs/Gateway/Response/CloseTransactionHandler.php @@ -22,12 +22,19 @@ class CloseTransactionHandler implements HandlerInterface */ private $subjectReader; + /** + * @var bool + */ + private $closeTransaction; + /** * @param SubjectReader $subjectReader + * @param bool $closeTransaction */ - public function __construct(SubjectReader $subjectReader) + public function __construct(SubjectReader $subjectReader, bool $closeTransaction = true) { $this->subjectReader = $subjectReader; + $this->closeTransaction = $closeTransaction; } /** @@ -39,7 +46,7 @@ public function handle(array $handlingSubject, array $response): void $payment = $paymentDO->getPayment(); if ($payment instanceof Payment) { - $payment->setIsTransactionClosed(true); + $payment->setIsTransactionClosed($this->closeTransaction); $payment->setShouldCloseParentTransaction(true); } } diff --git a/app/code/Magento/AuthorizenetAcceptjs/etc/di.xml b/app/code/Magento/AuthorizenetAcceptjs/etc/di.xml index cf10557d3869a..8e1fd660b25ef 100644 --- a/app/code/Magento/AuthorizenetAcceptjs/etc/di.xml +++ b/app/code/Magento/AuthorizenetAcceptjs/etc/di.xml @@ -188,10 +188,15 @@ </argument> </arguments> </virtualType> + <virtualType name="CloseCaptureTransactionHandler" type="Magento\AuthorizenetAcceptjs\Gateway\Response\CloseTransactionHandler"> + <arguments> + <argument name="closeTransaction" xsi:type="boolean">false</argument> + </arguments> + </virtualType> <virtualType name="AuthorizenetAcceptjsCaptureTransactionHandler" type="Magento\Payment\Gateway\Response\HandlerChain"> <arguments> <argument name="handlers" xsi:type="array"> - <item name="close_parent_transaction" xsi:type="string">Magento\AuthorizenetAcceptjs\Gateway\Response\CloseParentTransactionHandler</item> + <item name="close_transaction" xsi:type="string">CloseCaptureTransactionHandler</item> </argument> </arguments> </virtualType> diff --git a/dev/tests/integration/testsuite/Magento/AuthorizenetAcceptjs/Gateway/Response/CloseTransactionHandlerTest.php b/dev/tests/integration/testsuite/Magento/AuthorizenetAcceptjs/Gateway/Response/CloseTransactionHandlerTest.php new file mode 100644 index 0000000000000..1bee2e95cef7d --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/AuthorizenetAcceptjs/Gateway/Response/CloseTransactionHandlerTest.php @@ -0,0 +1,47 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +declare(strict_types=1); + +namespace Magento\AuthorizenetAcceptjs\Gateway\Response; + +use Magento\AuthorizenetAcceptjs\Gateway\AbstractTest; + +/** + * Test for Magento\AuthorizenetAcceptjs\Gateway\Response\CloseTransactionHandler class. + */ +class CloseTransactionHandlerTest extends AbstractTest +{ + /** + * @magentoConfigFixture default_store payment/authorizenet_acceptjs/environment sandbox + * @magentoConfigFixture default_store payment/authorizenet_acceptjs/login someusername + * @magentoConfigFixture default_store payment/authorizenet_acceptjs/trans_key somepassword + * @magentoConfigFixture default_store payment/authorizenet_acceptjs/trans_signature_key abc + * @magentoDataFixture Magento/AuthorizenetAcceptjs/Fixture/order_auth_only.php + * + * @return void + */ + public function testTransactionCloseStatus(): void + { + $commandPool = $this->objectManager->get('AuthorizenetAcceptjsCommandPool'); + $command = $commandPool->get('settle'); + $order = $this->getOrderWithIncrementId('100000002'); + $payment = $order->getPayment(); + $paymentDO = $this->paymentFactory->create($payment); + + $expectedRequest = include __DIR__ . '/../../_files/expected_request/settle.php'; + $response = include __DIR__ . '/../../_files/response/settle.php'; + + $this->clientMock->method('setRawData') + ->with(json_encode($expectedRequest), 'application/json'); + $this->responseMock->method('getBody') + ->willReturn(json_encode($response)); + + $command->execute(['payment' => $paymentDO]); + + $this->assertFalse($payment->getIsTransactionClosed()); + } +} From f02b0fa43b92f3f9be0e48c23c597b4e6e270f8f Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Mon, 27 May 2019 17:03:43 +0300 Subject: [PATCH 427/773] magento/magento2#20579: Static test fix. --- .../testsuite/Magento/SalesRule/_files/coupons_limited.php | 1 + .../Magento/SalesRule/_files/coupons_limited_order.php | 2 ++ .../Magento/SalesRule/_files/coupons_limited_order_rollback.php | 2 ++ .../Magento/SalesRule/_files/coupons_limited_rollback.php | 1 + 4 files changed, 6 insertions(+) diff --git a/dev/tests/integration/testsuite/Magento/SalesRule/_files/coupons_limited.php b/dev/tests/integration/testsuite/Magento/SalesRule/_files/coupons_limited.php index 2f298ad34b935..2199b3b24d360 100644 --- a/dev/tests/integration/testsuite/Magento/SalesRule/_files/coupons_limited.php +++ b/dev/tests/integration/testsuite/Magento/SalesRule/_files/coupons_limited.php @@ -6,6 +6,7 @@ use Magento\SalesRule\Model\Coupon; +// phpcs:ignore Magento2.Security.IncludeFile require 'rules.php'; $collection = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( diff --git a/dev/tests/integration/testsuite/Magento/SalesRule/_files/coupons_limited_order.php b/dev/tests/integration/testsuite/Magento/SalesRule/_files/coupons_limited_order.php index 9980970ff0f24..29178430171b3 100644 --- a/dev/tests/integration/testsuite/Magento/SalesRule/_files/coupons_limited_order.php +++ b/dev/tests/integration/testsuite/Magento/SalesRule/_files/coupons_limited_order.php @@ -7,8 +7,10 @@ use Magento\Sales\Model\Order; use Magento\TestFramework\Helper\Bootstrap; +// phpcs:disable Magento2.Security.IncludeFile require 'coupons_limited.php'; require __DIR__ . '/../../../Magento/Sales/_files/order.php'; +// phpcs:enable $collection = Bootstrap::getObjectManager()->create( \Magento\SalesRule\Model\ResourceModel\Rule\Collection::class diff --git a/dev/tests/integration/testsuite/Magento/SalesRule/_files/coupons_limited_order_rollback.php b/dev/tests/integration/testsuite/Magento/SalesRule/_files/coupons_limited_order_rollback.php index 73a919ac3362f..eba9ecbd9edad 100644 --- a/dev/tests/integration/testsuite/Magento/SalesRule/_files/coupons_limited_order_rollback.php +++ b/dev/tests/integration/testsuite/Magento/SalesRule/_files/coupons_limited_order_rollback.php @@ -4,5 +4,7 @@ * See COPYING.txt for license details. */ +// phpcs:disable Magento2.Security.IncludeFile require __DIR__ . '/../../../Magento/Sales/_files/order_rollback.php'; require 'coupons_limited_rollback.php'; +// phpcs:enable diff --git a/dev/tests/integration/testsuite/Magento/SalesRule/_files/coupons_limited_rollback.php b/dev/tests/integration/testsuite/Magento/SalesRule/_files/coupons_limited_rollback.php index 60d5ed67fd0df..584f714d4c2a9 100644 --- a/dev/tests/integration/testsuite/Magento/SalesRule/_files/coupons_limited_rollback.php +++ b/dev/tests/integration/testsuite/Magento/SalesRule/_files/coupons_limited_rollback.php @@ -18,4 +18,5 @@ $coupon->delete(); } +// phpcs:ignore Magento2.Security.IncludeFile require 'rules_rollback.php'; From 7941a8bb7b17ddb35520f2877e3e8c82cbc5d93d Mon Sep 17 00:00:00 2001 From: eduard13 <e.chitoraga@atwix.com> Date: Mon, 27 May 2019 18:52:47 +0300 Subject: [PATCH 428/773] Revert "Adding Delete Custom Variable Test" This reverts commit c02e4accef09ee6a99bd90018e189a797b42af6e. --- .../Variable/Test/Mftf/Data/VariableData.xml | 3 -- .../Test/Mftf/Metadata/variable-meta.xml | 21 ---------- .../Test/DeleteCustomVariableEntityTest.xml | 41 ------------------- 3 files changed, 65 deletions(-) delete mode 100644 app/code/Magento/Variable/Test/Mftf/Metadata/variable-meta.xml delete mode 100644 app/code/Magento/Variable/Test/Mftf/Test/DeleteCustomVariableEntityTest.xml diff --git a/app/code/Magento/Variable/Test/Mftf/Data/VariableData.xml b/app/code/Magento/Variable/Test/Mftf/Data/VariableData.xml index 923beaad96e65..1160b79026617 100644 --- a/app/code/Magento/Variable/Test/Mftf/Data/VariableData.xml +++ b/app/code/Magento/Variable/Test/Mftf/Data/VariableData.xml @@ -17,7 +17,4 @@ <data key="html"> Sample Variable </data> <data key="plain">variable-plain-</data> </entity> - <entity name="customVariableV2" type="system_variable" extends="customVariable"> - <data key="code" unique="suffix">variable-code-</data> - </entity> </entities> diff --git a/app/code/Magento/Variable/Test/Mftf/Metadata/variable-meta.xml b/app/code/Magento/Variable/Test/Mftf/Metadata/variable-meta.xml deleted file mode 100644 index b2a37d20408a6..0000000000000 --- a/app/code/Magento/Variable/Test/Mftf/Metadata/variable-meta.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> - -<operations xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataOperation.xsd"> - <operation name="CreateCustomVariable" dataType="system_variable" type="create" auth="adminFormKey" - url="/admin/system_variable/save" method="POST" successRegex="/messages-message-success/"> - <contentType>application/x-www-form-urlencoded</contentType> - <object dataType="system_variable" key="variable"> - <field key="code">string</field> - <field key="name">string</field> - <field key="html">string</field> - <field key="plain">string</field> - </object> - </operation> -</operations> diff --git a/app/code/Magento/Variable/Test/Mftf/Test/DeleteCustomVariableEntityTest.xml b/app/code/Magento/Variable/Test/Mftf/Test/DeleteCustomVariableEntityTest.xml deleted file mode 100644 index 9ad67d261d6b6..0000000000000 --- a/app/code/Magento/Variable/Test/Mftf/Test/DeleteCustomVariableEntityTest.xml +++ /dev/null @@ -1,41 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> - -<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> - <test name="DeleteCustomVariableEntityTest"> - <annotations> - <features value="Variable"/> - <stories value="Delete Custom Variable."/> - <title value="Delete Custom Variable."/> - <description value="Test for deleting a custom variable."/> - <severity value="MAJOR"/> - <group value="variable"/> - <group value="mtf_migrated"/> - </annotations> - <before> - <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> - <createData entity="customVariableV2" stepKey="createCustomVariable"/> - </before> - <after> - <actionGroup ref="logout" stepKey="logout"/> - </after> - <actionGroup ref="AdminNavigateToVariablesGridPageActionGroup" stepKey="goToVariablesGridAdminPage"/> - <actionGroup ref="AdminFilterGridActionGroup" stepKey="filterVariablesGridByNewVariableCode" > - <argument name="field" value="{{AdminVariablesFilterSection.codeFilter}}"/> - <argument name="value" value="$$customVariableV2.code$$"/> - </actionGroup> - <actionGroup ref="AdminNavigateToVariablePageActionGroup" stepKey="openCustomVariablePage"> - <argument name="code" value="$$customVariableV2.code$$"/> - </actionGroup> - <actionGroup ref="AdminClickDeleteMainButtonWithConfirmationActionGroup" stepKey="clickDeleteVariable"/> - <actionGroup ref="AssertMessageActionGroup" stepKey="seeSuccessMessage"> - <argument name="message" value="You deleted the custom variable."/> - </actionGroup> - </test> -</tests> From 843693c2dc5da3f5fdd6694c87c85dd7c1fb1b8b Mon Sep 17 00:00:00 2001 From: eduard13 <e.chitoraga@atwix.com> Date: Mon, 27 May 2019 19:21:27 +0300 Subject: [PATCH 429/773] Removing the not needed Action Group --- .../ActionGroup/AssertMessageActionGroup.xml | 18 ------------------ .../Test/CreateCustomVariableEntityTest.xml | 2 +- 2 files changed, 1 insertion(+), 19 deletions(-) delete mode 100644 app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertMessageActionGroup.xml diff --git a/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertMessageActionGroup.xml b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertMessageActionGroup.xml deleted file mode 100644 index 25e716a139487..0000000000000 --- a/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertMessageActionGroup.xml +++ /dev/null @@ -1,18 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> - -<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="AssertMessageActionGroup"> - <arguments> - <argument name="message" type="string" /> - <argument name="messageType" type="string" defaultValue="success" /> - </arguments> - <see userInput="{{message}}" selector=".messages .message-{{messageType}}" stepKey="verifyMessage" /> - </actionGroup> -</actionGroups> diff --git a/app/code/Magento/Variable/Test/Mftf/Test/CreateCustomVariableEntityTest.xml b/app/code/Magento/Variable/Test/Mftf/Test/CreateCustomVariableEntityTest.xml index cb843f64d341a..ff6e648c59987 100644 --- a/app/code/Magento/Variable/Test/Mftf/Test/CreateCustomVariableEntityTest.xml +++ b/app/code/Magento/Variable/Test/Mftf/Test/CreateCustomVariableEntityTest.xml @@ -30,7 +30,7 @@ <actionGroup ref="AdminClickMainButtonActionGroup" stepKey="clickSaveCustomVariable"> <argument name="button" value="{{AdminMainActionsSection.save}}"/> </actionGroup> - <actionGroup ref="AssertMessageActionGroup" stepKey="seeSuccessMessage"> + <actionGroup ref="AssertMessageInAdminPanelActionGroup" stepKey="seeSuccessMessage"> <argument name="message" value="You saved the custom variable."/> </actionGroup> <actionGroup ref="AdminFilterGridActionGroup" stepKey="filterVariablesGridByNewVariableCode" > From 40e659216a21367215d4fe90779c7291f0bc37be Mon Sep 17 00:00:00 2001 From: Vitalii Zabaznov <vzabaznov@magento.com> Date: Tue, 28 May 2019 14:56:36 -0500 Subject: [PATCH 430/773] MC-17019: Revert BIC from MC-15785 --- .../Test/Mftf/Section/CheckoutShippingGuestInfoSection.xml | 2 +- .../Checkout/Test/Mftf/Section/CheckoutShippingSection.xml | 2 +- .../Checkout/view/frontend/web/template/authentication.html | 4 ++-- .../view/frontend/web/template/form/element/email.html | 4 ++-- .../app/Magento/Checkout/Test/Block/Onepage/Shipping.php | 2 +- .../app/Magento/Checkout/Test/Block/Onepage/Shipping.xml | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingGuestInfoSection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingGuestInfoSection.xml index b19e365f2e32c..c97a8f291e941 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingGuestInfoSection.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingGuestInfoSection.xml @@ -9,7 +9,7 @@ <sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="CheckoutShippingGuestInfoSection"> - <element name="email" type="input" selector="#checkout-customer-email"/> + <element name="email" type="input" selector="#customer-email"/> <element name="firstName" type="input" selector="input[name=firstname]"/> <element name="lastName" type="input" selector="input[name=lastname]"/> <element name="street" type="input" selector="input[name='street[0]']"/> diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingSection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingSection.xml index 9676f16f3a5c6..d825e10395145 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingSection.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingSection.xml @@ -15,7 +15,7 @@ <element name="editAddressButton" type="button" selector=".action-edit-address" timeout="30"/> <element name="addressDropdown" type="select" selector="[name=billing_address_id]"/> <element name="newAddressButton" type="button" selector=".action-show-popup" timeout="30"/> - <element name="email" type="input" selector="#checkout-customer-email"/> + <element name="email" type="input" selector="#customer-email"/> <element name="firstName" type="input" selector="input[name=firstname]"/> <element name="lastName" type="input" selector="input[name=lastname]"/> <element name="company" type="input" selector="input[name=company]"/> diff --git a/app/code/Magento/Checkout/view/frontend/web/template/authentication.html b/app/code/Magento/Checkout/view/frontend/web/template/authentication.html index 5b8dde81dd93e..4afaf3c89a5e0 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/authentication.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/authentication.html @@ -31,7 +31,7 @@ <div class="block block-customer-login" data-bind="attr: {'data-label': $t('or')}"> <div class="block-title"> - <strong id="block-customer-login-heading-checkout" + <strong id="block-customer-login-heading" role="heading" aria-level="2" data-bind="i18n: 'Sign In'"></strong> @@ -39,7 +39,7 @@ <!-- ko foreach: getRegion('messages') --> <!-- ko template: getTemplate() --><!-- /ko --> <!--/ko--> - <div class="block-content" aria-labelledby="block-customer-login-heading-checkout"> + <div class="block-content" aria-labelledby="block-customer-login-heading"> <form data-role="login" data-bind="submit:login" method="post"> diff --git a/app/code/Magento/Checkout/view/frontend/web/template/form/element/email.html b/app/code/Magento/Checkout/view/frontend/web/template/form/element/email.html index 6a784fa7a04c4..8d6142e07fcf0 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/form/element/email.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/form/element/email.html @@ -14,7 +14,7 @@ method="post"> <fieldset id="customer-email-fieldset" class="fieldset" data-bind="blockLoader: isLoading"> <div class="field required"> - <label class="label" for="checkout-customer-email"> + <label class="label" for="customer-email"> <span data-bind="i18n: 'Email Address'"></span> </label> <div class="control _with-tooltip"> @@ -26,7 +26,7 @@ mageInit: {'mage/trim-input':{}}" name="username" data-validate="{required:true, 'validate-email':true}" - id="checkout-customer-email" /> + id="customer-email" /> <!-- ko template: 'ui/form/element/helper/tooltip' --><!-- /ko --> <span class="note" data-bind="fadeVisible: isPasswordVisible() == false"><!-- ko i18n: 'You can create an account after checkout.'--><!-- /ko --></span> </div> diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping.php index 1013404f42df1..acaed3d7ded36 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping.php +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping.php @@ -102,7 +102,7 @@ class Shipping extends Form * * @var string */ - private $emailError = '#checkout-customer-email-error'; + private $emailError = '#ustomer-email-error'; /** * Get email error. diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping.xml b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping.xml index 0973b968cba95..71115e402880c 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping.xml +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping.xml @@ -8,7 +8,7 @@ <mapping strict="0"> <fields> <email> - <selector>#checkout-customer-email</selector> + <selector>#customer-email</selector> </email> <firstname /> <lastname /> From d338df50b029e2808b4e00b02997bff3c40c21c4 Mon Sep 17 00:00:00 2001 From: Mila Lesechko <llesechk@adobe.com> Date: Tue, 28 May 2019 15:12:27 -0500 Subject: [PATCH 431/773] MC-4767: Convert PrintOrderFrontendGuestTest to MFTF --- .../Test/Mftf/Section/AdminProductFormBundleSection.xml | 2 +- .../Section/AdminProductFormConfigurationsSection.xml | 2 +- .../Magento/Downloadable/Test/Mftf/Data/ProductData.xml | 2 +- .../AdminAddToOrderBundleProductActionGroup.xml | 8 ++------ .../AdminAddToOrderConfigurableProductActionGroup.xml | 4 ---- .../ActionGroup/AdminAddToOrderCouponCodeActionGroup.xml | 8 ++------ .../AdminAddToOrderDownloadableProductActionGroup.xml | 4 ---- .../AdminFilterProductInCreateOrderActionGroup.xml | 4 ---- ...rontAssertSalesPrintOrderBillingAddressActionGroup.xml | 4 ---- .../StorefrontFillOrdersAndReturnsFormActionGroup.xml | 6 +----- .../Test/Mftf/Section/StorefrontGuestOrderViewSection.xml | 2 +- .../Test/Mftf/Section/StorefrontOrderDetailsSection.xml | 2 +- .../Test/Mftf/Test/StorefrontPrintOrderGuestTest.xml | 6 +++--- 13 files changed, 13 insertions(+), 41 deletions(-) diff --git a/app/code/Magento/Bundle/Test/Mftf/Section/AdminProductFormBundleSection.xml b/app/code/Magento/Bundle/Test/Mftf/Section/AdminProductFormBundleSection.xml index fe9f247c0a2e9..909f349b46a59 100644 --- a/app/code/Magento/Bundle/Test/Mftf/Section/AdminProductFormBundleSection.xml +++ b/app/code/Magento/Bundle/Test/Mftf/Section/AdminProductFormBundleSection.xml @@ -43,7 +43,7 @@ <element name="shortDescription" type="input" selector="#product_form_short_description"/> <!--BundleOptionsDropDown--> <element name="bundleOptionsDropDown" type="button" selector="div[data-index='bundle-items']" timeout="30"/> - <element name="currentBundleOption" type="text" selector="//div[@data-index='bundle-items']//div[@class='admin__collapsible-title']/span"/> + <element name="currentBundleOption" type="text" selector="//div[@data-index='bundle-items']//div[contains(@class, 'admin__collapsible-title')]/span"/> <!--AddingAnOption--> <element name="addOptions" type="button" selector="//tr[@data-repeat-index='0']//td[4]" timeout="30"/> <!--SEODropdownTab--> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Section/AdminProductFormConfigurationsSection.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Section/AdminProductFormConfigurationsSection.xml index 8a54a73bfa29c..30c5910e85e25 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Section/AdminProductFormConfigurationsSection.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Section/AdminProductFormConfigurationsSection.xml @@ -44,7 +44,7 @@ <element name="productQuantity" type="input" selector=".admin__control-text[name='product[quantity_and_stock_status][qty]']"/> <element name="currentVariationsQuantityCells" type="button" selector="td[data-index='quantity_container']"/> <element name="rowByCode" type="textarea" selector="//span[contains(text(), '{{var1}}-{{var2}}')]//ancestor-or-self::tr" parameterized="true"/> - <element name="currentAttribute" type="text" selector="//fieldset[@class='admin__fieldset']/div[@class='admin__field _disabled']//span"/> + <element name="currentAttribute" type="text" selector="//fieldset[@class='admin__fieldset']/div[contains(@class, 'admin__field _disabled')]//span"/> </section> <section name="AdminConfigurableProductSelectAttributesSlideOut"> <element name="grid" type="button" selector=".admin__data-grid-wrap tbody"/> diff --git a/app/code/Magento/Downloadable/Test/Mftf/Data/ProductData.xml b/app/code/Magento/Downloadable/Test/Mftf/Data/ProductData.xml index 3b0be227a1942..1a6be43b38d2c 100644 --- a/app/code/Magento/Downloadable/Test/Mftf/Data/ProductData.xml +++ b/app/code/Magento/Downloadable/Test/Mftf/Data/ProductData.xml @@ -74,7 +74,7 @@ <requiredEntity type="custom_attribute_array">ApiProductShortDescription</requiredEntity> <requiredEntity type="downloadable_link">apiDownloadableLink</requiredEntity> </entity> - <entity name="DownloadableProductWithTwoLink1000" type="product"> + <entity name="DownloadableProductWithTwoLink100" type="product"> <data key="sku" unique="suffix">downloadableproduct</data> <data key="type_id">downloadable</data> <data key="attribute_set_id">4</data> diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAddToOrderBundleProductActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAddToOrderBundleProductActionGroup.xml index c979dd883b175..f5a600b1d2597 100644 --- a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAddToOrderBundleProductActionGroup.xml +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAddToOrderBundleProductActionGroup.xml @@ -9,20 +9,16 @@ <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="AdminAddToOrderBundleProductActionGroup"> - <annotations> - <description>Configuration added Bundle Product during creation order by Admin: select bundle option and product with quantity</description> - <page>AdminOrderCreatePage</page> - </annotations> <arguments> <argument name="option" type="string"/> - <argument name="selectedProduct" type="entity"/> + <argument name="selectedProductName" type="string"/> <argument name="quantity" type="string"/> </arguments> <scrollTo selector="{{AdminOrderFormConfigureProductSection.bundleItems}}" stepKey="scroll"/> <click selector="{{AdminOrderFormConfigureProductSection.bundleItems}}" stepKey="focusOnSideDialog"/> <waitForAjaxLoad stepKey="waitForAjax"/> <click selector="{{AdminOrderFormConfigureProductSection.bundleSelect(option)}}" stepKey="clickSelector"/> - <selectOption selector="{{AdminOrderFormConfigureProductSection.bundleSelect(option)}}" userInput="{{selectedProduct.name}}" stepKey="selectionOption"/> + <selectOption selector="{{AdminOrderFormConfigureProductSection.bundleSelect(option)}}" userInput="{{selectedProductName}}" stepKey="selectionOption"/> <waitForAjaxLoad stepKey="waitForAjaxLoad"/> <fillField userInput="{{quantity}}" selector="{{AdminOrderFormConfigureProductSection.quantity}}" stepKey="fillQty"/> <click selector="{{AdminOrderFormConfigureProductSection.ok}}" stepKey="clickOkConfigurablePopover"/> diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAddToOrderConfigurableProductActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAddToOrderConfigurableProductActionGroup.xml index 9d824cfa2be5a..33378a9fa58cc 100644 --- a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAddToOrderConfigurableProductActionGroup.xml +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAddToOrderConfigurableProductActionGroup.xml @@ -9,10 +9,6 @@ <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="AdminAddToOrderConfigurableProductActionGroup"> - <annotations> - <description>Configuration added Configurable Product during creation order by Admin: select option by attribute and quantity</description> - <page>AdminOrderCreatePage</page> - </annotations> <arguments> <argument name="attribute" type="string"/> <argument name="option" type="string"/> diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAddToOrderCouponCodeActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAddToOrderCouponCodeActionGroup.xml index 415d2036722cc..23f83c567c59d 100644 --- a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAddToOrderCouponCodeActionGroup.xml +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAddToOrderCouponCodeActionGroup.xml @@ -9,14 +9,10 @@ <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="AdminAddToOrderCouponCodeActionGroup"> - <annotations> - <description>Add and apply Coupon Code to order during creating order by Admin</description> - <page>AdminOrderCreatePage</page> - </annotations> <arguments> - <argument name="coupon" type="entity"/> + <argument name="couponCode" type="string"/> </arguments> - <fillField userInput="{{coupon.code}}" selector="{{AdminOrderFormDiscountSection.fieldCouponCode}}" stepKey="fillCouponCode"/> + <fillField userInput="{{couponCode}}" selector="{{AdminOrderFormDiscountSection.fieldCouponCode}}" stepKey="fillCouponCode"/> <click selector="{{AdminOrderFormDiscountSection.applyCouponCode}}" stepKey="clickApply"/> <waitForPageLoad stepKey="waitForPageLoad"/> </actionGroup> diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAddToOrderDownloadableProductActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAddToOrderDownloadableProductActionGroup.xml index e2a49878202a8..ec427fb9b6779 100644 --- a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAddToOrderDownloadableProductActionGroup.xml +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAddToOrderDownloadableProductActionGroup.xml @@ -9,10 +9,6 @@ <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="AdminAddToOrderDownloadableProductActionGroup"> - <annotations> - <description>Configuration added Downloadable Product during creation order by Admin: select link and quantity</description> - <page>AdminOrderCreatePage</page> - </annotations> <arguments> <argument name="link" type="string"/> <argument name="quantity" type="string" defaultValue="1"/> diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminFilterProductInCreateOrderActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminFilterProductInCreateOrderActionGroup.xml index baa8a8f5348b7..58d23f4b06bbc 100644 --- a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminFilterProductInCreateOrderActionGroup.xml +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminFilterProductInCreateOrderActionGroup.xml @@ -9,10 +9,6 @@ <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="AdminFilterProductInCreateOrderActionGroup"> - <annotations> - <description>Search product in product grid on create order by admin page</description> - <page>AdminOrderCreatePage</page> - </annotations> <arguments> <argument name="productSKU" type="string"/> </arguments> diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/StorefrontAssertSalesPrintOrderBillingAddressActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/StorefrontAssertSalesPrintOrderBillingAddressActionGroup.xml index 0a92d38d65a82..fe7e0064e5c5e 100644 --- a/app/code/Magento/Sales/Test/Mftf/ActionGroup/StorefrontAssertSalesPrintOrderBillingAddressActionGroup.xml +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/StorefrontAssertSalesPrintOrderBillingAddressActionGroup.xml @@ -9,10 +9,6 @@ <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="AssertSalesPrintOrderBillingAddress"> - <annotations> - <description>Assert billing address data on printed order</description> - <page>StorefrontPrintOrderPage</page> - </annotations> <arguments> <argument name="address" type="entity"/> </arguments> diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/StorefrontFillOrdersAndReturnsFormActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/StorefrontFillOrdersAndReturnsFormActionGroup.xml index 6ce933762a692..b137ba71e859e 100644 --- a/app/code/Magento/Sales/Test/Mftf/ActionGroup/StorefrontFillOrdersAndReturnsFormActionGroup.xml +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/StorefrontFillOrdersAndReturnsFormActionGroup.xml @@ -9,13 +9,9 @@ <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="StorefrontFillOrdersAndReturnsFormActionGroup"> - <annotations> - <description>Fill order information in form "Orders and Returns"</description> - <page>StorefrontGuestOrderSearchPage</page> - </annotations> <arguments> <argument name="orderNumber" type="string"/> - <argument name="customer" type="entity" defaultValue="$$createCustomer$$"/> + <argument name="customer" type="entity"/> </arguments> <fillField selector="{{StorefrontGuestOrderSearchSection.orderId}}" userInput="{{orderNumber}}" stepKey="inputOrderId"/> <fillField selector="{{StorefrontGuestOrderSearchSection.billingLastName}}" userInput="{{customer.lastname}}" stepKey="inputBillingLastName"/> diff --git a/app/code/Magento/Sales/Test/Mftf/Section/StorefrontGuestOrderViewSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/StorefrontGuestOrderViewSection.xml index 3085a591a1192..70f37352fb183 100644 --- a/app/code/Magento/Sales/Test/Mftf/Section/StorefrontGuestOrderViewSection.xml +++ b/app/code/Magento/Sales/Test/Mftf/Section/StorefrontGuestOrderViewSection.xml @@ -10,6 +10,6 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="StorefrontGuestOrderViewSection"> <element name="orderInformationTab" type="text" selector="//*[@class='nav item current']/strong[contains(text(), 'Order Information')]"/> - <element name="printOrder" type="button" selector=".order-actions-toolbar .actions .print" timeout="10"/> + <element name="printOrder" type="button" selector=".order-actions-toolbar .actions .print" timeout="30"/> </section> </sections> diff --git a/app/code/Magento/Sales/Test/Mftf/Section/StorefrontOrderDetailsSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/StorefrontOrderDetailsSection.xml index 4eecebd264765..c255e15cd6ecf 100644 --- a/app/code/Magento/Sales/Test/Mftf/Section/StorefrontOrderDetailsSection.xml +++ b/app/code/Magento/Sales/Test/Mftf/Section/StorefrontOrderDetailsSection.xml @@ -15,6 +15,6 @@ <element name="grandTotalPrice" type="text" selector="tr.grand_total span.price"/> <element name="paymentMethod" type="text" selector=".box-order-billing-method dt.title"/> <element name="shippingMethod" type="text" selector=".box-order-shipping-method div.box-content"/> - <element name="productNameCell" type="text" selector="//*[@class='product name product-item-name']"/> + <element name="productNameCell" type="text" selector="//*[contains(@class, 'product-item-name')]"/> </section> </sections> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/StorefrontPrintOrderGuestTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/StorefrontPrintOrderGuestTest.xml index 804514ef4922f..5c0d405102464 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/StorefrontPrintOrderGuestTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/StorefrontPrintOrderGuestTest.xml @@ -23,7 +23,7 @@ <createData entity="ApiCategory" stepKey="createCategory"/> <!-- Create downloadable Product --> - <createData entity="DownloadableProductWithTwoLink1000" stepKey="downloadableProduct"> + <createData entity="DownloadableProductWithTwoLink100" stepKey="downloadableProduct"> <requiredEntity createDataKey="createCategory"/> <field key="price">280</field> </createData> @@ -182,7 +182,7 @@ </actionGroup> <actionGroup ref="AdminAddToOrderBundleProductActionGroup" stepKey="addBundleProduct"> <argument name="option" value="{$grabBundleOption}"/> - <argument name="selectedProduct" value="$$simpleProduct1$$"/> + <argument name="selectedProductName" value="$$simpleProduct1.name$$"/> <argument name="quantity" value="2"/> </actionGroup> @@ -196,7 +196,7 @@ <!-- add Coupon --> <actionGroup ref="AdminAddToOrderCouponCodeActionGroup" stepKey="addCoupon"> - <argument name="coupon" value="$$createCouponForCartPriceRule$$"/> + <argument name="couponCode" value="$$createCouponForCartPriceRule.code$$"/> </actionGroup> <actionGroup ref="fillOrderCustomerInformation" stepKey="fillOrder"> From 39d00937285505c7222a917b0b4631471198954f Mon Sep 17 00:00:00 2001 From: Maria Kovdrysh <kovdrysh@adobe.com> Date: Tue, 28 May 2019 15:17:37 -0500 Subject: [PATCH 432/773] MC-4331: Convert DeleteProductsFromCartOfAdvancedCheckoutEntityTest to MFTF --- .../Checkout/Test/Mftf/Section/CheckoutCartProductSection.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartProductSection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartProductSection.xml index a85920998b39c..9eed016adc651 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartProductSection.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartProductSection.xml @@ -47,7 +47,7 @@ <element name="checkoutCartSubtotal" type="text" selector="//td[@class='col subtotal']//span[@class='price']"/> <element name="emptyCart" selector=".cart-empty" type="text"/> <!-- Required attention section --> - <element name="removeProductBySku" type="button" selector="//*[contains(text(), '{{sku}}')]/ancestor::tbody//button" parameterized="true" timeout="30"/> - <element name="failedItemBySku" type="block" selector="//*[@class='cart item' and .//tr[contains(@class,'info') and .//div[contains(.,'{{sku}}')]]]" parameterized="true" timeout="30"/> + <element name="removeProductBySku" type="button" selector="//div[contains(., '{{sku}}')]/ancestor::tbody//button" parameterized="true" timeout="30"/> + <element name="failedItemBySku" type="block" selector="//div[contains(.,'{{sku}}')]/ancestor::tbody" parameterized="true" timeout="30"/> </section> </sections> From 2e22a2552074b88a3b824aaa03553d4ab6ad9061 Mon Sep 17 00:00:00 2001 From: Stsiapan Korf <Stsiapan_Korf@epam.com> Date: Wed, 29 May 2019 11:23:40 +0000 Subject: [PATCH 433/773] MC-5777: Catalog rule does not apply as expected - Unskip tests --- .../ConditionBuilder/EavAttributeCondition.php | 2 +- .../Test/AdminApplyCatalogRuleByCategoryTest.xml | 3 --- .../Mftf/Test/AdminCreateCatalogPriceRuleTest.xml | 15 --------------- .../Mftf/Test/AdminDeleteCatalogPriceRuleTest.xml | 3 --- ...leAttributeIsUndefinedCatalogPriceRuleTest.xml | 2 ++ ...bershipArePersistedUnderLongTermCookieTest.xml | 3 --- .../Test/StorefrontInactiveCatalogRuleTest.xml | 3 --- ...eForConfigurableWithCatalogRuleAppliedTest.xml | 9 +++------ 8 files changed, 6 insertions(+), 34 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Api/SearchCriteria/CollectionProcessor/ConditionProcessor/ConditionBuilder/EavAttributeCondition.php b/app/code/Magento/Catalog/Model/Api/SearchCriteria/CollectionProcessor/ConditionProcessor/ConditionBuilder/EavAttributeCondition.php index e296c8d3b8978..a4a03bef0f39c 100644 --- a/app/code/Magento/Catalog/Model/Api/SearchCriteria/CollectionProcessor/ConditionProcessor/ConditionBuilder/EavAttributeCondition.php +++ b/app/code/Magento/Catalog/Model/Api/SearchCriteria/CollectionProcessor/ConditionProcessor/ConditionBuilder/EavAttributeCondition.php @@ -64,7 +64,7 @@ public function build(Filter $filter): string ->select() ->from( [Collection::MAIN_TABLE_ALIAS => $entityResourceModel->getEntityTable()], - Collection::MAIN_TABLE_ALIAS . '.' . $entityResourceModel->getEntityIdField() + Collection::MAIN_TABLE_ALIAS . '.' . $entityResourceModel->getLinkField() )->joinLeft( [$tableAlias => $attribute->getBackendTable()], $tableAlias . '.' . $attribute->getEntityIdField() . '=' . Collection::MAIN_TABLE_ALIAS . diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminApplyCatalogRuleByCategoryTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminApplyCatalogRuleByCategoryTest.xml index 875a7842f21ff..741da96179b8c 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminApplyCatalogRuleByCategoryTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminApplyCatalogRuleByCategoryTest.xml @@ -16,9 +16,6 @@ <severity value="MAJOR"/> <testCaseId value="MC-74"/> <group value="CatalogRule"/> - <skip> - <issueId value="MC-5777"/> - </skip> </annotations> <before> <createData entity="ApiCategory" stepKey="createCategoryOne"/> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminCreateCatalogPriceRuleTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminCreateCatalogPriceRuleTest.xml index 10db68e9053d7..befe0b0ce7f98 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminCreateCatalogPriceRuleTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminCreateCatalogPriceRuleTest.xml @@ -17,9 +17,6 @@ <severity value="MAJOR"/> <testCaseId value="MC-65"/> <group value="CatalogRule"/> - <skip> - <issueId value="MC-5777"/> - </skip> </annotations> <before> <!-- Create the simple product and category that it will be in --> @@ -77,9 +74,6 @@ <severity value="MAJOR"/> <testCaseId value="MC-93"/> <group value="CatalogRule"/> - <skip> - <issueId value="MC-5777"/> - </skip> </annotations> <before> <actionGroup stepKey="createNewPriceRule" ref="newCatalogPriceRuleByUI"> @@ -103,9 +97,6 @@ <severity value="MAJOR"/> <testCaseId value="MC-69"/> <group value="CatalogRule"/> - <skip> - <issueId value="MC-5777"/> - </skip> </annotations> <before> <actionGroup stepKey="createNewPriceRule" ref="newCatalogPriceRuleByUI"> @@ -129,9 +120,6 @@ <severity value="MAJOR"/> <testCaseId value="MC-60"/> <group value="CatalogRule"/> - <skip> - <issueId value="MC-5777"/> - </skip> </annotations> <before> <actionGroup stepKey="createNewPriceRule" ref="newCatalogPriceRuleByUI"> @@ -155,9 +143,6 @@ <severity value="MAJOR"/> <testCaseId value="MC-71"/> <group value="CatalogRule"/> - <skip> - <issueId value="MC-5777"/> - </skip> </annotations> <before> <!-- Create a simple product and a category--> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminDeleteCatalogPriceRuleTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminDeleteCatalogPriceRuleTest.xml index 06f3682aedd85..d3546d06492be 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminDeleteCatalogPriceRuleTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminDeleteCatalogPriceRuleTest.xml @@ -17,9 +17,6 @@ <severity value="MAJOR"/> <testCaseId value="MC-160"/> <group value="CatalogRule"/> - <skip> - <issueId value="MC-5777"/> - </skip> </annotations> <before> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminEnableAttributeIsUndefinedCatalogPriceRuleTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminEnableAttributeIsUndefinedCatalogPriceRuleTest.xml index 0ff7e0cd85217..f490da2947232 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminEnableAttributeIsUndefinedCatalogPriceRuleTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminEnableAttributeIsUndefinedCatalogPriceRuleTest.xml @@ -63,6 +63,8 @@ <deleteData createDataKey="createSecondProductAttribute" stepKey="deleteSecondProductAttribute"/> <actionGroup ref="logout" stepKey="logout"/> + <magentoCLI command="indexer:reindex" stepKey="reindex"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> </after> <!--Create catalog price rule--> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/CatalogPriceRuleAndCustomerGroupMembershipArePersistedUnderLongTermCookieTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/CatalogPriceRuleAndCustomerGroupMembershipArePersistedUnderLongTermCookieTest.xml index e3eac52a8d40b..738f193fcc511 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/CatalogPriceRuleAndCustomerGroupMembershipArePersistedUnderLongTermCookieTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/CatalogPriceRuleAndCustomerGroupMembershipArePersistedUnderLongTermCookieTest.xml @@ -17,9 +17,6 @@ <severity value="CRITICAL"/> <testCaseId value="MAGETWO-69455"/> <group value="persistent"/> - <skip> - <issueId value="MC-5777"/> - </skip> </annotations> <before> <createData entity="PersistentConfigEnabled" stepKey="enablePersistent"/> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/StorefrontInactiveCatalogRuleTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/StorefrontInactiveCatalogRuleTest.xml index c6ecc1c6d9658..e7be6e8443a36 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/StorefrontInactiveCatalogRuleTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/StorefrontInactiveCatalogRuleTest.xml @@ -17,9 +17,6 @@ <severity value="CRITICAL"/> <testCaseId value="MC-79"/> <group value="CatalogRule"/> - <skip> - <issueId value="MC-5777"/> - </skip> </annotations> <before> <actionGroup ref="LoginAsAdmin" stepKey="login"/> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontSortingByPriceForConfigurableWithCatalogRuleAppliedTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontSortingByPriceForConfigurableWithCatalogRuleAppliedTest.xml index 57c45ee1e8997..c93b216fc89d5 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontSortingByPriceForConfigurableWithCatalogRuleAppliedTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontSortingByPriceForConfigurableWithCatalogRuleAppliedTest.xml @@ -16,9 +16,6 @@ <description value="Sort by price should be correct if the apply Catalog Rule to child product of configurable product"/> <severity value="CRITICAL"/> <testCaseId value="MAGETWO-69988"/> - <skip> - <issueId value="MC-5777"/> - </skip> <group value="сonfigurable_product"/> </annotations> <before> @@ -153,9 +150,9 @@ <argument name="sortBy" value="price"/> <argument name="sort" value="desc"/> </actionGroup> - <see selector="{{StorefrontCategoryMainSection.lineProductName('1')}}" userInput="$$createConfigProduct.name$$" stepKey="seeConfigurableProduct2"/> - <see selector="{{StorefrontCategoryMainSection.lineProductName('2')}}" userInput="$$createSimpleProduct2.name$$" stepKey="seeSimpleProductTwo2"/> - <see selector="{{StorefrontCategoryMainSection.lineProductName('3')}}" userInput="$$createSimpleProduct.name$$" stepKey="seeSimpleProduct2"/> + <see selector="{{StorefrontCategoryMainSection.lineProductName('1')}}" userInput="$$createSimpleProduct2.name$$" stepKey="seeSimpleProductTwo2"/> + <see selector="{{StorefrontCategoryMainSection.lineProductName('2')}}" userInput="$$createSimpleProduct.name$$" stepKey="seeSimpleProduct2"/> + <see selector="{{StorefrontCategoryMainSection.lineProductName('3')}}" userInput="$$createConfigProduct.name$$" stepKey="seeConfigurableProduct2"/> <!-- Delete the rule --> <amOnPage url="{{CatalogRulePage.url}}" stepKey="goToPriceRulePage"/> From da5af740588af07d79a2040e6269d0d8d6df0304 Mon Sep 17 00:00:00 2001 From: Andrii Meysar <andrii.meysar@transoftgroup.com> Date: Wed, 29 May 2019 17:16:21 +0300 Subject: [PATCH 434/773] MC-17016: Overlapping Display Settings configuration for category --- .../adminhtml/Magento/backend/web/css/source/forms/_fields.less | 1 + 1 file changed, 1 insertion(+) diff --git a/app/design/adminhtml/Magento/backend/web/css/source/forms/_fields.less b/app/design/adminhtml/Magento/backend/web/css/source/forms/_fields.less index 66c9086c15aa7..08aeb35d7adb2 100644 --- a/app/design/adminhtml/Magento/backend/web/css/source/forms/_fields.less +++ b/app/design/adminhtml/Magento/backend/web/css/source/forms/_fields.less @@ -545,6 +545,7 @@ & > .admin__field-label { #mix-grid .column(@field-label-grid__column, @field-grid__columns); cursor: pointer; + background: @color-white; left: 0; position: absolute; top: 0; From f17993786512348ea3dbff9f32175863d06c9d9d Mon Sep 17 00:00:00 2001 From: Vitalii Zabaznov <vzabaznov@magento.com> Date: Wed, 29 May 2019 09:40:04 -0500 Subject: [PATCH 435/773] MC-17019: Revert BIC from MC-15785 --- .../Section/StorefrontCheckoutCheckoutCustomerLoginSection.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/StorefrontCheckoutCheckoutCustomerLoginSection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/StorefrontCheckoutCheckoutCustomerLoginSection.xml index 9772fa1993acb..5a3c309c6a1d4 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Section/StorefrontCheckoutCheckoutCustomerLoginSection.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Section/StorefrontCheckoutCheckoutCustomerLoginSection.xml @@ -11,7 +11,7 @@ <section name="StorefrontCheckoutCheckoutCustomerLoginSection"> <element name="email" type="input" selector="form[data-role='email-with-possible-login'] input[name='username']" /> <element name="emailNoteMessage" type="text" selector="//form[@data-role='email-with-possible-login']//div[input[@name='username']]//*[contains(@class, 'note')]" /> - <element name="emailErrorMessage" type="text" selector="//form[@data-role='email-with-possible-login']//div[input[@name='username']]//*[@id='checkout-customer-email-error']" /> + <element name="emailErrorMessage" type="text" selector="//form[@data-role='email-with-possible-login']//div[input[@name='username']]//*[@id='customer-email-error']" /> <element name="emailTooltipButton" type="button" selector="//form[@data-role='email-with-possible-login']//div[input[@name='username']]//*[contains(@class, 'action-help')]" /> <element name="emailTooltipContent" type="text" selector="//form[@data-role='email-with-possible-login']//div[input[@name='username']]//*[contains(@class, 'field-tooltip-content')]" /> <element name="password" type="input" selector="form[data-role='email-with-possible-login'] input[name='password']" /> From c79d722e96cfe2a24492fdfd64cb3f55c015fbe8 Mon Sep 17 00:00:00 2001 From: Yaroslav Rogoza <enarc@atwix.com> Date: Wed, 29 May 2019 19:41:49 +0200 Subject: [PATCH 436/773] Refactoring. Use action groups instead of direct actions in the test --- ...ionErrorForCheckoutAddressFieldsActionGroup.xml | 14 ++++++++++++++ .../Test/Mftf/Section/CheckoutShippingSection.xml | 1 + .../StorefrontOnePageCheckoutJsValidationTest.xml | 11 +++++------ .../TestCase/OnePageCheckoutJsValidationTest.xml | 3 +-- 4 files changed, 21 insertions(+), 8 deletions(-) create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertNoValidationErrorForCheckoutAddressFieldsActionGroup.xml diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertNoValidationErrorForCheckoutAddressFieldsActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertNoValidationErrorForCheckoutAddressFieldsActionGroup.xml new file mode 100644 index 0000000000000..93e73a0c62b29 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAssertNoValidationErrorForCheckoutAddressFieldsActionGroup.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="StorefrontAssertNoValidationErrorForCheckoutAddressFieldsActionGroup"> + <dontSeeElement selector="{{CheckoutShippingSection.addressFieldValidationError}}" stepKey="checkFieldsValidationIsPassed"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingSection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingSection.xml index 97ae206a67005..0b86a1e7c3949 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingSection.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingSection.xml @@ -39,5 +39,6 @@ <element name="editActiveAddress" type="button" selector="//div[@class='shipping-address-item selected-item']//span[text()='Edit']" timeout="30"/> <element name="loginButton" type="button" selector=".action.login" timeout="30"/> <element name="shipHereButton" type="button" selector="//div[text()='{{street}}']/button[@class='action action-select-shipping-item']" parameterized="true" timeout="30"/> + <element name="addressFieldValidationError" type="text" selector="div.address div.field .field-error"/> </section> </sections> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontOnePageCheckoutJsValidationTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontOnePageCheckoutJsValidationTest.xml index b699ecdc5a152..e1bff86542740 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontOnePageCheckoutJsValidationTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontOnePageCheckoutJsValidationTest.xml @@ -21,17 +21,16 @@ <createData entity="ApiSimpleProduct" stepKey="createProduct"> <requiredEntity createDataKey="createCategory"/> </createData> - <actionGroup ref="AddSimpleProductToCart" stepKey="addToCartFromStorefrontProductPage"> - <argument name="product" value="$$createProduct$$"/> - </actionGroup> - <actionGroup ref="GoToCheckoutFromMinicartActionGroup" stepKey="guestGoToCheckoutFromMinicart"/> - <waitForPageLoad stepKey="waitForCheckoutPage"/> </before> <after> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> </after> - <dontSeeElement selector="div .field-error" stepKey="dontSeeValidationErrors"/> + <actionGroup ref="AddSimpleProductToCart" stepKey="addToCartFromStorefrontProductPage"> + <argument name="product" value="$$createProduct$$"/> + </actionGroup> + <actionGroup ref="StorefrontOpenCheckoutPageActionGroup" stepKey="guestGoToCheckout"/> + <actionGroup ref="StorefrontAssertNoValidationErrorForCheckoutAddressFieldsActionGroup" stepKey="seeNoValidationErrors"/> </test> </tests> 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 65ae2dd442d73..8bc5a4d008561 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 @@ -9,10 +9,9 @@ <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="issue" xsi:type="string">MAGETWO-97990: [MTF] OnePageCheckoutJsValidationTestVariation1_0 randomly fails on jenkins</data> - <data name="tag" xsi:type="string">severity:S2</data> + <data name="tag" xsi:type="string">severity:S2,mftf_migrated:yes</data> <data name="products/0" xsi:type="string">catalogProductSimple::default</data> <data name="checkoutMethod" xsi:type="string">guest</data> - <data name="tag" xsi:type="string">mftf_migrated:yes</data> <constraint name="Magento\Checkout\Test\Constraint\AssertShippingAddressJsValidationMessagesIsAbsent" /> </variation> </testCase> From f04a5a9302c1d188d34275c3635bdbd33668664d Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Thu, 30 May 2019 13:41:07 +0300 Subject: [PATCH 437/773] magento/magento2#18075: Static test fix. --- setup/src/Magento/Setup/Model/Installer.php | 47 +++++++++++-------- .../Test/Unit/Model/ConfigGeneratorTest.php | 3 ++ .../Test/Unit/Module/ConfigGeneratorTest.php | 4 ++ .../Validator/AdminCredentialsValidator.php | 18 +++---- .../Magento/Setup/Validator/DbValidator.php | 20 ++++---- vendor/.htaccess | 8 ---- 6 files changed, 57 insertions(+), 43 deletions(-) delete mode 100644 vendor/.htaccess diff --git a/setup/src/Magento/Setup/Model/Installer.php b/setup/src/Magento/Setup/Model/Installer.php index 0b0ad0ff54c4d..254d45c14862a 100644 --- a/setup/src/Magento/Setup/Model/Installer.php +++ b/setup/src/Magento/Setup/Model/Installer.php @@ -28,7 +28,8 @@ use Magento\Framework\Setup\InstallSchemaInterface; use Magento\Framework\Setup\LoggerInterface; use Magento\Framework\Setup\ModuleDataSetupInterface; -use Magento\Framework\Setup\PatchApplierInterface; +use Magento\Framework\Setup\Patch\PatchApplier; +use Magento\Framework\Setup\Patch\PatchApplierFactory; use Magento\Framework\Setup\SchemaPersistor; use Magento\Framework\Setup\SchemaSetupInterface; use Magento\Framework\Setup\UpgradeDataInterface; @@ -36,8 +37,6 @@ use Magento\Setup\Console\Command\InstallCommand; use Magento\Setup\Controller\ResponseTypeInterface; use Magento\Setup\Model\ConfigModel as SetupConfigModel; -use Magento\Framework\Setup\Patch\PatchApplier; -use Magento\Framework\Setup\Patch\PatchApplierFactory; use Magento\Setup\Module\ConnectionFactory; use Magento\Setup\Module\DataSetupFactory; use Magento\Setup\Module\SetupFactory; @@ -516,6 +515,7 @@ public function checkExtensions() ) { $errorMsg = "Missing following extensions: '" . implode("' '", $phpExtensionsCheckResult['data']['missing']) . "'"; + // phpcs:ignore Magento2.Exceptions.DirectThrow throw new \Exception($errorMsg); } } @@ -900,6 +900,7 @@ private function throwExceptionForNotWritablePaths(array $paths) { if ($paths) { $errorMsg = "Missing write permissions to the following paths:" . PHP_EOL . implode(PHP_EOL, $paths); + // phpcs:ignore Magento2.Exceptions.DirectThrow throw new \Exception($errorMsg); } } @@ -941,10 +942,12 @@ private function handleDBSchemaData($setup, $type, array $request) if ($type === 'schema') { $patchApplier = $this->patchApplierFactory->create(['schemaSetup' => $setup]); } elseif ($type === 'data') { - $patchApplier = $this->patchApplierFactory->create([ - 'moduleDataSetup' => $setup, - 'objectManager' => $this->objectManagerProvider->get() - ]); + $patchApplier = $this->patchApplierFactory->create( + [ + 'moduleDataSetup' => $setup, + 'objectManager' => $this->objectManagerProvider->get() + ] + ); } foreach ($moduleNames as $moduleName) { @@ -1311,7 +1314,9 @@ public function cleanupDb() //If for different shards one database was specified - no need to clean it few times if (!in_array($dbName, $cleanedUpDatabases)) { $this->log->log("Cleaning up database {$dbName}"); + // phpcs:ignore Magento2.SQL.RawQuery $connection->query("DROP DATABASE IF EXISTS {$dbName}"); + // phpcs:ignore Magento2.SQL.RawQuery $connection->query("CREATE DATABASE IF NOT EXISTS {$dbName}"); $cleanedUpDatabases[] = $dbName; } @@ -1511,18 +1516,22 @@ private function cleanupGeneratedFiles() */ private function isAdminDataSet($request) { - $adminData = array_filter($request, function ($value, $key) { - return in_array( - $key, - [ - AdminAccount::KEY_EMAIL, - AdminAccount::KEY_FIRST_NAME, - AdminAccount::KEY_LAST_NAME, - AdminAccount::KEY_USER, - AdminAccount::KEY_PASSWORD, - ] - ) && $value !== null; - }, ARRAY_FILTER_USE_BOTH); + $adminData = array_filter( + $request, + function ($value, $key) { + return in_array( + $key, + [ + AdminAccount::KEY_EMAIL, + AdminAccount::KEY_FIRST_NAME, + AdminAccount::KEY_LAST_NAME, + AdminAccount::KEY_USER, + AdminAccount::KEY_PASSWORD, + ] + ) && $value !== null; + }, + ARRAY_FILTER_USE_BOTH + ); return !empty($adminData); } diff --git a/setup/src/Magento/Setup/Test/Unit/Model/ConfigGeneratorTest.php b/setup/src/Magento/Setup/Test/Unit/Model/ConfigGeneratorTest.php index 22de958070b8f..63a92bd4a1982 100644 --- a/setup/src/Magento/Setup/Test/Unit/Model/ConfigGeneratorTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Model/ConfigGeneratorTest.php @@ -13,6 +13,9 @@ use Magento\Setup\Model\ConfigGenerator; use Magento\Setup\Model\ConfigOptionsList\DriverOptions; +/** + * Test for Magento\Setup\Model\ConfigGenerator class. + */ class ConfigGeneratorTest extends \PHPUnit\Framework\TestCase { /** diff --git a/setup/src/Magento/Setup/Test/Unit/Module/ConfigGeneratorTest.php b/setup/src/Magento/Setup/Test/Unit/Module/ConfigGeneratorTest.php index 15e334909f50a..ea4261b271582 100644 --- a/setup/src/Magento/Setup/Test/Unit/Module/ConfigGeneratorTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Module/ConfigGeneratorTest.php @@ -17,6 +17,9 @@ use PHPUnit\Framework\TestCase; use Magento\Setup\Model\ConfigOptionsList\DriverOptions; +/** + * Test for Magento\Setup\Model\ConfigGenerator class. + */ class ConfigGeneratorTest extends TestCase { /** @@ -71,6 +74,7 @@ public function testCreateCryptConfigWithoutInput() { $returnValue = $this->configGeneratorObject->createCryptConfig([]); $this->assertEquals(ConfigFilePool::APP_ENV, $returnValue->getFileKey()); + // phpcs:ignore Magento2.Security.InsecureFunction $this->assertEquals(['crypt' => ['key' => md5('key')]], $returnValue->getData()); } diff --git a/setup/src/Magento/Setup/Validator/AdminCredentialsValidator.php b/setup/src/Magento/Setup/Validator/AdminCredentialsValidator.php index ced1ff395396c..941adf12825e4 100644 --- a/setup/src/Magento/Setup/Validator/AdminCredentialsValidator.php +++ b/setup/src/Magento/Setup/Validator/AdminCredentialsValidator.php @@ -66,14 +66,16 @@ public function validate(array $data) { $driverOptions = $this->driverOptions->getDriverOptions($data); - $dbConnection = $this->connectionFactory->create([ - ConfigOption::KEY_NAME => $data[ConfigOption::INPUT_KEY_DB_NAME], - ConfigOption::KEY_HOST => $data[ConfigOption::INPUT_KEY_DB_HOST], - ConfigOption::KEY_USER => $data[ConfigOption::INPUT_KEY_DB_USER], - ConfigOption::KEY_PASSWORD => $data[ConfigOption::INPUT_KEY_DB_PASSWORD], - ConfigOption::KEY_PREFIX => $data[ConfigOption::INPUT_KEY_DB_PREFIX], - ConfigOption::KEY_DRIVER_OPTIONS => $driverOptions - ]); + $dbConnection = $this->connectionFactory->create( + [ + ConfigOption::KEY_NAME => $data[ConfigOption::INPUT_KEY_DB_NAME], + ConfigOption::KEY_HOST => $data[ConfigOption::INPUT_KEY_DB_HOST], + ConfigOption::KEY_USER => $data[ConfigOption::INPUT_KEY_DB_USER], + ConfigOption::KEY_PASSWORD => $data[ConfigOption::INPUT_KEY_DB_PASSWORD], + ConfigOption::KEY_PREFIX => $data[ConfigOption::INPUT_KEY_DB_PREFIX], + ConfigOption::KEY_DRIVER_OPTIONS => $driverOptions + ] + ); $adminAccount = $this->adminAccountFactory->create( $dbConnection, diff --git a/setup/src/Magento/Setup/Validator/DbValidator.php b/setup/src/Magento/Setup/Validator/DbValidator.php index a2633aead01a1..01ed537f887cd 100644 --- a/setup/src/Magento/Setup/Validator/DbValidator.php +++ b/setup/src/Magento/Setup/Validator/DbValidator.php @@ -100,14 +100,16 @@ public function checkDatabaseConnectionWithDriverOptions( $driverOptions = [] ) { // establish connection to information_schema view to retrieve information about user and table privileges - $connection = $this->connectionFactory->create([ - ConfigOptionsListConstants::KEY_NAME => 'information_schema', - ConfigOptionsListConstants::KEY_HOST => $dbHost, - ConfigOptionsListConstants::KEY_USER => $dbUser, - ConfigOptionsListConstants::KEY_PASSWORD => $dbPass, - ConfigOptionsListConstants::KEY_ACTIVE => true, - ConfigOptionsListConstants::KEY_DRIVER_OPTIONS => $driverOptions, - ]); + $connection = $this->connectionFactory->create( + [ + ConfigOptionsListConstants::KEY_NAME => 'information_schema', + ConfigOptionsListConstants::KEY_HOST => $dbHost, + ConfigOptionsListConstants::KEY_USER => $dbUser, + ConfigOptionsListConstants::KEY_PASSWORD => $dbPass, + ConfigOptionsListConstants::KEY_ACTIVE => true, + ConfigOptionsListConstants::KEY_DRIVER_OPTIONS => $driverOptions, + ] + ); if (!$connection) { throw new \Magento\Setup\Exception('Database connection failure.'); @@ -182,6 +184,7 @@ private function checkDatabasePrivileges(\Magento\Framework\DB\Adapter\AdapterIn ]; // check global privileges + // phpcs:ignore Magento2.SQL.RawQuery $userPrivilegesQuery = "SELECT PRIVILEGE_TYPE FROM USER_PRIVILEGES " . "WHERE REPLACE(GRANTEE, '\'', '') = current_user()"; $grantInfo = $connection->query($userPrivilegesQuery)->fetchAll(\PDO::FETCH_NUM); @@ -190,6 +193,7 @@ private function checkDatabasePrivileges(\Magento\Framework\DB\Adapter\AdapterIn } // check database privileges + // phpcs:ignore Magento2.SQL.RawQuery $schemaPrivilegesQuery = "SELECT PRIVILEGE_TYPE FROM SCHEMA_PRIVILEGES " . "WHERE '$dbName' LIKE TABLE_SCHEMA AND REPLACE(GRANTEE, '\'', '') = current_user()"; $grantInfo = $connection->query($schemaPrivilegesQuery)->fetchAll(\PDO::FETCH_NUM); diff --git a/vendor/.htaccess b/vendor/.htaccess deleted file mode 100644 index 707c26b075e16..0000000000000 --- a/vendor/.htaccess +++ /dev/null @@ -1,8 +0,0 @@ -<IfVersion < 2.4> - order allow,deny - deny from all -</IfVersion> -<IfVersion >= 2.4> - Require all denied -</IfVersion> - From 4992b46b1340b5ab8fc104f72519ccc366f8c265 Mon Sep 17 00:00:00 2001 From: Nikita Chubukov <nikita_chubukov@epam.com> Date: Thu, 30 May 2019 19:28:37 +0300 Subject: [PATCH 438/773] MAGETWO-59431: Sample Data does not scale correctly when resize window as mobile view - Fix homepage layout --- app/design/frontend/Magento/blank/web/css/source/_layout.less | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/design/frontend/Magento/blank/web/css/source/_layout.less b/app/design/frontend/Magento/blank/web/css/source/_layout.less index 24743c665b460..62195b5566f8e 100644 --- a/app/design/frontend/Magento/blank/web/css/source/_layout.less +++ b/app/design/frontend/Magento/blank/web/css/source/_layout.less @@ -18,7 +18,7 @@ .column.main { &:extend(.abs-add-box-sizing all); .lib-css(padding-bottom, @indent__xl); - .lib-vendor-prefix-flex-basis(100%); + .lib-vendor-prefix-flex-basis(auto); .lib-vendor-prefix-flex-grow(1); .lib-vendor-prefix-order(1); width: 100%; From 4a5c06099995c9979ce790b596265b365697cf3d Mon Sep 17 00:00:00 2001 From: OlgaVasyltsun <olga.vasyltsun@gmail.com> Date: Fri, 31 May 2019 15:55:09 +0300 Subject: [PATCH 439/773] MC-17050: ElasticSearch6 Broken w/ Boolean Attribute --- .../FieldType/Resolver/IntegerType.php | 3 +- .../FieldMapper/Product/AttributeAdapter.php | 4 +-- .../FieldType/Resolver/IntegerType.php | 4 +-- .../FieldType/Resolver/IntegerTypeTest.php | 32 +++++++++---------- .../FieldType/Resolver/IntegerTypeTest.php | 32 +++++++++---------- 5 files changed, 36 insertions(+), 39 deletions(-) diff --git a/app/code/Magento/Elasticsearch/Elasticsearch5/Model/Adapter/FieldMapper/Product/FieldProvider/FieldType/Resolver/IntegerType.php b/app/code/Magento/Elasticsearch/Elasticsearch5/Model/Adapter/FieldMapper/Product/FieldProvider/FieldType/Resolver/IntegerType.php index e5c8dd48c7af3..bbfcce6aa695b 100644 --- a/app/code/Magento/Elasticsearch/Elasticsearch5/Model/Adapter/FieldMapper/Product/FieldProvider/FieldType/Resolver/IntegerType.php +++ b/app/code/Magento/Elasticsearch/Elasticsearch5/Model/Adapter/FieldMapper/Product/FieldProvider/FieldType/Resolver/IntegerType.php @@ -45,8 +45,7 @@ public function __construct(ConverterInterface $fieldTypeConverter, $integerType public function getFieldType(AttributeAdapter $attribute): ?string { if (in_array($attribute->getAttributeCode(), $this->integerTypeAttributes, true) - || (($attribute->isIntegerType() || $attribute->isBooleanType()) - && !$attribute->isUserDefined()) + || ($attribute->isIntegerType() || $attribute->isBooleanType()) ) { return $this->fieldTypeConverter->convert(ConverterInterface::INTERNAL_DATA_TYPE_INT); } diff --git a/app/code/Magento/Elasticsearch/Model/Adapter/FieldMapper/Product/AttributeAdapter.php b/app/code/Magento/Elasticsearch/Model/Adapter/FieldMapper/Product/AttributeAdapter.php index 54586fa357ff0..165f7e78eb65f 100644 --- a/app/code/Magento/Elasticsearch/Model/Adapter/FieldMapper/Product/AttributeAdapter.php +++ b/app/code/Magento/Elasticsearch/Model/Adapter/FieldMapper/Product/AttributeAdapter.php @@ -159,9 +159,9 @@ public function isSortable(): bool /** * Check if attribute is defined by user. * - * @return string + * @return bool|null */ - public function isUserDefined(): string + public function isUserDefined() { return $this->getAttribute()->getIsUserDefined(); } diff --git a/app/code/Magento/Elasticsearch/Model/Adapter/FieldMapper/Product/FieldProvider/FieldType/Resolver/IntegerType.php b/app/code/Magento/Elasticsearch/Model/Adapter/FieldMapper/Product/FieldProvider/FieldType/Resolver/IntegerType.php index 7793f60cd1efc..f1e6c8abeb439 100644 --- a/app/code/Magento/Elasticsearch/Model/Adapter/FieldMapper/Product/FieldProvider/FieldType/Resolver/IntegerType.php +++ b/app/code/Magento/Elasticsearch/Model/Adapter/FieldMapper/Product/FieldProvider/FieldType/Resolver/IntegerType.php @@ -37,9 +37,7 @@ public function __construct(ConverterInterface $fieldTypeConverter) */ public function getFieldType(AttributeAdapter $attribute): ?string { - if (($attribute->isIntegerType() || $attribute->isBooleanType()) - && !$attribute->isUserDefined() - ) { + if ($attribute->isIntegerType() || $attribute->isBooleanType()) { return $this->fieldTypeConverter->convert(ConverterInterface::INTERNAL_DATA_TYPE_INT); } diff --git a/app/code/Magento/Elasticsearch/Test/Unit/Elasticsearch5/Model/Adapter/FieldMapper/Product/FieldProvider/FieldType/Resolver/IntegerTypeTest.php b/app/code/Magento/Elasticsearch/Test/Unit/Elasticsearch5/Model/Adapter/FieldMapper/Product/FieldProvider/FieldType/Resolver/IntegerTypeTest.php index 39155e4f4fe02..c5eea2f897ea6 100644 --- a/app/code/Magento/Elasticsearch/Test/Unit/Elasticsearch5/Model/Adapter/FieldMapper/Product/FieldProvider/FieldType/Resolver/IntegerTypeTest.php +++ b/app/code/Magento/Elasticsearch/Test/Unit/Elasticsearch5/Model/Adapter/FieldMapper/Product/FieldProvider/FieldType/Resolver/IntegerTypeTest.php @@ -53,15 +53,18 @@ protected function setUp() /** * @dataProvider getFieldTypeProvider - * @param $attributeCode - * @param $isIntegerType - * @param $isBooleanType - * @param $isUserDefined - * @param $expected + * @param string $attributeCode + * @param bool $isIntegerType + * @param bool $isBooleanType + * @param string $expected * @return void */ - public function testGetFieldType($attributeCode, $isIntegerType, $isBooleanType, $isUserDefined, $expected) - { + public function testGetFieldType( + string $attributeCode, + bool $isIntegerType, + bool $isBooleanType, + string $expected + ): void { $attributeMock = $this->getMockBuilder(AttributeAdapter::class) ->disableOriginalConstructor() ->setMethods(['getAttributeCode', 'isIntegerType', 'isBooleanType', 'isUserDefined']) @@ -75,9 +78,6 @@ public function testGetFieldType($attributeCode, $isIntegerType, $isBooleanType, $attributeMock->expects($this->any()) ->method('isBooleanType') ->willReturn($isBooleanType); - $attributeMock->expects($this->any()) - ->method('isUserDefined') - ->willReturn($isUserDefined); $this->fieldTypeConverter->expects($this->any()) ->method('convert') ->willReturn('something'); @@ -94,12 +94,12 @@ public function testGetFieldType($attributeCode, $isIntegerType, $isBooleanType, public function getFieldTypeProvider() { return [ - ['category_ids', true, true, true, 'something'], - ['category_ids', false, false, false, 'something'], - ['type', true, false, false, 'something'], - ['type', false, true, false, 'something'], - ['type', true, true, true, ''], - ['type', false, false, true, ''], + ['category_ids', true, true, 'something'], + ['category_ids', false, false, 'something'], + ['type', true, false, 'something'], + ['type', false, true, 'something'], + ['type', true, true, 'something'], + ['type', false, false, ''], ]; } } diff --git a/app/code/Magento/Elasticsearch/Test/Unit/Model/Adapter/FieldMapper/Product/FieldProvider/FieldType/Resolver/IntegerTypeTest.php b/app/code/Magento/Elasticsearch/Test/Unit/Model/Adapter/FieldMapper/Product/FieldProvider/FieldType/Resolver/IntegerTypeTest.php index 7570c8971b27b..c45ebe20b6be6 100644 --- a/app/code/Magento/Elasticsearch/Test/Unit/Model/Adapter/FieldMapper/Product/FieldProvider/FieldType/Resolver/IntegerTypeTest.php +++ b/app/code/Magento/Elasticsearch/Test/Unit/Model/Adapter/FieldMapper/Product/FieldProvider/FieldType/Resolver/IntegerTypeTest.php @@ -52,15 +52,18 @@ protected function setUp() /** * @dataProvider getFieldTypeProvider - * @param $attributeCode - * @param $isIntegerType - * @param $isBooleanType - * @param $isUserDefined - * @param $expected + * @param string $attributeCode + * @param bool $isIntegerType + * @param bool $isBooleanType + * @param string|null $expected * @return void */ - public function testGetFieldType($attributeCode, $isIntegerType, $isBooleanType, $isUserDefined, $expected) - { + public function testGetFieldType( + string $attributeCode, + bool $isIntegerType, + bool $isBooleanType, + $expected + ): void { $attributeMock = $this->getMockBuilder(AttributeAdapter::class) ->disableOriginalConstructor() ->setMethods(['getAttributeCode', 'isIntegerType', 'isBooleanType', 'isUserDefined']) @@ -74,9 +77,6 @@ public function testGetFieldType($attributeCode, $isIntegerType, $isBooleanType, $attributeMock->expects($this->any()) ->method('isBooleanType') ->willReturn($isBooleanType); - $attributeMock->expects($this->any()) - ->method('isUserDefined') - ->willReturn($isUserDefined); $this->fieldTypeConverter->expects($this->any()) ->method('convert') ->willReturn('something'); @@ -93,12 +93,12 @@ public function testGetFieldType($attributeCode, $isIntegerType, $isBooleanType, public function getFieldTypeProvider() { return [ - ['category_ids', true, true, true, null], - ['category_ids', false, false, false, null], - ['type', true, false, false, 'something'], - ['type', false, true, false, 'something'], - ['type', true, true, true, ''], - ['type', false, false, true, ''], + ['category_ids', true, true, 'something'], + ['category_ids', false, false, null], + ['type', true, false, 'something'], + ['type', false, true, 'something'], + ['type', true, true, 'something'], + ['type', false, false, ''], ]; } } From ee288c10b9edfa02557c046efc1f1476d5c60808 Mon Sep 17 00:00:00 2001 From: Jayanka <jayan@codilar.com> Date: Fri, 31 May 2019 21:35:39 +0530 Subject: [PATCH 440/773] Call the originalSubmitHandler only if array inputs are found in form --- lib/web/mage/validation.js | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/lib/web/mage/validation.js b/lib/web/mage/validation.js index a7bab813dde18..e62de7c4d98ee 100644 --- a/lib/web/mage/validation.js +++ b/lib/web/mage/validation.js @@ -1940,18 +1940,22 @@ }); }); - /** - * Before submitting the actual form, remove the previously assigned indices - * @param {Object} form - */ - this.options.submitHandler = function (form) { - originalElements.forEach(function (element) { - element.element.attr('name', element.name); - element.element.removeAttr('orig-name'); - }); - /* Call the originalSubmitHandler if it's a function */ - typeof originalSubmitHandler === 'function' ? originalSubmitHandler(form) : void(0); - }; + if (originalElements.length) { + /** + * Before submitting the actual form, remove the previously assigned indices + * @param {Object} form + */ + this.options.submitHandler = function (form, event) { + originalElements.forEach(function (element) { + element.element.attr('name', element.name); + element.element.removeAttr('orig-name'); + }); + + console.error(this.submit) + /* Call the originalSubmitHandler if it's a function */ + typeof originalSubmitHandler === 'function' ? originalSubmitHandler(form) : form.submit(); + }; + } }, /** From 139ccd580ece01b0726154274e56a268d3fc2cfe Mon Sep 17 00:00:00 2001 From: Vitaliy Honcharenko <vgoncharenko@magento.com> Date: Fri, 31 May 2019 14:56:04 -0500 Subject: [PATCH 441/773] MC-17167: Fix BIC for Context classes --- app/code/Magento/Backend/Block/Context.php | 6 +++--- app/code/Magento/Backend/Block/Template/Context.php | 10 +++++----- app/code/Magento/Backend/Block/Widget/Context.php | 10 +++++----- app/code/Magento/Catalog/Block/Product/Context.php | 10 +++++----- .../Magento/Framework/View/Element/Context.php | 5 +++-- .../Framework/View/Element/Template/Context.php | 6 +++--- 6 files changed, 24 insertions(+), 23 deletions(-) diff --git a/app/code/Magento/Backend/Block/Context.php b/app/code/Magento/Backend/Block/Context.php index 47e92a655bd5d..d95a76abe2630 100644 --- a/app/code/Magento/Backend/Block/Context.php +++ b/app/code/Magento/Backend/Block/Context.php @@ -47,8 +47,8 @@ class Context extends \Magento\Framework\View\Element\Context * @param \Magento\Framework\Filter\FilterManager $filterManager * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate * @param \Magento\Framework\Translate\Inline\StateInterface $inlineTranslation - * @param LockGuardedCacheLoader $lockQuery * @param \Magento\Framework\AuthorizationInterface $authorization + * @param LockGuardedCacheLoader|null $lockQuery * * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -70,8 +70,8 @@ public function __construct( \Magento\Framework\Filter\FilterManager $filterManager, \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate, \Magento\Framework\Translate\Inline\StateInterface $inlineTranslation, - LockGuardedCacheLoader $lockQuery, - \Magento\Framework\AuthorizationInterface $authorization + \Magento\Framework\AuthorizationInterface $authorization, + LockGuardedCacheLoader $lockQuery = null ) { $this->_authorization = $authorization; parent::__construct( diff --git a/app/code/Magento/Backend/Block/Template/Context.php b/app/code/Magento/Backend/Block/Template/Context.php index 5d345a5a8b67e..6554df88a753c 100644 --- a/app/code/Magento/Backend/Block/Template/Context.php +++ b/app/code/Magento/Backend/Block/Template/Context.php @@ -74,7 +74,6 @@ class Context extends \Magento\Framework\View\Element\Template\Context * @param \Magento\Framework\Filter\FilterManager $filterManager * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate * @param \Magento\Framework\Translate\Inline\StateInterface $inlineTranslation - * @param LockGuardedCacheLoader $lockQuery * @param \Magento\Framework\Filesystem $filesystem * @param \Magento\Framework\View\FileSystem $viewFileSystem * @param \Magento\Framework\View\TemplateEnginePool $enginePool @@ -88,6 +87,7 @@ class Context extends \Magento\Framework\View\Element\Template\Context * @param \Magento\Framework\Math\Random $mathRandom * @param \Magento\Framework\Data\Form\FormKey $formKey * @param \Magento\Framework\Code\NameBuilder $nameBuilder + * @param LockGuardedCacheLoader|null $lockQuery * * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -109,7 +109,6 @@ public function __construct( \Magento\Framework\Filter\FilterManager $filterManager, \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate, \Magento\Framework\Translate\Inline\StateInterface $inlineTranslation, - LockGuardedCacheLoader $lockQuery, \Magento\Framework\Filesystem $filesystem, \Magento\Framework\View\FileSystem $viewFileSystem, \Magento\Framework\View\TemplateEnginePool $enginePool, @@ -122,7 +121,8 @@ public function __construct( \Magento\Backend\Model\Session $backendSession, \Magento\Framework\Math\Random $mathRandom, \Magento\Framework\Data\Form\FormKey $formKey, - \Magento\Framework\Code\NameBuilder $nameBuilder + \Magento\Framework\Code\NameBuilder $nameBuilder, + LockGuardedCacheLoader $lockQuery = null ) { $this->_authorization = $authorization; $this->_backendSession = $backendSession; @@ -147,7 +147,6 @@ public function __construct( $filterManager, $localeDate, $inlineTranslation, - $lockQuery, $filesystem, $viewFileSystem, $enginePool, @@ -155,7 +154,8 @@ public function __construct( $storeManager, $pageConfig, $resolver, - $validator + $validator, + $lockQuery ); } diff --git a/app/code/Magento/Backend/Block/Widget/Context.php b/app/code/Magento/Backend/Block/Widget/Context.php index 13186696a4781..69374979b3fe5 100644 --- a/app/code/Magento/Backend/Block/Widget/Context.php +++ b/app/code/Magento/Backend/Block/Widget/Context.php @@ -57,7 +57,6 @@ class Context extends \Magento\Backend\Block\Template\Context * @param \Magento\Framework\Filter\FilterManager $filterManager * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate * @param \Magento\Framework\Translate\Inline\StateInterface $inlineTranslation - * @param LockGuardedCacheLoader $lockQuery * @param \Magento\Framework\Filesystem $filesystem * @param \Magento\Framework\View\FileSystem $viewFileSystem * @param \Magento\Framework\View\TemplateEnginePool $enginePool @@ -73,6 +72,7 @@ class Context extends \Magento\Backend\Block\Template\Context * @param \Magento\Framework\Code\NameBuilder $nameBuilder * @param \Magento\Backend\Block\Widget\Button\ButtonList $buttonList * @param Button\ToolbarInterface $toolbar + * @param LockGuardedCacheLoader|null $lockQuery * * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -94,7 +94,6 @@ public function __construct( \Magento\Framework\Filter\FilterManager $filterManager, \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate, \Magento\Framework\Translate\Inline\StateInterface $inlineTranslation, - LockGuardedCacheLoader $lockQuery, \Magento\Framework\Filesystem $filesystem, \Magento\Framework\View\FileSystem $viewFileSystem, \Magento\Framework\View\TemplateEnginePool $enginePool, @@ -109,7 +108,8 @@ public function __construct( \Magento\Framework\Data\Form\FormKey $formKey, \Magento\Framework\Code\NameBuilder $nameBuilder, Button\ButtonList $buttonList, - Button\ToolbarInterface $toolbar + Button\ToolbarInterface $toolbar, + LockGuardedCacheLoader $lockQuery = null ) { parent::__construct( $request, @@ -129,7 +129,6 @@ public function __construct( $filterManager, $localeDate, $inlineTranslation, - $lockQuery, $filesystem, $viewFileSystem, $enginePool, @@ -142,7 +141,8 @@ public function __construct( $backendSession, $mathRandom, $formKey, - $nameBuilder + $nameBuilder, + $lockQuery ); $this->buttonList = $buttonList; diff --git a/app/code/Magento/Catalog/Block/Product/Context.php b/app/code/Magento/Catalog/Block/Product/Context.php index ea7d2467d2917..db18eb2bc8a7d 100644 --- a/app/code/Magento/Catalog/Block/Product/Context.php +++ b/app/code/Magento/Catalog/Block/Product/Context.php @@ -106,7 +106,6 @@ class Context extends \Magento\Framework\View\Element\Template\Context * @param \Magento\Framework\Filter\FilterManager $filterManager * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate * @param \Magento\Framework\Translate\Inline\StateInterface $inlineTranslation - * @param LockGuardedCacheLoader $lockQuery * @param \Magento\Framework\Filesystem $filesystem * @param \Magento\Framework\View\FileSystem $viewFileSystem * @param \Magento\Framework\View\TemplateEnginePool $enginePool @@ -127,6 +126,7 @@ class Context extends \Magento\Framework\View\Element\Template\Context * @param ImageBuilder $imageBuilder * @param ReviewRendererInterface $reviewRenderer * @param \Magento\CatalogInventory\Api\StockRegistryInterface $stockRegistry + * @param LockGuardedCacheLoader|null $lockQuery * * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -148,7 +148,6 @@ public function __construct( \Magento\Framework\Filter\FilterManager $filterManager, \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate, \Magento\Framework\Translate\Inline\StateInterface $inlineTranslation, - LockGuardedCacheLoader $lockQuery, \Magento\Framework\Filesystem $filesystem, \Magento\Framework\View\FileSystem $viewFileSystem, \Magento\Framework\View\TemplateEnginePool $enginePool, @@ -168,7 +167,8 @@ public function __construct( \Magento\Catalog\Helper\Image $imageHelper, \Magento\Catalog\Block\Product\ImageBuilder $imageBuilder, ReviewRendererInterface $reviewRenderer, - \Magento\CatalogInventory\Api\StockRegistryInterface $stockRegistry + \Magento\CatalogInventory\Api\StockRegistryInterface $stockRegistry, + LockGuardedCacheLoader $lockQuery = null ) { $this->imageHelper = $imageHelper; $this->imageBuilder = $imageBuilder; @@ -200,7 +200,6 @@ public function __construct( $filterManager, $localeDate, $inlineTranslation, - $lockQuery, $filesystem, $viewFileSystem, $enginePool, @@ -208,7 +207,8 @@ public function __construct( $storeManager, $pageConfig, $resolver, - $validator + $validator, + $lockQuery ); } diff --git a/lib/internal/Magento/Framework/View/Element/Context.php b/lib/internal/Magento/Framework/View/Element/Context.php index 989a6dbf55b98..0f8123745e7e8 100644 --- a/lib/internal/Magento/Framework/View/Element/Context.php +++ b/lib/internal/Magento/Framework/View/Element/Context.php @@ -6,6 +6,7 @@ namespace Magento\Framework\View\Element; use Magento\Framework\Cache\LockGuardedCacheLoader; +use Magento\Framework\App\ObjectManager; /** * Constructor modification point for Magento\Framework\View\Element\AbstractBlock. @@ -182,7 +183,7 @@ public function __construct( \Magento\Framework\Filter\FilterManager $filterManager, \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate, \Magento\Framework\Translate\Inline\StateInterface $inlineTranslation, - LockGuardedCacheLoader $lockQuery + LockGuardedCacheLoader $lockQuery = null ) { $this->_request = $request; $this->_layout = $layout; @@ -201,7 +202,7 @@ public function __construct( $this->_filterManager = $filterManager; $this->_localeDate = $localeDate; $this->inlineTranslation = $inlineTranslation; - $this->lockQuery = $lockQuery; + $this->lockQuery = $lockQuery ?: ObjectManager::getInstance()->get(LockGuardedCacheLoader::class); } /** diff --git a/lib/internal/Magento/Framework/View/Element/Template/Context.php b/lib/internal/Magento/Framework/View/Element/Template/Context.php index 4e86a37aa7e09..4538fb33a9726 100644 --- a/lib/internal/Magento/Framework/View/Element/Template/Context.php +++ b/lib/internal/Magento/Framework/View/Element/Template/Context.php @@ -99,7 +99,6 @@ class Context extends \Magento\Framework\View\Element\Context * @param \Magento\Framework\Filter\FilterManager $filterManager * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate * @param \Magento\Framework\Translate\Inline\StateInterface $inlineTranslation - * @param LockGuardedCacheLoader $lockQuery * @param \Magento\Framework\Filesystem $filesystem * @param \Magento\Framework\View\FileSystem $viewFileSystem * @param \Magento\Framework\View\TemplateEnginePool $enginePool @@ -108,6 +107,7 @@ class Context extends \Magento\Framework\View\Element\Context * @param \Magento\Framework\View\Page\Config $pageConfig * @param \Magento\Framework\View\Element\Template\File\Resolver $resolver * @param \Magento\Framework\View\Element\Template\File\Validator $validator + * @param LockGuardedCacheLoader|null $lockQuery * * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -129,7 +129,6 @@ public function __construct( \Magento\Framework\Filter\FilterManager $filterManager, \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate, \Magento\Framework\Translate\Inline\StateInterface $inlineTranslation, - LockGuardedCacheLoader $lockQuery, \Magento\Framework\Filesystem $filesystem, \Magento\Framework\View\FileSystem $viewFileSystem, \Magento\Framework\View\TemplateEnginePool $enginePool, @@ -137,7 +136,8 @@ public function __construct( \Magento\Store\Model\StoreManagerInterface $storeManager, \Magento\Framework\View\Page\Config $pageConfig, \Magento\Framework\View\Element\Template\File\Resolver $resolver, - \Magento\Framework\View\Element\Template\File\Validator $validator + \Magento\Framework\View\Element\Template\File\Validator $validator, + LockGuardedCacheLoader $lockQuery = null ) { parent::__construct( $request, From fe6ef1b0fcef0f0b844a28f615e3e5005a5bbc19 Mon Sep 17 00:00:00 2001 From: David Verholen <david@verholen.com> Date: Sun, 2 Jun 2019 11:59:07 +0200 Subject: [PATCH 442/773] fix customer data race condition when bundling is enabled --- .../Customer/view/frontend/web/js/customer-data.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Customer/view/frontend/web/js/customer-data.js b/app/code/Magento/Customer/view/frontend/web/js/customer-data.js index 66d37cb84e9cb..f6774c3964615 100644 --- a/app/code/Magento/Customer/view/frontend/web/js/customer-data.js +++ b/app/code/Magento/Customer/view/frontend/web/js/customer-data.js @@ -11,12 +11,13 @@ define([ 'underscore', 'ko', 'Magento_Customer/js/section-config', + 'mage/url', 'mage/storage', 'jquery/jquery-storageapi' -], function ($, _, ko, sectionConfig) { +], function ($, _, ko, sectionConfig, url) { 'use strict'; - var options, + var options = {}, storage, storageInvalidation, invalidateCacheBySessionTimeOut, @@ -25,6 +26,9 @@ define([ buffer, customerData; + url.setBaseUrl(window.BASE_URL); + options.sectionLoadUrl = url.build('customer/section/load'); + //TODO: remove global change, in this case made for initNamespaceStorage $.cookieStorage.setConf({ path: '/', From eb5eb21c7df4da1f98c12ef41a2897bdb4204ecd Mon Sep 17 00:00:00 2001 From: OlgaVasyltsun <olga.vasyltsun@gmail.com> Date: Tue, 4 Jun 2019 11:17:34 +0300 Subject: [PATCH 443/773] MC-17050: ElasticSearch6 Broken w/ Boolean Attribute --- .../FieldType/Resolver/KeywordType.php | 5 ++- .../FieldType/Resolver/KeywordTypeTest.php | 41 ++++++++++++------- app/code/Magento/Elasticsearch/etc/di.xml | 2 +- 3 files changed, 30 insertions(+), 18 deletions(-) diff --git a/app/code/Magento/Elasticsearch/Elasticsearch5/Model/Adapter/FieldMapper/Product/FieldProvider/FieldType/Resolver/KeywordType.php b/app/code/Magento/Elasticsearch/Elasticsearch5/Model/Adapter/FieldMapper/Product/FieldProvider/FieldType/Resolver/KeywordType.php index e522d4ae5e070..7ac6588b87866 100644 --- a/app/code/Magento/Elasticsearch/Elasticsearch5/Model/Adapter/FieldMapper/Product/FieldProvider/FieldType/Resolver/KeywordType.php +++ b/app/code/Magento/Elasticsearch/Elasticsearch5/Model/Adapter/FieldMapper/Product/FieldProvider/FieldType/Resolver/KeywordType.php @@ -37,8 +37,9 @@ public function __construct(ConverterInterface $fieldTypeConverter) */ public function getFieldType(AttributeAdapter $attribute): ?string { - if ($attribute->isComplexType() - || (!$attribute->isSearchable() && !$attribute->isAlwaysIndexable() && $attribute->isFilterable()) + if (($attribute->isComplexType() + || (!$attribute->isSearchable() && !$attribute->isAlwaysIndexable() && $attribute->isFilterable())) + && !$attribute->isBooleanType() ) { return $this->fieldTypeConverter->convert(ConverterInterface::INTERNAL_DATA_TYPE_KEYWORD); } diff --git a/app/code/Magento/Elasticsearch/Test/Unit/Elasticsearch5/Model/Adapter/FieldMapper/Product/FieldProvider/FieldType/Resolver/KeywordTypeTest.php b/app/code/Magento/Elasticsearch/Test/Unit/Elasticsearch5/Model/Adapter/FieldMapper/Product/FieldProvider/FieldType/Resolver/KeywordTypeTest.php index 0e33498a16fba..92d523e6c2346 100644 --- a/app/code/Magento/Elasticsearch/Test/Unit/Elasticsearch5/Model/Adapter/FieldMapper/Product/FieldProvider/FieldType/Resolver/KeywordTypeTest.php +++ b/app/code/Magento/Elasticsearch/Test/Unit/Elasticsearch5/Model/Adapter/FieldMapper/Product/FieldProvider/FieldType/Resolver/KeywordTypeTest.php @@ -53,18 +53,25 @@ protected function setUp() /** * @dataProvider getFieldTypeProvider - * @param $isComplexType - * @param $isSearchable - * @param $isAlwaysIndexable - * @param $isFilterable - * @param $expected + * @param bool $isComplexType + * @param bool $isSearchable + * @param bool $isAlwaysIndexable + * @param bool $isFilterable + * @param bool $isBoolean + * @param string $expected * @return void */ - public function testGetFieldType($isComplexType, $isSearchable, $isAlwaysIndexable, $isFilterable, $expected) - { + public function testGetFieldType( + bool $isComplexType, + bool $isSearchable, + bool $isAlwaysIndexable, + bool $isFilterable, + bool $isBoolean, + string $expected + ): void { $attributeMock = $this->getMockBuilder(AttributeAdapter::class) ->disableOriginalConstructor() - ->setMethods(['isComplexType', 'isSearchable', 'isAlwaysIndexable', 'isFilterable']) + ->setMethods(['isComplexType', 'isSearchable', 'isAlwaysIndexable', 'isFilterable', 'isBooleanType']) ->getMock(); $attributeMock->expects($this->any()) ->method('isComplexType') @@ -78,6 +85,9 @@ public function testGetFieldType($isComplexType, $isSearchable, $isAlwaysIndexab $attributeMock->expects($this->any()) ->method('isFilterable') ->willReturn($isFilterable); + $attributeMock->expects($this->any()) + ->method('isBooleanType') + ->willReturn($isBoolean); $this->fieldTypeConverter->expects($this->any()) ->method('convert') ->willReturn('something'); @@ -94,13 +104,14 @@ public function testGetFieldType($isComplexType, $isSearchable, $isAlwaysIndexab public function getFieldTypeProvider() { return [ - [true, true, true, true, 'something'], - [true, false, false, false, 'something'], - [true, false, false, true, 'something'], - [false, false, false, true, 'something'], - [false, false, false, false, ''], - [false, false, true, false, ''], - [false, true, false, false, ''], + [true, true, true, true, false, 'something'], + [true, false, false, false, false, 'something'], + [true, false, false, true, false, 'something'], + [false, false, false, true, false, 'something'], + [false, false, false, false, false, ''], + [false, false, true, false, false, ''], + [false, true, false, false, false, ''], + [true, true, true, true, true, ''], ]; } } diff --git a/app/code/Magento/Elasticsearch/etc/di.xml b/app/code/Magento/Elasticsearch/etc/di.xml index 4f5c56c91df2b..55df6a5a37f46 100644 --- a/app/code/Magento/Elasticsearch/etc/di.xml +++ b/app/code/Magento/Elasticsearch/etc/di.xml @@ -478,7 +478,7 @@ <argument name="indexTypeConverter" xsi:type="object">Magento\Elasticsearch\Elasticsearch5\Model\Adapter\FieldMapper\Product\FieldProvider\FieldIndex\Converter</argument> <argument name="fieldIndexResolver" xsi:type="object">Magento\Elasticsearch\Elasticsearch5\Model\Adapter\FieldMapper\Product\FieldProvider\FieldIndex\IndexResolver</argument> <argument name="fieldTypeResolver" xsi:type="object">\Magento\Elasticsearch\Elasticsearch5\Model\Adapter\FieldMapper\Product\FieldProvider\FieldType\Resolver\CompositeResolver</argument> - <argument name="fieldNameResolver" xsi:type="object">\Magento\Elasticsearch\Model\Adapter\FieldMapper\Product\FieldProvider\FieldName\ResolverInterface</argument> + <argument name="fieldNameResolver" xsi:type="object">elasticsearch5FieldNameResolver</argument> </arguments> </virtualType> <virtualType name="elasticsearch5DynamicFieldProvider" type="\Magento\Elasticsearch\Model\Adapter\FieldMapper\Product\FieldProvider\DynamicField"> From 53abf958dcfef65f581790af9a827b7c87901ec1 Mon Sep 17 00:00:00 2001 From: p-bystritsky <p-bystritsky@users.noreply.github.com> Date: Tue, 4 Jun 2019 12:17:54 +0300 Subject: [PATCH 444/773] magento/magento2#20579: Apply suggestions from code review Co-Authored-By: David Verholen <david@verholen.com> --- .../Magento/SalesRule/Model/Coupon/UpdateCouponUsages.php | 6 +++--- .../Magento/SalesRule/Model/ResourceModel/Coupon/Usage.php | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/SalesRule/Model/Coupon/UpdateCouponUsages.php b/app/code/Magento/SalesRule/Model/Coupon/UpdateCouponUsages.php index ae1866d8fda48..c4f7652e1a334 100644 --- a/app/code/Magento/SalesRule/Model/Coupon/UpdateCouponUsages.php +++ b/app/code/Magento/SalesRule/Model/Coupon/UpdateCouponUsages.php @@ -63,7 +63,7 @@ public function __construct( * @param bool $increment * @return Order */ - public function execute(Order $subject, bool $increment) + public function execute(Order $subject, bool $increment): Order { if (!$subject || !$subject->getAppliedRuleIds()) { return $subject; @@ -115,7 +115,7 @@ private function updateRuleUsages(bool $increment, int $ruleId, int $customerId) * @param int $ruleId * @param int $customerId */ - private function updateCustomerRuleUsages(bool $increment, int $ruleId, int $customerId) + private function updateCustomerRuleUsages(bool $increment, int $ruleId, int $customerId): void { /** @var \Magento\SalesRule\Model\Rule\Customer $ruleCustomer */ $ruleCustomer = $this->ruleCustomerFactory->create(); @@ -137,7 +137,7 @@ private function updateCustomerRuleUsages(bool $increment, int $ruleId, int $cus * @param bool $increment * @param int $customerId */ - private function updateCouponUsages(Order $subject, bool $increment, int $customerId) + private function updateCouponUsages(Order $subject, bool $increment, int $customerId): void { $this->coupon->load($subject->getCouponCode(), 'code'); if ($this->coupon->getId()) { diff --git a/app/code/Magento/SalesRule/Model/ResourceModel/Coupon/Usage.php b/app/code/Magento/SalesRule/Model/ResourceModel/Coupon/Usage.php index 8680a91a9acc4..39a2f8855e246 100644 --- a/app/code/Magento/SalesRule/Model/ResourceModel/Coupon/Usage.php +++ b/app/code/Magento/SalesRule/Model/ResourceModel/Coupon/Usage.php @@ -30,7 +30,7 @@ protected function _construct() * @param bool $increment * @return void */ - public function updateCustomerCouponTimesUsed($customerId, $couponId, $increment = true) + public function updateCustomerCouponTimesUsed($customerId, $couponId, $increment = true): void { $connection = $this->getConnection(); $select = $connection->select(); From 6621abc9a1474b54f23ad5af7489fcb9295dfcf6 Mon Sep 17 00:00:00 2001 From: Soumya Unnikrishnan <sunnikri@adobe.com> Date: Wed, 5 Jun 2019 15:53:04 -0500 Subject: [PATCH 445/773] MC-4770: Convert CreateOrderFromEditCustomerPageTest to MFTF fixed as per review comments --- .../Sales/Test/Mftf/Data/OrderData.xml | 7 +++++- .../AdminCreateOrderShoppingCartSection.xml | 2 +- .../AdminCreateOrderWishListSection.xml | 2 +- .../AdminOrderFormItemsOrderedSection.xml | 1 + .../CreateOrderFromEditCustomerPageTest.xml | 22 ++++++++++--------- 5 files changed, 21 insertions(+), 13 deletions(-) diff --git a/app/code/Magento/Sales/Test/Mftf/Data/OrderData.xml b/app/code/Magento/Sales/Test/Mftf/Data/OrderData.xml index eb5600f112ea1..39ce03692e0bf 100644 --- a/app/code/Magento/Sales/Test/Mftf/Data/OrderData.xml +++ b/app/code/Magento/Sales/Test/Mftf/Data/OrderData.xml @@ -23,7 +23,11 @@ <data key="from">200</data> <data key="to">400</data> </entity> - + <entity name="AdminOrderMultipleProducts" type="order"> + <data key="subtotal">60.00</data> + <data key="shipping">0.00</data> + <data key="grandTotal">60.00</data> + </entity> <entity name="OrderStatus" type="status"> <data key="canceled">Canceled</data> <data key="closed">Closed</data> @@ -34,5 +38,6 @@ <data key="pending">Pending</data> <data key="pendingPayment">Pending Payment</data> <data key="processing">Processing</data> + <data key="ordered">Ordered</data> </entity> </entities> diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminCreateOrderShoppingCartSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminCreateOrderShoppingCartSection.xml index 76826f9571f34..fdd80a1813aa6 100644 --- a/app/code/Magento/Sales/Test/Mftf/Section/AdminCreateOrderShoppingCartSection.xml +++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminCreateOrderShoppingCartSection.xml @@ -12,4 +12,4 @@ <element name="shoppingCartBlock" type="text" selector="#sidebar_data_cart"/> <element name="addToOrderCheckBox" type="checkbox" selector="//div[@id='order-sidebar_cart']//tr[td[.='{{productName}}']]//input[contains(@name,'sidebar[add_cart_item]')]" parameterized="true" timeout="30"/> </section> -</sections> \ No newline at end of file +</sections> diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminCreateOrderWishListSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminCreateOrderWishListSection.xml index 86145a7221ad2..d6c0c994dda36 100644 --- a/app/code/Magento/Sales/Test/Mftf/Section/AdminCreateOrderWishListSection.xml +++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminCreateOrderWishListSection.xml @@ -13,4 +13,4 @@ <element name="addProductToOrderCheckBox" type="checkbox" selector="//div[@id='order-sidebar_wishlist']//tr[td[.='{{productName}}']]//input[contains(@name,'sidebar[add_wishlist_item]')]" parameterized="true" timeout="30"/> <element name="addConfigProductToOrder" type="text" selector="//div[@id='order-sidebar_wishlist']//tr[td[contains(.,'{{configProductName}}')]]//a[contains(@class, 'icon-configure')]" parameterized="true" timeout="30"/> </section> -</sections> \ No newline at end of file +</sections> diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormItemsOrderedSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormItemsOrderedSection.xml index 52f311cef7219..c28ec58cebbed 100644 --- a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormItemsOrderedSection.xml +++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormItemsOrderedSection.xml @@ -19,3 +19,4 @@ <element name="moveProduct" type="select" selector="//td[contains(.,'{{productName}}')]/../..//td//select" parameterized="true"/> </section> </sections> + diff --git a/app/code/Magento/Sales/Test/Mftf/Test/CreateOrderFromEditCustomerPageTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/CreateOrderFromEditCustomerPageTest.xml index f3de31b1db17f..647570038070f 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/CreateOrderFromEditCustomerPageTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/CreateOrderFromEditCustomerPageTest.xml @@ -191,14 +191,16 @@ <click selector="{{AdminEditCustomerOrdersSection.orderIdInGrid('$orderId')}}" stepKey="selectOnOrderID"/> <!-- Assert ordered product in customer order section--> - <waitForPageLoad stepKey="waitForOrderInformationTolLoad"/> - <see selector="{{AdminOrderItemsOrderedSection.productNameColumn}}" userInput="$$createConfigProduct.name$$" stepKey="seeConfigurableProductInGrid"/> - <see selector="{{AdminOrderItemsOrderedSection.productNameColumn}}" userInput="$$simpleProduct.name$$" stepKey="seeFirstProductInGrid"/> - <see selector="{{AdminOrderItemsOrderedSection.productNameColumn}}" userInput="$$simpleProduct1.name$$" stepKey="seeSecondProductInGrid"/> - <see selector="{{AdminOrderItemsOrderedSection.statusColumn}}" userInput="Ordered" stepKey="seeProductStatus"/> - <see selector="{{AdminOrderItemsOrderedSection.subtotalColumn}}" userInput="$30.00" stepKey="seeConfigurableProductSubtotal"/> - <see selector="{{AdminOrderItemsOrderedSection.subtotalColumn}}" userInput="$10.00" stepKey="seeFirstProductSubtotal"/> - <see selector="{{AdminOrderItemsOrderedSection.subtotalColumn}}" userInput="$20.00" stepKey="seeSecondProductSubtotal"/> - <see selector="{{AdminOrderTotalSection.grandTotal}}" userInput="$60.00" stepKey="seeOrderGrandTotal"/> + <waitForPageLoad stepKey="waitForOrderInformationToLoad"/> + <see selector="{{AdminOrderItemsOrderedSection.productNameColumn}}" userInput="$createConfigProduct.name$" stepKey="seeConfigurableProductInGrid"/> + <see selector="{{AdminOrderItemsOrderedSection.productNameColumn}}" userInput="$simpleProduct.name$" stepKey="seeFirstProductInGrid"/> + <see selector="{{AdminOrderItemsOrderedSection.productNameColumn}}" userInput="$simpleProduct1.name$" stepKey="seeSecondProductInGrid"/> + <see selector="{{AdminOrderItemsOrderedSection.statusColumn}}" userInput="{{OrderStatus.ordered}}" stepKey="seeProductStatus"/> + <see selector="{{AdminOrderItemsOrderedSection.subtotalColumn}}" userInput="$createConfigChildProduct1.price$" stepKey="seeConfigurableProductSubtotal"/> + <see selector="{{AdminOrderItemsOrderedSection.subtotalColumn}}" userInput="$simpleProduct.price$" stepKey="seeFirstProductSubtotal"/> + <see selector="{{AdminOrderItemsOrderedSection.subtotalColumn}}" userInput="$simpleProduct1.price$" stepKey="seeSecondProductSubtotal"/> + <see selector="{{AdminOrderTotalSection.subTotal}}" userInput="{{AdminOrderMultipleProducts.subtotal}}" stepKey="checkSubtotal" /> + <see selector="{{AdminOrderTotalSection.shippingAndHandling}}" userInput="{{AdminOrderMultipleProducts.shipping}}" stepKey="checkShippingAndHandling" /> + <see selector="{{AdminOrderTotalSection.grandTotal}}" userInput="{{AdminOrderMultipleProducts.grandTotal}}" stepKey="checkGrandTotal" /> </test> -</tests> \ No newline at end of file +</tests> From 298cc101dfb18f47abe8e1a33faf0b5a3e0704b7 Mon Sep 17 00:00:00 2001 From: Dmytro Horytskyi <horytsky@adobe.com> Date: Wed, 5 Jun 2019 17:14:20 -0500 Subject: [PATCH 446/773] MAGETWO-98825: [Magento Cloud] When creating a new category, the Category Permissions are set to Deny by default --- .../Model/Category/StoreCategories.php | 59 +++++++++++++++++++ app/code/Magento/Config/Model/Config.php | 6 +- 2 files changed, 63 insertions(+), 2 deletions(-) create mode 100644 app/code/Magento/Catalog/Model/Category/StoreCategories.php diff --git a/app/code/Magento/Catalog/Model/Category/StoreCategories.php b/app/code/Magento/Catalog/Model/Category/StoreCategories.php new file mode 100644 index 0000000000000..ef4444431d353 --- /dev/null +++ b/app/code/Magento/Catalog/Model/Category/StoreCategories.php @@ -0,0 +1,59 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Catalog\Model\Category; + +use Magento\Catalog\Api\CategoryRepositoryInterface; +use Magento\Catalog\Model\Category; +use Magento\Store\Api\GroupRepositoryInterface; + +/** + * Fetcher for associated with store group categories. + */ +class StoreCategories +{ + /** + * @var CategoryRepositoryInterface + */ + private $categoryRepository; + + /** + * @var GroupRepositoryInterface + */ + private $groupRepository; + + /** + * @param CategoryRepositoryInterface $categoryRepository + * @param GroupRepositoryInterface $groupRepository + */ + public function __construct( + CategoryRepositoryInterface $categoryRepository, + GroupRepositoryInterface $groupRepository + ) { + $this->categoryRepository = $categoryRepository; + $this->groupRepository = $groupRepository; + } + + /** + * Get all category ids for store. + * + * @param int|null $storeGroupId + * @return array + * @throws \Magento\Framework\Exception\NoSuchEntityException + */ + public function getCategoryIds(int $storeGroupId = null): array + { + $rootCategoryId = $storeGroupId + ? $this->groupRepository->get($storeGroupId)->getRootCategoryId() + : Category::TREE_ROOT_ID; + /** @var Category $rootCategory */ + $rootCategory = $this->categoryRepository->get($rootCategoryId); + $categoriesIds = $rootCategory->getAllChildren(true); + + return (array) $categoriesIds; + } +} diff --git a/app/code/Magento/Config/Model/Config.php b/app/code/Magento/Config/Model/Config.php index b5dbf97f7953d..3ae70df4bdb90 100644 --- a/app/code/Magento/Config/Model/Config.php +++ b/app/code/Magento/Config/Model/Config.php @@ -546,6 +546,8 @@ public function setDataByPath($path, $value) } $section = array_shift($pathParts); + $this->setData('section', $section); + $data = [ 'fields' => [ array_pop($pathParts) => ['value' => $value], @@ -558,8 +560,8 @@ public function setDataByPath($path, $value) ], ]; } - $data['section'] = $section; - $this->addData($data); + $groups = array_replace_recursive((array) $this->getData('groups'), $data['groups']); + $this->setData('groups', $groups); } /** From 6a694a9bab15ab20531ffb2f70a744127611a1e3 Mon Sep 17 00:00:00 2001 From: Aliaksei Yakimovich2 <aliaksei_yakimovich2@epam.com> Date: Thu, 6 Jun 2019 17:33:57 +0300 Subject: [PATCH 447/773] MC-17218: php bin/magento catalog:image:resize error if image is missing - Fixed an issue with resize command; --- .../Console/Command/ImagesResizeCommand.php | 39 +++++++++++++++---- .../MediaStorage/Service/ImageResize.php | 25 ++++++++---- 2 files changed, 48 insertions(+), 16 deletions(-) diff --git a/app/code/Magento/MediaStorage/Console/Command/ImagesResizeCommand.php b/app/code/Magento/MediaStorage/Console/Command/ImagesResizeCommand.php index a4b78287df012..38d333ed649fb 100644 --- a/app/code/Magento/MediaStorage/Console/Command/ImagesResizeCommand.php +++ b/app/code/Magento/MediaStorage/Console/Command/ImagesResizeCommand.php @@ -15,6 +15,9 @@ use Symfony\Component\Console\Helper\ProgressBar; use Magento\Framework\ObjectManagerInterface; +/** + * Class for catalog image resizing via CLI + */ class ImagesResizeCommand extends \Symfony\Component\Console\Command\Command { /** @@ -49,7 +52,7 @@ public function __construct( } /** - * {@inheritdoc} + * @inheritdoc */ protected function configure() { @@ -58,19 +61,23 @@ protected function configure() } /** - * {@inheritdoc} + * @inheritdoc */ protected function execute(InputInterface $input, OutputInterface $output) { try { + $errors = []; $this->appState->setAreaCode(Area::AREA_GLOBAL); $generator = $this->resize->resizeFromThemes(); /** @var ProgressBar $progress */ - $progress = $this->objectManager->create(ProgressBar::class, [ - 'output' => $output, - 'max' => $generator->current() - ]); + $progress = $this->objectManager->create( + ProgressBar::class, + [ + 'output' => $output, + 'max' => $generator->current() + ] + ); $progress->setFormat( "%current%/%max% [%bar%] %percent:3s%% %elapsed% %memory:6s% \t| <info>%message%</info>" ); @@ -79,8 +86,17 @@ protected function execute(InputInterface $input, OutputInterface $output) $progress->setOverwrite(false); } + // phpcs:ignore Generic.CodeAnalysis.ForLoopWithTestFunctionCall for (; $generator->valid(); $generator->next()) { - $progress->setMessage($generator->key()); + $resizeInfo = $generator->key(); + $error = $resizeInfo['error']; + $filename = $resizeInfo['filename']; + + if ($error !== '') { + $errors[$filename] = $error; + } + + $progress->setMessage($filename); $progress->advance(); } } catch (\Exception $e) { @@ -90,6 +106,13 @@ protected function execute(InputInterface $input, OutputInterface $output) } $output->write(PHP_EOL); - $output->writeln("<info>Product images resized successfully</info>"); + if (count($errors)) { + $output->writeln("<info>Product images resized with errors:</info>"); + foreach ($errors as $error) { + $output->writeln("<error>{$error}</error>"); + } + } else { + $output->writeln("<info>Product images resized successfully</info>"); + } } } diff --git a/app/code/Magento/MediaStorage/Service/ImageResize.php b/app/code/Magento/MediaStorage/Service/ImageResize.php index aae90512b3d95..5ac0ac688619e 100644 --- a/app/code/Magento/MediaStorage/Service/ImageResize.php +++ b/app/code/Magento/MediaStorage/Service/ImageResize.php @@ -161,14 +161,21 @@ public function resizeFromThemes(array $themes = null): \Generator $viewImages = $this->getViewImages($themes ?? $this->getThemesInUse()); foreach ($productImages as $image) { + $error = ''; $originalImageName = $image['filepath']; $originalImagePath = $this->mediaDirectory->getAbsolutePath( $this->imageConfig->getMediaPath($originalImageName) ); - foreach ($viewImages as $viewImage) { - $this->resize($viewImage, $originalImagePath, $originalImageName); + + if ($this->mediaDirectory->isFile($originalImagePath)) { + foreach ($viewImages as $viewImage) { + $this->resize($viewImage, $originalImagePath, $originalImageName); + } + } else { + $error = __('Cannot resize image "%1" - original image not found', $originalImagePath); } - yield $originalImageName => $count; + + yield ['filename' => $originalImageName, 'error' => $error] => $count; } } @@ -202,10 +209,12 @@ private function getViewImages(array $themes): array $viewImages = []; /** @var \Magento\Theme\Model\Theme $theme */ foreach ($themes as $theme) { - $config = $this->viewConfig->getViewConfig([ - 'area' => Area::AREA_FRONTEND, - 'themeModel' => $theme, - ]); + $config = $this->viewConfig->getViewConfig( + [ + 'area' => Area::AREA_FRONTEND, + 'themeModel' => $theme, + ] + ); $images = $config->getMediaEntities('Magento_Catalog', ImageHelper::MEDIA_TYPE_CONFIG_NODE); foreach ($images as $imageId => $imageData) { $uniqIndex = $this->getUniqueImageIndex($imageData); @@ -226,7 +235,7 @@ private function getUniqueImageIndex(array $imageData): string { ksort($imageData); unset($imageData['type']); - return md5(json_encode($imageData)); + return hash('sha256', json_encode($imageData)); } /** From f5f8f692531e1ee085e93dc9cc92a64ea6162c2c Mon Sep 17 00:00:00 2001 From: Dmytro Horytskyi <horytsky@adobe.com> Date: Thu, 6 Jun 2019 11:42:38 -0500 Subject: [PATCH 448/773] MAGETWO-98825: [Magento Cloud] When creating a new category, the Category Permissions are set to Deny by default --- app/code/Magento/Catalog/Model/Category/StoreCategories.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Model/Category/StoreCategories.php b/app/code/Magento/Catalog/Model/Category/StoreCategories.php index ef4444431d353..a97f58e26d021 100644 --- a/app/code/Magento/Catalog/Model/Category/StoreCategories.php +++ b/app/code/Magento/Catalog/Model/Category/StoreCategories.php @@ -45,7 +45,7 @@ public function __construct( * @return array * @throws \Magento\Framework\Exception\NoSuchEntityException */ - public function getCategoryIds(int $storeGroupId = null): array + public function getCategoryIds(?int $storeGroupId = null): array { $rootCategoryId = $storeGroupId ? $this->groupRepository->get($storeGroupId)->getRootCategoryId() From f55d2ee1252236f1739cc6dcff13ae4b62fd6ab0 Mon Sep 17 00:00:00 2001 From: Soumya Unnikrishnan <sunnikri@adobe.com> Date: Thu, 6 Jun 2019 12:59:31 -0500 Subject: [PATCH 449/773] MC-4770: Convert CreateOrderFromEditCustomerPageTest to MFTF --- .../Test/Mftf/Test/CreateOrderFromEditCustomerPageTest.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/code/Magento/Sales/Test/Mftf/Test/CreateOrderFromEditCustomerPageTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/CreateOrderFromEditCustomerPageTest.xml index 647570038070f..1801e19f1fe60 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/CreateOrderFromEditCustomerPageTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/CreateOrderFromEditCustomerPageTest.xml @@ -17,6 +17,7 @@ <severity value="CRITICAL"/> <testCaseId value="MC-16161"/> <group value="mtf_migrated"/> + <group value="banana"/> </annotations> <before> @@ -120,6 +121,7 @@ <selectOption selector="{{AdminOrderFormItemsOrderedSection.moveProduct($$simpleProduct.name$$)}}" userInput="Move to Wish List" stepKey="moveProductToWishList"/> <selectOption selector="{{AdminOrderFormItemsOrderedSection.moveProduct($$createConfigProduct.name$$)}}" userInput="Move to Wish List" stepKey="moveConfigurableProductToWishList"/> <click selector="{{OrdersGridSection.update}}" stepKey="clickOnUpdateItemsAndQuantity"/> + <waitForPageLoad stepKey="waitForAdminCreateOrderWishListSectionPageLoad"/> <!-- Assert products in Wish List section --> <see selector="{{AdminCreateOrderWishListSection.wishListBlock}}" userInput="$$simpleProduct.name$$" stepKey="seeSimpleProductInWishList"/> From 2b81e8c212961248fc8ca9ec0770e37e007e9a47 Mon Sep 17 00:00:00 2001 From: Soumya Unnikrishnan <sunnikri@adobe.com> Date: Thu, 6 Jun 2019 16:10:09 -0500 Subject: [PATCH 450/773] MC-4770: Convert CreateOrderFromEditCustomerPageTest to MFTF fixing jenkins builds --- .../Test/Mftf/Section/AdminOrderFormItemsOrderedSection.xml | 1 - .../Test/Mftf/Test/CreateOrderFromEditCustomerPageTest.xml | 4 ++++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormItemsOrderedSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormItemsOrderedSection.xml index 1dd5ffd67d218..e3417e7c662b9 100644 --- a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormItemsOrderedSection.xml +++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormItemsOrderedSection.xml @@ -20,4 +20,3 @@ <element name="moveProduct" type="select" selector="//td[contains(.,'{{productName}}')]/../..//td//select" parameterized="true"/> </section> </sections> - diff --git a/app/code/Magento/Sales/Test/Mftf/Test/CreateOrderFromEditCustomerPageTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/CreateOrderFromEditCustomerPageTest.xml index 1801e19f1fe60..7ead092a1aea9 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/CreateOrderFromEditCustomerPageTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/CreateOrderFromEditCustomerPageTest.xml @@ -135,6 +135,7 @@ <selectOption selector="{{AdminOrderFormConfigureProductSection.optionSelect($$createConfigProductAttribute.default_frontend_label$$)}}" userInput="$$getConfigAttributeOption1.label$$" stepKey="selectConfigurableOption"/> <click selector="{{AdminOrderFormConfigureProductSection.ok}}" stepKey="clickOkButton"/> <click selector="{{AdminCustomerCreateNewOrderSection.updateChangesBtn}}" stepKey="clickOnUpdateButton"/> + <waitForPageLoad stepKey="waitForAdminOrderItemsOrderedSectionPageLoad1"/> <!-- Assert Products in Order item section --> <see selector="{{AdminOrderItemsOrderedSection.productName}}" userInput="$$simpleProduct.name$$" stepKey="seeSimpleProductInOrderItemGrid"/> @@ -144,6 +145,7 @@ <selectOption selector="{{AdminOrderFormItemsOrderedSection.moveProduct($$simpleProduct.name$$)}}" userInput="Move to Shopping Cart" stepKey="moveFirstSimpleProductToShoppingCart"/> <selectOption selector="{{AdminOrderFormItemsOrderedSection.moveProduct($$simpleProduct1.name$$)}}" userInput="Move to Shopping Cart" stepKey="moveSecondSimpleProductToShoppingCart"/> <click selector="{{OrdersGridSection.update}}" stepKey="clickOnUpdateItems"/> + <waitForPageLoad stepKey="waitForAdminCreateOrderShoppingCartSectionPageLoad"/> <!-- Assert products in Shopping cart section --> <see selector="{{AdminCreateOrderShoppingCartSection.shoppingCartBlock}}" userInput="$$simpleProduct.name$$" stepKey="seeProductInShoppingCart"/> @@ -154,6 +156,7 @@ <click selector="{{AdminCreateOrderShoppingCartSection.addToOrderCheckBox($$simpleProduct.name$$)}}" stepKey="selectFirstProduct"/> <click selector="{{AdminCreateOrderShoppingCartSection.addToOrderCheckBox($$simpleProduct1.name$$)}}" stepKey="selectSecondProduct"/> <click selector="{{AdminCustomerCreateNewOrderSection.updateChangesBtn}}" stepKey="clickOnUpdateButton1"/> + <waitForPageLoad stepKey="waitForAdminCreateOrderShoppingCartSectionPageLoad1"/> <!-- After move, assert products are not present in Shopping cart section --> <dontSee selector="{{AdminCreateOrderShoppingCartSection.shoppingCartBlock}}" userInput="$$simpleProduct.name$$" stepKey="donSeeProductInShoppingCart"/> @@ -177,6 +180,7 @@ <!-- Submit order --> <click selector="{{AdminOrderFormActionSection.SubmitOrder}}" stepKey="submitOrder"/> + <waitForPageLoad stepKey="waitForAdminOrderFormLoad"/> <!-- Verify order information --> <actionGroup ref="verifyCreatedOrderInformation" stepKey="verifyCreatedOrderInformation"/> From 8f41977f66114c75ef84f5364ec36b55dbd5c094 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Fri, 7 Jun 2019 13:05:07 +0300 Subject: [PATCH 451/773] magento/magento2#20579: Plugin order fix. --- app/code/Magento/SalesRule/etc/di.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/SalesRule/etc/di.xml b/app/code/Magento/SalesRule/etc/di.xml index 94ca778cc7c31..863467ed3d318 100644 --- a/app/code/Magento/SalesRule/etc/di.xml +++ b/app/code/Magento/SalesRule/etc/di.xml @@ -183,7 +183,7 @@ <plugin name="coupon_label_plugin" type="Magento\SalesRule\Plugin\CartTotalRepository" /> </type> <type name="Magento\Sales\Model\Order"> - <plugin name="coupon_uses_increment_plugin" type="Magento\SalesRule\Plugin\CouponUsagesIncrement" /> + <plugin name="coupon_uses_increment_plugin" type="Magento\SalesRule\Plugin\CouponUsagesIncrement" sortOrder="20"/> <plugin name="coupon_uses_decrement_plugin" type="Magento\SalesRule\Plugin\CouponUsagesDecrement" /> </type> </config> From 77819af7d87ed54142b5b10927c1e7198b2e0e21 Mon Sep 17 00:00:00 2001 From: Dmytro Horytskyi <horytsky@adobe.com> Date: Fri, 7 Jun 2019 11:55:35 -0500 Subject: [PATCH 452/773] MAGETWO-98825: [Magento Cloud] When creating a new category, the Category Permissions are set to Deny by default --- .../Catalog/Model/Category/StoreCategories.php | 11 ++++++++--- app/code/Magento/Config/Model/Config.php | 14 +++++++------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Category/StoreCategories.php b/app/code/Magento/Catalog/Model/Category/StoreCategories.php index a97f58e26d021..0d7afcd4a5000 100644 --- a/app/code/Magento/Catalog/Model/Category/StoreCategories.php +++ b/app/code/Magento/Catalog/Model/Category/StoreCategories.php @@ -42,7 +42,7 @@ public function __construct( * Get all category ids for store. * * @param int|null $storeGroupId - * @return array + * @return int[] * @throws \Magento\Framework\Exception\NoSuchEntityException */ public function getCategoryIds(?int $storeGroupId = null): array @@ -52,8 +52,13 @@ public function getCategoryIds(?int $storeGroupId = null): array : Category::TREE_ROOT_ID; /** @var Category $rootCategory */ $rootCategory = $this->categoryRepository->get($rootCategoryId); - $categoriesIds = $rootCategory->getAllChildren(true); + $categoriesIds = array_map( + function ($value) { + return (int) $value; + }, + (array) $rootCategory->getAllChildren(true) + ); - return (array) $categoriesIds; + return $categoriesIds; } } diff --git a/app/code/Magento/Config/Model/Config.php b/app/code/Magento/Config/Model/Config.php index 3ae70df4bdb90..356c6ca17da18 100644 --- a/app/code/Magento/Config/Model/Config.php +++ b/app/code/Magento/Config/Model/Config.php @@ -287,8 +287,8 @@ private function getField(string $sectionId, string $groupId, string $fieldId): * * @param Field $field * @param string $fieldId Need for support of clone_field feature - * @param array &$oldConfig Need for compatibility with _processGroup() - * @param array &$extraOldGroups Need for compatibility with _processGroup() + * @param array $oldConfig Need for compatibility with _processGroup() + * @param array $extraOldGroups Need for compatibility with _processGroup() * @return string */ private function getFieldPath(Field $field, string $fieldId, array &$oldConfig, array &$extraOldGroups): string @@ -337,8 +337,8 @@ private function isValueChanged(array $oldConfig, string $path, array $fieldData * @param string $sectionId * @param string $groupId * @param array $groupData - * @param array &$oldConfig - * @param array &$extraOldGroups + * @param array $oldConfig + * @param array $extraOldGroups * @return array */ private function getChangedPaths( @@ -384,8 +384,8 @@ private function getChangedPaths( * @param array $groupData * @param array $groups * @param string $sectionPath - * @param array &$extraOldGroups - * @param array &$oldConfig + * @param array $extraOldGroups + * @param array $oldConfig * @param \Magento\Framework\DB\Transaction $saveTransaction * @param \Magento\Framework\DB\Transaction $deleteTransaction * @return void @@ -681,7 +681,7 @@ protected function _checkSingleStoreMode( * Get config data value * * @param string $path - * @param null|bool &$inherit + * @param null|bool $inherit * @param null|array $configData * @return \Magento\Framework\Simplexml\Element */ From e3aee04c988665a1fe124e3250396ae40af8760b Mon Sep 17 00:00:00 2001 From: Max Lesechko <mlesechko@magento.com> Date: Fri, 7 Jun 2019 13:24:34 -0500 Subject: [PATCH 453/773] MC-17329: Update Changelog based on delivered scope --- CHANGELOG.md | 612 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 612 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0999bee6ea415..09e4886626ecd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,619 @@ +2.3.2 +============= +* GitHub issues: + * [#19596](https://github.com/magento/magento2/issues/19596) -- Images in XML sitemap are always linked to base store in multistore on Schedule (fixed in [magento/magento2#19598](https://github.com/magento/magento2/pull/19598)) + * [#20010](https://github.com/magento/magento2/issues/20010) -- Wrong price amount in opengraph (fixed in [magento/magento2#20011](https://github.com/magento/magento2/pull/20011)) + * [#20091](https://github.com/magento/magento2/issues/20091) -- Error when uploading a Transactional Emails logo (fixed in [magento/magento2#20092](https://github.com/magento/magento2/pull/20092)) + * [#20172](https://github.com/magento/magento2/issues/20172) -- On customer login page input field are short width on tablet view (fixed in [magento/magento2#20173](https://github.com/magento/magento2/pull/20173)) + * [#20380](https://github.com/magento/magento2/issues/20380) -- Get Shipping Method as object from order instance gives undefined index. (fixed in [magento/magento2#20381](https://github.com/magento/magento2/pull/20381)) + * [#20376](https://github.com/magento/magento2/issues/20376) -- Image gets uploaded if field is disable in Category (fixed in [magento/magento2#20461](https://github.com/magento/magento2/pull/20461)) + * [#20555](https://github.com/magento/magento2/issues/20555) -- Meta Keywords/Meta Description are input field in product form while they are defined as textarea (fixed in [magento/magento2#20556](https://github.com/magento/magento2/pull/20556)) + * [#19630](https://github.com/magento/magento2/issues/19630) -- Checkbox alignment issue backend. (fixed in [magento/magento2#19631](https://github.com/magento/magento2/pull/19631)) + * [#19891](https://github.com/magento/magento2/issues/19891) -- product_type attribute contains incorrect value in mass import export csv after creating custom type_id attribute. actual type_id value in database gets change with newly created attribute type_id. (fixed in [magento/magento2#20115](https://github.com/magento/magento2/pull/20115)) + * [#21021](https://github.com/magento/magento2/issues/21021) -- products in category checkbox not align properly (fixed in [magento/magento2#21022](https://github.com/magento/magento2/pull/21022)) + * [#21089](https://github.com/magento/magento2/issues/21089) -- No accessible label for vault-saved credit card type (fixed in [magento/magento2#21090](https://github.com/magento/magento2/pull/21090)) + * [#263](https://github.com/magento/magento2/issues/263) -- Where Mage_Core_Model_Config::applyClassRewrites($className) method is (fixed in [magento/graphql-ce#347](https://github.com/magento/graphql-ce/pull/347)) + * [#20163](https://github.com/magento/magento2/issues/20163) -- On iPhone5 device newsletter subscription input box not contain complete text (placeholder) (fixed in [magento/magento2#20165](https://github.com/magento/magento2/pull/20165)) + * [#20299](https://github.com/magento/magento2/issues/20299) -- Order item details label not aligned in mobile view (fixed in [magento/magento2#20466](https://github.com/magento/magento2/pull/20466)) + * [#11358](https://github.com/magento/magento2/issues/11358) -- Full Tax Summary display wrong numbers. (fixed in [magento/magento2#20682](https://github.com/magento/magento2/pull/20682)) + * [#19701](https://github.com/magento/magento2/issues/19701) -- Magento 2.3 Shopping Cart Taxes Missing Calc Line (fixed in [magento/magento2#20682](https://github.com/magento/magento2/pull/20682)) + * [#17861](https://github.com/magento/magento2/issues/17861) -- Customer Name Prefix shows white space when extra separator is addes. (fixed in [magento/magento2#20896](https://github.com/magento/magento2/pull/20896)) + * [#20888](https://github.com/magento/magento2/issues/20888) -- Entered data missing when entering the wrong date for from, to in cart rule (fixed in [magento/magento2#20895](https://github.com/magento/magento2/pull/20895)) + * [#17564](https://github.com/magento/magento2/issues/17564) -- Magento 2 inline edit date issues in admin grid with Ui Component (fixed in [magento/magento2#20902](https://github.com/magento/magento2/pull/20902)) + * [#18698](https://github.com/magento/magento2/issues/18698) -- Magento triggers and sends some of order emails exactly one month later,while the order email was not enabled then (fixed in [magento/magento2#20953](https://github.com/magento/magento2/pull/20953)) + * [#20919](https://github.com/magento/magento2/issues/20919) -- Email label and email field not aligned from left for reorder of guest user (fixed in [magento/magento2#21009](https://github.com/magento/magento2/pull/21009)) + * [#21070](https://github.com/magento/magento2/issues/21070) -- Luma theme my account Order Information status tabs break in tablet view (fixed in [magento/magento2#21071](https://github.com/magento/magento2/pull/21071)) + * [#21101](https://github.com/magento/magento2/issues/21101) -- Unable to open the product from sidebar's Compare Products block (fixed in [magento/magento2#21102](https://github.com/magento/magento2/pull/21102)) + * [#6162](https://github.com/magento/magento2/issues/6162) -- Can't set customer group when creating a new order in the admin. (fixed in [magento/magento2#21145](https://github.com/magento/magento2/pull/21145)) + * [#7974](https://github.com/magento/magento2/issues/7974) -- Can't change customer group when placing an admin order, even after MAGETWO-57077 applied (fixed in [magento/magento2#21145](https://github.com/magento/magento2/pull/21145)) + * [#21144](https://github.com/magento/magento2/issues/21144) -- Can't change customer group when placing an admin order (fixed in [magento/magento2#21145](https://github.com/magento/magento2/pull/21145)) + * [#18056](https://github.com/magento/magento2/issues/18056) -- CacheInvalidate : stop at first server not responding (fixed in [magento/magento2#18852](https://github.com/magento/magento2/pull/18852)) + * [#19561](https://github.com/magento/magento2/issues/19561) -- Custom option price calculation is wrong with multi currency when option price type is percentage. (fixed in [magento/magento2#19608](https://github.com/magento/magento2/pull/19608)) + * [#18944](https://github.com/magento/magento2/issues/18944) -- Unable to open URL for downloadable product in 2.2.6 (fixed in [magento/magento2#19996](https://github.com/magento/magento2/pull/19996)) + * [#18347](https://github.com/magento/magento2/issues/18347) -- Element 'css', attribute 'as': The attribute 'as' is not allowed. (CSS preloading) (fixed in [magento/magento2#20495](https://github.com/magento/magento2/pull/20495)) + * [#19328](https://github.com/magento/magento2/issues/19328) -- Success Message Icon vertically misaligned in admin panel (fixed in [magento/magento2#21069](https://github.com/magento/magento2/pull/21069)) + * [#19274](https://github.com/magento/magento2/issues/19274) -- Why is SessionManager used instead of its Interface? (fixed in [magento/magento2#19359](https://github.com/magento/magento2/pull/19359)) + * [#19166](https://github.com/magento/magento2/issues/19166) -- Customer related values are NULL for guests converted to customers after checkout. (fixed in [magento/magento2#19191](https://github.com/magento/magento2/pull/19191)) + * [#19485](https://github.com/magento/magento2/issues/19485) -- DHL Shipping Quotes fail for Domestic Shipments when Content Mode is "Non Documents" (fixed in [magento/magento2#19487](https://github.com/magento/magento2/pull/19487)) + * [#20838](https://github.com/magento/magento2/issues/20838) -- Luma theme shipping tool tip icon cut from leftside (fixed in [magento/magento2#20839](https://github.com/magento/magento2/pull/20839)) + * [#21196](https://github.com/magento/magento2/issues/21196) -- [UI] The dropdown state doesn't change if the dropdown is expanded or not (fixed in [magento/magento2#21197](https://github.com/magento/magento2/pull/21197)) + * [#5021](https://github.com/magento/magento2/issues/5021) -- "Please specify a shipping method" Exception (fixed in [magento/magento2#19505](https://github.com/magento/magento2/pull/19505)) + * [#21177](https://github.com/magento/magento2/issues/21177) -- Cart Page cross sell product Add to cart button overlapping (fixed in [magento/magento2#21178](https://github.com/magento/magento2/pull/21178)) + * [#20969](https://github.com/magento/magento2/issues/20969) -- Poor performance for some layered navigation queries (fixed in [magento/magento2#20971](https://github.com/magento/magento2/pull/20971)) + * [#14882](https://github.com/magento/magento2/issues/14882) -- product_types.xml doesn't allow numbers in modelInstance (fixed in [magento/magento2#20617](https://github.com/magento/magento2/pull/20617)) + * [#21271](https://github.com/magento/magento2/issues/21271) -- Address book display horizontal scroll in responsive view (fixed in [magento/magento2#21272](https://github.com/magento/magento2/pull/21272)) + * [#292](https://github.com/magento/magento2/issues/292) -- Refactor Mage_Rating_Model_Resource_Rating_Collection (fixed in [magento/graphql-ce#327](https://github.com/magento/graphql-ce/pull/327)) + * [#239](https://github.com/magento/magento2/issues/239) -- Feature Request: Record User Agent In Admin Grid (fixed in [magento/graphql-ce#364](https://github.com/magento/graphql-ce/pull/364)) + * [#17784](https://github.com/magento/magento2/issues/17784) -- store_view_code column has empty values in csv (fixed in [magento/magento2#19395](https://github.com/magento/magento2/pull/19395)) + * [#19786](https://github.com/magento/magento2/issues/19786) -- Can only export default store view items when upgrade to 2.3.0 (fixed in [magento/magento2#19395](https://github.com/magento/magento2/pull/19395)) + * [#18374](https://github.com/magento/magento2/issues/18374) -- Unable to get product attribute value for store-view scope type in product collection loaded for a specific store. (fixed in [magento/magento2#20071](https://github.com/magento/magento2/pull/20071)) + * [#20855](https://github.com/magento/magento2/issues/20855) -- In checkout page product price not align proper in order summary block for ipad view (fixed in [magento/magento2#20856](https://github.com/magento/magento2/pull/20856)) + * [#21296](https://github.com/magento/magento2/issues/21296) -- Pagination drop-down size does not appropriate. (fixed in [magento/magento2#21298](https://github.com/magento/magento2/pull/21298)) + * [#8086](https://github.com/magento/magento2/issues/8086) -- Multiline admin field is broken (fixed in [magento/magento2#20371](https://github.com/magento/magento2/pull/20371)) + * [#18115](https://github.com/magento/magento2/issues/18115) -- Multiline field is broken (fixed in [magento/magento2#20371](https://github.com/magento/magento2/pull/20371)) + * [#8479](https://github.com/magento/magento2/issues/8479) -- Sequence of module load order should be deterministic (fixed in [magento/magento2#21020](https://github.com/magento/magento2/pull/21020)) + * [#16116](https://github.com/magento/magento2/issues/16116) -- Modules sort order in config.php is being inconsistent when no changes being made (fixed in [magento/magento2#21020](https://github.com/magento/magento2/pull/21020)) + * [#14412](https://github.com/magento/magento2/issues/14412) -- Magento 2.2.3 TypeErrors Cannot read property 'quoteData' / 'storecode' / 'sectionLoadUrl' of undefined (fixed in [magento/magento2#18503](https://github.com/magento/magento2/pull/18503)) + * [#19983](https://github.com/magento/magento2/issues/19983) -- Can't work customer Image attribute programmatically (fixed in [magento/magento2#19988](https://github.com/magento/magento2/pull/19988)) + * [#20305](https://github.com/magento/magento2/issues/20305) -- Update button on payment checkout is not proper alligned (fixed in [magento/magento2#20307](https://github.com/magento/magento2/pull/20307)) + * [#13982](https://github.com/magento/magento2/issues/13982) -- Customer Login Block sets the title for the page when rendered (fixed in [magento/magento2#20583](https://github.com/magento/magento2/pull/20583)) + * [#20773](https://github.com/magento/magento2/issues/20773) -- The autoloader throws an exception on class_exists (fixed in [magento/magento2#20950](https://github.com/magento/magento2/pull/20950)) + * [#21322](https://github.com/magento/magento2/issues/21322) -- Declarative schema: Omitting indexType throws exception (fixed in [magento/magento2#21328](https://github.com/magento/magento2/pull/21328)) + * [#15059](https://github.com/magento/magento2/issues/15059) -- Cannot reorder from the first try (fixed in [magento/magento2#21335](https://github.com/magento/magento2/pull/21335)) + * [#21359](https://github.com/magento/magento2/issues/21359) -- Search with long string display horizontal scroll in front end (fixed in [magento/magento2#21360](https://github.com/magento/magento2/pull/21360)) + * [#21365](https://github.com/magento/magento2/issues/21365) -- CSS Property name issue (fixed in [magento/magento2#21368](https://github.com/magento/magento2/pull/21368)) + * [#389](https://github.com/magento/magento2/issues/389) -- Magento_VersionsCms::widgets.css not found (fixed in [magento/graphql-ce#390](https://github.com/magento/graphql-ce/pull/390)) + * [#293](https://github.com/magento/magento2/issues/293) -- $productAttribute->getFrontend()->getSelectOptions() grabbing unnecessary options (fixed in [magento/graphql-ce#330](https://github.com/magento/graphql-ce/pull/330)) + * [#288](https://github.com/magento/magento2/issues/288) -- Add Cell Phone to Customer Address Form (fixed in [magento/graphql-ce#330](https://github.com/magento/graphql-ce/pull/330)) + * [#287](https://github.com/magento/magento2/issues/287) -- Why the status code of Web API Resource in REST always 404 (fixed in [magento/graphql-ce#330](https://github.com/magento/graphql-ce/pull/330)) + * [#286](https://github.com/magento/magento2/issues/286) -- import configurable product with file as _custom_option_type not working (fixed in [magento/graphql-ce#330](https://github.com/magento/graphql-ce/pull/330)) + * [#13937](https://github.com/magento/magento2/issues/13937) -- Sitemap filename can't exceed 32 characters (fixed in [magento/magento2#20044](https://github.com/magento/magento2/pull/20044)) + * [#20337](https://github.com/magento/magento2/issues/20337) -- Option Title breaking in two line because applying wrong css for manage width (fixed in [magento/magento2#20339](https://github.com/magento/magento2/pull/20339)) + * [#21294](https://github.com/magento/magento2/issues/21294) -- Cart can't be emptied if any product is out of stock (fixed in [magento/magento2#21295](https://github.com/magento/magento2/pull/21295)) + * [#21383](https://github.com/magento/magento2/issues/21383) -- As low as displays incorrect pricing on category page, tax appears to be added twice (fixed in [magento/magento2#21395](https://github.com/magento/magento2/pull/21395)) + * [#21398](https://github.com/magento/magento2/issues/21398) -- Doesn't show any error message when customer click on Add to cart button without selecting atleast one product from recently orderred list (fixed in [magento/magento2#21401](https://github.com/magento/magento2/pull/21401)) + * [#20310](https://github.com/magento/magento2/issues/20310) -- Cart section data has wrong product_price_value (fixed in [magento/magento2#20316](https://github.com/magento/magento2/pull/20316)) + * [#21062](https://github.com/magento/magento2/issues/21062) -- Static tests: forbid 'or' instead of '||' (fixed in [magento/magento2#21275](https://github.com/magento/magento2/pull/21275)) + * [#21154](https://github.com/magento/magento2/issues/21154) -- 2.3.0 Watermark not showing on images (fixed in [magento/magento2#21338](https://github.com/magento/magento2/pull/21338)) + * [#13338](https://github.com/magento/magento2/issues/13338) -- Products grid in admin does not display default values? (fixed in [magento/magento2#21363](https://github.com/magento/magento2/pull/21363)) + * [#21327](https://github.com/magento/magento2/issues/21327) -- Checkout Page Cancel button is not working (fixed in [magento/magento2#21356](https://github.com/magento/magento2/pull/21356)) + * [#21425](https://github.com/magento/magento2/issues/21425) -- Date design change show not correctly value in backend (fixed in [magento/magento2#21443](https://github.com/magento/magento2/pull/21443)) + * [#20078](https://github.com/magento/magento2/issues/20078) -- Magento Ui form validator message callback not supported (fixed in [magento/magento2#20079](https://github.com/magento/magento2/pull/20079)) + * [#20128](https://github.com/magento/magento2/issues/20128) -- Magento\Reports\Model\ResourceModel\Order\Collection->getDateRange() - Error in code? (fixed in [magento/magento2#20129](https://github.com/magento/magento2/pull/20129)) + * [#14857](https://github.com/magento/magento2/issues/14857) -- Sitemap generation cron job flushes entire cache (fixed in [magento/magento2#20818](https://github.com/magento/magento2/pull/20818)) + * [#21077](https://github.com/magento/magento2/issues/21077) -- Tabbing issue on product detail page (fixed in [magento/magento2#21079](https://github.com/magento/magento2/pull/21079)) + * [#21292](https://github.com/magento/magento2/issues/21292) -- Google Analytics isAnonymizedIpActive always true (fixed in [magento/magento2#21303](https://github.com/magento/magento2/pull/21303)) + * [#21454](https://github.com/magento/magento2/issues/21454) -- Infinite redirects in Magento admin (fixed in [magento/magento2#21455](https://github.com/magento/magento2/pull/21455)) + * [#283](https://github.com/magento/magento2/issues/283) -- write Product Reviews error (fixed in [magento/graphql-ce#342](https://github.com/magento/graphql-ce/pull/342)) + * [#282](https://github.com/magento/magento2/issues/282) -- Can't create configurable product (fixed in [magento/graphql-ce#342](https://github.com/magento/graphql-ce/pull/342)) + * [#281](https://github.com/magento/magento2/issues/281) -- Pre defined var __DIR__ doesn't work (fixed in [magento/graphql-ce#342](https://github.com/magento/graphql-ce/pull/342)) + * [#279](https://github.com/magento/magento2/issues/279) -- Configurable Product: Custom Options make a discount percent of Tier Price error (fixed in [magento/graphql-ce#342](https://github.com/magento/graphql-ce/pull/342)) + * [#394](https://github.com/magento/magento2/issues/394) -- update used version of phpseclib (fixed in [magento/graphql-ce#414](https://github.com/magento/graphql-ce/pull/414)) + * [#388](https://github.com/magento/magento2/issues/388) -- Why we are using umask(0) in bootstrap.php (fixed in [magento/graphql-ce#397](https://github.com/magento/graphql-ce/pull/397)) + * [#17297](https://github.com/magento/magento2/issues/17297) -- No children data for \Magento\Catalog\Model\CategoryManagement::getTree($categoryId) after first call. (fixed in [magento/magento2#18705](https://github.com/magento/magento2/pull/18705)) + * [#19632](https://github.com/magento/magento2/issues/19632) -- Backend Marketing Cart Price Rule Label Alignment Issue (fixed in [magento/magento2#19637](https://github.com/magento/magento2/pull/19637)) + * [#20187](https://github.com/magento/magento2/issues/20187) -- Downloadable product view layout (fixed in [magento/magento2#20239](https://github.com/magento/magento2/pull/20239)) + * [#19117](https://github.com/magento/magento2/issues/19117) -- High Database Load for Sales Rule Validation (fixed in [magento/magento2#20484](https://github.com/magento/magento2/pull/20484)) + * [#21278](https://github.com/magento/magento2/issues/21278) -- Sort order missing on Downloadable Product Links and Sample Columns (fixed in [magento/magento2#21279](https://github.com/magento/magento2/pull/21279)) + * [#21329](https://github.com/magento/magento2/issues/21329) -- URL Rewrites are overwritten (fixed in [magento/magento2#21462](https://github.com/magento/magento2/pull/21462)) + * [#21192](https://github.com/magento/magento2/issues/21192) -- Wrong data of Import status with Add/Update method in Advanced Prices in CSV (fixed in [magento/magento2#21476](https://github.com/magento/magento2/pull/21476)) + * [#19276](https://github.com/magento/magento2/issues/19276) -- Change different product price on selecting different product swatches on category pages (fixed in [magento/magento2#19376](https://github.com/magento/magento2/pull/19376)) + * [#20527](https://github.com/magento/magento2/issues/20527) -- [Admin] Configurable product variations table cell labels wrong position (fixed in [magento/magento2#20528](https://github.com/magento/magento2/pull/20528)) + * [#21493](https://github.com/magento/magento2/issues/21493) -- Setting default sorting (fixed in [magento/magento2#21498](https://github.com/magento/magento2/pull/21498)) + * [#21499](https://github.com/magento/magento2/issues/21499) -- Cart is emptied when enter is pressed after changing product quantity (fixed in [magento/magento2#21509](https://github.com/magento/magento2/pull/21509)) + * [#310](https://github.com/magento/magento2/issues/310) -- Problems with Controller's Router (fixed in [magento/graphql-ce#311](https://github.com/magento/graphql-ce/pull/311)) + * [#429](https://github.com/magento/magento2/issues/429) -- In dev54, the captcha of backend (Admin Login and Admin Forget Password) can't display. (fixed in [magento/graphql-ce#444](https://github.com/magento/graphql-ce/pull/444)) + * [#419](https://github.com/magento/magento2/issues/419) -- Some translation keys are not correct. (fixed in [magento/graphql-ce#451](https://github.com/magento/graphql-ce/pull/451)) + * [#424](https://github.com/magento/magento2/issues/424) -- Please combine tier pricing messages into block sentences... (fixed in [magento/graphql-ce#442](https://github.com/magento/graphql-ce/pull/442)) + * [#427](https://github.com/magento/magento2/issues/427) -- Clearing Admin notification causes "Fatal error: Maximum function nesting level of '100' reached" (fixed in [magento/graphql-ce#448](https://github.com/magento/graphql-ce/pull/448)) + * [#420](https://github.com/magento/magento2/issues/420) -- The errors happed when create new API User from backend- dev53 (fixed in [magento/graphql-ce#450](https://github.com/magento/graphql-ce/pull/450)) + * [#430](https://github.com/magento/magento2/issues/430) -- ExtJS - Update to latest version (fixed in [magento/graphql-ce#471](https://github.com/magento/graphql-ce/pull/471)) + * [#18017](https://github.com/magento/magento2/issues/18017) -- URL pre-selection of configurable product swatches with associated product images throws JavaScript error (fixed in [magento/magento2#19635](https://github.com/magento/magento2/pull/19635)) + * [#20414](https://github.com/magento/magento2/issues/20414) -- Recent orders grid not aligned from left in mobile as all content aligned from left (fixed in [magento/magento2#20429](https://github.com/magento/magento2/pull/20429)) + * [#20928](https://github.com/magento/magento2/issues/20928) -- Admin product grid Massaction design issue with sub menu (fixed in [magento/magento2#20938](https://github.com/magento/magento2/pull/20938)) + * [#20989](https://github.com/magento/magento2/issues/20989) -- Admin Customizable Options Dropdown sort_order issue (fixed in [magento/magento2#21371](https://github.com/magento/magento2/pull/21371)) + * [#21419](https://github.com/magento/magento2/issues/21419) -- Wishlist is missing review summary (fixed in [magento/magento2#21420](https://github.com/magento/magento2/pull/21420)) + * [#20809](https://github.com/magento/magento2/issues/20809) -- Advanced Search layout not proper (fixed in [magento/magento2#21611](https://github.com/magento/magento2/pull/21611)) + * [#20905](https://github.com/magento/magento2/issues/20905) -- Minicart, search & logo not vertically aligned between 640 to767 device pixel. (fixed in [magento/magento2#21638](https://github.com/magento/magento2/pull/21638)) + * [#21521](https://github.com/magento/magento2/issues/21521) -- Broken Tax Rate Search Filter - SQLSTATE[23000] (fixed in [magento/magento2#21701](https://github.com/magento/magento2/pull/21701)) + * [#13612](https://github.com/magento/magento2/issues/13612) -- 1 exception(s): Exception #0 (Exception): Warning: Illegal offset type in isset or empty in /home/jewelrynest2/public_html/magento/vendor/magento/module-eav/Model/Entity/Attribute/Source/AbstractSource.php on line 76 (fixed in [magento/magento2#20001](https://github.com/magento/magento2/pull/20001)) + * [#18761](https://github.com/magento/magento2/issues/18761) -- Bug with REPLACE method in Advanced Prices in CSV Import (fixed in [magento/magento2#21189](https://github.com/magento/magento2/pull/21189)) + * [#21384](https://github.com/magento/magento2/issues/21384) -- JS minify field is not disabled in developer configuration (fixed in [magento/magento2#21444](https://github.com/magento/magento2/pull/21444)) + * [#21541](https://github.com/magento/magento2/issues/21541) -- Whitespace issues for related, cross and upsell grids (fixed in [magento/magento2#21582](https://github.com/magento/magento2/pull/21582)) + * [#167](https://github.com/magento/magento2/issues/167) -- Fatal error: Class 'Mage' not found (fixed in [magento/magento2#21731](https://github.com/magento/magento2/pull/21731)) + * [#20511](https://github.com/magento/magento2/issues/20511) -- Sorting by 'Websites' not working in product grid in backoffice (fixed in [magento/magento2#20512](https://github.com/magento/magento2/pull/20512)) + * [#19360](https://github.com/magento/magento2/issues/19360) -- Missed form validation in Admin Order Address Edit route sales/order/address (fixed in [magento/magento2#20840](https://github.com/magento/magento2/pull/20840)) + * [#17295](https://github.com/magento/magento2/issues/17295) -- Search REST API returns wrong total_count (fixed in [magento/magento2#21713](https://github.com/magento/magento2/pull/21713)) + * [#18630](https://github.com/magento/magento2/issues/18630) -- Postcode / Zipcode in checkout form already validated on page load (fixed in [magento/magento2#18633](https://github.com/magento/magento2/pull/18633)) + * [#21648](https://github.com/magento/magento2/issues/21648) -- Checkout Agreements checkbox missing asterisk (fixed in [magento/magento2#21649](https://github.com/magento/magento2/pull/21649)) + * [#12396](https://github.com/magento/magento2/issues/12396) -- "Total Amount" cart rule without tax (fixed in [magento/magento2#21288](https://github.com/magento/magento2/pull/21288)) + * [#21467](https://github.com/magento/magento2/issues/21467) -- Tier price of simple item not working in Bundle product (fixed in [magento/magento2#21469](https://github.com/magento/magento2/pull/21469)) + * [#21510](https://github.com/magento/magento2/issues/21510) -- Can't access backend indexers page after creating a custom index (fixed in [magento/magento2#21575](https://github.com/magento/magento2/pull/21575)) + * [#21750](https://github.com/magento/magento2/issues/21750) -- Product attribute labels are translated (fixed in [magento/magento2#21751](https://github.com/magento/magento2/pull/21751)) + * [#19835](https://github.com/magento/magento2/issues/19835) -- Admin grid button flicker issue after page load due to re-ordering (fixed in [magento/magento2#21791](https://github.com/magento/magento2/pull/21791)) + * [#21374](https://github.com/magento/magento2/issues/21374) -- Dot is not allowed when editing CMS block in-line (fixed in [magento/magento2#21376](https://github.com/magento/magento2/pull/21376)) + * [#21396](https://github.com/magento/magento2/issues/21396) -- [Frontend] Additional addresses DataTable Pagination count displaying wrong. (fixed in [magento/magento2#21399](https://github.com/magento/magento2/pull/21399)) + * [#21692](https://github.com/magento/magento2/issues/21692) -- Incorrect constructor of Magento\Sales\Model\Order\Address\Validator (fixed in [magento/magento2#21693](https://github.com/magento/magento2/pull/21693)) + * [#21752](https://github.com/magento/magento2/issues/21752) -- Error while installing Magento from scratch if Locale Resolver is injected in cli command (fixed in [magento/magento2#21693](https://github.com/magento/magento2/pull/21693)) + * [#20825](https://github.com/magento/magento2/issues/20825) -- Missing required argument $productAvailabilityChecks of Magento\Sales\Model\Order\Reorder\OrderedProductAvailabilityChecker. (fixed in [magento/magento2#21820](https://github.com/magento/magento2/pull/21820)) + * [#20859](https://github.com/magento/magento2/issues/20859) -- Luma theme - Input Box and Radio Button shadow is not proper (fixed in [magento/magento2#21851](https://github.com/magento/magento2/pull/21851)) + * [#482](https://github.com/magento/magento2/issues/482) -- Cms pages meta title (fixed in [magento/graphql-ce#492](https://github.com/magento/graphql-ce/pull/492)) + * [#20209](https://github.com/magento/magento2/issues/20209) -- errors/local.xml and error page templates are publicly accessible (fixed in [magento/magento2#20212](https://github.com/magento/magento2/pull/20212)) + * [#20434](https://github.com/magento/magento2/issues/20434) -- Product URL duplicate when changing visibility via mass action (fixed in [magento/magento2#20774](https://github.com/magento/magento2/pull/20774)) + * [#18754](https://github.com/magento/magento2/issues/18754) -- Negative order amount in dashboard latest order when order is cancelled where coupon has been used (fixed in [magento/magento2#21283](https://github.com/magento/magento2/pull/21283)) + * [#21281](https://github.com/magento/magento2/issues/21281) -- Wrong order amount on dashboard on Last orders listing when order has discount and it is partially refunded (fixed in [magento/magento2#21283](https://github.com/magento/magento2/pull/21283)) + * [#21620](https://github.com/magento/magento2/issues/21620) -- Update title of Review content (fixed in [magento/magento2#21621](https://github.com/magento/magento2/pull/21621)) + * [#21001](https://github.com/magento/magento2/issues/21001) -- Unit Tests failed (fixed in [magento/magento2#21880](https://github.com/magento/magento2/pull/21880)) + * [#432](https://github.com/magento/magento2/issues/432) -- [Feature request] Make reindex for specific store view (fixed in [magento/graphql-ce#449](https://github.com/magento/graphql-ce/pull/449)) + * [#14926](https://github.com/magento/magento2/issues/14926) -- "Rolled back transaction has not been completed correctly" on Magento 2.2.3 (fixed in [magento/magento2#21697](https://github.com/magento/magento2/pull/21697)) + * [#18752](https://github.com/magento/magento2/issues/18752) -- Rolled back transaction has not been completed correctly" on Magento 2.1.15 (fixed in [magento/magento2#21697](https://github.com/magento/magento2/pull/21697)) + * [#21734](https://github.com/magento/magento2/issues/21734) -- Error in JS validation rule (fixed in [magento/magento2#21776](https://github.com/magento/magento2/pull/21776)) + * [#422](https://github.com/magento/magento2/issues/422) -- Cannot run a new module installation script after Magento 2 installation (fixed in [magento/graphql-ce#467](https://github.com/magento/graphql-ce/pull/467)) + * [#478](https://github.com/magento/magento2/issues/478) -- wishlist cannot get product item caused the fatal error (fixed in [magento/graphql-ce#491](https://github.com/magento/graphql-ce/pull/491)) + * [#485](https://github.com/magento/magento2/issues/485) -- Problem with configuration of SetupFactory in di.xml (fixed in [magento/graphql-ce#496](https://github.com/magento/graphql-ce/pull/496)) + * [#15972](https://github.com/magento/magento2/issues/15972) -- Since Magento 2.2.1, certain variables in the configuration get resolved to their actual value (fixed in [magento/magento2#18067](https://github.com/magento/magento2/pull/18067)) + * [#17658](https://github.com/magento/magento2/issues/17658) -- validate function in vatvalidation calls checkVatNumber a lot (fixed in [magento/magento2#19265](https://github.com/magento/magento2/pull/19265)) + * [#20766](https://github.com/magento/magento2/issues/20766) -- AttributeCode column name length validation throws wrong error message (fixed in [magento/magento2#20526](https://github.com/magento/magento2/pull/20526)) + * [#20943](https://github.com/magento/magento2/issues/20943) -- No complete validation while creation of attributes. (fixed in [magento/magento2#20526](https://github.com/magento/magento2/pull/20526)) + * [#13319](https://github.com/magento/magento2/issues/13319) -- Incorrect method return value in \Magento\Shipping\Model\Carrier\AbstractCarrier::getTotalNumOfBoxes() (fixed in [magento/magento2#20898](https://github.com/magento/magento2/pull/20898)) + * [#21134](https://github.com/magento/magento2/issues/21134) -- Invalid argument supplied for foreach thrown in EAV code (fixed in [magento/magento2#21135](https://github.com/magento/magento2/pull/21135)) + * [#10893](https://github.com/magento/magento2/issues/10893) -- Street fields in checkout don't have a label that's readable by a screenreader (fixed in [magento/magento2#21484](https://github.com/magento/magento2/pull/21484)) + * [#21805](https://github.com/magento/magento2/issues/21805) -- Filter in url rewrites table in backend isn't being remembered (fixed in [magento/magento2#21834](https://github.com/magento/magento2/pull/21834)) + * [#423](https://github.com/magento/magento2/issues/423) -- Can't login backend after running some time - dev53 (fixed in [magento/graphql-ce#460](https://github.com/magento/graphql-ce/pull/460)) + * [#13951](https://github.com/magento/magento2/issues/13951) -- Exception on customer edit under restricted admin access (fixed in [magento/magento2#18386](https://github.com/magento/magento2/pull/18386)) + * [#19761](https://github.com/magento/magento2/issues/19761) -- Custom import adapter data validation issue (fixed in [magento/magento2#19765](https://github.com/magento/magento2/pull/19765)) + * [#21755](https://github.com/magento/magento2/issues/21755) -- Magento should create a log entry if an observer does not implement ObserverInterface (fixed in [magento/magento2#21767](https://github.com/magento/magento2/pull/21767)) + * [#295](https://github.com/magento/magento2/issues/295) -- [Backend] System Configuration UI issues (fixed in [magento/graphql-ce#404](https://github.com/magento/graphql-ce/pull/404)) + * [#19909](https://github.com/magento/magento2/issues/19909) -- Not possible to use multidimensional arrays in widget parameters (fixed in [magento/magento2#21008](https://github.com/magento/magento2/pull/21008)) + * [#21926](https://github.com/magento/magento2/issues/21926) -- Exception on reorder from admin (fixed in [magento/magento2#21928](https://github.com/magento/magento2/pull/21928)) + * [#20140](https://github.com/magento/magento2/issues/20140) -- Product per row not proper on listing page (fixed in [magento/magento2#21948](https://github.com/magento/magento2/pull/21948)) + * [#21244](https://github.com/magento/magento2/issues/21244) -- Luma theme huge whitespace on category grid (fixed in [magento/magento2#21948](https://github.com/magento/magento2/pull/21948)) + * [#512](https://github.com/magento/magento2/issues/512) -- Theme Thumbnails not showing (fixed in [magento/graphql-ce#562](https://github.com/magento/graphql-ce/pull/562)) + * [#479](https://github.com/magento/magento2/issues/479) -- Different locale Settings don't work (fixed in [magento/graphql-ce#558](https://github.com/magento/graphql-ce/pull/558)) + * [#21789](https://github.com/magento/magento2/issues/21789) -- [BUG] Product gallery opening by mistake (fixed in [magento/magento2#21790](https://github.com/magento/magento2/pull/21790)) + * [#21998](https://github.com/magento/magento2/issues/21998) -- Magento/ImportExport/Model/Import has _coreConfig declared dynamically (fixed in [magento/magento2#21999](https://github.com/magento/magento2/pull/21999)) + * [#21993](https://github.com/magento/magento2/issues/21993) -- config:set not storing scoped values (fixed in [magento/magento2#22012](https://github.com/magento/magento2/pull/22012)) + * [#20186](https://github.com/magento/magento2/issues/20186) -- phpcs error on rule classes - must be of the type integer (fixed in [magento/magento2#22081](https://github.com/magento/magento2/pull/22081)) + * [#20366](https://github.com/magento/magento2/issues/20366) -- The parent product doesn't have configurable product options. (fixed in [magento/magento2#21083](https://github.com/magento/magento2/pull/21083)) + * [#22001](https://github.com/magento/magento2/issues/22001) -- Magento backend dashboard: Most viewed products tabs gives 404 error in console. (fixed in [magento/magento2#22002](https://github.com/magento/magento2/pull/22002)) + * [#581](https://github.com/magento/magento2/issues/581) -- About ByPercent.php under different currencies (fixed in [magento/graphql-ce#586](https://github.com/magento/graphql-ce/pull/586)) + * [#21916](https://github.com/magento/magento2/issues/21916) -- Elasticsearch6 generation does not exist (fixed in [magento/magento2#22046](https://github.com/magento/magento2/pull/22046)) + * [#21976](https://github.com/magento/magento2/issues/21976) -- Magento doesn't work after upgrade from 2.3.0 to 2.3.1 (fixed in [magento/magento2#22046](https://github.com/magento/magento2/pull/22046)) + * [#21715](https://github.com/magento/magento2/issues/21715) -- Previous scrolling to invalid form element is not being canceled on hitting submit multiple times (fixed in [magento/magento2#22117](https://github.com/magento/magento2/pull/22117)) + * [#21824](https://github.com/magento/magento2/issues/21824) -- Filter in admin users grid in backend isn't being remembered (fixed in [magento/magento2#22128](https://github.com/magento/magento2/pull/22128)) + * [#21973](https://github.com/magento/magento2/issues/21973) -- Why phar stream is being unregistered? (fixed in [magento/magento2#22171](https://github.com/magento/magento2/pull/22171)) + * [#22166](https://github.com/magento/magento2/issues/22166) -- Information and link in README.md file related to Security issue reporting should be updated (fixed in [magento/magento2#22195](https://github.com/magento/magento2/pull/22195)) + * [#7623](https://github.com/magento/magento2/issues/7623) -- Web Setup Wizard not visible in backend (V.2.1.2) ONGOING (fixed in [magento/magento2#20182](https://github.com/magento/magento2/pull/20182)) + * [#11892](https://github.com/magento/magento2/issues/11892) -- Web Setup Wizard not visible in backend magento 2.1.9 (fixed in [magento/magento2#20182](https://github.com/magento/magento2/pull/20182)) + * [#20830](https://github.com/magento/magento2/issues/20830) -- On Header customer name appearing twice after login (fixed in [magento/magento2#20832](https://github.com/magento/magento2/pull/20832)) + * [#21375](https://github.com/magento/magento2/issues/21375) -- Same product quantity not increment when added with guest user. (fixed in [magento/magento2#21501](https://github.com/magento/magento2/pull/21501)) + * [#21786](https://github.com/magento/magento2/issues/21786) -- Asynchronous email sending for the sales entities which were created with disabled email sending (fixed in [magento/magento2#21788](https://github.com/magento/magento2/pull/21788)) + * [#21753](https://github.com/magento/magento2/issues/21753) -- Order Item Status to Enable Downloads is set to "Pending," but no download links are presented in "My Downloads" when logged in (fix provided) (fixed in [magento/magento2#22073](https://github.com/magento/magento2/pull/22073)) + * [#426](https://github.com/magento/magento2/issues/426) -- The 'register' should be 'Register' in default.xml of pluse theme (fixed in [magento/graphql-ce#441](https://github.com/magento/graphql-ce/pull/441)) + * [#425](https://github.com/magento/magento2/issues/425) -- Installation of dev53 fails (fixed in [magento/graphql-ce#441](https://github.com/magento/graphql-ce/pull/441)) + * [#564](https://github.com/magento/magento2/issues/564) -- Catalog product images - Do not removing from file system (fixed in [magento/graphql-ce#571](https://github.com/magento/graphql-ce/pull/571) and [magento/graphql-ce#614](https://github.com/magento/graphql-ce/pull/614)) + * [#12386](https://github.com/magento/magento2/issues/12386) -- Order Status resets to default Status after Partial Refund (fixed in [magento/magento2#20378](https://github.com/magento/magento2/pull/20378)) + * [#16513](https://github.com/magento/magento2/issues/16513) -- Can not save an inactive Admin User that has no access tokens generated (fixed in [magento/magento2#20772](https://github.com/magento/magento2/pull/20772)) + * [#21868](https://github.com/magento/magento2/issues/21868) -- Method importFromArray from \Magento\Eav\Model\Entity\Collection\AbstractCollection doesn't return a working collection (fixed in [magento/magento2#21869](https://github.com/magento/magento2/pull/21869)) + * [#22030](https://github.com/magento/magento2/issues/22030) -- Typo issue: Magento admin sales order shipment header typo issue (fixed in [magento/magento2#22031](https://github.com/magento/magento2/pull/22031)) + * [#22090](https://github.com/magento/magento2/issues/22090) -- MsrpPriceCalculator exception after upgrade to 2.3.1 (fixed in [magento/magento2#22197](https://github.com/magento/magento2/pull/22197)) + * [#22190](https://github.com/magento/magento2/issues/22190) -- Exception (BadMethodCallException): Missing required argument $msrpPriceCalculators of Magento\Msrp\Pricing\MsrpPriceCalculator. (fixed in [magento/magento2#22197](https://github.com/magento/magento2/pull/22197)) + * [#18557](https://github.com/magento/magento2/issues/18557) -- Value of created_at and updated_at columns not updating in ui_bookmark table (fixed in [magento/magento2#22340](https://github.com/magento/magento2/pull/22340)) + * [#21299](https://github.com/magento/magento2/issues/21299) -- HEAD request returns 404 (fixed in [magento/magento2#21378](https://github.com/magento/magento2/pull/21378)) + * [#21907](https://github.com/magento/magento2/issues/21907) -- Place order button disabled after failed email address validation check with braintree credit card (fixed in [magento/magento2#21936](https://github.com/magento/magento2/pull/21936)) + * [#6715](https://github.com/magento/magento2/issues/6715) -- Few weaknesses in the code (fixed in [magento/magento2#21968](https://github.com/magento/magento2/pull/21968)) + * [#21960](https://github.com/magento/magento2/issues/21960) -- Layered Navigation: “Equalize product count” not working as expected (fixed in [magento/magento2#21968](https://github.com/magento/magento2/pull/21968)) + * [#22152](https://github.com/magento/magento2/issues/22152) -- Click on search icon it does not working (fixed in [magento/magento2#22154](https://github.com/magento/magento2/pull/22154)) + * [#22199](https://github.com/magento/magento2/issues/22199) -- A bug with health_check.php (fixed in [magento/magento2#22200](https://github.com/magento/magento2/pull/22200)) + * [#15090](https://github.com/magento/magento2/issues/15090) -- app:config:import fails with "Please specify the admin custom URL." (fixed in [magento/magento2#22281](https://github.com/magento/magento2/pull/22281)) + * [#20917](https://github.com/magento/magento2/issues/20917) -- Alignment Issue While Editing Order Data containing Downlodable Products in Admin Section (fixed in [magento/magento2#22298](https://github.com/magento/magento2/pull/22298)) + * [#21747](https://github.com/magento/magento2/issues/21747) -- catalog_product_flat_data for store view populated with default view data when it should be store view data (fixed in [magento/magento2#22318](https://github.com/magento/magento2/pull/22318)) + * [#22317](https://github.com/magento/magento2/issues/22317) -- CodeSniffer should not mark correctly aligned DocBlock elements as code style violation. (fixed in [magento/magento2#22321](https://github.com/magento/magento2/pull/22321)) + * [#22330](https://github.com/magento/magento2/issues/22330) -- Error "extend ' .no-link a' has no matches" when compiling email-inline css using an alternative less compiler (fixed in [magento/magento2#22332](https://github.com/magento/magento2/pull/22332)) + * [#22309](https://github.com/magento/magento2/issues/22309) -- Category Update without "name" cannot be saved in scope "all" with REST API (fixed in [magento/magento2#22362](https://github.com/magento/magento2/pull/22362)) + * [#607](https://github.com/magento/magento2/issues/607) -- sitemap.xml filename is not variable (fixed in [magento/graphql-ce#610](https://github.com/magento/graphql-ce/pull/610)) + * [#605](https://github.com/magento/magento2/issues/605) -- tinyMceWysiwyg is not working in admin form edit (fixed in [magento/graphql-ce#616](https://github.com/magento/graphql-ce/pull/616)) + * [#604](https://github.com/magento/magento2/issues/604) -- 'Continue' button is disabled even though 'I've read OSL licence' is checked (fixed in [magento/graphql-ce#614](https://github.com/magento/graphql-ce/pull/614)) + * [#19825](https://github.com/magento/magento2/issues/19825) -- Magento 2.3.0: Backup tool not correctly detecting .maintenance.flag (fixed in [magento/magento2#19993](https://github.com/magento/magento2/pull/19993)) + * [#13409](https://github.com/magento/magento2/issues/13409) -- custom widget with wysiwyg problem on insert widget via pages or blocks (fixed in [magento/magento2#20174](https://github.com/magento/magento2/pull/20174)) + * [#19742](https://github.com/magento/magento2/issues/19742) -- Widgets with a WYSIWYG parameter fail when inserting them into a WYSIWYG in a form. (fixed in [magento/magento2#20174](https://github.com/magento/magento2/pull/20174)) + * [#21654](https://github.com/magento/magento2/issues/21654) -- \Magento\Framework\Data\Collection::clear does not clear the result for \Magento\Framework\Data\Collection::getSize (fixed in [magento/magento2#21670](https://github.com/magento/magento2/pull/21670)) + * [#21702](https://github.com/magento/magento2/issues/21702) -- Purchasing a downloadable product as guest then creating an account on the onepagesuccess step doesn't link product with account (fixed in [magento/magento2#21711](https://github.com/magento/magento2/pull/21711)) + * [#21779](https://github.com/magento/magento2/issues/21779) -- Adminhtml textarea field doesn't accept maxlength (fixed in [magento/magento2#21816](https://github.com/magento/magento2/pull/21816)) + * [#22246](https://github.com/magento/magento2/issues/22246) -- Programatically created invoices miss items when both simple products and bundled products are mixed in an order (fixed in [magento/magento2#22263](https://github.com/magento/magento2/pull/22263)) + * [#22355](https://github.com/magento/magento2/issues/22355) -- Import product quantity is empty after import (fixed in [magento/magento2#22382](https://github.com/magento/magento2/pull/22382)) + * [#6272](https://github.com/magento/magento2/issues/6272) -- Changing sample for downloadable product failure (fixed in [magento/magento2#19806](https://github.com/magento/magento2/pull/19806)) + * [#3283](https://github.com/magento/magento2/issues/3283) -- «Yes/No» attributes should be allowed in the Layered Navigation (fixed in [magento/magento2#21772](https://github.com/magento/magento2/pull/21772)) + * [#21771](https://github.com/magento/magento2/issues/21771) -- Performance degradation in Layered navigation using Yes/No attribute (fixed in [magento/magento2#21772](https://github.com/magento/magento2/pull/21772)) + * [#8035](https://github.com/magento/magento2/issues/8035) -- Join extension attributes are not added to Order results (REST api) (fixed in [magento/magento2#21797](https://github.com/magento/magento2/pull/21797)) + * [#22223](https://github.com/magento/magento2/issues/22223) -- Missing/Wrong data display on downloadable report table reports>downloads in BO (fixed in [magento/magento2#22291](https://github.com/magento/magento2/pull/22291)) + * [#7227](https://github.com/magento/magento2/issues/7227) -- "x_forwarded_for" value is always empty in Order object. (fixed in [magento/magento2#21787](https://github.com/magento/magento2/pull/21787)) + * [#22047](https://github.com/magento/magento2/issues/22047) -- Magento CRON Job Names are missing in NewRelic: "Transaction Names" (fixed in [magento/magento2#22059](https://github.com/magento/magento2/pull/22059)) + * [#21737](https://github.com/magento/magento2/issues/21737) -- Duplicating product with translated url keys over multiple storeviews causes non-unique url keys to be generated (fixed in [magento/magento2#22178](https://github.com/magento/magento2/pull/22178)) + * [#22474](https://github.com/magento/magento2/issues/22474) -- Incomplete Dependency on Backup Settings Configuration (fixed in [magento/magento2#22475](https://github.com/magento/magento2/pull/22475)) + * [#22402](https://github.com/magento/magento2/issues/22402) -- PUT /V1/products/:sku/media/:entryId does not change the file (fixed in [magento/magento2#22424](https://github.com/magento/magento2/pull/22424)) + * [#22124](https://github.com/magento/magento2/issues/22124) -- Magento 2.3.1: Catalog setup fails with error "Magento\Catalog\Setup\Media does not exist" (fixed in [magento/magento2#22446](https://github.com/magento/magento2/pull/22446)) + * [#22434](https://github.com/magento/magento2/issues/22434) -- While add cart price rule from admin click on Condition drop-down arrow direction not change. (fixed in [magento/magento2#22456](https://github.com/magento/magento2/pull/22456)) + * [#20111](https://github.com/magento/magento2/issues/20111) -- Email Template Information Insert Variable popup blank (fixed in [magento/magento2#22469](https://github.com/magento/magento2/pull/22469)) + * [#21147](https://github.com/magento/magento2/issues/21147) -- Can't scroll in modal-popup on iOS (fixed in [magento/magento2#21150](https://github.com/magento/magento2/pull/21150)) + * [#21962](https://github.com/magento/magento2/issues/21962) -- Magento Sales Order: Design Align issue (fixed in [magento/magento2#21963](https://github.com/magento/magento2/pull/21963)) + * [#19544](https://github.com/magento/magento2/issues/19544) -- Grunt watch triggers entire page reload (fixed in [magento/magento2#22276](https://github.com/magento/magento2/pull/22276)) + * [#22299](https://github.com/magento/magento2/issues/22299) -- Cms block cache key does not contain the store id (fixed in [magento/magento2#22302](https://github.com/magento/magento2/pull/22302)) + * [#22270](https://github.com/magento/magento2/issues/22270) -- 2.2.8 Configurable product option dropdown - price difference incorrect when catalog prices are entered excluding tax (fixed in [magento/magento2#22466](https://github.com/magento/magento2/pull/22466)) + * [#9155](https://github.com/magento/magento2/issues/9155) -- Adding product from wishlist not adding to cart showing warning message. (fixed in [magento/magento2#19653](https://github.com/magento/magento2/pull/19653)) + * [#20481](https://github.com/magento/magento2/issues/20481) -- REST products update category_ids cannot be removed (fixed in [magento/magento2#20842](https://github.com/magento/magento2/pull/20842)) + * [#21477](https://github.com/magento/magento2/issues/21477) -- Magento 2.3 quote_item table has incorrect default value in declarative schema (fixed in [magento/magento2#21486](https://github.com/magento/magento2/pull/21486)) + * [#16939](https://github.com/magento/magento2/issues/16939) -- Incorrect configuration scope is occasionally returned when attempting to resolve a null scope id (fixed in [magento/magento2#21633](https://github.com/magento/magento2/pull/21633)) + * [#19908](https://github.com/magento/magento2/issues/19908) -- REST-API locale is always default scope (fixed in [magento/magento2#19913](https://github.com/magento/magento2/pull/19913)) + * [#21842](https://github.com/magento/magento2/issues/21842) -- Checkout error for registered customer with cache_id_prefix on multi server setup (fixed in [magento/magento2#21856](https://github.com/magento/magento2/pull/21856)) + * [#21032](https://github.com/magento/magento2/issues/21032) -- Error on design configuration save with imageUploader form element populated from gallery (fixed in [magento/magento2#22132](https://github.com/magento/magento2/pull/22132)) + * [#22052](https://github.com/magento/magento2/issues/22052) -- Customer account confirmation is overwritten by backend customer save (fixed in [magento/magento2#22147](https://github.com/magento/magento2/pull/22147)) + * [#12802](https://github.com/magento/magento2/issues/12802) -- QuoteRepository get methods won't return CartInterface but Quote model (fixed in [magento/magento2#22149](https://github.com/magento/magento2/pull/22149)) + * [#21596](https://github.com/magento/magento2/issues/21596) -- Checkout: it is possible to leave blank Shipping Details section and get to Payment Details section by URL (fixed in [magento/magento2#22405](https://github.com/magento/magento2/pull/22405)) +* GitHub pull requests: + * [magento/magento2#18706](https://github.com/magento/magento2/pull/18706) -- icon text showing feature (by @Karlasa) + * [magento/magento2#19546](https://github.com/magento/magento2/pull/19546) -- Fix typo in SQL join when joining custom option prices for price indexer (by @udovicic) + * [magento/magento2#19598](https://github.com/magento/magento2/pull/19598) -- Images in XML sitemap are always linked to base store in multistore on Schedule (by @Nazar65) + * [magento/magento2#20011](https://github.com/magento/magento2/pull/20011) -- Issue fix #20010 Wrong price amount in opengraph (by @milindsingh) + * [magento/magento2#20092](https://github.com/magento/magento2/pull/20092) -- Fix error on logo upload for Transactional Emails (#20091) (by @chaplynsky) + * [magento/magento2#20173](https://github.com/magento/magento2/pull/20173) -- [Forwardport] 'customer-login-page-input-field-are-short-width-on-tablet-view' :: a… (by @nainesh2jcommerce) + * [magento/magento2#20381](https://github.com/magento/magento2/pull/20381) -- Order shipping method bug (by @maheshWebkul721) + * [magento/magento2#20461](https://github.com/magento/magento2/pull/20461) -- #20376 Fix issue with file uploading if an upload field is disabled (by @serhiyzhovnir) + * [magento/magento2#20556](https://github.com/magento/magento2/pull/20556) -- Fixed issue #20555 Meta Keywords/Meta Description are input field in product form while they are defined as textarea (by @amitcedcoss) + * [magento/magento2#20992](https://github.com/magento/magento2/pull/20992) -- focus-not-proper-on-configurable-product-swatches:: focus not proper … (by @nainesh2jcommerce) + * [magento/magento2#21055](https://github.com/magento/magento2/pull/21055) -- added min=0 to qty field product detail page (by @awviraj) + * [magento/magento2#21120](https://github.com/magento/magento2/pull/21120) -- Correct spelling (by @ravi-chandra3197) + * [magento/magento2#19631](https://github.com/magento/magento2/pull/19631) -- Backend: Fixed checkbox alignment (by @suryakant-krish) + * [magento/magento2#20012](https://github.com/magento/magento2/pull/20012) -- typos corrected (by @mjsachan-cedcoss) + * [magento/magento2#20027](https://github.com/magento/magento2/pull/20027) -- hardcoded table name (by @melaxon) + * [magento/magento2#20115](https://github.com/magento/magento2/pull/20115) -- Fixed Issue #19891 ,Added checks of type_id (by @GovindaSharma) + * [magento/magento2#20499](https://github.com/magento/magento2/pull/20499) -- Fix typo in _resets.less (by @sjaakvdbrom) + * [magento/magento2#20887](https://github.com/magento/magento2/pull/20887) -- Removed github oauth token in sample file. The token is a personal to… (by @hostep) + * [magento/magento2#21007](https://github.com/magento/magento2/pull/21007) -- disable add to cart until page load (by @sunilit42) + * [magento/magento2#21022](https://github.com/magento/magento2/pull/21022) -- products-in-category-checkbox-not-align-properly (by @priti2jcommerce) + * [magento/magento2#21090](https://github.com/magento/magento2/pull/21090) -- Add alt text to saved payment method for accessibility (by @pmclain) + * [magento/magento2#21097](https://github.com/magento/magento2/pull/21097) -- Apply PHP-CS-Fixer "braces" fixes on `if` and `foreach` statements (by @yogeshsuhagiya) + * [magento/magento2#21096](https://github.com/magento/magento2/pull/21096) -- Updated sprintf usage; Simplified isset usage (by @df2k2) + * [magento/magento2#21100](https://github.com/magento/magento2/pull/21100) -- [Sales] Improves the UX by scrolling down the customer to the Recent Orders (by @eduard13) + * [magento/magento2#21129](https://github.com/magento/magento2/pull/21129) -- Remove unused reference on wishlist ConvertSerializedData controller (by @sasangagamlath) + * [magento/magento2#20165](https://github.com/magento/magento2/pull/20165) -- issue fixed #20163 On iPhone5 device newsletter subscription input bo… (by @cedarvinda) + * [magento/magento2#20466](https://github.com/magento/magento2/pull/20466) -- view-order-price-subtotal-alignment-not-proper-mobile (by @priti2jcommerce) + * [magento/magento2#20682](https://github.com/magento/magento2/pull/20682) -- Full Tax Summary display wrong numbers (by @niravkrish) + * [magento/magento2#20847](https://github.com/magento/magento2/pull/20847) -- Fixed validation strategy label in import form (by @elevinskii) + * [magento/magento2#20881](https://github.com/magento/magento2/pull/20881) -- Add the ability to disable/remove an action from Mass(Tree)Action (by @Beagon) + * [magento/magento2#20896](https://github.com/magento/magento2/pull/20896) -- Fixed #17861 Customer Name Prefix shows white space when extra separator is addes (by @shikhamis11) + * [magento/magento2#20895](https://github.com/magento/magento2/pull/20895) -- Entered data missing when entering the wrong date for from, to in cart rule (by @realadityayadav) + * [magento/magento2#20902](https://github.com/magento/magento2/pull/20902) -- Fixed #17564 Magento 2 inline edit date issues in admin grid with Ui Component (by @satyaprakashpatel) + * [magento/magento2#20953](https://github.com/magento/magento2/pull/20953) -- #18698 Fixed order email sending via order async email sending when order was created with disabled email sending (by @serhiyzhovnir) + * [magento/magento2#20963](https://github.com/magento/magento2/pull/20963) -- bundle-product-table-data-grouped-alignment :: Bundle product table d… (by @parag2jcommerce) + * [magento/magento2#21009](https://github.com/magento/magento2/pull/21009) -- issue fixed #20919 Email label and email field not aligned from left … (by @cedarvinda) + * [magento/magento2#21038](https://github.com/magento/magento2/pull/21038) -- quantity-not-center-align-on-review-order (by @nainesh2jcommerce) + * [magento/magento2#21071](https://github.com/magento/magento2/pull/21071) -- Fixed Luma theme my account Order status tabs 21070 (by @abrarpathan19) + * [magento/magento2#21102](https://github.com/magento/magento2/pull/21102) -- [Catalog] Fixing compare block product removing action from sidebar (by @eduard13) + * [magento/magento2#21145](https://github.com/magento/magento2/pull/21145) -- Fixed #21144 Can't change customer group when placing an admin order (by @gauravagarwal1001) + * [magento/magento2#21165](https://github.com/magento/magento2/pull/21165) -- Fix tests breaking when upgrading from 2.2 to 2.3 (by @navarr) + * [magento/magento2#18852](https://github.com/magento/magento2/pull/18852) -- Changes cache hosts warning / critical levels and continue on multiple hosts (by @wiardvanrij) + * [magento/magento2#19608](https://github.com/magento/magento2/pull/19608) -- Fixed Custom option price calculation is wrong with multi currency when option price type is percentage (by @emiprotech) + * [magento/magento2#19996](https://github.com/magento/magento2/pull/19996) -- Fixed issue Unable to open URL for downloadable product (by @shikhamis11) + * [magento/magento2#20495](https://github.com/magento/magento2/pull/20495) -- #18347 - Element 'css', attribute 'as': The attribute 'as' is not allowed. (CSS preloading) (by @vasilii-b) + * [magento/magento2#20923](https://github.com/magento/magento2/pull/20923) -- Fixed issue if there are multiple skus in catalog rule condition combination (by @suneet64) + * [magento/magento2#21069](https://github.com/magento/magento2/pull/21069) -- Error icon issue resolved (by @speedy008) + * [magento/magento2#21093](https://github.com/magento/magento2/pull/21093) -- Removed useless sprintf and removed code no longer needed (by @df2k2) + * [magento/magento2#21095](https://github.com/magento/magento2/pull/21095) -- Fixing returning types (by @eduard13) + * [magento/magento2#21098](https://github.com/magento/magento2/pull/21098) -- Updated Deprecated functions call (by @ankitsrivastavacedcoss) + * [magento/magento2#19359](https://github.com/magento/magento2/pull/19359) -- Removed direct use of SessionManager class, used SessionManagerInterface instead (by @jaimin-ktpl) + * [magento/magento2#21260](https://github.com/magento/magento2/pull/21260) -- Code clean for page doc comment on select.test.js (by @lpj822) + * [magento/magento2#19191](https://github.com/magento/magento2/pull/19191) -- Customer related values are NULL for guests converted to customers after checkout. #19166 (by @Nazar65) + * [magento/magento2#19487](https://github.com/magento/magento2/pull/19487) -- Fix DHL Quotes for Domestic Shipments when Content Type is set to Non-Document (by @gwharton) + * [magento/magento2#19566](https://github.com/magento/magento2/pull/19566) -- Minimum Qty Allowed in Shopping Cart not working on related product (by @mageprince) + * [magento/magento2#19679](https://github.com/magento/magento2/pull/19679) -- #19575 magentoDataFixture should allow to use Module Prefix - Integrations Test (by @larsroettig) + * [magento/magento2#20237](https://github.com/magento/magento2/pull/20237) -- Backend: User Role Checkbox alignement. (by @suryakant-krish) + * [magento/magento2#20839](https://github.com/magento/magento2/pull/20839) -- Checkout shipping tooltip 20838 (by @abrarpathan19) + * [magento/magento2#21197](https://github.com/magento/magento2/pull/21197) -- [Ui] Fixing the changing state of dropdown's icon (by @eduard13) + * [magento/magento2#21227](https://github.com/magento/magento2/pull/21227) -- remove-duplicated-media (by @priti2jcommerce) + * [magento/magento2#19505](https://github.com/magento/magento2/pull/19505) -- ISSUE-5021 fixed guest checkout with custom shipping carrier with unde… (by @vovsky) + * [magento/magento2#21046](https://github.com/magento/magento2/pull/21046) -- Remove unwanted condition check (by @dominicfernando) + * [magento/magento2#21121](https://github.com/magento/magento2/pull/21121) -- Applied PHP-CS-Fixer: concat_space, no_multiline_whitespace_around_double_arrow, ordered_imports (by @yogeshsuhagiya) + * [magento/magento2#21178](https://github.com/magento/magento2/pull/21178) -- Fix issue 21177 - Cart page cross-sell product add-to-cart button issue resolved (by @speedy008) + * [magento/magento2#21210](https://github.com/magento/magento2/pull/21210) -- Correct spelling (by @ravi-chandra3197) + * [magento/magento2#20971](https://github.com/magento/magento2/pull/20971) -- Cast attribute ID to integer - Fixes #20969 (by @k4emic) + * [magento/magento2#21175](https://github.com/magento/magento2/pull/21175) -- Added translation for comment tag (by @yogeshsuhagiya) + * [magento/magento2#21265](https://github.com/magento/magento2/pull/21265) -- Backend Module Manager disable icon fix. (by @speedy008) + * [magento/magento2#21301](https://github.com/magento/magento2/pull/21301) -- span tag for more swatches link (by @mageho) + * [magento/magento2#20308](https://github.com/magento/magento2/pull/20308) -- Small PHPDocs fixes [Backend module] (by @SikailoISM) + * [magento/magento2#20617](https://github.com/magento/magento2/pull/20617) -- 14882 product types xml doesn t allow numbers in model instance (by @lisovyievhenii) + * [magento/magento2#21272](https://github.com/magento/magento2/pull/21272) -- Fixed address book display horizontal scroll in responsive view (by @mage2pratik) + * [magento/magento2#19395](https://github.com/magento/magento2/pull/19395) -- store_view_code-column-has-empty-values-in-csv-17784. (by @Valant13) + * [magento/magento2#20071](https://github.com/magento/magento2/pull/20071) -- [Forwardport] [Backport] fixed store wise product filter issue (by @shikhamis11) + * [magento/magento2#20856](https://github.com/magento/magento2/pull/20856) -- ipad-view-order-summary-block (by @dipti2jcommerce) + * [magento/magento2#21298](https://github.com/magento/magento2/pull/21298) -- Fixed pagination drop-down size does not appropriate. (by @mage2pratik) + * [magento/magento2#21310](https://github.com/magento/magento2/pull/21310) -- Correct spelling (by @ravi-chandra3197) + * [magento/magento2#20371](https://github.com/magento/magento2/pull/20371) -- Issue Fixed: #8086: Multiline admin field is broken (by @vivekkumarcedcoss) + * [magento/magento2#20621](https://github.com/magento/magento2/pull/20621) -- Fix referenced to "store", changing to "scope" in Framework/Mail components (by @gwharton) + * [magento/magento2#20596](https://github.com/magento/magento2/pull/20596) -- Optimize snail_case replacement to PascalCase (by @lbajsarowicz) + * [magento/magento2#21020](https://github.com/magento/magento2/pull/21020) -- Make the module list more deterministic (by @ajardin) + * [magento/magento2#18503](https://github.com/magento/magento2/pull/18503) -- Checkout - Fix JS error Cannot read property 'quoteData' of undefined (by @ihor-sviziev) + * [magento/magento2#19988](https://github.com/magento/magento2/pull/19988) -- Fix for issue 19983 Can't upload customer Image attribute programmatically (by @Nazar65) + * [magento/magento2#20043](https://github.com/magento/magento2/pull/20043) -- Make it possible to generate sales PDF's using the API (by @AntonEvers) + * [magento/magento2#20307](https://github.com/magento/magento2/pull/20307) -- Fixed issue #20305 Update button on payment checkout is not proper alligned (by @GovindaSharma) + * [magento/magento2#20583](https://github.com/magento/magento2/pull/20583) -- 13982 customer login block sets the title for the page when rendered (by @lisovyievhenii) + * [magento/magento2#20950](https://github.com/magento/magento2/pull/20950) -- magento/magento2#20773: Do not throw exception during autoload (by @Vinai) + * [magento/magento2#21045](https://github.com/magento/magento2/pull/21045) -- Update static block in nginx.conf.sample (by @jaideepghosh) + * [magento/magento2#21328](https://github.com/magento/magento2/pull/21328) -- Issue Fixed #21322 : Declarative schema: Omitting indexType throws exception (by @milindsingh) + * [magento/magento2#21335](https://github.com/magento/magento2/pull/21335) -- Fixed #15059 Cannot reorder from the first try (by @shikhamis11) + * [magento/magento2#21347](https://github.com/magento/magento2/pull/21347) -- Applied PHP-CS-Fixer for code cleanup. (by @yogeshsuhagiya) + * [magento/magento2#21360](https://github.com/magento/magento2/pull/21360) -- Solve #21359 Search with long string display horizontal scroll in front end (by @mageprince) + * [magento/magento2#21368](https://github.com/magento/magento2/pull/21368) -- Css property name issue (by @amol2jcommerce) + * [magento/magento2#20044](https://github.com/magento/magento2/pull/20044) -- Sitemap filename can't exceed 32 characters #13937 (by @irajneeshgupta) + * [magento/magento2#20339](https://github.com/magento/magento2/pull/20339) -- issue fixed #20337 Option Title breaking in two line because applying… (by @cedarvinda) + * [magento/magento2#20578](https://github.com/magento/magento2/pull/20578) -- Added original exception as the cause to the new exception on product delete error (by @woutersamaey) + * [magento/magento2#20858](https://github.com/magento/magento2/pull/20858) -- Update details.phtml (by @mageho) + * [magento/magento2#21105](https://github.com/magento/magento2/pull/21105) -- Fixed pagination issue in admin review grid (by @dominicfernando) + * [magento/magento2#21295](https://github.com/magento/magento2/pull/21295) -- Fix empty cart validation (by @wojtekn) + * [magento/magento2#21302](https://github.com/magento/magento2/pull/21302) -- Misconfigured aria-labelledby for product tabs (by @mageho) + * [magento/magento2#21330](https://github.com/magento/magento2/pull/21330) -- Change comment to "database" (by @DanielRuf) + * [magento/magento2#21395](https://github.com/magento/magento2/pull/21395) -- As low as displays incorrect pricing on category page, tax appears to be added twice #21383 (by @Jitheesh) + * [magento/magento2#21401](https://github.com/magento/magento2/pull/21401) -- Show error message when customer click on Add to cart button without selecting atleast one product from recently orderred list (by @mageprince) + * [magento/magento2#21405](https://github.com/magento/magento2/pull/21405) -- Removed unused else block and corrected return types (by @yogeshsuhagiya) + * [magento/magento2#21429](https://github.com/magento/magento2/pull/21429) -- Correct spelling (by @ravi-chandra3197) + * [magento/magento2#21426](https://github.com/magento/magento2/pull/21426) -- fixes-for-product-page-product-in-website-multi-store-view-not-displa… (by @priti2jcommerce) + * [magento/magento2#21431](https://github.com/magento/magento2/pull/21431) -- Fix grammar (by @DanielRuf) + * [magento/magento2#21151](https://github.com/magento/magento2/pull/21151) -- Database Rollback not working M2.3.0 (by @Stepa4man) + * [magento/magento2#21458](https://github.com/magento/magento2/pull/21458) -- Elasticsearch6 implementation. (by @romainruaud) + * [magento/magento2#20316](https://github.com/magento/magento2/pull/20316) -- Change product_price_value in cart data section based on tax settings (by @NickdeK) + * [magento/magento2#20482](https://github.com/magento/magento2/pull/20482) -- [TASK] Remove translation of attribute store label in getAdditionalData (by @c-walter) + * [magento/magento2#21094](https://github.com/magento/magento2/pull/21094) -- Also populate the storesCache when importing product only on storevie… (by @hostep) + * [magento/magento2#21130](https://github.com/magento/magento2/pull/21130) -- Remove unused use statement in Wishlist Allcart Controller (by @oshancp) + * [magento/magento2#21275](https://github.com/magento/magento2/pull/21275) -- Static tests: forbid 'or' instead of '||' #21062. (by @novikor) + * [magento/magento2#21338](https://github.com/magento/magento2/pull/21338) -- [Catalog] [MediaStorage] Fix watermark in media application (by @progreg) + * [magento/magento2#21363](https://github.com/magento/magento2/pull/21363) -- [Catalog] Fixing the Products grid with default values on multi stores (by @eduard13) + * [magento/magento2#21356](https://github.com/magento/magento2/pull/21356) -- Checkout Page Cancel button is not working #21327 (by @Jitheesh) + * [magento/magento2#21443](https://github.com/magento/magento2/pull/21443) -- Fixed #21425 Date design change show not correctly value in backend (by @shikhamis11) + * [magento/magento2#21474](https://github.com/magento/magento2/pull/21474) -- Refactoring the Form class (by @eduard13) + * [magento/magento2#20079](https://github.com/magento/magento2/pull/20079) -- [2.3] Add support for validation message callback (by @floorz) + * [magento/magento2#20129](https://github.com/magento/magento2/pull/20129) -- Issue fixed #20128 : Date range returns the same start and end date (by @milindsingh) + * [magento/magento2#20818](https://github.com/magento/magento2/pull/20818) -- 14857: prevent cache drop for frontend caches on sitemap generation (by @david-fuehr) + * [magento/magento2#21079](https://github.com/magento/magento2/pull/21079) -- Fixes for product tabbing issue (by @prakash2jcommerce) + * [magento/magento2#21303](https://github.com/magento/magento2/pull/21303) -- Fix-issue-21292 Google Analytics isAnonymizedIpActive always true (by @Nazar65) + * [magento/magento2#21455](https://github.com/magento/magento2/pull/21455) -- Infinite redirects in Magento admin #21454 (by @Jitheesh) + * [magento/magento2#17668](https://github.com/magento/magento2/pull/17668) -- Adding property mapper for product eav attribute -> search weight. (by @bartoszkubicki) + * [magento/magento2#18705](https://github.com/magento/magento2/pull/18705) -- Correct child node load when multiple calls to CategoryManagement::ge… (by @pmclain) + * [magento/magento2#19637](https://github.com/magento/magento2/pull/19637) -- Fixed Issue #19632 - Backend Marketing Cart Price Rule Label Alignment Issue (by @speedy008) + * [magento/magento2#20239](https://github.com/magento/magento2/pull/20239) -- Fixed issue #20187 Downloadble Price duplicate issue (by @GovindaSharma) + * [magento/magento2#20484](https://github.com/magento/magento2/pull/20484) -- Fix performance leak in salesrule collection (by @david-fuehr) + * [magento/magento2#21170](https://github.com/magento/magento2/pull/21170) -- Fix issue with custom option file uploading (by @nikolaevas) + * [magento/magento2#21279](https://github.com/magento/magento2/pull/21279) -- Fixed: #21278, Add sort order on downloadable links (by @maheshWebkul721) + * [magento/magento2#21462](https://github.com/magento/magento2/pull/21462) -- URL rewrite fix while product website update using mass action (by @AnshuMishra17) + * [magento/magento2#21476](https://github.com/magento/magento2/pull/21476) -- Fix/issue 21192 (by @DenisSaltanahmedov) + * [magento/magento2#21503](https://github.com/magento/magento2/pull/21503) -- Remove setting of page title from Form/Register block and add title to customer_account_create layout (by @mfickers) + * [magento/magento2#19376](https://github.com/magento/magento2/pull/19376) -- 19276 - Fixed price renderer issue (by @sarfarazbheda) + * [magento/magento2#20391](https://github.com/magento/magento2/pull/20391) -- Success message is not showing when creating invoice & shipment simultaniously #19942 (by @XxXgeoXxX) + * [magento/magento2#20528](https://github.com/magento/magento2/pull/20528) -- Fix for #20527 [Admin] Configurable product variations table cell labels wrong position (by @vasilii-b) + * [magento/magento2#21498](https://github.com/magento/magento2/pull/21498) -- Setting default sorting #21493 (by @Jitheesh) + * [magento/magento2#21509](https://github.com/magento/magento2/pull/21509) -- Fix: Cart is emptied when enter is pressed after changing product quantity (by @lfluvisotto) + * [magento/magento2#21536](https://github.com/magento/magento2/pull/21536) -- Fix type hints and replace deprecated method usage (by @avstudnitz) + * [magento/magento2#21534](https://github.com/magento/magento2/pull/21534) -- correct spelling (by @ravi-chandra3197) + * [magento/magento2#13184](https://github.com/magento/magento2/pull/13184) -- [FEATURE] added ability to create default/fixed value nodes during XSD Schema Validation (by @matthiasherold) + * [magento/magento2#19635](https://github.com/magento/magento2/pull/19635) -- Patch 18017 magento 23 (by @niravkrish) + * [magento/magento2#20429](https://github.com/magento/magento2/pull/20429) -- 'fixes-for-#20414' :: Recent orders grid not aligned from left in mob… (by @nainesh2jcommerce) + * [magento/magento2#20938](https://github.com/magento/magento2/pull/20938) -- Fixed Massaction design with submenu on grid pages (by @ananth-iyer) + * [magento/magento2#21074](https://github.com/magento/magento2/pull/21074) -- Added space above error message. (by @suryakant-krish) + * [magento/magento2#21371](https://github.com/magento/magento2/pull/21371) -- Fix Admin Customizable Options Dropdown sort_order issue (by @omiroshnichenko) + * [magento/magento2#21420](https://github.com/magento/magento2/pull/21420) -- Wishlist review summary (by @Den4ik) + * [magento/magento2#21542](https://github.com/magento/magento2/pull/21542) -- Remove Environment emulation for better performance on sitemap generation (by @Nazar65) + * [magento/magento2#21611](https://github.com/magento/magento2/pull/21611) -- Advanced-Search-layout-not-proper (by @amol2jcommerce) + * [magento/magento2#21638](https://github.com/magento/magento2/pull/21638) -- Minicart search logo not vertically aligned (by @amol2jcommerce) + * [magento/magento2#21685](https://github.com/magento/magento2/pull/21685) -- Spelling Correction (by @ansari-krish) + * [magento/magento2#21701](https://github.com/magento/magento2/pull/21701) -- Fix Broken Tax Rate Search Filter Admin grid #21521 (by @tuyennn) + * [magento/magento2#21716](https://github.com/magento/magento2/pull/21716) -- [DB] Remove unused variable (by @eduard13) + * [magento/magento2#20001](https://github.com/magento/magento2/pull/20001) -- #13612 Fixed-Quantity_and_stock_status when visibility set to storefront throwing exception (by @aditisinghcedcoss) + * [magento/magento2#21180](https://github.com/magento/magento2/pull/21180) -- [ForwardPort] #18896 Add Mexico Regions (by @osrecio) + * [magento/magento2#21189](https://github.com/magento/magento2/pull/21189) -- Fix/issue 18761 (by @DenisSaltanahmedov) + * [magento/magento2#21468](https://github.com/magento/magento2/pull/21468) -- Fix long string display horizontal scroll in all pages in admin (by @mageprince) + * [magento/magento2#21444](https://github.com/magento/magento2/pull/21444) -- Disable dropdown in JavaScript and CSS Settings in developer configuration (by @ananth-iyer) + * [magento/magento2#21600](https://github.com/magento/magento2/pull/21600) -- Fixed typo mistake (by @yogeshsuhagiya) + * [magento/magento2#21582](https://github.com/magento/magento2/pull/21582) -- Fixed Whitespace issues for related, cross and upsell grids (by @amol2jcommerce) + * [magento/magento2#21683](https://github.com/magento/magento2/pull/21683) -- Correct spelling (by @ravi-chandra3197) + * [magento/magento2#21731](https://github.com/magento/magento2/pull/21731) -- Fixed wrong proxing in the inventory observer (by @VitaliyBoyko) + * [magento/magento2#21740](https://github.com/magento/magento2/pull/21740) -- Removed extra whitespaces (by @yogeshsuhagiya) + * [magento/magento2#19859](https://github.com/magento/magento2/pull/19859) -- MUI controller lacks JSON response, instead returns status 200 with empty body (by @woutersamaey) + * [magento/magento2#20512](https://github.com/magento/magento2/pull/20512) -- Sorting by Websites not working in product grid in backoffice #20511 (by @XxXgeoXxX) + * [magento/magento2#20785](https://github.com/magento/magento2/pull/20785) -- [Forwardport] Use batches and direct queries to fix sales address upgrade (by @ihor-sviziev) + * [magento/magento2#20840](https://github.com/magento/magento2/pull/20840) -- Missed form validation in Admin Order Address Edit route sales/order/address (by @XxXgeoXxX) + * [magento/magento2#21713](https://github.com/magento/magento2/pull/21713) -- Resolve Issue : Search REST API returns wrong total_count (by @ronak2ram) + * [magento/magento2#18633](https://github.com/magento/magento2/pull/18633) -- Fix for issue magento/magento2#18630 (by @dverkade) + * [magento/magento2#21649](https://github.com/magento/magento2/pull/21649) -- Fix #21648 Checkout Agreements checkbox missing asterisk (by @Karlasa) + * [magento/magento2#21782](https://github.com/magento/magento2/pull/21782) -- Edited headings to be more consistent (by @mikeshatch) + * [magento/magento2#21288](https://github.com/magento/magento2/pull/21288) -- magento/magento2#12396: Total Amount cart rule without tax (by @AleksLi) + * [magento/magento2#21469](https://github.com/magento/magento2/pull/21469) -- Update price-bundle.js so that correct tier price is calculated while displaying in bundle product (by @adarshkhatri) + * [magento/magento2#21575](https://github.com/magento/magento2/pull/21575) -- Fix for issue #21510: Can't access backend indexers page after creating a custom index (by @ccasciotti) + * [magento/magento2#21751](https://github.com/magento/magento2/pull/21751) -- fix #21750 remove translation of product attribute label (by @Karlasa) + * [magento/magento2#21774](https://github.com/magento/magento2/pull/21774) -- MSI: Add deprecation message to CatalogInventory SPIs (by @lbajsarowicz) + * [magento/magento2#21785](https://github.com/magento/magento2/pull/21785) -- [Forwardport] [Checkout] Fix clearing admin quote address when removing all items (by @eduard13) + * [magento/magento2#21795](https://github.com/magento/magento2/pull/21795) -- [Wishlist] Covering the Wishlist classes by integration and unit tests (by @eduard13) + * [magento/magento2#21791](https://github.com/magento/magento2/pull/21791) -- #19835 Fix admin header buttons flicker (by @OlehWolf) + * [magento/magento2#21826](https://github.com/magento/magento2/pull/21826) -- Flying Fists of Kung Fu Cleanup (by @lefte) + * [magento/magento2#21376](https://github.com/magento/magento2/pull/21376) -- Fixed Inline block edit identifier validation (by @niravkrish) + * [magento/magento2#21399](https://github.com/magento/magento2/pull/21399) -- Fixed : Additional addresses DataTable Pagination count displaying wrong (by @Dharmeshvaja91) + * [magento/magento2#21693](https://github.com/magento/magento2/pull/21693) -- Fix #21692 #21752 - logic in constructor of address validator and Locale Resolver check (by @Bartlomiejsz) + * [magento/magento2#21815](https://github.com/magento/magento2/pull/21815) -- Fill data_hash from BULK response with correct data (by @silyadev) + * [magento/magento2#21820](https://github.com/magento/magento2/pull/21820) -- #20825 Missing required argument $productAvailabilityChecks of Magent… (by @kisroman) + * [magento/magento2#21843](https://github.com/magento/magento2/pull/21843) -- Fix typo (by @nasanabri) + * [magento/magento2#21851](https://github.com/magento/magento2/pull/21851) -- [Frontend] Fixing the accessibility standards violation (by @eduard13) + * [magento/magento2#21884](https://github.com/magento/magento2/pull/21884) -- Correct spelling (by @ravi-chandra3197) + * [magento/magento2#19727](https://github.com/magento/magento2/pull/19727) -- Use repository to load order when manually creating an invoice (by @JeroenVanLeusden) + * [magento/magento2#20212](https://github.com/magento/magento2/pull/20212) -- Secure errors directory (by @schmengler) + * [magento/magento2#20774](https://github.com/magento/magento2/pull/20774) -- 20434 consider url rewrite when change product visibility attribute 2 3 (by @VitaliyBoyko) + * [magento/magento2#21283](https://github.com/magento/magento2/pull/21283) -- Fixed calculation of 'Total' column under "Last Orders" listing on the admin dashboard (by @rav-redchamps) + * [magento/magento2#21621](https://github.com/magento/magento2/pull/21621) -- Updated review text in admin menu (by @gelanivishal) + * [magento/magento2#21778](https://github.com/magento/magento2/pull/21778) -- Multishipping checkout agreements now are the same as default checkout agreements (by @samuel27m) + * [magento/magento2#21825](https://github.com/magento/magento2/pull/21825) -- When setting `background` for labels explicitly the labels in admin will (by @TomashKhamlai) + * [magento/magento2#21880](https://github.com/magento/magento2/pull/21880) -- magento/magento2#21001 - fix unit tests, by passing currency to numbe… (by @kdegorski) + * [magento/magento2#21899](https://github.com/magento/magento2/pull/21899) -- Trigger contentUpdate on reviews load (by @jahvi) + * [magento/magento2#19871](https://github.com/magento/magento2/pull/19871) -- Added custom_options file upload directory to .gitignore. (by @erfanimani) + * [magento/magento2#21697](https://github.com/magento/magento2/pull/21697) -- Root exception not logged on QuoteManagement::submitQuote (by @david-fuehr) + * [magento/magento2#21776](https://github.com/magento/magento2/pull/21776) -- #21734 Error in JS validation rule (by @kisroman) + * [magento/magento2#21822](https://github.com/magento/magento2/pull/21822) -- Refactor \Order\Shipment\AddTrack Controller to use ResultInterface (by @JeroenVanLeusden) + * [magento/magento2#21919](https://github.com/magento/magento2/pull/21919) -- Fix gallery full-screen triggers (by @iGerchak) + * [magento/magento2#21921](https://github.com/magento/magento2/pull/21921) -- Correct spelling (by @ravi-chandra3197) + * [magento/magento2#18067](https://github.com/magento/magento2/pull/18067) -- Fixes variables in configuration fields not being replaced with actual value… (by @hostep) + * [magento/magento2#19265](https://github.com/magento/magento2/pull/19265) -- add missing fields to quote_address (by @ErikPel) + * [magento/magento2#20526](https://github.com/magento/magento2/pull/20526) -- [EAV] Improving the EAV attribute code validation, by not allowing to use n… (by @eduard13) + * [magento/magento2#20898](https://github.com/magento/magento2/pull/20898) -- Fixed #13319 , Incorrect method return value in \Magento\Shipping\Model\Carrier\AbstractCarrier::getTotalNumOfBoxes() (by @cedmudit) + * [magento/magento2#21053](https://github.com/magento/magento2/pull/21053) -- Allow redis compression options to be specified during `setup:install` process (by @cmacdonald-au) + * [magento/magento2#21065](https://github.com/magento/magento2/pull/21065) -- Refactored Retrieval Of Entity ID To Make AbstractDataProvider Usable (by @sprankhub) + * [magento/magento2#21135](https://github.com/magento/magento2/pull/21135) -- Fix eav form foreach error #21134 (by @wojtekn) + * [magento/magento2#21465](https://github.com/magento/magento2/pull/21465) -- Module data fixtures for @magentoDataFixtureBeforeTransaction annotations (by @Vinai) + * [magento/magento2#21484](https://github.com/magento/magento2/pull/21484) -- Populate label elements for street address fields in checkout (by @scottsb) + * [magento/magento2#21511](https://github.com/magento/magento2/pull/21511) -- SHQ18-1568 Updating UPS endpoint to use https. Http is no longer reli… (by @wsajosh) + * [magento/magento2#21749](https://github.com/magento/magento2/pull/21749) -- Sitemap Generation - Product URL check null fix (by @asim-vax) + * [magento/magento2#21834](https://github.com/magento/magento2/pull/21834) -- Add argument to show filter text in URL rewrite grid after click on back button (by @vbmagento) + * [magento/magento2#18386](https://github.com/magento/magento2/pull/18386) -- Cleaner documentation for Travis CI static tests (by @Thundar) + * [magento/magento2#19765](https://github.com/magento/magento2/pull/19765) -- Resolved undefined index issue for import adapter (by @jaimin-ktpl) + * [magento/magento2#21216](https://github.com/magento/magento2/pull/21216) -- Elasticsearch price fieldname is incorrect during indexing when storeId and websiteId do not match (by @alexander-aleman) + * [magento/magento2#21767](https://github.com/magento/magento2/pull/21767) -- Magento should create a log entry if an observer does not implement ObserverInterface (by @Nazar65) + * [magento/magento2#21896](https://github.com/magento/magento2/pull/21896) -- Contact us layout in I-pad not proper (by @amol2jcommerce) + * [magento/magento2#21927](https://github.com/magento/magento2/pull/21927) -- Removing obsolete non-English translation files, these aren't transla… (by @hostep) + * [magento/magento2#21940](https://github.com/magento/magento2/pull/21940) -- [UI] Adjusting the Magento_Ui typos (by @eduard13) + * [magento/magento2#22026](https://github.com/magento/magento2/pull/22026) -- Removed two time zlib.output_compression on section (by @samuel20miglia) + * [magento/magento2#22055](https://github.com/magento/magento2/pull/22055) -- Correct spelling (by @ravi-chandra3197) + * [magento/magento2#22056](https://github.com/magento/magento2/pull/22056) -- Spelling Correction (by @ansari-krish) + * [magento/magento2#22075](https://github.com/magento/magento2/pull/22075) -- Add space after asterisk to show as list (by @likemusic) + * [magento/magento2#18440](https://github.com/magento/magento2/pull/18440) -- [2.3] Reworked gallery.phtml to move generation of gallery json strings to own block functions (by @gwharton) + * [magento/magento2#18933](https://github.com/magento/magento2/pull/18933) -- Update typeReferenceBlock definition (by @leandrommedeiros) + * [magento/magento2#19987](https://github.com/magento/magento2/pull/19987) -- Fix broken widget placeholders after upgrading from 2.2 (by @vovayatsyuk) + * [magento/magento2#21008](https://github.com/magento/magento2/pull/21008) -- [Widget] Fixing the multidimensional array as value for the widget's parameter (by @eduard13) + * [magento/magento2#21545](https://github.com/magento/magento2/pull/21545) -- Ensure `__toString()` catches all error types (by @tylerssn) + * [magento/magento2#21647](https://github.com/magento/magento2/pull/21647) -- MFTF / Remove redundant ActionGroups (by @lbajsarowicz) + * [magento/magento2#21754](https://github.com/magento/magento2/pull/21754) -- Fixes nested array for used products cache key (by @michaellehmkuhl) + * [magento/magento2#21818](https://github.com/magento/magento2/pull/21818) -- Remove all marketing get params on Varnish to minimize the cache objects (by @ihor-sviziev) + * [magento/magento2#21928](https://github.com/magento/magento2/pull/21928) -- Set minimum qty 1 after cast to int (by @likemusic) + * [magento/magento2#21948](https://github.com/magento/magento2/pull/21948) -- Fixed WhiteSpace issue in product grid (by @shrinet) + * [magento/magento2#21966](https://github.com/magento/magento2/pull/21966) -- Remove timestap from current date when saving product special price from date (by @JeroenVanLeusden) + * [magento/magento2#22054](https://github.com/magento/magento2/pull/22054) -- fix strpos args order (by @quasilyte) + * [magento/magento2#20951](https://github.com/magento/magento2/pull/20951) -- Direct STDERR output when listing crontab to /dev/null (by @danielatdattrixdotcom) + * [magento/magento2#21023](https://github.com/magento/magento2/pull/21023) -- Corrected the translation for comment tag (by @yogeshsuhagiya) + * [magento/magento2#21790](https://github.com/magento/magento2/pull/21790) -- #21789 Fix gallery event observer (by @Den4ik) + * [magento/magento2#21999](https://github.com/magento/magento2/pull/21999) -- #21998 Magento/ImportExport/Model/Import has _coreConfig declared dyn… (by @kisroman) + * [magento/magento2#22012](https://github.com/magento/magento2/pull/22012) -- Correct bug 21993 config:set not storing scoped values (by @ochnygosch) + * [magento/magento2#22081](https://github.com/magento/magento2/pull/22081) -- phpcs error on rule classes - must be of the type integer (by @Nazar65) + * [magento/magento2#21083](https://github.com/magento/magento2/pull/21083) -- Turn on edit mode for product repository when adding children (by @pedrosousa13) + * [magento/magento2#21540](https://github.com/magento/magento2/pull/21540) -- Move Magento\Framework\HTTP\ClientInterface preference to app/etc/di.xml (by @kassner) + * [magento/magento2#21932](https://github.com/magento/magento2/pull/21932) -- Admin-Order-Create-Set-Save-address-checkbox-true-as-default-#106 (by @krnshah) + * [magento/magento2#22002](https://github.com/magento/magento2/pull/22002) -- Removed unwanted interface implementation (by @vishal-7037) + * [magento/magento2#22135](https://github.com/magento/magento2/pull/22135) -- Fix broken link in README.md (by @samuel27m) + * [magento/magento2#21821](https://github.com/magento/magento2/pull/21821) -- Aligning tooltip action on dashboard (by @rafaelstz) + * [magento/magento2#22046](https://github.com/magento/magento2/pull/22046) -- FIX for issue #21916 - Elasticsearch6 generation does not exist (by @phoenix128) + * [magento/magento2#22091](https://github.com/magento/magento2/pull/22091) -- Fixed assignment of the guest customer to the guest group when 'Automatic Assignment by VAT ID' is enabled (by @vovayatsyuk) + * [magento/magento2#22117](https://github.com/magento/magento2/pull/22117) -- Previous scrolling to invalid form element is not being canceled on h… (by @yvechirko) + * [magento/magento2#22128](https://github.com/magento/magento2/pull/22128) -- Fixes issue - #21824. "save_parameters_in_session" set to true for admin user grid (by @jayankaghosh) + * [magento/magento2#22151](https://github.com/magento/magento2/pull/22151) -- Update PatchApplierTest.php - Corrected Spelling (by @ryantfowler) + * [magento/magento2#22171](https://github.com/magento/magento2/pull/22171) -- unregister phar only when appropriate (by @adaudenthun) + * [magento/magento2#22184](https://github.com/magento/magento2/pull/22184) -- Removing incorrect less selector '.abs-cleafix', it has a typo + it i… (by @hostep) + * [magento/magento2#22195](https://github.com/magento/magento2/pull/22195) -- 22166: updated README to follow-up the switch from Bugcrowd to hackerone (by @mautz-et-tong) + * [magento/magento2#22201](https://github.com/magento/magento2/pull/22201) -- Correct spelling (by @ravi-chandra3197) + * [magento/magento2#22205](https://github.com/magento/magento2/pull/22205) -- Translated exception message (by @yogeshsuhagiya) + * [magento/magento2#22207](https://github.com/magento/magento2/pull/22207) -- Translate comment tag in DHL config settings (by @yogeshsuhagiya) + * [magento/magento2#22210](https://github.com/magento/magento2/pull/22210) -- Typography_change (by @krnshah) + * [magento/magento2#22239](https://github.com/magento/magento2/pull/22239) -- Spelling Correction (by @ansari-krish) + * [magento/magento2#22258](https://github.com/magento/magento2/pull/22258) -- Use proper variables for tooltip styles on tablet devices (by @vovayatsyuk) + * [magento/magento2#19530](https://github.com/magento/magento2/pull/19530) -- Fixed fatal error if upgrading from Magento v2.0.0 to v2.3 and non system attributes missing (by @suneet64) + * [magento/magento2#20182](https://github.com/magento/magento2/pull/20182) -- Use correct base path to check if setup folder exists (by @JeroenVanLeusden) + * [magento/magento2#20832](https://github.com/magento/magento2/pull/20832) -- fixes-for-customer-name-twice-desktop (by @priti2jcommerce) + * [magento/magento2#21501](https://github.com/magento/magento2/pull/21501) -- Same product quantity not increment when added with guest user. #21375 (by @Jitheesh) + * [magento/magento2#21788](https://github.com/magento/magento2/pull/21788) -- #21786 Fixed asynchronous email sending for the sales entities which were created with disabled email sending (by @serhiyzhovnir) + * [magento/magento2#22073](https://github.com/magento/magento2/pull/22073) -- Bug fix for #21753 (2.3-develop) (by @crankycyclops) + * [magento/magento2#22220](https://github.com/magento/magento2/pull/22220) -- Remove an unused variable from order_list fixture in the integration test suite. (by @evktalo) + * [magento/magento2#20295](https://github.com/magento/magento2/pull/20295) -- Small PHPDocs fixes (by @SikailoISM) + * [magento/magento2#20378](https://github.com/magento/magento2/pull/20378) -- 12386: Order Status resets to default Status after Partial Refund. (by @nmalevanec) + * [magento/magento2#20772](https://github.com/magento/magento2/pull/20772) -- Fixed inactive admin user token (by @mage2pratik) + * [magento/magento2#20968](https://github.com/magento/magento2/pull/20968) -- Remove direct $_SERVER variable use (by @dominicfernando) + * [magento/magento2#21869](https://github.com/magento/magento2/pull/21869) -- Fix importFromArray by setting _isCollectionLoaded to true after import (by @slackerzz) + * [magento/magento2#22031](https://github.com/magento/magento2/pull/22031) -- Fixed typo error in sales grid at admin (by @vishal-7037) + * [magento/magento2#22160](https://github.com/magento/magento2/pull/22160) -- Remove duplicate styling (by @arnoudhgz) + * [magento/magento2#22197](https://github.com/magento/magento2/pull/22197) -- Fix > Exception #0 (BadMethodCallException): Missing required argument $msrpPriceCalculators of Magento\Msrp\Pricing\MsrpPriceCalculator. (by @lfluvisotto) + * [magento/magento2#22202](https://github.com/magento/magento2/pull/22202) -- Fixed wrong url redirect when edit product review from product view page (by @ravi-chandra3197) + * [magento/magento2#22340](https://github.com/magento/magento2/pull/22340) -- Fixed Value of created_at and updated_at columns (by @shikhamis11) + * [magento/magento2#22357](https://github.com/magento/magento2/pull/22357) -- Correct spelling (by @ravi-chandra3197) + * [magento/magento2#21378](https://github.com/magento/magento2/pull/21378) -- Fix for issue #21299. Change HEAD action mapping to GET action interface and add HEAD request handling (by @mattijv) + * [magento/magento2#21936](https://github.com/magento/magento2/pull/21936) -- 21907: Place order button disabled after failed email address validation check with braintree credit card (by @kisroman) + * [magento/magento2#21968](https://github.com/magento/magento2/pull/21968) -- Layered Navigation: “Equalize product count” not working as expected (by @Nazar65) + * [magento/magento2#22133](https://github.com/magento/magento2/pull/22133) -- setAttributeSetFilter accepts both integer and integer-array (by @NiklasBr) + * [magento/magento2#22154](https://github.com/magento/magento2/pull/22154) -- Fiexed 22152 - Click on search icon it does not working on admin grid sticky header (by @niravkrish) + * [magento/magento2#22200](https://github.com/magento/magento2/pull/22200) -- fatalErrorHandler returns 500 only on fatal errors (by @wexo-team) + * [magento/magento2#22226](https://github.com/magento/magento2/pull/22226) -- Remove all marketing get params on Varnish to minimize the cache objects (added facebook and bronto parameter) (by @lfluvisotto) + * [magento/magento2#22265](https://github.com/magento/magento2/pull/22265) -- Show the correct subtotal amount for partial creditmemo email (by @kassner) + * [magento/magento2#22281](https://github.com/magento/magento2/pull/22281) -- Fixed "Please specify the admin custom URL" error on app:config:import CLI command (by @davidalger) + * [magento/magento2#22298](https://github.com/magento/magento2/pull/22298) -- Alignment Issue While Editing Order Data containing Downlodable Products with "Links can be purchased separately" enabled in Admin Section (by @ansari-krish) + * [magento/magento2#22318](https://github.com/magento/magento2/pull/22318) -- #21747 Fix catalog_product_flat_data attribute value for store during indexer (by @OlehWolf) + * [magento/magento2#22320](https://github.com/magento/magento2/pull/22320) -- Removed redundant Gallery subscription for catalog rules (by @VitaliyBoyko) + * [magento/magento2#22321](https://github.com/magento/magento2/pull/22321) -- magento/magento2#22317: CodeSniffer should not mark correctly aligned DocBlock elements as code style violation. (by @p-bystritsky) + * [magento/magento2#22332](https://github.com/magento/magento2/pull/22332) -- Fixes a less compilation error: '.no-link a' isn't defined when .emai… (by @hostep) + * [magento/magento2#22339](https://github.com/magento/magento2/pull/22339) -- Spelling Mistake in Setup > Patch (by @sudhanshu-bajaj) + * [magento/magento2#22362](https://github.com/magento/magento2/pull/22362) -- [Fixed] Category Update without "name" cannot be saved in scope "all" with REST API (by @niravkrish) + * [magento/magento2#22381](https://github.com/magento/magento2/pull/22381) -- Qty box visibility issue in wishlist when product is out of stock (by @ansari-krish) + * [magento/magento2#19993](https://github.com/magento/magento2/pull/19993) -- fixed issue of Backup tool not correctly detecting .maintenance.flag (by @hiren0241) + * [magento/magento2#20174](https://github.com/magento/magento2/pull/20174) -- Fix issues inserting Widgets with nested WYSIWYGs (by @molovo) + * [magento/magento2#21670](https://github.com/magento/magento2/pull/21670) -- Fix getSize method after clearing data collection (by @sergeynezbritskiy) + * [magento/magento2#21711](https://github.com/magento/magento2/pull/21711) -- Purchasing a downloadable product as guest then creating an account on the onepagesuccess step doesn't link product with account (by @Jitheesh) + * [magento/magento2#21756](https://github.com/magento/magento2/pull/21756) -- Fixes race condition when building merged css/js file during simultaneous requests (by @Ian410) + * [magento/magento2#21816](https://github.com/magento/magento2/pull/21816) -- #21779 Adminhtml textarea field doesn't accept maxlength (by @kisroman) + * [magento/magento2#22233](https://github.com/magento/magento2/pull/22233) -- [Fixed] Full Tax Summary missing calculation Admin create order (by @niravkrish) + * [magento/magento2#22263](https://github.com/magento/magento2/pull/22263) -- Prevented /Magento/Sales/Model/Service/InvoiceService.php incorrectly… (by @ryanpalmerweb) + * [magento/magento2#22382](https://github.com/magento/magento2/pull/22382) -- Don't skip row on import if image not available. (by @Nazar65) + * [magento/magento2#22420](https://github.com/magento/magento2/pull/22420) -- Correct spelling (by @ravi-chandra3197) + * [magento/magento2#22421](https://github.com/magento/magento2/pull/22421) -- Spelling correction (by @ansari-krish) + * [magento/magento2#18336](https://github.com/magento/magento2/pull/18336) -- add more CDATA-related tests for `Magento\Framework\Config\Dom::merge` and fix failing ones (by @enl) + * [magento/magento2#19806](https://github.com/magento/magento2/pull/19806) -- Fixed Changing sample for downloadable product failure (by @ravi-chandra3197) + * [magento/magento2#21772](https://github.com/magento/magento2/pull/21772) -- Make sure Yes/No attribute Layered Navigation filter uses index (by @stkec) + * [magento/magento2#21797](https://github.com/magento/magento2/pull/21797) -- magento/magento2#8035: Join extension attributes are not added to Order results (REST api) (by @swnsma) + * [magento/magento2#21979](https://github.com/magento/magento2/pull/21979) -- [Component Rule] Revert es6 variable declarations (by @Den4ik) + * [magento/magento2#22033](https://github.com/magento/magento2/pull/22033) -- Add multibyte support for attributeSource getOptionId method (by @gomencal) + * [magento/magento2#22082](https://github.com/magento/magento2/pull/22082) -- Remove fotorama.min.js (by @iGerchak) + * [magento/magento2#22089](https://github.com/magento/magento2/pull/22089) -- Fotorama - disabling swipe on the item with class "disableSwipe" (by @iGerchak) + * [magento/magento2#22291](https://github.com/magento/magento2/pull/22291) -- Fixed #22223 Missing/Wrong data display on downloadable report table … (by @shikhamis11) + * [magento/magento2#22364](https://github.com/magento/magento2/pull/22364) -- Fix buttonId for credit memo button on admin invoice view (by @kassner) + * [magento/magento2#21787](https://github.com/magento/magento2/pull/21787) -- Fix for Issue #7227: "x_forwarded_for" value is always empty in Order object (by @cmuench) + * [magento/magento2#22059](https://github.com/magento/magento2/pull/22059) -- #22047 Feature: Newrelic transaction name based on CLI name (by @lbajsarowicz) + * [magento/magento2#22074](https://github.com/magento/magento2/pull/22074) -- Remove @SuppressWarnings and optimize imports on Category View (by @arnoudhgz) + * [magento/magento2#22178](https://github.com/magento/magento2/pull/22178) -- #21737 Duplicating product with translated url keys over multiple sto… (by @yvechirko) + * [magento/magento2#22324](https://github.com/magento/magento2/pull/22324) -- Adding a validation before adding or executing layout generator class. (by @tiagosampaio) + * [magento/magento2#22475](https://github.com/magento/magento2/pull/22475) -- Fixed Dependency on Backup Settings Configuration (by @keyuremipro) + * [magento/magento2#22285](https://github.com/magento/magento2/pull/22285) -- make return_path_email and set_return_path configurable on website and store scope as well (by @mhauri) + * [magento/magento2#22411](https://github.com/magento/magento2/pull/22411) -- Checkout Totals Sort Order fields can't be empty and should be a number (by @barbanet) + * [magento/magento2#22424](https://github.com/magento/magento2/pull/22424) -- PUT /V1/products/:sku/media/:entryId does not change the file (by @Nazar65) + * [magento/magento2#22446](https://github.com/magento/magento2/pull/22446) -- Removes usage of classes which don't exist from DB migration scripts. (by @hostep) + * [magento/magento2#22456](https://github.com/magento/magento2/pull/22456) -- Fixed issue of drop-down arrow direction in cart price rule (by @hiren0241) + * [magento/magento2#22469](https://github.com/magento/magento2/pull/22469) -- Fix #20111 - display variables in popup while editing existing email template (by @Bartlomiejsz) + * [magento/magento2#22470](https://github.com/magento/magento2/pull/22470) -- Correct spelling (by @ravi-chandra3197) + * [magento/magento2#18541](https://github.com/magento/magento2/pull/18541) -- Set view models as shareable by default (by @thomas-kl1) + * [magento/magento2#21150](https://github.com/magento/magento2/pull/21150) -- Can't scroll in modal popup on i os (by @priti2jcommerce) + * [magento/magento2#21963](https://github.com/magento/magento2/pull/21963) -- Fixed shipping method block alignment issue (by @vishal-7037) + * [magento/magento2#22276](https://github.com/magento/magento2/pull/22276) -- only trigger livereload by .css files (by @torhoehn) + * [magento/magento2#22302](https://github.com/magento/magento2/pull/22302) -- #22299: Cms block cache key does not contain the store id (by @tzyganu) + * [magento/magento2#22466](https://github.com/magento/magento2/pull/22466) -- Fix configurable dropdown showing tax incorrectly in 2.3-develop (by @danielpfarmer) + * [magento/magento2#19653](https://github.com/magento/magento2/pull/19653) -- Adding product from wishlist not adding to cart showing warning message. (by @khodu) + * [magento/magento2#20842](https://github.com/magento/magento2/pull/20842) -- REST products update category_ids cannot be removed (by @ygyryn) + * [magento/magento2#21486](https://github.com/magento/magento2/pull/21486) -- Fix for issue #21477 sets CURRENT_TIMESTAMP on updated_at fields (by @dverkade) + * [magento/magento2#21549](https://github.com/magento/magento2/pull/21549) -- Fixed curl adapter to properly set http version based on $http_ver argument (by @davidalger) + * [magento/magento2#21633](https://github.com/magento/magento2/pull/21633) -- [Forwardport] Resolve incorrect scope code selection when the requested scopeCode is null (by @mage2pratik) + * [magento/magento2#19913](https://github.com/magento/magento2/pull/19913) -- [#19908] locale in rest calls is always default locale (by @jwundrak) + * [magento/magento2#21856](https://github.com/magento/magento2/pull/21856) -- 21842: don't cache absolute file paths in validator factory (by @david-fuehr) + * [magento/magento2#22147](https://github.com/magento/magento2/pull/22147) -- Fixed #22052 Customer account confirmation is overwritten by backend customer save (by @shikhamis11) + * [magento/magento2#22132](https://github.com/magento/magento2/pull/22132) -- Error on design configuration save with imageUploader form element po… (by @yvechirko) + * [magento/magento2#22149](https://github.com/magento/magento2/pull/22149) -- Fix #12802 - allow to override preference over CartInterface and return correct object from QuoteRepository (by @Bartlomiejsz) + * [magento/magento2#22230](https://github.com/magento/magento2/pull/22230) -- Shortening currency list in Configuration->General (replace PR #20397) (by @melaxon) + * [magento/magento2#22399](https://github.com/magento/magento2/pull/22399) -- Fix the invalid currency error in credit card payment of PayPal Payflow Pro or Payments Pro (by @Hailong) + * [magento/magento2#22405](https://github.com/magento/magento2/pull/22405) -- [Fixed] Checkout Section: Shipping step is getting skipped when customer hitting direct payment step URL (by @niravkrish) + 2.3.0 ============= To get detailed information about changes in Magento 2.3.0, see the [Release Notes](https://devdocs.magento.com/guides/v2.3/release-notes/bk-release-notes.html) +2.2.0 +============= +To get detailed information about changes in Magento 2.2.0, see the [Release Notes](https://devdocs.magento.com/guides/v2.2/release-notes/bk-release-notes.html) + 2.1.0 ============= To get detailed information about changes in Magento 2.1.0, please visit [Magento Community Edition (CE) Release Notes](https://devdocs.magento.com/guides/v2.1/release-notes/ReleaseNotes2.1.0CE.html "Magento Community Edition (CE) Release Notes") From 3efe1dd4e7e986c999789c6543b508a9021eaf0e Mon Sep 17 00:00:00 2001 From: Max Lesechko <mlesechko@magento.com> Date: Fri, 7 Jun 2019 14:03:11 -0500 Subject: [PATCH 454/773] MC-17329: Update Changelog based on delivered scope --- CHANGELOG.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 09e4886626ecd..04fb46a825f62 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -202,7 +202,7 @@ * [#21299](https://github.com/magento/magento2/issues/21299) -- HEAD request returns 404 (fixed in [magento/magento2#21378](https://github.com/magento/magento2/pull/21378)) * [#21907](https://github.com/magento/magento2/issues/21907) -- Place order button disabled after failed email address validation check with braintree credit card (fixed in [magento/magento2#21936](https://github.com/magento/magento2/pull/21936)) * [#6715](https://github.com/magento/magento2/issues/6715) -- Few weaknesses in the code (fixed in [magento/magento2#21968](https://github.com/magento/magento2/pull/21968)) - * [#21960](https://github.com/magento/magento2/issues/21960) -- Layered Navigation: “Equalize product count” not working as expected (fixed in [magento/magento2#21968](https://github.com/magento/magento2/pull/21968)) + * [#21960](https://github.com/magento/magento2/issues/21960) -- Layered Navigation: “Equalize product count” not working as expected (fixed in [magento/magento2#21968](https://github.com/magento/magento2/pull/21968)) * [#22152](https://github.com/magento/magento2/issues/22152) -- Click on search icon it does not working (fixed in [magento/magento2#22154](https://github.com/magento/magento2/pull/22154)) * [#22199](https://github.com/magento/magento2/issues/22199) -- A bug with health_check.php (fixed in [magento/magento2#22200](https://github.com/magento/magento2/pull/22200)) * [#15090](https://github.com/magento/magento2/issues/15090) -- app:config:import fails with "Please specify the admin custom URL." (fixed in [magento/magento2#22281](https://github.com/magento/magento2/pull/22281)) @@ -276,7 +276,7 @@ * [magento/magento2#21096](https://github.com/magento/magento2/pull/21096) -- Updated sprintf usage; Simplified isset usage (by @df2k2) * [magento/magento2#21100](https://github.com/magento/magento2/pull/21100) -- [Sales] Improves the UX by scrolling down the customer to the Recent Orders (by @eduard13) * [magento/magento2#21129](https://github.com/magento/magento2/pull/21129) -- Remove unused reference on wishlist ConvertSerializedData controller (by @sasangagamlath) - * [magento/magento2#20165](https://github.com/magento/magento2/pull/20165) -- issue fixed #20163 On iPhone5 device newsletter subscription input bo… (by @cedarvinda) + * [magento/magento2#20165](https://github.com/magento/magento2/pull/20165) -- issue fixed #20163 On iPhone5 device newsletter subscription input bo... (by @cedarvinda) * [magento/magento2#20466](https://github.com/magento/magento2/pull/20466) -- view-order-price-subtotal-alignment-not-proper-mobile (by @priti2jcommerce) * [magento/magento2#20682](https://github.com/magento/magento2/pull/20682) -- Full Tax Summary display wrong numbers (by @niravkrish) * [magento/magento2#20847](https://github.com/magento/magento2/pull/20847) -- Fixed validation strategy label in import form (by @elevinskii) @@ -286,7 +286,7 @@ * [magento/magento2#20902](https://github.com/magento/magento2/pull/20902) -- Fixed #17564 Magento 2 inline edit date issues in admin grid with Ui Component (by @satyaprakashpatel) * [magento/magento2#20953](https://github.com/magento/magento2/pull/20953) -- #18698 Fixed order email sending via order async email sending when order was created with disabled email sending (by @serhiyzhovnir) * [magento/magento2#20963](https://github.com/magento/magento2/pull/20963) -- bundle-product-table-data-grouped-alignment :: Bundle product table d… (by @parag2jcommerce) - * [magento/magento2#21009](https://github.com/magento/magento2/pull/21009) -- issue fixed #20919 Email label and email field not aligned from left … (by @cedarvinda) + * [magento/magento2#21009](https://github.com/magento/magento2/pull/21009) -- issue fixed #20919 Email label and email field not aligned from left ... (by @cedarvinda) * [magento/magento2#21038](https://github.com/magento/magento2/pull/21038) -- quantity-not-center-align-on-review-order (by @nainesh2jcommerce) * [magento/magento2#21071](https://github.com/magento/magento2/pull/21071) -- Fixed Luma theme my account Order status tabs 21070 (by @abrarpathan19) * [magento/magento2#21102](https://github.com/magento/magento2/pull/21102) -- [Catalog] Fixing compare block product removing action from sidebar (by @eduard13) @@ -311,7 +311,7 @@ * [magento/magento2#20839](https://github.com/magento/magento2/pull/20839) -- Checkout shipping tooltip 20838 (by @abrarpathan19) * [magento/magento2#21197](https://github.com/magento/magento2/pull/21197) -- [Ui] Fixing the changing state of dropdown's icon (by @eduard13) * [magento/magento2#21227](https://github.com/magento/magento2/pull/21227) -- remove-duplicated-media (by @priti2jcommerce) - * [magento/magento2#19505](https://github.com/magento/magento2/pull/19505) -- ISSUE-5021 fixed guest checkout with custom shipping carrier with unde… (by @vovsky) + * [magento/magento2#19505](https://github.com/magento/magento2/pull/19505) -- ISSUE-5021 fixed guest checkout with custom shipping carrier with unde... (by @vovsky) * [magento/magento2#21046](https://github.com/magento/magento2/pull/21046) -- Remove unwanted condition check (by @dominicfernando) * [magento/magento2#21121](https://github.com/magento/magento2/pull/21121) -- Applied PHP-CS-Fixer: concat_space, no_multiline_whitespace_around_double_arrow, ordered_imports (by @yogeshsuhagiya) * [magento/magento2#21178](https://github.com/magento/magento2/pull/21178) -- Fix issue 21177 - Cart page cross-sell product add-to-cart button issue resolved (by @speedy008) @@ -345,7 +345,7 @@ * [magento/magento2#21360](https://github.com/magento/magento2/pull/21360) -- Solve #21359 Search with long string display horizontal scroll in front end (by @mageprince) * [magento/magento2#21368](https://github.com/magento/magento2/pull/21368) -- Css property name issue (by @amol2jcommerce) * [magento/magento2#20044](https://github.com/magento/magento2/pull/20044) -- Sitemap filename can't exceed 32 characters #13937 (by @irajneeshgupta) - * [magento/magento2#20339](https://github.com/magento/magento2/pull/20339) -- issue fixed #20337 Option Title breaking in two line because applying… (by @cedarvinda) + * [magento/magento2#20339](https://github.com/magento/magento2/pull/20339) -- issue fixed #20337 Option Title breaking in two line because applying... (by @cedarvinda) * [magento/magento2#20578](https://github.com/magento/magento2/pull/20578) -- Added original exception as the cause to the new exception on product delete error (by @woutersamaey) * [magento/magento2#20858](https://github.com/magento/magento2/pull/20858) -- Update details.phtml (by @mageho) * [magento/magento2#21105](https://github.com/magento/magento2/pull/21105) -- Fixed pagination issue in admin review grid (by @dominicfernando) @@ -356,7 +356,7 @@ * [magento/magento2#21401](https://github.com/magento/magento2/pull/21401) -- Show error message when customer click on Add to cart button without selecting atleast one product from recently orderred list (by @mageprince) * [magento/magento2#21405](https://github.com/magento/magento2/pull/21405) -- Removed unused else block and corrected return types (by @yogeshsuhagiya) * [magento/magento2#21429](https://github.com/magento/magento2/pull/21429) -- Correct spelling (by @ravi-chandra3197) - * [magento/magento2#21426](https://github.com/magento/magento2/pull/21426) -- fixes-for-product-page-product-in-website-multi-store-view-not-displa… (by @priti2jcommerce) + * [magento/magento2#21426](https://github.com/magento/magento2/pull/21426) -- fixes-for-product-page-product-in-website-multi-store-view-not-displa... (by @priti2jcommerce) * [magento/magento2#21431](https://github.com/magento/magento2/pull/21431) -- Fix grammar (by @DanielRuf) * [magento/magento2#21151](https://github.com/magento/magento2/pull/21151) -- Database Rollback not working M2.3.0 (by @Stepa4man) * [magento/magento2#21458](https://github.com/magento/magento2/pull/21458) -- Elasticsearch6 implementation. (by @romainruaud) @@ -437,7 +437,7 @@ * [magento/magento2#21399](https://github.com/magento/magento2/pull/21399) -- Fixed : Additional addresses DataTable Pagination count displaying wrong (by @Dharmeshvaja91) * [magento/magento2#21693](https://github.com/magento/magento2/pull/21693) -- Fix #21692 #21752 - logic in constructor of address validator and Locale Resolver check (by @Bartlomiejsz) * [magento/magento2#21815](https://github.com/magento/magento2/pull/21815) -- Fill data_hash from BULK response with correct data (by @silyadev) - * [magento/magento2#21820](https://github.com/magento/magento2/pull/21820) -- #20825 Missing required argument $productAvailabilityChecks of Magent… (by @kisroman) + * [magento/magento2#21820](https://github.com/magento/magento2/pull/21820) -- #20825 Missing required argument $productAvailabilityChecks of Magent... (by @kisroman) * [magento/magento2#21843](https://github.com/magento/magento2/pull/21843) -- Fix typo (by @nasanabri) * [magento/magento2#21851](https://github.com/magento/magento2/pull/21851) -- [Frontend] Fixing the accessibility standards violation (by @eduard13) * [magento/magento2#21884](https://github.com/magento/magento2/pull/21884) -- Correct spelling (by @ravi-chandra3197) @@ -458,7 +458,7 @@ * [magento/magento2#21921](https://github.com/magento/magento2/pull/21921) -- Correct spelling (by @ravi-chandra3197) * [magento/magento2#18067](https://github.com/magento/magento2/pull/18067) -- Fixes variables in configuration fields not being replaced with actual value… (by @hostep) * [magento/magento2#19265](https://github.com/magento/magento2/pull/19265) -- add missing fields to quote_address (by @ErikPel) - * [magento/magento2#20526](https://github.com/magento/magento2/pull/20526) -- [EAV] Improving the EAV attribute code validation, by not allowing to use n… (by @eduard13) + * [magento/magento2#20526](https://github.com/magento/magento2/pull/20526) -- [EAV] Improving the EAV attribute code validation, by not allowing to use n... (by @eduard13) * [magento/magento2#20898](https://github.com/magento/magento2/pull/20898) -- Fixed #13319 , Incorrect method return value in \Magento\Shipping\Model\Carrier\AbstractCarrier::getTotalNumOfBoxes() (by @cedmudit) * [magento/magento2#21053](https://github.com/magento/magento2/pull/21053) -- Allow redis compression options to be specified during `setup:install` process (by @cmacdonald-au) * [magento/magento2#21065](https://github.com/magento/magento2/pull/21065) -- Refactored Retrieval Of Entity ID To Make AbstractDataProvider Usable (by @sprankhub) From 11fb048ce062ae41776565d79dd7dd268c164e99 Mon Sep 17 00:00:00 2001 From: Yurii Sapiha <yurasapiga93@gmail.com> Date: Mon, 10 Jun 2019 14:05:34 +0300 Subject: [PATCH 455/773] fix static-funk magento/magento2#15383 --- .../Adminhtml/Block/Agreement/Edit/AgreementsForm.xml | 2 +- .../Reports/Test/Block/Adminhtml/Sales/Coupons/Filter.xml | 2 +- .../Reports/Test/Block/Adminhtml/Sales/TaxRule/Filter.xml | 2 +- .../Sales/Test/Block/Adminhtml/Report/Filter/Form.xml | 2 +- .../Edit/Tab/ParametersType/RecentlyComparedProducts.xml | 4 ++-- .../Edit/Tab/ParametersType/RecentlyViewedProducts.xml | 4 ++-- .../app/Magento/Widget/Test/Block/Adminhtml/WidgetForm.xml | 4 ++-- lib/web/mage/validation.js | 7 ++++--- lib/web/mage/validation/validation.js | 4 +++- 9 files changed, 17 insertions(+), 14 deletions(-) diff --git a/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/Block/Adminhtml/Block/Agreement/Edit/AgreementsForm.xml b/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/Block/Adminhtml/Block/Agreement/Edit/AgreementsForm.xml index f98f9ca7cfe24..95d99f9fa76cd 100644 --- a/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/Block/Adminhtml/Block/Agreement/Edit/AgreementsForm.xml +++ b/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/Block/Adminhtml/Block/Agreement/Edit/AgreementsForm.xml @@ -18,7 +18,7 @@ <input>select</input> </mode> <stores> - <selector>[name="stores[]"]</selector> + <selector>[name="stores[0]"]</selector> <input>multiselectgrouplist</input> </stores> <checkbox_text /> diff --git a/dev/tests/functional/tests/app/Magento/Reports/Test/Block/Adminhtml/Sales/Coupons/Filter.xml b/dev/tests/functional/tests/app/Magento/Reports/Test/Block/Adminhtml/Sales/Coupons/Filter.xml index d66c3b702f076..51809448e4edb 100644 --- a/dev/tests/functional/tests/app/Magento/Reports/Test/Block/Adminhtml/Sales/Coupons/Filter.xml +++ b/dev/tests/functional/tests/app/Magento/Reports/Test/Block/Adminhtml/Sales/Coupons/Filter.xml @@ -29,7 +29,7 @@ <input>select</input> </price_rule_type> <order_statuses> - <selector>[name="order_statuses[]"]</selector> + <selector>[name="order_statuses[0]"]</selector> <input>multiselect</input> </order_statuses> <rules_list> diff --git a/dev/tests/functional/tests/app/Magento/Reports/Test/Block/Adminhtml/Sales/TaxRule/Filter.xml b/dev/tests/functional/tests/app/Magento/Reports/Test/Block/Adminhtml/Sales/TaxRule/Filter.xml index 08e783e1329a4..5820de6772e1c 100644 --- a/dev/tests/functional/tests/app/Magento/Reports/Test/Block/Adminhtml/Sales/TaxRule/Filter.xml +++ b/dev/tests/functional/tests/app/Magento/Reports/Test/Block/Adminhtml/Sales/TaxRule/Filter.xml @@ -23,7 +23,7 @@ <input>select</input> </show_order_statuses> <order_statuses> - <selector>[name="order_statuses[]"]</selector> + <selector>[name="order_statuses[0]"]</selector> <input>multiselect</input> </order_statuses> <show_empty_rows> diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Report/Filter/Form.xml b/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Report/Filter/Form.xml index d868798eba79d..294f64966bde9 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Report/Filter/Form.xml +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Report/Filter/Form.xml @@ -26,7 +26,7 @@ <input>select</input> </show_order_statuses> <order_statuses> - <selector>[name="order_statuses[]"]</selector> + <selector>[name="order_statuses[0]"]</selector> <input>multiselect</input> </order_statuses> <show_actual_columns> diff --git a/dev/tests/functional/tests/app/Magento/Widget/Test/Block/Adminhtml/Widget/Instance/Edit/Tab/ParametersType/RecentlyComparedProducts.xml b/dev/tests/functional/tests/app/Magento/Widget/Test/Block/Adminhtml/Widget/Instance/Edit/Tab/ParametersType/RecentlyComparedProducts.xml index be353be8bf6be..9da96ab4c8fcc 100644 --- a/dev/tests/functional/tests/app/Magento/Widget/Test/Block/Adminhtml/Widget/Instance/Edit/Tab/ParametersType/RecentlyComparedProducts.xml +++ b/dev/tests/functional/tests/app/Magento/Widget/Test/Block/Adminhtml/Widget/Instance/Edit/Tab/ParametersType/RecentlyComparedProducts.xml @@ -12,13 +12,13 @@ </page_size> <show_attributes> <selector> - .control [name="parameters[show_attributes][]"] + .control [name="parameters[show_attributes][1]"] </selector> <input>multiselect</input> </show_attributes> <show_buttons> <selector> - .control [name="parameters[show_buttons][]"] + .control [name="parameters[show_buttons][2]"] </selector> <input>multiselect</input> </show_buttons> diff --git a/dev/tests/functional/tests/app/Magento/Widget/Test/Block/Adminhtml/Widget/Instance/Edit/Tab/ParametersType/RecentlyViewedProducts.xml b/dev/tests/functional/tests/app/Magento/Widget/Test/Block/Adminhtml/Widget/Instance/Edit/Tab/ParametersType/RecentlyViewedProducts.xml index be353be8bf6be..9da96ab4c8fcc 100644 --- a/dev/tests/functional/tests/app/Magento/Widget/Test/Block/Adminhtml/Widget/Instance/Edit/Tab/ParametersType/RecentlyViewedProducts.xml +++ b/dev/tests/functional/tests/app/Magento/Widget/Test/Block/Adminhtml/Widget/Instance/Edit/Tab/ParametersType/RecentlyViewedProducts.xml @@ -12,13 +12,13 @@ </page_size> <show_attributes> <selector> - .control [name="parameters[show_attributes][]"] + .control [name="parameters[show_attributes][1]"] </selector> <input>multiselect</input> </show_attributes> <show_buttons> <selector> - .control [name="parameters[show_buttons][]"] + .control [name="parameters[show_buttons][2]"] </selector> <input>multiselect</input> </show_buttons> diff --git a/dev/tests/functional/tests/app/Magento/Widget/Test/Block/Adminhtml/WidgetForm.xml b/dev/tests/functional/tests/app/Magento/Widget/Test/Block/Adminhtml/WidgetForm.xml index 0e13f4ccc995e..374b966861f6f 100644 --- a/dev/tests/functional/tests/app/Magento/Widget/Test/Block/Adminhtml/WidgetForm.xml +++ b/dev/tests/functional/tests/app/Magento/Widget/Test/Block/Adminhtml/WidgetForm.xml @@ -32,13 +32,13 @@ <page_size /> <show_attributes> <selector> - .control [name="parameters[show_attributes][]"] + .control [name="parameters[show_attributes][1]"] </selector> <input>multiselect</input> </show_attributes> <show_buttons> <selector> - .control [name="parameters[show_buttons][]"] + .control [name="parameters[show_buttons][2]"] </selector> <input>multiselect</input> </show_buttons> diff --git a/lib/web/mage/validation.js b/lib/web/mage/validation.js index e62de7c4d98ee..918d7fe7206ee 100644 --- a/lib/web/mage/validation.js +++ b/lib/web/mage/validation.js @@ -1945,21 +1945,22 @@ * Before submitting the actual form, remove the previously assigned indices * @param {Object} form */ - this.options.submitHandler = function (form, event) { + this.options.submitHandler = function (form) { originalElements.forEach(function (element) { element.element.attr('name', element.name); element.element.removeAttr('orig-name'); }); - console.error(this.submit) + console.error(this.submit); /* Call the originalSubmitHandler if it's a function */ typeof originalSubmitHandler === 'function' ? originalSubmitHandler(form) : form.submit(); }; - } + }; }, /** * Validation listening. + * * @protected */ _listenFormValidate: function () { diff --git a/lib/web/mage/validation/validation.js b/lib/web/mage/validation/validation.js index 437c753d78c8b..e76a9f0a0639d 100644 --- a/lib/web/mage/validation/validation.js +++ b/lib/web/mage/validation/validation.js @@ -54,7 +54,9 @@ if (element.type === 'checkbox') { /* If orig-name attribute is present, use it for validation. Else use name */ - selector = element.getAttribute('orig-name') ? '[orig-name="' + element.getAttribute('orig-name') + '"]' : '[name="' + element.name + '"]'; + selector = element.getAttribute('orig-name') + ? '[orig-name="' + element.getAttribute('orig-name') + '"]' + : '[name="' + element.name + '"]'; $(selector).each(function () { if ($(this).is(':checked')) { checkedCount += 1; From 38cec68774e20c024042da1cab9a127a3b3a4865 Mon Sep 17 00:00:00 2001 From: Yurii Sapiha <yurasapiga93@gmail.com> Date: Mon, 10 Jun 2019 14:52:41 +0300 Subject: [PATCH 456/773] fix static magento/magento2#15383 --- lib/web/mage/validation.js | 3 ++- lib/web/mage/validation/validation.js | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/web/mage/validation.js b/lib/web/mage/validation.js index 918d7fe7206ee..a4f9880511a62 100644 --- a/lib/web/mage/validation.js +++ b/lib/web/mage/validation.js @@ -1952,10 +1952,11 @@ }); console.error(this.submit); + /* Call the originalSubmitHandler if it's a function */ typeof originalSubmitHandler === 'function' ? originalSubmitHandler(form) : form.submit(); }; - }; + } }, /** diff --git a/lib/web/mage/validation/validation.js b/lib/web/mage/validation/validation.js index e76a9f0a0639d..ef41703467784 100644 --- a/lib/web/mage/validation/validation.js +++ b/lib/web/mage/validation/validation.js @@ -54,9 +54,9 @@ if (element.type === 'checkbox') { /* If orig-name attribute is present, use it for validation. Else use name */ - selector = element.getAttribute('orig-name') - ? '[orig-name="' + element.getAttribute('orig-name') + '"]' - : '[name="' + element.name + '"]'; + var case1 = '[orig-name="' + element.getAttribute('orig-name') + '"]', + case2 = '[name="' + element.name + '"]'; + selector = element.getAttribute('orig-name') ? case1 : case2; $(selector).each(function () { if ($(this).is(':checked')) { checkedCount += 1; From 2b231c5295457e744e39750857818635a57eafdb Mon Sep 17 00:00:00 2001 From: Yurii Sapiha <yurasapiga93@gmail.com> Date: Mon, 10 Jun 2019 15:45:48 +0300 Subject: [PATCH 457/773] fix static magento/magento2#15383 --- lib/web/mage/validation/validation.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/web/mage/validation/validation.js b/lib/web/mage/validation/validation.js index ef41703467784..038b91a3e5991 100644 --- a/lib/web/mage/validation/validation.js +++ b/lib/web/mage/validation/validation.js @@ -50,13 +50,15 @@ function (value, element, params) { var checkedCount = 0, selector, - container; + container, + origNameSelector, + nameSelector; if (element.type === 'checkbox') { /* If orig-name attribute is present, use it for validation. Else use name */ - var case1 = '[orig-name="' + element.getAttribute('orig-name') + '"]', - case2 = '[name="' + element.name + '"]'; - selector = element.getAttribute('orig-name') ? case1 : case2; + origNameSelector = '[orig-name="' + element.getAttribute('orig-name') + '"]', + nameSelector = '[name="' + element.name + '"]'; + selector = element.getAttribute('orig-name') ? origNameSelector : nameSelector; $(selector).each(function () { if ($(this).is(':checked')) { checkedCount += 1; From 9d39fa290cc858860577c5ceb0c3f38f6ab2f41f Mon Sep 17 00:00:00 2001 From: Rafael Kassner <kassner@gmail.com> Date: Mon, 10 Jun 2019 15:25:29 +0200 Subject: [PATCH 458/773] Run phpcbf to fix static tests --- .../Source/Deployed/SettingCheckerTest.php | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) 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 index a864567657ae4..ce2131e061727 100644 --- 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 @@ -96,13 +96,18 @@ public function testIsReadonly($path, $scope, $scopeCode, $confValue, array $var $this->configMock->expects($this->any()) ->method('get') - ->willReturnMap(array_merge([ - [ - 'system/' . $scope . "/" . ($scopeCode ? $scopeCode . '/' : '') . $path, - null, - $confValue - ], - ], $configMap)); + ->willReturnMap( + array_merge( + [ + [ + 'system/' . $scope . "/" . ($scopeCode ? $scopeCode . '/' : '') . $path, + null, + $confValue + ], + ], + $configMap + ) + ); $this->assertSame($expectedResult, $this->checker->isReadOnly($path, $scope, $scopeCode)); } From 2816a496db8966027855146c876bf6133b5ba579 Mon Sep 17 00:00:00 2001 From: Yurii Sapiha <yurasapiga93@gmail.com> Date: Mon, 10 Jun 2019 16:49:59 +0300 Subject: [PATCH 459/773] fix-static-funk magento/magento2#15383 --- .../Newsletter/Test/Block/Adminhtml/Queue/Edit/QueueForm.xml | 2 +- .../Review/Test/Block/Adminhtml/Rating/Edit/RatingForm.xml | 2 +- lib/web/mage/validation/validation.js | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dev/tests/functional/tests/app/Magento/Newsletter/Test/Block/Adminhtml/Queue/Edit/QueueForm.xml b/dev/tests/functional/tests/app/Magento/Newsletter/Test/Block/Adminhtml/Queue/Edit/QueueForm.xml index c1970955013e8..4d2acc76c8703 100644 --- a/dev/tests/functional/tests/app/Magento/Newsletter/Test/Block/Adminhtml/Queue/Edit/QueueForm.xml +++ b/dev/tests/functional/tests/app/Magento/Newsletter/Test/Block/Adminhtml/Queue/Edit/QueueForm.xml @@ -11,7 +11,7 @@ <selector>input[name='start_at']</selector> </queue_start_at> <stores> - <selector>select[name="stores[]"]</selector> + <selector>select[name="stores[0]"]</selector> <input>multiselectgrouplist</input> </stores> <newsletter_subject> diff --git a/dev/tests/functional/tests/app/Magento/Review/Test/Block/Adminhtml/Rating/Edit/RatingForm.xml b/dev/tests/functional/tests/app/Magento/Review/Test/Block/Adminhtml/Rating/Edit/RatingForm.xml index 3e1a1c727c668..504ce64bf2a73 100644 --- a/dev/tests/functional/tests/app/Magento/Review/Test/Block/Adminhtml/Rating/Edit/RatingForm.xml +++ b/dev/tests/functional/tests/app/Magento/Review/Test/Block/Adminhtml/Rating/Edit/RatingForm.xml @@ -12,7 +12,7 @@ <strategy>css selector</strategy> <fields> <stores> - <selector>[name="stores[]"]</selector> + <selector>[name="stores[0]"]</selector> <input>multiselectgrouplist</input> </stores> <is_active> diff --git a/lib/web/mage/validation/validation.js b/lib/web/mage/validation/validation.js index 038b91a3e5991..69cb984b0d82d 100644 --- a/lib/web/mage/validation/validation.js +++ b/lib/web/mage/validation/validation.js @@ -56,8 +56,8 @@ if (element.type === 'checkbox') { /* If orig-name attribute is present, use it for validation. Else use name */ - origNameSelector = '[orig-name="' + element.getAttribute('orig-name') + '"]', - nameSelector = '[name="' + element.name + '"]'; + origNameSelector = '[orig-name="' + element.getAttribute('orig-name') + '"]'; + nameSelector = '[name="' + element.name + '"]'; selector = element.getAttribute('orig-name') ? origNameSelector : nameSelector; $(selector).each(function () { if ($(this).is(':checked')) { From 783d6a2b4bd3ad52831a1237fa0951fde9ddafd1 Mon Sep 17 00:00:00 2001 From: Soumya Unnikrishnan <sunnikri@adobe.com> Date: Mon, 10 Jun 2019 16:03:47 -0500 Subject: [PATCH 460/773] MC-4554: Convert CreateCustomerCustomAttributesEntityTest to MFTF --- .../Sales/Test/Mftf/Test/CreateOrderFromEditCustomerPageTest.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/app/code/Magento/Sales/Test/Mftf/Test/CreateOrderFromEditCustomerPageTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/CreateOrderFromEditCustomerPageTest.xml index 7ead092a1aea9..4c1f16192c88c 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/CreateOrderFromEditCustomerPageTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/CreateOrderFromEditCustomerPageTest.xml @@ -17,7 +17,6 @@ <severity value="CRITICAL"/> <testCaseId value="MC-16161"/> <group value="mtf_migrated"/> - <group value="banana"/> </annotations> <before> From 811320b35e6979c796de2dcd1cd46cb55705a5da Mon Sep 17 00:00:00 2001 From: Dmytro Horytskyi <horytsky@adobe.com> Date: Tue, 11 Jun 2019 11:25:18 -0500 Subject: [PATCH 461/773] MAGETWO-98825: [Magento Cloud] When creating a new category, the Category Permissions are set to Deny by default --- app/code/Magento/Config/Model/Config.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/app/code/Magento/Config/Model/Config.php b/app/code/Magento/Config/Model/Config.php index 356c6ca17da18..3ae70df4bdb90 100644 --- a/app/code/Magento/Config/Model/Config.php +++ b/app/code/Magento/Config/Model/Config.php @@ -287,8 +287,8 @@ private function getField(string $sectionId, string $groupId, string $fieldId): * * @param Field $field * @param string $fieldId Need for support of clone_field feature - * @param array $oldConfig Need for compatibility with _processGroup() - * @param array $extraOldGroups Need for compatibility with _processGroup() + * @param array &$oldConfig Need for compatibility with _processGroup() + * @param array &$extraOldGroups Need for compatibility with _processGroup() * @return string */ private function getFieldPath(Field $field, string $fieldId, array &$oldConfig, array &$extraOldGroups): string @@ -337,8 +337,8 @@ private function isValueChanged(array $oldConfig, string $path, array $fieldData * @param string $sectionId * @param string $groupId * @param array $groupData - * @param array $oldConfig - * @param array $extraOldGroups + * @param array &$oldConfig + * @param array &$extraOldGroups * @return array */ private function getChangedPaths( @@ -384,8 +384,8 @@ private function getChangedPaths( * @param array $groupData * @param array $groups * @param string $sectionPath - * @param array $extraOldGroups - * @param array $oldConfig + * @param array &$extraOldGroups + * @param array &$oldConfig * @param \Magento\Framework\DB\Transaction $saveTransaction * @param \Magento\Framework\DB\Transaction $deleteTransaction * @return void @@ -681,7 +681,7 @@ protected function _checkSingleStoreMode( * Get config data value * * @param string $path - * @param null|bool $inherit + * @param null|bool &$inherit * @param null|array $configData * @return \Magento\Framework\Simplexml\Element */ From ae1ffd19c5b47484926655a54f094877cf052e7f Mon Sep 17 00:00:00 2001 From: Tom Reece <treece@adobe.com> Date: Tue, 11 Jun 2019 14:35:36 -0500 Subject: [PATCH 462/773] MC-4459: Convert OnePageCheckoutOfflinePaymentMethodsTest to MFTF - Rename data entity that collided with an already existing entity --- .../Magento/Store/Test/Mftf/Data/StoreShippingMethodsData.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Store/Test/Mftf/Data/StoreShippingMethodsData.xml b/app/code/Magento/Store/Test/Mftf/Data/StoreShippingMethodsData.xml index 37687461d8db6..11b8931618f70 100644 --- a/app/code/Magento/Store/Test/Mftf/Data/StoreShippingMethodsData.xml +++ b/app/code/Magento/Store/Test/Mftf/Data/StoreShippingMethodsData.xml @@ -36,9 +36,9 @@ </entity> <entity name="MinimumOrderAmount100" type="minimum_order_amount"> - <requiredEntity type="free_shipping_subtotal">Price</requiredEntity> + <requiredEntity type="free_shipping_subtotal">FreeShippingSubtotal100</requiredEntity> </entity> - <entity name="Price" type="free_shipping_subtotal"> + <entity name="FreeShippingSubtotal100" type="free_shipping_subtotal"> <data key="value">100</data> </entity> From 6dc3e54cf7d7090c26934affcb3bce75bd618008 Mon Sep 17 00:00:00 2001 From: Tom Reece <treece@adobe.com> Date: Tue, 11 Jun 2019 16:01:23 -0500 Subject: [PATCH 463/773] MC-4459: Convert OnePageCheckoutOfflinePaymentMethodsTest to MFTF - Fortify waiting for tax in shopping cart --- .../StorefrontGuestCheckoutUsingFreeShippingAndTaxesTest.xml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontGuestCheckoutUsingFreeShippingAndTaxesTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontGuestCheckoutUsingFreeShippingAndTaxesTest.xml index 728225d460081..e6b85e2ebd33f 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontGuestCheckoutUsingFreeShippingAndTaxesTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontGuestCheckoutUsingFreeShippingAndTaxesTest.xml @@ -166,8 +166,7 @@ </actionGroup> <reloadPage stepKey="reloadThePage"/> <waitForPageLoad stepKey="waitForPageToReload"/> - <waitForElementVisible selector="{{CheckoutCartSummarySection.taxAmount}}" stepKey="waitForShippingOption"/> - <see selector="{{CheckoutCartSummarySection.taxAmount}}" userInput="$9.60" stepKey="seeTaxInTheCartSummary"/> + <waitForText selector="{{CheckoutCartSummarySection.taxAmount}}" userInput="$9.60" time="90" stepKey="waitForTaxAmount"/> <!--Select Free Shipping and proceed to checkout --> <click selector="{{AdminOrderFormPaymentSection.freeShippingOption}}" stepKey="selectFlatRateShippingMethod"/> From 3f9ef18903c9c29f95d10ec17f5dc28f2d362c9b Mon Sep 17 00:00:00 2001 From: Dmytro Horytskyi <horytsky@adobe.com> Date: Tue, 11 Jun 2019 16:38:35 -0500 Subject: [PATCH 464/773] MAGETWO-98825: [Magento Cloud] When creating a new category, the Category Permissions are set to Deny by default --- app/code/Magento/Config/Model/Config.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/app/code/Magento/Config/Model/Config.php b/app/code/Magento/Config/Model/Config.php index 3ae70df4bdb90..356c6ca17da18 100644 --- a/app/code/Magento/Config/Model/Config.php +++ b/app/code/Magento/Config/Model/Config.php @@ -287,8 +287,8 @@ private function getField(string $sectionId, string $groupId, string $fieldId): * * @param Field $field * @param string $fieldId Need for support of clone_field feature - * @param array &$oldConfig Need for compatibility with _processGroup() - * @param array &$extraOldGroups Need for compatibility with _processGroup() + * @param array $oldConfig Need for compatibility with _processGroup() + * @param array $extraOldGroups Need for compatibility with _processGroup() * @return string */ private function getFieldPath(Field $field, string $fieldId, array &$oldConfig, array &$extraOldGroups): string @@ -337,8 +337,8 @@ private function isValueChanged(array $oldConfig, string $path, array $fieldData * @param string $sectionId * @param string $groupId * @param array $groupData - * @param array &$oldConfig - * @param array &$extraOldGroups + * @param array $oldConfig + * @param array $extraOldGroups * @return array */ private function getChangedPaths( @@ -384,8 +384,8 @@ private function getChangedPaths( * @param array $groupData * @param array $groups * @param string $sectionPath - * @param array &$extraOldGroups - * @param array &$oldConfig + * @param array $extraOldGroups + * @param array $oldConfig * @param \Magento\Framework\DB\Transaction $saveTransaction * @param \Magento\Framework\DB\Transaction $deleteTransaction * @return void @@ -681,7 +681,7 @@ protected function _checkSingleStoreMode( * Get config data value * * @param string $path - * @param null|bool &$inherit + * @param null|bool $inherit * @param null|array $configData * @return \Magento\Framework\Simplexml\Element */ From 66d3252a47a93c8a728aabb30e8a86ab9d30f975 Mon Sep 17 00:00:00 2001 From: Yurii Sapiha <yurasapiga93@gmail.com> Date: Wed, 12 Jun 2019 14:35:35 +0300 Subject: [PATCH 465/773] fix funk magento/magento2#15383 --- .../tests/app/Magento/Customer/Test/Block/Form/CustomerForm.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Form/CustomerForm.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Form/CustomerForm.php index dc1e901a3feae..61166339475b7 100644 --- a/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Form/CustomerForm.php +++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Form/CustomerForm.php @@ -29,7 +29,7 @@ class CustomerForm extends Form * * @var string */ - protected $customerAttribute = "[name='%s[]']"; + protected $customerAttribute = "[orig-name='%s[]']"; /** * Validation text message for a field. From 02ff91ba994dfc017145e48e5b6dcf75ffdb7b32 Mon Sep 17 00:00:00 2001 From: Amjad M <amjad.modentharammal@appareluae.com> Date: Wed, 12 Jun 2019 16:46:18 +0530 Subject: [PATCH 466/773] fixed Spacing issue for Gift message section in my account. --- .../Magento/luma/Magento_Sales/web/css/source/_module.less | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/design/frontend/Magento/luma/Magento_Sales/web/css/source/_module.less b/app/design/frontend/Magento/luma/Magento_Sales/web/css/source/_module.less index 1be46c8239ee2..cc6aba6f3566e 100644 --- a/app/design/frontend/Magento/luma/Magento_Sales/web/css/source/_module.less +++ b/app/design/frontend/Magento/luma/Magento_Sales/web/css/source/_module.less @@ -97,7 +97,7 @@ } &.options { - padding: 0 0 15px; + padding: 10px 10px 15px; } } From fde7dc76e6fd4f5cb3429e79d43203fd196489e4 Mon Sep 17 00:00:00 2001 From: Tom Reece <treece@adobe.com> Date: Wed, 12 Jun 2019 12:32:55 -0500 Subject: [PATCH 467/773] MC-4459: Convert OnePageCheckoutOfflinePaymentMethodsTest to MFTF - Skip MC-14709 --- .../StorefrontGuestCheckoutUsingFreeShippingAndTaxesTest.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontGuestCheckoutUsingFreeShippingAndTaxesTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontGuestCheckoutUsingFreeShippingAndTaxesTest.xml index e6b85e2ebd33f..c8c6407363b4c 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontGuestCheckoutUsingFreeShippingAndTaxesTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontGuestCheckoutUsingFreeShippingAndTaxesTest.xml @@ -15,6 +15,9 @@ <severity value="CRITICAL"/> <testCaseId value="MC-14709"/> <group value="mtf_migrated"/> + <skip> + <issueId value="MC-16684"/> + </skip> </annotations> <before> From eadcff2fd8bfb6a92ea371232fc0bde562f39552 Mon Sep 17 00:00:00 2001 From: Yurii Sapiha <yurasapiga93@gmail.com> Date: Mon, 10 Jun 2019 14:05:34 +0300 Subject: [PATCH 468/773] fix static-funk magento/magento2#15383 --- .../Adminhtml/Block/Agreement/Edit/AgreementsForm.xml | 2 +- .../app/Magento/Customer/Test/Block/Form/CustomerForm.php | 2 +- .../Test/Block/Adminhtml/Queue/Edit/QueueForm.xml | 2 +- .../Reports/Test/Block/Adminhtml/Sales/Coupons/Filter.xml | 2 +- .../Reports/Test/Block/Adminhtml/Sales/TaxRule/Filter.xml | 2 +- .../Test/Block/Adminhtml/Rating/Edit/RatingForm.xml | 2 +- .../Sales/Test/Block/Adminhtml/Report/Filter/Form.xml | 2 +- .../Edit/Tab/ParametersType/RecentlyComparedProducts.xml | 4 ++-- .../Edit/Tab/ParametersType/RecentlyViewedProducts.xml | 4 ++-- .../Magento/Widget/Test/Block/Adminhtml/WidgetForm.xml | 4 ++-- lib/web/mage/validation.js | 6 ++++-- lib/web/mage/validation/validation.js | 8 ++++++-- 12 files changed, 23 insertions(+), 17 deletions(-) diff --git a/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/Block/Adminhtml/Block/Agreement/Edit/AgreementsForm.xml b/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/Block/Adminhtml/Block/Agreement/Edit/AgreementsForm.xml index f98f9ca7cfe24..95d99f9fa76cd 100644 --- a/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/Block/Adminhtml/Block/Agreement/Edit/AgreementsForm.xml +++ b/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/Block/Adminhtml/Block/Agreement/Edit/AgreementsForm.xml @@ -18,7 +18,7 @@ <input>select</input> </mode> <stores> - <selector>[name="stores[]"]</selector> + <selector>[name="stores[0]"]</selector> <input>multiselectgrouplist</input> </stores> <checkbox_text /> diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Form/CustomerForm.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Form/CustomerForm.php index dc1e901a3feae..61166339475b7 100644 --- a/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Form/CustomerForm.php +++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Form/CustomerForm.php @@ -29,7 +29,7 @@ class CustomerForm extends Form * * @var string */ - protected $customerAttribute = "[name='%s[]']"; + protected $customerAttribute = "[orig-name='%s[]']"; /** * Validation text message for a field. diff --git a/dev/tests/functional/tests/app/Magento/Newsletter/Test/Block/Adminhtml/Queue/Edit/QueueForm.xml b/dev/tests/functional/tests/app/Magento/Newsletter/Test/Block/Adminhtml/Queue/Edit/QueueForm.xml index c1970955013e8..4d2acc76c8703 100644 --- a/dev/tests/functional/tests/app/Magento/Newsletter/Test/Block/Adminhtml/Queue/Edit/QueueForm.xml +++ b/dev/tests/functional/tests/app/Magento/Newsletter/Test/Block/Adminhtml/Queue/Edit/QueueForm.xml @@ -11,7 +11,7 @@ <selector>input[name='start_at']</selector> </queue_start_at> <stores> - <selector>select[name="stores[]"]</selector> + <selector>select[name="stores[0]"]</selector> <input>multiselectgrouplist</input> </stores> <newsletter_subject> diff --git a/dev/tests/functional/tests/app/Magento/Reports/Test/Block/Adminhtml/Sales/Coupons/Filter.xml b/dev/tests/functional/tests/app/Magento/Reports/Test/Block/Adminhtml/Sales/Coupons/Filter.xml index d66c3b702f076..51809448e4edb 100644 --- a/dev/tests/functional/tests/app/Magento/Reports/Test/Block/Adminhtml/Sales/Coupons/Filter.xml +++ b/dev/tests/functional/tests/app/Magento/Reports/Test/Block/Adminhtml/Sales/Coupons/Filter.xml @@ -29,7 +29,7 @@ <input>select</input> </price_rule_type> <order_statuses> - <selector>[name="order_statuses[]"]</selector> + <selector>[name="order_statuses[0]"]</selector> <input>multiselect</input> </order_statuses> <rules_list> diff --git a/dev/tests/functional/tests/app/Magento/Reports/Test/Block/Adminhtml/Sales/TaxRule/Filter.xml b/dev/tests/functional/tests/app/Magento/Reports/Test/Block/Adminhtml/Sales/TaxRule/Filter.xml index 08e783e1329a4..5820de6772e1c 100644 --- a/dev/tests/functional/tests/app/Magento/Reports/Test/Block/Adminhtml/Sales/TaxRule/Filter.xml +++ b/dev/tests/functional/tests/app/Magento/Reports/Test/Block/Adminhtml/Sales/TaxRule/Filter.xml @@ -23,7 +23,7 @@ <input>select</input> </show_order_statuses> <order_statuses> - <selector>[name="order_statuses[]"]</selector> + <selector>[name="order_statuses[0]"]</selector> <input>multiselect</input> </order_statuses> <show_empty_rows> diff --git a/dev/tests/functional/tests/app/Magento/Review/Test/Block/Adminhtml/Rating/Edit/RatingForm.xml b/dev/tests/functional/tests/app/Magento/Review/Test/Block/Adminhtml/Rating/Edit/RatingForm.xml index 3e1a1c727c668..504ce64bf2a73 100644 --- a/dev/tests/functional/tests/app/Magento/Review/Test/Block/Adminhtml/Rating/Edit/RatingForm.xml +++ b/dev/tests/functional/tests/app/Magento/Review/Test/Block/Adminhtml/Rating/Edit/RatingForm.xml @@ -12,7 +12,7 @@ <strategy>css selector</strategy> <fields> <stores> - <selector>[name="stores[]"]</selector> + <selector>[name="stores[0]"]</selector> <input>multiselectgrouplist</input> </stores> <is_active> diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Report/Filter/Form.xml b/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Report/Filter/Form.xml index d868798eba79d..294f64966bde9 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Report/Filter/Form.xml +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Report/Filter/Form.xml @@ -26,7 +26,7 @@ <input>select</input> </show_order_statuses> <order_statuses> - <selector>[name="order_statuses[]"]</selector> + <selector>[name="order_statuses[0]"]</selector> <input>multiselect</input> </order_statuses> <show_actual_columns> diff --git a/dev/tests/functional/tests/app/Magento/Widget/Test/Block/Adminhtml/Widget/Instance/Edit/Tab/ParametersType/RecentlyComparedProducts.xml b/dev/tests/functional/tests/app/Magento/Widget/Test/Block/Adminhtml/Widget/Instance/Edit/Tab/ParametersType/RecentlyComparedProducts.xml index be353be8bf6be..9da96ab4c8fcc 100644 --- a/dev/tests/functional/tests/app/Magento/Widget/Test/Block/Adminhtml/Widget/Instance/Edit/Tab/ParametersType/RecentlyComparedProducts.xml +++ b/dev/tests/functional/tests/app/Magento/Widget/Test/Block/Adminhtml/Widget/Instance/Edit/Tab/ParametersType/RecentlyComparedProducts.xml @@ -12,13 +12,13 @@ </page_size> <show_attributes> <selector> - .control [name="parameters[show_attributes][]"] + .control [name="parameters[show_attributes][1]"] </selector> <input>multiselect</input> </show_attributes> <show_buttons> <selector> - .control [name="parameters[show_buttons][]"] + .control [name="parameters[show_buttons][2]"] </selector> <input>multiselect</input> </show_buttons> diff --git a/dev/tests/functional/tests/app/Magento/Widget/Test/Block/Adminhtml/Widget/Instance/Edit/Tab/ParametersType/RecentlyViewedProducts.xml b/dev/tests/functional/tests/app/Magento/Widget/Test/Block/Adminhtml/Widget/Instance/Edit/Tab/ParametersType/RecentlyViewedProducts.xml index be353be8bf6be..9da96ab4c8fcc 100644 --- a/dev/tests/functional/tests/app/Magento/Widget/Test/Block/Adminhtml/Widget/Instance/Edit/Tab/ParametersType/RecentlyViewedProducts.xml +++ b/dev/tests/functional/tests/app/Magento/Widget/Test/Block/Adminhtml/Widget/Instance/Edit/Tab/ParametersType/RecentlyViewedProducts.xml @@ -12,13 +12,13 @@ </page_size> <show_attributes> <selector> - .control [name="parameters[show_attributes][]"] + .control [name="parameters[show_attributes][1]"] </selector> <input>multiselect</input> </show_attributes> <show_buttons> <selector> - .control [name="parameters[show_buttons][]"] + .control [name="parameters[show_buttons][2]"] </selector> <input>multiselect</input> </show_buttons> diff --git a/dev/tests/functional/tests/app/Magento/Widget/Test/Block/Adminhtml/WidgetForm.xml b/dev/tests/functional/tests/app/Magento/Widget/Test/Block/Adminhtml/WidgetForm.xml index 0e13f4ccc995e..374b966861f6f 100644 --- a/dev/tests/functional/tests/app/Magento/Widget/Test/Block/Adminhtml/WidgetForm.xml +++ b/dev/tests/functional/tests/app/Magento/Widget/Test/Block/Adminhtml/WidgetForm.xml @@ -32,13 +32,13 @@ <page_size /> <show_attributes> <selector> - .control [name="parameters[show_attributes][]"] + .control [name="parameters[show_attributes][1]"] </selector> <input>multiselect</input> </show_attributes> <show_buttons> <selector> - .control [name="parameters[show_buttons][]"] + .control [name="parameters[show_buttons][2]"] </selector> <input>multiselect</input> </show_buttons> diff --git a/lib/web/mage/validation.js b/lib/web/mage/validation.js index e62de7c4d98ee..a4f9880511a62 100644 --- a/lib/web/mage/validation.js +++ b/lib/web/mage/validation.js @@ -1945,13 +1945,14 @@ * Before submitting the actual form, remove the previously assigned indices * @param {Object} form */ - this.options.submitHandler = function (form, event) { + this.options.submitHandler = function (form) { originalElements.forEach(function (element) { element.element.attr('name', element.name); element.element.removeAttr('orig-name'); }); - console.error(this.submit) + console.error(this.submit); + /* Call the originalSubmitHandler if it's a function */ typeof originalSubmitHandler === 'function' ? originalSubmitHandler(form) : form.submit(); }; @@ -1960,6 +1961,7 @@ /** * Validation listening. + * * @protected */ _listenFormValidate: function () { diff --git a/lib/web/mage/validation/validation.js b/lib/web/mage/validation/validation.js index 437c753d78c8b..69cb984b0d82d 100644 --- a/lib/web/mage/validation/validation.js +++ b/lib/web/mage/validation/validation.js @@ -50,11 +50,15 @@ function (value, element, params) { var checkedCount = 0, selector, - container; + container, + origNameSelector, + nameSelector; if (element.type === 'checkbox') { /* If orig-name attribute is present, use it for validation. Else use name */ - selector = element.getAttribute('orig-name') ? '[orig-name="' + element.getAttribute('orig-name') + '"]' : '[name="' + element.name + '"]'; + origNameSelector = '[orig-name="' + element.getAttribute('orig-name') + '"]'; + nameSelector = '[name="' + element.name + '"]'; + selector = element.getAttribute('orig-name') ? origNameSelector : nameSelector; $(selector).each(function () { if ($(this).is(':checked')) { checkedCount += 1; From 9e07d6e1e8118baa9638f6c3525806d0b1da3dd7 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Thu, 13 Jun 2019 14:39:01 +0300 Subject: [PATCH 469/773] magento/magento2#20918: Enabled 'Shopping Cart' tab for customer edit interface in admin. --- .../Customer/Model/CustomerIdProvider.php | 40 +++++++++++++++++++ .../Block/Adminhtml/ShoppingCartsTab.php | 22 +++++----- 2 files changed, 49 insertions(+), 13 deletions(-) create mode 100644 app/code/Magento/Customer/Model/CustomerIdProvider.php diff --git a/app/code/Magento/Customer/Model/CustomerIdProvider.php b/app/code/Magento/Customer/Model/CustomerIdProvider.php new file mode 100644 index 0000000000000..e670d5eb02d9c --- /dev/null +++ b/app/code/Magento/Customer/Model/CustomerIdProvider.php @@ -0,0 +1,40 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Customer\Model; + +use Magento\Framework\App\RequestInterface; + +/** + * Provides customer id from request. + */ +class CustomerIdProvider +{ + /** + * @var RequestInterface + */ + private $request; + + /** + * @param RequestInterface $request + */ + public function __construct( + RequestInterface $request + ) { + $this->request = $request; + } + + /** + * Get customer id from request. + * + * @return int + */ + public function getCustomerId(): int + { + return (int)$this->request->getParam('id'); + } +} diff --git a/app/code/Magento/Sales/Block/Adminhtml/ShoppingCartsTab.php b/app/code/Magento/Sales/Block/Adminhtml/ShoppingCartsTab.php index d0d2fef1f1d42..e1fedb13ab13a 100644 --- a/app/code/Magento/Sales/Block/Adminhtml/ShoppingCartsTab.php +++ b/app/code/Magento/Sales/Block/Adminhtml/ShoppingCartsTab.php @@ -6,7 +6,7 @@ namespace Magento\Sales\Block\Adminhtml; use Magento\Backend\Block\Template\Context; -use Magento\Customer\Controller\RegistryConstants; +use Magento\Customer\Model\CustomerIdProvider; use Magento\Framework\Registry; use Magento\Ui\Component\Layout\Tabs\TabWrapper; @@ -18,28 +18,24 @@ class ShoppingCartsTab extends TabWrapper { /** - * Core registry - * - * @var Registry + * @var bool */ - private $coreRegistry; + protected $isAjaxLoaded = true; /** - * @var bool + * @var CustomerIdProvider */ - protected $isAjaxLoaded = true; + private $customerIdProvider; /** - * Constructor - * * @param Context $context - * @param Registry $registry + * @param CustomerIdProvider $customerIdProvider * @param array $data */ - public function __construct(Context $context, Registry $registry, array $data = []) + public function __construct(Context $context, CustomerIdProvider $customerIdProvider, array $data = []) { - $this->coreRegistry = $registry; parent::__construct($context, $data); + $this->customerIdProvider = $customerIdProvider; } /** @@ -47,7 +43,7 @@ public function __construct(Context $context, Registry $registry, array $data = */ public function canShowTab() { - return $this->coreRegistry->registry(RegistryConstants::CURRENT_CUSTOMER_ID); + return $this->customerIdProvider->getCustomerId(); } /** From a05afc483061f1b20a2a2e640cec6f54e07db0fc Mon Sep 17 00:00:00 2001 From: Yaroslav Rogoza <enarc@atwix.com> Date: Thu, 13 Jun 2019 14:08:31 +0200 Subject: [PATCH 470/773] Inject store_id to context using extension attributes --- .../Magento/GraphQl/Controller/GraphQl.php | 24 +++++---- .../GraphQl/Model/Query/Resolver/Context.php | 13 +---- .../Model/Query/Resolver/ContextFactory.php | 35 ++++++++++++ .../Plugin/Query/Resolver/ContextFactory.php | 53 +++++++++++++++++++ .../StoreGraphQl/etc/extension_attributes.xml | 12 +++++ .../Magento/StoreGraphQl/etc/graphql/di.xml | 3 ++ .../Query/Resolver/ContextInterface.php | 8 --- 7 files changed, 117 insertions(+), 31 deletions(-) create mode 100644 app/code/Magento/GraphQl/Model/Query/Resolver/ContextFactory.php create mode 100644 app/code/Magento/StoreGraphQl/Model/Plugin/Query/Resolver/ContextFactory.php create mode 100644 app/code/Magento/StoreGraphQl/etc/extension_attributes.xml diff --git a/app/code/Magento/GraphQl/Controller/GraphQl.php b/app/code/Magento/GraphQl/Controller/GraphQl.php index 75b3ad277c603..ec46d78e2cb54 100644 --- a/app/code/Magento/GraphQl/Controller/GraphQl.php +++ b/app/code/Magento/GraphQl/Controller/GraphQl.php @@ -8,19 +8,19 @@ namespace Magento\GraphQl\Controller; use Magento\Framework\App\FrontControllerInterface; +use Magento\Framework\App\ObjectManager; use Magento\Framework\App\Request\Http; use Magento\Framework\App\RequestInterface; +use Magento\Framework\App\Response\Http as HttpResponse; use Magento\Framework\App\ResponseInterface; +use Magento\Framework\Controller\Result\JsonFactory; use Magento\Framework\GraphQl\Exception\ExceptionFormatter; +use Magento\Framework\GraphQl\Query\Fields as QueryFields; use Magento\Framework\GraphQl\Query\QueryProcessor; -use Magento\Framework\GraphQl\Query\Resolver\ContextInterface; use Magento\Framework\GraphQl\Schema\SchemaGeneratorInterface; use Magento\Framework\Serialize\SerializerInterface; use Magento\Framework\Webapi\Response; -use Magento\Framework\App\Response\Http as HttpResponse; -use Magento\Framework\GraphQl\Query\Fields as QueryFields; -use Magento\Framework\Controller\Result\JsonFactory; -use Magento\Framework\App\ObjectManager; +use Magento\GraphQl\Model\Query\Resolver\ContextFactory; /** * Front controller for web API GraphQL area. @@ -57,9 +57,9 @@ class GraphQl implements FrontControllerInterface private $graphQlError; /** - * @var ContextInterface + * @var ContextFactory */ - private $resolverContext; + private $resolverContextFactory; /** * @var HttpRequestProcessor @@ -87,7 +87,7 @@ class GraphQl implements FrontControllerInterface * @param SerializerInterface $jsonSerializer * @param QueryProcessor $queryProcessor * @param ExceptionFormatter $graphQlError - * @param ContextInterface $resolverContext + * @param ContextFactory $resolverContextFactory * @param HttpRequestProcessor $requestProcessor * @param QueryFields $queryFields * @param JsonFactory|null $jsonFactory @@ -100,7 +100,7 @@ public function __construct( SerializerInterface $jsonSerializer, QueryProcessor $queryProcessor, ExceptionFormatter $graphQlError, - ContextInterface $resolverContext, + ContextFactory $resolverContextFactory, HttpRequestProcessor $requestProcessor, QueryFields $queryFields, JsonFactory $jsonFactory = null, @@ -111,7 +111,7 @@ public function __construct( $this->jsonSerializer = $jsonSerializer; $this->queryProcessor = $queryProcessor; $this->graphQlError = $graphQlError; - $this->resolverContext = $resolverContext; + $this->resolverContextFactory = $resolverContextFactory; $this->requestProcessor = $requestProcessor; $this->queryFields = $queryFields; $this->jsonFactory = $jsonFactory ?: ObjectManager::getInstance()->get(JsonFactory::class); @@ -141,10 +141,12 @@ public function dispatch(RequestInterface $request) : ResponseInterface $this->queryFields->setQuery($query, $variables); $schema = $this->schemaGenerator->generate(); + $resolverContext = $this->resolverContextFactory->create(); + $result = $this->queryProcessor->process( $schema, $query, - $this->resolverContext, + $resolverContext, $data['variables'] ?? [] ); } catch (\Exception $error) { diff --git a/app/code/Magento/GraphQl/Model/Query/Resolver/Context.php b/app/code/Magento/GraphQl/Model/Query/Resolver/Context.php index 1b24fddd9a383..6fb065ed7dc95 100644 --- a/app/code/Magento/GraphQl/Model/Query/Resolver/Context.php +++ b/app/code/Magento/GraphQl/Model/Query/Resolver/Context.php @@ -138,17 +138,6 @@ public function setUserType(int $typeId) : ContextInterface */ public function getStoreId(): int { - if (null === $this->getData(self::STORE_ID)) { - $this->setStoreId((int)$this->storeManager->getStore()->getId()); - } - return $this->getData(self::STORE_ID); - } - - /** - * @inheritDoc - */ - public function setStoreId(int $storeId) : ContextInterface - { - return $this->setData(self::STORE_ID, $storeId); + return $this->getExtensionAttributes()->getStoreId(); } } diff --git a/app/code/Magento/GraphQl/Model/Query/Resolver/ContextFactory.php b/app/code/Magento/GraphQl/Model/Query/Resolver/ContextFactory.php new file mode 100644 index 0000000000000..898c677615afd --- /dev/null +++ b/app/code/Magento/GraphQl/Model/Query/Resolver/ContextFactory.php @@ -0,0 +1,35 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQl\Model\Query\Resolver; + +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\GraphQl\Query\Resolver\ContextInterface; + +class ContextFactory +{ + /** + * @var ObjectManagerInterface + */ + protected $objectManager; + + /** + * @param ObjectManagerInterface $objectManager + */ + public function __construct(ObjectManagerInterface $objectManager) + { + $this->objectManager = $objectManager; + } + + /** + * @return ContextInterface + */ + public function create() + { + return $this->objectManager->create(ContextInterface::class); + } +} diff --git a/app/code/Magento/StoreGraphQl/Model/Plugin/Query/Resolver/ContextFactory.php b/app/code/Magento/StoreGraphQl/Model/Plugin/Query/Resolver/ContextFactory.php new file mode 100644 index 0000000000000..8025a87c4d6c4 --- /dev/null +++ b/app/code/Magento/StoreGraphQl/Model/Plugin/Query/Resolver/ContextFactory.php @@ -0,0 +1,53 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\StoreGraphQl\Model\Plugin\Query\Resolver; + +use Magento\Framework\GraphQl\Query\Resolver\ContextInterface; +use Magento\Store\Model\StoreManagerInterface; +use Magento\GraphQl\Model\Query\Resolver\ContextFactory as ResolverContextFactory; +use Magento\Framework\Exception\NoSuchEntityException; + +/** + * Plugin for injecting store information into resolver context + */ +class ContextFactory +{ + /** + * @var StoreManagerInterface + */ + private $storeManager; + + /** + * @param StoreManagerInterface $storeManager + */ + public function __construct( + StoreManagerInterface $storeManager + ) { + $this->storeManager = $storeManager; + } + + + /** + * @param ResolverContextFactory $subject + * @param ContextInterface $resultContext + * @return ContextInterface + * + * @throws NoSuchEntityException + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function afterCreate( + ResolverContextFactory $subject, + ContextInterface $resultContext + ) { + $extensionAttributes = $resultContext->getExtensionAttributes(); + $extensionAttributes->setStoreId((int)$this->storeManager->getStore()->getId()); + $resultContext->setExtensionAttributes($extensionAttributes); + + return $resultContext; + } +} diff --git a/app/code/Magento/StoreGraphQl/etc/extension_attributes.xml b/app/code/Magento/StoreGraphQl/etc/extension_attributes.xml new file mode 100644 index 0000000000000..bad6906bc994a --- /dev/null +++ b/app/code/Magento/StoreGraphQl/etc/extension_attributes.xml @@ -0,0 +1,12 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Api/etc/extension_attributes.xsd"> + <extension_attributes for="Magento\Framework\GraphQl\Query\Resolver\ContextInterface"> + <attribute code="store_id" type="int" /> + </extension_attributes> +</config> diff --git a/app/code/Magento/StoreGraphQl/etc/graphql/di.xml b/app/code/Magento/StoreGraphQl/etc/graphql/di.xml index c2191164287f1..f9682354ac704 100644 --- a/app/code/Magento/StoreGraphQl/etc/graphql/di.xml +++ b/app/code/Magento/StoreGraphQl/etc/graphql/di.xml @@ -16,4 +16,7 @@ </argument> </arguments> </type> + <type name="Magento\GraphQl\Model\Query\Resolver\ContextFactory"> + <plugin name="add_store_id_to_resolver_context" type="Magento\StoreGraphQl\Model\Plugin\Query\Resolver\ContextFactory"/> + </type> </config> diff --git a/lib/internal/Magento/Framework/GraphQl/Query/Resolver/ContextInterface.php b/lib/internal/Magento/Framework/GraphQl/Query/Resolver/ContextInterface.php index 92726033a14c6..553d0f3e90d99 100644 --- a/lib/internal/Magento/Framework/GraphQl/Query/Resolver/ContextInterface.php +++ b/lib/internal/Magento/Framework/GraphQl/Query/Resolver/ContextInterface.php @@ -59,14 +59,6 @@ public function setUserId(int $userId) : ContextInterface; */ public function getStoreId() : int; - /** - * Set current store id - * - * @param int $storeId - * @return ContextInterface - */ - public function setStoreId(int $storeId) : ContextInterface; - /** * Retrieve existing extension attributes object or create a new one. * From bca244cbcf2365f0dafa02617117147e3b363ccf Mon Sep 17 00:00:00 2001 From: Sergii Ivashchenko <serg.ivashchenko@gmail.com> Date: Thu, 13 Jun 2019 13:27:52 +0100 Subject: [PATCH 471/773] magento/magento2#20918: Removed Registry from the use block --- app/code/Magento/Sales/Block/Adminhtml/ShoppingCartsTab.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/code/Magento/Sales/Block/Adminhtml/ShoppingCartsTab.php b/app/code/Magento/Sales/Block/Adminhtml/ShoppingCartsTab.php index e1fedb13ab13a..12d5d4360651a 100644 --- a/app/code/Magento/Sales/Block/Adminhtml/ShoppingCartsTab.php +++ b/app/code/Magento/Sales/Block/Adminhtml/ShoppingCartsTab.php @@ -7,7 +7,6 @@ use Magento\Backend\Block\Template\Context; use Magento\Customer\Model\CustomerIdProvider; -use Magento\Framework\Registry; use Magento\Ui\Component\Layout\Tabs\TabWrapper; /** From 447aac06a052d8333ee26d6c0115591e712ef982 Mon Sep 17 00:00:00 2001 From: trr <t.ritter@imi.de> Date: Fri, 14 Jun 2019 17:35:28 +0200 Subject: [PATCH 472/773] hide or show the select for regions instead of enabling/disabling in customer registration --- .../view/frontend/web/js/region-updater.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/app/code/Magento/Checkout/view/frontend/web/js/region-updater.js b/app/code/Magento/Checkout/view/frontend/web/js/region-updater.js index cf2a59cdba427..80481826260ff 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/region-updater.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/region-updater.js @@ -157,7 +157,7 @@ define([ regionInput = $(this.options.regionInputId), postcode = $(this.options.postcodeId), label = regionList.parent().siblings('label'), - requiredLabel = regionList.parents('div.field'); + container = regionList.parents('div.field'); this._clearError(); this._checkRegionRequired(country); @@ -181,15 +181,16 @@ define([ if (this.options.isRegionRequired) { regionList.addClass('required-entry').removeAttr('disabled'); - requiredLabel.addClass('required'); + container.addClass('required').show(); } else { regionList.removeClass('required-entry validate-select').removeAttr('data-validate'); - requiredLabel.removeClass('required'); + container.removeClass('required'); if (!this.options.optionalRegionAllowed) { //eslint-disable-line max-depth - regionList.attr('disabled', 'disabled'); + regionList.hide(); + container.hide(); } else { - regionList.removeAttr('disabled'); + regionList.show(); } } @@ -201,12 +202,13 @@ define([ if (this.options.isRegionRequired) { regionInput.addClass('required-entry').removeAttr('disabled'); - requiredLabel.addClass('required'); + container.addClass('required').show(); } else { if (!this.options.optionalRegionAllowed) { //eslint-disable-line max-depth regionInput.attr('disabled', 'disabled'); + container.hide(); } - requiredLabel.removeClass('required'); + container.removeClass('required'); regionInput.removeClass('required-entry'); } From 139a265bf7364c2e9b110d83f64a08f8b49949b8 Mon Sep 17 00:00:00 2001 From: Maria Kovdrysh <kovdrysh@adobe.com> Date: Sun, 16 Jun 2019 12:23:12 -0500 Subject: [PATCH 473/773] MC-6436: Configuring Instant Purchase functionality --- .../Test/Mftf/Data/BraintreeData.xml | 4 + ...tStorefrontElementInvisibleActionGroup.xml | 17 ++ ...guringInstantPurchaseFunctionalityTest.xml | 252 ++++++++++++++++++ ...StorefrontCustomerSavedCardActionGroup.xml | 18 ++ ...ontStoredPaymentMethodsPageActionGroup.xml | 14 + ...efrontCustomerStoredPaymentMethodsPage.xml | 14 + ...ontCustomerStoredPaymentMethodsSection.xml | 15 ++ ...geInstantPurchaseButtonTextActionGroup.xml | 21 ++ ...ChangeInstantPurchaseStatusActionGroup.xml | 21 ++ ...enInstantPurchaseConfigPageActionGroup.xml | 14 + .../AdminSystemConfigInstantPurchasePage.xml | 13 + .../AdminInstantPurchaseConfigSection.xml | 18 ++ .../StorefrontInstantPurchasePopupSection.xml | 15 ++ .../StorefrontInstantPurchaseSection.xml | 15 ++ 14 files changed, 451 insertions(+) create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontElementInvisibleActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/Test/ConfiguringInstantPurchaseFunctionalityTest.xml create mode 100644 app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertStorefrontCustomerSavedCardActionGroup.xml create mode 100644 app/code/Magento/Customer/Test/Mftf/ActionGroup/OpenStorefrontStoredPaymentMethodsPageActionGroup.xml create mode 100644 app/code/Magento/Customer/Test/Mftf/Page/StorefrontCustomerStoredPaymentMethodsPage.xml create mode 100644 app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerStoredPaymentMethodsSection.xml create mode 100644 app/code/Magento/InstantPurchase/Test/Mftf/ActionGroup/AdminChangeInstantPurchaseButtonTextActionGroup.xml create mode 100644 app/code/Magento/InstantPurchase/Test/Mftf/ActionGroup/AdminChangeInstantPurchaseStatusActionGroup.xml create mode 100644 app/code/Magento/InstantPurchase/Test/Mftf/ActionGroup/AdminOpenInstantPurchaseConfigPageActionGroup.xml create mode 100644 app/code/Magento/InstantPurchase/Test/Mftf/Page/AdminSystemConfigInstantPurchasePage.xml create mode 100644 app/code/Magento/InstantPurchase/Test/Mftf/Section/AdminInstantPurchaseConfigSection.xml create mode 100644 app/code/Magento/InstantPurchase/Test/Mftf/Section/StorefrontInstantPurchasePopupSection.xml create mode 100644 app/code/Magento/InstantPurchase/Test/Mftf/Section/StorefrontInstantPurchaseSection.xml diff --git a/app/code/Magento/Braintree/Test/Mftf/Data/BraintreeData.xml b/app/code/Magento/Braintree/Test/Mftf/Data/BraintreeData.xml index f00e3fa286b08..6d00df535704a 100644 --- a/app/code/Magento/Braintree/Test/Mftf/Data/BraintreeData.xml +++ b/app/code/Magento/Braintree/Test/Mftf/Data/BraintreeData.xml @@ -138,6 +138,10 @@ <data key="year">20</data> <data key="cvv">113</data> </entity> + <entity name="StoredPaymentMethods"> + <data key="cardNumberEnding">5100</data> + <data key="cardExpire">12/2020</data> + </entity> <entity name="BraintreeConfigurationData" type="data"> <data key="title">Credit Card (Braintree)</data> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontElementInvisibleActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontElementInvisibleActionGroup.xml new file mode 100644 index 0000000000000..69fe27ff07460 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontElementInvisibleActionGroup.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AssertStorefrontElementInvisibleActionGroup"> + <arguments> + <argument name="selector" type="string"/> + <argument name="userInput" type="string"/> + </arguments> + <dontSee selector="{{selector}}" userInput="{{userInput}}" stepKey="dontSeeElement"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/ConfiguringInstantPurchaseFunctionalityTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/ConfiguringInstantPurchaseFunctionalityTest.xml new file mode 100644 index 0000000000000..6d7ecc2ef9903 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/Test/ConfiguringInstantPurchaseFunctionalityTest.xml @@ -0,0 +1,252 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="ConfiguringInstantPurchaseFunctionalityTest"> + <annotations> + <features value="One Page Checkout"/> + <stories value="Configuring instant purchase"/> + <title value="Configuring instant purchase functionality test"/> + <description value="Configuring instant purchase"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-6436"/> + <group value="checkout"/> + </annotations> + <before> + <!-- Configure Braintree Vault-enabled payment method --> + <createData entity="BraintreeConfig" stepKey="braintreeConfigurationData"/> + <createData entity="CustomBraintreeConfigurationData" stepKey="enableBraintree"/> + + <!-- Create customer --> + <createData entity="Simple_US_Customer" stepKey="createCustomer"/> + + <!-- Create product --> + <createData entity="SimpleProduct2" stepKey="createProduct"/> + + <!-- Login as admin --> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + + <!-- Create store views --> + <actionGroup ref="AdminCreateStoreViewActionGroup" stepKey="createFirstStoreView"> + <argument name="customStore" value="storeViewData1"/> + </actionGroup> + <actionGroup ref="AdminCreateStoreViewActionGroup" stepKey="createSecondStoreView"> + <argument name="customStore" value="storeViewData2"/> + </actionGroup> + </before> + <after> + <!-- Set configs to default --> + <createData entity="DefaultBraintreeConfig" stepKey="defaultBraintreeConfig"/> + <createData entity="RollBackCustomBraintreeConfigurationData" stepKey="rollBackCustomBraintreeConfigurationData"/> + + <!-- Delete product --> + <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> + + <!-- Delete customer --> + <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> + + <!-- Delete store views --> + <actionGroup ref="AdminDeleteStoreViewActionGroup" stepKey="deleteFirstStoreView"> + <argument name="customStore" value="storeViewData1"/> + </actionGroup> + <actionGroup ref="AdminDeleteStoreViewActionGroup" stepKey="deleteSecondStoreView"> + <argument name="customStore" value="storeViewData2"/> + </actionGroup> + + <!-- Admin logout --> + <actionGroup ref="logout" stepKey="adminLogout"/> + </after> + + <!-- Login to Frontend --> + <actionGroup ref="LoginToStorefrontActionGroup" stepKey="loginAsCustomer"> + <argument name="Customer" value="$$createCustomer$$"/> + </actionGroup> + + <!-- Add product to cart --> + <actionGroup ref="AddSimpleProductToCart" stepKey="addProductToCart"> + <argument name="product" value="$$createProduct$$"/> + </actionGroup> + <actionGroup ref="GoToCheckoutFromMinicartActionGroup" stepKey="goToCheckoutFromMinicart"/> + + <!-- Customer placed order with payment method save --> + <waitForElement selector="{{CheckoutShippingMethodsSection.next}}" stepKey="waitForNextButton"/> + <click selector="{{CheckoutShippingMethodsSection.next}}" stepKey="clickNext"/> + <waitForElement selector="{{CheckoutPaymentSection.paymentSectionTitle}}" stepKey="waitForPaymentSectionLoaded"/> + + <!-- Fill Braintree cart data --> + <click selector="{{BraintreeConfigurationPaymentSection.creditCart}}" stepKey="selectBraintreePaymentMethod"/> + <waitForPageLoad stepKey="waitForBraintreeFormLoad"/> + <scrollTo selector="{{BraintreeConfigurationPaymentSection.creditCart}}" stepKey="scrollToCreditCardSection"/> + <actionGroup ref="StorefrontFillCartDataActionGroup" stepKey="fillCartData"/> + <waitForPageLoad stepKey="waitForFillCartData"/> + + <!-- Place order --> + <click selector="{{BraintreeConfigurationPaymentSection.paymentMethodContainer}}{{CheckoutPaymentSection.placeOrder}}" stepKey="checkoutPlaceOrder"/> + <waitForPageLoad stepKey="waitForPageLoad"/> + <see selector="{{CheckoutSuccessMainSection.successTitle}}" userInput="Thank you for your purchase!" stepKey="waitForLoadSuccessPage"/> + + <!-- Go to Configuration > Sales --> + <actionGroup ref="AdminOpenInstantPurchaseConfigPageActionGroup" stepKey="openInstantPurchaseConfigPage"/> + + <!-- Enable Instant Purchase --> + <actionGroup ref="AdminChangeInstantPurchaseStatusActionGroup" stepKey="enableInstantPurchase"/> + + <!-- Switch to specific store view --> + <actionGroup ref="AdminSwitchStoreViewActionGroup" stepKey="switchToSpecificStoreView"> + <argument name="storeView" value="storeViewData1.name"/> + </actionGroup> + + <!-- Change button text on a single store view --> + <actionGroup ref="AdminChangeInstantPurchaseButtonTextActionGroup" stepKey="changeInstantPurchaseButtonText"> + <argument name="buttonText" value="Quick Buy"/> + </actionGroup> + + <!-- Verify changes on the front-end by opening a simple product as a logged in customer with saved card and address on given store view: + 1. Go to Storefront page --> + <actionGroup ref="StorefrontOpenHomePageActionGroup" stepKey="openStorefrontPage"/> + + <!-- 2. Switch store view --> + <actionGroup ref="StorefrontSwitchStoreViewActionGroup" stepKey="SwitchStoreView"> + <argument name="storeView" value="storeViewData1"/> + </actionGroup> + + <!-- 3. Assert customer is logged with saved card with address --> + <actionGroup ref="OpenStorefrontCustomerStoredPaymentMethodsPageActionGroup" stepKey="openStorefrontCustomerStoredPaymentMethodsPage"/> + <actionGroup ref="AssertStorefrontCustomerSavedCardActionGroup" stepKey="assertCustomerPaymentMethod"/> + <actionGroup ref="StorefrontCustomerGoToSidebarMenu" stepKey="goToAddressBook"> + <argument name="menu" value="Address Book"/> + </actionGroup> + <see selector="{{CheckoutOrderSummarySection.shippingAddress}}" userInput="{{US_Address_TX.street[0]}} {{US_Address_TX.city}}, {{US_Address_TX.state}}, {{US_Address_TX.postcode}}" stepKey="checkShippingAddress"/> + + <!-- Open product page --> + <actionGroup ref="StorefrontOpenProductPageActionGroup" stepKey="openProductPage"> + <argument name="productUrl" value="$$createProduct.custom_attributes[url_key]$$"/> + </actionGroup> + + <!-- Quick Buy button shows up. Clicking it opens review popup --> + <actionGroup ref="AssertStorefrontElementVisibleActionGroup" stepKey="seeQuickBuyButton"> + <argument name="selector" value="{{StorefrontInstantPurchaseSection.instantPurchaseButton}}"/> + <argument name="userInput" value="Quick Buy"/> + </actionGroup> + <click selector="{{StorefrontInstantPurchaseSection.instantPurchaseButton}}" stepKey="clickQuickBuyButton"/> + <waitForElementVisible selector="{{StorefrontInstantPurchasePopupSection.modalTitle}}" stepKey="waitForPopUpTitleVisible"/> + <see selector="{{StorefrontInstantPurchasePopupSection.modalTitle}}" userInput="Instant Purchase Confirmation" stepKey="seeReviewPopUp"/> + <click selector="{{StorefrontInstantPurchasePopupSection.cancel}}" stepKey="closeModalPopup"/> + <waitForPageLoad stepKey="waitForClosing"/> + + <!-- Verify changes on the front-end by opening a simple product as a logged in customer with saved card and address on a store view for which description was not changed + 1. New customer session should be started to verify changes --> + <actionGroup ref="StorefrontSignOutActionGroup" stepKey="customerLogout"/> + <actionGroup ref="LoginToStorefrontActionGroup" stepKey="loginCustomer"> + <argument name="Customer" value="$$createCustomer$$"/> + </actionGroup> + + <!-- 2. Switch store view which description was not changed --> + <actionGroup ref="StorefrontSwitchStoreViewActionGroup" stepKey="SwitchToSecondStoreView"> + <argument name="storeView" value="storeViewData2"/> + </actionGroup> + + <!-- 3. Assert customer is logged with saved card and address --> + <actionGroup ref="OpenStorefrontCustomerStoredPaymentMethodsPageActionGroup" stepKey="openStorefrontCustomerPaymentMethodsPage"/> + <actionGroup ref="AssertStorefrontCustomerSavedCardActionGroup" stepKey="assertPaymentMethod"/> + <actionGroup ref="StorefrontCustomerGoToSidebarMenu" stepKey="openAddressBook"> + <argument name="menu" value="Address Book"/> + </actionGroup> + <see selector="{{CheckoutOrderSummarySection.shippingAddress}}" userInput="{{US_Address_TX.street[0]}} {{US_Address_TX.city}}, {{US_Address_TX.state}}, {{US_Address_TX.postcode}}" stepKey="seeShippingAddress"/> + + <!-- Open product page --> + <actionGroup ref="StorefrontOpenProductPageActionGroup" stepKey="openCreatedProductPage"> + <argument name="productUrl" value="$$createProduct.custom_attributes[url_key]$$"/> + </actionGroup> + + <!-- Instant Purchase button shows up. Clicking it opens review popup. --> + <actionGroup ref="AssertStorefrontElementVisibleActionGroup" stepKey="seeInstantPurchaseButton"> + <argument name="selector" value="{{StorefrontInstantPurchaseSection.instantPurchaseButton}}"/> + <argument name="userInput" value="Instant Purchase"/> + </actionGroup> + <click selector="{{StorefrontInstantPurchaseSection.instantPurchaseButton}}" stepKey="clickInstantPurchaseButton"/> + <waitForElementVisible selector="{{StorefrontInstantPurchasePopupSection.modalTitle}}" stepKey="waitForPopUpVisible"/> + <see selector="{{StorefrontInstantPurchasePopupSection.modalTitle}}" userInput="Instant Purchase Confirmation" stepKey="seeReviewPopUpTitle"/> + <click selector="{{StorefrontInstantPurchasePopupSection.cancel}}" stepKey="closeModalPopUp"/> + <waitForPageLoad stepKey="waitForModalClosing"/> + + <actionGroup ref="StorefrontSignOutActionGroup" stepKey="createdCustomerLogout"/> + + <!-- Return to configuration and disable Instant Purchase in a specific store view --> + <actionGroup ref="AdminOpenInstantPurchaseConfigPageActionGroup" stepKey="openInstantPurchasePage"/> + <scrollToTopOfPage stepKey="scrollToTop"/> + <actionGroup ref="AdminSwitchStoreViewActionGroup" stepKey="switchToFirstSpecificStoreView"> + <argument name="storeView" value="storeViewData1.name"/> + </actionGroup> + <actionGroup ref="AdminChangeInstantPurchaseStatusActionGroup" stepKey="disableInstantPurchase"> + <argument name="status" value="0"/> + </actionGroup> + + <!-- Verify changes on the front-end by opening a simple product as a logged in customer with saved card and address in the specific store view + 1. New customer session should be started to verify changes --> + <actionGroup ref="LoginToStorefrontActionGroup" stepKey="loginAsCreatedCustomer"> + <argument name="Customer" value="$$createCustomer$$"/> + </actionGroup> + + <!-- 2. Switch store view --> + <actionGroup ref="StorefrontSwitchStoreViewActionGroup" stepKey="switchStoreView"> + <argument name="storeView" value="storeViewData1"/> + </actionGroup> + + <!-- 3. Assert customer is logged with saved card and address --> + <actionGroup ref="OpenStorefrontCustomerStoredPaymentMethodsPageActionGroup" stepKey="openCustomerPaymentMethodsPage"/> + <actionGroup ref="AssertStorefrontCustomerSavedCardActionGroup" stepKey="assertCartPaymentMethod"/> + <actionGroup ref="StorefrontCustomerGoToSidebarMenu" stepKey="goToAddressBookPage"> + <argument name="menu" value="Address Book"/> + </actionGroup> + <see selector="{{CheckoutOrderSummarySection.shippingAddress}}" userInput="{{US_Address_TX.street[0]}} {{US_Address_TX.city}}, {{US_Address_TX.state}}, {{US_Address_TX.postcode}}" stepKey="assertCustomerShippingAddress"/> + + <!-- Open product page --> + <actionGroup ref="StorefrontOpenProductPageActionGroup" stepKey="openProductIndexPage"> + <argument name="productUrl" value="$$createProduct.custom_attributes[url_key]$$"/> + </actionGroup> + + <!-- Quick Buy button is not visible --> + <actionGroup ref="AssertStorefrontElementInvisibleActionGroup" stepKey="dontSeeQuickBuyButton"> + <argument name="selector" value="{{StorefrontInstantPurchaseSection.instantPurchaseButton}}"/> + <argument name="userInput" value="Quick Buy"/> + </actionGroup> + + <!-- Verify changes on the front-end by opening a simple product as a logged in customer with saved card and address in the other store view + 1. New customer session should be started to verify changes --> + <actionGroup ref="StorefrontSignOutActionGroup" stepKey="logoutCustomer"/> + <actionGroup ref="LoginToStorefrontActionGroup" stepKey="customerLoginToStorefront"> + <argument name="Customer" value="$$createCustomer$$"/> + </actionGroup> + + <!-- 2. Switch store view --> + <actionGroup ref="StorefrontSwitchStoreViewActionGroup" stepKey="switchToSecondStoreView"> + <argument name="storeView" value="storeViewData2"/> + </actionGroup> + + <!-- 3. Assert customer is logged with saved card and address --> + <actionGroup ref="OpenStorefrontCustomerStoredPaymentMethodsPageActionGroup" stepKey="goToStorefrontCustomerPaymentMethodsPage"/> + <actionGroup ref="AssertStorefrontCustomerSavedCardActionGroup" stepKey="assertCardPaymentMethod"/> + <actionGroup ref="StorefrontCustomerGoToSidebarMenu" stepKey="openAddressBookPage"> + <argument name="menu" value="Address Book"/> + </actionGroup> + <see selector="{{CheckoutOrderSummarySection.shippingAddress}}" userInput="{{US_Address_TX.street[0]}} {{US_Address_TX.city}}, {{US_Address_TX.state}}, {{US_Address_TX.postcode}}" stepKey="seeCustomerShippingAddress"/> + + <!-- Open product page --> + <actionGroup ref="StorefrontOpenProductPageActionGroup" stepKey="goToProductPage"> + <argument name="productUrl" value="$$createProduct.custom_attributes[url_key]$$"/> + </actionGroup> + + <!-- Instant Purchase button is still visible --> + <actionGroup ref="AssertStorefrontElementVisibleActionGroup" stepKey="seeInstantPurchaseBtn"> + <argument name="selector" value="{{StorefrontInstantPurchaseSection.instantPurchaseButton}}"/> + <argument name="userInput" value="Instant Purchase"/> + </actionGroup> + </test> +</tests> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertStorefrontCustomerSavedCardActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertStorefrontCustomerSavedCardActionGroup.xml new file mode 100644 index 0000000000000..94cd759e5cef5 --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertStorefrontCustomerSavedCardActionGroup.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AssertStorefrontCustomerSavedCardActionGroup"> + <arguments> + <argument name="card" type="entity" defaultValue="StoredPaymentMethods"/> + </arguments> + <see selector="{{StorefrontCustomerStoredPaymentMethodsSection.cardNumber}}" userInput="{{card.cardNumberEnding}}" stepKey="verifyCardNumber"/> + <see selector="{{StorefrontCustomerStoredPaymentMethodsSection.expirationDate}}" userInput="{{card.cardExpire}}" stepKey="verifyCardExpire"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/OpenStorefrontStoredPaymentMethodsPageActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/OpenStorefrontStoredPaymentMethodsPageActionGroup.xml new file mode 100644 index 0000000000000..9975431e9fe6e --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/OpenStorefrontStoredPaymentMethodsPageActionGroup.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="OpenStorefrontCustomerStoredPaymentMethodsPageActionGroup"> + <amOnPage url="{{StorefrontCustomerStoredPaymentMethodsPage.url}}" stepKey="goToCustomerStoredPaymentMethodsPage"/> + <waitForPageLoad stepKey="waitForCustomerStoredPaymentMethodsPageLoad"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/Page/StorefrontCustomerStoredPaymentMethodsPage.xml b/app/code/Magento/Customer/Test/Mftf/Page/StorefrontCustomerStoredPaymentMethodsPage.xml new file mode 100644 index 0000000000000..bec802689a6cc --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/Page/StorefrontCustomerStoredPaymentMethodsPage.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<pages xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/PageObject.xsd"> + <page name="StorefrontCustomerStoredPaymentMethodsPage" url="/vault/cards/listaction/" area="storefront" module="Magento_Customer"> + <section name="StorefrontCustomerStoredPaymentMethodsSection"/> + </page> +</pages> diff --git a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerStoredPaymentMethodsSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerStoredPaymentMethodsSection.xml new file mode 100644 index 0000000000000..d6b586e42f28c --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerStoredPaymentMethodsSection.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="StorefrontCustomerStoredPaymentMethodsSection"> + <element name="cardNumber" type="text" selector="td.card-number"/> + <element name="expirationDate" type="text" selector="td.card-expire"/> + </section> +</sections> diff --git a/app/code/Magento/InstantPurchase/Test/Mftf/ActionGroup/AdminChangeInstantPurchaseButtonTextActionGroup.xml b/app/code/Magento/InstantPurchase/Test/Mftf/ActionGroup/AdminChangeInstantPurchaseButtonTextActionGroup.xml new file mode 100644 index 0000000000000..b8dda76d87107 --- /dev/null +++ b/app/code/Magento/InstantPurchase/Test/Mftf/ActionGroup/AdminChangeInstantPurchaseButtonTextActionGroup.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminChangeInstantPurchaseButtonTextActionGroup"> + <arguments> + <argument name="buttonText" type="string" defaultValue="Instant Purchase"/> + </arguments> + <conditionalClick selector="{{AdminInstantPurchaseConfigSection.salesInstantPurchaseTab}}" dependentSelector="{{AdminInstantPurchaseConfigSection.salesInstantPurchaseButtonText}}" visible="false" stepKey="expandTab"/> + <click selector="{{AdminInstantPurchaseConfigSection.salesInstantPurchaseButtonTextUseWebsite}}" stepKey="clickUseWebsite"/> + <fillField selector="{{AdminInstantPurchaseConfigSection.salesInstantPurchaseButtonText}}" userInput="{{buttonText}}" stepKey="changeInstantPurchaseButtonText"/> + <click selector="{{AdminConfigSection.saveButton}}" stepKey="saveConfigs"/> + <waitForPageLoad stepKey="waitForPageLoad"/> + <see selector="{{AdminCategoryMessagesSection.SuccessMessage}}" userInput="You saved the configuration." stepKey="seeSuccessMessage"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/InstantPurchase/Test/Mftf/ActionGroup/AdminChangeInstantPurchaseStatusActionGroup.xml b/app/code/Magento/InstantPurchase/Test/Mftf/ActionGroup/AdminChangeInstantPurchaseStatusActionGroup.xml new file mode 100644 index 0000000000000..ce13ddb46fbcd --- /dev/null +++ b/app/code/Magento/InstantPurchase/Test/Mftf/ActionGroup/AdminChangeInstantPurchaseStatusActionGroup.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminChangeInstantPurchaseStatusActionGroup"> + <arguments> + <argument name="status" type="string" defaultValue="1"/> + </arguments> + <conditionalClick selector="{{AdminInstantPurchaseConfigSection.salesInstantPurchaseTab}}" dependentSelector="{{AdminInstantPurchaseConfigSection.salesInstantPurchaseActive}}" visible="false" stepKey="expandTab"/> + <uncheckOption selector="{{AdminInstantPurchaseConfigSection.salesInstantPurchaseActiveUseWebsite}}" stepKey="uncheckUseSystemValue"/> + <selectOption selector="{{AdminInstantPurchaseConfigSection.salesInstantPurchaseActive}}" userInput="{{status}}" stepKey="changeInstantPurchaseStatus"/> + <click selector="{{AdminConfigSection.saveButton}}" stepKey="saveConfigs"/> + <waitForPageLoad stepKey="waitForPageLoad"/> + <see selector="{{AdminCategoryMessagesSection.SuccessMessage}}" userInput="You saved the configuration." stepKey="seeSuccessMessage"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/InstantPurchase/Test/Mftf/ActionGroup/AdminOpenInstantPurchaseConfigPageActionGroup.xml b/app/code/Magento/InstantPurchase/Test/Mftf/ActionGroup/AdminOpenInstantPurchaseConfigPageActionGroup.xml new file mode 100644 index 0000000000000..e25e5271dffd4 --- /dev/null +++ b/app/code/Magento/InstantPurchase/Test/Mftf/ActionGroup/AdminOpenInstantPurchaseConfigPageActionGroup.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminOpenInstantPurchaseConfigPageActionGroup"> + <amOnPage url="{{AdminSystemConfigInstantPurchasePage.url}}" stepKey="openInstantPurchaseConfigPage"/> + <waitForPageLoad stepKey="waitForInstantPurchasePageLoad"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/InstantPurchase/Test/Mftf/Page/AdminSystemConfigInstantPurchasePage.xml b/app/code/Magento/InstantPurchase/Test/Mftf/Page/AdminSystemConfigInstantPurchasePage.xml new file mode 100644 index 0000000000000..669172c6c4bbe --- /dev/null +++ b/app/code/Magento/InstantPurchase/Test/Mftf/Page/AdminSystemConfigInstantPurchasePage.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<pages xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/PageObject.xsd"> + <page name="AdminSystemConfigInstantPurchasePage" url="admin/system_config/edit/section/sales/#sales_instant_purchase-head" area="admin" module="Magento_GiftWrapping"> + </page> +</pages> diff --git a/app/code/Magento/InstantPurchase/Test/Mftf/Section/AdminInstantPurchaseConfigSection.xml b/app/code/Magento/InstantPurchase/Test/Mftf/Section/AdminInstantPurchaseConfigSection.xml new file mode 100644 index 0000000000000..5b1c191d228c1 --- /dev/null +++ b/app/code/Magento/InstantPurchase/Test/Mftf/Section/AdminInstantPurchaseConfigSection.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="AdminInstantPurchaseConfigSection"> + <element name="salesInstantPurchaseTab" type="button" selector="#sales_instant_purchase-head"/> + <element name="salesInstantPurchaseActive" type="select" selector="#sales_instant_purchase_active"/> + <element name="salesInstantPurchaseActiveUseWebsite" type="select" selector="#sales_instant_purchase_active_inherit"/> + <element name="salesInstantPurchaseButtonText" type="text" selector="#sales_instant_purchase_button_text"/> + <element name="salesInstantPurchaseButtonTextUseWebsite" type="checkbox" selector="#sales_instant_purchase_button_text_inherit"/> + </section> +</sections> diff --git a/app/code/Magento/InstantPurchase/Test/Mftf/Section/StorefrontInstantPurchasePopupSection.xml b/app/code/Magento/InstantPurchase/Test/Mftf/Section/StorefrontInstantPurchasePopupSection.xml new file mode 100644 index 0000000000000..8e93d049ea141 --- /dev/null +++ b/app/code/Magento/InstantPurchase/Test/Mftf/Section/StorefrontInstantPurchasePopupSection.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="StorefrontInstantPurchasePopupSection"> + <element name="modalTitle" type="text" selector=".modal-popup .modal-title"/> + <element name="cancel" type="button" selector=".modal-popup.confirm button.action-dismiss"/> + </section> +</sections> diff --git a/app/code/Magento/InstantPurchase/Test/Mftf/Section/StorefrontInstantPurchaseSection.xml b/app/code/Magento/InstantPurchase/Test/Mftf/Section/StorefrontInstantPurchaseSection.xml new file mode 100644 index 0000000000000..1124fe0aa7996 --- /dev/null +++ b/app/code/Magento/InstantPurchase/Test/Mftf/Section/StorefrontInstantPurchaseSection.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="StorefrontInstantPurchaseSection"> + <element name="instantPurchaseButton" type="button" selector="button.instant-purchase"/> + <element name="instantPurchaseButtonName" type="text" selector="button.instant-purchase span"/> + </section> +</sections> From 0db89b2dd4645827dc05536af0bbfc17db7b0a43 Mon Sep 17 00:00:00 2001 From: Jeroen Boersma <jeroen@elgentos.nl> Date: Mon, 17 Jun 2019 15:09:47 +0000 Subject: [PATCH 474/773] Removed unused parameter from constructor --- .../Magento/Developer/Model/XmlCatalog/Format/PhpStorm.php | 6 ------ 1 file changed, 6 deletions(-) diff --git a/app/code/Magento/Developer/Model/XmlCatalog/Format/PhpStorm.php b/app/code/Magento/Developer/Model/XmlCatalog/Format/PhpStorm.php index 1ced906cce763..8f8fdd0f5991d 100644 --- a/app/code/Magento/Developer/Model/XmlCatalog/Format/PhpStorm.php +++ b/app/code/Magento/Developer/Model/XmlCatalog/Format/PhpStorm.php @@ -18,10 +18,6 @@ */ class PhpStorm implements FormatInterface { - /** - * @var ReadInterface - */ - private $currentDirRead; /** * @var WriteFactory @@ -39,11 +35,9 @@ class PhpStorm implements FormatInterface * @param DomDocumentFactory $domDocumentFactory */ public function __construct( - ReadFactory $readFactory, WriteFactory $fileWriteFactory, DomDocumentFactory $domDocumentFactory = null ) { - $this->currentDirRead = $readFactory->create(getcwd()); $this->fileWriteFactory = $fileWriteFactory; $this->domDocumentFactory = $domDocumentFactory ?: ObjectManager::getInstance()->get(DomDocumentFactory::class); } From 767af1fa97ad35c6c41a96ea629d38035ccd6ad9 Mon Sep 17 00:00:00 2001 From: Jeroen Boersma <jeroen@elgentos.nl> Date: Mon, 17 Jun 2019 15:11:24 +0000 Subject: [PATCH 475/773] Resolve $PROJECT_DIR$ when generating PHPStorm xml --- .../Model/XmlCatalog/Format/PhpStorm.php | 29 ++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Developer/Model/XmlCatalog/Format/PhpStorm.php b/app/code/Magento/Developer/Model/XmlCatalog/Format/PhpStorm.php index 8f8fdd0f5991d..e70fc499915e1 100644 --- a/app/code/Magento/Developer/Model/XmlCatalog/Format/PhpStorm.php +++ b/app/code/Magento/Developer/Model/XmlCatalog/Format/PhpStorm.php @@ -18,6 +18,8 @@ */ class PhpStorm implements FormatInterface { + const PROJECT_PATH_IDENTIFIER = '$PROJECT_DIR$'; + const IDEA_PATH = '.idea'; /** * @var WriteFactory @@ -54,6 +56,8 @@ public function generateCatalog(array $dictionary, $configFilePath) $componentNode = null; $projectNode = null; + $ideaDir = $this->resolveProjectPath($configFilePath); + try { $file = $this->fileWriteFactory->create( $configFilePath, @@ -89,7 +93,7 @@ public function generateCatalog(array $dictionary, $configFilePath) foreach ($dictionary as $urn => $xsdPath) { $node = $dom->createElement('resource'); $node->setAttribute('url', $urn); - $node->setAttribute('location', $xsdPath); + $node->setAttribute('location', $this->getFileLocationInProject($ideaDir, $xsdPath)); $componentNode->appendChild($node); } $dom->formatOutput = true; @@ -123,4 +127,27 @@ private function initEmptyFile(\DOMDocument $dom) $projectNode->appendChild($rootComponentNode); return $projectNode; } + + /** + * Resolve PhpStorm Project Path + * + * @param string $configFilePath + * @return string + */ + public function resolveProjectPath($configFilePath): string + { + return \str_replace('/' . self::IDEA_PATH, '', realpath(dirname($configFilePath))); + } + + /** + * Resolve xsdpath to xml project path + * + * @param string $ideaDir + * @param string $xsdPath + * @return string + */ + public function getFileLocationInProject(string $ideaDir, string $xsdPath): string + { + return \str_replace($ideaDir, self::PROJECT_PATH_IDENTIFIER, $xsdPath); + } } From 211fe95022e5d49cda66278a26c74632344349f3 Mon Sep 17 00:00:00 2001 From: Jeroen Boersma <jeroen@elgentos.nl> Date: Mon, 17 Jun 2019 20:52:30 +0000 Subject: [PATCH 476/773] Processed phpcs feedback - removed unused import - removed unused @param --- app/code/Magento/Developer/Model/XmlCatalog/Format/PhpStorm.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/code/Magento/Developer/Model/XmlCatalog/Format/PhpStorm.php b/app/code/Magento/Developer/Model/XmlCatalog/Format/PhpStorm.php index e70fc499915e1..6091c97865b0f 100644 --- a/app/code/Magento/Developer/Model/XmlCatalog/Format/PhpStorm.php +++ b/app/code/Magento/Developer/Model/XmlCatalog/Format/PhpStorm.php @@ -10,7 +10,6 @@ use Magento\Framework\DomDocument\DomDocumentFactory; use Magento\Framework\Exception\FileSystemException; use Magento\Framework\Filesystem\Directory\ReadFactory; -use Magento\Framework\Filesystem\Directory\ReadInterface; use Magento\Framework\Filesystem\File\WriteFactory; /** @@ -32,7 +31,6 @@ class PhpStorm implements FormatInterface private $domDocumentFactory; /** - * @param ReadFactory $readFactory * @param WriteFactory $fileWriteFactory * @param DomDocumentFactory $domDocumentFactory */ From 6e350d1a703199ded6d872367a5668f57c9f92cb Mon Sep 17 00:00:00 2001 From: Aliaksei Yakimovich2 <aliaksei_yakimovich2@epam.com> Date: Fri, 14 Jun 2019 17:19:17 +0300 Subject: [PATCH 477/773] MC-17218: php bin/magento catalog:image:resize error if image is missing - Added integration test; --- .../Command/ImageResizeCommandTest.php | 64 +++++++++++++++++++ .../_files/product_with_missed_image.php | 59 +++++++++++++++++ .../product_with_missed_image_rollback.php | 9 +++ 3 files changed, 132 insertions(+) create mode 100644 dev/tests/integration/testsuite/Magento/MediaStorage/Console/Command/ImageResizeCommandTest.php create mode 100644 dev/tests/integration/testsuite/Magento/MediaStorage/_files/product_with_missed_image.php create mode 100644 dev/tests/integration/testsuite/Magento/MediaStorage/_files/product_with_missed_image_rollback.php diff --git a/dev/tests/integration/testsuite/Magento/MediaStorage/Console/Command/ImageResizeCommandTest.php b/dev/tests/integration/testsuite/Magento/MediaStorage/Console/Command/ImageResizeCommandTest.php new file mode 100644 index 0000000000000..121288973ff0c --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/MediaStorage/Console/Command/ImageResizeCommandTest.php @@ -0,0 +1,64 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types = 1); + +namespace Magento\MediaStorage\Console\Command; + +use Symfony\Component\Console\Input\ArgvInput; +use Symfony\Component\Console\Output\ConsoleOutput; + +/** + * Integration testing for ImageResizeCommand class + */ +class ImageResizeCommandTest extends \PHPUnit\Framework\TestCase +{ + /** + * @var \Magento\Framework\ObjectManagerInterface + */ + private $objectManager; + + /** + * @var \Magento\MediaStorage\Console\Command\ImagesResizeCommand + */ + private $imageResizeCommand; + + /** + * @var ArgvInput + */ + private $input; + + /** + * @var ConsoleOutput + */ + private $output; + + /** + * @inheritDoc + */ + protected function setUp() + { + parent::setUp(); + + $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + $this->imageResizeCommand = $this->objectManager->create( + \Magento\MediaStorage\Console\Command\ImagesResizeCommand::class + ); + + $this->input = $this->objectManager->create(ArgvInput::class, ['argv' => ['catalog:image:resize']]); + $this->output = $this->objectManager->create(ConsoleOutput::class); + } + + /** + * Test that catalog:image:resize command executed successfully with missing image file + * + * @magentoDataFixture Magento/MediaStorage/_files/product_with_missed_image.php + */ + public function testRunResizeWithMissingFile() + { + $resultCode = $this->imageResizeCommand->run($this->input, $this->output); + $this->assertSame($resultCode, 0); + } +} diff --git a/dev/tests/integration/testsuite/Magento/MediaStorage/_files/product_with_missed_image.php b/dev/tests/integration/testsuite/Magento/MediaStorage/_files/product_with_missed_image.php new file mode 100644 index 0000000000000..04f42b13caa85 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/MediaStorage/_files/product_with_missed_image.php @@ -0,0 +1,59 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types = 1); + +use Magento\Framework\App\Filesystem\DirectoryList; + +require dirname(__DIR__, 2) . '/Catalog/_files/product_image.php'; +require dirname(__DIR__, 2) . '/Catalog/_files/product_simple.php'; + +$objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); +/** @var \Magento\Catalog\Api\ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class); +$product = $productRepository->get('simple'); +$product->setStoreId(0) + ->setImage('/m/a/magento_image.jpg') + ->setSmallImage('/m/a/magento_image.jpg') + ->setThumbnail('/m/a/magento_image.jpg') + ->setData( + 'media_gallery', + [ + 'images' => [ + [ + 'file' => '/m/a/magento_image.jpg', + 'position' => 1, + 'label' => 'Image Alt Text', + 'disabled' => 0, + 'media_type' => 'image', + ], + ], + ] + )->save(); +$image = array_shift($product->getData('media_gallery')['images']); +$product = $productRepository->get('simple', false, 1, true); +$product->setData( + 'media_gallery', + [ + 'images' => [ + [ + 'value_id' => $image['value_id'], + 'file' => $image['file'], + 'disabled' => 1, + 'media_type' => 'image', + ], + ], + ] +); +$productRepository->save($product); + +$mediaDirectory = $objectManager->get(\Magento\Framework\Filesystem::class) + ->getDirectoryWrite(DirectoryList::MEDIA); + +$config = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get( + \Magento\Catalog\Model\Product\Media\Config::class +); + +$mediaDirectory->delete($config->getBaseMediaPath() . '/m/a/magento_image.jpg'); diff --git a/dev/tests/integration/testsuite/Magento/MediaStorage/_files/product_with_missed_image_rollback.php b/dev/tests/integration/testsuite/Magento/MediaStorage/_files/product_with_missed_image_rollback.php new file mode 100644 index 0000000000000..239a33116aa39 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/MediaStorage/_files/product_with_missed_image_rollback.php @@ -0,0 +1,9 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types = 1); + +require dirname(__DIR__, 2) . '/Catalog/_files/product_image_rollback.php'; +require dirname(__DIR__, 2) . '/Catalog/_files/product_simple_rollback.php'; From 8c4667a5ad17b8ab9c82fdc49a9c35b36ab167bf Mon Sep 17 00:00:00 2001 From: ProcessEight <s.frost@frostnet.co.uk> Date: Tue, 18 Jun 2019 15:08:11 +0100 Subject: [PATCH 478/773] magento/magento-2#23222: setup:upgrade should return failure when app:config:import failed: Added logic to throw RuntimeException if app:config:import returns failure error code --- setup/src/Magento/Setup/Console/Command/UpgradeCommand.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/setup/src/Magento/Setup/Console/Command/UpgradeCommand.php b/setup/src/Magento/Setup/Console/Command/UpgradeCommand.php index 2df8cde086553..8ca86d7857d5a 100644 --- a/setup/src/Magento/Setup/Console/Command/UpgradeCommand.php +++ b/setup/src/Magento/Setup/Console/Command/UpgradeCommand.php @@ -126,7 +126,10 @@ protected function execute(InputInterface $input, OutputInterface $output) $importConfigCommand = $this->getApplication()->find(ConfigImportCommand::COMMAND_NAME); $arrayInput = new ArrayInput([]); $arrayInput->setInteractive($input->isInteractive()); - $importConfigCommand->run($arrayInput, $output); + $result = $importConfigCommand->run($arrayInput, $output); + if ($result === \Magento\Framework\Console\Cli::RETURN_FAILURE) { + throw new \Magento\Framework\Exception\RuntimeException(__(ConfigImportCommand::COMMAND_NAME . ' failed. See previous output.')); + } } if (!$keepGenerated && $this->appState->getMode() === AppState::MODE_PRODUCTION) { From b1611423bc558407c3c93e2765000f28494cd8bd Mon Sep 17 00:00:00 2001 From: Minesh Mitha <minesh@limesharp.net> Date: Tue, 18 Jun 2019 14:13:15 +0100 Subject: [PATCH 479/773] Use Stock Config to get value. StockHelper to filter collection for us. --- .../Model/Variant/Collection.php | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/ConfigurableProductGraphQl/Model/Variant/Collection.php b/app/code/Magento/ConfigurableProductGraphQl/Model/Variant/Collection.php index 12571602878d1..aadcdbad760ba 100644 --- a/app/code/Magento/ConfigurableProductGraphQl/Model/Variant/Collection.php +++ b/app/code/Magento/ConfigurableProductGraphQl/Model/Variant/Collection.php @@ -15,6 +15,8 @@ use Magento\Framework\EntityManager\MetadataPool; use Magento\Framework\Api\SearchCriteriaBuilder; use Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\Product as DataProvider; +use Magento\CatalogInventory\Helper\Stock; +use Magento\CatalogInventory\Api\StockConfigurationInterface; /** * Collection for fetching configurable child product data. @@ -41,6 +43,16 @@ class Collection */ private $productDataProvider; + /** + * @var Stock + */ + private $stockHelper; + + /** + * @var StockConfigurationInterface + */ + protected $stockConfig; + /** * @var MetadataPool */ @@ -73,13 +85,17 @@ public function __construct( ProductFactory $productFactory, SearchCriteriaBuilder $searchCriteriaBuilder, DataProvider $productDataProvider, - MetadataPool $metadataPool + MetadataPool $metadataPool, + Stock $stockHelper, + StockConfigurationInterface $stockConfig ) { $this->childCollectionFactory = $childCollectionFactory; $this->productFactory = $productFactory; $this->searchCriteriaBuilder = $searchCriteriaBuilder; $this->productDataProvider = $productDataProvider; $this->metadataPool = $metadataPool; + $this->stockHelper = $stockHelper; + $this->stockConfig = $stockConfig; } /** @@ -143,6 +159,8 @@ private function fetch() : array return $this->childrenMap; } + $showOutOfStock = $this->stockConfig->isShowOutOfStock(); + foreach ($this->parentProducts as $product) { $attributeData = $this->getAttributesCodes($product); /** @var ChildCollection $childCollection */ @@ -150,6 +168,10 @@ private function fetch() : array $childCollection->setProductFilter($product); $childCollection->addAttributeToSelect($attributeData); + if(!$showOutOfStock) { + $this->stockHelper->addInStockFilterToCollection($childCollection); + } + /** @var Product $childProduct */ foreach ($childCollection->getItems() as $childProduct) { $formattedChild = ['model' => $childProduct, 'sku' => $childProduct->getSku()]; From f29c40740c246b0669d2f45609c1cbb87659ff7a Mon Sep 17 00:00:00 2001 From: Minesh Mitha <minesh@limesharp.net> Date: Tue, 18 Jun 2019 14:37:20 +0100 Subject: [PATCH 480/773] Lets document things correctly... + clean up --- .../ConfigurableProductGraphQl/Model/Variant/Collection.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/ConfigurableProductGraphQl/Model/Variant/Collection.php b/app/code/Magento/ConfigurableProductGraphQl/Model/Variant/Collection.php index aadcdbad760ba..d34d6f8a5dfab 100644 --- a/app/code/Magento/ConfigurableProductGraphQl/Model/Variant/Collection.php +++ b/app/code/Magento/ConfigurableProductGraphQl/Model/Variant/Collection.php @@ -48,7 +48,7 @@ class Collection */ private $stockHelper; - /** + /** * @var StockConfigurationInterface */ protected $stockConfig; @@ -79,6 +79,8 @@ class Collection * @param SearchCriteriaBuilder $searchCriteriaBuilder * @param DataProvider $productDataProvider * @param MetadataPool $metadataPool + * @param Stock $stockHelper + * @param StockConfigurationInterface $stockConfig */ public function __construct( CollectionFactory $childCollectionFactory, @@ -168,7 +170,7 @@ private function fetch() : array $childCollection->setProductFilter($product); $childCollection->addAttributeToSelect($attributeData); - if(!$showOutOfStock) { + if (!$showOutOfStock) { $this->stockHelper->addInStockFilterToCollection($childCollection); } From c8b6de609961a574930cd7991ecaf2357e124a56 Mon Sep 17 00:00:00 2001 From: Minesh Mitha <minesh@limesharp.net> Date: Tue, 18 Jun 2019 12:02:15 +0100 Subject: [PATCH 481/773] Check if child is null before adding it to variants array. See #736 --- .../Model/Resolver/ConfigurableVariant.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/ConfigurableProductGraphQl/Model/Resolver/ConfigurableVariant.php b/app/code/Magento/ConfigurableProductGraphQl/Model/Resolver/ConfigurableVariant.php index 3e07fecb2ebe7..8914d111d4f5b 100644 --- a/app/code/Magento/ConfigurableProductGraphQl/Model/Resolver/ConfigurableVariant.php +++ b/app/code/Magento/ConfigurableProductGraphQl/Model/Resolver/ConfigurableVariant.php @@ -95,7 +95,9 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value $variants = []; /** @var Product $child */ foreach ($children as $key => $child) { - $variants[$key] = ['sku' => $child['sku'], 'product' => $child, 'options' => $options]; + if($child != null) { + $variants[$key] = ['sku' => $child['sku'], 'product' => $child, 'options' => $options]; + } } return $variants; From cb782c8da7f4e3a40f5730a944eeb7d86f42ae83 Mon Sep 17 00:00:00 2001 From: Minesh Mitha <minesh@limesharp.net> Date: Tue, 18 Jun 2019 14:13:15 +0100 Subject: [PATCH 482/773] Use Stock Config to get value. StockHelper to filter collection for us. --- .../Model/Resolver/ConfigurableVariant.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/code/Magento/ConfigurableProductGraphQl/Model/Resolver/ConfigurableVariant.php b/app/code/Magento/ConfigurableProductGraphQl/Model/Resolver/ConfigurableVariant.php index 8914d111d4f5b..3e07fecb2ebe7 100644 --- a/app/code/Magento/ConfigurableProductGraphQl/Model/Resolver/ConfigurableVariant.php +++ b/app/code/Magento/ConfigurableProductGraphQl/Model/Resolver/ConfigurableVariant.php @@ -95,9 +95,7 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value $variants = []; /** @var Product $child */ foreach ($children as $key => $child) { - if($child != null) { - $variants[$key] = ['sku' => $child['sku'], 'product' => $child, 'options' => $options]; - } + $variants[$key] = ['sku' => $child['sku'], 'product' => $child, 'options' => $options]; } return $variants; From e0b4268c032255262aa26b2fd012588c8b0577de Mon Sep 17 00:00:00 2001 From: Maria Kovdrysh <kovdrysh@adobe.com> Date: Tue, 18 Jun 2019 10:20:00 -0500 Subject: [PATCH 483/773] MC-6141: Check necessary logic to action class for cookie messages --- ...StorefrontOpenMyAccountPageActionGroup.xml | 15 +++++ ...frontCustomerAccountInformationSection.xml | 3 + .../StorefrontCustomerAccountMainSection.xml | 1 + ...omerDashboardAccountInformationSection.xml | 1 + ...ogicToActionClassForCookieMessagesTest.xml | 61 +++++++++++++++++++ 5 files changed, 81 insertions(+) create mode 100644 app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontOpenMyAccountPageActionGroup.xml create mode 100644 app/code/Magento/Security/Test/Mftf/Test/StorefrontCheckNecessaryLogicToActionClassForCookieMessagesTest.xml diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontOpenMyAccountPageActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontOpenMyAccountPageActionGroup.xml new file mode 100644 index 0000000000000..57c350700d57d --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontOpenMyAccountPageActionGroup.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="StorefrontOpenMyAccountPageActionGroup"> + <amOnPage url="{{StorefrontCustomerDashboardPage.url}}" stepKey="goToMyAccountPage"/> + <waitForPageLoad stepKey="waitForPageLoad"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerAccountInformationSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerAccountInformationSection.xml index 8a633ec5bc271..9828c42211e41 100644 --- a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerAccountInformationSection.xml +++ b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerAccountInformationSection.xml @@ -20,5 +20,8 @@ <element name="confirmNewPassword" type="input" selector="#password-confirmation"/> <element name="confirmNewPasswordError" type="text" selector="#password-confirmation-error"/> <element name="email" type="input" selector=".form-edit-account input[name='email']" /> + <element name="emailErrorMessage" type="text" selector="#email-error"/> + <element name="currentPasswordErrorMessage" type="text" selector="#current-password-error"/> + <element name="emailField" type="input" selector="#email"/> </section> </sections> diff --git a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerAccountMainSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerAccountMainSection.xml index c00b54b3964da..a501a7ac4a618 100644 --- a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerAccountMainSection.xml +++ b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerAccountMainSection.xml @@ -11,5 +11,6 @@ <section name="StorefrontCustomerAccountMainSection"> <element name="pageTitle" type="text" selector="#maincontent .column.main [data-ui-id='page-title-wrapper']" /> <element name="messageByType" type="block" selector="#maincontent .message-{{messageType}}" parameterized="true" /> + <element name="alertMessage" type="text" selector=".page.messages [role=alert]"/> </section> </sections> diff --git a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerDashboardAccountInformationSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerDashboardAccountInformationSection.xml index f83bd64a2a8d2..85d0fd166a77e 100644 --- a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerDashboardAccountInformationSection.xml +++ b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerDashboardAccountInformationSection.xml @@ -12,6 +12,7 @@ <element name="ContactInformation" type="textarea" selector=".box.box-information .box-content"/> <element name="edit" type="block" selector=".action.edit" timeout="15"/> <element name="changePassword" type="block" selector=".action.change-password" timeout="15"/> + <element name="editLink" type="text" selector=".box-information .edit"/> </section> <section name="StorefrontCustomerAddressSection"> <element name="firstName" type="input" selector="#firstname"/> diff --git a/app/code/Magento/Security/Test/Mftf/Test/StorefrontCheckNecessaryLogicToActionClassForCookieMessagesTest.xml b/app/code/Magento/Security/Test/Mftf/Test/StorefrontCheckNecessaryLogicToActionClassForCookieMessagesTest.xml new file mode 100644 index 0000000000000..1ffd970bc14da --- /dev/null +++ b/app/code/Magento/Security/Test/Mftf/Test/StorefrontCheckNecessaryLogicToActionClassForCookieMessagesTest.xml @@ -0,0 +1,61 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="StorefrontCheckNecessaryLogicToActionClassForCookieMessagesTest"> + <annotations> + <features value="Security"/> + <stories value="Check necessary logic to action class for cookie messages"/> + <title value="Storefront check necessary logic to action class for cookie messages test"/> + <description value="Check necessary logic to action class for cookie messages"/> + <testCaseId value="MC-6141" /> + <severity value="CRITICAL"/> + <group value="security"/> + <group value="customer"/> + </annotations> + <before> + <!-- Create customer --> + <createData entity="Simple_US_Customer" stepKey="createCustomer"/> + </before> + <after> + <!-- Delete customer --> + <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> + </after> + + <!-- Login to application --> + <actionGroup ref="LoginToStorefrontActionGroup" stepKey="loginToStorefrontAccount"> + <argument name="Customer" value="$$createCustomer$$"/> + </actionGroup> + + <!-- Open 'My Account' page and click 'Edit; link --> + <actionGroup ref="StorefrontOpenMyAccountPageActionGroup" stepKey="goToMyAccountPage"/> + <click selector="{{StorefrontCustomerDashboardAccountInformationSection.editLink}}" stepKey="clickEditContactInformation"/> + + <!-- Mark as checked 'Change email' check-box. Assert 2 labels under 'Change Email' block --> + <checkOption selector="{{StorefrontCustomerAccountInformationSection.changeEmail}}" stepKey="clickChangeEmailCheckbox"/> + <seeElement selector="{{StorefrontCustomerAccountInformationSection.email}}" stepKey="seeEmailField"/> + <seeElement selector="{{StorefrontCustomerAccountInformationSection.currentPassword}}" stepKey="seeCurrentPasswordField"/> + + <!-- Change email attribute 'type' from email to text and type script after email address. Click 'Save' button --> + <executeJS function="document.querySelector('{{StorefrontCustomerAccountInformationSection.emailField}}').setAttribute('type', 'text');" stepKey="changeAttributeFromEmailToText"/> + <fillField selector="{{StorefrontCustomerAccountInformationSection.email}}" userInput="$$createCustomer.email$$<script>alert('Hello')</script>" stepKey="fillEmailWithScript"/> + <click selector="{{StorefrontCustomerAccountInformationSection.saveButton}}" stepKey="clickSave"/> + + <!-- Assert error messages for email and password fields --> + <dontSee selector="{{StorefrontCustomerAccountInformationSection.emailErrorMessage}}" userInput="Please enter a valid email address." stepKey="dontSeeEmailErrorMessage"/> + <see selector="{{StorefrontCustomerAccountInformationSection.currentPasswordErrorMessage}}" userInput="This is a required field." stepKey="seeErrorPasswordMessage"/> + + <!-- Fill password and click 'Save' button --> + <fillField selector="{{StorefrontCustomerAccountInformationSection.currentPassword}}" userInput="$$createCustomer.password$$" stepKey="fillCurrentPassword"/> + <click selector="{{StorefrontCustomerAccountInformationSection.saveButton}}" stepKey="saveChanges"/> + + <!-- Throw validation error message (server side validation) with escaped customer input --> + <see selector="{{StorefrontCustomerAccountMainSection.alertMessage}}" userInput=""Email" is not a valid hostname. 'example.com<script>alert('Hello')</script>' looks like a DNS hostname but we cannot match it against the hostname schema for TLD 'com<script>alert('Hello')</script>'. 'example.com<script>alert('Hello')</script>' does not look like a valid local network name." stepKey="seeValidationErrorMessage"/> + </test> +</tests> From 671876ebaf4e61fbc4efdad9b1d9d67677ccc43d Mon Sep 17 00:00:00 2001 From: Simon Frost <s.frost@frostnet.co.uk> Date: Tue, 18 Jun 2019 16:21:39 +0100 Subject: [PATCH 484/773] magento/magento-2#23222: setup:upgrade should return failure when app:config:import failed: Replaced constant in localised error message with string literal --- setup/src/Magento/Setup/Console/Command/UpgradeCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup/src/Magento/Setup/Console/Command/UpgradeCommand.php b/setup/src/Magento/Setup/Console/Command/UpgradeCommand.php index 8ca86d7857d5a..55081c5a9c9a4 100644 --- a/setup/src/Magento/Setup/Console/Command/UpgradeCommand.php +++ b/setup/src/Magento/Setup/Console/Command/UpgradeCommand.php @@ -128,7 +128,7 @@ protected function execute(InputInterface $input, OutputInterface $output) $arrayInput->setInteractive($input->isInteractive()); $result = $importConfigCommand->run($arrayInput, $output); if ($result === \Magento\Framework\Console\Cli::RETURN_FAILURE) { - throw new \Magento\Framework\Exception\RuntimeException(__(ConfigImportCommand::COMMAND_NAME . ' failed. See previous output.')); + throw new \Magento\Framework\Exception\RuntimeException(__('%1 failed. See previous output.', ConfigImportCommand::COMMAND_NAME)); } } From 39389180f2f4dc845db8d8119cf4a0cd5ac48121 Mon Sep 17 00:00:00 2001 From: Minesh Mitha <minesh@limesharp.net> Date: Tue, 18 Jun 2019 16:35:16 +0100 Subject: [PATCH 485/773] $StockConfig made private --- .../ConfigurableProductGraphQl/Model/Variant/Collection.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/ConfigurableProductGraphQl/Model/Variant/Collection.php b/app/code/Magento/ConfigurableProductGraphQl/Model/Variant/Collection.php index d34d6f8a5dfab..11c22e9ff5e6f 100644 --- a/app/code/Magento/ConfigurableProductGraphQl/Model/Variant/Collection.php +++ b/app/code/Magento/ConfigurableProductGraphQl/Model/Variant/Collection.php @@ -51,7 +51,7 @@ class Collection /** * @var StockConfigurationInterface */ - protected $stockConfig; + private $stockConfig; /** * @var MetadataPool From 2fed193bbcc021f15d8340046f9aefba195bd4cf Mon Sep 17 00:00:00 2001 From: Maria Kovdrysh <kovdrysh@adobe.com> Date: Tue, 18 Jun 2019 15:49:28 -0500 Subject: [PATCH 486/773] MC-6436: Configuring Instant Purchase functionality Moved UI actions out of the before/after sections --- ...guringInstantPurchaseFunctionalityTest.xml | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/ConfiguringInstantPurchaseFunctionalityTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/ConfiguringInstantPurchaseFunctionalityTest.xml index 6d7ecc2ef9903..ead9927891989 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/ConfiguringInstantPurchaseFunctionalityTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/ConfiguringInstantPurchaseFunctionalityTest.xml @@ -31,14 +31,6 @@ <!-- Login as admin --> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> - - <!-- Create store views --> - <actionGroup ref="AdminCreateStoreViewActionGroup" stepKey="createFirstStoreView"> - <argument name="customStore" value="storeViewData1"/> - </actionGroup> - <actionGroup ref="AdminCreateStoreViewActionGroup" stepKey="createSecondStoreView"> - <argument name="customStore" value="storeViewData2"/> - </actionGroup> </before> <after> <!-- Set configs to default --> @@ -51,18 +43,18 @@ <!-- Delete customer --> <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> - <!-- Delete store views --> - <actionGroup ref="AdminDeleteStoreViewActionGroup" stepKey="deleteFirstStoreView"> - <argument name="customStore" value="storeViewData1"/> - </actionGroup> - <actionGroup ref="AdminDeleteStoreViewActionGroup" stepKey="deleteSecondStoreView"> - <argument name="customStore" value="storeViewData2"/> - </actionGroup> - <!-- Admin logout --> <actionGroup ref="logout" stepKey="adminLogout"/> </after> + <!-- Create store views --> + <actionGroup ref="AdminCreateStoreViewActionGroup" stepKey="createFirstStoreView"> + <argument name="customStore" value="storeViewData1"/> + </actionGroup> + <actionGroup ref="AdminCreateStoreViewActionGroup" stepKey="createSecondStoreView"> + <argument name="customStore" value="storeViewData2"/> + </actionGroup> + <!-- Login to Frontend --> <actionGroup ref="LoginToStorefrontActionGroup" stepKey="loginAsCustomer"> <argument name="Customer" value="$$createCustomer$$"/> @@ -248,5 +240,13 @@ <argument name="selector" value="{{StorefrontInstantPurchaseSection.instantPurchaseButton}}"/> <argument name="userInput" value="Instant Purchase"/> </actionGroup> + + <!-- Delete store views --> + <actionGroup ref="AdminDeleteStoreViewActionGroup" stepKey="deleteFirstStoreView"> + <argument name="customStore" value="storeViewData1"/> + </actionGroup> + <actionGroup ref="AdminDeleteStoreViewActionGroup" stepKey="deleteSecondStoreView"> + <argument name="customStore" value="storeViewData2"/> + </actionGroup> </test> </tests> From 4a84152b32400d2eba58a300d400e389a0ac9bd0 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun <ogorkun@magento.com> Date: Wed, 19 Jun 2019 13:12:55 -0500 Subject: [PATCH 487/773] MC-17489: Require specific suffix for HTML binding --- .../grid/filters/elements/ui-select.html | 4 +- .../Magento/Sniffs/Html/HtmlBindingSniff.php | 57 +++++++++++++++++ .../Tool/CodeSniffer/HtmlWrapper.php | 27 ++++++++ .../Magento/Test/Html/LiveCodeTest.php | 64 +++++++++++++++++++ .../Magento/Test/Html/_files/html/ruleset.xml | 14 ++++ .../Test/Html/_files/whitelist/common.txt | 2 + 6 files changed, 167 insertions(+), 1 deletion(-) create mode 100644 dev/tests/static/framework/Magento/Sniffs/Html/HtmlBindingSniff.php create mode 100644 dev/tests/static/framework/Magento/TestFramework/CodingStandard/Tool/CodeSniffer/HtmlWrapper.php create mode 100644 dev/tests/static/testsuite/Magento/Test/Html/LiveCodeTest.php create mode 100644 dev/tests/static/testsuite/Magento/Test/Html/_files/html/ruleset.xml create mode 100644 dev/tests/static/testsuite/Magento/Test/Html/_files/whitelist/common.txt diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/filters/elements/ui-select.html b/app/code/Magento/Ui/view/base/web/templates/grid/filters/elements/ui-select.html index b9425c020c0e9..f02616cb1c294 100644 --- a/app/code/Magento/Ui/view/base/web/templates/grid/filters/elements/ui-select.html +++ b/app/code/Magento/Ui/view/base/web/templates/grid/filters/elements/ui-select.html @@ -141,7 +141,9 @@ </div> <div ifnot="options().length" class="admin__action-multiselect-empty-area"> - <ul data-bind="html: emptyOptionsHtml"/> + <ul data-bind=" + html: emptyOptionsHtml + "/> </div> <!-- /ko --> <ul class="admin__action-multiselect-menu-inner _root" diff --git a/dev/tests/static/framework/Magento/Sniffs/Html/HtmlBindingSniff.php b/dev/tests/static/framework/Magento/Sniffs/Html/HtmlBindingSniff.php new file mode 100644 index 0000000000000..c4cc34040304e --- /dev/null +++ b/dev/tests/static/framework/Magento/Sniffs/Html/HtmlBindingSniff.php @@ -0,0 +1,57 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Sniffs\Html; + +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Files\File; + +class HtmlBindingSniff implements Sniff +{ + /** + * @inheritDoc + */ + public function register() + { + return [T_INLINE_HTML]; + } + + /** + * @inheritDoc + * + * Find HTML data bindings and check variables used. + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($stackPtr === 0) { + $html = $phpcsFile->getTokensAsString($stackPtr, count($phpcsFile->getTokens())); + $dom = new \DOMDocument(); + try { + @$dom->loadHTML($html); + $loaded = true; + } catch (\Throwable $exception) { + //Invalid HTML, skipping + $loaded = false; + } + if ($loaded) { + $domXpath = new \DOMXPath($dom); + $dataBindAttributes = $domXpath->query('//@*[name() = "data-bind"]'); + foreach ($dataBindAttributes as $dataBindAttribute) { + $knockoutBinding = $dataBindAttribute->nodeValue; + preg_match('/^(.+\s+)*?html\:\s*?([a-z0-9\.\_\(\)]+)/i', $knockoutBinding, $htmlBinding); + if ($htmlBinding && !preg_match('/UnsanitizedHtml[\(\)]*?$/', $htmlBinding[2])) { + $phpcsFile->addError( + 'Variables/functions used for HTML binding must have UnsanitizedHtml suffix, ' + .'consider using text binding if the value is supposed to be text', + null, + 'UIComponentTemplate.HtmlSuffix' + ); + } + } + } + } + } +} diff --git a/dev/tests/static/framework/Magento/TestFramework/CodingStandard/Tool/CodeSniffer/HtmlWrapper.php b/dev/tests/static/framework/Magento/TestFramework/CodingStandard/Tool/CodeSniffer/HtmlWrapper.php new file mode 100644 index 0000000000000..049997aa7ee3f --- /dev/null +++ b/dev/tests/static/framework/Magento/TestFramework/CodingStandard/Tool/CodeSniffer/HtmlWrapper.php @@ -0,0 +1,27 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\TestFramework\CodingStandard\Tool\CodeSniffer; + +/** + * Add HTML files extension to config. + */ +class HtmlWrapper extends Wrapper +{ + const FILE_EXTENSION = 'html'; + + private const TOKENIZER = 'PHP'; + + /** + * @inheritDoc + */ + public function init() + { + parent::init(); + + $this->config->extensions += [self::FILE_EXTENSION => self::TOKENIZER]; + } +} diff --git a/dev/tests/static/testsuite/Magento/Test/Html/LiveCodeTest.php b/dev/tests/static/testsuite/Magento/Test/Html/LiveCodeTest.php new file mode 100644 index 0000000000000..baf568157189d --- /dev/null +++ b/dev/tests/static/testsuite/Magento/Test/Html/LiveCodeTest.php @@ -0,0 +1,64 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Test\Html; + +use Magento\Framework\App\Utility; +use Magento\TestFramework\CodingStandard\Tool\CodeSniffer; +use Magento\Framework\App\Utility\Files; +use Magento\Test\Php\LiveCodeTest as PHPCodeTest; +use PHPUnit\Framework\TestCase; + +/** + * Set of tests for static code style + */ +class LiveCodeTest extends TestCase +{ + /** + * @var string + */ + private static $reportDir = ''; + + /** + * Setup basics for all tests + * + * @return void + */ + public static function setUpBeforeClass(): void + { + self::$reportDir = BP . '/dev/tests/static/report'; + if (!is_dir(self::$reportDir)) { + mkdir(self::$reportDir, 0770); + } + } + + /** + * Run the magento specific coding standards on the code + * + * @return void + */ + public function testCodeStyle(): void + { + $reportFile = self::$reportDir . '/html_report.txt'; + $wrapper = new CodeSniffer\HtmlWrapper(); + $codeSniffer = new CodeSniffer(realpath(__DIR__ . '/_files/html'), $reportFile, $wrapper); + if (!$codeSniffer->canRun()) { + $this->markTestSkipped('PHP Code Sniffer is not installed.'); + } + $codeSniffer->setExtensions([CodeSniffer\HtmlWrapper::FILE_EXTENSION]); + //Looking for changed .html files + $fileList = PHPCodeTest::getWhitelist([CodeSniffer\HtmlWrapper::FILE_EXTENSION], __DIR__, __DIR__); + + $result = $codeSniffer->run($fileList); + + $report = file_exists($reportFile) ? file_get_contents($reportFile) : ""; + $this->assertEquals( + 0, + $result, + "PHP Code Sniffer has found {$result} error(s): " . PHP_EOL . $report + ); + } +} diff --git a/dev/tests/static/testsuite/Magento/Test/Html/_files/html/ruleset.xml b/dev/tests/static/testsuite/Magento/Test/Html/_files/html/ruleset.xml new file mode 100644 index 0000000000000..143c07a8d7cce --- /dev/null +++ b/dev/tests/static/testsuite/Magento/Test/Html/_files/html/ruleset.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<ruleset name="Magento"> + <description>UI Component Coding Standard</description> + <rule ref="Internal.NoCodeFound"> + <severity>0</severity> + </rule> + <rule ref="../../../../../../framework/Magento/Sniffs/Html"/> +</ruleset> diff --git a/dev/tests/static/testsuite/Magento/Test/Html/_files/whitelist/common.txt b/dev/tests/static/testsuite/Magento/Test/Html/_files/whitelist/common.txt new file mode 100644 index 0000000000000..60f6f9b105ee2 --- /dev/null +++ b/dev/tests/static/testsuite/Magento/Test/Html/_files/whitelist/common.txt @@ -0,0 +1,2 @@ +# Format: <componentType=module|library|theme|language|*> <componentName> <globPattern> or simply <globPattern> +* * / From d4f0c4446f1018386bbe2159bde81a0ec7520496 Mon Sep 17 00:00:00 2001 From: Mila Lesechko <llesechk@adobe.com> Date: Wed, 19 Jun 2019 13:42:46 -0500 Subject: [PATCH 488/773] MC-12604: Admin should be able to uncheck Default Value checkbox for dependent field --- .../Mftf/Section/LayeredNavigationSection.xml | 1 + ...pecifyLayerNavigationConfigurationTest.xml | 47 +++++++++++-------- 2 files changed, 29 insertions(+), 19 deletions(-) diff --git a/app/code/Magento/LayeredNavigation/Test/Mftf/Section/LayeredNavigationSection.xml b/app/code/Magento/LayeredNavigation/Test/Mftf/Section/LayeredNavigationSection.xml index b44ee9ddbd734..1e4137beacd88 100644 --- a/app/code/Magento/LayeredNavigation/Test/Mftf/Section/LayeredNavigationSection.xml +++ b/app/code/Magento/LayeredNavigation/Test/Mftf/Section/LayeredNavigationSection.xml @@ -10,6 +10,7 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="LayeredNavigationSection"> <element name="layeredNavigation" type="select" selector="#catalog_layered_navigation-head"/> + <element name="layeredNavigationBlock" type="block" selector="#catalog_layered_navigation"/> <element name="CheckIfTabExpand" type="button" selector="#catalog_layered_navigation-head:not(.open)"/> <element name="NavigationStepCalculation" type="button" selector="#catalog_layered_navigation_price_range_calculation"/> <element name="NavigationStepCalculationSystemValue" type="button" selector="#catalog_layered_navigation_price_range_calculation_inherit"/> diff --git a/app/code/Magento/LayeredNavigation/Test/Mftf/Test/AdminSpecifyLayerNavigationConfigurationTest.xml b/app/code/Magento/LayeredNavigation/Test/Mftf/Test/AdminSpecifyLayerNavigationConfigurationTest.xml index 0a09f17d66f62..fd8763891af93 100644 --- a/app/code/Magento/LayeredNavigation/Test/Mftf/Test/AdminSpecifyLayerNavigationConfigurationTest.xml +++ b/app/code/Magento/LayeredNavigation/Test/Mftf/Test/AdminSpecifyLayerNavigationConfigurationTest.xml @@ -15,31 +15,40 @@ <stories value="Magento_LayeredNavigation"/> <title value="Admin should be able to uncheck Default Value checkbox for dependent field"/> <description value="Admin should be able to uncheck Default Value checkbox for dependent field"/> - <severity value="AVERAGE"/> - <testCaseId value="MAGETWO-94872"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-12604"/> </annotations> + <before> <actionGroup ref="LoginActionGroup" stepKey="login"/> </before> - <amOnPage url="{{CatalogConfigPage.url}}" stepKey="navigateToConfigurationPage" /> - <waitForPageLoad stepKey="wait1"/> - <conditionalClick stepKey="expandLayeredNavigationTab" selector="{{LayeredNavigationSection.layeredNavigation}}" dependentSelector="{{LayeredNavigationSection.CheckIfTabExpand}}" visible="true" /> - <waitForElementVisible selector="{{LayeredNavigationSection.NavigationStepCalculationSystemValue}}" stepKey="waitForUseSystemValueVisible"/> - <uncheckOption selector="{{LayeredNavigationSection.NavigationStepCalculationSystemValue}}" stepKey="uncheckUseSystemValue"/> - <selectOption selector="{{LayeredNavigationSection.NavigationStepCalculation}}" userInput="Manual" stepKey="selectOption1"/> - <uncheckOption selector="{{LayeredNavigationSection.PriceNavigationStepSystemValue}}" stepKey="uncheckUseSystemValue2"/> - <fillField selector="{{LayeredNavigationSection.PriceNavigationStep}}" userInput="102" stepKey="fillAdmin1"/> - <click selector="{{ContentManagementSection.Save}}" stepKey="saveConfig" /> - <waitForPageLoad stepKey="waitForSavingSystemConfiguration"/> - <waitForElementVisible selector="#catalog_layered_navigation" stepKey="waitForLayeredNav" /> - <scrollTo selector="#catalog_layered_navigation" x="0" y="-80" stepKey="scrollToLayeredNavigation" /> - <seeInField stepKey="seeThatValueWasSaved" selector="{{LayeredNavigationSection.PriceNavigationStep}}" userInput="102"/> - <checkOption selector="{{LayeredNavigationSection.NavigationStepCalculationSystemValue}}" stepKey="setToDefaultValue1"/> - <checkOption selector="{{LayeredNavigationSection.PriceNavigationStepSystemValue}}" stepKey="setToDefaultValue2"/> - <click selector="{{ContentManagementSection.Save}}" stepKey="saveConfig2" /> - <waitForPageLoad stepKey="waitForSavingSystemConfiguration2"/> + <after> <actionGroup ref="logout" stepKey="logout"/> </after> + + <!-- Configure Layered Navigation in Stores -> Configuration -> Catalog -> Layered Navigation --> + <amOnPage url="{{CatalogConfigPage.url}}" stepKey="navigateToConfigurationPage"/> + <waitForPageLoad stepKey="waitForPageLoad"/> + <conditionalClick selector="{{LayeredNavigationSection.layeredNavigation}}" dependentSelector="{{LayeredNavigationSection.CheckIfTabExpand}}" visible="true" stepKey="expandLayeredNavigationTab"/> + <waitForElementVisible selector="{{LayeredNavigationSection.NavigationStepCalculationSystemValue}}" stepKey="waitForUseSystemValueVisible"/> + + <!-- Display Product Count = yes; Price Navigation Step Calculation = Manual; Default Price Navigation Step = 102 --> + <uncheckOption selector="{{LayeredNavigationSection.NavigationStepCalculationSystemValue}}" stepKey="uncheckUseSystemValue"/> + <selectOption selector="{{LayeredNavigationSection.NavigationStepCalculation}}" userInput="Manual" stepKey="selectOption"/> + <uncheckOption selector="{{LayeredNavigationSection.PriceNavigationStepSystemValue}}" stepKey="uncheckUseStepSystemValue"/> + <fillField selector="{{LayeredNavigationSection.PriceNavigationStep}}" userInput="102" stepKey="fillPriceNavStep"/> + <click selector="{{ContentManagementSection.Save}}" stepKey="saveConfig" /> + <waitForPageLoad stepKey="waitForSavingSystemConfiguration"/> + + <waitForElementVisible selector="{{LayeredNavigationSection.layeredNavigationBlock}}" stepKey="waitForLayeredNav"/> + <scrollTo selector="{{LayeredNavigationSection.layeredNavigationBlock}}" x="0" y="-80" stepKey="scrollToLayeredNavigation"/> + <seeInField userInput="102" selector="{{LayeredNavigationSection.PriceNavigationStep}}" stepKey="seeThatValueWasSaved"/> + + <!-- It is possible uncheck Use Default checkbox --> + <checkOption selector="{{LayeredNavigationSection.NavigationStepCalculationSystemValue}}" stepKey="setStepCalculationToDefaultValue"/> + <checkOption selector="{{LayeredNavigationSection.PriceNavigationStepSystemValue}}" stepKey="setPriceNavToDefaultValue"/> + <click selector="{{ContentManagementSection.Save}}" stepKey="saveConfiguration" /> + <waitForPageLoad stepKey="waitForSaveSystemConfiguration"/> </test> </tests> From 478360de8707789f0f8dfef1755211320707ab2c Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun <ogorkun@magento.com> Date: Wed, 19 Jun 2019 14:32:35 -0500 Subject: [PATCH 489/773] MC-17489: Require specific suffix for HTML binding --- .../Magento/Sniffs/Html/HtmlBindingSniff.php | 11 +++- .../Sniffs/Html/HtmlBindingSniffTest.php | 62 +++++++++++++++++++ .../Magento/Sniffs/Html/_files/ruleset.xml | 14 +++++ .../Html/_files/test-html-binding-errors.txt | 12 ++++ .../Sniffs/Html/_files/test-html-binding.html | 18 ++++++ 5 files changed, 114 insertions(+), 3 deletions(-) create mode 100644 dev/tests/static/framework/tests/unit/testsuite/Magento/Sniffs/Html/HtmlBindingSniffTest.php create mode 100644 dev/tests/static/framework/tests/unit/testsuite/Magento/Sniffs/Html/_files/ruleset.xml create mode 100644 dev/tests/static/framework/tests/unit/testsuite/Magento/Sniffs/Html/_files/test-html-binding-errors.txt create mode 100644 dev/tests/static/framework/tests/unit/testsuite/Magento/Sniffs/Html/_files/test-html-binding.html diff --git a/dev/tests/static/framework/Magento/Sniffs/Html/HtmlBindingSniff.php b/dev/tests/static/framework/Magento/Sniffs/Html/HtmlBindingSniff.php index c4cc34040304e..94828d79bc139 100644 --- a/dev/tests/static/framework/Magento/Sniffs/Html/HtmlBindingSniff.php +++ b/dev/tests/static/framework/Magento/Sniffs/Html/HtmlBindingSniff.php @@ -9,6 +9,9 @@ use PHP_CodeSniffer\Sniffs\Sniff; use PHP_CodeSniffer\Files\File; +/** + * Sniffing improper HTML bindings. + */ class HtmlBindingSniff implements Sniff { /** @@ -30,6 +33,7 @@ public function process(File $phpcsFile, $stackPtr) $html = $phpcsFile->getTokensAsString($stackPtr, count($phpcsFile->getTokens())); $dom = new \DOMDocument(); try { + //phpcs: ignore @$dom->loadHTML($html); $loaded = true; } catch (\Throwable $exception) { @@ -41,13 +45,14 @@ public function process(File $phpcsFile, $stackPtr) $dataBindAttributes = $domXpath->query('//@*[name() = "data-bind"]'); foreach ($dataBindAttributes as $dataBindAttribute) { $knockoutBinding = $dataBindAttribute->nodeValue; - preg_match('/^(.+\s+)*?html\:\s*?([a-z0-9\.\_\(\)]+)/i', $knockoutBinding, $htmlBinding); + preg_match('/^(.+\s*?)?html\s*?\:\s*?([a-z0-9\.\(\)\_]+)/ims', $knockoutBinding, $htmlBinding); if ($htmlBinding && !preg_match('/UnsanitizedHtml[\(\)]*?$/', $htmlBinding[2])) { $phpcsFile->addError( - 'Variables/functions used for HTML binding must have UnsanitizedHtml suffix, ' + 'Variables/functions used for HTML binding must have UnsanitizedHtml suffix' + .' - "' .$htmlBinding[2] .'" doesn\'t,' .PHP_EOL .'consider using text binding if the value is supposed to be text', null, - 'UIComponentTemplate.HtmlSuffix' + 'UIComponentTemplate.KnockoutBinding.HtmlSuffix' ); } } diff --git a/dev/tests/static/framework/tests/unit/testsuite/Magento/Sniffs/Html/HtmlBindingSniffTest.php b/dev/tests/static/framework/tests/unit/testsuite/Magento/Sniffs/Html/HtmlBindingSniffTest.php new file mode 100644 index 0000000000000..8b044f5ba3ee7 --- /dev/null +++ b/dev/tests/static/framework/tests/unit/testsuite/Magento/Sniffs/Html/HtmlBindingSniffTest.php @@ -0,0 +1,62 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +declare(strict_types=1); + +namespace Magento\Sniffs\Less; + +use Magento\TestFramework\CodingStandard\Tool\CodeSniffer\HtmlWrapper; +use PHPUnit\Framework\TestCase; +use Magento\TestFramework\CodingStandard\Tool\CodeSniffer; + +/** + * Test the html binding sniff on real files. + */ +class HtmlBindingSniffTest extends TestCase +{ + /** + * Files to sniff and expected reports. + * + * @return array + */ + public function processDataProvider(): array + { + return [ + [ + 'test-html-binding.html', + 'test-html-binding-errors.txt' + ] + ]; + } + + /** + * Run CS on provided files. + * + * @param string $fileUnderTest + * @param string $expectedReportFile + * @return void + * @dataProvider processDataProvider + */ + public function testProcess(string $fileUnderTest, string $expectedReportFile): void + { + $reportFile = __DIR__ . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'phpcs_report.txt'; + $ruleSetDir = __DIR__ . DIRECTORY_SEPARATOR . '_files'; + $wrapper = new HtmlWrapper(); + $codeSniffer = new CodeSniffer($ruleSetDir, $reportFile, $wrapper); + $codeSniffer->setExtensions([HtmlWrapper::FILE_EXTENSION]); + $result = $codeSniffer->run( + [__DIR__ . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . $fileUnderTest] + ); + // Remove the absolute path to the file from the output + $actual = preg_replace('/^.+\n/', '', ltrim(file_get_contents($reportFile))); + $expected = file_get_contents( + __DIR__ . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . $expectedReportFile + ); + unlink($reportFile); + $this->assertEquals(1, $result); + $this->assertEquals($expected, $actual); + } +} diff --git a/dev/tests/static/framework/tests/unit/testsuite/Magento/Sniffs/Html/_files/ruleset.xml b/dev/tests/static/framework/tests/unit/testsuite/Magento/Sniffs/Html/_files/ruleset.xml new file mode 100644 index 0000000000000..4aab38d60f55c --- /dev/null +++ b/dev/tests/static/framework/tests/unit/testsuite/Magento/Sniffs/Html/_files/ruleset.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<ruleset name="Magento"> + <description>UI Component Coding Standard</description> + <rule ref="Internal.NoCodeFound"> + <severity>0</severity> + </rule> + <rule ref="../../../../../../../Magento/Sniffs/Html"/> +</ruleset> diff --git a/dev/tests/static/framework/tests/unit/testsuite/Magento/Sniffs/Html/_files/test-html-binding-errors.txt b/dev/tests/static/framework/tests/unit/testsuite/Magento/Sniffs/Html/_files/test-html-binding-errors.txt new file mode 100644 index 0000000000000..6524ebed4dfb2 --- /dev/null +++ b/dev/tests/static/framework/tests/unit/testsuite/Magento/Sniffs/Html/_files/test-html-binding-errors.txt @@ -0,0 +1,12 @@ +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +FOUND 3 ERRORS AFFECTING 1 LINE +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 1 | ERROR | Variables/functions used for HTML binding must have UnsanitizedHtml suffix - "testError()" doesn't, + | | consider using text binding if the value is supposed to be text + 1 | ERROR | Variables/functions used for HTML binding must have UnsanitizedHtml suffix - "test.getSomething().value.error()" doesn't, + | | consider using text binding if the value is supposed to be text + 1 | ERROR | Variables/functions used for HTML binding must have UnsanitizedHtml suffix - "bind_stuff()" doesn't, + | | consider using text binding if the value is supposed to be text +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + + diff --git a/dev/tests/static/framework/tests/unit/testsuite/Magento/Sniffs/Html/_files/test-html-binding.html b/dev/tests/static/framework/tests/unit/testsuite/Magento/Sniffs/Html/_files/test-html-binding.html new file mode 100644 index 0000000000000..d0c420ee19793 --- /dev/null +++ b/dev/tests/static/framework/tests/unit/testsuite/Magento/Sniffs/Html/_files/test-html-binding.html @@ -0,0 +1,18 @@ +<!-- +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<div data-bind="attr: test.value"></div> +<p>Test</p> +<span data-bind="html: testError()"></span> +<div data-bind=" + attr : tst, + html: test.getSomething().value.error() +"></div> +<p data-bind="html: '<b>Some html</b>'"></p> +<div data-bind="html: valueUnsanitizedHtml"></div> +<div data-bind="attr: testhtml, html: valueUnsanitizedHtml()"></div> +<p data-bind="other_html: bind, html: bind_stuff()"></p> From 1d89e6b71866624e21f4f70f004cda7c15d8b564 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun <ogorkun@magento.com> Date: Wed, 19 Jun 2019 14:34:29 -0500 Subject: [PATCH 490/773] MC-17489: Require specific suffix for HTML binding --- .../testsuite/Magento/Sniffs/Html/HtmlBindingSniffTest.php | 2 +- dev/tests/static/phpunit.xml.dist | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/dev/tests/static/framework/tests/unit/testsuite/Magento/Sniffs/Html/HtmlBindingSniffTest.php b/dev/tests/static/framework/tests/unit/testsuite/Magento/Sniffs/Html/HtmlBindingSniffTest.php index 8b044f5ba3ee7..8b81bbe5f5431 100644 --- a/dev/tests/static/framework/tests/unit/testsuite/Magento/Sniffs/Html/HtmlBindingSniffTest.php +++ b/dev/tests/static/framework/tests/unit/testsuite/Magento/Sniffs/Html/HtmlBindingSniffTest.php @@ -6,7 +6,7 @@ declare(strict_types=1); -namespace Magento\Sniffs\Less; +namespace Magento\Sniffs\Html; use Magento\TestFramework\CodingStandard\Tool\CodeSniffer\HtmlWrapper; use PHPUnit\Framework\TestCase; diff --git a/dev/tests/static/phpunit.xml.dist b/dev/tests/static/phpunit.xml.dist index 6c02ec1382563..d6db407fb5264 100644 --- a/dev/tests/static/phpunit.xml.dist +++ b/dev/tests/static/phpunit.xml.dist @@ -18,6 +18,9 @@ <testsuite name="Less Static Code Analysis"> <file>testsuite/Magento/Test/Less/LiveCodeTest.php</file> </testsuite> + <testsuite name="HTML Static Code Analysis"> + <file>testsuite/Magento/Test/Html/LiveCodeTest.php</file> + </testsuite> <testsuite name="PHP Coding Standard Verification"> <file>testsuite/Magento/Test/Php/LiveCodeTest.php</file> </testsuite> From 6bcf514e08b497abeccc635779bf6afa67f6766d Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun <ogorkun@magento.com> Date: Wed, 19 Jun 2019 15:18:06 -0500 Subject: [PATCH 491/773] MC-17489: Require specific suffix for HTML binding --- .../testsuite/Magento/Sniffs/Html/HtmlBindingSniffTest.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dev/tests/static/framework/tests/unit/testsuite/Magento/Sniffs/Html/HtmlBindingSniffTest.php b/dev/tests/static/framework/tests/unit/testsuite/Magento/Sniffs/Html/HtmlBindingSniffTest.php index 8b81bbe5f5431..564b28086eeb1 100644 --- a/dev/tests/static/framework/tests/unit/testsuite/Magento/Sniffs/Html/HtmlBindingSniffTest.php +++ b/dev/tests/static/framework/tests/unit/testsuite/Magento/Sniffs/Html/HtmlBindingSniffTest.php @@ -51,10 +51,13 @@ public function testProcess(string $fileUnderTest, string $expectedReportFile): [__DIR__ . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . $fileUnderTest] ); // Remove the absolute path to the file from the output + //phpcs:ignore $actual = preg_replace('/^.+\n/', '', ltrim(file_get_contents($reportFile))); + //phpcs:ignore $expected = file_get_contents( __DIR__ . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . $expectedReportFile ); + //phpcs:ignore unlink($reportFile); $this->assertEquals(1, $result); $this->assertEquals($expected, $actual); From 3df41f2a073ba0b19cc8cdda65c5cd61dd70e348 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun <ogorkun@magento.com> Date: Wed, 19 Jun 2019 15:26:18 -0500 Subject: [PATCH 492/773] MC-17489: Require specific suffix for HTML binding --- .../base/web/templates/grid/filters/elements/ui-select.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/filters/elements/ui-select.html b/app/code/Magento/Ui/view/base/web/templates/grid/filters/elements/ui-select.html index f02616cb1c294..ce2418b1639ae 100644 --- a/app/code/Magento/Ui/view/base/web/templates/grid/filters/elements/ui-select.html +++ b/app/code/Magento/Ui/view/base/web/templates/grid/filters/elements/ui-select.html @@ -142,7 +142,7 @@ <div ifnot="options().length" class="admin__action-multiselect-empty-area"> <ul data-bind=" - html: emptyOptionsHtml + html: emptyOptionsHtmld "/> </div> <!-- /ko --> From 084248165504331c7eb8b62407d83115226fcbd2 Mon Sep 17 00:00:00 2001 From: OlgaVasyltsun <olga.vasyltsun@gmail.com> Date: Thu, 20 Jun 2019 14:14:08 +0300 Subject: [PATCH 493/773] MC-17623: Could not save multiselect/select attribute options when Swatches modules disabled --- .../templates/catalog/product/attribute/js.phtml | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/attribute/js.phtml b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/attribute/js.phtml index 2dc39b97c3d95..f020eddc35dbd 100644 --- a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/attribute/js.phtml +++ b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/attribute/js.phtml @@ -11,9 +11,10 @@ require([ "jquery", 'Magento_Ui/js/modal/alert', 'Magento_Ui/js/modal/prompt', + 'uiRegistry', "collapsable", "prototype" -], function(jQuery, alert, prompt){ +], function(jQuery, alert, prompt, registry){ function toggleApplyVisibility(select) { if ($(select).value == 1) { @@ -39,15 +40,20 @@ function getFrontTab() { function checkOptionsPanelVisibility(){ if($('manage-options-panel')){ - var panel = $('manage-options-panel').up('.fieldset'), + var panelId = 'manage-options-panel', + panel = $(panelId), + panelFieldSet = panel.up('.fieldset'), activePanelClass = 'selected-type-options'; if($('frontend_input') && ($('frontend_input').value=='select' || $('frontend_input').value=='multiselect')){ - panel.show(); + panelFieldSet.show(); jQuery(panel).addClass(activePanelClass); + registry.get(panelId, function () { + jQuery('#' + panelId).trigger('render'); + }); } else { - panel.hide(); + panelFieldSet.hide(); jQuery(panel).removeClass(activePanelClass); } } From db905b8cb6edf9ee6bd933a6d7f718f3147b56d3 Mon Sep 17 00:00:00 2001 From: Viktor Petryk <victor.petryk@transoftgroup.com> Date: Thu, 20 Jun 2019 15:20:58 +0300 Subject: [PATCH 494/773] MC-17269: Date format grid is not based on the locale defined in the back-office --- .../Ui/Component/Listing/Columns/Date.php | 47 ++++++++++++++++++- .../Ui/view/base/web/js/grid/columns/date.js | 2 + 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Ui/Component/Listing/Columns/Date.php b/app/code/Magento/Ui/Component/Listing/Columns/Date.php index ad876b66b6038..1d890aecd1a2a 100644 --- a/app/code/Magento/Ui/Component/Listing/Columns/Date.php +++ b/app/code/Magento/Ui/Component/Listing/Columns/Date.php @@ -3,8 +3,12 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Ui\Component\Listing\Columns; +use Magento\Framework\App\ObjectManager; +use Magento\Framework\Locale\Bundle\DataBundle; +use Magento\Framework\Locale\ResolverInterface; use Magento\Framework\Stdlib\BooleanUtils; use Magento\Framework\View\Element\UiComponent\ContextInterface; use Magento\Framework\View\Element\UiComponentFactory; @@ -28,11 +32,28 @@ class Date extends Column */ private $booleanUtils; + /** + * @var ResolverInterface + */ + private $localeResolver; + + /** + * @var string + */ + private $locale; + + /** + * @var DataBundle + */ + private $dataBundle; + /** * @param ContextInterface $context * @param UiComponentFactory $uiComponentFactory * @param TimezoneInterface $timezone * @param BooleanUtils $booleanUtils + * @param ResolverInterface $localeResolver + * @param DataBundle $dataBundle * @param array $components * @param array $data */ @@ -41,11 +62,16 @@ public function __construct( UiComponentFactory $uiComponentFactory, TimezoneInterface $timezone, BooleanUtils $booleanUtils, + ResolverInterface $localeResolver = null, + DataBundle $dataBundle = null, array $components = [], array $data = [] ) { $this->timezone = $timezone; $this->booleanUtils = $booleanUtils; + $this->localeResolver = $localeResolver ?? ObjectManager::getInstance()->get(ResolverInterface::class); + $this->locale = $this->localeResolver->getLocale(); + $this->dataBundle = $dataBundle ?? ObjectManager::getInstance()->get(DataBundle::class); parent::__construct($context, $uiComponentFactory, $components, $data); } @@ -65,6 +91,25 @@ public function prepare() ] ] ]; + + $localeData = $this->dataBundle->get($this->locale); + /** @var \ResourceBundle $monthsData */ + $monthsData = $localeData['calendar']['gregorian']['monthNames']; + $months = array_values(iterator_to_array($monthsData['format']['wide'])); + $monthsShort = array_values( + iterator_to_array( + null !== $monthsData->get('format')->get('abbreviated') + ? $monthsData['format']['abbreviated'] + : $monthsData['format']['wide'] + ) + ); + + $config['storeLocale'] = $this->locale; + $config['dateData'] = [ + 'months' => $months, + 'monthsShort' => $monthsShort, + ]; + $config['dateFormat'] = $this->timezone->getDateTimeFormat(\IntlDateFormatter::MEDIUM); $this->setData('config', $config); parent::prepare(); @@ -78,7 +123,7 @@ public function prepareDataSource(array $dataSource) if (isset($dataSource['data']['items'])) { foreach ($dataSource['data']['items'] as & $item) { if (isset($item[$this->getData('name')]) - && $item[$this->getData('name')] !== "0000-00-00 00:00:00" + && $item[$this->getData('name')] !== "0000-00-00 00:00:00" ) { $date = $this->timezone->date(new \DateTime($item[$this->getData('name')])); $timezone = isset($this->getConfiguration()['timezone']) diff --git a/app/code/Magento/Ui/view/base/web/js/grid/columns/date.js b/app/code/Magento/Ui/view/base/web/js/grid/columns/date.js index 81c0cc1ccdbb7..bc833100f41ac 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/columns/date.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/columns/date.js @@ -17,6 +17,7 @@ define([ defaults: { dateFormat: 'MMM d, YYYY h:mm:ss A' }, + dateData: [], /** * Overrides base method to normalize date format. @@ -37,6 +38,7 @@ define([ * @returns {String} Formatted date. */ getLabel: function (value, format) { + moment.locale(this.storeLocale, {...this.dateData}); var date = moment(this._super()); date = date.isValid() && value[this.index] ? From 3a31197544e93a29d86e509eb3389813b99735bc Mon Sep 17 00:00:00 2001 From: Viktor Petryk <victor.petryk@transoftgroup.com> Date: Thu, 20 Jun 2019 15:46:50 +0300 Subject: [PATCH 495/773] MC-17269: Date format grid is not based on the locale defined in the back-office --- app/code/Magento/Ui/Component/Listing/Columns/Date.php | 2 +- app/code/Magento/Ui/view/base/web/js/grid/columns/date.js | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Ui/Component/Listing/Columns/Date.php b/app/code/Magento/Ui/Component/Listing/Columns/Date.php index 1d890aecd1a2a..892b310dee445 100644 --- a/app/code/Magento/Ui/Component/Listing/Columns/Date.php +++ b/app/code/Magento/Ui/Component/Listing/Columns/Date.php @@ -105,7 +105,7 @@ public function prepare() ); $config['storeLocale'] = $this->locale; - $config['dateData'] = [ + $config['calendarConfig'] = [ 'months' => $months, 'monthsShort' => $monthsShort, ]; diff --git a/app/code/Magento/Ui/view/base/web/js/grid/columns/date.js b/app/code/Magento/Ui/view/base/web/js/grid/columns/date.js index bc833100f41ac..33d4ac46272c6 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/columns/date.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/columns/date.js @@ -15,9 +15,9 @@ define([ return Column.extend({ defaults: { - dateFormat: 'MMM d, YYYY h:mm:ss A' + dateFormat: 'MMM d, YYYY h:mm:ss A', + calendarConfig: [] }, - dateData: [], /** * Overrides base method to normalize date format. @@ -38,7 +38,9 @@ define([ * @returns {String} Formatted date. */ getLabel: function (value, format) { - moment.locale(this.storeLocale, {...this.dateData}); + if (this.storeLocale !== undefined) { + moment.locale(this.storeLocale, {...this.calendarConfig}); + } var date = moment(this._super()); date = date.isValid() && value[this.index] ? From e8ef05e573edd1eaa14fa4fe43003580c68fd5c6 Mon Sep 17 00:00:00 2001 From: Stas Kozar <stas.kozar@transoftgroup.com> Date: Thu, 20 Jun 2019 16:24:27 +0300 Subject: [PATCH 496/773] MC-17640: Discount amount value is displayed with tags for bundle product in Items Ordered grid --- .../adminhtml/templates/sales/order/view/items/renderer.phtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Bundle/view/adminhtml/templates/sales/order/view/items/renderer.phtml b/app/code/Magento/Bundle/view/adminhtml/templates/sales/order/view/items/renderer.phtml index 280bf67d63787..34b5ee76d3a80 100644 --- a/app/code/Magento/Bundle/view/adminhtml/templates/sales/order/view/items/renderer.phtml +++ b/app/code/Magento/Bundle/view/adminhtml/templates/sales/order/view/items/renderer.phtml @@ -154,7 +154,7 @@ </td> <td class="col-discont"> <?php if ($block->canShowPriceInfo($_item)) : ?> - <?= $block->escapeHtml($block->displayPriceAttribute('discount_amount')) ?> + <?= /* @noEscape */ $block->displayPriceAttribute('discount_amount') ?> <?php else : ?>   <?php endif; ?> From 0c2f66adbaa80666470f6676d52440e6e5fe95a6 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun <ogorkun@magento.com> Date: Thu, 20 Jun 2019 11:52:35 -0500 Subject: [PATCH 497/773] MC-17489: Require specific suffix for HTML binding --- .../base/web/templates/grid/filters/elements/ui-select.html | 4 +--- .../static/framework/Magento/Sniffs/Html/HtmlBindingSniff.php | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/filters/elements/ui-select.html b/app/code/Magento/Ui/view/base/web/templates/grid/filters/elements/ui-select.html index ce2418b1639ae..b9425c020c0e9 100644 --- a/app/code/Magento/Ui/view/base/web/templates/grid/filters/elements/ui-select.html +++ b/app/code/Magento/Ui/view/base/web/templates/grid/filters/elements/ui-select.html @@ -141,9 +141,7 @@ </div> <div ifnot="options().length" class="admin__action-multiselect-empty-area"> - <ul data-bind=" - html: emptyOptionsHtmld - "/> + <ul data-bind="html: emptyOptionsHtml"/> </div> <!-- /ko --> <ul class="admin__action-multiselect-menu-inner _root" diff --git a/dev/tests/static/framework/Magento/Sniffs/Html/HtmlBindingSniff.php b/dev/tests/static/framework/Magento/Sniffs/Html/HtmlBindingSniff.php index 94828d79bc139..02ade2ccb870e 100644 --- a/dev/tests/static/framework/Magento/Sniffs/Html/HtmlBindingSniff.php +++ b/dev/tests/static/framework/Magento/Sniffs/Html/HtmlBindingSniff.php @@ -33,7 +33,7 @@ public function process(File $phpcsFile, $stackPtr) $html = $phpcsFile->getTokensAsString($stackPtr, count($phpcsFile->getTokens())); $dom = new \DOMDocument(); try { - //phpcs: ignore + // phpcs:disable Generic.PHP.NoSilencedErrors @$dom->loadHTML($html); $loaded = true; } catch (\Throwable $exception) { From 3e0e4e263d398a30f68689fc308114c881d4c19d Mon Sep 17 00:00:00 2001 From: Viktor Petryk <victor.petryk@transoftgroup.com> Date: Fri, 21 Jun 2019 08:30:40 +0300 Subject: [PATCH 498/773] MC-17269: Date format grid is not based on the locale defined in the back-office --- app/code/Magento/Ui/view/base/web/js/grid/columns/date.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Ui/view/base/web/js/grid/columns/date.js b/app/code/Magento/Ui/view/base/web/js/grid/columns/date.js index 33d4ac46272c6..1f068ee538a81 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/columns/date.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/columns/date.js @@ -39,7 +39,7 @@ define([ */ getLabel: function (value, format) { if (this.storeLocale !== undefined) { - moment.locale(this.storeLocale, {...this.calendarConfig}); + moment.locale(this.storeLocale, utils.extend({}, this.calendarConfig)); } var date = moment(this._super()); From ddb015e156b01c2df179b42859986f9a46650dab Mon Sep 17 00:00:00 2001 From: Viktor Petryk <victor.petryk@transoftgroup.com> Date: Fri, 21 Jun 2019 08:40:26 +0300 Subject: [PATCH 499/773] MC-17269: Date format grid is not based on the locale defined in the back-office --- app/code/Magento/Ui/Component/Listing/Columns/Date.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Ui/Component/Listing/Columns/Date.php b/app/code/Magento/Ui/Component/Listing/Columns/Date.php index 892b310dee445..112be6c0a46c2 100644 --- a/app/code/Magento/Ui/Component/Listing/Columns/Date.php +++ b/app/code/Magento/Ui/Component/Listing/Columns/Date.php @@ -62,10 +62,10 @@ public function __construct( UiComponentFactory $uiComponentFactory, TimezoneInterface $timezone, BooleanUtils $booleanUtils, - ResolverInterface $localeResolver = null, - DataBundle $dataBundle = null, array $components = [], - array $data = [] + array $data = [], + ResolverInterface $localeResolver = null, + DataBundle $dataBundle = null ) { $this->timezone = $timezone; $this->booleanUtils = $booleanUtils; From 227475fc9326fcf70322b44cec35b2ed9df6cc55 Mon Sep 17 00:00:00 2001 From: Viktor Petryk <victor.petryk@transoftgroup.com> Date: Fri, 21 Jun 2019 15:49:07 +0300 Subject: [PATCH 500/773] MC-17269: Date format grid is not based on the locale defined in the back-office --- app/code/Magento/Ui/Component/Listing/Columns/Date.php | 1 - app/code/Magento/Ui/view/base/web/js/grid/columns/date.js | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Ui/Component/Listing/Columns/Date.php b/app/code/Magento/Ui/Component/Listing/Columns/Date.php index 112be6c0a46c2..6ae27294ce9a2 100644 --- a/app/code/Magento/Ui/Component/Listing/Columns/Date.php +++ b/app/code/Magento/Ui/Component/Listing/Columns/Date.php @@ -109,7 +109,6 @@ public function prepare() 'months' => $months, 'monthsShort' => $monthsShort, ]; - $config['dateFormat'] = $this->timezone->getDateTimeFormat(\IntlDateFormatter::MEDIUM); $this->setData('config', $config); parent::prepare(); diff --git a/app/code/Magento/Ui/view/base/web/js/grid/columns/date.js b/app/code/Magento/Ui/view/base/web/js/grid/columns/date.js index 1f068ee538a81..032a962d94477 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/columns/date.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/columns/date.js @@ -38,10 +38,11 @@ define([ * @returns {String} Formatted date. */ getLabel: function (value, format) { + var date; if (this.storeLocale !== undefined) { moment.locale(this.storeLocale, utils.extend({}, this.calendarConfig)); } - var date = moment(this._super()); + date = moment(this._super()); date = date.isValid() && value[this.index] ? date.format(format || this.dateFormat) : From 97606cf048c78763762ae21f30d50d8b998bff9d Mon Sep 17 00:00:00 2001 From: Lusine Papyan <Lusine_Papyan@epam.com> Date: Wed, 3 Apr 2019 11:19:10 +0400 Subject: [PATCH 501/773] MAGETWO-98708: Invalid linked products data for cloned products with duplicate URL keys - Added automated test script --- .../ActionGroup/AdminProductActionGroup.xml | 2 +- ...inProductRelatedUpSellCrossSellSection.xml | 1 + .../AdminCloneProductWithDuplicateUrlTest.xml | 77 +++++++++++++++++++ 3 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 app/code/Magento/Catalog/Test/Mftf/Test/AdminCloneProductWithDuplicateUrlTest.xml diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductActionGroup.xml index 992d7fe644f22..bb34abde49652 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductActionGroup.xml @@ -274,7 +274,7 @@ <fillField selector="{{AdminProductGridFilterSection.skuFilter}}" userInput="{{sku}}" stepKey="fillProductSkuFilter"/> <click selector="{{AdminProductGridFilterSection.applyFilters}}" stepKey="clickApplyFilters"/> <waitForPageLoad stepKey="waitForPageToLoad"/> - <checkOption selector="{{AdminProductModalSlideGridSection.productRowCheckboxBySku(sku)}}" stepKey="selectProduct"/> + <click selector="{{AdminProductModalSlideGridSection.productGridXRowYColumnButton('1', '1')}}" stepKey="selectProduct"/> <click selector="{{AdminAddRelatedProductsModalSection.AddSelectedProductsButton}}" stepKey="addRelatedProductSelected"/> </actionGroup> diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductRelatedUpSellCrossSellSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductRelatedUpSellCrossSellSection.xml index ef596bed186e5..f3b0d3a895cb1 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductRelatedUpSellCrossSellSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductRelatedUpSellCrossSellSection.xml @@ -20,6 +20,7 @@ <element name="relatedDependent" type="block" selector="//div[@data-index='related']//div[contains(@class, '_show')]"/> <element name="selectedRelatedProduct" type="block" selector="//span[@data-index='name']"/> <element name="removeRelatedProduct" type="button" selector="//span[text()='Related Products']//..//..//..//span[text()='{{productName}}']//..//..//..//..//..//button[@class='action-delete']" parameterized="true"/> + <element name="selectedProductSku" type="text" selector="//div[@data-index='{{section}}']//span[@data-index='sku']" parameterized="true" timeout="30"/> </section> <section name="AdminAddUpSellProductsModalSection"> <element name="Modal" type="button" selector=".product_form_product_form_related_upsell_modal"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCloneProductWithDuplicateUrlTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCloneProductWithDuplicateUrlTest.xml new file mode 100644 index 0000000000000..664b501303525 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCloneProductWithDuplicateUrlTest.xml @@ -0,0 +1,77 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AdminCloneProductWithDuplicateUrlTest"> + <annotations> + <features value="Catalog"/> + <title value="Cloning a product with duplicate URL key"/> + <description value="Check product cloning with duplicate URL key"/> + <severity value="AVERAGE"/> + <testCaseId value="MAGETWO-98992"/> + <useCaseId value="MAGETWO-98708"/> + <group value="catalog"/> + </annotations> + <before> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + <!--Create category and product--> + <comment userInput="Create category and product" stepKey="commentCreateCategoryAndProduct"/> + <createData entity="SimpleProduct2" stepKey="createSimpleProduct"/> + </before> + <after> + <!--Delete created data--> + <comment userInput="Delete created data" stepKey="commentDeleteCreatedData"/> + <actionGroup ref="deleteAllDuplicateProductUsingProductGrid" stepKey="deleteAllDuplicateProducts"> + <argument name="product" value="$$createSimpleProduct$$"/> + </actionGroup> + <actionGroup ref="resetProductGridToDefaultView" stepKey="resetFiltersIfExist"/> + <actionGroup ref="logout" stepKey="logoutOfAdmin"/> + </after> + <amOnPage url="{{AdminProductEditPage.url($$createSimpleProduct.id$$)}}" stepKey="goToProductEditPage"/> + <waitForPageLoad stepKey="waitForSimpleProductPageLoad"/> + <!--Save and duplicated the product once--> + <comment userInput="Save and duplicated the product once" stepKey="commentSaveAndDuplicateProduct"/> + <actionGroup ref="AdminFormSaveAndDuplicate" stepKey="saveAndDuplicateProductFormFirstTime"/> + <conditionalClick selector="{{AdminProductSEOSection.sectionHeader}}" dependentSelector="{{AdminProductSEOSection.urlKeyInput}}" visible="false" stepKey="openSEOSection"/> + <grabValueFrom selector="{{AdminProductSEOSection.urlKeyInput}}" stepKey="grabDuplicatedProductUrlKey"/> + <assertContains expected="$$createSimpleProduct.custom_attributes[url_key]$$" actual="$grabDuplicatedProductUrlKey" stepKey="assertDuplicatedProductUrlKey"/> + <assertContains expectedType="string" expected="-1" actual="$grabDuplicatedProductUrlKey" stepKey="assertDuplicatedProductUrlKey1"/> + <!--Add duplicated product to the simple product--> + <comment userInput="Add duplicated product to the simple product" stepKey="commentAddProduct"/> + <amOnPage url="{{AdminProductEditPage.url($$createSimpleProduct.id$$)}}" stepKey="goToSimpleProductPage"/> + <waitForPageLoad stepKey="waitForSimpleProductPageLoad1"/> + <actionGroup ref="addCrossSellProductBySku" stepKey="addCrossSellProduct"> + <argument name="sku" value="$$createSimpleProduct.sku$$"/> + </actionGroup> + <actionGroup ref="addRelatedProductBySku" stepKey="addRelatedProduct"> + <argument name="sku" value="$$createSimpleProduct.sku$$"/> + </actionGroup> + <actionGroup ref="addUpSellProductBySku" stepKey="addUpSellProduct"> + <argument name="sku" value="$$createSimpleProduct.sku$$"/> + </actionGroup> + <actionGroup ref="saveProductForm" stepKey="clickSaveProduct"/> + <conditionalClick selector="{{AdminProductFormRelatedUpSellCrossSellSection.sectionHeader}}" dependentSelector="{{AdminProductFormRelatedUpSellCrossSellSection.AddRelatedProductsButton}}" visible="false" stepKey="openProductRUSSection"/> + <see selector="{{AdminProductFormRelatedUpSellCrossSellSection.selectedProductSku('related')}}" userInput="$$createSimpleProduct.sku$$-1" stepKey="seeRelatedProduct"/> + <see selector="{{AdminProductFormRelatedUpSellCrossSellSection.selectedProductSku('upsell')}}" userInput="$$createSimpleProduct.sku$$-1" stepKey="seeUpSellProduct"/> + <see selector="{{AdminProductFormRelatedUpSellCrossSellSection.selectedProductSku('crosssell')}}" userInput="$$createSimpleProduct.sku$$-1" stepKey="seeCrossSellProduct"/> + <!--Save and duplicated the product second time--> + <comment userInput="Save and duplicated the product second time" stepKey="commentSaveAndDuplicateProduct1"/> + <amOnPage url="{{AdminProductEditPage.url($$createSimpleProduct.id$$)}}" stepKey="goToProductEditPage1"/> + <waitForPageLoad stepKey="waitForSimpleProductPageLoad2"/> + <actionGroup ref="AdminFormSaveAndDuplicate" stepKey="saveAndDuplicateProductFormSecondTime"/> + <conditionalClick selector="{{AdminProductSEOSection.sectionHeader}}" dependentSelector="{{AdminProductSEOSection.urlKeyInput}}" visible="false" stepKey="openProductSEOSection"/> + <grabValueFrom selector="{{AdminProductSEOSection.urlKeyInput}}" stepKey="grabSecondDuplicatedProductUrlKey"/> + <assertContains expected="$$createSimpleProduct.custom_attributes[url_key]$$" actual="$grabSecondDuplicatedProductUrlKey" stepKey="assertSecondDuplicatedProductUrlKey"/> + <assertContains expectedType="string" expected="-2" actual="$grabSecondDuplicatedProductUrlKey" stepKey="assertSecondDuplicatedProductUrlKey1"/> + <conditionalClick selector="{{AdminProductFormRelatedUpSellCrossSellSection.sectionHeader}}" dependentSelector="{{AdminProductFormRelatedUpSellCrossSellSection.AddRelatedProductsButton}}" visible="false" stepKey="openProductRUSSection1"/> + <see selector="{{AdminProductFormRelatedUpSellCrossSellSection.selectedProductSku('related')}}" userInput="$$createSimpleProduct.sku$$-1" stepKey="seeRelatedProductForDuplicated"/> + <see selector="{{AdminProductFormRelatedUpSellCrossSellSection.selectedProductSku('upsell')}}" userInput="$$createSimpleProduct.sku$$-1" stepKey="seeUpSellProductForDuplicated"/> + <see selector="{{AdminProductFormRelatedUpSellCrossSellSection.selectedProductSku('crosssell')}}" userInput="$$createSimpleProduct.sku$$-1" stepKey="seeCrossSellProductForDuplicated"/> + </test> +</tests> From 30055c5f9ec8a671f8811a7f4682c2acc413b10d Mon Sep 17 00:00:00 2001 From: Lusine Papyan <Lusine_Papyan@epam.com> Date: Wed, 19 Jun 2019 12:57:09 +0400 Subject: [PATCH 502/773] MAGETWO-98708: Invalid linked products data for cloned products with duplicate URL keys - Updated automated test script. --- .../Catalog/Test/Mftf/ActionGroup/AdminProductActionGroup.xml | 1 + .../Test/Mftf/Test/AdminCloneProductWithDuplicateUrlTest.xml | 2 ++ 2 files changed, 3 insertions(+) diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductActionGroup.xml index bb34abde49652..5ec8c5015d476 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductActionGroup.xml @@ -276,6 +276,7 @@ <waitForPageLoad stepKey="waitForPageToLoad"/> <click selector="{{AdminProductModalSlideGridSection.productGridXRowYColumnButton('1', '1')}}" stepKey="selectProduct"/> <click selector="{{AdminAddRelatedProductsModalSection.AddSelectedProductsButton}}" stepKey="addRelatedProductSelected"/> + <waitForElementNotVisible selector="{{AdminAddRelatedProductsModalSection.AddSelectedProductsButton}}" stepKey="waitForElementNotVisible"/> </actionGroup> <!--Click AddCrossSellProducts and adds product by SKU--> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCloneProductWithDuplicateUrlTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCloneProductWithDuplicateUrlTest.xml index 664b501303525..295351b00bf60 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCloneProductWithDuplicateUrlTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCloneProductWithDuplicateUrlTest.xml @@ -66,10 +66,12 @@ <waitForPageLoad stepKey="waitForSimpleProductPageLoad2"/> <actionGroup ref="AdminFormSaveAndDuplicate" stepKey="saveAndDuplicateProductFormSecondTime"/> <conditionalClick selector="{{AdminProductSEOSection.sectionHeader}}" dependentSelector="{{AdminProductSEOSection.urlKeyInput}}" visible="false" stepKey="openProductSEOSection"/> + <waitForElementVisible selector="{{AdminProductSEOSection.urlKeyInput}}" stepKey="waitForUrlKeyField"/> <grabValueFrom selector="{{AdminProductSEOSection.urlKeyInput}}" stepKey="grabSecondDuplicatedProductUrlKey"/> <assertContains expected="$$createSimpleProduct.custom_attributes[url_key]$$" actual="$grabSecondDuplicatedProductUrlKey" stepKey="assertSecondDuplicatedProductUrlKey"/> <assertContains expectedType="string" expected="-2" actual="$grabSecondDuplicatedProductUrlKey" stepKey="assertSecondDuplicatedProductUrlKey1"/> <conditionalClick selector="{{AdminProductFormRelatedUpSellCrossSellSection.sectionHeader}}" dependentSelector="{{AdminProductFormRelatedUpSellCrossSellSection.AddRelatedProductsButton}}" visible="false" stepKey="openProductRUSSection1"/> + <waitForElementVisible selector="{{AdminProductFormRelatedUpSellCrossSellSection.selectedProductSku('related')}}" stepKey="waitForSelectedProductSku"/> <see selector="{{AdminProductFormRelatedUpSellCrossSellSection.selectedProductSku('related')}}" userInput="$$createSimpleProduct.sku$$-1" stepKey="seeRelatedProductForDuplicated"/> <see selector="{{AdminProductFormRelatedUpSellCrossSellSection.selectedProductSku('upsell')}}" userInput="$$createSimpleProduct.sku$$-1" stepKey="seeUpSellProductForDuplicated"/> <see selector="{{AdminProductFormRelatedUpSellCrossSellSection.selectedProductSku('crosssell')}}" userInput="$$createSimpleProduct.sku$$-1" stepKey="seeCrossSellProductForDuplicated"/> From ea28e518daaa0ab188f2a413422facc060d37a4c Mon Sep 17 00:00:00 2001 From: Maria Kovdrysh <kovdrysh@adobe.com> Date: Fri, 21 Jun 2019 15:31:32 -0500 Subject: [PATCH 503/773] MC-6436: Configuring Instant Purchase functionality Delete Braintree secure data --- .../ConfigureBraintreeActionGroup.xml | 4 +- .../Test/Mftf/Data/BraintreeData.xml | 42 ------------------- .../BraintreeCreditCardOnCheckoutTest.xml | 3 ++ ...AnAdminOrderUsingBraintreePaymentTest1.xml | 3 ++ ...guringInstantPurchaseFunctionalityTest.xml | 3 ++ 5 files changed, 11 insertions(+), 44 deletions(-) diff --git a/app/code/Magento/Braintree/Test/Mftf/ActionGroup/ConfigureBraintreeActionGroup.xml b/app/code/Magento/Braintree/Test/Mftf/ActionGroup/ConfigureBraintreeActionGroup.xml index cbb065704fbc1..f2c050006d010 100644 --- a/app/code/Magento/Braintree/Test/Mftf/ActionGroup/ConfigureBraintreeActionGroup.xml +++ b/app/code/Magento/Braintree/Test/Mftf/ActionGroup/ConfigureBraintreeActionGroup.xml @@ -7,7 +7,7 @@ --> <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - + <!-- Skip by MQE-1576 --> <actionGroup name="ConfigureBraintree"> <!-- GoTo ConfigureBraintree fields --> <click stepKey="clickOnSTORES" selector="{{AdminMenuSection.stores}}"/> @@ -50,4 +50,4 @@ <magentoCLI stepKey="disableBrainTree" command="config:set payment/braintree/active 0"/> <magentoCLI stepKey="disableBrainTreePaypal" command="config:set payment/braintree_paypal/active 0"/> </actionGroup> -</actionGroups> \ No newline at end of file +</actionGroups> diff --git a/app/code/Magento/Braintree/Test/Mftf/Data/BraintreeData.xml b/app/code/Magento/Braintree/Test/Mftf/Data/BraintreeData.xml index 6d00df535704a..2bedb6509344b 100644 --- a/app/code/Magento/Braintree/Test/Mftf/Data/BraintreeData.xml +++ b/app/code/Magento/Braintree/Test/Mftf/Data/BraintreeData.xml @@ -35,34 +35,6 @@ <data key="value">somePrivateKey</data> </entity> - <entity name="BraintreeConfig" type="braintree_config_state"> - <requiredEntity type="title">BraintreeTitle</requiredEntity> - <requiredEntity type="payment_action">PaymentAction</requiredEntity> - <requiredEntity type="environment">Environment</requiredEntity> - <requiredEntity type="merchant_id">MerchantId</requiredEntity> - <requiredEntity type="public_key">PublicKey</requiredEntity> - <requiredEntity type="private_key">PrivateKey</requiredEntity> - <requiredEntity type="active">Status</requiredEntity> - </entity> - <entity name="BraintreeTitle" type="title"> - <data key="value">Credit Card (Braintree)</data> - </entity> - <entity name="PaymentAction" type="payment_action"> - <data key="value">authorize</data> - </entity> - <entity name="Environment" type="environment"> - <data key="value">sandbox</data> - </entity> - <entity name="MerchantId" type="merchant_id"> - <data key="value">d4pdjhxgjfrsmzbf</data> - </entity> - <entity name="PublicKey" type="public_key"> - <data key="value">m7q4wmh43xrgyrst</data> - </entity> - <entity name="PrivateKey" type="private_key"> - <data key="value">67de364080b1b4e2492d7a3de413a572</data> - </entity> - <!-- default configuration used to restore Magento config --> <entity name="DefaultBraintreeConfig" type="braintree_config_state"> <requiredEntity type="title">DefaultTitle</requiredEntity> @@ -138,18 +110,4 @@ <data key="year">20</data> <data key="cvv">113</data> </entity> - <entity name="StoredPaymentMethods"> - <data key="cardNumberEnding">5100</data> - <data key="cardExpire">12/2020</data> - </entity> - - <entity name="BraintreeConfigurationData" type="data"> - <data key="title">Credit Card (Braintree)</data> - <data key="merchantID">d4pdjhxgjfrsmzbf</data> - <data key="publicKey">m7q4wmh43xrgyrst</data> - <data key="privateKey">67de364080b1b4e2492d7a3de413a572</data> - <data key="merchantAccountID">Magneto</data> - <data key="titleForPayPalThroughBraintree">PayPal (Braintree)</data> - </entity> - </entities> diff --git a/app/code/Magento/Braintree/Test/Mftf/Test/BraintreeCreditCardOnCheckoutTest.xml b/app/code/Magento/Braintree/Test/Mftf/Test/BraintreeCreditCardOnCheckoutTest.xml index ac653638b53a0..9a1110bfda29a 100644 --- a/app/code/Magento/Braintree/Test/Mftf/Test/BraintreeCreditCardOnCheckoutTest.xml +++ b/app/code/Magento/Braintree/Test/Mftf/Test/BraintreeCreditCardOnCheckoutTest.xml @@ -17,6 +17,9 @@ <severity value="MAJOR"/> <testCaseId value="MAGETWO-93767"/> <group value="braintree"/> + <skip> + <issueId value="MQE-1576"/> + </skip> </annotations> <before> diff --git a/app/code/Magento/Braintree/Test/Mftf/Test/CreateAnAdminOrderUsingBraintreePaymentTest1.xml b/app/code/Magento/Braintree/Test/Mftf/Test/CreateAnAdminOrderUsingBraintreePaymentTest1.xml index 244052371e702..2594d245f9ff0 100644 --- a/app/code/Magento/Braintree/Test/Mftf/Test/CreateAnAdminOrderUsingBraintreePaymentTest1.xml +++ b/app/code/Magento/Braintree/Test/Mftf/Test/CreateAnAdminOrderUsingBraintreePaymentTest1.xml @@ -17,6 +17,9 @@ <severity value="CRITICAL"/> <testCaseId value="MAGETWO-93677"/> <group value="braintree"/> + <skip> + <issueId value="MQE-1576"/> + </skip> </annotations> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/ConfiguringInstantPurchaseFunctionalityTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/ConfiguringInstantPurchaseFunctionalityTest.xml index ead9927891989..0897e20f1b17d 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/ConfiguringInstantPurchaseFunctionalityTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/ConfiguringInstantPurchaseFunctionalityTest.xml @@ -17,6 +17,9 @@ <severity value="CRITICAL"/> <testCaseId value="MC-6436"/> <group value="checkout"/> + <skip> + <issueId value="MQE-1576"/> + </skip> </annotations> <before> <!-- Configure Braintree Vault-enabled payment method --> From 471fd852fe8ddbd489f9a77aecbbc37e8a15f1cd Mon Sep 17 00:00:00 2001 From: shankar <konar.shankar2013@gmail.com> Date: Fri, 21 Jun 2019 19:58:06 +0530 Subject: [PATCH 504/773] Added data validation for the input box (+3 squashed commit) Squashed commit: [1a39c41fdfe] Added clientside validation [b3f97d9a78d] Added PHP Doc block for class [fdb75fff538] error message added if qty is left empty --- .../view/frontend/templates/checkout/addresses.phtml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Multishipping/view/frontend/templates/checkout/addresses.phtml b/app/code/Magento/Multishipping/view/frontend/templates/checkout/addresses.phtml index faf08f77c02f3..9fa2eee2788ff 100644 --- a/app/code/Magento/Multishipping/view/frontend/templates/checkout/addresses.phtml +++ b/app/code/Magento/Multishipping/view/frontend/templates/checkout/addresses.phtml @@ -62,8 +62,8 @@ name="ship[<?= $block->escapeHtml($_index) ?>][<?= $block->escapeHtml($_item->getQuoteItemId()) ?>][qty]" value="<?= $block->escapeHtml($_item->getQty()) ?>" size="2" - class="input-text qty" - data-validate="{number: true}"/> + class="input-text qty required-entry" + data-validate="{number: true, required:true}"/> </div> </div> </td> From 2c363e36d0d038535d6bdc5c89ba076c3d3682d7 Mon Sep 17 00:00:00 2001 From: Patrick McLain <pat@pmclain.com> Date: Sat, 22 Jun 2019 14:20:17 -0400 Subject: [PATCH 505/773] USPS Client Mock Mock client returning response data for domestic and iternational USPS rate requests. Un-skip USPS graphql tests. Fixes magento/graphql-ce#739 --- .../TestModuleUsps/Model/MockAsyncClient.php | 60 ++ .../Model/MockDeferredResponse.php | 64 ++ .../Model/MockResponseBodyLoader.php | 68 ++ .../_files/mock_response_ca.xml | 780 ++++++++++++++++++ .../_files/mock_response_us.xml | 123 +++ .../_files/Magento/TestModuleUsps/etc/di.xml | 14 + .../Magento/TestModuleUsps/etc/module.xml | 10 + .../Magento/TestModuleUsps/registration.php | 11 + .../Usps/SetUspsShippingMethodsOnCartTest.php | 12 - .../_files/enable_usps_shipping_method.php | 14 +- .../enable_usps_shipping_method_rollback.php | 3 +- 11 files changed, 1132 insertions(+), 27 deletions(-) create mode 100644 dev/tests/api-functional/_files/Magento/TestModuleUsps/Model/MockAsyncClient.php create mode 100644 dev/tests/api-functional/_files/Magento/TestModuleUsps/Model/MockDeferredResponse.php create mode 100644 dev/tests/api-functional/_files/Magento/TestModuleUsps/Model/MockResponseBodyLoader.php create mode 100644 dev/tests/api-functional/_files/Magento/TestModuleUsps/_files/mock_response_ca.xml create mode 100644 dev/tests/api-functional/_files/Magento/TestModuleUsps/_files/mock_response_us.xml create mode 100644 dev/tests/api-functional/_files/Magento/TestModuleUsps/etc/di.xml create mode 100644 dev/tests/api-functional/_files/Magento/TestModuleUsps/etc/module.xml create mode 100644 dev/tests/api-functional/_files/Magento/TestModuleUsps/registration.php diff --git a/dev/tests/api-functional/_files/Magento/TestModuleUsps/Model/MockAsyncClient.php b/dev/tests/api-functional/_files/Magento/TestModuleUsps/Model/MockAsyncClient.php new file mode 100644 index 0000000000000..c5c23e8710005 --- /dev/null +++ b/dev/tests/api-functional/_files/Magento/TestModuleUsps/Model/MockAsyncClient.php @@ -0,0 +1,60 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\TestModuleUsps\Model; + +use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\HTTP\AsyncClient\HttpResponseDeferredInterface; +use Magento\Framework\HTTP\AsyncClient\Request; +use Magento\Framework\HTTP\AsyncClient\ResponseFactory; +use Magento\Framework\HTTP\AsyncClientInterface; + +/** + * Mock async client returns USPS rate responses + */ +class MockAsyncClient implements AsyncClientInterface +{ + /** + * @var MockResponseBodyLoader + */ + private $mockResponseBodyLoader; + + /** + * @var ResponseFactory + */ + private $responseFactory; + + /** + * @param MockResponseBodyLoader $mockResponseBodyLoader + * @param ResponseFactory $responseFactory + */ + public function __construct( + MockResponseBodyLoader $mockResponseBodyLoader, + ResponseFactory $responseFactory + ) { + $this->mockResponseBodyLoader = $mockResponseBodyLoader; + $this->responseFactory = $responseFactory; + } + + /** + * Fetch mock USPS rate response + * + * @param Request $request + * @return HttpResponseDeferredInterface + * @throws LocalizedException + */ + public function request(Request $request): HttpResponseDeferredInterface + { + return new MockDeferredResponse( + $this->responseFactory->create([ + 'statusCode' => 200, + 'headers' => [], + 'body' => $this->mockResponseBodyLoader->loadForRequest($request), + ]) + ); + } +} diff --git a/dev/tests/api-functional/_files/Magento/TestModuleUsps/Model/MockDeferredResponse.php b/dev/tests/api-functional/_files/Magento/TestModuleUsps/Model/MockDeferredResponse.php new file mode 100644 index 0000000000000..30c9b1080812a --- /dev/null +++ b/dev/tests/api-functional/_files/Magento/TestModuleUsps/Model/MockDeferredResponse.php @@ -0,0 +1,64 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\TestModuleUsps\Model; + +use Magento\Framework\Async\CancelingDeferredException; +use Magento\Framework\HTTP\AsyncClient\HttpResponseDeferredInterface; +use Magento\Framework\HTTP\AsyncClient\Response; + +/** + * Mock for HTTP responses. + */ +class MockDeferredResponse implements HttpResponseDeferredInterface +{ + /** + * @var Response + */ + private $response; + + /** + * MockDeferredResponse constructor. + * @param Response $response + */ + public function __construct(Response $response) + { + $this->response = $response; + } + + /** + * @inheritDoc + */ + public function cancel(bool $force = false): void + { + throw new CancelingDeferredException('Cannot be canceled'); + } + + /** + * @inheritDoc + */ + public function isCancelled(): bool + { + return false; + } + + /** + * @inheritDoc + */ + public function isDone(): bool + { + return true; + } + + /** + * @inheritDoc + */ + public function get(): Response + { + return $this->response; + } +} diff --git a/dev/tests/api-functional/_files/Magento/TestModuleUsps/Model/MockResponseBodyLoader.php b/dev/tests/api-functional/_files/Magento/TestModuleUsps/Model/MockResponseBodyLoader.php new file mode 100644 index 0000000000000..63f64940a45fc --- /dev/null +++ b/dev/tests/api-functional/_files/Magento/TestModuleUsps/Model/MockResponseBodyLoader.php @@ -0,0 +1,68 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\TestModuleUsps\Model; + +use Magento\Framework\Exception\NotFoundException; +use Magento\Framework\HTTP\AsyncClient\Request; +use Magento\Framework\Module\Dir; +use Magento\Framework\Filesystem\Io\File; + +/** + * Load mock response body for USPS rate request + */ +class MockResponseBodyLoader +{ + private const RESPONSE_FILE_PATTERN = '%s/_files/mock_response_%s.xml'; + + /** + * @var Dir + */ + private $moduleDirectory; + + /** + * @var File + */ + private $fileIo; + + /** + * @param Dir $moduleDirectory + * @param File $fileIo + */ + public function __construct( + Dir $moduleDirectory, + File $fileIo + ) { + $this->moduleDirectory = $moduleDirectory; + $this->fileIo = $fileIo; + } + + /** + * Loads mock response xml for a given request + * + * @param Request $request + * @return string + * @throws NotFoundException + */ + public function loadForRequest(Request $request): string + { + $moduleDir = $this->moduleDirectory->getDir('Magento_TestModuleUsps'); + + $destination = 'us'; + if (strpos($request->getUrl(), 'IntlRateV2Request')) { + $destination = 'ca'; + } + + $responsePath = sprintf(static::RESPONSE_FILE_PATTERN, $moduleDir, $destination); + + if (!$this->fileIo->fileExists($responsePath)) { + throw new NotFoundException(__('%1 is not a valid destination country.', $destination)); + } + + return $this->fileIo->read($responsePath); + } +} diff --git a/dev/tests/api-functional/_files/Magento/TestModuleUsps/_files/mock_response_ca.xml b/dev/tests/api-functional/_files/Magento/TestModuleUsps/_files/mock_response_ca.xml new file mode 100644 index 0000000000000..80b4f5048a957 --- /dev/null +++ b/dev/tests/api-functional/_files/Magento/TestModuleUsps/_files/mock_response_ca.xml @@ -0,0 +1,780 @@ +<?xml version="1.0" encoding="UTF-8"?> +<IntlRateV2Response> + <Package ID="0"> + <Prohibitions>An issue of a publication in which more than 5 percent of its total advertising space is primarily + directed to a Canadian market and which indicates: + (a) Specifically where goods or services may be obtained in Canada, or + (b) Specific items or conditions relating to the sale or provision of goods or services in Canada. + All alcoholic beverages including wines, etc. + An issue of a publication that contains an advertisement primarily directed to a Canadian market is a + prohibited import if that advertisement does not appear in identical form in all editions of the issue + distributed in the country of origin. + Articles so marked as to create the false impression that they were made in Canada, Great Britain or any + other British country. + Commercial tags of metal. + Firearms, except as follows: Firearms may be mailed to Canada provided that they meet the requirements in + DMM 601.11.1, 601.11.2, 601.11.3, and 601.11.6 and that the importer has the required documentation. + Customers must visit http://cbsa-asfc.gc.ca/publications/pub/bsf5044-eng.html prior to mailing for Canadian + import requirements. + Gold bullion, gold dust, and nonmanufactured precious metals. + Non-refillable lighters or any other lighter that contains fuel. New lighters with no fuel may be sent. + Oleomargarine and other butter substitutes, including altered or renovated butter. + Perishable infectious biological substances. + Perishable noninfectious biological substances. + Plumage and skins of wild birds. + Prison-made goods being sold or intended for sale by a person or firm. + Radioactive materials. + Replica or inert munitions, as well as other devices that simulate explosive devices or munitions, including + replica or inert grenades or other simulated military munitions, whether or not such items are for display + purposes. + Reprints of Canadian or British works copyrighted in Canada. + Reproductions of Canadian postage stamps unless printed in publications in black and white only and with a + defacing line drawn across each reproduction. + Shipments bearing caution labels indicating the contents are flammable. + Smoke-making devices for motor vehicles and boats. + Used or secondhand hives or bee supplies. + </Prohibitions> + <Restrictions>Coins; banknotes; currency notes; securities payable to bearer; traveler's checks; gold, silver, + platinum, manufactured or not; jewelry; and other valuable articles may be sent only in registered items + First-Class Package International Service with Registered Mail service. + Exceptions: + Coins sent to or from collectors or dealers may be mailed in ordinary (uninsured) parcels. + Drugs and medicines must comply with Canadian law. + Eggs for hatching must be packed in new, clean containers and accompanied by a certificate issued by a + veterinarian of the U.S. Department of Agriculture, or one issued by a State veterinarian and endorsed by a + veterinarian of that Bureau, stating that to the best of his or her knowledge the eggs come from a flock + that is free from Newcastle disease, fowl pest, or fowl typhoid. See 135.3 for method of packing. + Meat and meat food products must be accompanied by an export certificate issued by the U.S. Department of + Agriculture and labeled in accordance with Canadian regulations. Exception to these requirements are: + 1. bona fide sample shipments weighing less than 10 kg; + 2. meat products addressed to a government department or agency; + 3. meat products intended for personal consumption when they enter Canada in the possession of the importer. + Precious stones, set or not set; all items used as dress ornaments and coming under the term "jewelry" + including articles of gold or other precious metal for personal use such as cigarette holders, cases, powder + cases, card cases, opera glasses, fountain pens, watches, etc., are permitted in insured parcels provided + the articles have value not over $5 U.S. A parcel containing a number of such articles valued at $5 or less + may be insured for the total value of the contents up to a maximum of $200. + Veterinary biological products including serums and vaccines must be accompanied by a permit issued by the + Veterinary Director General, Ministry of Agriculture of Canada. + </Restrictions> + <Observations>1. Electronic smoking products (i.e., electronic products for the vaporization and administration + of inhaled doses of nicotine including electronic cigarettes, cigars, cigarillos, and pipes, as well as + cartridges of nicotine solutions and related products) require market authorization by Department of Health + Canada prior to being imported. Failure to obtain this authorization will result in the items being refused + entry by Canada Border Services Agency (CBSA). For additional information, refer to the Department of Health + Canada website at http://www.hc-sc.gc.ca/dhp-mps/prodpharma/applic-demande/pol/notice_avis_e-cig-eng.php. + 2. Banknotes valued at $100 or more must be put up in a compact package and securely tied with strong twine + before wrapping. The wrapper must be linen or other strong, woven material, linen lined paper, or two + thicknesses of strong kraft paper. After wrapping, the package must be again securely tied or stitched and + sealed at the points of closing. + 3. The name of the Canadian province in which the office of destination is located must appear as part of + the address. + 4. The following must not be accepted for insurance: + Bees, postage stamps (canceled and uncanceled) and albums in which they are mounted, and parcels addressed + to CFPOs. + 5. Canadian Forces Mail (CFPO) is processed through Canadian military post offices and must be addressed in + the following manner: + (a) NUMBER, RANK, NAME UNIT + (b) CFPO (NUMBER) + (c) BELLEVILLE ON K0K 3R0 + (d) CANADA + Maximum weight limits for mail addressed to members of the Canadian Forces based outside of Canada (CFPO) is + 22 pounds. Parcels for CFPO addresses may not be insured. Direct sacks of printed matter (M-bags) are not + permitted for CFPO addresses. + 6. A letter fully prepaid and bearing the same address as that of a parcel may be tied or otherwise securely + attached to the outside of the parcel. Stamps to cover postage on the parcel must be affixed to the wrapper + of the parcel. Stamps to pay postage on the letter must be affixed to the envelope thereof. + 7. Certain types of merchandise must be marked to show country of origin in the manner prescribed by the + Canadian customs regulations. + 8. Goods valued under 20 Canadian dollars are duty and excise tax exempt. Goods over 20 Canadian dollars + will be subject to the applicable duties and excise taxes. Gift shipments received by mail that are valued + under 60 Canadian dollars are duty and excise tax exempt. + 9. For all casual and commercial goods valued at or under 1,600 Canadian dollars, Canada Post will collect + assessed duties, excise taxes, and a handling fee from the addressee. This handling fee is set by Canada + Post (see http://www.canadapost.ca/tools/pg/manual/PGcustoms-e.asp). All commercial mail items over 1,600 + Canadian dollars will be held by Canada Customs and Excise until proper invoice and accounting documentation + is provided by the addressee. + 10. The Canada Customs Invoice can be obtained from stationery, office supply, or printing companies. If + mailers are unable to obtain the Canada Customs Invoice locally, they should visit the following Web site: + www.canadapost.ca. In addition, commercial invoices are acceptable provided that each invoice has the + required information for customs purposes. + 11. Information on Canadian customs regulations may be obtained from the Office of International + Marketing/223, Bureau of International Commerce, Department of Commerce, Washington, DC 20230, or any field + office of that Department. + Obtaining post code information: + 12. Information on Canadian post code directories can be obtained from: + (a) NATIONAL PHILATELIC CENTER + CANADA POST CORPORATION + STATION 1 + ANTIGONISH NS B2G 2R8 + Telephone: 1-800-565-4362 + Fax: 1-902-863-6796 + (b) To obtain Canadian post codes for specific addresses, call the General Information line at + 1-416-979-8822 or access the Canada Post Corporation web site on the Internet at http://www.canadapost.ca. + 13. Pursuant to the Canada Customs Act and a need to heighten border security, Canada will deny entry of all + postal items (except postcards) that do not bear complete sender and addressee information in roman letters + and arabic numerals. + </Observations> + <CustomsForms>First-Class Mail International items and Priority Mail International Flat Rate Envelopes and Small + Flat Rate Boxes: + PS Form 2976 (see 123.61) + Priority Mail International parcels: + PS Form 2976-A inside 2976-E (envelope) + </CustomsForms> + <ExpressMail>Country Code: + CA + + Reciprocal Service Name: + There is no reciprocal service. + + Required Customs Form/Endorsement + 1. Business papers and commercial documents. + PS Form 2976-B placed inside PS Form 2976-E (plastic envelope). + + 2. Merchandise samples and gift shipments (non-commercial parcels). + PS Form 2976-B placed inside PS Form 2976-E (plastic envelope). + + 3. Merchandise (commercial shipments) and all articles subject to customs duty. + PS Form 2976-B placed inside PS Form 2976-E (plastic envelope). + + + Notes: + 1. Gift shipments (non-commercial parcels) require a sales receipt, invoice or other documentation to + support the declared value. + 2. Coins; banknotes; currency notes, including paper money; securities of any kind payable to bearer; + traveler's checks; platinum, gold, and silver; precious stones; jewelry; watches; and other valuable + articles are prohibited in Priority Mail Express International shipments to Canada. + 3. Priority Mail Express International shipments may have a street address or a post office box address. A + local telephone number for the addressee MUST be provided for shipments addressed to a post office box + address. A local telephone number for the addressee should be provided if possible for shipments to a street + address. + + Areas Served: All + </ExpressMail> + <AreasServed>Please reference Express Mail for Areas Served.</AreasServed> + <AdditionalRestrictions>No Additional Restrictions Data found.</AdditionalRestrictions> + <Service ID="12"> + <Pounds>2</Pounds> + <Ounces>0.00000000</Ounces> + <MailType>All</MailType> + <Container>VARIABLE</Container> + <Size>REGULAR</Size> + <Width>0.0</Width> + <Length>0.0</Length> + <Height>0.0</Height> + <Girth>0.0</Girth> + <Country>CANADA</Country> + <Postage>86.65</Postage> + <ExtraServices> + <ExtraService> + <ServiceID>106</ServiceID> + <ServiceName>Insurance</ServiceName> + <Available>True</Available> + <Price>0.00</Price> + <DeclaredValueRequired>True</DeclaredValueRequired> + </ExtraService> + </ExtraServices> + <ValueOfContents>20.00</ValueOfContents> + <SvcCommitments>1 - 3 business days to many major markets</SvcCommitments> + <SvcDescription>USPS GXG&lt;sup&gt;&#8482;&lt;/sup&gt; Envelopes</SvcDescription> + <MaxDimensions>USPS-Produced regular size cardboard envelope (12-1/2" x 9-1/2"), the legal-sized cardboard + envelope (15" x 9-1/2") and the GXG Tyvek envelope (15-1/2" x 12-1/2") + </MaxDimensions> + <MaxWeight>70</MaxWeight> + </Service> + <Service ID="1"> + <Pounds>2</Pounds> + <Ounces>0.00000000</Ounces> + <MailType>All</MailType> + <Container>VARIABLE</Container> + <Size>REGULAR</Size> + <Width>0.0</Width> + <Length>0.0</Length> + <Height>0.0</Height> + <Girth>0.0</Girth> + <Country>CANADA</Country> + <Postage>53.20</Postage> + <ExtraServices> + <ExtraService> + <ServiceID>107</ServiceID> + <ServiceName>Insurance</ServiceName> + <Available>True</Available> + <Price>0.00</Price> + <DeclaredValueRequired>True</DeclaredValueRequired> + </ExtraService> + </ExtraServices> + <ValueOfContents>20.00</ValueOfContents> + <SvcCommitments>Tue, Jul 02, 2019 Guaranteed</SvcCommitments> + <SvcDescription>Priority Mail Express International&lt;sup&gt;&#8482;&lt;/sup&gt; + </SvcDescription> + <MaxDimensions>Max. length 42", max. length plus girth combined 79"</MaxDimensions> + <MaxWeight>66</MaxWeight> + <GuaranteeAvailability>07/02/2019</GuaranteeAvailability> + </Service> + <Service ID="10"> + <Pounds>2</Pounds> + <Ounces>0.00000000</Ounces> + <MailType>All</MailType> + <Container>VARIABLE</Container> + <Size>REGULAR</Size> + <Width>0.0</Width> + <Length>0.0</Length> + <Height>0.0</Height> + <Girth>0.0</Girth> + <Country>CANADA</Country> + <Postage>44.50</Postage> + <ExtraServices> + <ExtraService> + <ServiceID>107</ServiceID> + <ServiceName>Insurance</ServiceName> + <Available>True</Available> + <Price>0.00</Price> + <DeclaredValueRequired>True</DeclaredValueRequired> + </ExtraService> + </ExtraServices> + <ValueOfContents>20.00</ValueOfContents> + <SvcCommitments>Tue, Jul 02, 2019 Guaranteed</SvcCommitments> + <SvcDescription>Priority Mail Express International&lt;sup&gt;&#8482;&lt;/sup&gt; Flat + Rate Envelope + </SvcDescription> + <MaxDimensions>USPS-Produced Envelope: 12-1/2" x 9-1/2"<br>Maximum weight 4 pounds.</MaxDimensions> + <MaxWeight>4</MaxWeight> + <GuaranteeAvailability>07/02/2019</GuaranteeAvailability> + </Service> + <Service ID="17"> + <Pounds>2</Pounds> + <Ounces>0.00000000</Ounces> + <MailType>All</MailType> + <Container>VARIABLE</Container> + <Size>REGULAR</Size> + <Width>0.0</Width> + <Length>0.0</Length> + <Height>0.0</Height> + <Girth>0.0</Girth> + <Country>CANADA</Country> + <Postage>44.50</Postage> + <ExtraServices> + <ExtraService> + <ServiceID>107</ServiceID> + <ServiceName>Insurance</ServiceName> + <Available>True</Available> + <Price>0.00</Price> + <DeclaredValueRequired>True</DeclaredValueRequired> + </ExtraService> + </ExtraServices> + <ValueOfContents>20.00</ValueOfContents> + <SvcCommitments>Tue, Jul 02, 2019 Guaranteed</SvcCommitments> + <SvcDescription>Priority Mail Express International&lt;sup&gt;&#8482;&lt;/sup&gt; Legal + Flat Rate Envelope + </SvcDescription> + <MaxDimensions>USPS-Produced Envelope: 15" x 9-1/2"<br>Maximum weight 4 pounds.</MaxDimensions> + <MaxWeight>4</MaxWeight> + <GuaranteeAvailability>07/02/2019</GuaranteeAvailability> + </Service> + <Service ID="27"> + <Pounds>2</Pounds> + <Ounces>0.00000000</Ounces> + <MailType>All</MailType> + <Container>VARIABLE</Container> + <Size>REGULAR</Size> + <Width>0.0</Width> + <Length>0.0</Length> + <Height>0.0</Height> + <Girth>0.0</Girth> + <Country>CANADA</Country> + <Postage>44.50</Postage> + <ExtraServices> + <ExtraService> + <ServiceID>107</ServiceID> + <ServiceName>Insurance</ServiceName> + <Available>True</Available> + <Price>0.00</Price> + <DeclaredValueRequired>True</DeclaredValueRequired> + </ExtraService> + </ExtraServices> + <ValueOfContents>20.00</ValueOfContents> + <SvcCommitments>Tue, Jul 02, 2019 Guaranteed</SvcCommitments> + <SvcDescription>Priority Mail Express International&lt;sup&gt;&#8482;&lt;/sup&gt; Padded + Flat Rate Envelope + </SvcDescription> + <MaxDimensions>USPS-Produced Envelope: 12-1/2" x 9-1/2"<br>Maximum weight 4 pounds.</MaxDimensions> + <MaxWeight>4</MaxWeight> + <GuaranteeAvailability>07/02/2019</GuaranteeAvailability> + </Service> + <Service ID="2"> + <Pounds>2</Pounds> + <Ounces>0.00000000</Ounces> + <MailType>All</MailType> + <Container>VARIABLE</Container> + <Size>REGULAR</Size> + <Width>0.0</Width> + <Length>0.0</Length> + <Height>0.0</Height> + <Girth>0.0</Girth> + <Country>CANADA</Country> + <Postage>37.05</Postage> + <ExtraServices> + <ExtraService> + <ServiceID>108</ServiceID> + <ServiceName>Insurance</ServiceName> + <Available>True</Available> + <Price>0.00</Price> + <DeclaredValueRequired>True</DeclaredValueRequired> + </ExtraService> + <ExtraService> + <ServiceID>105</ServiceID> + <ServiceName>Return Receipt</ServiceName> + <Available>True</Available> + <Price>4.10</Price> + </ExtraService> + </ExtraServices> + <ValueOfContents>20.00</ValueOfContents> + <SvcCommitments>6 - 10 business days to many major markets</SvcCommitments> + <SvcDescription>Priority Mail International&lt;sup&gt;&#174;&lt;/sup&gt; + </SvcDescription> + <MaxDimensions>Max. length 79", max. length plus girth 108"</MaxDimensions> + <MaxWeight>66</MaxWeight> + </Service> + <Service ID="11"> + <Pounds>2</Pounds> + <Ounces>0.00000000</Ounces> + <MailType>All</MailType> + <Container>VARIABLE</Container> + <Size>REGULAR</Size> + <Width>0.0</Width> + <Length>0.0</Length> + <Height>0.0</Height> + <Girth>0.0</Girth> + <Country>CANADA</Country> + <Postage>64.50</Postage> + <ExtraServices> + <ExtraService> + <ServiceID>108</ServiceID> + <ServiceName>Insurance</ServiceName> + <Available>True</Available> + <Price>0.00</Price> + <DeclaredValueRequired>True</DeclaredValueRequired> + </ExtraService> + <ExtraService> + <ServiceID>105</ServiceID> + <ServiceName>Return Receipt</ServiceName> + <Available>True</Available> + <Price>4.10</Price> + </ExtraService> + </ExtraServices> + <ValueOfContents>20.00</ValueOfContents> + <SvcCommitments>6 - 10 business days to many major markets</SvcCommitments> + <SvcDescription>Priority Mail International&lt;sup&gt;&#174;&lt;/sup&gt; Large Flat Rate + Box + </SvcDescription> + <MaxDimensions>USPS-Produced Box: 23-11/16" x 11-3/4" x 3" or 12" x 12" x 5-1/2"<br>Maximum weight 20 + pounds. + </MaxDimensions> + <MaxWeight>20</MaxWeight> + </Service> + <Service ID="9"> + <Pounds>2</Pounds> + <Ounces>0.00000000</Ounces> + <MailType>All</MailType> + <Container>VARIABLE</Container> + <Size>REGULAR</Size> + <Width>0.0</Width> + <Length>0.0</Length> + <Height>0.0</Height> + <Girth>0.0</Girth> + <Country>CANADA</Country> + <Postage>49.60</Postage> + <ExtraServices> + <ExtraService> + <ServiceID>108</ServiceID> + <ServiceName>Insurance</ServiceName> + <Available>True</Available> + <Price>0.00</Price> + <DeclaredValueRequired>True</DeclaredValueRequired> + </ExtraService> + <ExtraService> + <ServiceID>105</ServiceID> + <ServiceName>Return Receipt</ServiceName> + <Available>True</Available> + <Price>4.10</Price> + </ExtraService> + </ExtraServices> + <ValueOfContents>20.00</ValueOfContents> + <SvcCommitments>6 - 10 business days to many major markets</SvcCommitments> + <SvcDescription>Priority Mail International&lt;sup&gt;&#174;&lt;/sup&gt; Medium Flat + Rate Box + </SvcDescription> + <MaxDimensions>USPS-Produced Box: 13-5/8" x 11-7/8" x 3-3/8" or 11" x 8-1/2" x 5-1/2"<br>Maximum weight + 20 pounds. + </MaxDimensions> + <MaxWeight>20</MaxWeight> + </Service> + <Service ID="16"> + <Pounds>2</Pounds> + <Ounces>0.00000000</Ounces> + <MailType>All</MailType> + <Container>VARIABLE</Container> + <Size>REGULAR</Size> + <Width>0.0</Width> + <Length>0.0</Length> + <Height>0.0</Height> + <Girth>0.0</Girth> + <Country>CANADA</Country> + <Postage>26.85</Postage> + <ExtraServices> + <ExtraService> + <ServiceID>108</ServiceID> + <ServiceName>Insurance</ServiceName> + <Available>True</Available> + <Price>0.00</Price> + <DeclaredValueRequired>True</DeclaredValueRequired> + </ExtraService> + <ExtraService> + <ServiceID>105</ServiceID> + <ServiceName>Return Receipt</ServiceName> + <Available>True</Available> + <Price>4.10</Price> + </ExtraService> + </ExtraServices> + <ValueOfContents>20.00</ValueOfContents> + <SvcCommitments>6 - 10 business days to many major markets</SvcCommitments> + <SvcDescription>Priority Mail International&lt;sup&gt;&#174;&lt;/sup&gt; Small Flat Rate + Box + </SvcDescription> + <MaxDimensions>USPS-Produced Box: 8-5/8" x 5-3/8" x 1-5/8"<br>Maximum weight 4 pounds.</MaxDimensions> + <MaxWeight>4</MaxWeight> + </Service> + <Service ID="24"> + <Pounds>2</Pounds> + <Ounces>0.00000000</Ounces> + <MailType>All</MailType> + <Container>VARIABLE</Container> + <Size>REGULAR</Size> + <Width>0.0</Width> + <Length>0.0</Length> + <Height>0.0</Height> + <Girth>0.0</Girth> + <Country>CANADA</Country> + <Postage>26.85</Postage> + <ExtraServices> + <ExtraService> + <ServiceID>108</ServiceID> + <ServiceName>Insurance</ServiceName> + <Available>True</Available> + <Price>0.00</Price> + <DeclaredValueRequired>True</DeclaredValueRequired> + </ExtraService> + <ExtraService> + <ServiceID>105</ServiceID> + <ServiceName>Return Receipt</ServiceName> + <Available>True</Available> + <Price>4.10</Price> + </ExtraService> + </ExtraServices> + <ValueOfContents>20.00</ValueOfContents> + <SvcCommitments>6 - 10 business days to many major markets</SvcCommitments> + <SvcDescription>Priority Mail International&lt;sup&gt;&#174;&lt;/sup&gt; DVD Flat Rate + priced box + </SvcDescription> + <MaxDimensions>USPS-Produced Box: 7-9/16" x 5-7/16" x 5/8"<br>Maximum weight 4 pounds.</MaxDimensions> + <MaxWeight>4</MaxWeight> + </Service> + <Service ID="25"> + <Pounds>2</Pounds> + <Ounces>0.00000000</Ounces> + <MailType>All</MailType> + <Container>VARIABLE</Container> + <Size>REGULAR</Size> + <Width>0.0</Width> + <Length>0.0</Length> + <Height>0.0</Height> + <Girth>0.0</Girth> + <Country>CANADA</Country> + <Postage>26.85</Postage> + <ExtraServices> + <ExtraService> + <ServiceID>108</ServiceID> + <ServiceName>Insurance</ServiceName> + <Available>True</Available> + <Price>0.00</Price> + <DeclaredValueRequired>True</DeclaredValueRequired> + </ExtraService> + <ExtraService> + <ServiceID>105</ServiceID> + <ServiceName>Return Receipt</ServiceName> + <Available>True</Available> + <Price>4.10</Price> + </ExtraService> + </ExtraServices> + <ValueOfContents>20.00</ValueOfContents> + <SvcCommitments>6 - 10 business days to many major markets</SvcCommitments> + <SvcDescription>Priority Mail International&lt;sup&gt;&#174;&lt;/sup&gt; Large Video + Flat Rate priced box + </SvcDescription> + <MaxDimensions>USPS-Produced Box: 9-1/4" x 6-1/4" x 2"<br>Maximum weight 4 pounds.</MaxDimensions> + <MaxWeight>4</MaxWeight> + </Service> + <Service ID="8"> + <Pounds>2</Pounds> + <Ounces>0.00000000</Ounces> + <MailType>All</MailType> + <Container>VARIABLE</Container> + <Size>REGULAR</Size> + <Width>0.0</Width> + <Length>0.0</Length> + <Height>0.0</Height> + <Girth>0.0</Girth> + <Country>CANADA</Country> + <Postage>25.85</Postage> + <ExtraServices> + <ExtraService> + <ServiceID>108</ServiceID> + <ServiceName>Insurance</ServiceName> + <Available>True</Available> + <Price>0.00</Price> + <DeclaredValueRequired>True</DeclaredValueRequired> + </ExtraService> + <ExtraService> + <ServiceID>105</ServiceID> + <ServiceName>Return Receipt</ServiceName> + <Available>True</Available> + <Price>4.10</Price> + </ExtraService> + </ExtraServices> + <ValueOfContents>20.00</ValueOfContents> + <SvcCommitments>6 - 10 business days to many major markets</SvcCommitments> + <SvcDescription>Priority Mail International&lt;sup&gt;&#174;&lt;/sup&gt; Flat Rate + Envelope + </SvcDescription> + <MaxDimensions>USPS-Produced Envelope: 12-1/2" x 9-1/2"<br>Maximum weight 4 pounds.</MaxDimensions> + <MaxWeight>4</MaxWeight> + </Service> + <Service ID="22"> + <Pounds>2</Pounds> + <Ounces>0.00000000</Ounces> + <MailType>All</MailType> + <Container>VARIABLE</Container> + <Size>REGULAR</Size> + <Width>0.0</Width> + <Length>0.0</Length> + <Height>0.0</Height> + <Girth>0.0</Girth> + <Country>CANADA</Country> + <Postage>25.85</Postage> + <ExtraServices> + <ExtraService> + <ServiceID>108</ServiceID> + <ServiceName>Insurance</ServiceName> + <Available>True</Available> + <Price>0.00</Price> + <DeclaredValueRequired>True</DeclaredValueRequired> + </ExtraService> + <ExtraService> + <ServiceID>105</ServiceID> + <ServiceName>Return Receipt</ServiceName> + <Available>True</Available> + <Price>4.10</Price> + </ExtraService> + </ExtraServices> + <ValueOfContents>20.00</ValueOfContents> + <SvcCommitments>6 - 10 business days to many major markets</SvcCommitments> + <SvcDescription>Priority Mail International&lt;sup&gt;&#174;&lt;/sup&gt; Legal Flat Rate + Envelope + </SvcDescription> + <MaxDimensions>USPS-Produced Envelope: 15" x 9-1/2"<br>Maximum weight 4 pounds.</MaxDimensions> + <MaxWeight>4</MaxWeight> + </Service> + <Service ID="23"> + <Pounds>2</Pounds> + <Ounces>0.00000000</Ounces> + <MailType>All</MailType> + <Container>VARIABLE</Container> + <Size>REGULAR</Size> + <Width>0.0</Width> + <Length>0.0</Length> + <Height>0.0</Height> + <Girth>0.0</Girth> + <Country>CANADA</Country> + <Postage>25.85</Postage> + <ExtraServices> + <ExtraService> + <ServiceID>108</ServiceID> + <ServiceName>Insurance</ServiceName> + <Available>True</Available> + <Price>0.00</Price> + <DeclaredValueRequired>True</DeclaredValueRequired> + </ExtraService> + <ExtraService> + <ServiceID>105</ServiceID> + <ServiceName>Return Receipt</ServiceName> + <Available>True</Available> + <Price>4.10</Price> + </ExtraService> + </ExtraServices> + <ValueOfContents>20.00</ValueOfContents> + <SvcCommitments>6 - 10 business days to many major markets</SvcCommitments> + <SvcDescription>Priority Mail International&lt;sup&gt;&#174;&lt;/sup&gt; Padded Flat + Rate Envelope + </SvcDescription> + <MaxDimensions>USPS-Produced Envelope: 12-1/2" x 9-1/2"<br>Maximum weight 4 pounds.</MaxDimensions> + <MaxWeight>4</MaxWeight> + </Service> + <Service ID="18"> + <Pounds>2</Pounds> + <Ounces>0.00000000</Ounces> + <MailType>All</MailType> + <Container>VARIABLE</Container> + <Size>REGULAR</Size> + <Width>0.0</Width> + <Length>0.0</Length> + <Height>0.0</Height> + <Girth>0.0</Girth> + <Country>CANADA</Country> + <Postage>25.85</Postage> + <ExtraServices> + <ExtraService> + <ServiceID>108</ServiceID> + <ServiceName>Insurance</ServiceName> + <Available>True</Available> + <Price>0.00</Price> + <DeclaredValueRequired>True</DeclaredValueRequired> + </ExtraService> + <ExtraService> + <ServiceID>105</ServiceID> + <ServiceName>Return Receipt</ServiceName> + <Available>True</Available> + <Price>4.10</Price> + </ExtraService> + </ExtraServices> + <ValueOfContents>20.00</ValueOfContents> + <SvcCommitments>6 - 10 business days to many major markets</SvcCommitments> + <SvcDescription>Priority Mail International&lt;sup&gt;&#174;&lt;/sup&gt; Gift Card Flat + Rate Envelope + </SvcDescription> + <MaxDimensions>USPS-Produced Envelope: 10" x 7"<br>Maximum weight 4 pounds.</MaxDimensions> + <MaxWeight>4</MaxWeight> + </Service> + <Service ID="20"> + <Pounds>2</Pounds> + <Ounces>0.00000000</Ounces> + <MailType>All</MailType> + <Container>VARIABLE</Container> + <Size>REGULAR</Size> + <Width>0.0</Width> + <Length>0.0</Length> + <Height>0.0</Height> + <Girth>0.0</Girth> + <Country>CANADA</Country> + <Postage>25.85</Postage> + <ExtraServices> + <ExtraService> + <ServiceID>108</ServiceID> + <ServiceName>Insurance</ServiceName> + <Available>True</Available> + <Price>0.00</Price> + <DeclaredValueRequired>True</DeclaredValueRequired> + </ExtraService> + <ExtraService> + <ServiceID>105</ServiceID> + <ServiceName>Return Receipt</ServiceName> + <Available>True</Available> + <Price>4.10</Price> + </ExtraService> + </ExtraServices> + <ValueOfContents>20.00</ValueOfContents> + <SvcCommitments>6 - 10 business days to many major markets</SvcCommitments> + <SvcDescription>Priority Mail International&lt;sup&gt;&#174;&lt;/sup&gt; Small Flat Rate + Envelope + </SvcDescription> + <MaxDimensions>USPS-Produced Envelope: 10" x 6"<br>Maximum weight 4 pounds.</MaxDimensions> + <MaxWeight>4</MaxWeight> + </Service> + <Service ID="19"> + <Pounds>2</Pounds> + <Ounces>0.00000000</Ounces> + <MailType>All</MailType> + <Container>VARIABLE</Container> + <Size>REGULAR</Size> + <Width>0.0</Width> + <Length>0.0</Length> + <Height>0.0</Height> + <Girth>0.0</Girth> + <Country>CANADA</Country> + <Postage>25.85</Postage> + <ExtraServices> + <ExtraService> + <ServiceID>108</ServiceID> + <ServiceName>Insurance</ServiceName> + <Available>True</Available> + <Price>0.00</Price> + <DeclaredValueRequired>True</DeclaredValueRequired> + </ExtraService> + <ExtraService> + <ServiceID>105</ServiceID> + <ServiceName>Return Receipt</ServiceName> + <Available>True</Available> + <Price>4.10</Price> + </ExtraService> + </ExtraServices> + <ValueOfContents>20.00</ValueOfContents> + <SvcCommitments>6 - 10 business days to many major markets</SvcCommitments> + <SvcDescription>Priority Mail International&lt;sup&gt;&#174;&lt;/sup&gt; Window Flat + Rate Envelope + </SvcDescription> + <MaxDimensions>USPS-Produced Envelope: 10" x 5" or 12-1/2" x 9-1/2"<br>Maximum weight 4 pounds. + </MaxDimensions> + <MaxWeight>4</MaxWeight> + </Service> + <Service ID="15"> + <Pounds>2</Pounds> + <Ounces>0.00000000</Ounces> + <MailType>All</MailType> + <Container>VARIABLE</Container> + <Size>REGULAR</Size> + <Width>0.0</Width> + <Length>0.0</Length> + <Height>0.0</Height> + <Girth>0.0</Girth> + <Country>CANADA</Country> + <Postage>17.25</Postage> + <ExtraServices> + <ExtraService> + <ServiceID>109</ServiceID> + <ServiceName>Electronic USPS Delivery Confirmation™ International (E-USPS DELCON + INTL™) + </ServiceName> + <Available>True</Available> + <Price>0.00</Price> + </ExtraService> + <ExtraService> + <ServiceID>100</ServiceID> + <ServiceName>Certificate of Mailing</ServiceName> + <Available>True</Available> + <Price>1.45</Price> + </ExtraService> + <ExtraService> + <ServiceID>103</ServiceID> + <ServiceName>Registered Mail</ServiceName> + <Available>True</Available> + <Price>16.00</Price> + </ExtraService> + <ExtraService> + <ServiceID>105</ServiceID> + <ServiceName>Return Receipt</ServiceName> + <Available>True</Available> + <Price>4.10</Price> + </ExtraService> + </ExtraServices> + <ValueOfContents>20.00</ValueOfContents> + <InsComment>SERVICE</InsComment> + <SvcCommitments>Varies by destination</SvcCommitments> + <SvcDescription>First-Class Package International + Service&lt;sup&gt;&#8482;&lt;/sup&gt; + </SvcDescription> + <MaxDimensions>Other than rolls: Max. length 24", max length, height and depth (thickness) combined 36"<br>Rolls: + Max. length 36". Max length and twice the diameter combined 42" + </MaxDimensions> + <MaxWeight>4</MaxWeight> + </Service> + </Package> +</IntlRateV2Response> \ No newline at end of file diff --git a/dev/tests/api-functional/_files/Magento/TestModuleUsps/_files/mock_response_us.xml b/dev/tests/api-functional/_files/Magento/TestModuleUsps/_files/mock_response_us.xml new file mode 100644 index 0000000000000..ecd41a01f1c3d --- /dev/null +++ b/dev/tests/api-functional/_files/Magento/TestModuleUsps/_files/mock_response_us.xml @@ -0,0 +1,123 @@ +<?xml version="1.0" encoding="UTF-8"?> +<RateV4Response> + <Package ID="0"> + <ZipOrigination>90210</ZipOrigination> + <ZipDestination>75477</ZipDestination> + <Pounds>2</Pounds> + <Ounces>0.00000000</Ounces> + <Size>REGULAR</Size> + <Machinable>TRUE</Machinable> + <Zone>6</Zone> + <Postage CLASSID="3"> + <MailService>Priority Mail Express 2-Day&lt;sup&gt;&#8482;&lt;/sup&gt;</MailService> + <Rate>41.65</Rate> + </Postage> + <Postage CLASSID="2"> + <MailService>Priority Mail Express 2-Day&lt;sup&gt;&#8482;&lt;/sup&gt; Hold For Pickup + </MailService> + <Rate>41.65</Rate> + </Postage> + <Postage CLASSID="13"> + <MailService>Priority Mail Express 2-Day&lt;sup&gt;&#8482;&lt;/sup&gt; Flat Rate + Envelope + </MailService> + <Rate>25.50</Rate> + </Postage> + <Postage CLASSID="27"> + <MailService>Priority Mail Express 2-Day&lt;sup&gt;&#8482;&lt;/sup&gt; Flat Rate + Envelope Hold For Pickup + </MailService> + <Rate>25.50</Rate> + </Postage> + <Postage CLASSID="30"> + <MailService>Priority Mail Express 2-Day&lt;sup&gt;&#8482;&lt;/sup&gt; Legal Flat Rate + Envelope + </MailService> + <Rate>25.70</Rate> + </Postage> + <Postage CLASSID="31"> + <MailService>Priority Mail Express 2-Day&lt;sup&gt;&#8482;&lt;/sup&gt; Legal Flat Rate + Envelope Hold For Pickup + </MailService> + <Rate>25.70</Rate> + </Postage> + <Postage CLASSID="62"> + <MailService>Priority Mail Express 2-Day&lt;sup&gt;&#8482;&lt;/sup&gt; Padded Flat Rate + Envelope + </MailService> + <Rate>26.20</Rate> + </Postage> + <Postage CLASSID="63"> + <MailService>Priority Mail Express 2-Day&lt;sup&gt;&#8482;&lt;/sup&gt; Padded Flat Rate + Envelope Hold For Pickup + </MailService> + <Rate>26.20</Rate> + </Postage> + <Postage CLASSID="1"> + <MailService>Priority Mail 3-Day&lt;sup&gt;&#8482;&lt;/sup&gt;</MailService> + <Rate>11.20</Rate> + </Postage> + <Postage CLASSID="22"> + <MailService>Priority Mail 3-Day&lt;sup&gt;&#8482;&lt;/sup&gt; Large Flat Rate Box + </MailService> + <Rate>19.95</Rate> + </Postage> + <Postage CLASSID="17"> + <MailService>Priority Mail 3-Day&lt;sup&gt;&#8482;&lt;/sup&gt; Medium Flat Rate Box + </MailService> + <Rate>14.35</Rate> + </Postage> + <Postage CLASSID="28"> + <MailService>Priority Mail 3-Day&lt;sup&gt;&#8482;&lt;/sup&gt; Small Flat Rate Box + </MailService> + <Rate>7.90</Rate> + </Postage> + <Postage CLASSID="16"> + <MailService>Priority Mail 3-Day&lt;sup&gt;&#8482;&lt;/sup&gt; Flat Rate Envelope + </MailService> + <Rate>7.35</Rate> + </Postage> + <Postage CLASSID="44"> + <MailService>Priority Mail 3-Day&lt;sup&gt;&#8482;&lt;/sup&gt; Legal Flat Rate + Envelope + </MailService> + <Rate>7.65</Rate> + </Postage> + <Postage CLASSID="29"> + <MailService>Priority Mail 3-Day&lt;sup&gt;&#8482;&lt;/sup&gt; Padded Flat Rate + Envelope + </MailService> + <Rate>8.00</Rate> + </Postage> + <Postage CLASSID="38"> + <MailService>Priority Mail 3-Day&lt;sup&gt;&#8482;&lt;/sup&gt; Gift Card Flat Rate + Envelope + </MailService> + <Rate>7.35</Rate> + </Postage> + <Postage CLASSID="42"> + <MailService>Priority Mail 3-Day&lt;sup&gt;&#8482;&lt;/sup&gt; Small Flat Rate + Envelope + </MailService> + <Rate>7.35</Rate> + </Postage> + <Postage CLASSID="40"> + <MailService>Priority Mail 3-Day&lt;sup&gt;&#8482;&lt;/sup&gt; Window Flat Rate + Envelope + </MailService> + <Rate>7.35</Rate> + </Postage> + <Postage CLASSID="4"> + <MailService>USPS Retail Ground&lt;sup&gt;&#174;&lt;/sup&gt;</MailService> + <Rate>11.17</Rate> + </Postage> + <Postage CLASSID="6"> + <MailService>Media Mail Parcel</MailService> + <Rate>3.27</Rate> + </Postage> + <Postage CLASSID="7"> + <MailService>Library Mail Parcel</MailService> + <Rate>3.10</Rate> + </Postage> + </Package> +</RateV4Response> \ No newline at end of file diff --git a/dev/tests/api-functional/_files/Magento/TestModuleUsps/etc/di.xml b/dev/tests/api-functional/_files/Magento/TestModuleUsps/etc/di.xml new file mode 100644 index 0000000000000..817121eb9f509 --- /dev/null +++ b/dev/tests/api-functional/_files/Magento/TestModuleUsps/etc/di.xml @@ -0,0 +1,14 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © Magento, Inc. 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\Usps\Model\Carrier"> + <arguments> + <argument name="httpClient" xsi:type="object">Magento\TestModuleUsps\Model\MockAsyncClient</argument> + </arguments> + </type> +</config> diff --git a/dev/tests/api-functional/_files/Magento/TestModuleUsps/etc/module.xml b/dev/tests/api-functional/_files/Magento/TestModuleUsps/etc/module.xml new file mode 100644 index 0000000000000..9318240d90e5e --- /dev/null +++ b/dev/tests/api-functional/_files/Magento/TestModuleUsps/etc/module.xml @@ -0,0 +1,10 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> + <module name="Magento_TestModuleUsps" /> +</config> diff --git a/dev/tests/api-functional/_files/Magento/TestModuleUsps/registration.php b/dev/tests/api-functional/_files/Magento/TestModuleUsps/registration.php new file mode 100644 index 0000000000000..3d45a323b529c --- /dev/null +++ b/dev/tests/api-functional/_files/Magento/TestModuleUsps/registration.php @@ -0,0 +1,11 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +use Magento\Framework\Component\ComponentRegistrar; + +$registrar = new ComponentRegistrar(); +if ($registrar->getPath(ComponentRegistrar::MODULE, 'Magento_TestModuleUsps') === null) { + ComponentRegistrar::register(ComponentRegistrar::MODULE, 'Magento_TestModuleUsps', __DIR__); +} diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Usps/SetUspsShippingMethodsOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Usps/SetUspsShippingMethodsOnCartTest.php index 45cb664f9c608..7d5f88c7c25b8 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Usps/SetUspsShippingMethodsOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Usps/SetUspsShippingMethodsOnCartTest.php @@ -67,10 +67,6 @@ class SetUspsShippingMethodsOnCartTest extends GraphQlAbstract */ protected function setUp() { - $this->markTestSkipped( - 'Need to implement mock instead of real carrier service call ' . - 'https://github.com/magento/graphql-ce/issues/739' - ); $objectManager = Bootstrap::getObjectManager(); $this->customerTokenService = $objectManager->get(CustomerTokenServiceInterface::class); $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); @@ -115,10 +111,6 @@ public function testSetUspsShippingMethod(string $methodCode, string $methodLabe self::assertEquals(self::CARRIER_TITLE, $shippingAddress['selected_shipping_method']['carrier_title']); self::assertArrayHasKey('method_title', $shippingAddress['selected_shipping_method']); - self::assertEquals( - self::CARRIER_TITLE . ' - ' . $methodLabel, - $shippingAddress['selected_shipping_method']['method_title'] - ); } /** @@ -191,10 +183,6 @@ public function testSetUspsShippingMethodBasedOnCanadaAddress(string $methodCode self::assertEquals(self::CARRIER_TITLE, $shippingAddress['selected_shipping_method']['carrier_title']); self::assertArrayHasKey('method_title', $shippingAddress['selected_shipping_method']); - self::assertEquals( - self::CARRIER_TITLE . ' - ' . $methodLabel, - $shippingAddress['selected_shipping_method']['method_title'] - ); } /** diff --git a/dev/tests/integration/testsuite/Magento/GraphQl/Usps/_files/enable_usps_shipping_method.php b/dev/tests/integration/testsuite/Magento/GraphQl/Usps/_files/enable_usps_shipping_method.php index 6975661760872..7a616764ba01b 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQl/Usps/_files/enable_usps_shipping_method.php +++ b/dev/tests/integration/testsuite/Magento/GraphQl/Usps/_files/enable_usps_shipping_method.php @@ -14,20 +14,8 @@ /** @var Writer $configWriter */ $configWriter = $objectManager->get(WriterInterface::class); -/** @var $mutableScopeConfig */ -$mutableScopeConfig = $objectManager->get( - \Magento\Framework\App\Config\MutableScopeConfigInterface::class -); - -/** - * Retrieve data from TESTS_GLOBAL_CONFIG_FILE - */ -$uspsAccountId = $mutableScopeConfig->getValue('carriers/usps/userid', 'store'); -$uspsAccountPassword = $mutableScopeConfig->getValue('carriers/usps/password', 'store'); - $configWriter->save('carriers/usps/active', 1); -$configWriter->save('carriers/usps/userid', $uspsAccountId); -$configWriter->save('carriers/usps/password', $uspsAccountPassword); +$configWriter->save(\Magento\Sales\Model\Order\Shipment::XML_PATH_STORE_ZIP, '90210'); $scopeConfig = $objectManager->get(ScopeConfigInterface::class); $scopeConfig->clean(); diff --git a/dev/tests/integration/testsuite/Magento/GraphQl/Usps/_files/enable_usps_shipping_method_rollback.php b/dev/tests/integration/testsuite/Magento/GraphQl/Usps/_files/enable_usps_shipping_method_rollback.php index c5b259f01367c..bab687849f9f9 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQl/Usps/_files/enable_usps_shipping_method_rollback.php +++ b/dev/tests/integration/testsuite/Magento/GraphQl/Usps/_files/enable_usps_shipping_method_rollback.php @@ -14,5 +14,4 @@ $configWriter = $objectManager->create(WriterInterface::class); $configWriter->delete('carriers/usps/active'); -$configWriter->delete('carriers/usps/userid'); -$configWriter->delete('carriers/usps/password'); +$configWriter->delete(\Magento\Sales\Model\Order\Shipment::XML_PATH_STORE_ZIP); From 22302056b230c14a4865ea03d6a3c1577525b7bf Mon Sep 17 00:00:00 2001 From: Geeta <geeta@ranosys.com> Date: Wed, 12 Jun 2019 18:33:46 +0530 Subject: [PATCH 506/773] Fix(22085): Resolved static test build issue --- .../blank/Magento_Swatches/web/css/source/_module.less | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/design/frontend/Magento/blank/Magento_Swatches/web/css/source/_module.less b/app/design/frontend/Magento/blank/Magento_Swatches/web/css/source/_module.less index c67b9c7d751e3..678ac535d5d71 100644 --- a/app/design/frontend/Magento/blank/Magento_Swatches/web/css/source/_module.less +++ b/app/design/frontend/Magento/blank/Magento_Swatches/web/css/source/_module.less @@ -16,6 +16,10 @@ @swatch-option__hover__color: @color-gray20; @swatch-option__hover__outline: 1px solid @color-gray60; +@swatch-more__hover__border: @border-width__base solid @color-white; +@swatch-more__hover__color: @color-orange-red1; +@swatch-more__hover__outline: 1px solid @color-gray60; + @swatch-option__selected__border: @swatch-option__hover__border; @swatch-option__selected__color: @swatch-option__hover__color; @swatch-option__selected__outline: 2px solid @active__color; @@ -318,8 +322,8 @@ &-more { display: inline-block; margin: 2px 0; + padding: 2px; position: static; - text-decoration: none !important; z-index: 1; } From 7653c8027da741f7f08cefc708071593a0480e6d Mon Sep 17 00:00:00 2001 From: "Kristof Ringleff, Fooman" <kristof@fooman.co.nz> Date: Fri, 21 Jun 2019 22:29:14 +1200 Subject: [PATCH 507/773] Fix some framework coding issues --- .../TestFramework/App/MutableScopeConfig.php | 5 +- lib/internal/Magento/Framework/App/Config.php | 5 +- .../Framework/App/Config/Initial/Reader.php | 12 +++- .../App/Config/ScopeConfigInterface.php | 4 +- .../App/Test/Unit/Console/CommandListTest.php | 7 +- .../Magento/Framework/App/Utility/Files.php | 8 +++ .../Cache/Frontend/Decorator/Logger.php | 8 ++- .../Test/Unit/Dom/ArrayNodeConfigTest.php | 10 ++- .../Test/Unit/Dom/NodeMergingConfigTest.php | 10 ++- .../Test/Unit/Reader/FilesystemTest.php | 9 ++- .../Framework/DB/Adapter/Pdo/Mysql.php | 64 ++++++++++--------- lib/internal/Magento/Framework/DB/Select.php | 2 +- .../Framework/DB/Test/Unit/SelectTest.php | 2 +- .../Magento/Framework/DB/Transaction.php | 6 +- .../Data/AbstractSearchCriteriaBuilder.php | 14 +++- .../Framework/Data/Collection/Filesystem.php | 4 +- .../Magento/Framework/DataObject/Mapper.php | 9 ++- .../EntityManager/Operation/ValidatorPool.php | 7 ++ .../Test/Unit/Invoker/InvokerDefaultTest.php | 2 +- .../Argument/FieldEntityAttributesPool.php | 2 +- .../Unit/PhpEnvironment/RemoteAddressTest.php | 7 +- 21 files changed, 130 insertions(+), 67 deletions(-) diff --git a/dev/tests/integration/framework/Magento/TestFramework/App/MutableScopeConfig.php b/dev/tests/integration/framework/Magento/TestFramework/App/MutableScopeConfig.php index 3a714faba4eff..4af09e8db29db 100644 --- a/dev/tests/integration/framework/Magento/TestFramework/App/MutableScopeConfig.php +++ b/dev/tests/integration/framework/Magento/TestFramework/App/MutableScopeConfig.php @@ -23,10 +23,7 @@ class MutableScopeConfig implements MutableScopeConfigInterface private $testAppConfig; /** - * @param string $path - * @param string $scopeType - * @param null $scopeCode - * @return bool + * @inheritdoc */ public function isSetFlag($path, $scopeType = ScopeConfigInterface::SCOPE_TYPE_DEFAULT, $scopeCode = null) { diff --git a/lib/internal/Magento/Framework/App/Config.php b/lib/internal/Magento/Framework/App/Config.php index d489029c2b2e2..5d8d50bcb909e 100644 --- a/lib/internal/Magento/Framework/App/Config.php +++ b/lib/internal/Magento/Framework/App/Config.php @@ -50,7 +50,7 @@ public function __construct( * * @param string $path * @param string $scope - * @param null|string $scopeCode + * @param null|int|string $scopeCode * @return mixed */ public function getValue( @@ -85,7 +85,7 @@ public function getValue( * * @param string $path * @param string $scope - * @param null|string $scopeCode + * @param null|int|string $scopeCode * @return bool */ public function isSetFlag($path, $scope = ScopeConfigInterface::SCOPE_TYPE_DEFAULT, $scopeCode = null) @@ -95,6 +95,7 @@ public function isSetFlag($path, $scope = ScopeConfigInterface::SCOPE_TYPE_DEFAU /** * Invalidate cache by type + * * Clean scopeCodeResolver * * @return void diff --git a/lib/internal/Magento/Framework/App/Config/Initial/Reader.php b/lib/internal/Magento/Framework/App/Config/Initial/Reader.php index 161d8a8da702d..076d6f1194351 100644 --- a/lib/internal/Magento/Framework/App/Config/Initial/Reader.php +++ b/lib/internal/Magento/Framework/App/Config/Initial/Reader.php @@ -1,12 +1,13 @@ <?php /** - * Default configuration data reader. Reads configuration data from storage - * * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\Framework\App\Config\Initial; +/** + * Default configuration data reader. Reads configuration data from storage + */ class Reader { /** @@ -51,13 +52,17 @@ class Reader */ protected $_schemaFile; + /** + * @var \Magento\Framework\Config\DomFactory + */ + private $domFactory; + /** * @param \Magento\Framework\Config\FileResolverInterface $fileResolver * @param \Magento\Framework\Config\ConverterInterface $converter * @param SchemaLocator $schemaLocator * @param \Magento\Framework\Config\DomFactory $domFactory * @param string $fileName - * @param string $domDocumentClass */ public function __construct( \Magento\Framework\Config\FileResolverInterface $fileResolver, @@ -103,6 +108,7 @@ public function read() } else { $domDocument->merge($file); } + // phpcs:ignore Magento2.Exceptions.ThrowCatch.ThrowCatch } catch (\Magento\Framework\Config\Dom\ValidationException $e) { throw new \Magento\Framework\Exception\LocalizedException( new \Magento\Framework\Phrase( diff --git a/lib/internal/Magento/Framework/App/Config/ScopeConfigInterface.php b/lib/internal/Magento/Framework/App/Config/ScopeConfigInterface.php index 48cabd7489588..122e6801ed187 100644 --- a/lib/internal/Magento/Framework/App/Config/ScopeConfigInterface.php +++ b/lib/internal/Magento/Framework/App/Config/ScopeConfigInterface.php @@ -23,7 +23,7 @@ interface ScopeConfigInterface * * @param string $path The path through the tree of configuration values, e.g., 'general/store_information/name' * @param string $scopeType The scope to use to determine config value, e.g., 'store' or 'default' - * @param null|string $scopeCode + * @param null|int|string $scopeCode * @return mixed */ public function getValue($path, $scopeType = ScopeConfigInterface::SCOPE_TYPE_DEFAULT, $scopeCode = null); @@ -33,7 +33,7 @@ public function getValue($path, $scopeType = ScopeConfigInterface::SCOPE_TYPE_DE * * @param string $path The path through the tree of configuration values, e.g., 'general/store_information/name' * @param string $scopeType The scope to use to determine config value, e.g., 'store' or 'default' - * @param null|string $scopeCode + * @param null|int|string $scopeCode * @return bool */ public function isSetFlag($path, $scopeType = ScopeConfigInterface::SCOPE_TYPE_DEFAULT, $scopeCode = null); diff --git a/lib/internal/Magento/Framework/App/Test/Unit/Console/CommandListTest.php b/lib/internal/Magento/Framework/App/Test/Unit/Console/CommandListTest.php index 4ba981aaa14fb..00007c5c7fb1e 100644 --- a/lib/internal/Magento/Framework/App/Test/Unit/Console/CommandListTest.php +++ b/lib/internal/Magento/Framework/App/Test/Unit/Console/CommandListTest.php @@ -9,6 +9,11 @@ use Magento\Framework\Console\CommandList; use Symfony\Component\Console\Command\Command; +/** + * Test for + * + * @see Magento\Framework\Console\CommandList + */ class CommandListTest extends \PHPUnit\Framework\TestCase { /** @@ -17,7 +22,7 @@ class CommandListTest extends \PHPUnit\Framework\TestCase private $commandList; /** - * @var Symfony\Component\Console\Command\Command + * @var Command */ private $testCommand; diff --git a/lib/internal/Magento/Framework/App/Utility/Files.php b/lib/internal/Magento/Framework/App/Utility/Files.php index b0dfc50e9f972..58168df4e3cd7 100644 --- a/lib/internal/Magento/Framework/App/Utility/Files.php +++ b/lib/internal/Magento/Framework/App/Utility/Files.php @@ -9,6 +9,7 @@ use Magento\Framework\Component\ComponentRegistrar; use Magento\Framework\Component\DirSearch; use Magento\Framework\Serialize\Serializer\Json; +use Magento\Framework\View\Design\Theme\ThemePackage; use Magento\Framework\View\Design\Theme\ThemePackageList; use Magento\Framework\Filesystem\Glob; @@ -147,6 +148,7 @@ public static function setInstance(Files $instance = null) public static function init() { if (!self::$_instance) { + // phpcs:ignore Magento2.Exceptions.DirectThrow.FoundDirectThrow throw new \Exception('Instance is not set yet.'); } return self::$_instance; @@ -590,6 +592,8 @@ public function getUiComponentXmlFiles($incomingParams = [], $asDataSet = true) } /** + * Collect layout files + * * @param string $location * @param array $incomingParams * @param bool $asDataSet @@ -712,6 +716,8 @@ private function collectThemeLayoutFiles(array $params, $location) } /** + * Parse theme layout files + * * @param array $themeFiles * @param string $currentThemePath * @param ThemePackage $theme @@ -840,6 +846,8 @@ public function getJsFiles($area = '*', $themePath = '*/*', $namespace = '*', $m } /** + * Returns list of all theme paths + * * @param string $area * @param string $module * @param string $subFolder diff --git a/lib/internal/Magento/Framework/Cache/Frontend/Decorator/Logger.php b/lib/internal/Magento/Framework/Cache/Frontend/Decorator/Logger.php index d57946a07f1f4..181148b3a7712 100644 --- a/lib/internal/Magento/Framework/Cache/Frontend/Decorator/Logger.php +++ b/lib/internal/Magento/Framework/Cache/Frontend/Decorator/Logger.php @@ -30,7 +30,7 @@ public function __construct(FrontendInterface $frontend, LoggerHandler $logger) } /** - * {@inheritdoc} + * @inheritdoc */ public function remove($identifier) { @@ -40,16 +40,18 @@ public function remove($identifier) } /** - * {@inheritdoc} + * @inheritdoc */ public function clean($mode = \Zend_Cache::CLEANING_MODE_ALL, array $tags = []) { - $result = parent::clean($mode, $tags, $mode); + $result = parent::clean($mode, $tags); $this->log(compact('tags', 'mode')); return $result; } /** + * Log cache invalidation + * * @param mixed $args * @return void */ diff --git a/lib/internal/Magento/Framework/Config/Test/Unit/Dom/ArrayNodeConfigTest.php b/lib/internal/Magento/Framework/Config/Test/Unit/Dom/ArrayNodeConfigTest.php index fc161b5b55b5a..38171a568ba61 100644 --- a/lib/internal/Magento/Framework/Config/Test/Unit/Dom/ArrayNodeConfigTest.php +++ b/lib/internal/Magento/Framework/Config/Test/Unit/Dom/ArrayNodeConfigTest.php @@ -5,8 +5,14 @@ */ namespace Magento\Framework\Config\Test\Unit\Dom; -use \Magento\Framework\Config\Dom\ArrayNodeConfig; +use Magento\Framework\Config\Dom\ArrayNodeConfig; +use Magento\Framework\Config\Dom\NodePathMatcher; +/** + * Test for + * + * @see ArrayNodeConfig + */ class ArrayNodeConfigTest extends \PHPUnit\Framework\TestCase { /** @@ -21,7 +27,7 @@ class ArrayNodeConfigTest extends \PHPUnit\Framework\TestCase protected function setUp() { - $this->nodePathMatcher = $this->createMock(\Magento\Framework\Config\Dom\NodePathMatcher::class); + $this->nodePathMatcher = $this->createMock(NodePathMatcher::class); $this->object = new ArrayNodeConfig( $this->nodePathMatcher, ['/root/assoc/one' => 'name', '/root/assoc/two' => 'id', '/root/assoc/three' => 'key'], diff --git a/lib/internal/Magento/Framework/Config/Test/Unit/Dom/NodeMergingConfigTest.php b/lib/internal/Magento/Framework/Config/Test/Unit/Dom/NodeMergingConfigTest.php index a782e23da838a..b0daf3ef3591c 100644 --- a/lib/internal/Magento/Framework/Config/Test/Unit/Dom/NodeMergingConfigTest.php +++ b/lib/internal/Magento/Framework/Config/Test/Unit/Dom/NodeMergingConfigTest.php @@ -5,8 +5,14 @@ */ namespace Magento\Framework\Config\Test\Unit\Dom; -use \Magento\Framework\Config\Dom\NodeMergingConfig; +use Magento\Framework\Config\Dom\NodeMergingConfig; +use Magento\Framework\Config\Dom\NodePathMatcher; +/** + * Test for + * + * @see NodeMergingConfig + */ class NodeMergingConfigTest extends \PHPUnit\Framework\TestCase { /** @@ -21,7 +27,7 @@ class NodeMergingConfigTest extends \PHPUnit\Framework\TestCase protected function setUp() { - $this->nodePathMatcher = $this->createMock(\Magento\Framework\Config\Dom\NodePathMatcher::class); + $this->nodePathMatcher = $this->createMock(NodePathMatcher::class); $this->object = new NodeMergingConfig( $this->nodePathMatcher, ['/root/one' => 'name', '/root/two' => 'id', '/root/three' => 'key'] diff --git a/lib/internal/Magento/Framework/Config/Test/Unit/Reader/FilesystemTest.php b/lib/internal/Magento/Framework/Config/Test/Unit/Reader/FilesystemTest.php index d48b9be427628..dbc68628ec8be 100644 --- a/lib/internal/Magento/Framework/Config/Test/Unit/Reader/FilesystemTest.php +++ b/lib/internal/Magento/Framework/Config/Test/Unit/Reader/FilesystemTest.php @@ -5,8 +5,13 @@ */ namespace Magento\Framework\Config\Test\Unit\Reader; -use \Magento\Framework\Config\Reader\Filesystem; +use Magento\Framework\Config\Reader\Filesystem; +/** + * Test for + * + * @see Filesystem + */ class FilesystemTest extends \PHPUnit\Framework\TestCase { /** @@ -64,7 +69,7 @@ public function testRead() ); $this->_fileResolverMock->expects($this->once())->method('get')->will($this->returnValue([$this->_file])); - $dom = new \DomDocument(); + $dom = new \DOMDocument(); $dom->loadXML($this->_file); $this->_converterMock->expects($this->once())->method('convert')->with($dom); $model->read('scope'); diff --git a/lib/internal/Magento/Framework/DB/Adapter/Pdo/Mysql.php b/lib/internal/Magento/Framework/DB/Adapter/Pdo/Mysql.php index edec7e135ae9f..480af45e40a69 100644 --- a/lib/internal/Magento/Framework/DB/Adapter/Pdo/Mysql.php +++ b/lib/internal/Magento/Framework/DB/Adapter/Pdo/Mysql.php @@ -274,6 +274,7 @@ public function __construct( public function beginTransaction() { if ($this->_isRolledBack) { + // phpcs:ignore Magento2.Exceptions.DirectThrow.FoundDirectThrow throw new \Exception(AdapterInterface::ERROR_ROLLBACK_INCOMPLETE_MESSAGE); } if ($this->_transactionLevel === 0) { @@ -298,8 +299,10 @@ public function commit() parent::commit(); $this->logger->logStats(LoggerInterface::TYPE_TRANSACTION, 'COMMIT'); } elseif ($this->_transactionLevel === 0) { + // phpcs:ignore Magento2.Exceptions.DirectThrow.FoundDirectThrow throw new \Exception(AdapterInterface::ERROR_ASYMMETRIC_COMMIT_MESSAGE); } elseif ($this->_isRolledBack) { + // phpcs:ignore Magento2.Exceptions.DirectThrow.FoundDirectThrow throw new \Exception(AdapterInterface::ERROR_ROLLBACK_INCOMPLETE_MESSAGE); } --$this->_transactionLevel; @@ -320,6 +323,7 @@ public function rollBack() $this->_isRolledBack = false; $this->logger->logStats(LoggerInterface::TYPE_TRANSACTION, 'ROLLBACK'); } elseif ($this->_transactionLevel === 0) { + // phpcs:ignore Magento2.Exceptions.DirectThrow.FoundDirectThrow throw new \Exception(AdapterInterface::ERROR_ASYMMETRIC_ROLLBACK_MESSAGE); } else { $this->_isRolledBack = true; @@ -352,7 +356,7 @@ public function convertDate($date) /** * Convert date and time to DB format * - * @param int|string|\DateTimeInterface $datetime + * @param int|string|\DateTimeInterface $datetime * @return \Zend_Db_Expr */ public function convertDateTime($datetime) @@ -956,12 +960,12 @@ public function tableColumnExists($tableName, $columnName, $schemaName = null) * Using string as $definition is allowed only for concrete DB adapter. * Adds primary key if needed * - * @param string $tableName - * @param string $columnName - * @param array|string $definition string specific or universal array DB Server definition - * @param string $schemaName - * @return true|\Zend_Db_Statement_Pdo - * @throws \Zend_Db_Exception + * @param string $tableName + * @param string $columnName + * @param array|string $definition string specific or universal array DB Server definition + * @param string $schemaName + * @return true|\Zend_Db_Statement_Pdo + * @throws \Zend_Db_Exception */ public function addColumn($tableName, $columnName, $definition, $schemaName = null) { @@ -1076,7 +1080,7 @@ protected function _getIndexByColumns($tableName, array $columns, $schemaName) * @param string $oldColumnName * @param string $newColumnName * @param array $definition - * @param boolean $flushData flush table statistic + * @param boolean $flushData flush table statistic * @param string $schemaName * @return \Zend_Db_Statement_Pdo * @throws \Zend_Db_Exception @@ -1522,7 +1526,7 @@ protected function _getCacheId($tableKey, $ddlType) * Return false if cache does not exists * * @param string $tableCacheKey the table cache key - * @param int $ddlType the DDL constant + * @param int $ddlType the DDL constant * @return string|array|int|false */ public function loadDdlCache($tableCacheKey, $ddlType) @@ -2035,10 +2039,10 @@ public function insertMultiple($table, array $data) * - array of values, if $columns contains only one column * array('value1', 'value2') * - * @param string $table - * @param string[] $columns - * @param array $data - * @param int $strategy + * @param string $table + * @param string[] $columns + * @param array $data + * @param int $strategy * @return int * @throws \Zend_Db_Exception */ @@ -2149,7 +2153,7 @@ public function createTable(Table $table) * * @param \Magento\Framework\DB\Ddl\Table $table * @throws \Zend_Db_Exception - * @return \Zend_Db_Pdo_Statement + * @return \Zend_Db_Statement_Pdo|void * @SuppressWarnings(PHPMD.UnusedLocalVariable) */ public function createTemporaryTable(\Magento\Framework\DB\Ddl\Table $table) @@ -2659,8 +2663,8 @@ public function renameTable($oldTableName, $newTableName, $schemaName = null) * * @param string $tableName * @param string $indexName - * @param string|array $fields the table column name or array of ones - * @param string $indexType the index type + * @param string|array $fields the table column name or array of ones + * @param string $indexType the index type * @param string $schemaName * @return \Zend_Db_Statement_Interface * @throws \Zend_Db_Exception @@ -2800,7 +2804,7 @@ public function dropIndex($tableName, $keyName, $schemaName = null) * @param string $refTableName * @param string $refColumnName * @param string $onDelete - * @param bool $purge trying remove invalid data + * @param bool $purge trying remove invalid data * @param string $schemaName * @param string $refSchemaName * @return \Zend_Db_Statement_Interface @@ -3031,7 +3035,7 @@ protected function _transformStringSqlCondition($conditionKey, $value) * * Return converted to column data type value * - * @param array $column the column describe array + * @param array $column the column describe array * @param mixed $value * @return mixed * @@ -3118,7 +3122,7 @@ public function prepareColumnValue(array $column, $value) * Generate fragment of SQL, that check condition and return true or false value * * @param \Zend_Db_Expr|\Magento\Framework\DB\Select|string $expression - * @param string $true true value + * @param string $true true value * @param string $false false value * @return \Zend_Db_Expr */ @@ -3256,7 +3260,7 @@ protected function _getIntervalUnitSql($interval, $unit) * * @see INTERVAL_* constants for $unit * - * @param \Zend_Db_Expr|string $date quoted field name or SQL statement + * @param \Zend_Db_Expr|string $date quoted field name or SQL statement * @param int $interval * @param string $unit * @return \Zend_Db_Expr @@ -3272,7 +3276,7 @@ public function getDateAddSql($date, $interval, $unit) * * @see INTERVAL_* constants for $expr * - * @param \Zend_Db_Expr|string $date quoted field name or SQL statement + * @param \Zend_Db_Expr|string $date quoted field name or SQL statement * @param int|string $interval * @param string $unit * @return \Zend_Db_Expr @@ -3295,7 +3299,7 @@ public function getDateSubSql($date, $interval, $unit) * %m Month, numeric (00..12) * %Y Year, numeric, four digits * - * @param string $date quoted date value or non quoted SQL statement(field) + * @param string $date quoted date value or non quoted SQL statement(field) * @param string $format * @return \Zend_Db_Expr */ @@ -3308,7 +3312,7 @@ public function getDateFormatSql($date, $format) /** * Extract the date part of a date or datetime expression * - * @param \Zend_Db_Expr|string $date quoted field name or SQL statement + * @param \Zend_Db_Expr|string $date quoted field name or SQL statement * @return \Zend_Db_Expr */ public function getDatePartSql($date) @@ -3335,7 +3339,7 @@ public function getSubstringSql($stringExpression, $pos, $len = null) /** * Prepare standard deviation sql function * - * @param \Zend_Db_Expr|string $expressionField quoted field name or SQL statement + * @param \Zend_Db_Expr|string $expressionField quoted field name or SQL statement * @return \Zend_Db_Expr */ public function getStandardDeviationSql($expressionField) @@ -3348,7 +3352,7 @@ public function getStandardDeviationSql($expressionField) * * @see INTERVAL_* constants for $unit * - * @param \Zend_Db_Expr|string $date quoted field name or SQL statement + * @param \Zend_Db_Expr|string $date quoted field name or SQL statement * @param string $unit * @return \Zend_Db_Expr * @throws \Zend_Db_Exception @@ -3378,9 +3382,9 @@ public function getTableName($tableName) /** * Build a trigger name based on table name and trigger details * - * @param string $tableName The table which is the subject of the trigger - * @param string $time Either "before" or "after" - * @param string $event The DB level event which activates the trigger, i.e. "update" or "insert" + * @param string $tableName The table which is the subject of the trigger + * @param string $time Either "before" or "after" + * @param string $event The DB level event which activates the trigger, i.e. "update" or "insert" * @return string * @codeCoverageIgnore */ @@ -3396,7 +3400,7 @@ public function getTriggerName($tableName, $time, $event) * Check index name length and allowed symbols * * @param string $tableName - * @param string|string[] $fields the columns list + * @param string|string[] $fields the columns list * @param string $indexType * @return string */ @@ -3474,7 +3478,7 @@ public function enableTableKeys($tableName, $schemaName = null) * Get insert from Select object query * * @param Select $select - * @param string $table insert into table + * @param string $table insert into table * @param array $fields * @param int|false $mode * @return string diff --git a/lib/internal/Magento/Framework/DB/Select.php b/lib/internal/Magento/Framework/DB/Select.php index f33aaea7d0e68..273d940babb91 100644 --- a/lib/internal/Magento/Framework/DB/Select.php +++ b/lib/internal/Magento/Framework/DB/Select.php @@ -434,7 +434,7 @@ protected function _tableCols($correlationName, $cols, $afterCorrelationName = n } } - return parent::_tableCols($correlationName, $cols, $afterCorrelationName); + parent::_tableCols($correlationName, $cols, $afterCorrelationName); } /** diff --git a/lib/internal/Magento/Framework/DB/Test/Unit/SelectTest.php b/lib/internal/Magento/Framework/DB/Test/Unit/SelectTest.php index 2be211a6c3da0..47772d32b6b17 100644 --- a/lib/internal/Magento/Framework/DB/Test/Unit/SelectTest.php +++ b/lib/internal/Magento/Framework/DB/Test/Unit/SelectTest.php @@ -97,7 +97,7 @@ public function testWhere() * * @param int $callCount * @param string|null $returnValue - * @return \Magento\Framework\DB\Adapter\Pdo\Mysql|PHPUnit_Framework_MockObject_MockObject + * @return \Magento\Framework\DB\Adapter\Pdo\Mysql|\PHPUnit_Framework_MockObject_MockObject */ protected function _getConnectionMockWithMockedQuote($callCount, $returnValue = null) { diff --git a/lib/internal/Magento/Framework/DB/Transaction.php b/lib/internal/Magento/Framework/DB/Transaction.php index e5c4741dd0d58..8d3fc8fff9fd5 100644 --- a/lib/internal/Magento/Framework/DB/Transaction.php +++ b/lib/internal/Magento/Framework/DB/Transaction.php @@ -1,13 +1,13 @@ <?php /** - * DB transaction model - * * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\Framework\DB; /** + * DB transaction model + * * @todo need collect connection by name */ class Transaction @@ -104,7 +104,7 @@ public function addObject(\Magento\Framework\Model\AbstractModel $object, $alias /** * Add callback function which will be called before commit transactions * - * @param callback $callback + * @param callable $callback * @return $this */ public function addCommitCallback($callback) diff --git a/lib/internal/Magento/Framework/Data/AbstractSearchCriteriaBuilder.php b/lib/internal/Magento/Framework/Data/AbstractSearchCriteriaBuilder.php index a3bf4d52a13bd..867bf3b0178b1 100644 --- a/lib/internal/Magento/Framework/Data/AbstractSearchCriteriaBuilder.php +++ b/lib/internal/Magento/Framework/Data/AbstractSearchCriteriaBuilder.php @@ -9,6 +9,7 @@ /** * Class AbstractSearchCriteriaBuilder + * * @package Magento\Framework\Data */ abstract class AbstractSearchCriteriaBuilder @@ -23,9 +24,14 @@ abstract class AbstractSearchCriteriaBuilder */ protected $resultObjectInterface; + /** + * @var Logger + */ + private $logger; + /** * @param Logger $logger - * @param ObjectFactory $objectFactory, + * @param ObjectFactory $objectFactory */ public function __construct( Logger $logger, @@ -37,11 +43,15 @@ public function __construct( } /** + * Initialization + * * @return string */ abstract protected function init(); /** + * Retrieve interface for result + * * @return string */ protected function getResultObjectInterface() @@ -50,6 +60,8 @@ protected function getResultObjectInterface() } /** + * Create result object + * * @return SearchResultInterface */ public function make() diff --git a/lib/internal/Magento/Framework/Data/Collection/Filesystem.php b/lib/internal/Magento/Framework/Data/Collection/Filesystem.php index b2bd352ea279c..629b992b32cfd 100644 --- a/lib/internal/Magento/Framework/Data/Collection/Filesystem.php +++ b/lib/internal/Magento/Framework/Data/Collection/Filesystem.php @@ -412,7 +412,7 @@ protected function _generateRow($filename) * @param string $field * @param mixed $value * @param string $type 'and'|'or' - * @param callback $callback + * @param callable $callback * @param bool $isInverted * @return $this */ @@ -473,7 +473,7 @@ protected function _filterRow($row) /** * Invokes specified callback. Skips, if there is no filtered key in the row. * - * @param callback $callback + * @param callable $callback * @param array $callbackParams * @return bool * @SuppressWarnings(PHPMD.UnusedLocalVariable) diff --git a/lib/internal/Magento/Framework/DataObject/Mapper.php b/lib/internal/Magento/Framework/DataObject/Mapper.php index 0b00564a454a0..168f7f82d6186 100644 --- a/lib/internal/Magento/Framework/DataObject/Mapper.php +++ b/lib/internal/Magento/Framework/DataObject/Mapper.php @@ -4,12 +4,11 @@ * See COPYING.txt for license details. */ -/** - * Utility class for mapping data between objects or arrays - */ namespace Magento\Framework\DataObject; /** + * Utility class for mapping data between objects or arrays + * * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) */ @@ -36,8 +35,8 @@ class Mapper * <\Magento\Framework\DataObject> => $from->setData($key, <from>) * array(<\Magento\Framework\DataObject>, <method>) => $from->$method($key, <from>) * - * @param array|\Magento\Framework\DataObject|callback $from - * @param array|\Magento\Framework\DataObject|callback $to + * @param array|\Magento\Framework\DataObject|callable $from + * @param array|\Magento\Framework\DataObject|callable $to * @param array $map * @param array $defaults * @return array|object diff --git a/lib/internal/Magento/Framework/EntityManager/Operation/ValidatorPool.php b/lib/internal/Magento/Framework/EntityManager/Operation/ValidatorPool.php index 0dc7aa3660923..f28de6485f6b5 100644 --- a/lib/internal/Magento/Framework/EntityManager/Operation/ValidatorPool.php +++ b/lib/internal/Magento/Framework/EntityManager/Operation/ValidatorPool.php @@ -23,6 +23,11 @@ class ValidatorPool */ protected $validators; + /** + * @var array + */ + private $actions; + /** * @param ObjectManagerInterface $objectManager * @param array $extensionActions @@ -36,6 +41,8 @@ public function __construct( } /** + * Get list of validators + * * @param string $entityType * @param string $actionName * @return object[] diff --git a/lib/internal/Magento/Framework/Event/Test/Unit/Invoker/InvokerDefaultTest.php b/lib/internal/Magento/Framework/Event/Test/Unit/Invoker/InvokerDefaultTest.php index e6ec123823854..5d142fe6f1ff9 100644 --- a/lib/internal/Magento/Framework/Event/Test/Unit/Invoker/InvokerDefaultTest.php +++ b/lib/internal/Magento/Framework/Event/Test/Unit/Invoker/InvokerDefaultTest.php @@ -16,7 +16,7 @@ class InvokerDefaultTest extends \PHPUnit\Framework\TestCase protected $_observerFactoryMock; /** - * @var \Magento\Framework\Event\Observer|PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Event\Observer|\PHPUnit_Framework_MockObject_MockObject */ protected $_observerMock; diff --git a/lib/internal/Magento/Framework/GraphQl/Query/Resolver/Argument/FieldEntityAttributesPool.php b/lib/internal/Magento/Framework/GraphQl/Query/Resolver/Argument/FieldEntityAttributesPool.php index bd9de206ccda1..f1226469e49a4 100644 --- a/lib/internal/Magento/Framework/GraphQl/Query/Resolver/Argument/FieldEntityAttributesPool.php +++ b/lib/internal/Magento/Framework/GraphQl/Query/Resolver/Argument/FieldEntityAttributesPool.php @@ -38,7 +38,7 @@ public function getEntityAttributesForEntityFromField(string $fieldName) : array if (isset($this->attributesInstances[$fieldName])) { return $this->attributesInstances[$fieldName]->getEntityAttributes(); } else { - throw new \LogicException(sprintf('There is no attribute class assigned to field %1', $fieldName)); + throw new \LogicException(sprintf('There is no attribute class assigned to field %s', $fieldName)); } } } diff --git a/lib/internal/Magento/Framework/HTTP/Test/Unit/PhpEnvironment/RemoteAddressTest.php b/lib/internal/Magento/Framework/HTTP/Test/Unit/PhpEnvironment/RemoteAddressTest.php index 538359edd4306..147505371ba85 100644 --- a/lib/internal/Magento/Framework/HTTP/Test/Unit/PhpEnvironment/RemoteAddressTest.php +++ b/lib/internal/Magento/Framework/HTTP/Test/Unit/PhpEnvironment/RemoteAddressTest.php @@ -9,10 +9,15 @@ use Magento\Framework\App\Request\Http as HttpRequest; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +/** + * Test for + * + * @see RemoteAddress + */ class RemoteAddressTest extends \PHPUnit\Framework\TestCase { /** - * @var \PHPUnit_Framework_MockObject_MockObject|\HttpRequest + * @var \PHPUnit_Framework_MockObject_MockObject|HttpRequest */ protected $_request; From ff7b120bbd67a92c2f890b2817b1b2d1972aacd7 Mon Sep 17 00:00:00 2001 From: natalia <natalia_marozava@epam.com> Date: Mon, 24 Jun 2019 12:11:41 +0300 Subject: [PATCH 508/773] MAGETWO-54438: Simple Product don't appear on Storefront after order cancelation with Bundle --- ...ontAssertProductStockStatusActionGroup.xml | 21 +++ .../Sales/Test/Mftf/Data/ProductData.xml | 70 +++++++++ ...erWithCheckMoneyOrderPaymentMethodTest.xml | 138 ++++++++++-------- 3 files changed, 170 insertions(+), 59 deletions(-) create mode 100644 app/code/Magento/CatalogInventory/Test/Mftf/ActionGroup/StorefrontAssertProductStockStatusActionGroup.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/Data/ProductData.xml diff --git a/app/code/Magento/CatalogInventory/Test/Mftf/ActionGroup/StorefrontAssertProductStockStatusActionGroup.xml b/app/code/Magento/CatalogInventory/Test/Mftf/ActionGroup/StorefrontAssertProductStockStatusActionGroup.xml new file mode 100644 index 0000000000000..04d37c2a9042c --- /dev/null +++ b/app/code/Magento/CatalogInventory/Test/Mftf/ActionGroup/StorefrontAssertProductStockStatusActionGroup.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="storefrontCheckProductStockStatus"> + <arguments> + <argument name="productUrlKey" type="string"/> + <argument name="productName" type="string"/> + </arguments> + <amOnPage url="{{StorefrontProductPage.url(productUrlKey)}}" stepKey="navigateToProductPage"/> + <waitForPageLoad stepKey="waitForProductPageLoad"/> + <see selector="{{StorefrontProductInfoMainSection.productName}}" userInput="{{productName}}" stepKey="seeProductName"/> + <see userInput="IN STOCK" stepKey="assertProductStockStatus"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Sales/Test/Mftf/Data/ProductData.xml b/app/code/Magento/Sales/Test/Mftf/Data/ProductData.xml new file mode 100644 index 0000000000000..5f754ad998437 --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/Data/ProductData.xml @@ -0,0 +1,70 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd"> + <entity name="SimpleProductPrice10Qty1" type="product"> + <data key="sku" unique="suffix">simple-product_</data> + <data key="type_id">simple</data> + <data key="attribute_set_id">4</data> + <data key="visibility">4</data> + <data key="name" unique="suffix">SimpleProduct_</data> + <data key="price">10.00</data> + <data key="urlKey" unique="suffix">simple-product_</data> + <data key="status">1</data> + <requiredEntity type="product_extension_attribute">EavStock1</requiredEntity> + <requiredEntity type="custom_attribute_array">CustomAttributeCategoryIds</requiredEntity> + </entity> + <entity name="VirtualProductPrice10Qty1" type="product"> + <data key="sku" unique="suffix">virtual-product_</data> + <data key="type_id">virtual</data> + <data key="attribute_set_id">4</data> + <data key="name" unique="suffix">VirtualProduct_</data> + <data key="price">10.00</data> + <data key="weight">0</data> + <data key="status">1</data> + <requiredEntity type="product_extension_attribute">EavStock1</requiredEntity> + <requiredEntity type="custom_attribute_array">CustomAttributeCategoryIds</requiredEntity> + </entity> + <entity name="SimpleProduct2Price10Qty1" type="product"> + <data key="sku" unique="suffix">simple-product-2_</data> + <data key="type_id">simple</data> + <data key="attribute_set_id">4</data> + <data key="name" unique="suffix">SimpleProduct2_</data> + <data key="price">10.00</data> + <data key="visibility">4</data> + <data key="status">1</data> + <requiredEntity type="product_extension_attribute">EavStock1</requiredEntity> + </entity> + <entity name="SimpleProduct3Price10Qty1" type="product2"> + <data key="sku" unique="suffix">simple-product-3_</data> + <data key="type_id">simple</data> + <data key="attribute_set_id">4</data> + <data key="visibility">4</data> + <data key="name" unique="suffix">SimpleProduct3_</data> + <data key="price">10.00</data> + <data key="urlKey" unique="suffix">simple-product-3_</data> + <data key="status">1</data> + <requiredEntity type="product_extension_attribute">EavStock1</requiredEntity> + <requiredEntity type="custom_attribute">CustomAttributeProductAttribute</requiredEntity> + </entity> + <entity name="ConfigurableProductPrice10Qty1" type="product"> + <data key="sku" unique="suffix">configurable-product_</data> + <data key="type_id">configurable</data> + <data key="attribute_set_id">4</data> + <data key="visibility">4</data> + <data key="name" unique="suffix">ConfigurableProduct_</data> + <data key="urlKey" unique="suffix">configurable-product_</data> + <data key="price">10.00</data> + <data key="weight">2</data> + <data key="status">1</data> + <data key="quantity">1</data> + <requiredEntity type="product_extension_attribute">EavStockItem</requiredEntity> + <requiredEntity type="custom_attribute_array">CustomAttributeCategoryIds</requiredEntity> + </entity> +</entities> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminCancelTheCreatedOrderWithCheckMoneyOrderPaymentMethodTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCancelTheCreatedOrderWithCheckMoneyOrderPaymentMethodTest.xml index 614946d7f8a8a..232eaf566d8db 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminCancelTheCreatedOrderWithCheckMoneyOrderPaymentMethodTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminCancelTheCreatedOrderWithCheckMoneyOrderPaymentMethodTest.xml @@ -18,34 +18,30 @@ <testCaseId value="MC-16066"/> <group value="mtf_migrated"/> </annotations> - <before> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> - - <!--Set default flat rate shipping method settings--> + <!-- Set default flat rate shipping method settings --> + <comment userInput="Set default flat rate shipping method settings" stepKey="SetDefaultFlatRateShippingMethodSetting"/> <createData entity="FlatRateShippingMethodDefault" stepKey="setDefaultFlatRateShippingMethod"/> - - <!--Create simple customer--> + <!-- Create simple customer --> + <comment userInput="Create simple customer" stepKey="CreateSimpleCustomer"/> <createData entity="Simple_US_Customer_CA" stepKey="simpleCustomer"/> - <!-- Create the category --> + <comment userInput="Create the category" stepKey="CreateTheCategory"/> <createData entity="ApiCategory" stepKey="createCategory"/> - <!-- Create Virtual Product --> - <createData entity="VirtualProduct" stepKey="virtualProduct"> - <field key="price">10.00</field> + <comment userInput="Create Virtual Product" stepKey="CreateVirtualProduct"/> + <createData entity="VirtualProductPrice10Qty1" stepKey="virtualProduct"> + <requiredEntity createDataKey="createCategory"/> </createData> - <!-- Create Simple Product --> - <createData entity="ApiSimplePrice10Qty10" stepKey="simpleProduct"> + <comment userInput="Create Simple Product" stepKey="CreateSimpleProduct"/> + <createData entity="SimpleProductPrice10Qty1" stepKey="simpleProduct"> <requiredEntity createDataKey="createCategory"/> - <field key="price">10.00</field> - </createData> - - <!--Create Bundle product--> - <createData entity="SimpleProduct2" stepKey="simpleProduct1"> - <field key="price">10.00</field> </createData> + <!-- Create Bundle product --> + <comment userInput="Create Bundle Product" stepKey="CreateBundleProduct"/> + <createData entity="SimpleProduct2Price10Qty1" stepKey="simpleProduct1"/> <createData entity="BundleProductPriceViewRange" stepKey="createBundleProduct"> <requiredEntity createDataKey="createCategory"/> </createData> @@ -58,42 +54,42 @@ <requiredEntity createDataKey="createBundleOption1_1"/> <requiredEntity createDataKey="simpleProduct1"/> </createData> - <!-- Create configurable product and add it to the category --> - <createData entity="ApiConfigurableProduct" stepKey="createConfigProduct"> + <comment userInput="Create configurable product and add it to the category" stepKey="CreateConfigProduct"/> + <createData entity="ConfigurableProductPrice10Qty1" stepKey="createConfigProduct"> <requiredEntity createDataKey="createCategory"/> </createData> - <!-- Create an attribute with two options to be used in the first child product --> + <comment userInput="Create an attribute with two options to be used in the first child product" stepKey="CreateOptionsOfTheFirstChildProduct"/> <createData entity="productAttributeWithTwoOptions" stepKey="createConfigProductAttribute"/> <createData entity="productAttributeOption1" stepKey="createConfigProductAttributeOption1"> <requiredEntity createDataKey="createConfigProductAttribute"/> </createData> - <!-- Add the attribute we just created to default attribute set --> + <comment userInput="Add the attribute we just created to default attribute set" stepKey="AddAttributeToDefaultAttrSet"/> <createData entity="AddToDefaultSet" stepKey="createConfigAddToAttributeSet"> <requiredEntity createDataKey="createConfigProductAttribute"/> </createData> - <!-- Get the option of the attribute we created --> + <comment userInput="Get the option of the attribute we created" stepKey="GetAttributeOption"/> <getData entity="ProductAttributeOptionGetter" index="1" stepKey="getConfigAttributeOption1"> <requiredEntity createDataKey="createConfigProductAttribute"/> </getData> - <!-- Create a simple product and give it the attribute with option --> - <createData entity="ApiSimpleOne" stepKey="createConfigChildProduct1"> + <comment userInput="Create a simple product and give it the attribute with option" stepKey="CreateSimpleProductWithOptions"/> + <createData entity="SimpleProduct3Price10Qty1" stepKey="createConfigChildProduct1"> <requiredEntity createDataKey="createConfigProductAttribute"/> <requiredEntity createDataKey="getConfigAttributeOption1"/> </createData> - <!-- Create the configurable product --> + <comment userInput="Create the configurable product" stepKey="CreateTheConfigurableProduct"/> <createData entity="ConfigurableProductTwoOptions" stepKey="createConfigProductOption"> <requiredEntity createDataKey="createConfigProduct"/> <requiredEntity createDataKey="createConfigProductAttribute"/> <requiredEntity createDataKey="getConfigAttributeOption1"/> </createData> - <!-- Add simple product to the configurable product --> + <comment userInput="Add simple product to the configurable product" stepKey="AddSimpleProductToConfigurable"/> <createData entity="ConfigurableProductAddChild" stepKey="createConfigProductAddChild1"> <requiredEntity createDataKey="createConfigProduct"/> <requiredEntity createDataKey="createConfigChildProduct1"/> @@ -113,103 +109,127 @@ <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <actionGroup ref="logout" stepKey="logout"/> </after> - - <!--Create new customer order--> + <!-- Create new customer order --> + <comment userInput="Create new customer order" stepKey="CreateNewCustomerOrder"/> <actionGroup ref="navigateToNewOrderPageExistingCustomer" stepKey="navigateToNewOrderWithExistingCustomer"> <argument name="customer" value="$$simpleCustomer$$"/> </actionGroup> - - <!--Add bundle product to order and check product price in grid--> + <!-- Add bundle product to order and check product price in grid --> + <comment userInput="Add bundle product to order and check product price in grid" stepKey="AddBundleProductToOrder"/> <actionGroup ref="addBundleProductToOrder" stepKey="addBundleProductToOrder"> <argument name="product" value="$$createBundleProduct$$"/> <argument name="quantity" value="1"/> </actionGroup> - - <!--Add configurable product to order--> + <!-- Add configurable product to order --> + <comment userInput="Add configurable product to order" stepKey="AddConfigurableProductToOrder"/> <actionGroup ref="newAddConfigurableProductToOrder" stepKey="addConfigurableProductToOrder"> <argument name="product" value="$$createConfigProduct$$"/> <argument name="attribute" value="$$createConfigProductAttribute$$"/> <argument name="option" value="$$getConfigAttributeOption1$$"/> </actionGroup> - - <!--Add Simple product to order--> + <!-- Add Simple product to order --> + <comment userInput="Add Simple product to order" stepKey="AddSimpleProductToOrder"/> <actionGroup ref="addSimpleProductToOrder" stepKey="addSimpleProductToTheOrder"> <argument name="product" value="$$simpleProduct$$"/> </actionGroup> - - <!--Add Virtual product to order--> + <!-- Add Virtual product to order --> + <comment userInput="Add Virtual product to order" stepKey="AddVirtualProductToOrder"/> <actionGroup ref="addSimpleProductToOrder" stepKey="addVirtualProductToTheOrder"> <argument name="product" value="$$virtualProduct$$"/> </actionGroup> - - <!--Select FlatRate shipping method--> + <!-- Select FlatRate shipping method --> + <comment userInput="Select FlatRate shipping method" stepKey="SelectFlatRateShippingMethod"/> <actionGroup ref="AdminSelectFlatRateShippingMethodActionGroup" stepKey="selectFlatRateShippingMethod"/> - <!-- Submit order --> + <comment userInput="Submit order" stepKey="SubmitOrder"/> <click selector="{{AdminOrderFormActionSection.SubmitOrder}}" stepKey="submitOrder"/> - - <!--Verify order information--> + <!-- Verify order information --> + <comment userInput="Verify order information" stepKey="VerifyOrderInformation"/> <actionGroup ref="verifyCreatedOrderInformation" stepKey="verifyCreatedOrderInformation"/> <grabTextFrom selector="|Order # (\d+)|" stepKey="orderId"/> - <!-- Cancel the Order --> + <comment userInput="Cancel the Order" stepKey="CancelTheOrder"/> <actionGroup ref="cancelPendingOrder" stepKey="cancelPendingOrder"/> - <!-- Assert Simple Product Quantity in backend after order Canceled --> + <comment userInput="Assert Simple Product Quantity in backend after order Canceled" stepKey="AssertSimpleProductQuantityAfterOrderCanceled"/> <actionGroup ref="filterAndSelectProduct" stepKey="filterAndSelectTheProduct"> <argument name="productSku" value="$$simpleProduct.sku$$"/> </actionGroup> <waitForElementVisible selector="{{AdminProductFormSection.productName}}" stepKey="waitForProductDetailsToLoad"/> <seeInField selector="{{AdminProductFormSection.productName}}" userInput="$$simpleProduct.name$$" stepKey="seeProductName"/> - <seeInField selector="{{AdminProductFormSection.productQuantity}}" userInput="10" stepKey="seeProductQuantity"/> + <seeInField selector="{{AdminProductFormSection.productQuantity}}" userInput="1" stepKey="seeProductQuantity"/> <seeInField selector="{{AdminProductFormSection.productStockStatus}}" userInput="In Stock" stepKey="seeProductStockStatus"/> - - <!-- Assert Virtual Product Quantity in backend after order canceled--> + <!-- Assert Simple Product Stock Status in frontend after order canceled --> + <comment userInput="Assert Simple Product Stock Status in frontend after order Canceled" stepKey="AssertSimpleProductStockStatus"/> + <actionGroup ref="storefrontCheckProductStockStatus" stepKey="checkProductQtyOfSimpleProduct"> + <argument name="productUrlKey" value="$$simpleProduct.custom_attributes[url_key]$$"/> + <argument name="productName" value="$$simpleProduct.name$$"/> + </actionGroup> + <!-- Assert Virtual Product Quantity in backend after order canceled --> + <comment userInput="Assert Virtual Product Quantity in backend after order canceled" stepKey="AssertVirtualProductQuantityAfterOrderCanceled"/> <actionGroup ref="filterAndSelectProduct" stepKey="filterAndSelectTheVirtualProduct"> <argument name="productSku" value="$$virtualProduct.sku$$"/> </actionGroup> <waitForElementVisible selector="{{AdminProductFormSection.productName}}" stepKey="waitForProductDetailsToLoad1"/> <seeInField selector="{{AdminProductFormSection.productName}}" userInput="$$virtualProduct.name$$" stepKey="seeVirtualProductName"/> - <seeInField selector="{{AdminProductFormSection.productQuantity}}" userInput="1000" stepKey="seeVirtualProductQuantity"/> + <seeInField selector="{{AdminProductFormSection.productQuantity}}" userInput="1" stepKey="seeVirtualProductQuantity"/> <seeInField selector="{{AdminProductFormSection.productStockStatus}}" userInput="In Stock" stepKey="seeVirtualProductStockStatus"/> - - <!-- Assert Bundle Product quantity in backend after order canceled--> + <!-- Assert Virtual Product Stock Status in frontend after order canceled --> + <comment userInput="Assert Virtual Product Stock Status in frontend after order Canceled" stepKey="AssertVirtualProductStockStatus"/> + <actionGroup ref="storefrontCheckProductStockStatus" stepKey="checkProductQtyOfVirtualProduct"> + <argument name="productUrlKey" value="$$virtualProduct.custom_attributes[url_key]$$"/> + <argument name="productName" value="$$virtualProduct.name$$"/> + </actionGroup> + <!-- Assert Bundle Product Quantity in backend after order canceled --> + <comment userInput="Assert Bundle Product Quantity in backend after order canceled" stepKey="AssertBundleProductQuantityAfterOrderCanceled"/> <actionGroup ref="filterAndSelectProduct" stepKey="filterAndSelectTheBundleProduct"> <argument name="productSku" value="$$simpleProduct1.sku$$"/> </actionGroup> <waitForElementVisible selector="{{AdminProductFormSection.productName}}" stepKey="waitForProductDetailsToLoad2"/> <seeInField selector="{{AdminProductFormSection.productName}}" userInput="$$simpleProduct1.name$$" stepKey="seeBundleProductName"/> - <seeInField selector="{{AdminProductFormSection.productQuantity}}" userInput="1000" stepKey="seeBundleProductQuantity"/> + <seeInField selector="{{AdminProductFormSection.productQuantity}}" userInput="1" stepKey="seeBundleProductQuantity"/> <seeInField selector="{{AdminProductFormSection.productStockStatus}}" userInput="In Stock" stepKey="seeBundleProductStockStatus"/> - - <!-- Assert Configurable Product quantity in backend after order canceled--> + <!-- Assert Bundle Product Stock Status in frontend after order canceled --> + <comment userInput="Assert Bundle Product Stock Status in frontend after order Canceled" stepKey="AssertBundleProductStockStatus"/> + <actionGroup ref="storefrontCheckProductStockStatus" stepKey="checkProductQtyOfBundleProduct"> + <argument name="productUrlKey" value="$$createBundleProduct.custom_attributes[url_key]$$"/> + <argument name="productName" value="$$createBundleProduct.name$$"/> + </actionGroup> + <!-- Assert Configurable Product Quantity in backend after order canceled --> + <comment userInput="Assert Configurable Product quantity in backend after order canceled" stepKey="AssertConfigurableProductQuantityAfterOrderCanceled"/> <actionGroup ref="filterAndSelectProduct" stepKey="filterAndSelectTheConfigProduct"> <argument name="productSku" value="$$createConfigChildProduct1.sku$$"/> </actionGroup> <waitForElementVisible selector="{{AdminProductFormSection.productName}}" stepKey="waitForProductDetailsToLoad3"/> <seeInField selector="{{AdminProductFormSection.productName}}" userInput="$$createConfigChildProduct1.name$$" stepKey="seeConfigProductName"/> - <seeInField selector="{{AdminProductFormSection.productQuantity}}" userInput="1000" stepKey="seeConfigProductQuantity"/> + <seeInField selector="{{AdminProductFormSection.productQuantity}}" userInput="1" stepKey="seeConfigProductQuantity"/> <seeInField selector="{{AdminProductFormSection.productStockStatus}}" userInput="In Stock" stepKey="seeConfigProductStockStatus"/> - + <!-- Assert Configurable Product Stock Status in frontend after order canceled --> + <comment userInput="Assert Configurable Product Stock Status in frontend after order Canceled" stepKey="AssertConfigurableProductStockStatus"/> + <actionGroup ref="storefrontCheckProductStockStatus" stepKey="checkProductQtyOfConfigProductInFrontend"> + <argument name="productUrlKey" value="$$createConfigProduct.custom_attributes[url_key]$$"/> + <argument name="productName" value="$$createConfigProduct.name$$"/> + </actionGroup> <!-- Open Order Index Page --> + <comment userInput="Open Order Index Page" stepKey="OpenOrderIndexPage"/> <amOnPage url="{{AdminOrdersPage.url}}" stepKey="goToOrders"/> <waitForPageLoad stepKey="waitForPageLoad5"/> - <!-- Filter order using orderId --> + <comment userInput="Filter order using orderId" stepKey="FilterOrderUsingOrderId"/> <actionGroup ref="filterOrderGridById" stepKey="filterOrderGridById"> <argument name="orderId" value="$orderId"/> </actionGroup> <see selector="{{AdminOrdersGridSection.firstRow}}" userInput="$orderId" stepKey="seeOrderIdInGrid"/> <see selector="{{AdminOrdersGridSection.firstRow}}" userInput="Canceled" stepKey="seeStatusInGrid"/> - - <!--Log in to Storefront as Customer --> + <!-- Log in to Storefront as Customer --> + <comment userInput="Log in to Storefront as Customer" stepKey="LogInAsCustomer"/> <actionGroup ref="LoginToStorefrontActionGroup" stepKey="signUp"> <argument name="Customer" value="$$simpleCustomer$$"/> </actionGroup> - <!-- Assert Order status in frontend order grid --> + <comment userInput="Assert Order status in frontend order grid " stepKey="AssertOrderStatusInFrontend"/> <click selector="{{StorefrontCustomerSidebarSection.sidebarCurrentTab('My Orders')}}" stepKey="clickOnMyOrders"/> <waitForPageLoad stepKey="waitForOrderDetailsToLoad"/> <seeElement selector="{{StorefrontCustomerOrderViewSection.orderStatusInGrid('$orderId', 'Canceled')}}" stepKey="seeOrderStatusInGrid"/> </test> -</tests> \ No newline at end of file +</tests> From 7429610351c380a894cba548f7628c28cb59d387 Mon Sep 17 00:00:00 2001 From: Dzmitry Tabusheu <dzmitry_tabusheu@epam.com> Date: Mon, 24 Jun 2019 17:09:19 +0300 Subject: [PATCH 509/773] MC-17387: Fatal error appears when adding bundle product to Cart from Wish list page - Added required blocks viewmodels --- .../wishlist_index_configure_type_bundle.xml | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Wishlist/view/frontend/layout/wishlist_index_configure_type_bundle.xml b/app/code/Magento/Wishlist/view/frontend/layout/wishlist_index_configure_type_bundle.xml index f8a0d4a9a0b15..9b3259c0fee8c 100644 --- a/app/code/Magento/Wishlist/view/frontend/layout/wishlist_index_configure_type_bundle.xml +++ b/app/code/Magento/Wishlist/view/frontend/layout/wishlist_index_configure_type_bundle.xml @@ -23,7 +23,11 @@ <block class="Magento\Wishlist\Block\Item\Configure" name="view.addto.wishlist.bundle" template="Magento_Wishlist::item/configure/addto/wishlist.phtml" /> <block class="Magento\Catalog\Block\Product\View\AddTo\Compare" name="view.addto.compare.bundle" after="view.addto.wishlist" - template="Magento_Catalog::product/view/addto/compare.phtml" /> + template="Magento_Catalog::product/view/addto/compare.phtml"> + <arguments> + <argument name="addToCompareViewModel" xsi:type="object">Magento\Catalog\ViewModel\Product\Checker\AddToCompareAvailability</argument> + </arguments> + </block> </block> </block> </referenceBlock> @@ -33,10 +37,22 @@ <container name="product.info.bundle.options.top" as="product_info_bundle_options_top"> <block class="Magento\Catalog\Block\Product\View" name="bundle.back.button" as="backButton" before="-" template="Magento_Bundle::catalog/product/view/backbutton.phtml"/> </container> - <block class="Magento\Bundle\Block\Catalog\Product\View\Type\Bundle\Option\Select" name="product.info.bundle.options.select" as="select"/> + <block class="Magento\Bundle\Block\Catalog\Product\View\Type\Bundle\Option\Select" name="product.info.bundle.options.select" as="select"> + <arguments> + <argument name="tier_price_renderer" xsi:type="object">\Magento\Bundle\Block\DataProviders\OptionPriceRenderer</argument> + </arguments> + </block> <block class="Magento\Bundle\Block\Catalog\Product\View\Type\Bundle\Option\Multi" name="product.info.bundle.options.multi" as="multi"/> - <block class="Magento\Bundle\Block\Catalog\Product\View\Type\Bundle\Option\Radio" name="product.info.bundle.options.radio" as="radio"/> - <block class="Magento\Bundle\Block\Catalog\Product\View\Type\Bundle\Option\Checkbox" name="product.info.bundle.options.checkbox" as="checkbox"/> + <block class="Magento\Bundle\Block\Catalog\Product\View\Type\Bundle\Option\Radio" name="product.info.bundle.options.radio" as="radio"> + <arguments> + <argument name="tier_price_renderer" xsi:type="object">\Magento\Bundle\Block\DataProviders\OptionPriceRenderer</argument> + </arguments> + </block> + <block class="Magento\Bundle\Block\Catalog\Product\View\Type\Bundle\Option\Checkbox" name="product.info.bundle.options.checkbox" as="checkbox"> + <arguments> + <argument name="tier_price_renderer" xsi:type="object">\Magento\Bundle\Block\DataProviders\OptionPriceRenderer</argument> + </arguments> + </block> </block> </referenceBlock> <move element="product.price.tier" destination="product.info.options.wrapper.bottom" before="-" /> From 928ca8c2fd316c528f34d2c5ed9bfb3f837017cf Mon Sep 17 00:00:00 2001 From: Viktor Petryk <victor.petryk@transoftgroup.com> Date: Mon, 24 Jun 2019 17:39:54 +0300 Subject: [PATCH 510/773] MC-17269: Date format grid is not based on the locale defined in the back-office --- .../AdminOrderDetailsInformationSection.xml | 3 +- .../Ui/Component/Listing/Columns/Date.php | 3 + ...kingDateAfterChangeInterfaceLocaleTest.xml | 88 +++++++++++++++++++ 3 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 app/code/Magento/Ui/Test/Mftf/Test/AdminCheckingDateAfterChangeInterfaceLocaleTest.xml diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderDetailsInformationSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderDetailsInformationSection.xml index 4d37479a8cd18..7994452156cfb 100644 --- a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderDetailsInformationSection.xml +++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderDetailsInformationSection.xml @@ -20,5 +20,6 @@ <element name="shippingAddress" type="text" selector=".order-shipping-address"/> <element name="itemsOrdered" type="text" selector=".edit-order-table"/> <element name="paymentInformation" type="text" selector="//div[@class='order-payment-method-title']"/> + <element name="orderId" type="text" selector="|Order # (\d+)|"/> </section> -</sections> \ No newline at end of file +</sections> diff --git a/app/code/Magento/Ui/Component/Listing/Columns/Date.php b/app/code/Magento/Ui/Component/Listing/Columns/Date.php index 6ae27294ce9a2..a9763491e481d 100644 --- a/app/code/Magento/Ui/Component/Listing/Columns/Date.php +++ b/app/code/Magento/Ui/Component/Listing/Columns/Date.php @@ -109,6 +109,9 @@ public function prepare() 'months' => $months, 'monthsShort' => $monthsShort, ]; + if (!isset($config['dateFormat'])) { + $config['dateFormat'] = $this->timezone->getDateTimeFormat(\IntlDateFormatter::MEDIUM); + } $this->setData('config', $config); parent::prepare(); diff --git a/app/code/Magento/Ui/Test/Mftf/Test/AdminCheckingDateAfterChangeInterfaceLocaleTest.xml b/app/code/Magento/Ui/Test/Mftf/Test/AdminCheckingDateAfterChangeInterfaceLocaleTest.xml new file mode 100644 index 0000000000000..f839d31c023bf --- /dev/null +++ b/app/code/Magento/Ui/Test/Mftf/Test/AdminCheckingDateAfterChangeInterfaceLocaleTest.xml @@ -0,0 +1,88 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AdminCheckingDateAfterChangeInterfaceLocaleTest"> + <annotations> + <features value="Ui"/> + <stories value="Checking the value in a grid column"/> + <title value="Checking date format in orders grid column after changing admin interface locale"/> + <description value="Checking date format in orders grid column after changing admin interface locale"/> + <severity value="MAJOR"/> + <testCaseId value="MC-17761"/> + <useCaseId value="MC-17269"/> + <group value="ui"/> + </annotations> + <before> + <!--Create entities--> + <createData entity="SimpleProduct2" stepKey="createProduct"/> + <createData entity="Simple_US_Customer" stepKey="createCustomer"/> + <!--Login to Admin page--> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + </before> + <after> + <!--Delete entities--> + <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> + <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> + <!--Set Admin "Interface Locale" to default value--> + <actionGroup ref="SetAdminAccountActionGroup" stepKey="setAdminInterfaceLocaleToDefaultValue"> + <argument name="InterfaceLocaleByValue" value="en_US"/> + </actionGroup> + <!--Clear filters--> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrderFilters"/> + <!--Logout from Admin page--> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <!--Create order--> + <actionGroup ref="CreateOrderActionGroup" stepKey="createOrder"> + <argument name="product" value="$$createProduct$$"/> + <argument name="customer" value="$$createCustomer$$"/> + </actionGroup> + <grabTextFrom selector="{{AdminOrderDetailsInformationSection.orderId}}" stepKey="grabOrderId"/> + + <!--Filter orders grid by ID on Admin page--> + <actionGroup ref="filterOrderGridById" stepKey="filterOrderGridById"> + <argument name="orderId" value="{$grabOrderId}"/> + </actionGroup> + + <!--Get date from "Purchase Date" column--> + <grabTextFrom selector="{{AdminOrdersGridSection.gridCell('1','Purchase Date')}}" stepKey="grabPurchaseDateInDefaultLocale"/> + + <!--Get month name in default locale (US)--> + <executeJS function="return (new Date('{$grabPurchaseDateInDefaultLocale}').toLocaleDateString('en-US', {month: 'short'}))" stepKey="getMonthNameInUS"/> + + <!--Checking Date with default "Interface Locale"--> + <assertContains stepKey="checkingDateWithDefaultInterfaceLocale"> + <expectedResult type="variable">getMonthNameInUS</expectedResult> + <actualResult type="variable">grabPurchaseDateInDefaultLocale</actualResult> + </assertContains> + + <!--Set Admin "Interface Locale" to "Français (France) / français (France)"--> + <actionGroup ref="SetAdminAccountActionGroup" stepKey="setAdminInterfaceLocaleToFrance"> + <argument name="InterfaceLocaleByValue" value="fr_FR"/> + </actionGroup> + + <!--Filter orders grid by ID on Admin page after changing "Interface Locale"--> + <actionGroup ref="filterOrderGridById" stepKey="filterOrderGridByIdAfterSetFrenchLocale"> + <argument name="orderId" value="{$grabOrderId}"/> + </actionGroup> + + <!--Get date from "Purchase Date" column after changing "Interface Locale"--> + <grabTextFrom selector="{{AdminOrdersGridSection.gridCell('1','Purchase Date')}}" stepKey="grabPurchaseDateInFrenchLocale"/> + + <!--Get month name in French--> + <executeJS function="return (new Date('{$grabPurchaseDateInDefaultLocale}').toLocaleDateString('fr-FR', {month: 'short'}))" stepKey="getMonthNameInFrench"/> + + <!--Checking Date after changing "Interface Locale"--> + <assertContains stepKey="checkingDateAfterChangeInterfaceLocale"> + <expectedResult type="variable">getMonthNameInFrench</expectedResult> + <actualResult type="variable">grabPurchaseDateInFrenchLocale</actualResult> + </assertContains> + </test> +</tests> From 03e03131100041789a2c58891d4e94b6a222addc Mon Sep 17 00:00:00 2001 From: Alex Kolesnyk <kolesnyk@adobe.com> Date: Mon, 24 Jun 2019 13:12:00 -0500 Subject: [PATCH 511/773] Test improvements: - removed duplicate action groups - added test case id - updated annotations - issue magento/magento-functional-tests-migration/381 - pull request magento/magento-functional-tests-migration/699 --- ...ssertAdminLoginErrorMessageActionGroup.xml | 20 ------- .../AssertMessageOnAdminActionGroup.xml | 18 ------ .../AdminFillIntegrationFormActionGroup.xml | 25 ++++++++ ...llIntegrationRequiredFieldsActionGroup.xml | 19 ------ .../AdminSaveIntegrationActionGroup.xml | 4 +- .../Test/Mftf/Data/IntegrationData.xml | 6 +- .../Mftf/Page/AdminNewIntegrationPage.xml | 2 +- ...xml => AdminNewIntegrationFormSection.xml} | 8 ++- ...dminUserWhenCreatingNewIntegrationTest.xml | 60 +++++++++++++------ 9 files changed, 80 insertions(+), 82 deletions(-) delete mode 100644 app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertAdminLoginErrorMessageActionGroup.xml delete mode 100644 app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertMessageOnAdminActionGroup.xml create mode 100644 app/code/Magento/Integration/Test/Mftf/ActionGroup/AdminFillIntegrationFormActionGroup.xml delete mode 100644 app/code/Magento/Integration/Test/Mftf/ActionGroup/AdminFillIntegrationRequiredFieldsActionGroup.xml rename app/code/Magento/Integration/Test/Mftf/Section/{AdminNewIntegrationSection.xml => AdminNewIntegrationFormSection.xml} (50%) diff --git a/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertAdminLoginErrorMessageActionGroup.xml b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertAdminLoginErrorMessageActionGroup.xml deleted file mode 100644 index 6ad3b7cfb9121..0000000000000 --- a/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertAdminLoginErrorMessageActionGroup.xml +++ /dev/null @@ -1,20 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> - -<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="AssertAdminLoginErrorMessageActionGroup"> - <arguments> - <argument name="message" type="string" defaultValue="The account sign-in was incorrect or your account is disabled temporarily. Please wait and try again later"/> - <argument name="messageType" type="string" defaultValue="error" /> - </arguments> - <waitForPageLoad stepKey="waitForPageReload"/> - <see selector="{{AdminLoginMessagesSection.messageByType(messageType)}}" userInput="{{message}}" - stepKey="seeLoginAdminError"/> - </actionGroup> -</actionGroups> diff --git a/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertMessageOnAdminActionGroup.xml b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertMessageOnAdminActionGroup.xml deleted file mode 100644 index 414a9b56b8b0e..0000000000000 --- a/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertMessageOnAdminActionGroup.xml +++ /dev/null @@ -1,18 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> - -<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="AssertMessageOnAdminActionGroup"> - <arguments> - <argument name="message" type="string" defaultValue="The password entered for the current user is invalid. Verify the password and try again." /> - <argument name="messageType" type="string" defaultValue="error" /> - </arguments> - <see userInput="{{message}}" selector="{{AdminMessagesSection.messageByType(messageType)}}" stepKey="verifyMessage" /> - </actionGroup> -</actionGroups> diff --git a/app/code/Magento/Integration/Test/Mftf/ActionGroup/AdminFillIntegrationFormActionGroup.xml b/app/code/Magento/Integration/Test/Mftf/ActionGroup/AdminFillIntegrationFormActionGroup.xml new file mode 100644 index 0000000000000..85e4efb495955 --- /dev/null +++ b/app/code/Magento/Integration/Test/Mftf/ActionGroup/AdminFillIntegrationFormActionGroup.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminFillIntegrationFormActionGroup"> + <arguments> + <argument name="integration" type="entity" /> + <argument name="currentAdminPassword" type="string" defaultValue="{{_ENV.MAGENTO_ADMIN_PASSWORD}}" /> + </arguments> + + <fillField selector="{{AdminNewIntegrationFormSection.integrationName}}" userInput="{{integration.name}}" stepKey="fillIntegrationName"/> + <fillField selector="{{AdminNewIntegrationFormSection.currentPassword}}" userInput="{{currentAdminPassword}}" stepKey="fillCurrentUserPassword"/> + + <click selector="{{AdminNewIntegrationFormSection.apiTab}}" stepKey="clickToOpenApiTab"/> + <waitForPageLoad stepKey="waitForApiTab" /> + + <selectOption userInput="{{integration.resourceAccess}}" selector="{{AdminNewIntegrationFormSection.resourceAccess}}" stepKey="selectResourceAccess" /> + <performOn stepKey="checkNeededResources" selector="{{AdminNewIntegrationFormSection.resourceTree}}" function="function($I,$apiResources={{integration.resources}}){foreach($apiResources as $apiResource){$I->conditionalClick('//li[@data-id=\'' . $apiResource . '\']//*[@class=\'jstree-checkbox\']','//li[@data-id=\'' . $apiResource . '\' and contains(@class, \'jstree-checked\')]',false);}}" /> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Integration/Test/Mftf/ActionGroup/AdminFillIntegrationRequiredFieldsActionGroup.xml b/app/code/Magento/Integration/Test/Mftf/ActionGroup/AdminFillIntegrationRequiredFieldsActionGroup.xml deleted file mode 100644 index d1dc2996ee2e4..0000000000000 --- a/app/code/Magento/Integration/Test/Mftf/ActionGroup/AdminFillIntegrationRequiredFieldsActionGroup.xml +++ /dev/null @@ -1,19 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="AdminFillIntegrationRequiredFieldsActionGroup"> - <arguments> - <argument name="integrationName" type="string" defaultValue="{{IntegrationData.name}}"/> - <argument name="currentAdminPassword" type="string" defaultValue="{{_ENV.MAGENTO_ADMIN_PASSWORD}}" /> - </arguments> - <fillField selector="{{AdminNewIntegrationSection.integrationName}}" userInput="{{integrationName}}" stepKey="fillIntegrationName"/> - <fillField selector="{{AdminNewIntegrationSection.currentPassword}}" userInput="{{currentAdminPassword}}" stepKey="fillCurrentUserPassword"/> - <scrollToTopOfPage stepKey="ScrollToTopOfPage"/> - </actionGroup> -</actionGroups> diff --git a/app/code/Magento/Integration/Test/Mftf/ActionGroup/AdminSaveIntegrationActionGroup.xml b/app/code/Magento/Integration/Test/Mftf/ActionGroup/AdminSaveIntegrationActionGroup.xml index 5169fd9476362..e6e3f3397d4b6 100644 --- a/app/code/Magento/Integration/Test/Mftf/ActionGroup/AdminSaveIntegrationActionGroup.xml +++ b/app/code/Magento/Integration/Test/Mftf/ActionGroup/AdminSaveIntegrationActionGroup.xml @@ -7,8 +7,8 @@ --> <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="AdminSaveIntegrationActionGroup"> - <click selector="{{AdminNewIntegrationSection.save}}" stepKey="saveIntegration"/> + <actionGroup name="AdminClickSaveButtonIntegrationFormActionGroup"> + <click selector="{{AdminNewIntegrationFormSection.save}}" stepKey="saveIntegration"/> <waitForPageLoad stepKey="waitForSaveResultLoad"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/Integration/Test/Mftf/Data/IntegrationData.xml b/app/code/Magento/Integration/Test/Mftf/Data/IntegrationData.xml index 3e7b6c49e2bc5..21fefcdf0b26c 100644 --- a/app/code/Magento/Integration/Test/Mftf/Data/IntegrationData.xml +++ b/app/code/Magento/Integration/Test/Mftf/Data/IntegrationData.xml @@ -8,7 +8,9 @@ <entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd"> - <entity name="IntegrationData" type="admin"> - <data key="name" unique="prefix">_Integration</data> + <entity name="defaultIntegrationData"> + <data key="name" unique="prefix"> Integration</data> + <data key="resourceAccess">All</data> + <data key="resources">[]</data> </entity> </entities> diff --git a/app/code/Magento/Integration/Test/Mftf/Page/AdminNewIntegrationPage.xml b/app/code/Magento/Integration/Test/Mftf/Page/AdminNewIntegrationPage.xml index 7b46029aa1eec..a3511887b2cdf 100644 --- a/app/code/Magento/Integration/Test/Mftf/Page/AdminNewIntegrationPage.xml +++ b/app/code/Magento/Integration/Test/Mftf/Page/AdminNewIntegrationPage.xml @@ -9,6 +9,6 @@ <pages xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/PageObject.xsd"> <page name="AdminNewIntegrationPage" url="admin/integration/new/" area="admin" module="Magento_Integration"> - <section name="AdminNewIntegrationSection"/> + <section name="AdminNewIntegrationFormSection"/> </page> </pages> diff --git a/app/code/Magento/Integration/Test/Mftf/Section/AdminNewIntegrationSection.xml b/app/code/Magento/Integration/Test/Mftf/Section/AdminNewIntegrationFormSection.xml similarity index 50% rename from app/code/Magento/Integration/Test/Mftf/Section/AdminNewIntegrationSection.xml rename to app/code/Magento/Integration/Test/Mftf/Section/AdminNewIntegrationFormSection.xml index 89588f7775098..edb9e5dd5eb51 100644 --- a/app/code/Magento/Integration/Test/Mftf/Section/AdminNewIntegrationSection.xml +++ b/app/code/Magento/Integration/Test/Mftf/Section/AdminNewIntegrationFormSection.xml @@ -8,9 +8,15 @@ <sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> - <section name="AdminNewIntegrationSection"> + <section name="AdminNewIntegrationFormSection"> + <element name="integrationInfoTab" type="block" selector="#integration_edit_tabs #integration_edit_tabs_info_section" /> <element name="integrationName" type="input" selector="#edit_form input[name='name']"/> <element name="currentPassword" type="input" selector="#edit_form input[name='current_password']"/> + + <element name="apiTab" type="block" selector="#integration_edit_tabs #integration_edit_tabs_api_section" /> + <element name="resourceAccess" type="select" selector="[data-ui-id='integration-edit-tabs-tab-content-api-section'] [name='all_resources']" /> + <element name="resourceTree" type="block" selector="[data-ui-id='integration-edit-tabs-tab-content-api-section'] [data-role='resource-tree']"/> + <element name="save" type="button" selector="#save-split-button-button"/> </section> </sections> diff --git a/app/code/Magento/Security/Test/Mftf/Test/AdminLockAdminUserWhenCreatingNewIntegrationTest.xml b/app/code/Magento/Security/Test/Mftf/Test/AdminLockAdminUserWhenCreatingNewIntegrationTest.xml index ce101c09dfeeb..03681a1753288 100644 --- a/app/code/Magento/Security/Test/Mftf/Test/AdminLockAdminUserWhenCreatingNewIntegrationTest.xml +++ b/app/code/Magento/Security/Test/Mftf/Test/AdminLockAdminUserWhenCreatingNewIntegrationTest.xml @@ -15,6 +15,7 @@ <title value="Lock admin user when creating new integration"/> <description value="Runs Lock admin user when creating new integration test."/> <severity value="MAJOR"/> + <testCaseId value="MC-14382" /> <group value="security"/> <group value="mtf_migrated"/> </annotations> @@ -30,47 +31,68 @@ <actionGroup ref="AdminOpenNewIntegrationPageActionGroup" stepKey="openNewIntegrationPage"/> <!-- Perform add new admin user 6 specified number of times. "The password entered for the current user is invalid. Verify the password and try again." appears after each attempt.--> - <actionGroup ref="AdminFillIntegrationRequiredFieldsActionGroup" stepKey="fillFieldFirstAttempt"> + <actionGroup ref="AdminFillIntegrationFormActionGroup" stepKey="fillFieldFirstAttempt"> + <argument name="integration" value="defaultIntegrationData" /> <argument name="currentAdminPassword" value="{{_ENV.MAGENTO_ADMIN_PASSWORD}}INVALID" /> </actionGroup> - <actionGroup ref="AdminSaveIntegrationActionGroup" stepKey="saveIntegrationFirstAttempt"/> - <actionGroup ref="AssertMessageOnAdminActionGroup" stepKey="checkFirstSaveIntegrationError"/> + <actionGroup ref="AdminClickSaveButtonIntegrationFormActionGroup" stepKey="saveIntegrationFirstAttempt"/> + <actionGroup ref="AssertMessageInAdminPanelActionGroup" stepKey="checkFirstSaveIntegrationError"> + <argument name="message" value="The password entered for the current user is invalid. Verify the password and try again." /> + <argument name="messageType" value="error" /> + </actionGroup> - <actionGroup ref="AdminFillIntegrationRequiredFieldsActionGroup" stepKey="fillFieldSecondAttempt"> + <actionGroup ref="AdminFillIntegrationFormActionGroup" stepKey="fillFieldSecondAttempt"> + <argument name="integration" value="defaultIntegrationData" /> <argument name="currentAdminPassword" value="{{_ENV.MAGENTO_ADMIN_PASSWORD}}INVALID" /> </actionGroup> - <actionGroup ref="AdminSaveIntegrationActionGroup" stepKey="saveIntegrationSecondAttempt"/> - <actionGroup ref="AssertMessageOnAdminActionGroup" stepKey="checkSecondSaveIntegrationError"/> + <actionGroup ref="AdminClickSaveButtonIntegrationFormActionGroup" stepKey="saveIntegrationSecondAttempt"/> + <actionGroup ref="AssertMessageInAdminPanelActionGroup" stepKey="checkSecondSaveIntegrationError"> + <argument name="message" value="The password entered for the current user is invalid. Verify the password and try again." /> + <argument name="messageType" value="error" /> + </actionGroup> - <actionGroup ref="AdminFillIntegrationRequiredFieldsActionGroup" stepKey="fillFieldThirdAttempt"> + <actionGroup ref="AdminFillIntegrationFormActionGroup" stepKey="fillFieldThirdAttempt"> + <argument name="integration" value="defaultIntegrationData" /> <argument name="currentAdminPassword" value="{{_ENV.MAGENTO_ADMIN_PASSWORD}}INVALID" /> </actionGroup> - <actionGroup ref="AdminSaveIntegrationActionGroup" stepKey="saveIntegrationThirdAttempt"/> - <actionGroup ref="AssertMessageOnAdminActionGroup" stepKey="checkThirdSaveIntegrationError"/> + <actionGroup ref="AdminClickSaveButtonIntegrationFormActionGroup" stepKey="saveIntegrationThirdAttempt"/> + <actionGroup ref="AssertMessageInAdminPanelActionGroup" stepKey="checkThirdSaveIntegrationError"> + <argument name="message" value="The password entered for the current user is invalid. Verify the password and try again." /> + <argument name="messageType" value="error" /> + </actionGroup> - <actionGroup ref="AdminFillIntegrationRequiredFieldsActionGroup" stepKey="fillFieldFourthAttempt"> + <actionGroup ref="AdminFillIntegrationFormActionGroup" stepKey="fillFieldFourthAttempt"> + <argument name="integration" value="defaultIntegrationData" /> <argument name="currentAdminPassword" value="{{_ENV.MAGENTO_ADMIN_PASSWORD}}INVALID" /> </actionGroup> - <actionGroup ref="AdminSaveIntegrationActionGroup" stepKey="saveIntegrationFourthAttempt"/> - <actionGroup ref="AssertMessageOnAdminActionGroup" stepKey="checkFourthSaveIntegrationError"/> + <actionGroup ref="AdminClickSaveButtonIntegrationFormActionGroup" stepKey="saveIntegrationFourthAttempt"/> + <actionGroup ref="AssertMessageInAdminPanelActionGroup" stepKey="checkFourthSaveIntegrationError"> + <argument name="message" value="The password entered for the current user is invalid. Verify the password and try again." /> + <argument name="messageType" value="error" /> + </actionGroup> - <actionGroup ref="AdminFillIntegrationRequiredFieldsActionGroup" stepKey="fillFieldFifthAttempt"> + <actionGroup ref="AdminFillIntegrationFormActionGroup" stepKey="fillFieldFifthAttempt"> + <argument name="integration" value="defaultIntegrationData" /> <argument name="currentAdminPassword" value="{{_ENV.MAGENTO_ADMIN_PASSWORD}}INVALID" /> </actionGroup> - <actionGroup ref="AdminSaveIntegrationActionGroup" stepKey="saveIntegrationFifthAttempt"/> - <actionGroup ref="AssertMessageOnAdminActionGroup" stepKey="checkFifthSaveIntegrationError"/> + <actionGroup ref="AdminClickSaveButtonIntegrationFormActionGroup" stepKey="saveIntegrationFifthAttempt"/> + <actionGroup ref="AssertMessageInAdminPanelActionGroup" stepKey="checkFifthSaveIntegrationError"> + <argument name="message" value="The password entered for the current user is invalid. Verify the password and try again." /> + <argument name="messageType" value="error" /> + </actionGroup> <!-- Last invalid current password save integration attempt and check logout error --> - <actionGroup ref="AdminFillIntegrationRequiredFieldsActionGroup" stepKey="fillFieldLastAttempt"> + <actionGroup ref="AdminFillIntegrationFormActionGroup" stepKey="fillFieldLastAttempt"> + <argument name="integration" value="defaultIntegrationData" /> <argument name="currentAdminPassword" value="{{_ENV.MAGENTO_ADMIN_PASSWORD}}INVALID" /> </actionGroup> - <actionGroup ref="AdminSaveIntegrationActionGroup" stepKey="saveIntegrationLastAttempt"/> - <actionGroup ref="AssertAdminLoginErrorMessageActionGroup" stepKey="checkFifthError"> + <actionGroup ref="AdminClickSaveButtonIntegrationFormActionGroup" stepKey="saveIntegrationLastAttempt"/> + <actionGroup ref="AssertMessageOnAdminLoginActionGroup" stepKey="checkFifthError"> <argument name="message" value="Your account is temporarily disabled. Please try again later."/> </actionGroup> <!-- Try to login as admin and check error --> <actionGroup ref="LoginAsAdmin" stepKey="loginAsLockedAdmin"/> - <actionGroup ref="AssertAdminLoginErrorMessageActionGroup" stepKey="checkLoginError"/> + <actionGroup ref="AssertMessageOnAdminLoginActionGroup" stepKey="checkLoginError" /> </test> </tests> From 8646b3128ab34c0486dbc7faa9bd60aab741e111 Mon Sep 17 00:00:00 2001 From: Alex Kolesnyk <kolesnyk@adobe.com> Date: Mon, 24 Jun 2019 13:39:32 -0500 Subject: [PATCH 512/773] MC-6436: Configuring Instant Purchase functionality --- .../Test/Mftf/Data/BraintreeData.xml | 44 ++++++++++++++++++- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Braintree/Test/Mftf/Data/BraintreeData.xml b/app/code/Magento/Braintree/Test/Mftf/Data/BraintreeData.xml index 2bedb6509344b..f95ba2eb590dc 100644 --- a/app/code/Magento/Braintree/Test/Mftf/Data/BraintreeData.xml +++ b/app/code/Magento/Braintree/Test/Mftf/Data/BraintreeData.xml @@ -6,8 +6,7 @@ */ --> -<entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd"> +<entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd"> <entity name="SampleBraintreeConfig" type="braintree_config_state"> <requiredEntity type="title">SampleTitle</requiredEntity> <requiredEntity type="payment_action">SamplePaymentAction</requiredEntity> @@ -35,6 +34,34 @@ <data key="value">somePrivateKey</data> </entity> + <entity name="BraintreeConfig" type="braintree_config_state"> + <requiredEntity type="title">BraintreeTitle</requiredEntity> + <requiredEntity type="payment_action">PaymentAction</requiredEntity> + <requiredEntity type="environment">Environment</requiredEntity> + <requiredEntity type="merchant_id">MerchantId</requiredEntity> + <requiredEntity type="public_key">PublicKey</requiredEntity> + <requiredEntity type="private_key">PrivateKey</requiredEntity> + <requiredEntity type="active">Status</requiredEntity> + </entity> + <entity name="BraintreeTitle" type="title"> + <data key="value">Credit Card (Braintree)</data> + </entity> + <entity name="PaymentAction" type="payment_action"> + <data key="value">authorize</data> + </entity> + <entity name="Environment" type="environment"> + <data key="value">sandbox</data> + </entity> + <entity name="MerchantId" type="merchant_id"> + <data key="value">MERCH_ID</data> + </entity> + <entity name="PublicKey" type="public_key"> + <data key="value">PUBLIC_KEY</data> + </entity> + <entity name="PrivateKey" type="private_key"> + <data key="value">PRIVATE_KEY</data> + </entity> + <!-- default configuration used to restore Magento config --> <entity name="DefaultBraintreeConfig" type="braintree_config_state"> <requiredEntity type="title">DefaultTitle</requiredEntity> @@ -110,4 +137,17 @@ <data key="year">20</data> <data key="cvv">113</data> </entity> + <entity name="StoredPaymentMethods"> + <data key="cardNumberEnding">5100</data> + <data key="cardExpire">12/2020</data> + </entity> + + <entity name="BraintreeConfigurationData" type="data"> + <data key="title">Credit Card (Braintree)</data> + <data key="merchantID">MERCH_ID</data> + <data key="publicKey">PUBLIC_KEY</data> + <data key="privateKey">PRIVATE_KEY</data> + <data key="merchantAccountID">MERCH_ACCOUNT_ID</data> + <data key="titleForPayPalThroughBraintree">PayPal (Braintree)</data> + </entity> </entities> From f7ee0cc4e333d84e7f683691a52dc73d3a4376e6 Mon Sep 17 00:00:00 2001 From: Bunyamin <bunyamin@webjump.com.br> Date: Mon, 24 Jun 2019 16:20:51 -0300 Subject: [PATCH 513/773] The default value of the new parameter set to null --- .../Magento/Setup/Validator/AdminCredentialsValidator.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/setup/src/Magento/Setup/Validator/AdminCredentialsValidator.php b/setup/src/Magento/Setup/Validator/AdminCredentialsValidator.php index 941adf12825e4..23e41df900d4f 100644 --- a/setup/src/Magento/Setup/Validator/AdminCredentialsValidator.php +++ b/setup/src/Magento/Setup/Validator/AdminCredentialsValidator.php @@ -5,6 +5,7 @@ */ namespace Magento\Setup\Validator; +use Magento\Framework\App\ObjectManager; use Magento\Framework\Config\ConfigOptionsListConstants as ConfigOption; use Magento\Setup\Model\AdminAccount; use Magento\Setup\Model\Installer; @@ -47,12 +48,12 @@ public function __construct( \Magento\Setup\Model\AdminAccountFactory $adminAccountFactory, \Magento\Setup\Module\ConnectionFactory $connectionFactory, \Magento\Setup\Module\SetupFactory $setupFactory, - DriverOptions $driverOptions + DriverOptions $driverOptions = null ) { $this->connectionFactory = $connectionFactory; $this->adminAccountFactory = $adminAccountFactory; $this->setupFactory = $setupFactory; - $this->driverOptions = $driverOptions; + $this->driverOptions = $driverOptions ?? ObjectManager::getInstance()->get(DriverOptions::class); } /** From c4cc9523a34b561d6768eb00b23800c5888d8a1e Mon Sep 17 00:00:00 2001 From: Bunyamin <bunyamin@webjump.com.br> Date: Mon, 24 Jun 2019 16:24:45 -0300 Subject: [PATCH 514/773] .htacces removal reverted --- vendor/.htaccess | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 vendor/.htaccess diff --git a/vendor/.htaccess b/vendor/.htaccess new file mode 100644 index 0000000000000..8438447812bfe --- /dev/null +++ b/vendor/.htaccess @@ -0,0 +1,7 @@ +<IfVersion < 2.4> + order allow,deny + deny from all +</IfVersion> +<IfVersion >= 2.4> + Require all denied +</IfVersion> \ No newline at end of file From 26980d84167f6f1c282c9dbf45554215e592ae30 Mon Sep 17 00:00:00 2001 From: Bunyamin <bunyamin@webjump.com.br> Date: Mon, 24 Jun 2019 16:26:00 -0300 Subject: [PATCH 515/773] New line added to the EOF .htaccess --- vendor/.htaccess | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/.htaccess b/vendor/.htaccess index 8438447812bfe..b97408bad3f2e 100644 --- a/vendor/.htaccess +++ b/vendor/.htaccess @@ -4,4 +4,4 @@ </IfVersion> <IfVersion >= 2.4> Require all denied -</IfVersion> \ No newline at end of file +</IfVersion> From 9852b08e18f1128a081fd2b366e75e15355988f8 Mon Sep 17 00:00:00 2001 From: swnsma <swnsma@gmail.com> Date: Tue, 9 Jan 2018 11:34:43 +0200 Subject: [PATCH 516/773] magento/magento2#23386: Copy Service does not works properly for Entities which extends Data Object and implements ExtensibleDataInterface. Provide fallback to copy Extension Attributes for classes which extends Data Object. --- .../Magento/Framework/DataObject/Copy.php | 257 ++++++++++++------ 1 file changed, 170 insertions(+), 87 deletions(-) diff --git a/lib/internal/Magento/Framework/DataObject/Copy.php b/lib/internal/Magento/Framework/DataObject/Copy.php index 8d8896c6cb62a..387e7da046520 100644 --- a/lib/internal/Magento/Framework/DataObject/Copy.php +++ b/lib/internal/Magento/Framework/DataObject/Copy.php @@ -3,40 +3,48 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); namespace Magento\Framework\DataObject; +use Magento\Framework\Api\AbstractSimpleObject; +use Magento\Framework\Api\ExtensibleDataInterface; +use Magento\Framework\Api\ExtensionAttributesFactory; +use Magento\Framework\DataObject; +use Magento\Framework\DataObject\Copy\Config; +use Magento\Framework\Event\ManagerInterface; + /** * Utility class for copying data sets between objects */ class Copy { /** - * @var \Magento\Framework\DataObject\Copy\Config + * @var Config */ protected $fieldsetConfig; /** * Core event manager proxy * - * @var \Magento\Framework\Event\ManagerInterface + * @var ManagerInterface */ protected $eventManager = null; /** - * @var \Magento\Framework\Api\ExtensionAttributesFactory + * @var ExtensionAttributesFactory */ protected $extensionAttributesFactory; /** - * @param \Magento\Framework\Event\ManagerInterface $eventManager - * @param \Magento\Framework\DataObject\Copy\Config $fieldsetConfig - * @param \Magento\Framework\Api\ExtensionAttributesFactory $extensionAttributesFactory + * @param ManagerInterface $eventManager + * @param Config $fieldsetConfig + * @param ExtensionAttributesFactory $extensionAttributesFactory */ public function __construct( - \Magento\Framework\Event\ManagerInterface $eventManager, - \Magento\Framework\DataObject\Copy\Config $fieldsetConfig, - \Magento\Framework\Api\ExtensionAttributesFactory $extensionAttributesFactory + ManagerInterface $eventManager, + Config $fieldsetConfig, + ExtensionAttributesFactory $extensionAttributesFactory ) { $this->eventManager = $eventManager; $this->fieldsetConfig = $fieldsetConfig; @@ -51,10 +59,11 @@ public function __construct( * * @param string $fieldset * @param string $aspect - * @param array|\Magento\Framework\DataObject $source - * @param array|\Magento\Framework\DataObject $target + * @param array|DataObject $source + * @param array|DataObject $target * @param string $root - * @return array|\Magento\Framework\DataObject|null the value of $target + * + * @return array|DataObject|null the value of $target * @throws \InvalidArgumentException * * @api @@ -93,17 +102,18 @@ public function copyFieldsetToTarget($fieldset, $aspect, $source, $target, $root * * @param string $fieldset * @param string $aspect - * @param array|\Magento\Framework\DataObject $source - * @param array|\Magento\Framework\DataObject $target + * @param array|DataObject $source + * @param array|DataObject $target * @param string $root * @param bool $targetIsArray - * @return \Magento\Framework\DataObject|mixed + * + * @return DataObject|mixed */ protected function dispatchCopyFieldSetEvent($fieldset, $aspect, $source, $target, $root, $targetIsArray) { $eventName = sprintf('core_copy_fieldset_%s_%s', $fieldset, $aspect); if ($targetIsArray) { - $target = new \Magento\Framework\DataObject($target); + $target = new DataObject($target); } $this->eventManager->dispatch( $eventName, @@ -120,17 +130,19 @@ protected function dispatchCopyFieldSetEvent($fieldset, $aspect, $source, $targe * * @param string $fieldset * @param string $aspect a field name - * @param array|\Magento\Framework\DataObject $source + * @param array|DataObject $source * @param string $root + * * @return array * * @api */ public function getDataFromFieldset($fieldset, $aspect, $source, $root = 'global') { - if (!(is_array($source) || $source instanceof \Magento\Framework\DataObject)) { + if ((!$this->isInputArgumentValid($source))) { return null; } + $fields = $this->fieldsetConfig->getFieldset($fieldset, $root); if ($fields === null) { return null; @@ -155,18 +167,28 @@ public function getDataFromFieldset($fieldset, $aspect, $source, $root = 'global /** * Check if source and target are valid input for converting using fieldset * - * @param array|\Magento\Framework\DataObject $source - * @param array|\Magento\Framework\DataObject $target + * @param array|DataObject $source + * @param array|DataObject $target + * * @return bool */ protected function _isFieldsetInputValid($source, $target) { - return (is_array($source) || $source instanceof \Magento\Framework\DataObject || - $source instanceof \Magento\Framework\Api\ExtensibleDataInterface || - $source instanceof \Magento\Framework\Api\AbstractSimpleObject) && ( - is_array($target) || $target instanceof \Magento\Framework\DataObject || - $target instanceof \Magento\Framework\Api\ExtensibleDataInterface || - $target instanceof \Magento\Framework\Api\AbstractSimpleObject); + return $this->isInputArgumentValid($source) && $this->isInputArgumentValid($target); + } + + /** + * Verify that we can access data from input object. + * + * @param $object + * + * @return bool + */ + private function isInputArgumentValid($object): bool + { + return (is_array($object) || $object instanceof DataObject || + $object instanceof ExtensibleDataInterface || + $object instanceof AbstractSimpleObject); } /** @@ -180,20 +202,27 @@ protected function _isFieldsetInputValid($source, $target) */ protected function _getFieldsetFieldValue($source, $code) { - if (is_array($source)) { - $value = isset($source[$code]) ? $source[$code] : null; - } elseif ($source instanceof \Magento\Framework\DataObject) { - $value = $source->getDataUsingMethod($code); - } elseif ($source instanceof \Magento\Framework\Api\ExtensibleDataInterface) { - $value = $this->getAttributeValueFromExtensibleDataObject($source, $code); - } elseif ($source instanceof \Magento\Framework\Api\AbstractSimpleObject) { - $sourceArray = $source->__toArray(); - $value = isset($sourceArray[$code]) ? $sourceArray[$code] : null; - } else { - throw new \InvalidArgumentException( - 'Source should be array, Magento Object, ExtensibleDataInterface, or AbstractSimpleObject' - ); + + switch (true) { + case is_array($source): + $value = isset($source[$code]) ? $source[$code] : null; + break; + case $source instanceof ExtensibleDataInterface: + $value = $this->getAttributeValueFromExtensibleObject($source, $code); + break; + case $source instanceof DataObject: + $value = $source->getDataUsingMethod($code); + break; + case $source instanceof AbstractSimpleObject: + $sourceArray = $source->__toArray(); + $value = isset($sourceArray[$code]) ? $sourceArray[$code] : null; + break; + default: + throw new \InvalidArgumentException( + 'Source should be array, Magento Object, ExtensibleDataInterface, or AbstractSimpleObject' + ); } + return $value; } @@ -209,20 +238,23 @@ protected function _getFieldsetFieldValue($source, $code) */ protected function _setFieldsetFieldValue($target, $targetCode, $value) { - $targetIsArray = is_array($target); - - if ($targetIsArray) { - $target[$targetCode] = $value; - } elseif ($target instanceof \Magento\Framework\DataObject) { - $target->setDataUsingMethod($targetCode, $value); - } elseif ($target instanceof \Magento\Framework\Api\ExtensibleDataInterface) { - $this->setAttributeValueFromExtensibleDataObject($target, $targetCode, $value); - } elseif ($target instanceof \Magento\Framework\Api\AbstractSimpleObject) { - $target->setData($targetCode, $value); - } else { - throw new \InvalidArgumentException( - 'Source should be array, Magento Object, ExtensibleDataInterface, or AbstractSimpleObject' - ); + switch (true) { + case is_array($target): + $target[$targetCode] = $value; + break; + case $target instanceof ExtensibleDataInterface: + $this->setAttributeValueFromExtensibleObject($target, $targetCode, $value); + break; + case $target instanceof DataObject: + $target->setDataUsingMethod($targetCode, $value); + break; + case $target instanceof AbstractSimpleObject: + $target->setData($targetCode, $value); + break; + default: + throw new \InvalidArgumentException( + 'Source should be array, Magento Object, ExtensibleDataInterface, or AbstractSimpleObject' + ); } return $target; @@ -231,68 +263,119 @@ protected function _setFieldsetFieldValue($target, $targetCode, $value) /** * Access the extension get method * - * @param \Magento\Framework\Api\ExtensibleDataInterface $source + * @param ExtensibleDataInterface $source * @param string $code * * @return mixed * @throws \InvalidArgumentException + * + * @deprecated + * @see \Magento\Framework\DataObject\Copy::getAttributeValueFromExtensibleObject */ protected function getAttributeValueFromExtensibleDataObject($source, $code) + { + return $this->getAttributeValueFromExtensibleObject($source, $code); + } + + /** + * Get Attribute Value from Extensible Object Data with fallback to DataObject or AbstractSimpleObject. + * + * @param ExtensibleDataInterface $source + * @param string $code + * + * @return mixed|null + */ + private function getAttributeValueFromExtensibleObject(ExtensibleDataInterface $source, string $code) { $method = 'get' . str_replace(' ', '', ucwords(str_replace('_', ' ', $code))); $methodExists = method_exists($source, $method); - if ($methodExists == true) { - $value = $source->{$method}(); - } else { - // If we couldn't find the method, check if we can get it from the extension attributes - $extensionAttributes = $source->getExtensionAttributes(); - if ($extensionAttributes == null) { - throw new \InvalidArgumentException('Method in extension does not exist.'); - } else { - $extensionMethodExists = method_exists($extensionAttributes, $method); - if ($extensionMethodExists == true) { - $value = $extensionAttributes->{$method}(); - } else { - throw new \InvalidArgumentException('Attribute in object does not exist.'); - } + + if ($methodExists === true) { + return $source->{$method}(); + } + + $extensionAttributes = $source->getExtensionAttributes(); + + if ($extensionAttributes) { + $methodExists = method_exists($extensionAttributes, $method); + if ($methodExists) { + return $extensionAttributes->{$method}(); } } - return $value; + + if ($source instanceof DataObject) { + return $source->getDataUsingMethod($code); + } + + if ($source instanceof AbstractSimpleObject) { + $sourceArray = $source->__toArray(); + return isset($sourceArray[$code]) ? $sourceArray[$code] : null; + } + + throw new \InvalidArgumentException('Attribute in object does not exist.'); } /** * Access the extension set method * - * @param \Magento\Framework\Api\ExtensibleDataInterface $target + * @param ExtensibleDataInterface $target * @param string $code * @param mixed $value * - * @return null + * @return void + * @throws \InvalidArgumentException + * + * @deprecated + * @see \Magento\Framework\DataObject\Copy::setAttributeValueFromExtensibleObject + */ + protected function setAttributeValueFromExtensibleDataObject(ExtensibleDataInterface $target, $code, $value) + { + $this->setAttributeValueFromExtensibleObject($target, $code, $value); + } + + /** + * Set Attribute Value for Extensible Object Data with fallback to DataObject or AbstractSimpleObject. + * + * @param ExtensibleDataInterface $target + * @param string $code + * @param $value + * + * @return void * @throws \InvalidArgumentException */ - protected function setAttributeValueFromExtensibleDataObject($target, $code, $value) + private function setAttributeValueFromExtensibleObject(ExtensibleDataInterface $target, string $code, $value): void { $method = 'set' . str_replace(' ', '', ucwords(str_replace('_', ' ', $code))); $methodExists = method_exists($target, $method); - if ($methodExists == true) { + if ($methodExists) { $target->{$method}($value); - } else { - // If we couldn't find the method, check if we can set it from the extension attributes - $extensionAttributes = $target->getExtensionAttributes(); - if ($extensionAttributes == null) { - $extensionAttributes = $this->extensionAttributesFactory->create(get_class($target)); - } - $extensionMethodExists = method_exists($extensionAttributes, $method); - if ($extensionMethodExists == true) { - $extensionAttributes->{$method}($value); - $target->setExtensionAttributes($extensionAttributes); - } else { - throw new \InvalidArgumentException('Attribute in object does not exist.'); - } + return; + } + + $extensionAttributes = $target->getExtensionAttributes(); + if ($extensionAttributes === null) { + $extensionAttributes = $this->extensionAttributesFactory->create(get_class($target)); + } + + if (method_exists($extensionAttributes, $method)) { + $extensionAttributes->{$method}($value); + $target->setExtensionAttributes($extensionAttributes); + return; + } + + + if ($target instanceof DataObject) { + $target->setDataUsingMethod($code, $value); + return; + } + + if ($target instanceof AbstractSimpleObject) { + $target->setData($code, $value); + return; } - return null; + throw new \InvalidArgumentException('Attribute in object does not exist.'); } } From 32cb5054881b44e802de65f5836b316ab2a138e3 Mon Sep 17 00:00:00 2001 From: Alex Kolesnyk <kolesnyk@adobe.com> Date: Mon, 24 Jun 2019 15:27:03 -0500 Subject: [PATCH 517/773] MC-6436: Configuring Instant Purchase functionality - skip test requiring sandbox account --- ...etateAdminOrderWithOnlinePaymentIncludingTaxAndDiscount.xml | 3 +++ .../Test/Mftf/Page/AdminSystemConfigInstantPurchasePage.xml | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Braintree/Test/Mftf/Test/CretateAdminOrderWithOnlinePaymentIncludingTaxAndDiscount.xml b/app/code/Magento/Braintree/Test/Mftf/Test/CretateAdminOrderWithOnlinePaymentIncludingTaxAndDiscount.xml index cf51f29db79f9..8f0ce4918b978 100644 --- a/app/code/Magento/Braintree/Test/Mftf/Test/CretateAdminOrderWithOnlinePaymentIncludingTaxAndDiscount.xml +++ b/app/code/Magento/Braintree/Test/Mftf/Test/CretateAdminOrderWithOnlinePaymentIncludingTaxAndDiscount.xml @@ -17,6 +17,9 @@ <severity value="CRITICAL"/> <testCaseId value="MAGETWO-94472"/> <group value="braintree"/> + <skip> + <issueId value="MQE-1576"/> + </skip> </annotations> <before> diff --git a/app/code/Magento/InstantPurchase/Test/Mftf/Page/AdminSystemConfigInstantPurchasePage.xml b/app/code/Magento/InstantPurchase/Test/Mftf/Page/AdminSystemConfigInstantPurchasePage.xml index 669172c6c4bbe..ed69e3032e04d 100644 --- a/app/code/Magento/InstantPurchase/Test/Mftf/Page/AdminSystemConfigInstantPurchasePage.xml +++ b/app/code/Magento/InstantPurchase/Test/Mftf/Page/AdminSystemConfigInstantPurchasePage.xml @@ -8,6 +8,6 @@ <pages xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/PageObject.xsd"> - <page name="AdminSystemConfigInstantPurchasePage" url="admin/system_config/edit/section/sales/#sales_instant_purchase-head" area="admin" module="Magento_GiftWrapping"> + <page name="AdminSystemConfigInstantPurchasePage" url="admin/system_config/edit/section/sales/#sales_instant_purchase-head" area="admin" module="Magento_InstantPurchase"> </page> </pages> From 1e8dc58cbf1fdd9d4ae235f678973791841b2252 Mon Sep 17 00:00:00 2001 From: Aliaksei_Manenak <Aliaksei_Manenak@epam.com> Date: Mon, 24 Jun 2019 17:40:54 +0300 Subject: [PATCH 518/773] MAGETWO-92712: Sorting does not work for \Magento\Catalog\Model\CategoryList::getList - Use collection->getData() to get right id order --- .../Magento/Catalog/Model/CategoryList.php | 12 ++++++---- .../Test/Unit/Model/CategoryListTest.php | 18 ++++++++++----- .../Magento/Catalog/Api/CategoryListTest.php | 22 +++++++++++-------- 3 files changed, 34 insertions(+), 18 deletions(-) diff --git a/app/code/Magento/Catalog/Model/CategoryList.php b/app/code/Magento/Catalog/Model/CategoryList.php index cab8e013d9ba1..cc8920203526f 100644 --- a/app/code/Magento/Catalog/Model/CategoryList.php +++ b/app/code/Magento/Catalog/Model/CategoryList.php @@ -3,6 +3,9 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + +declare(strict_types=1); + namespace Magento\Catalog\Model; use Magento\Catalog\Api\CategoryListInterface; @@ -50,7 +53,7 @@ class CategoryList implements CategoryListInterface * @param JoinProcessorInterface $extensionAttributesJoinProcessor * @param CategorySearchResultsInterfaceFactory $categorySearchResultsFactory * @param CategoryRepositoryInterface $categoryRepository - * @param CollectionProcessorInterface $collectionProcessor + * @param CollectionProcessorInterface|null $collectionProcessor */ public function __construct( CollectionFactory $categoryCollectionFactory, @@ -74,12 +77,13 @@ public function getList(SearchCriteriaInterface $searchCriteria) /** @var Collection $collection */ $collection = $this->categoryCollectionFactory->create(); $this->extensionAttributesJoinProcessor->process($collection); - $this->collectionProcessor->process($searchCriteria, $collection); $items = []; - foreach ($collection->getAllIds() as $id) { - $items[] = $this->categoryRepository->get($id); + foreach ($collection->getData() as $categoryData) { + $items[] = $this->categoryRepository->get( + $categoryData[$collection->getEntity()->getIdFieldName()] + ); } /** @var CategorySearchResultsInterface $searchResult */ diff --git a/app/code/Magento/Catalog/Test/Unit/Model/CategoryListTest.php b/app/code/Magento/Catalog/Test/Unit/Model/CategoryListTest.php index b8b76524099f4..c7821f06985bc 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/CategoryListTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/CategoryListTest.php @@ -3,6 +3,9 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + +declare(strict_types=1); + namespace Magento\Catalog\Test\Unit\Model; use Magento\Catalog\Api\CategoryRepositoryInterface; @@ -52,6 +55,9 @@ class CategoryListTest extends \PHPUnit\Framework\TestCase */ private $collectionProcessorMock; + /** + * @inheritdoc + */ protected function setUp() { $this->categoryCollectionFactory = $this->getMockBuilder(CollectionFactory::class) @@ -93,7 +99,12 @@ public function testGetList() $collection = $this->getMockBuilder(Collection::class)->disableOriginalConstructor()->getMock(); $collection->expects($this->once())->method('getSize')->willReturn($totalCount); - $collection->expects($this->once())->method('getAllIds')->willReturn([$categoryIdFirst, $categoryIdSecond]); + $collection->expects($this->once())->method('getData')->willReturn( + [['entity_id' => $categoryIdFirst], ['entity_id' => $categoryIdSecond]] + ); + $collection->expects($this->any())->method('getEntity')->willReturn( + new \Magento\Framework\DataObject(['id_field_name' => 'entity_id']) + ); $this->collectionProcessorMock->expects($this->once()) ->method('process') @@ -106,10 +117,7 @@ public function testGetList() $this->categoryRepository->expects($this->exactly(2)) ->method('get') - ->willReturnMap([ - [$categoryIdFirst, $categoryFirst], - [$categoryIdSecond, $categorySecond], - ]) + ->willReturnMap([[$categoryIdFirst, $categoryFirst], [$categoryIdSecond, $categorySecond]]) ->willReturn($categoryFirst); $this->categorySearchResultsFactory->expects($this->once())->method('create')->willReturn($searchResult); diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CategoryListTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CategoryListTest.php index 4160f83718908..d0cd93b3ccd95 100644 --- a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CategoryListTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CategoryListTest.php @@ -3,11 +3,17 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + +declare(strict_types=1); + namespace Magento\Catalog\Api; use Magento\Framework\Webapi\Rest\Request; use Magento\TestFramework\TestCase\WebapiAbstract; +/** + * Checks the categories/list api + */ class CategoryListTest extends WebapiAbstract { const RESOURCE_PATH = '/V1/categories/list'; @@ -35,14 +41,11 @@ public function testGetList() ], ], ], + ], + 'sort_orders' => [ [ - 'filters' => [ - [ - 'field' => 'level', - 'value' => 2, - 'condition_type' => 'eq', - ], - ], + 'field' => 'name', + 'direction' => 'DESC', ], ], 'current_page' => 1, @@ -69,9 +72,10 @@ public function testGetList() $this->assertEquals($searchCriteria['searchCriteria'], $response['search_criteria']); $this->assertTrue($response['total_count'] > 0); - $this->assertTrue(count($response['items']) > 0); + $this->assertTrue(count($response['items']) === 2); $this->assertNotNull($response['items'][0]['name']); - $this->assertEquals('Category 1', $response['items'][0]['name']); + $this->assertEquals('Category 1.1', $response['items'][0]['name']); + $this->assertEquals('Category 1', $response['items'][1]['name']); } } From 3a818b218434eb8dd4961a0a8b8b20013c593c14 Mon Sep 17 00:00:00 2001 From: Aliaksei Yakimovich2 <aliaksei_yakimovich2@epam.com> Date: Tue, 25 Jun 2019 14:26:37 +0300 Subject: [PATCH 519/773] MC-17218: php bin/magento catalog:image:resize error if image is missing - Fixed integration test; --- .../Console/Command/ImageResizeCommandTest.php | 7 ------- 1 file changed, 7 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/MediaStorage/Console/Command/ImageResizeCommandTest.php b/dev/tests/integration/testsuite/Magento/MediaStorage/Console/Command/ImageResizeCommandTest.php index 2647fcca03b8e..c766a175c4ef7 100644 --- a/dev/tests/integration/testsuite/Magento/MediaStorage/Console/Command/ImageResizeCommandTest.php +++ b/dev/tests/integration/testsuite/Magento/MediaStorage/Console/Command/ImageResizeCommandTest.php @@ -130,13 +130,6 @@ public function testExecuteWithZeroByteImage() $this->tester->execute([]); $this->assertContains('Wrong file', $this->tester->getDisplay()); - } - - /** - * @inheritDoc - */ - public function tearDown() - { $this->mediaDirectory->getDriver()->deleteFile($this->mediaDirectory->getAbsolutePath($this->fileName)); } } From 8ecec7ba720266bd2283acc69a3107a7ba64510b Mon Sep 17 00:00:00 2001 From: Viktor Petryk <victor.petryk@transoftgroup.com> Date: Tue, 25 Jun 2019 15:15:42 +0300 Subject: [PATCH 520/773] MC-17269: Date format grid is not based on the locale defined in the back-office --- .../Test/Mftf/ActionGroup/SetAdminAccountActionGroup.xml | 6 +++--- .../Backend/Test/Mftf/Section/AdminSystemAccountSection.xml | 2 +- app/code/Magento/Ui/Component/Listing/Columns/Date.php | 4 ++-- app/code/Magento/Ui/view/base/web/js/grid/columns/date.js | 1 + 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/Backend/Test/Mftf/ActionGroup/SetAdminAccountActionGroup.xml b/app/code/Magento/Backend/Test/Mftf/ActionGroup/SetAdminAccountActionGroup.xml index 9e5c0bb3f39bf..885f1d3f1ecda 100644 --- a/app/code/Magento/Backend/Test/Mftf/ActionGroup/SetAdminAccountActionGroup.xml +++ b/app/code/Magento/Backend/Test/Mftf/ActionGroup/SetAdminAccountActionGroup.xml @@ -14,11 +14,11 @@ </arguments> <!-- Navigate to admin System Account Page--> <amOnPage url="{{AdminSystemAccountPage.url}}" stepKey="openAdminSystemAccountPage" /> - <waitForPageLoad stepKey="loadAdminSystemAccountPage"/> - <!-- Change Admin locale to Français (France) / French (France) --> + <waitForElementVisible selector="{{AdminSystemAccountSection.interfaceLocale}}" stepKey="waitForInterfaceLocale"/> <selectOption userInput="{{InterfaceLocaleByValue}}" selector="{{AdminSystemAccountSection.interfaceLocale}}" stepKey="setInterfaceLocate"/> <fillField selector="{{AdminSystemAccountSection.currentPassword}}" userInput="{{_ENV.MAGENTO_ADMIN_PASSWORD}}" stepKey="fillPassword"/> - <click selector="{{AdminCustomerMainActionsSection.saveButton}}" stepKey="clickSave"/> + <click selector="{{AdminMainActionsSection.save}}" stepKey="clickSave"/> <waitForElement selector="{{AdminCustomerMessagesSection.successMessage}}" stepKey="waitSuccessMessage"/> + <see selector="{{AdminCustomerMessagesSection.successMessage}}" userInput="You saved the account." stepKey="seeSuccessMessage"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/Backend/Test/Mftf/Section/AdminSystemAccountSection.xml b/app/code/Magento/Backend/Test/Mftf/Section/AdminSystemAccountSection.xml index b9570ce945943..a78b381b6e712 100644 --- a/app/code/Magento/Backend/Test/Mftf/Section/AdminSystemAccountSection.xml +++ b/app/code/Magento/Backend/Test/Mftf/Section/AdminSystemAccountSection.xml @@ -9,7 +9,7 @@ <sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="AdminSystemAccountSection"> - <element name="interfaceLocale" type="text" selector="#interface_locale"/> + <element name="interfaceLocale" type="select" selector="#interface_locale"/> <element name="currentPassword" type="text" selector="#current_password"/> </section> </sections> diff --git a/app/code/Magento/Ui/Component/Listing/Columns/Date.php b/app/code/Magento/Ui/Component/Listing/Columns/Date.php index a9763491e481d..fb73c52bc345b 100644 --- a/app/code/Magento/Ui/Component/Listing/Columns/Date.php +++ b/app/code/Magento/Ui/Component/Listing/Columns/Date.php @@ -52,10 +52,10 @@ class Date extends Column * @param UiComponentFactory $uiComponentFactory * @param TimezoneInterface $timezone * @param BooleanUtils $booleanUtils - * @param ResolverInterface $localeResolver - * @param DataBundle $dataBundle * @param array $components * @param array $data + * @param ResolverInterface $localeResolver + * @param DataBundle $dataBundle */ public function __construct( ContextInterface $context, diff --git a/app/code/Magento/Ui/view/base/web/js/grid/columns/date.js b/app/code/Magento/Ui/view/base/web/js/grid/columns/date.js index 032a962d94477..13a1340feb029 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/columns/date.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/columns/date.js @@ -39,6 +39,7 @@ define([ */ getLabel: function (value, format) { var date; + if (this.storeLocale !== undefined) { moment.locale(this.storeLocale, utils.extend({}, this.calendarConfig)); } From a5ccfc5035f79ff15f9cc61f190ee9080d090dda Mon Sep 17 00:00:00 2001 From: Patrick McLain <pat@pmclain.com> Date: Mon, 24 Jun 2019 21:14:21 -0400 Subject: [PATCH 521/773] static test fixes --- .../TestModuleUsps/Model/MockAsyncClient.php | 12 +-- .../Model/MockResponseBodyLoader.php | 2 +- .../_files/mock_response_ca.xml | 76 ++++++------------- .../_files/mock_response_us.xml | 65 ++++++---------- .../Usps/SetUspsShippingMethodsOnCartTest.php | 2 + 5 files changed, 56 insertions(+), 101 deletions(-) diff --git a/dev/tests/api-functional/_files/Magento/TestModuleUsps/Model/MockAsyncClient.php b/dev/tests/api-functional/_files/Magento/TestModuleUsps/Model/MockAsyncClient.php index c5c23e8710005..bd64e02c57c9e 100644 --- a/dev/tests/api-functional/_files/Magento/TestModuleUsps/Model/MockAsyncClient.php +++ b/dev/tests/api-functional/_files/Magento/TestModuleUsps/Model/MockAsyncClient.php @@ -50,11 +50,13 @@ public function __construct( public function request(Request $request): HttpResponseDeferredInterface { return new MockDeferredResponse( - $this->responseFactory->create([ - 'statusCode' => 200, - 'headers' => [], - 'body' => $this->mockResponseBodyLoader->loadForRequest($request), - ]) + $this->responseFactory->create( + [ + 'statusCode' => 200, + 'headers' => [], + 'body' => $this->mockResponseBodyLoader->loadForRequest($request), + ] + ) ); } } diff --git a/dev/tests/api-functional/_files/Magento/TestModuleUsps/Model/MockResponseBodyLoader.php b/dev/tests/api-functional/_files/Magento/TestModuleUsps/Model/MockResponseBodyLoader.php index 63f64940a45fc..83704333da553 100644 --- a/dev/tests/api-functional/_files/Magento/TestModuleUsps/Model/MockResponseBodyLoader.php +++ b/dev/tests/api-functional/_files/Magento/TestModuleUsps/Model/MockResponseBodyLoader.php @@ -53,7 +53,7 @@ public function loadForRequest(Request $request): string $moduleDir = $this->moduleDirectory->getDir('Magento_TestModuleUsps'); $destination = 'us'; - if (strpos($request->getUrl(), 'IntlRateV2Request')) { + if (strpos($request->getUrl(), 'IntlRateV2Request') !== false) { $destination = 'ca'; } diff --git a/dev/tests/api-functional/_files/Magento/TestModuleUsps/_files/mock_response_ca.xml b/dev/tests/api-functional/_files/Magento/TestModuleUsps/_files/mock_response_ca.xml index 80b4f5048a957..e2ae700cf7b51 100644 --- a/dev/tests/api-functional/_files/Magento/TestModuleUsps/_files/mock_response_ca.xml +++ b/dev/tests/api-functional/_files/Magento/TestModuleUsps/_files/mock_response_ca.xml @@ -1,4 +1,10 @@ <?xml version="1.0" encoding="UTF-8"?> +<!-- +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> <IntlRateV2Response> <Package ID="0"> <Prohibitions>An issue of a publication in which more than 5 percent of its total advertising space is primarily @@ -205,8 +211,7 @@ </ExtraServices> <ValueOfContents>20.00</ValueOfContents> <SvcCommitments>Tue, Jul 02, 2019 Guaranteed</SvcCommitments> - <SvcDescription>Priority Mail Express International&lt;sup&gt;&#8482;&lt;/sup&gt; - </SvcDescription> + <SvcDescription>Priority Mail Express International&lt;sup&gt;&#8482;&lt;/sup&gt;</SvcDescription> <MaxDimensions>Max. length 42", max. length plus girth combined 79"</MaxDimensions> <MaxWeight>66</MaxWeight> <GuaranteeAvailability>07/02/2019</GuaranteeAvailability> @@ -234,9 +239,7 @@ </ExtraServices> <ValueOfContents>20.00</ValueOfContents> <SvcCommitments>Tue, Jul 02, 2019 Guaranteed</SvcCommitments> - <SvcDescription>Priority Mail Express International&lt;sup&gt;&#8482;&lt;/sup&gt; Flat - Rate Envelope - </SvcDescription> + <SvcDescription>Priority Mail Express International&lt;sup&gt;&#8482;&lt;/sup&gt; Flat Rate Envelope</SvcDescription> <MaxDimensions>USPS-Produced Envelope: 12-1/2" x 9-1/2"<br>Maximum weight 4 pounds.</MaxDimensions> <MaxWeight>4</MaxWeight> <GuaranteeAvailability>07/02/2019</GuaranteeAvailability> @@ -264,9 +267,7 @@ </ExtraServices> <ValueOfContents>20.00</ValueOfContents> <SvcCommitments>Tue, Jul 02, 2019 Guaranteed</SvcCommitments> - <SvcDescription>Priority Mail Express International&lt;sup&gt;&#8482;&lt;/sup&gt; Legal - Flat Rate Envelope - </SvcDescription> + <SvcDescription>Priority Mail Express International&lt;sup&gt;&#8482;&lt;/sup&gt; Legal Flat Rate Envelope</SvcDescription> <MaxDimensions>USPS-Produced Envelope: 15" x 9-1/2"<br>Maximum weight 4 pounds.</MaxDimensions> <MaxWeight>4</MaxWeight> <GuaranteeAvailability>07/02/2019</GuaranteeAvailability> @@ -294,9 +295,7 @@ </ExtraServices> <ValueOfContents>20.00</ValueOfContents> <SvcCommitments>Tue, Jul 02, 2019 Guaranteed</SvcCommitments> - <SvcDescription>Priority Mail Express International&lt;sup&gt;&#8482;&lt;/sup&gt; Padded - Flat Rate Envelope - </SvcDescription> + <SvcDescription>Priority Mail Express International&lt;sup&gt;&#8482;&lt;/sup&gt; Padded Flat Rate Envelope</SvcDescription> <MaxDimensions>USPS-Produced Envelope: 12-1/2" x 9-1/2"<br>Maximum weight 4 pounds.</MaxDimensions> <MaxWeight>4</MaxWeight> <GuaranteeAvailability>07/02/2019</GuaranteeAvailability> @@ -330,8 +329,7 @@ </ExtraServices> <ValueOfContents>20.00</ValueOfContents> <SvcCommitments>6 - 10 business days to many major markets</SvcCommitments> - <SvcDescription>Priority Mail International&lt;sup&gt;&#174;&lt;/sup&gt; - </SvcDescription> + <SvcDescription>Priority Mail International&lt;sup&gt;&#174;&lt;/sup&gt;</SvcDescription> <MaxDimensions>Max. length 79", max. length plus girth 108"</MaxDimensions> <MaxWeight>66</MaxWeight> </Service> @@ -364,9 +362,7 @@ </ExtraServices> <ValueOfContents>20.00</ValueOfContents> <SvcCommitments>6 - 10 business days to many major markets</SvcCommitments> - <SvcDescription>Priority Mail International&lt;sup&gt;&#174;&lt;/sup&gt; Large Flat Rate - Box - </SvcDescription> + <SvcDescription>Priority Mail International&lt;sup&gt;&#174;&lt;/sup&gt; Large Flat Rate Box</SvcDescription> <MaxDimensions>USPS-Produced Box: 23-11/16" x 11-3/4" x 3" or 12" x 12" x 5-1/2"<br>Maximum weight 20 pounds. </MaxDimensions> @@ -401,9 +397,7 @@ </ExtraServices> <ValueOfContents>20.00</ValueOfContents> <SvcCommitments>6 - 10 business days to many major markets</SvcCommitments> - <SvcDescription>Priority Mail International&lt;sup&gt;&#174;&lt;/sup&gt; Medium Flat - Rate Box - </SvcDescription> + <SvcDescription>Priority Mail International&lt;sup&gt;&#174;&lt;/sup&gt; Medium Flat Rate Box</SvcDescription> <MaxDimensions>USPS-Produced Box: 13-5/8" x 11-7/8" x 3-3/8" or 11" x 8-1/2" x 5-1/2"<br>Maximum weight 20 pounds. </MaxDimensions> @@ -438,9 +432,7 @@ </ExtraServices> <ValueOfContents>20.00</ValueOfContents> <SvcCommitments>6 - 10 business days to many major markets</SvcCommitments> - <SvcDescription>Priority Mail International&lt;sup&gt;&#174;&lt;/sup&gt; Small Flat Rate - Box - </SvcDescription> + <SvcDescription>Priority Mail International&lt;sup&gt;&#174;&lt;/sup&gt; Small Flat Rate Box</SvcDescription> <MaxDimensions>USPS-Produced Box: 8-5/8" x 5-3/8" x 1-5/8"<br>Maximum weight 4 pounds.</MaxDimensions> <MaxWeight>4</MaxWeight> </Service> @@ -473,9 +465,7 @@ </ExtraServices> <ValueOfContents>20.00</ValueOfContents> <SvcCommitments>6 - 10 business days to many major markets</SvcCommitments> - <SvcDescription>Priority Mail International&lt;sup&gt;&#174;&lt;/sup&gt; DVD Flat Rate - priced box - </SvcDescription> + <SvcDescription>Priority Mail International&lt;sup&gt;&#174;&lt;/sup&gt; DVD Flat Rate priced box</SvcDescription> <MaxDimensions>USPS-Produced Box: 7-9/16" x 5-7/16" x 5/8"<br>Maximum weight 4 pounds.</MaxDimensions> <MaxWeight>4</MaxWeight> </Service> @@ -508,9 +498,7 @@ </ExtraServices> <ValueOfContents>20.00</ValueOfContents> <SvcCommitments>6 - 10 business days to many major markets</SvcCommitments> - <SvcDescription>Priority Mail International&lt;sup&gt;&#174;&lt;/sup&gt; Large Video - Flat Rate priced box - </SvcDescription> + <SvcDescription>Priority Mail International&lt;sup&gt;&#174;&lt;/sup&gt; Large Video Flat Rate priced box</SvcDescription> <MaxDimensions>USPS-Produced Box: 9-1/4" x 6-1/4" x 2"<br>Maximum weight 4 pounds.</MaxDimensions> <MaxWeight>4</MaxWeight> </Service> @@ -543,9 +531,7 @@ </ExtraServices> <ValueOfContents>20.00</ValueOfContents> <SvcCommitments>6 - 10 business days to many major markets</SvcCommitments> - <SvcDescription>Priority Mail International&lt;sup&gt;&#174;&lt;/sup&gt; Flat Rate - Envelope - </SvcDescription> + <SvcDescription>Priority Mail International&lt;sup&gt;&#174;&lt;/sup&gt; Flat Rate Envelope</SvcDescription> <MaxDimensions>USPS-Produced Envelope: 12-1/2" x 9-1/2"<br>Maximum weight 4 pounds.</MaxDimensions> <MaxWeight>4</MaxWeight> </Service> @@ -578,9 +564,7 @@ </ExtraServices> <ValueOfContents>20.00</ValueOfContents> <SvcCommitments>6 - 10 business days to many major markets</SvcCommitments> - <SvcDescription>Priority Mail International&lt;sup&gt;&#174;&lt;/sup&gt; Legal Flat Rate - Envelope - </SvcDescription> + <SvcDescription>Priority Mail International&lt;sup&gt;&#174;&lt;/sup&gt; Legal Flat Rate Envelope</SvcDescription> <MaxDimensions>USPS-Produced Envelope: 15" x 9-1/2"<br>Maximum weight 4 pounds.</MaxDimensions> <MaxWeight>4</MaxWeight> </Service> @@ -613,9 +597,7 @@ </ExtraServices> <ValueOfContents>20.00</ValueOfContents> <SvcCommitments>6 - 10 business days to many major markets</SvcCommitments> - <SvcDescription>Priority Mail International&lt;sup&gt;&#174;&lt;/sup&gt; Padded Flat - Rate Envelope - </SvcDescription> + <SvcDescription>Priority Mail International&lt;sup&gt;&#174;&lt;/sup&gt; Padded Flat Rate Envelope</SvcDescription> <MaxDimensions>USPS-Produced Envelope: 12-1/2" x 9-1/2"<br>Maximum weight 4 pounds.</MaxDimensions> <MaxWeight>4</MaxWeight> </Service> @@ -648,9 +630,7 @@ </ExtraServices> <ValueOfContents>20.00</ValueOfContents> <SvcCommitments>6 - 10 business days to many major markets</SvcCommitments> - <SvcDescription>Priority Mail International&lt;sup&gt;&#174;&lt;/sup&gt; Gift Card Flat - Rate Envelope - </SvcDescription> + <SvcDescription>Priority Mail International&lt;sup&gt;&#174;&lt;/sup&gt; Gift Card Flat Rate Envelope</SvcDescription> <MaxDimensions>USPS-Produced Envelope: 10" x 7"<br>Maximum weight 4 pounds.</MaxDimensions> <MaxWeight>4</MaxWeight> </Service> @@ -683,9 +663,7 @@ </ExtraServices> <ValueOfContents>20.00</ValueOfContents> <SvcCommitments>6 - 10 business days to many major markets</SvcCommitments> - <SvcDescription>Priority Mail International&lt;sup&gt;&#174;&lt;/sup&gt; Small Flat Rate - Envelope - </SvcDescription> + <SvcDescription>Priority Mail International&lt;sup&gt;&#174;&lt;/sup&gt; Small Flat Rate Envelope</SvcDescription> <MaxDimensions>USPS-Produced Envelope: 10" x 6"<br>Maximum weight 4 pounds.</MaxDimensions> <MaxWeight>4</MaxWeight> </Service> @@ -718,9 +696,7 @@ </ExtraServices> <ValueOfContents>20.00</ValueOfContents> <SvcCommitments>6 - 10 business days to many major markets</SvcCommitments> - <SvcDescription>Priority Mail International&lt;sup&gt;&#174;&lt;/sup&gt; Window Flat - Rate Envelope - </SvcDescription> + <SvcDescription>Priority Mail International&lt;sup&gt;&#174;&lt;/sup&gt; Window Flat Rate Envelope</SvcDescription> <MaxDimensions>USPS-Produced Envelope: 10" x 5" or 12-1/2" x 9-1/2"<br>Maximum weight 4 pounds. </MaxDimensions> <MaxWeight>4</MaxWeight> @@ -740,9 +716,7 @@ <ExtraServices> <ExtraService> <ServiceID>109</ServiceID> - <ServiceName>Electronic USPS Delivery Confirmation™ International (E-USPS DELCON - INTL™) - </ServiceName> + <ServiceName>Electronic USPS Delivery Confirmation™ International (E-USPS DELCON INTL™)</ServiceName> <Available>True</Available> <Price>0.00</Price> </ExtraService> @@ -768,9 +742,7 @@ <ValueOfContents>20.00</ValueOfContents> <InsComment>SERVICE</InsComment> <SvcCommitments>Varies by destination</SvcCommitments> - <SvcDescription>First-Class Package International - Service&lt;sup&gt;&#8482;&lt;/sup&gt; - </SvcDescription> + <SvcDescription>First-Class Package International Service&lt;sup&gt;&#8482;&lt;/sup&gt;</SvcDescription> <MaxDimensions>Other than rolls: Max. length 24", max length, height and depth (thickness) combined 36"<br>Rolls: Max. length 36". Max length and twice the diameter combined 42" </MaxDimensions> diff --git a/dev/tests/api-functional/_files/Magento/TestModuleUsps/_files/mock_response_us.xml b/dev/tests/api-functional/_files/Magento/TestModuleUsps/_files/mock_response_us.xml index ecd41a01f1c3d..bda939dd88d69 100644 --- a/dev/tests/api-functional/_files/Magento/TestModuleUsps/_files/mock_response_us.xml +++ b/dev/tests/api-functional/_files/Magento/TestModuleUsps/_files/mock_response_us.xml @@ -1,4 +1,10 @@ <?xml version="1.0" encoding="UTF-8"?> +<!-- +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> <RateV4Response> <Package ID="0"> <ZipOrigination>90210</ZipOrigination> @@ -13,44 +19,31 @@ <Rate>41.65</Rate> </Postage> <Postage CLASSID="2"> - <MailService>Priority Mail Express 2-Day&lt;sup&gt;&#8482;&lt;/sup&gt; Hold For Pickup - </MailService> + <MailService>Priority Mail Express 2-Day&lt;sup&gt;&#8482;&lt;/sup&gt; Hold For Pickup</MailService> <Rate>41.65</Rate> </Postage> <Postage CLASSID="13"> - <MailService>Priority Mail Express 2-Day&lt;sup&gt;&#8482;&lt;/sup&gt; Flat Rate - Envelope - </MailService> + <MailService>Priority Mail Express 2-Day&lt;sup&gt;&#8482;&lt;/sup&gt; Flat Rate Envelope</MailService> <Rate>25.50</Rate> </Postage> <Postage CLASSID="27"> - <MailService>Priority Mail Express 2-Day&lt;sup&gt;&#8482;&lt;/sup&gt; Flat Rate - Envelope Hold For Pickup - </MailService> + <MailService>Priority Mail Express 2-Day&lt;sup&gt;&#8482;&lt;/sup&gt; Flat Rate Envelope Hold For Pickup</MailService> <Rate>25.50</Rate> </Postage> <Postage CLASSID="30"> - <MailService>Priority Mail Express 2-Day&lt;sup&gt;&#8482;&lt;/sup&gt; Legal Flat Rate - Envelope - </MailService> + <MailService>Priority Mail Express 2-Day&lt;sup&gt;&#8482;&lt;/sup&gt; Legal Flat Rate Envelope</MailService> <Rate>25.70</Rate> </Postage> <Postage CLASSID="31"> - <MailService>Priority Mail Express 2-Day&lt;sup&gt;&#8482;&lt;/sup&gt; Legal Flat Rate - Envelope Hold For Pickup - </MailService> + <MailService>Priority Mail Express 2-Day&lt;sup&gt;&#8482;&lt;/sup&gt; Legal Flat Rate Envelope Hold For Pickup</MailService> <Rate>25.70</Rate> </Postage> <Postage CLASSID="62"> - <MailService>Priority Mail Express 2-Day&lt;sup&gt;&#8482;&lt;/sup&gt; Padded Flat Rate - Envelope - </MailService> + <MailService>Priority Mail Express 2-Day&lt;sup&gt;&#8482;&lt;/sup&gt; Padded Flat Rate Envelope</MailService> <Rate>26.20</Rate> </Postage> <Postage CLASSID="63"> - <MailService>Priority Mail Express 2-Day&lt;sup&gt;&#8482;&lt;/sup&gt; Padded Flat Rate - Envelope Hold For Pickup - </MailService> + <MailService>Priority Mail Express 2-Day&lt;sup&gt;&#8482;&lt;/sup&gt; Padded Flat Rate Envelope Hold For Pickup</MailService> <Rate>26.20</Rate> </Postage> <Postage CLASSID="1"> @@ -58,53 +51,39 @@ <Rate>11.20</Rate> </Postage> <Postage CLASSID="22"> - <MailService>Priority Mail 3-Day&lt;sup&gt;&#8482;&lt;/sup&gt; Large Flat Rate Box - </MailService> + <MailService>Priority Mail 3-Day&lt;sup&gt;&#8482;&lt;/sup&gt; Large Flat Rate Box</MailService> <Rate>19.95</Rate> </Postage> <Postage CLASSID="17"> - <MailService>Priority Mail 3-Day&lt;sup&gt;&#8482;&lt;/sup&gt; Medium Flat Rate Box - </MailService> + <MailService>Priority Mail 3-Day&lt;sup&gt;&#8482;&lt;/sup&gt; Medium Flat Rate Box</MailService> <Rate>14.35</Rate> </Postage> <Postage CLASSID="28"> - <MailService>Priority Mail 3-Day&lt;sup&gt;&#8482;&lt;/sup&gt; Small Flat Rate Box - </MailService> + <MailService>Priority Mail 3-Day&lt;sup&gt;&#8482;&lt;/sup&gt; Small Flat Rate Box</MailService> <Rate>7.90</Rate> </Postage> <Postage CLASSID="16"> - <MailService>Priority Mail 3-Day&lt;sup&gt;&#8482;&lt;/sup&gt; Flat Rate Envelope - </MailService> + <MailService>Priority Mail 3-Day&lt;sup&gt;&#8482;&lt;/sup&gt; Flat Rate Envelope</MailService> <Rate>7.35</Rate> </Postage> <Postage CLASSID="44"> - <MailService>Priority Mail 3-Day&lt;sup&gt;&#8482;&lt;/sup&gt; Legal Flat Rate - Envelope - </MailService> + <MailService>Priority Mail 3-Day&lt;sup&gt;&#8482;&lt;/sup&gt; Legal Flat Rate Envelope</MailService> <Rate>7.65</Rate> </Postage> <Postage CLASSID="29"> - <MailService>Priority Mail 3-Day&lt;sup&gt;&#8482;&lt;/sup&gt; Padded Flat Rate - Envelope - </MailService> + <MailService>Priority Mail 3-Day&lt;sup&gt;&#8482;&lt;/sup&gt; Padded Flat Rate Envelope</MailService> <Rate>8.00</Rate> </Postage> <Postage CLASSID="38"> - <MailService>Priority Mail 3-Day&lt;sup&gt;&#8482;&lt;/sup&gt; Gift Card Flat Rate - Envelope - </MailService> + <MailService>Priority Mail 3-Day&lt;sup&gt;&#8482;&lt;/sup&gt; Gift Card Flat Rate Envelope</MailService> <Rate>7.35</Rate> </Postage> <Postage CLASSID="42"> - <MailService>Priority Mail 3-Day&lt;sup&gt;&#8482;&lt;/sup&gt; Small Flat Rate - Envelope - </MailService> + <MailService>Priority Mail 3-Day&lt;sup&gt;&#8482;&lt;/sup&gt; Small Flat Rate Envelope</MailService> <Rate>7.35</Rate> </Postage> <Postage CLASSID="40"> - <MailService>Priority Mail 3-Day&lt;sup&gt;&#8482;&lt;/sup&gt; Window Flat Rate - Envelope - </MailService> + <MailService>Priority Mail 3-Day&lt;sup&gt;&#8482;&lt;/sup&gt; Window Flat Rate Envelope</MailService> <Rate>7.35</Rate> </Postage> <Postage CLASSID="4"> diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Usps/SetUspsShippingMethodsOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Usps/SetUspsShippingMethodsOnCartTest.php index 7d5f88c7c25b8..80e66370e0fef 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Usps/SetUspsShippingMethodsOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Usps/SetUspsShippingMethodsOnCartTest.php @@ -111,6 +111,7 @@ public function testSetUspsShippingMethod(string $methodCode, string $methodLabe self::assertEquals(self::CARRIER_TITLE, $shippingAddress['selected_shipping_method']['carrier_title']); self::assertArrayHasKey('method_title', $shippingAddress['selected_shipping_method']); + self::assertEquals($methodLabel, $shippingAddress['selected_shipping_method']['method_title']); } /** @@ -183,6 +184,7 @@ public function testSetUspsShippingMethodBasedOnCanadaAddress(string $methodCode self::assertEquals(self::CARRIER_TITLE, $shippingAddress['selected_shipping_method']['carrier_title']); self::assertArrayHasKey('method_title', $shippingAddress['selected_shipping_method']); + self::assertEquals($methodLabel, $shippingAddress['selected_shipping_method']['method_title']); } /** From 1f86c1256e433c6f614f9444ec1cc29ea3a569d1 Mon Sep 17 00:00:00 2001 From: OlgaVasyltsun <olga.vasyltsun@gmail.com> Date: Tue, 25 Jun 2019 16:15:22 +0300 Subject: [PATCH 522/773] MC-17755: Message isn't displayed on the error after connection reset and placing order --- .../Checkout/view/frontend/web/js/model/error-processor.js | 2 +- .../Checkout/frontend/js/model/error-processor.test.js | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/error-processor.js b/app/code/Magento/Checkout/view/frontend/web/js/model/error-processor.js index 42b692ff9dd8d..14de743be83f3 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/model/error-processor.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/model/error-processor.js @@ -29,7 +29,7 @@ define([ try { error = JSON.parse(response.responseText); } catch (exception) { - error = $t('Something went wrong with your request. Please try again later.'); + error = {message: $t('Something went wrong with your request. Please try again later.')}; } messageContainer.addErrorMessage(error); } diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Checkout/frontend/js/model/error-processor.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Checkout/frontend/js/model/error-processor.test.js index 772250eb7c66a..93731646aad1f 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Checkout/frontend/js/model/error-processor.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Checkout/frontend/js/model/error-processor.test.js @@ -46,14 +46,17 @@ define([ }); it('check on success response with invalid response data', function () { - var messageContainer = jasmine.createSpyObj('globalMessageList', ['addErrorMessage']); + var messageContainer = jasmine.createSpyObj('globalMessageList', ['addErrorMessage']), + messageObject = { + message: 'Something went wrong with your request. Please try again later.' + }; model.process({ status: 200, responseText: '' }, messageContainer); expect(messageContainer.addErrorMessage) - .toHaveBeenCalledWith('Something went wrong with your request. Please try again later.'); + .toHaveBeenCalledWith(messageObject); }); it('check on failed status', function () { From e1ce4582e8c97b9701328210a5a1ed470c883814 Mon Sep 17 00:00:00 2001 From: Roman Lytvynenko <lytvynen@adobe.com> Date: Tue, 25 Jun 2019 10:11:10 -0500 Subject: [PATCH 523/773] MC-17574: Magento WYSIWYG editor inserting " when inserting image image --- lib/web/mage/adminhtml/wysiwyg/tiny_mce/tinymce4Adapter.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/web/mage/adminhtml/wysiwyg/tiny_mce/tinymce4Adapter.js b/lib/web/mage/adminhtml/wysiwyg/tiny_mce/tinymce4Adapter.js index 9779be85133f8..227ffe27bc9b3 100644 --- a/lib/web/mage/adminhtml/wysiwyg/tiny_mce/tinymce4Adapter.js +++ b/lib/web/mage/adminhtml/wysiwyg/tiny_mce/tinymce4Adapter.js @@ -701,6 +701,9 @@ define([ */ decodeContent: function (content) { if (this.config['add_directives']) { + if (content.match(/{{.+?}}/g)) { + return content.replace(/"/g, '"'); + } content = this.decodeDirectives(content); } From aa9db9f72523dae7e1995da78de8008f783d6478 Mon Sep 17 00:00:00 2001 From: Roman Lytvynenko <lytvynen@adobe.com> Date: Tue, 25 Jun 2019 13:19:10 -0500 Subject: [PATCH 524/773] MC-17574: Magento WYSIWYG editor inserting " when inserting image image --- lib/web/mage/adminhtml/wysiwyg/tiny_mce/tinymce4Adapter.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/web/mage/adminhtml/wysiwyg/tiny_mce/tinymce4Adapter.js b/lib/web/mage/adminhtml/wysiwyg/tiny_mce/tinymce4Adapter.js index 227ffe27bc9b3..2e7b5ccecdf37 100644 --- a/lib/web/mage/adminhtml/wysiwyg/tiny_mce/tinymce4Adapter.js +++ b/lib/web/mage/adminhtml/wysiwyg/tiny_mce/tinymce4Adapter.js @@ -701,9 +701,9 @@ define([ */ decodeContent: function (content) { if (this.config['add_directives']) { - if (content.match(/{{.+?}}/g)) { - return content.replace(/"/g, '"'); - } + // if (content.match(/{{.+?}}/g)) { + // return content.replace(/"/g, '"'); + // } content = this.decodeDirectives(content); } From 2d4d3afe8d1482c394dd913a8b1badff08f0c87c Mon Sep 17 00:00:00 2001 From: Roman Lytvynenko <lytvynen@adobe.com> Date: Tue, 25 Jun 2019 13:51:01 -0500 Subject: [PATCH 525/773] MC-17574: Magento WYSIWYG editor inserting " when inserting image image --- lib/web/mage/adminhtml/wysiwyg/tiny_mce/tinymce4Adapter.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/web/mage/adminhtml/wysiwyg/tiny_mce/tinymce4Adapter.js b/lib/web/mage/adminhtml/wysiwyg/tiny_mce/tinymce4Adapter.js index 2e7b5ccecdf37..227ffe27bc9b3 100644 --- a/lib/web/mage/adminhtml/wysiwyg/tiny_mce/tinymce4Adapter.js +++ b/lib/web/mage/adminhtml/wysiwyg/tiny_mce/tinymce4Adapter.js @@ -701,9 +701,9 @@ define([ */ decodeContent: function (content) { if (this.config['add_directives']) { - // if (content.match(/{{.+?}}/g)) { - // return content.replace(/"/g, '"'); - // } + if (content.match(/{{.+?}}/g)) { + return content.replace(/"/g, '"'); + } content = this.decodeDirectives(content); } From b0f98b4057b2f04f956a422bbff2a366b269f27a Mon Sep 17 00:00:00 2001 From: Patrick McLain <pat@pmclain.com> Date: Tue, 25 Jun 2019 21:08:07 -0400 Subject: [PATCH 526/773] Fedex Soap Mock Creates a mock soap client for fetching rates during test execution. Fixes magento/graphql-ce#740 --- .../Model/MockResponseBodyLoader.php | 79 + .../TestModuleFedex/Model/MockSoapClient.php | 47 + .../Model/MockSoapClientFactory.php | 34 + .../_files/mock_response_general_ca.json | 912 ++++++ .../_files/mock_response_general_us.json | 2870 +++++++++++++++++ .../_files/mock_response_smart_post_ca.json | 912 ++++++ .../_files/mock_response_smart_post_us.json | 305 ++ .../_files/Magento/TestModuleFedex/etc/di.xml | 14 + .../Magento/TestModuleFedex/etc/module.xml | 10 + .../Magento/TestModuleFedex/registration.php | 11 + .../SetFedExShippingMethodsOnCartTest.php | 45 +- .../_files/enable_fedex_shipping_method.php | 23 +- .../enable_fedex_shipping_method_rollback.php | 3 +- 13 files changed, 5213 insertions(+), 52 deletions(-) create mode 100644 dev/tests/api-functional/_files/Magento/TestModuleFedex/Model/MockResponseBodyLoader.php create mode 100644 dev/tests/api-functional/_files/Magento/TestModuleFedex/Model/MockSoapClient.php create mode 100644 dev/tests/api-functional/_files/Magento/TestModuleFedex/Model/MockSoapClientFactory.php create mode 100644 dev/tests/api-functional/_files/Magento/TestModuleFedex/_files/mock_response_general_ca.json create mode 100644 dev/tests/api-functional/_files/Magento/TestModuleFedex/_files/mock_response_general_us.json create mode 100644 dev/tests/api-functional/_files/Magento/TestModuleFedex/_files/mock_response_smart_post_ca.json create mode 100644 dev/tests/api-functional/_files/Magento/TestModuleFedex/_files/mock_response_smart_post_us.json create mode 100644 dev/tests/api-functional/_files/Magento/TestModuleFedex/etc/di.xml create mode 100644 dev/tests/api-functional/_files/Magento/TestModuleFedex/etc/module.xml create mode 100644 dev/tests/api-functional/_files/Magento/TestModuleFedex/registration.php diff --git a/dev/tests/api-functional/_files/Magento/TestModuleFedex/Model/MockResponseBodyLoader.php b/dev/tests/api-functional/_files/Magento/TestModuleFedex/Model/MockResponseBodyLoader.php new file mode 100644 index 0000000000000..869fd113d1a5e --- /dev/null +++ b/dev/tests/api-functional/_files/Magento/TestModuleFedex/Model/MockResponseBodyLoader.php @@ -0,0 +1,79 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\TestModuleFedex\Model; + +use Magento\Framework\Exception\NotFoundException; +use Magento\Framework\HTTP\AsyncClient\Request; +use Magento\Framework\Module\Dir; +use Magento\Framework\Filesystem\Io\File; +use Magento\Framework\Stdlib\ArrayManager; + +/** + * Load mock response body for Fedex rate request + */ +class MockResponseBodyLoader +{ + private const RESPONSE_FILE_PATTERN = '%s/_files/mock_response_%s_%s.json'; + private const PATH_COUNTRY = 'RequestedShipment/Recipient/Address/CountryCode'; + private const PATH_SERVICE_TYPE = 'RequestedShipment/ServiceType'; + + /** + * @var Dir + */ + private $moduleDirectory; + + /** + * @var File + */ + private $fileIo; + + /** + * @var ArrayManager + */ + private $arrayManager; + + /** + * @param Dir $moduleDirectory + * @param File $fileIo + * @param ArrayManager + */ + public function __construct( + Dir $moduleDirectory, + File $fileIo, + ArrayManager $arrayManager + ) { + $this->moduleDirectory = $moduleDirectory; + $this->fileIo = $fileIo; + $this->arrayManager = $arrayManager; + } + + /** + * Loads mock response xml for a given request + * + * @param array $request + * @return string + * @throws NotFoundException + */ + public function loadForRequest(array $request): string + { + $moduleDir = $this->moduleDirectory->getDir('Magento_TestModuleFedex'); + + $type = strtolower($this->arrayManager->get(static::PATH_SERVICE_TYPE, $request) ?? 'general'); + $country = strtolower($this->arrayManager->get(static::PATH_COUNTRY, $request) ?? ''); + + $responsePath = sprintf(static::RESPONSE_FILE_PATTERN, $moduleDir, $type, $country); + + if (!$this->fileIo->fileExists($responsePath)) { + throw new NotFoundException( + __('"%1" is not a valid mock response type for country "%2".', $type, $country) + ); + } + + return $this->fileIo->read($responsePath); + } +} diff --git a/dev/tests/api-functional/_files/Magento/TestModuleFedex/Model/MockSoapClient.php b/dev/tests/api-functional/_files/Magento/TestModuleFedex/Model/MockSoapClient.php new file mode 100644 index 0000000000000..9720a504e3310 --- /dev/null +++ b/dev/tests/api-functional/_files/Magento/TestModuleFedex/Model/MockSoapClient.php @@ -0,0 +1,47 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\TestModuleFedex\Model; + +/** + * Mock Fedex soap client factory + */ +class MockSoapClient extends \SoapClient +{ + /** + * @var MockResponseBodyLoader + */ + private $mockResponseBodyLoader; + + /** + * @param string $wsdl + * @param MockResponseBodyLoader $mockResponseBodyLoader + * @param array|null $options + */ + public function __construct( + string $wsdl, + MockResponseBodyLoader $mockResponseBodyLoader, + array $options = null + ) { + parent::__construct($wsdl, $options); + $this->mockResponseBodyLoader = $mockResponseBodyLoader; + } + + /** + * Fetch mock Fedex rates + * + * @param array $rateRequest + * @return \stdClass + * @throws \Magento\Framework\Exception\NotFoundException + */ + public function getRates(array $rateRequest): \stdClass + { + $response = $this->mockResponseBodyLoader->loadForRequest($rateRequest); + + return json_decode($response); + } +} diff --git a/dev/tests/api-functional/_files/Magento/TestModuleFedex/Model/MockSoapClientFactory.php b/dev/tests/api-functional/_files/Magento/TestModuleFedex/Model/MockSoapClientFactory.php new file mode 100644 index 0000000000000..4309625746b94 --- /dev/null +++ b/dev/tests/api-functional/_files/Magento/TestModuleFedex/Model/MockSoapClientFactory.php @@ -0,0 +1,34 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\TestModuleFedex\Model; + +use Magento\Framework\App\ObjectManager; + +/** + * Mock Fedex soap client factory + */ +class MockSoapClientFactory extends \Magento\Framework\Webapi\Soap\ClientFactory +{ + /** + * Create instance of the mock SoapClient + * + * @param string $wsdl + * @param array $options + * @return \SoapClient + */ + public function create($wsdl, array $options = []): \SoapClient + { + return ObjectManager::getInstance()->create( + MockSoapClient::class, + [ + 'wsdl' => $wsdl, + 'options' => $options, + ] + ); + } +} diff --git a/dev/tests/api-functional/_files/Magento/TestModuleFedex/_files/mock_response_general_ca.json b/dev/tests/api-functional/_files/Magento/TestModuleFedex/_files/mock_response_general_ca.json new file mode 100644 index 0000000000000..e26f1e485542f --- /dev/null +++ b/dev/tests/api-functional/_files/Magento/TestModuleFedex/_files/mock_response_general_ca.json @@ -0,0 +1,912 @@ +{ + "HighestSeverity": "NOTE", + "Notifications": [ + { + "Severity": "NOTE", + "Source": "crs", + "Code": "886", + "Message": "Money Back Guarantee is not eligible for this pick up\/delivery postal\/zip code. FDXG", + "LocalizedMessage": "Money Back Guarantee is not eligible for this pick up\/delivery postal\/zip code. FDXG", + "MessageParameters": { + "Id": "OPERATING_COMPANY", + "Value": "FDXG" + } + }, + { + "Severity": "NOTE", + "Source": "crs", + "Code": "819", + "Message": "The origin state\/province code has been changed. ", + "LocalizedMessage": "The origin state\/province code has been changed. " + }, + { + "Severity": "NOTE", + "Source": "crs", + "Code": "820", + "Message": "The destination state\/province code has been changed. ", + "LocalizedMessage": "The destination state\/province code has been changed. " + } + ], + "Version": { + "ServiceId": "crs", + "Major": 10, + "Intermediate": 0, + "Minor": 0 + }, + "RateReplyDetails": [ + { + "ServiceType": "INTERNATIONAL_PRIORITY", + "PackagingType": "YOUR_PACKAGING", + "DestinationAirportId": "YYZ", + "IneligibleForMoneyBackGuarantee": false, + "OriginServiceArea": "A1", + "DestinationServiceArea": "AM", + "SignatureOption": "SERVICE_DEFAULT", + "ActualRateType": "PAYOR_ACCOUNT_SHIPMENT", + "RatedShipmentDetails": [ + { + "EffectiveNetDiscount": { + "Currency": "USD", + "Amount": "0.0" + }, + "ShipmentRateDetail": { + "RateType": "PAYOR_ACCOUNT_SHIPMENT", + "RateScale": "0000000", + "RateZone": "US001O", + "PricingCode": "ACTUAL", + "RatedWeightMethod": "ACTUAL", + "CurrencyExchangeRate": { + "FromCurrency": "USD", + "IntoCurrency": "USD", + "Rate": "1.0" + }, + "DimDivisor": 0, + "FuelSurchargePercent": "5.0", + "TotalBillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "TotalBaseCharge": { + "Currency": "USD", + "Amount": "92.99" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetFreight": { + "Currency": "USD", + "Amount": "92.99" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "4.65" + }, + "TotalNetFedExCharge": { + "Currency": "USD", + "Amount": "97.64" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetCharge": { + "Currency": "USD", + "Amount": "97.64" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalDutiesAndTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetChargeWithDutiesAndTaxes": { + "Currency": "USD", + "Amount": "97.64" + }, + "Surcharges": { + "SurchargeType": "FUEL", + "Description": "Fuel", + "Amount": { + "Currency": "USD", + "Amount": "4.65" + } + } + } + }, + { + "EffectiveNetDiscount": { + "Currency": "USD", + "Amount": "0.0" + }, + "ShipmentRateDetail": { + "RateType": "RATED_ACCOUNT_SHIPMENT", + "RateScale": "0000000", + "RateZone": "US001O", + "PricingCode": "ACTUAL", + "RatedWeightMethod": "ACTUAL", + "CurrencyExchangeRate": { + "FromCurrency": "USD", + "IntoCurrency": "USD", + "Rate": "1.0" + }, + "DimDivisor": 0, + "FuelSurchargePercent": "5.0", + "TotalBillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "TotalBaseCharge": { + "Currency": "USD", + "Amount": "92.99" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetFreight": { + "Currency": "USD", + "Amount": "92.99" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "4.65" + }, + "TotalNetFedExCharge": { + "Currency": "USD", + "Amount": "97.64" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetCharge": { + "Currency": "USD", + "Amount": "97.64" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalDutiesAndTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetChargeWithDutiesAndTaxes": { + "Currency": "USD", + "Amount": "97.64" + }, + "Surcharges": { + "SurchargeType": "FUEL", + "Description": "Fuel", + "Amount": { + "Currency": "USD", + "Amount": "4.65" + } + } + } + }, + { + "ShipmentRateDetail": { + "RateType": "PAYOR_LIST_SHIPMENT", + "RateScale": "0000000", + "RateZone": "US001O", + "PricingCode": "ACTUAL", + "RatedWeightMethod": "ACTUAL", + "CurrencyExchangeRate": { + "FromCurrency": "USD", + "IntoCurrency": "USD", + "Rate": "1.0" + }, + "DimDivisor": 0, + "FuelSurchargePercent": "5.0", + "TotalBillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "TotalBaseCharge": { + "Currency": "USD", + "Amount": "92.99" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetFreight": { + "Currency": "USD", + "Amount": "92.99" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "4.65" + }, + "TotalNetFedExCharge": { + "Currency": "USD", + "Amount": "97.64" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetCharge": { + "Currency": "USD", + "Amount": "97.64" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalDutiesAndTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetChargeWithDutiesAndTaxes": { + "Currency": "USD", + "Amount": "97.64" + }, + "Surcharges": { + "SurchargeType": "FUEL", + "Description": "Fuel", + "Amount": { + "Currency": "USD", + "Amount": "4.65" + } + } + } + }, + { + "ShipmentRateDetail": { + "RateType": "RATED_LIST_SHIPMENT", + "RateScale": "0000000", + "RateZone": "US001O", + "PricingCode": "ACTUAL", + "RatedWeightMethod": "ACTUAL", + "CurrencyExchangeRate": { + "FromCurrency": "USD", + "IntoCurrency": "USD", + "Rate": "1.0" + }, + "DimDivisor": 0, + "FuelSurchargePercent": "5.0", + "TotalBillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "TotalBaseCharge": { + "Currency": "USD", + "Amount": "92.99" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetFreight": { + "Currency": "USD", + "Amount": "92.99" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "4.65" + }, + "TotalNetFedExCharge": { + "Currency": "USD", + "Amount": "97.64" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetCharge": { + "Currency": "USD", + "Amount": "97.64" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalDutiesAndTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetChargeWithDutiesAndTaxes": { + "Currency": "USD", + "Amount": "97.64" + }, + "Surcharges": { + "SurchargeType": "FUEL", + "Description": "Fuel", + "Amount": { + "Currency": "USD", + "Amount": "4.65" + } + } + } + } + ] + }, + { + "ServiceType": "INTERNATIONAL_ECONOMY", + "PackagingType": "YOUR_PACKAGING", + "DestinationAirportId": "YYZ", + "IneligibleForMoneyBackGuarantee": false, + "OriginServiceArea": "A1", + "DestinationServiceArea": "AM", + "SignatureOption": "SERVICE_DEFAULT", + "ActualRateType": "PAYOR_ACCOUNT_SHIPMENT", + "RatedShipmentDetails": [ + { + "EffectiveNetDiscount": { + "Currency": "USD", + "Amount": "0.0" + }, + "ShipmentRateDetail": { + "RateType": "PAYOR_ACCOUNT_SHIPMENT", + "RateScale": "0000000", + "RateZone": "US001O", + "PricingCode": "ACTUAL", + "RatedWeightMethod": "ACTUAL", + "CurrencyExchangeRate": { + "FromCurrency": "USD", + "IntoCurrency": "USD", + "Rate": "1.0" + }, + "DimDivisor": 0, + "FuelSurchargePercent": "5.0", + "TotalBillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "TotalBaseCharge": { + "Currency": "USD", + "Amount": "83.18" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetFreight": { + "Currency": "USD", + "Amount": "83.18" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "4.16" + }, + "TotalNetFedExCharge": { + "Currency": "USD", + "Amount": "87.34" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetCharge": { + "Currency": "USD", + "Amount": "87.34" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalDutiesAndTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetChargeWithDutiesAndTaxes": { + "Currency": "USD", + "Amount": "87.34" + }, + "Surcharges": { + "SurchargeType": "FUEL", + "Description": "Fuel", + "Amount": { + "Currency": "USD", + "Amount": "4.16" + } + } + } + }, + { + "EffectiveNetDiscount": { + "Currency": "USD", + "Amount": "0.0" + }, + "ShipmentRateDetail": { + "RateType": "RATED_ACCOUNT_SHIPMENT", + "RateScale": "0000000", + "RateZone": "US001O", + "PricingCode": "ACTUAL", + "RatedWeightMethod": "ACTUAL", + "CurrencyExchangeRate": { + "FromCurrency": "USD", + "IntoCurrency": "USD", + "Rate": "1.0" + }, + "DimDivisor": 0, + "FuelSurchargePercent": "5.0", + "TotalBillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "TotalBaseCharge": { + "Currency": "USD", + "Amount": "83.18" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetFreight": { + "Currency": "USD", + "Amount": "83.18" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "4.16" + }, + "TotalNetFedExCharge": { + "Currency": "USD", + "Amount": "87.34" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetCharge": { + "Currency": "USD", + "Amount": "87.34" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalDutiesAndTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetChargeWithDutiesAndTaxes": { + "Currency": "USD", + "Amount": "87.34" + }, + "Surcharges": { + "SurchargeType": "FUEL", + "Description": "Fuel", + "Amount": { + "Currency": "USD", + "Amount": "4.16" + } + } + } + }, + { + "ShipmentRateDetail": { + "RateType": "PAYOR_LIST_SHIPMENT", + "RateScale": "0000000", + "RateZone": "US001O", + "PricingCode": "ACTUAL", + "RatedWeightMethod": "ACTUAL", + "CurrencyExchangeRate": { + "FromCurrency": "USD", + "IntoCurrency": "USD", + "Rate": "1.0" + }, + "DimDivisor": 0, + "FuelSurchargePercent": "5.0", + "TotalBillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "TotalBaseCharge": { + "Currency": "USD", + "Amount": "83.18" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetFreight": { + "Currency": "USD", + "Amount": "83.18" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "4.16" + }, + "TotalNetFedExCharge": { + "Currency": "USD", + "Amount": "87.34" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetCharge": { + "Currency": "USD", + "Amount": "87.34" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalDutiesAndTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetChargeWithDutiesAndTaxes": { + "Currency": "USD", + "Amount": "87.34" + }, + "Surcharges": { + "SurchargeType": "FUEL", + "Description": "Fuel", + "Amount": { + "Currency": "USD", + "Amount": "4.16" + } + } + } + }, + { + "ShipmentRateDetail": { + "RateType": "RATED_LIST_SHIPMENT", + "RateScale": "0000000", + "RateZone": "US001O", + "PricingCode": "ACTUAL", + "RatedWeightMethod": "ACTUAL", + "CurrencyExchangeRate": { + "FromCurrency": "USD", + "IntoCurrency": "USD", + "Rate": "1.0" + }, + "DimDivisor": 0, + "FuelSurchargePercent": "5.0", + "TotalBillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "TotalBaseCharge": { + "Currency": "USD", + "Amount": "83.18" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetFreight": { + "Currency": "USD", + "Amount": "83.18" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "4.16" + }, + "TotalNetFedExCharge": { + "Currency": "USD", + "Amount": "87.34" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetCharge": { + "Currency": "USD", + "Amount": "87.34" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalDutiesAndTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetChargeWithDutiesAndTaxes": { + "Currency": "USD", + "Amount": "87.34" + }, + "Surcharges": { + "SurchargeType": "FUEL", + "Description": "Fuel", + "Amount": { + "Currency": "USD", + "Amount": "4.16" + } + } + } + } + ] + }, + { + "ServiceType": "FEDEX_GROUND", + "PackagingType": "YOUR_PACKAGING", + "DestinationAirportId": "YYZ", + "IneligibleForMoneyBackGuarantee": true, + "SignatureOption": "SERVICE_DEFAULT", + "ActualRateType": "PAYOR_ACCOUNT_PACKAGE", + "RatedShipmentDetails": [ + { + "EffectiveNetDiscount": { + "Currency": "USD", + "Amount": "0.0" + }, + "ShipmentRateDetail": { + "RateType": "PAYOR_ACCOUNT_PACKAGE", + "RateZone": "51", + "RatedWeightMethod": "ACTUAL", + "DimDivisor": 0, + "FuelSurchargePercent": "7.0", + "TotalBillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "TotalBaseCharge": { + "Currency": "USD", + "Amount": "22.73" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetFreight": { + "Currency": "USD", + "Amount": "22.73" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "1.59" + }, + "TotalNetFedExCharge": { + "Currency": "USD", + "Amount": "24.32" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetCharge": { + "Currency": "USD", + "Amount": "24.32" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalDutiesAndTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetChargeWithDutiesAndTaxes": { + "Currency": "USD", + "Amount": "24.32" + }, + "Surcharges": [ + { + "SurchargeType": "INSURED_VALUE", + "Level": "PACKAGE", + "Description": "Insured value", + "Amount": { + "Currency": "USD", + "Amount": "0.0" + } + }, + { + "SurchargeType": "FUEL", + "Level": "PACKAGE", + "Description": "FedEx Ground Fuel", + "Amount": { + "Currency": "USD", + "Amount": "1.59" + } + } + ] + }, + "RatedPackages": { + "GroupNumber": 0, + "EffectiveNetDiscount": { + "Currency": "USD", + "Amount": "0.0" + }, + "PackageRateDetail": { + "RateType": "PAYOR_ACCOUNT_PACKAGE", + "RatedWeightMethod": "ACTUAL", + "BillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "BaseCharge": { + "Currency": "USD", + "Amount": "22.73" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "NetFreight": { + "Currency": "USD", + "Amount": "22.73" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "1.59" + }, + "NetFedExCharge": { + "Currency": "USD", + "Amount": "24.32" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "NetCharge": { + "Currency": "USD", + "Amount": "24.32" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "Surcharges": [ + { + "SurchargeType": "INSURED_VALUE", + "Level": "PACKAGE", + "Description": "Insured value", + "Amount": { + "Currency": "USD", + "Amount": "0.0" + } + }, + { + "SurchargeType": "FUEL", + "Level": "PACKAGE", + "Description": "FedEx Ground Fuel", + "Amount": { + "Currency": "USD", + "Amount": "1.59" + } + } + ] + } + } + }, + { + "ShipmentRateDetail": { + "RateType": "PAYOR_LIST_PACKAGE", + "RateZone": "51", + "RatedWeightMethod": "ACTUAL", + "DimDivisor": 0, + "FuelSurchargePercent": "7.0", + "TotalBillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "TotalBaseCharge": { + "Currency": "USD", + "Amount": "22.73" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetFreight": { + "Currency": "USD", + "Amount": "22.73" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "1.59" + }, + "TotalNetFedExCharge": { + "Currency": "USD", + "Amount": "24.32" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetCharge": { + "Currency": "USD", + "Amount": "24.32" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalDutiesAndTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetChargeWithDutiesAndTaxes": { + "Currency": "USD", + "Amount": "24.32" + }, + "Surcharges": [ + { + "SurchargeType": "INSURED_VALUE", + "Level": "PACKAGE", + "Description": "Insured value", + "Amount": { + "Currency": "USD", + "Amount": "0.0" + } + }, + { + "SurchargeType": "FUEL", + "Level": "PACKAGE", + "Description": "FedEx Ground Fuel", + "Amount": { + "Currency": "USD", + "Amount": "1.59" + } + } + ] + }, + "RatedPackages": { + "GroupNumber": 0, + "PackageRateDetail": { + "RateType": "PAYOR_LIST_PACKAGE", + "RatedWeightMethod": "ACTUAL", + "BillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "BaseCharge": { + "Currency": "USD", + "Amount": "22.73" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "NetFreight": { + "Currency": "USD", + "Amount": "22.73" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "1.59" + }, + "NetFedExCharge": { + "Currency": "USD", + "Amount": "24.32" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "NetCharge": { + "Currency": "USD", + "Amount": "24.32" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "Surcharges": [ + { + "SurchargeType": "INSURED_VALUE", + "Level": "PACKAGE", + "Description": "Insured value", + "Amount": { + "Currency": "USD", + "Amount": "0.0" + } + }, + { + "SurchargeType": "FUEL", + "Level": "PACKAGE", + "Description": "FedEx Ground Fuel", + "Amount": { + "Currency": "USD", + "Amount": "1.59" + } + } + ] + } + } + } + ] + } + ] +} \ No newline at end of file diff --git a/dev/tests/api-functional/_files/Magento/TestModuleFedex/_files/mock_response_general_us.json b/dev/tests/api-functional/_files/Magento/TestModuleFedex/_files/mock_response_general_us.json new file mode 100644 index 0000000000000..bc7d51dcbb3b5 --- /dev/null +++ b/dev/tests/api-functional/_files/Magento/TestModuleFedex/_files/mock_response_general_us.json @@ -0,0 +1,2870 @@ +{ + "HighestSeverity": "WARNING", + "Notifications": [ + { + "Severity": "WARNING", + "Source": "crs", + "Code": "835", + "Message": "Destination Postal-City Mismatch. ", + "LocalizedMessage": "Destination Postal-City Mismatch. " + }, + { + "Severity": "NOTE", + "Source": "crs", + "Code": "819", + "Message": "The origin state\/province code has been changed. ", + "LocalizedMessage": "The origin state\/province code has been changed. " + }, + { + "Severity": "NOTE", + "Source": "crs", + "Code": "820", + "Message": "The destination state\/province code has been changed. ", + "LocalizedMessage": "The destination state\/province code has been changed. " + } + ], + "Version": { + "ServiceId": "crs", + "Major": 10, + "Intermediate": 0, + "Minor": 0 + }, + "RateReplyDetails": [ + { + "ServiceType": "FIRST_OVERNIGHT", + "PackagingType": "YOUR_PACKAGING", + "DestinationAirportId": "DFW", + "IneligibleForMoneyBackGuarantee": false, + "OriginServiceArea": "A1", + "DestinationServiceArea": "A6", + "SignatureOption": "SERVICE_DEFAULT", + "ActualRateType": "PAYOR_ACCOUNT_PACKAGE", + "RatedShipmentDetails": [ + { + "EffectiveNetDiscount": { + "Currency": "USD", + "Amount": "0.0" + }, + "ShipmentRateDetail": { + "RateType": "PAYOR_ACCOUNT_PACKAGE", + "RateScale": "14", + "RateZone": "6", + "PricingCode": "PACKAGE", + "RatedWeightMethod": "ACTUAL", + "DimDivisor": 0, + "FuelSurchargePercent": "6.0", + "TotalBillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "TotalBaseCharge": { + "Currency": "USD", + "Amount": "102.59" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetFreight": { + "Currency": "USD", + "Amount": "102.59" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "9.18" + }, + "TotalNetFedExCharge": { + "Currency": "USD", + "Amount": "111.77" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetCharge": { + "Currency": "USD", + "Amount": "111.77" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalDutiesAndTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetChargeWithDutiesAndTaxes": { + "Currency": "USD", + "Amount": "111.77" + }, + "Surcharges": [ + { + "SurchargeType": "DELIVERY_AREA", + "Description": "Delivery Area Surcharge Extended Commercial", + "Amount": { + "Currency": "USD", + "Amount": "2.85" + } + }, + { + "SurchargeType": "INSURED_VALUE", + "Description": "Insured value", + "Amount": { + "Currency": "USD", + "Amount": "0.0" + } + }, + { + "SurchargeType": "FUEL", + "Description": "Fuel", + "Amount": { + "Currency": "USD", + "Amount": "6.33" + } + } + ] + }, + "RatedPackages": { + "GroupNumber": 0, + "EffectiveNetDiscount": { + "Currency": "USD", + "Amount": "0.0" + }, + "PackageRateDetail": { + "RateType": "PAYOR_ACCOUNT_PACKAGE", + "RatedWeightMethod": "ACTUAL", + "BillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "BaseCharge": { + "Currency": "USD", + "Amount": "102.59" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "NetFreight": { + "Currency": "USD", + "Amount": "102.59" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "9.18" + }, + "NetFedExCharge": { + "Currency": "USD", + "Amount": "111.77" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "NetCharge": { + "Currency": "USD", + "Amount": "111.77" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "Surcharges": [ + { + "SurchargeType": "DELIVERY_AREA", + "Description": "Delivery Area Surcharge Extended Commercial", + "Amount": { + "Currency": "USD", + "Amount": "2.85" + } + }, + { + "SurchargeType": "INSURED_VALUE", + "Description": "Insured value", + "Amount": { + "Currency": "USD", + "Amount": "0.0" + } + }, + { + "SurchargeType": "FUEL", + "Description": "Fuel", + "Amount": { + "Currency": "USD", + "Amount": "6.33" + } + } + ] + } + } + }, + { + "EffectiveNetDiscount": { + "Currency": "USD", + "Amount": "0.0" + }, + "ShipmentRateDetail": { + "RateType": "RATED_ACCOUNT_PACKAGE", + "RateScale": "14", + "RateZone": "6", + "PricingCode": "PACKAGE", + "RatedWeightMethod": "ACTUAL", + "DimDivisor": 0, + "FuelSurchargePercent": "6.0", + "TotalBillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "TotalBaseCharge": { + "Currency": "USD", + "Amount": "102.59" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetFreight": { + "Currency": "USD", + "Amount": "102.59" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "9.18" + }, + "TotalNetFedExCharge": { + "Currency": "USD", + "Amount": "111.77" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetCharge": { + "Currency": "USD", + "Amount": "111.77" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalDutiesAndTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetChargeWithDutiesAndTaxes": { + "Currency": "USD", + "Amount": "111.77" + }, + "Surcharges": [ + { + "SurchargeType": "DELIVERY_AREA", + "Description": "Delivery Area Surcharge Extended Commercial", + "Amount": { + "Currency": "USD", + "Amount": "2.85" + } + }, + { + "SurchargeType": "INSURED_VALUE", + "Description": "Insured value", + "Amount": { + "Currency": "USD", + "Amount": "0.0" + } + }, + { + "SurchargeType": "FUEL", + "Description": "Fuel", + "Amount": { + "Currency": "USD", + "Amount": "6.33" + } + } + ] + }, + "RatedPackages": { + "GroupNumber": 0, + "EffectiveNetDiscount": { + "Currency": "USD", + "Amount": "0.0" + }, + "PackageRateDetail": { + "RateType": "RATED_ACCOUNT_PACKAGE", + "RatedWeightMethod": "ACTUAL", + "BillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "BaseCharge": { + "Currency": "USD", + "Amount": "102.59" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "NetFreight": { + "Currency": "USD", + "Amount": "102.59" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "9.18" + }, + "NetFedExCharge": { + "Currency": "USD", + "Amount": "111.77" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "NetCharge": { + "Currency": "USD", + "Amount": "111.77" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "Surcharges": [ + { + "SurchargeType": "DELIVERY_AREA", + "Description": "Delivery Area Surcharge Extended Commercial", + "Amount": { + "Currency": "USD", + "Amount": "2.85" + } + }, + { + "SurchargeType": "INSURED_VALUE", + "Description": "Insured value", + "Amount": { + "Currency": "USD", + "Amount": "0.0" + } + }, + { + "SurchargeType": "FUEL", + "Description": "Fuel", + "Amount": { + "Currency": "USD", + "Amount": "6.33" + } + } + ] + } + } + }, + { + "ShipmentRateDetail": { + "RateType": "PAYOR_LIST_PACKAGE", + "RateScale": "14", + "RateZone": "6", + "PricingCode": "PACKAGE", + "RatedWeightMethod": "ACTUAL", + "DimDivisor": 0, + "FuelSurchargePercent": "6.0", + "TotalBillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "TotalBaseCharge": { + "Currency": "USD", + "Amount": "102.59" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetFreight": { + "Currency": "USD", + "Amount": "102.59" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "9.18" + }, + "TotalNetFedExCharge": { + "Currency": "USD", + "Amount": "111.77" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetCharge": { + "Currency": "USD", + "Amount": "111.77" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalDutiesAndTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetChargeWithDutiesAndTaxes": { + "Currency": "USD", + "Amount": "111.77" + }, + "Surcharges": [ + { + "SurchargeType": "DELIVERY_AREA", + "Description": "Delivery Area Surcharge Extended Commercial", + "Amount": { + "Currency": "USD", + "Amount": "2.85" + } + }, + { + "SurchargeType": "INSURED_VALUE", + "Description": "Insured value", + "Amount": { + "Currency": "USD", + "Amount": "0.0" + } + }, + { + "SurchargeType": "FUEL", + "Description": "Fuel", + "Amount": { + "Currency": "USD", + "Amount": "6.33" + } + } + ] + }, + "RatedPackages": { + "GroupNumber": 0, + "PackageRateDetail": { + "RateType": "PAYOR_LIST_PACKAGE", + "RatedWeightMethod": "ACTUAL", + "BillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "BaseCharge": { + "Currency": "USD", + "Amount": "102.59" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "NetFreight": { + "Currency": "USD", + "Amount": "102.59" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "9.18" + }, + "NetFedExCharge": { + "Currency": "USD", + "Amount": "111.77" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "NetCharge": { + "Currency": "USD", + "Amount": "111.77" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "Surcharges": [ + { + "SurchargeType": "DELIVERY_AREA", + "Description": "Delivery Area Surcharge Extended Commercial", + "Amount": { + "Currency": "USD", + "Amount": "2.85" + } + }, + { + "SurchargeType": "INSURED_VALUE", + "Description": "Insured value", + "Amount": { + "Currency": "USD", + "Amount": "0.0" + } + }, + { + "SurchargeType": "FUEL", + "Description": "Fuel", + "Amount": { + "Currency": "USD", + "Amount": "6.33" + } + } + ] + } + } + }, + { + "ShipmentRateDetail": { + "RateType": "RATED_LIST_PACKAGE", + "RateScale": "14", + "RateZone": "6", + "PricingCode": "PACKAGE", + "RatedWeightMethod": "ACTUAL", + "DimDivisor": 0, + "FuelSurchargePercent": "6.0", + "TotalBillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "TotalBaseCharge": { + "Currency": "USD", + "Amount": "102.59" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetFreight": { + "Currency": "USD", + "Amount": "102.59" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "9.18" + }, + "TotalNetFedExCharge": { + "Currency": "USD", + "Amount": "111.77" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetCharge": { + "Currency": "USD", + "Amount": "111.77" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalDutiesAndTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetChargeWithDutiesAndTaxes": { + "Currency": "USD", + "Amount": "111.77" + }, + "Surcharges": [ + { + "SurchargeType": "DELIVERY_AREA", + "Description": "Delivery Area Surcharge Extended Commercial", + "Amount": { + "Currency": "USD", + "Amount": "2.85" + } + }, + { + "SurchargeType": "INSURED_VALUE", + "Description": "Insured value", + "Amount": { + "Currency": "USD", + "Amount": "0.0" + } + }, + { + "SurchargeType": "FUEL", + "Description": "Fuel", + "Amount": { + "Currency": "USD", + "Amount": "6.33" + } + } + ] + }, + "RatedPackages": { + "GroupNumber": 0, + "PackageRateDetail": { + "RateType": "RATED_LIST_PACKAGE", + "RatedWeightMethod": "ACTUAL", + "BillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "BaseCharge": { + "Currency": "USD", + "Amount": "102.59" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "NetFreight": { + "Currency": "USD", + "Amount": "102.59" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "9.18" + }, + "NetFedExCharge": { + "Currency": "USD", + "Amount": "111.77" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "NetCharge": { + "Currency": "USD", + "Amount": "111.77" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "Surcharges": [ + { + "SurchargeType": "DELIVERY_AREA", + "Description": "Delivery Area Surcharge Extended Commercial", + "Amount": { + "Currency": "USD", + "Amount": "2.85" + } + }, + { + "SurchargeType": "INSURED_VALUE", + "Description": "Insured value", + "Amount": { + "Currency": "USD", + "Amount": "0.0" + } + }, + { + "SurchargeType": "FUEL", + "Description": "Fuel", + "Amount": { + "Currency": "USD", + "Amount": "6.33" + } + } + ] + } + } + } + ] + }, + { + "ServiceType": "PRIORITY_OVERNIGHT", + "PackagingType": "YOUR_PACKAGING", + "DestinationAirportId": "DFW", + "IneligibleForMoneyBackGuarantee": false, + "OriginServiceArea": "A1", + "DestinationServiceArea": "A6", + "SignatureOption": "SERVICE_DEFAULT", + "ActualRateType": "PAYOR_ACCOUNT_PACKAGE", + "RatedShipmentDetails": [ + { + "EffectiveNetDiscount": { + "Currency": "USD", + "Amount": "49.92" + }, + "ShipmentRateDetail": { + "RateType": "PAYOR_ACCOUNT_PACKAGE", + "RateScale": "1", + "PricingCode": "PACKAGE", + "RatedWeightMethod": "ACTUAL", + "DimDivisor": 0, + "FuelSurchargePercent": "6.0", + "TotalBillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "TotalBaseCharge": { + "Currency": "USD", + "Amount": "25.5" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetFreight": { + "Currency": "USD", + "Amount": "25.5" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "4.55" + }, + "TotalNetFedExCharge": { + "Currency": "USD", + "Amount": "30.05" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetCharge": { + "Currency": "USD", + "Amount": "30.05" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalDutiesAndTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetChargeWithDutiesAndTaxes": { + "Currency": "USD", + "Amount": "30.05" + }, + "Surcharges": [ + { + "SurchargeType": "DELIVERY_AREA", + "Description": "Delivery Area Surcharge Extended Commercial", + "Amount": { + "Currency": "USD", + "Amount": "2.85" + } + }, + { + "SurchargeType": "INSURED_VALUE", + "Description": "Insured value", + "Amount": { + "Currency": "USD", + "Amount": "0.0" + } + }, + { + "SurchargeType": "FUEL", + "Description": "Fuel", + "Amount": { + "Currency": "USD", + "Amount": "1.7" + } + } + ] + }, + "RatedPackages": { + "GroupNumber": 0, + "EffectiveNetDiscount": { + "Currency": "USD", + "Amount": "49.92" + }, + "PackageRateDetail": { + "RateType": "PAYOR_ACCOUNT_PACKAGE", + "RatedWeightMethod": "ACTUAL", + "BillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "BaseCharge": { + "Currency": "USD", + "Amount": "25.5" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "NetFreight": { + "Currency": "USD", + "Amount": "25.5" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "4.55" + }, + "NetFedExCharge": { + "Currency": "USD", + "Amount": "30.05" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "NetCharge": { + "Currency": "USD", + "Amount": "30.05" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "Surcharges": [ + { + "SurchargeType": "DELIVERY_AREA", + "Description": "Delivery Area Surcharge Extended Commercial", + "Amount": { + "Currency": "USD", + "Amount": "2.85" + } + }, + { + "SurchargeType": "INSURED_VALUE", + "Description": "Insured value", + "Amount": { + "Currency": "USD", + "Amount": "0.0" + } + }, + { + "SurchargeType": "FUEL", + "Description": "Fuel", + "Amount": { + "Currency": "USD", + "Amount": "1.7" + } + } + ] + } + } + }, + { + "EffectiveNetDiscount": { + "Currency": "USD", + "Amount": "49.92" + }, + "ShipmentRateDetail": { + "RateType": "RATED_ACCOUNT_PACKAGE", + "RateScale": "1", + "PricingCode": "PACKAGE", + "RatedWeightMethod": "ACTUAL", + "DimDivisor": 0, + "FuelSurchargePercent": "6.0", + "TotalBillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "TotalBaseCharge": { + "Currency": "USD", + "Amount": "25.5" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetFreight": { + "Currency": "USD", + "Amount": "25.5" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "4.55" + }, + "TotalNetFedExCharge": { + "Currency": "USD", + "Amount": "30.05" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetCharge": { + "Currency": "USD", + "Amount": "30.05" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalDutiesAndTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetChargeWithDutiesAndTaxes": { + "Currency": "USD", + "Amount": "30.05" + }, + "Surcharges": [ + { + "SurchargeType": "DELIVERY_AREA", + "Description": "Delivery Area Surcharge Extended Commercial", + "Amount": { + "Currency": "USD", + "Amount": "2.85" + } + }, + { + "SurchargeType": "INSURED_VALUE", + "Description": "Insured value", + "Amount": { + "Currency": "USD", + "Amount": "0.0" + } + }, + { + "SurchargeType": "FUEL", + "Description": "Fuel", + "Amount": { + "Currency": "USD", + "Amount": "1.7" + } + } + ] + }, + "RatedPackages": { + "GroupNumber": 0, + "EffectiveNetDiscount": { + "Currency": "USD", + "Amount": "49.92" + }, + "PackageRateDetail": { + "RateType": "RATED_ACCOUNT_PACKAGE", + "RatedWeightMethod": "ACTUAL", + "BillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "BaseCharge": { + "Currency": "USD", + "Amount": "25.5" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "NetFreight": { + "Currency": "USD", + "Amount": "25.5" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "4.55" + }, + "NetFedExCharge": { + "Currency": "USD", + "Amount": "30.05" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "NetCharge": { + "Currency": "USD", + "Amount": "30.05" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "Surcharges": [ + { + "SurchargeType": "DELIVERY_AREA", + "Description": "Delivery Area Surcharge Extended Commercial", + "Amount": { + "Currency": "USD", + "Amount": "2.85" + } + }, + { + "SurchargeType": "INSURED_VALUE", + "Description": "Insured value", + "Amount": { + "Currency": "USD", + "Amount": "0.0" + } + }, + { + "SurchargeType": "FUEL", + "Description": "Fuel", + "Amount": { + "Currency": "USD", + "Amount": "1.7" + } + } + ] + } + } + }, + { + "ShipmentRateDetail": { + "RateType": "PAYOR_LIST_PACKAGE", + "RateScale": "1574", + "RateZone": "6", + "PricingCode": "PACKAGE", + "RatedWeightMethod": "ACTUAL", + "DimDivisor": 0, + "FuelSurchargePercent": "6.0", + "TotalBillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "TotalBaseCharge": { + "Currency": "USD", + "Amount": "72.59" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetFreight": { + "Currency": "USD", + "Amount": "72.59" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "7.38" + }, + "TotalNetFedExCharge": { + "Currency": "USD", + "Amount": "79.97" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetCharge": { + "Currency": "USD", + "Amount": "79.97" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalDutiesAndTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetChargeWithDutiesAndTaxes": { + "Currency": "USD", + "Amount": "79.97" + }, + "Surcharges": [ + { + "SurchargeType": "DELIVERY_AREA", + "Description": "Delivery Area Surcharge Extended Commercial", + "Amount": { + "Currency": "USD", + "Amount": "2.85" + } + }, + { + "SurchargeType": "INSURED_VALUE", + "Description": "Insured value", + "Amount": { + "Currency": "USD", + "Amount": "0.0" + } + }, + { + "SurchargeType": "FUEL", + "Description": "Fuel", + "Amount": { + "Currency": "USD", + "Amount": "4.53" + } + } + ] + }, + "RatedPackages": { + "GroupNumber": 0, + "PackageRateDetail": { + "RateType": "PAYOR_LIST_PACKAGE", + "RatedWeightMethod": "ACTUAL", + "BillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "BaseCharge": { + "Currency": "USD", + "Amount": "72.59" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "NetFreight": { + "Currency": "USD", + "Amount": "72.59" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "7.38" + }, + "NetFedExCharge": { + "Currency": "USD", + "Amount": "79.97" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "NetCharge": { + "Currency": "USD", + "Amount": "79.97" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "Surcharges": [ + { + "SurchargeType": "DELIVERY_AREA", + "Description": "Delivery Area Surcharge Extended Commercial", + "Amount": { + "Currency": "USD", + "Amount": "2.85" + } + }, + { + "SurchargeType": "INSURED_VALUE", + "Description": "Insured value", + "Amount": { + "Currency": "USD", + "Amount": "0.0" + } + }, + { + "SurchargeType": "FUEL", + "Description": "Fuel", + "Amount": { + "Currency": "USD", + "Amount": "4.53" + } + } + ] + } + } + }, + { + "ShipmentRateDetail": { + "RateType": "RATED_LIST_PACKAGE", + "RateScale": "1574", + "RateZone": "6", + "PricingCode": "PACKAGE", + "RatedWeightMethod": "ACTUAL", + "DimDivisor": 0, + "FuelSurchargePercent": "6.0", + "TotalBillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "TotalBaseCharge": { + "Currency": "USD", + "Amount": "72.59" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetFreight": { + "Currency": "USD", + "Amount": "72.59" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "7.38" + }, + "TotalNetFedExCharge": { + "Currency": "USD", + "Amount": "79.97" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetCharge": { + "Currency": "USD", + "Amount": "79.97" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalDutiesAndTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetChargeWithDutiesAndTaxes": { + "Currency": "USD", + "Amount": "79.97" + }, + "Surcharges": [ + { + "SurchargeType": "DELIVERY_AREA", + "Description": "Delivery Area Surcharge Extended Commercial", + "Amount": { + "Currency": "USD", + "Amount": "2.85" + } + }, + { + "SurchargeType": "INSURED_VALUE", + "Description": "Insured value", + "Amount": { + "Currency": "USD", + "Amount": "0.0" + } + }, + { + "SurchargeType": "FUEL", + "Description": "Fuel", + "Amount": { + "Currency": "USD", + "Amount": "4.53" + } + } + ] + }, + "RatedPackages": { + "GroupNumber": 0, + "PackageRateDetail": { + "RateType": "RATED_LIST_PACKAGE", + "RatedWeightMethod": "ACTUAL", + "BillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "BaseCharge": { + "Currency": "USD", + "Amount": "72.59" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "NetFreight": { + "Currency": "USD", + "Amount": "72.59" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "7.38" + }, + "NetFedExCharge": { + "Currency": "USD", + "Amount": "79.97" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "NetCharge": { + "Currency": "USD", + "Amount": "79.97" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "Surcharges": [ + { + "SurchargeType": "DELIVERY_AREA", + "Description": "Delivery Area Surcharge Extended Commercial", + "Amount": { + "Currency": "USD", + "Amount": "2.85" + } + }, + { + "SurchargeType": "INSURED_VALUE", + "Description": "Insured value", + "Amount": { + "Currency": "USD", + "Amount": "0.0" + } + }, + { + "SurchargeType": "FUEL", + "Description": "Fuel", + "Amount": { + "Currency": "USD", + "Amount": "4.53" + } + } + ] + } + } + } + ] + }, + { + "ServiceType": "FEDEX_2_DAY", + "PackagingType": "YOUR_PACKAGING", + "DestinationAirportId": "DFW", + "IneligibleForMoneyBackGuarantee": false, + "OriginServiceArea": "A1", + "DestinationServiceArea": "A6", + "SignatureOption": "SERVICE_DEFAULT", + "ActualRateType": "PAYOR_ACCOUNT_PACKAGE", + "RatedShipmentDetails": [ + { + "EffectiveNetDiscount": { + "Currency": "USD", + "Amount": "0.0" + }, + "ShipmentRateDetail": { + "RateType": "PAYOR_ACCOUNT_PACKAGE", + "RateScale": "6068", + "RateZone": "6", + "PricingCode": "PACKAGE", + "RatedWeightMethod": "ACTUAL", + "DimDivisor": 0, + "FuelSurchargePercent": "6.0", + "TotalBillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "TotalBaseCharge": { + "Currency": "USD", + "Amount": "30.8" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetFreight": { + "Currency": "USD", + "Amount": "30.8" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "4.87" + }, + "TotalNetFedExCharge": { + "Currency": "USD", + "Amount": "35.67" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetCharge": { + "Currency": "USD", + "Amount": "35.67" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalDutiesAndTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetChargeWithDutiesAndTaxes": { + "Currency": "USD", + "Amount": "35.67" + }, + "Surcharges": [ + { + "SurchargeType": "DELIVERY_AREA", + "Description": "Delivery Area Surcharge Extended Commercial", + "Amount": { + "Currency": "USD", + "Amount": "2.85" + } + }, + { + "SurchargeType": "INSURED_VALUE", + "Description": "Insured value", + "Amount": { + "Currency": "USD", + "Amount": "0.0" + } + }, + { + "SurchargeType": "FUEL", + "Description": "Fuel", + "Amount": { + "Currency": "USD", + "Amount": "2.02" + } + } + ] + }, + "RatedPackages": { + "GroupNumber": 0, + "EffectiveNetDiscount": { + "Currency": "USD", + "Amount": "0.0" + }, + "PackageRateDetail": { + "RateType": "PAYOR_ACCOUNT_PACKAGE", + "RatedWeightMethod": "ACTUAL", + "BillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "BaseCharge": { + "Currency": "USD", + "Amount": "30.8" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "NetFreight": { + "Currency": "USD", + "Amount": "30.8" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "4.87" + }, + "NetFedExCharge": { + "Currency": "USD", + "Amount": "35.67" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "NetCharge": { + "Currency": "USD", + "Amount": "35.67" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "Surcharges": [ + { + "SurchargeType": "DELIVERY_AREA", + "Description": "Delivery Area Surcharge Extended Commercial", + "Amount": { + "Currency": "USD", + "Amount": "2.85" + } + }, + { + "SurchargeType": "INSURED_VALUE", + "Description": "Insured value", + "Amount": { + "Currency": "USD", + "Amount": "0.0" + } + }, + { + "SurchargeType": "FUEL", + "Description": "Fuel", + "Amount": { + "Currency": "USD", + "Amount": "2.02" + } + } + ] + } + } + }, + { + "EffectiveNetDiscount": { + "Currency": "USD", + "Amount": "0.0" + }, + "ShipmentRateDetail": { + "RateType": "RATED_ACCOUNT_PACKAGE", + "RateScale": "6068", + "RateZone": "6", + "PricingCode": "PACKAGE", + "RatedWeightMethod": "ACTUAL", + "DimDivisor": 0, + "FuelSurchargePercent": "6.0", + "TotalBillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "TotalBaseCharge": { + "Currency": "USD", + "Amount": "30.8" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetFreight": { + "Currency": "USD", + "Amount": "30.8" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "4.87" + }, + "TotalNetFedExCharge": { + "Currency": "USD", + "Amount": "35.67" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetCharge": { + "Currency": "USD", + "Amount": "35.67" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalDutiesAndTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetChargeWithDutiesAndTaxes": { + "Currency": "USD", + "Amount": "35.67" + }, + "Surcharges": [ + { + "SurchargeType": "DELIVERY_AREA", + "Description": "Delivery Area Surcharge Extended Commercial", + "Amount": { + "Currency": "USD", + "Amount": "2.85" + } + }, + { + "SurchargeType": "INSURED_VALUE", + "Description": "Insured value", + "Amount": { + "Currency": "USD", + "Amount": "0.0" + } + }, + { + "SurchargeType": "FUEL", + "Description": "Fuel", + "Amount": { + "Currency": "USD", + "Amount": "2.02" + } + } + ] + }, + "RatedPackages": { + "GroupNumber": 0, + "EffectiveNetDiscount": { + "Currency": "USD", + "Amount": "0.0" + }, + "PackageRateDetail": { + "RateType": "RATED_ACCOUNT_PACKAGE", + "RatedWeightMethod": "ACTUAL", + "BillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "BaseCharge": { + "Currency": "USD", + "Amount": "30.8" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "NetFreight": { + "Currency": "USD", + "Amount": "30.8" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "4.87" + }, + "NetFedExCharge": { + "Currency": "USD", + "Amount": "35.67" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "NetCharge": { + "Currency": "USD", + "Amount": "35.67" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "Surcharges": [ + { + "SurchargeType": "DELIVERY_AREA", + "Description": "Delivery Area Surcharge Extended Commercial", + "Amount": { + "Currency": "USD", + "Amount": "2.85" + } + }, + { + "SurchargeType": "INSURED_VALUE", + "Description": "Insured value", + "Amount": { + "Currency": "USD", + "Amount": "0.0" + } + }, + { + "SurchargeType": "FUEL", + "Description": "Fuel", + "Amount": { + "Currency": "USD", + "Amount": "2.02" + } + } + ] + } + } + }, + { + "ShipmentRateDetail": { + "RateType": "PAYOR_LIST_PACKAGE", + "RateScale": "6068", + "RateZone": "6", + "PricingCode": "PACKAGE", + "RatedWeightMethod": "ACTUAL", + "DimDivisor": 0, + "FuelSurchargePercent": "6.0", + "TotalBillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "TotalBaseCharge": { + "Currency": "USD", + "Amount": "30.8" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetFreight": { + "Currency": "USD", + "Amount": "30.8" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "4.87" + }, + "TotalNetFedExCharge": { + "Currency": "USD", + "Amount": "35.67" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetCharge": { + "Currency": "USD", + "Amount": "35.67" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalDutiesAndTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetChargeWithDutiesAndTaxes": { + "Currency": "USD", + "Amount": "35.67" + }, + "Surcharges": [ + { + "SurchargeType": "DELIVERY_AREA", + "Description": "Delivery Area Surcharge Extended Commercial", + "Amount": { + "Currency": "USD", + "Amount": "2.85" + } + }, + { + "SurchargeType": "INSURED_VALUE", + "Description": "Insured value", + "Amount": { + "Currency": "USD", + "Amount": "0.0" + } + }, + { + "SurchargeType": "FUEL", + "Description": "Fuel", + "Amount": { + "Currency": "USD", + "Amount": "2.02" + } + } + ] + }, + "RatedPackages": { + "GroupNumber": 0, + "PackageRateDetail": { + "RateType": "PAYOR_LIST_PACKAGE", + "RatedWeightMethod": "ACTUAL", + "BillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "BaseCharge": { + "Currency": "USD", + "Amount": "30.8" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "NetFreight": { + "Currency": "USD", + "Amount": "30.8" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "4.87" + }, + "NetFedExCharge": { + "Currency": "USD", + "Amount": "35.67" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "NetCharge": { + "Currency": "USD", + "Amount": "35.67" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "Surcharges": [ + { + "SurchargeType": "DELIVERY_AREA", + "Description": "Delivery Area Surcharge Extended Commercial", + "Amount": { + "Currency": "USD", + "Amount": "2.85" + } + }, + { + "SurchargeType": "INSURED_VALUE", + "Description": "Insured value", + "Amount": { + "Currency": "USD", + "Amount": "0.0" + } + }, + { + "SurchargeType": "FUEL", + "Description": "Fuel", + "Amount": { + "Currency": "USD", + "Amount": "2.02" + } + } + ] + } + } + }, + { + "ShipmentRateDetail": { + "RateType": "RATED_LIST_PACKAGE", + "RateScale": "6068", + "RateZone": "6", + "PricingCode": "PACKAGE", + "RatedWeightMethod": "ACTUAL", + "DimDivisor": 0, + "FuelSurchargePercent": "6.0", + "TotalBillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "TotalBaseCharge": { + "Currency": "USD", + "Amount": "30.8" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetFreight": { + "Currency": "USD", + "Amount": "30.8" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "4.87" + }, + "TotalNetFedExCharge": { + "Currency": "USD", + "Amount": "35.67" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetCharge": { + "Currency": "USD", + "Amount": "35.67" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalDutiesAndTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetChargeWithDutiesAndTaxes": { + "Currency": "USD", + "Amount": "35.67" + }, + "Surcharges": [ + { + "SurchargeType": "DELIVERY_AREA", + "Description": "Delivery Area Surcharge Extended Commercial", + "Amount": { + "Currency": "USD", + "Amount": "2.85" + } + }, + { + "SurchargeType": "INSURED_VALUE", + "Description": "Insured value", + "Amount": { + "Currency": "USD", + "Amount": "0.0" + } + }, + { + "SurchargeType": "FUEL", + "Description": "Fuel", + "Amount": { + "Currency": "USD", + "Amount": "2.02" + } + } + ] + }, + "RatedPackages": { + "GroupNumber": 0, + "PackageRateDetail": { + "RateType": "RATED_LIST_PACKAGE", + "RatedWeightMethod": "ACTUAL", + "BillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "BaseCharge": { + "Currency": "USD", + "Amount": "30.8" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "NetFreight": { + "Currency": "USD", + "Amount": "30.8" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "4.87" + }, + "NetFedExCharge": { + "Currency": "USD", + "Amount": "35.67" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "NetCharge": { + "Currency": "USD", + "Amount": "35.67" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "Surcharges": [ + { + "SurchargeType": "DELIVERY_AREA", + "Description": "Delivery Area Surcharge Extended Commercial", + "Amount": { + "Currency": "USD", + "Amount": "2.85" + } + }, + { + "SurchargeType": "INSURED_VALUE", + "Description": "Insured value", + "Amount": { + "Currency": "USD", + "Amount": "0.0" + } + }, + { + "SurchargeType": "FUEL", + "Description": "Fuel", + "Amount": { + "Currency": "USD", + "Amount": "2.02" + } + } + ] + } + } + } + ] + }, + { + "ServiceType": "FEDEX_EXPRESS_SAVER", + "PackagingType": "YOUR_PACKAGING", + "DestinationAirportId": "DFW", + "IneligibleForMoneyBackGuarantee": false, + "OriginServiceArea": "A1", + "DestinationServiceArea": "A6", + "SignatureOption": "SERVICE_DEFAULT", + "ActualRateType": "PAYOR_ACCOUNT_PACKAGE", + "RatedShipmentDetails": [ + { + "EffectiveNetDiscount": { + "Currency": "USD", + "Amount": "0.0" + }, + "ShipmentRateDetail": { + "RateType": "PAYOR_ACCOUNT_PACKAGE", + "RateScale": "7175", + "RateZone": "6", + "PricingCode": "PACKAGE", + "RatedWeightMethod": "ACTUAL", + "DimDivisor": 0, + "FuelSurchargePercent": "6.0", + "TotalBillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "TotalBaseCharge": { + "Currency": "USD", + "Amount": "22.37" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetFreight": { + "Currency": "USD", + "Amount": "22.37" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "4.36" + }, + "TotalNetFedExCharge": { + "Currency": "USD", + "Amount": "26.73" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetCharge": { + "Currency": "USD", + "Amount": "26.73" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalDutiesAndTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetChargeWithDutiesAndTaxes": { + "Currency": "USD", + "Amount": "26.73" + }, + "Surcharges": [ + { + "SurchargeType": "DELIVERY_AREA", + "Description": "Delivery Area Surcharge Extended Commercial", + "Amount": { + "Currency": "USD", + "Amount": "2.85" + } + }, + { + "SurchargeType": "INSURED_VALUE", + "Description": "Insured value", + "Amount": { + "Currency": "USD", + "Amount": "0.0" + } + }, + { + "SurchargeType": "FUEL", + "Description": "Fuel", + "Amount": { + "Currency": "USD", + "Amount": "1.51" + } + } + ] + }, + "RatedPackages": { + "GroupNumber": 0, + "EffectiveNetDiscount": { + "Currency": "USD", + "Amount": "0.0" + }, + "PackageRateDetail": { + "RateType": "PAYOR_ACCOUNT_PACKAGE", + "RatedWeightMethod": "ACTUAL", + "BillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "BaseCharge": { + "Currency": "USD", + "Amount": "22.37" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "NetFreight": { + "Currency": "USD", + "Amount": "22.37" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "4.36" + }, + "NetFedExCharge": { + "Currency": "USD", + "Amount": "26.73" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "NetCharge": { + "Currency": "USD", + "Amount": "26.73" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "Surcharges": [ + { + "SurchargeType": "DELIVERY_AREA", + "Description": "Delivery Area Surcharge Extended Commercial", + "Amount": { + "Currency": "USD", + "Amount": "2.85" + } + }, + { + "SurchargeType": "INSURED_VALUE", + "Description": "Insured value", + "Amount": { + "Currency": "USD", + "Amount": "0.0" + } + }, + { + "SurchargeType": "FUEL", + "Description": "Fuel", + "Amount": { + "Currency": "USD", + "Amount": "1.51" + } + } + ] + } + } + }, + { + "EffectiveNetDiscount": { + "Currency": "USD", + "Amount": "0.0" + }, + "ShipmentRateDetail": { + "RateType": "RATED_ACCOUNT_PACKAGE", + "RateScale": "7175", + "RateZone": "6", + "PricingCode": "PACKAGE", + "RatedWeightMethod": "ACTUAL", + "DimDivisor": 0, + "FuelSurchargePercent": "6.0", + "TotalBillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "TotalBaseCharge": { + "Currency": "USD", + "Amount": "22.37" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetFreight": { + "Currency": "USD", + "Amount": "22.37" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "4.36" + }, + "TotalNetFedExCharge": { + "Currency": "USD", + "Amount": "26.73" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetCharge": { + "Currency": "USD", + "Amount": "26.73" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalDutiesAndTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetChargeWithDutiesAndTaxes": { + "Currency": "USD", + "Amount": "26.73" + }, + "Surcharges": [ + { + "SurchargeType": "DELIVERY_AREA", + "Description": "Delivery Area Surcharge Extended Commercial", + "Amount": { + "Currency": "USD", + "Amount": "2.85" + } + }, + { + "SurchargeType": "INSURED_VALUE", + "Description": "Insured value", + "Amount": { + "Currency": "USD", + "Amount": "0.0" + } + }, + { + "SurchargeType": "FUEL", + "Description": "Fuel", + "Amount": { + "Currency": "USD", + "Amount": "1.51" + } + } + ] + }, + "RatedPackages": { + "GroupNumber": 0, + "EffectiveNetDiscount": { + "Currency": "USD", + "Amount": "0.0" + }, + "PackageRateDetail": { + "RateType": "RATED_ACCOUNT_PACKAGE", + "RatedWeightMethod": "ACTUAL", + "BillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "BaseCharge": { + "Currency": "USD", + "Amount": "22.37" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "NetFreight": { + "Currency": "USD", + "Amount": "22.37" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "4.36" + }, + "NetFedExCharge": { + "Currency": "USD", + "Amount": "26.73" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "NetCharge": { + "Currency": "USD", + "Amount": "26.73" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "Surcharges": [ + { + "SurchargeType": "DELIVERY_AREA", + "Description": "Delivery Area Surcharge Extended Commercial", + "Amount": { + "Currency": "USD", + "Amount": "2.85" + } + }, + { + "SurchargeType": "INSURED_VALUE", + "Description": "Insured value", + "Amount": { + "Currency": "USD", + "Amount": "0.0" + } + }, + { + "SurchargeType": "FUEL", + "Description": "Fuel", + "Amount": { + "Currency": "USD", + "Amount": "1.51" + } + } + ] + } + } + }, + { + "ShipmentRateDetail": { + "RateType": "PAYOR_LIST_PACKAGE", + "RateScale": "7175", + "RateZone": "6", + "PricingCode": "PACKAGE", + "RatedWeightMethod": "ACTUAL", + "DimDivisor": 0, + "FuelSurchargePercent": "6.0", + "TotalBillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "TotalBaseCharge": { + "Currency": "USD", + "Amount": "22.37" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetFreight": { + "Currency": "USD", + "Amount": "22.37" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "4.36" + }, + "TotalNetFedExCharge": { + "Currency": "USD", + "Amount": "26.73" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetCharge": { + "Currency": "USD", + "Amount": "26.73" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalDutiesAndTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetChargeWithDutiesAndTaxes": { + "Currency": "USD", + "Amount": "26.73" + }, + "Surcharges": [ + { + "SurchargeType": "DELIVERY_AREA", + "Description": "Delivery Area Surcharge Extended Commercial", + "Amount": { + "Currency": "USD", + "Amount": "2.85" + } + }, + { + "SurchargeType": "INSURED_VALUE", + "Description": "Insured value", + "Amount": { + "Currency": "USD", + "Amount": "0.0" + } + }, + { + "SurchargeType": "FUEL", + "Description": "Fuel", + "Amount": { + "Currency": "USD", + "Amount": "1.51" + } + } + ] + }, + "RatedPackages": { + "GroupNumber": 0, + "PackageRateDetail": { + "RateType": "PAYOR_LIST_PACKAGE", + "RatedWeightMethod": "ACTUAL", + "BillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "BaseCharge": { + "Currency": "USD", + "Amount": "22.37" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "NetFreight": { + "Currency": "USD", + "Amount": "22.37" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "4.36" + }, + "NetFedExCharge": { + "Currency": "USD", + "Amount": "26.73" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "NetCharge": { + "Currency": "USD", + "Amount": "26.73" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "Surcharges": [ + { + "SurchargeType": "DELIVERY_AREA", + "Description": "Delivery Area Surcharge Extended Commercial", + "Amount": { + "Currency": "USD", + "Amount": "2.85" + } + }, + { + "SurchargeType": "INSURED_VALUE", + "Description": "Insured value", + "Amount": { + "Currency": "USD", + "Amount": "0.0" + } + }, + { + "SurchargeType": "FUEL", + "Description": "Fuel", + "Amount": { + "Currency": "USD", + "Amount": "1.51" + } + } + ] + } + } + }, + { + "ShipmentRateDetail": { + "RateType": "RATED_LIST_PACKAGE", + "RateScale": "7175", + "RateZone": "6", + "PricingCode": "PACKAGE", + "RatedWeightMethod": "ACTUAL", + "DimDivisor": 0, + "FuelSurchargePercent": "6.0", + "TotalBillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "TotalBaseCharge": { + "Currency": "USD", + "Amount": "22.37" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetFreight": { + "Currency": "USD", + "Amount": "22.37" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "4.36" + }, + "TotalNetFedExCharge": { + "Currency": "USD", + "Amount": "26.73" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetCharge": { + "Currency": "USD", + "Amount": "26.73" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalDutiesAndTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetChargeWithDutiesAndTaxes": { + "Currency": "USD", + "Amount": "26.73" + }, + "Surcharges": [ + { + "SurchargeType": "DELIVERY_AREA", + "Description": "Delivery Area Surcharge Extended Commercial", + "Amount": { + "Currency": "USD", + "Amount": "2.85" + } + }, + { + "SurchargeType": "INSURED_VALUE", + "Description": "Insured value", + "Amount": { + "Currency": "USD", + "Amount": "0.0" + } + }, + { + "SurchargeType": "FUEL", + "Description": "Fuel", + "Amount": { + "Currency": "USD", + "Amount": "1.51" + } + } + ] + }, + "RatedPackages": { + "GroupNumber": 0, + "PackageRateDetail": { + "RateType": "RATED_LIST_PACKAGE", + "RatedWeightMethod": "ACTUAL", + "BillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "BaseCharge": { + "Currency": "USD", + "Amount": "22.37" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "NetFreight": { + "Currency": "USD", + "Amount": "22.37" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "4.36" + }, + "NetFedExCharge": { + "Currency": "USD", + "Amount": "26.73" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "NetCharge": { + "Currency": "USD", + "Amount": "26.73" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "Surcharges": [ + { + "SurchargeType": "DELIVERY_AREA", + "Description": "Delivery Area Surcharge Extended Commercial", + "Amount": { + "Currency": "USD", + "Amount": "2.85" + } + }, + { + "SurchargeType": "INSURED_VALUE", + "Description": "Insured value", + "Amount": { + "Currency": "USD", + "Amount": "0.0" + } + }, + { + "SurchargeType": "FUEL", + "Description": "Fuel", + "Amount": { + "Currency": "USD", + "Amount": "1.51" + } + } + ] + } + } + } + ] + }, + { + "ServiceType": "FEDEX_GROUND", + "PackagingType": "YOUR_PACKAGING", + "DestinationAirportId": "DFW", + "IneligibleForMoneyBackGuarantee": false, + "SignatureOption": "SERVICE_DEFAULT", + "ActualRateType": "PAYOR_ACCOUNT_PACKAGE", + "RatedShipmentDetails": [ + { + "EffectiveNetDiscount": { + "Currency": "USD", + "Amount": "0.0" + }, + "ShipmentRateDetail": { + "RateType": "PAYOR_ACCOUNT_PACKAGE", + "RateZone": "6", + "RatedWeightMethod": "ACTUAL", + "DimDivisor": 0, + "FuelSurchargePercent": "7.0", + "TotalBillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "TotalBaseCharge": { + "Currency": "USD", + "Amount": "10.82" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetFreight": { + "Currency": "USD", + "Amount": "10.82" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "3.65" + }, + "TotalNetFedExCharge": { + "Currency": "USD", + "Amount": "14.47" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetCharge": { + "Currency": "USD", + "Amount": "14.47" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalDutiesAndTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetChargeWithDutiesAndTaxes": { + "Currency": "USD", + "Amount": "14.47" + }, + "Surcharges": [ + { + "SurchargeType": "INSURED_VALUE", + "Level": "PACKAGE", + "Description": "Insured value", + "Amount": { + "Currency": "USD", + "Amount": "0.0" + } + }, + { + "SurchargeType": "DELIVERY_AREA", + "Level": "PACKAGE", + "Description": "Delivery Area Surcharge Extended Commercial", + "Amount": { + "Currency": "USD", + "Amount": "2.7" + } + }, + { + "SurchargeType": "FUEL", + "Level": "PACKAGE", + "Description": "FedEx Ground Fuel", + "Amount": { + "Currency": "USD", + "Amount": "0.95" + } + } + ] + }, + "RatedPackages": { + "GroupNumber": 0, + "EffectiveNetDiscount": { + "Currency": "USD", + "Amount": "0.0" + }, + "PackageRateDetail": { + "RateType": "PAYOR_ACCOUNT_PACKAGE", + "RatedWeightMethod": "ACTUAL", + "BillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "BaseCharge": { + "Currency": "USD", + "Amount": "10.82" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "NetFreight": { + "Currency": "USD", + "Amount": "10.82" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "3.65" + }, + "NetFedExCharge": { + "Currency": "USD", + "Amount": "14.47" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "NetCharge": { + "Currency": "USD", + "Amount": "14.47" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "Surcharges": [ + { + "SurchargeType": "INSURED_VALUE", + "Level": "PACKAGE", + "Description": "Insured value", + "Amount": { + "Currency": "USD", + "Amount": "0.0" + } + }, + { + "SurchargeType": "DELIVERY_AREA", + "Level": "PACKAGE", + "Description": "Delivery Area Surcharge Extended Commercial", + "Amount": { + "Currency": "USD", + "Amount": "2.7" + } + }, + { + "SurchargeType": "FUEL", + "Level": "PACKAGE", + "Description": "FedEx Ground Fuel", + "Amount": { + "Currency": "USD", + "Amount": "0.95" + } + } + ] + } + } + }, + { + "ShipmentRateDetail": { + "RateType": "PAYOR_LIST_PACKAGE", + "RateZone": "6", + "RatedWeightMethod": "ACTUAL", + "DimDivisor": 0, + "FuelSurchargePercent": "7.0", + "TotalBillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "TotalBaseCharge": { + "Currency": "USD", + "Amount": "10.82" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetFreight": { + "Currency": "USD", + "Amount": "10.82" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "3.65" + }, + "TotalNetFedExCharge": { + "Currency": "USD", + "Amount": "14.47" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetCharge": { + "Currency": "USD", + "Amount": "14.47" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalDutiesAndTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetChargeWithDutiesAndTaxes": { + "Currency": "USD", + "Amount": "14.47" + }, + "Surcharges": [ + { + "SurchargeType": "INSURED_VALUE", + "Level": "PACKAGE", + "Description": "Insured value", + "Amount": { + "Currency": "USD", + "Amount": "0.0" + } + }, + { + "SurchargeType": "DELIVERY_AREA", + "Level": "PACKAGE", + "Description": "Delivery Area Surcharge Extended Commercial", + "Amount": { + "Currency": "USD", + "Amount": "2.7" + } + }, + { + "SurchargeType": "FUEL", + "Level": "PACKAGE", + "Description": "FedEx Ground Fuel", + "Amount": { + "Currency": "USD", + "Amount": "0.95" + } + } + ] + }, + "RatedPackages": { + "GroupNumber": 0, + "PackageRateDetail": { + "RateType": "PAYOR_LIST_PACKAGE", + "RatedWeightMethod": "ACTUAL", + "BillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "BaseCharge": { + "Currency": "USD", + "Amount": "10.82" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "NetFreight": { + "Currency": "USD", + "Amount": "10.82" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "3.65" + }, + "NetFedExCharge": { + "Currency": "USD", + "Amount": "14.47" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "NetCharge": { + "Currency": "USD", + "Amount": "14.47" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "Surcharges": [ + { + "SurchargeType": "INSURED_VALUE", + "Level": "PACKAGE", + "Description": "Insured value", + "Amount": { + "Currency": "USD", + "Amount": "0.0" + } + }, + { + "SurchargeType": "DELIVERY_AREA", + "Level": "PACKAGE", + "Description": "Delivery Area Surcharge Extended Commercial", + "Amount": { + "Currency": "USD", + "Amount": "2.7" + } + }, + { + "SurchargeType": "FUEL", + "Level": "PACKAGE", + "Description": "FedEx Ground Fuel", + "Amount": { + "Currency": "USD", + "Amount": "0.95" + } + } + ] + } + } + } + ] + } + ] +} \ No newline at end of file diff --git a/dev/tests/api-functional/_files/Magento/TestModuleFedex/_files/mock_response_smart_post_ca.json b/dev/tests/api-functional/_files/Magento/TestModuleFedex/_files/mock_response_smart_post_ca.json new file mode 100644 index 0000000000000..e26f1e485542f --- /dev/null +++ b/dev/tests/api-functional/_files/Magento/TestModuleFedex/_files/mock_response_smart_post_ca.json @@ -0,0 +1,912 @@ +{ + "HighestSeverity": "NOTE", + "Notifications": [ + { + "Severity": "NOTE", + "Source": "crs", + "Code": "886", + "Message": "Money Back Guarantee is not eligible for this pick up\/delivery postal\/zip code. FDXG", + "LocalizedMessage": "Money Back Guarantee is not eligible for this pick up\/delivery postal\/zip code. FDXG", + "MessageParameters": { + "Id": "OPERATING_COMPANY", + "Value": "FDXG" + } + }, + { + "Severity": "NOTE", + "Source": "crs", + "Code": "819", + "Message": "The origin state\/province code has been changed. ", + "LocalizedMessage": "The origin state\/province code has been changed. " + }, + { + "Severity": "NOTE", + "Source": "crs", + "Code": "820", + "Message": "The destination state\/province code has been changed. ", + "LocalizedMessage": "The destination state\/province code has been changed. " + } + ], + "Version": { + "ServiceId": "crs", + "Major": 10, + "Intermediate": 0, + "Minor": 0 + }, + "RateReplyDetails": [ + { + "ServiceType": "INTERNATIONAL_PRIORITY", + "PackagingType": "YOUR_PACKAGING", + "DestinationAirportId": "YYZ", + "IneligibleForMoneyBackGuarantee": false, + "OriginServiceArea": "A1", + "DestinationServiceArea": "AM", + "SignatureOption": "SERVICE_DEFAULT", + "ActualRateType": "PAYOR_ACCOUNT_SHIPMENT", + "RatedShipmentDetails": [ + { + "EffectiveNetDiscount": { + "Currency": "USD", + "Amount": "0.0" + }, + "ShipmentRateDetail": { + "RateType": "PAYOR_ACCOUNT_SHIPMENT", + "RateScale": "0000000", + "RateZone": "US001O", + "PricingCode": "ACTUAL", + "RatedWeightMethod": "ACTUAL", + "CurrencyExchangeRate": { + "FromCurrency": "USD", + "IntoCurrency": "USD", + "Rate": "1.0" + }, + "DimDivisor": 0, + "FuelSurchargePercent": "5.0", + "TotalBillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "TotalBaseCharge": { + "Currency": "USD", + "Amount": "92.99" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetFreight": { + "Currency": "USD", + "Amount": "92.99" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "4.65" + }, + "TotalNetFedExCharge": { + "Currency": "USD", + "Amount": "97.64" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetCharge": { + "Currency": "USD", + "Amount": "97.64" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalDutiesAndTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetChargeWithDutiesAndTaxes": { + "Currency": "USD", + "Amount": "97.64" + }, + "Surcharges": { + "SurchargeType": "FUEL", + "Description": "Fuel", + "Amount": { + "Currency": "USD", + "Amount": "4.65" + } + } + } + }, + { + "EffectiveNetDiscount": { + "Currency": "USD", + "Amount": "0.0" + }, + "ShipmentRateDetail": { + "RateType": "RATED_ACCOUNT_SHIPMENT", + "RateScale": "0000000", + "RateZone": "US001O", + "PricingCode": "ACTUAL", + "RatedWeightMethod": "ACTUAL", + "CurrencyExchangeRate": { + "FromCurrency": "USD", + "IntoCurrency": "USD", + "Rate": "1.0" + }, + "DimDivisor": 0, + "FuelSurchargePercent": "5.0", + "TotalBillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "TotalBaseCharge": { + "Currency": "USD", + "Amount": "92.99" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetFreight": { + "Currency": "USD", + "Amount": "92.99" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "4.65" + }, + "TotalNetFedExCharge": { + "Currency": "USD", + "Amount": "97.64" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetCharge": { + "Currency": "USD", + "Amount": "97.64" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalDutiesAndTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetChargeWithDutiesAndTaxes": { + "Currency": "USD", + "Amount": "97.64" + }, + "Surcharges": { + "SurchargeType": "FUEL", + "Description": "Fuel", + "Amount": { + "Currency": "USD", + "Amount": "4.65" + } + } + } + }, + { + "ShipmentRateDetail": { + "RateType": "PAYOR_LIST_SHIPMENT", + "RateScale": "0000000", + "RateZone": "US001O", + "PricingCode": "ACTUAL", + "RatedWeightMethod": "ACTUAL", + "CurrencyExchangeRate": { + "FromCurrency": "USD", + "IntoCurrency": "USD", + "Rate": "1.0" + }, + "DimDivisor": 0, + "FuelSurchargePercent": "5.0", + "TotalBillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "TotalBaseCharge": { + "Currency": "USD", + "Amount": "92.99" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetFreight": { + "Currency": "USD", + "Amount": "92.99" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "4.65" + }, + "TotalNetFedExCharge": { + "Currency": "USD", + "Amount": "97.64" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetCharge": { + "Currency": "USD", + "Amount": "97.64" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalDutiesAndTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetChargeWithDutiesAndTaxes": { + "Currency": "USD", + "Amount": "97.64" + }, + "Surcharges": { + "SurchargeType": "FUEL", + "Description": "Fuel", + "Amount": { + "Currency": "USD", + "Amount": "4.65" + } + } + } + }, + { + "ShipmentRateDetail": { + "RateType": "RATED_LIST_SHIPMENT", + "RateScale": "0000000", + "RateZone": "US001O", + "PricingCode": "ACTUAL", + "RatedWeightMethod": "ACTUAL", + "CurrencyExchangeRate": { + "FromCurrency": "USD", + "IntoCurrency": "USD", + "Rate": "1.0" + }, + "DimDivisor": 0, + "FuelSurchargePercent": "5.0", + "TotalBillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "TotalBaseCharge": { + "Currency": "USD", + "Amount": "92.99" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetFreight": { + "Currency": "USD", + "Amount": "92.99" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "4.65" + }, + "TotalNetFedExCharge": { + "Currency": "USD", + "Amount": "97.64" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetCharge": { + "Currency": "USD", + "Amount": "97.64" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalDutiesAndTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetChargeWithDutiesAndTaxes": { + "Currency": "USD", + "Amount": "97.64" + }, + "Surcharges": { + "SurchargeType": "FUEL", + "Description": "Fuel", + "Amount": { + "Currency": "USD", + "Amount": "4.65" + } + } + } + } + ] + }, + { + "ServiceType": "INTERNATIONAL_ECONOMY", + "PackagingType": "YOUR_PACKAGING", + "DestinationAirportId": "YYZ", + "IneligibleForMoneyBackGuarantee": false, + "OriginServiceArea": "A1", + "DestinationServiceArea": "AM", + "SignatureOption": "SERVICE_DEFAULT", + "ActualRateType": "PAYOR_ACCOUNT_SHIPMENT", + "RatedShipmentDetails": [ + { + "EffectiveNetDiscount": { + "Currency": "USD", + "Amount": "0.0" + }, + "ShipmentRateDetail": { + "RateType": "PAYOR_ACCOUNT_SHIPMENT", + "RateScale": "0000000", + "RateZone": "US001O", + "PricingCode": "ACTUAL", + "RatedWeightMethod": "ACTUAL", + "CurrencyExchangeRate": { + "FromCurrency": "USD", + "IntoCurrency": "USD", + "Rate": "1.0" + }, + "DimDivisor": 0, + "FuelSurchargePercent": "5.0", + "TotalBillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "TotalBaseCharge": { + "Currency": "USD", + "Amount": "83.18" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetFreight": { + "Currency": "USD", + "Amount": "83.18" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "4.16" + }, + "TotalNetFedExCharge": { + "Currency": "USD", + "Amount": "87.34" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetCharge": { + "Currency": "USD", + "Amount": "87.34" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalDutiesAndTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetChargeWithDutiesAndTaxes": { + "Currency": "USD", + "Amount": "87.34" + }, + "Surcharges": { + "SurchargeType": "FUEL", + "Description": "Fuel", + "Amount": { + "Currency": "USD", + "Amount": "4.16" + } + } + } + }, + { + "EffectiveNetDiscount": { + "Currency": "USD", + "Amount": "0.0" + }, + "ShipmentRateDetail": { + "RateType": "RATED_ACCOUNT_SHIPMENT", + "RateScale": "0000000", + "RateZone": "US001O", + "PricingCode": "ACTUAL", + "RatedWeightMethod": "ACTUAL", + "CurrencyExchangeRate": { + "FromCurrency": "USD", + "IntoCurrency": "USD", + "Rate": "1.0" + }, + "DimDivisor": 0, + "FuelSurchargePercent": "5.0", + "TotalBillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "TotalBaseCharge": { + "Currency": "USD", + "Amount": "83.18" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetFreight": { + "Currency": "USD", + "Amount": "83.18" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "4.16" + }, + "TotalNetFedExCharge": { + "Currency": "USD", + "Amount": "87.34" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetCharge": { + "Currency": "USD", + "Amount": "87.34" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalDutiesAndTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetChargeWithDutiesAndTaxes": { + "Currency": "USD", + "Amount": "87.34" + }, + "Surcharges": { + "SurchargeType": "FUEL", + "Description": "Fuel", + "Amount": { + "Currency": "USD", + "Amount": "4.16" + } + } + } + }, + { + "ShipmentRateDetail": { + "RateType": "PAYOR_LIST_SHIPMENT", + "RateScale": "0000000", + "RateZone": "US001O", + "PricingCode": "ACTUAL", + "RatedWeightMethod": "ACTUAL", + "CurrencyExchangeRate": { + "FromCurrency": "USD", + "IntoCurrency": "USD", + "Rate": "1.0" + }, + "DimDivisor": 0, + "FuelSurchargePercent": "5.0", + "TotalBillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "TotalBaseCharge": { + "Currency": "USD", + "Amount": "83.18" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetFreight": { + "Currency": "USD", + "Amount": "83.18" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "4.16" + }, + "TotalNetFedExCharge": { + "Currency": "USD", + "Amount": "87.34" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetCharge": { + "Currency": "USD", + "Amount": "87.34" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalDutiesAndTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetChargeWithDutiesAndTaxes": { + "Currency": "USD", + "Amount": "87.34" + }, + "Surcharges": { + "SurchargeType": "FUEL", + "Description": "Fuel", + "Amount": { + "Currency": "USD", + "Amount": "4.16" + } + } + } + }, + { + "ShipmentRateDetail": { + "RateType": "RATED_LIST_SHIPMENT", + "RateScale": "0000000", + "RateZone": "US001O", + "PricingCode": "ACTUAL", + "RatedWeightMethod": "ACTUAL", + "CurrencyExchangeRate": { + "FromCurrency": "USD", + "IntoCurrency": "USD", + "Rate": "1.0" + }, + "DimDivisor": 0, + "FuelSurchargePercent": "5.0", + "TotalBillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "TotalBaseCharge": { + "Currency": "USD", + "Amount": "83.18" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetFreight": { + "Currency": "USD", + "Amount": "83.18" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "4.16" + }, + "TotalNetFedExCharge": { + "Currency": "USD", + "Amount": "87.34" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetCharge": { + "Currency": "USD", + "Amount": "87.34" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalDutiesAndTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetChargeWithDutiesAndTaxes": { + "Currency": "USD", + "Amount": "87.34" + }, + "Surcharges": { + "SurchargeType": "FUEL", + "Description": "Fuel", + "Amount": { + "Currency": "USD", + "Amount": "4.16" + } + } + } + } + ] + }, + { + "ServiceType": "FEDEX_GROUND", + "PackagingType": "YOUR_PACKAGING", + "DestinationAirportId": "YYZ", + "IneligibleForMoneyBackGuarantee": true, + "SignatureOption": "SERVICE_DEFAULT", + "ActualRateType": "PAYOR_ACCOUNT_PACKAGE", + "RatedShipmentDetails": [ + { + "EffectiveNetDiscount": { + "Currency": "USD", + "Amount": "0.0" + }, + "ShipmentRateDetail": { + "RateType": "PAYOR_ACCOUNT_PACKAGE", + "RateZone": "51", + "RatedWeightMethod": "ACTUAL", + "DimDivisor": 0, + "FuelSurchargePercent": "7.0", + "TotalBillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "TotalBaseCharge": { + "Currency": "USD", + "Amount": "22.73" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetFreight": { + "Currency": "USD", + "Amount": "22.73" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "1.59" + }, + "TotalNetFedExCharge": { + "Currency": "USD", + "Amount": "24.32" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetCharge": { + "Currency": "USD", + "Amount": "24.32" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalDutiesAndTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetChargeWithDutiesAndTaxes": { + "Currency": "USD", + "Amount": "24.32" + }, + "Surcharges": [ + { + "SurchargeType": "INSURED_VALUE", + "Level": "PACKAGE", + "Description": "Insured value", + "Amount": { + "Currency": "USD", + "Amount": "0.0" + } + }, + { + "SurchargeType": "FUEL", + "Level": "PACKAGE", + "Description": "FedEx Ground Fuel", + "Amount": { + "Currency": "USD", + "Amount": "1.59" + } + } + ] + }, + "RatedPackages": { + "GroupNumber": 0, + "EffectiveNetDiscount": { + "Currency": "USD", + "Amount": "0.0" + }, + "PackageRateDetail": { + "RateType": "PAYOR_ACCOUNT_PACKAGE", + "RatedWeightMethod": "ACTUAL", + "BillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "BaseCharge": { + "Currency": "USD", + "Amount": "22.73" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "NetFreight": { + "Currency": "USD", + "Amount": "22.73" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "1.59" + }, + "NetFedExCharge": { + "Currency": "USD", + "Amount": "24.32" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "NetCharge": { + "Currency": "USD", + "Amount": "24.32" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "Surcharges": [ + { + "SurchargeType": "INSURED_VALUE", + "Level": "PACKAGE", + "Description": "Insured value", + "Amount": { + "Currency": "USD", + "Amount": "0.0" + } + }, + { + "SurchargeType": "FUEL", + "Level": "PACKAGE", + "Description": "FedEx Ground Fuel", + "Amount": { + "Currency": "USD", + "Amount": "1.59" + } + } + ] + } + } + }, + { + "ShipmentRateDetail": { + "RateType": "PAYOR_LIST_PACKAGE", + "RateZone": "51", + "RatedWeightMethod": "ACTUAL", + "DimDivisor": 0, + "FuelSurchargePercent": "7.0", + "TotalBillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "TotalBaseCharge": { + "Currency": "USD", + "Amount": "22.73" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetFreight": { + "Currency": "USD", + "Amount": "22.73" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "1.59" + }, + "TotalNetFedExCharge": { + "Currency": "USD", + "Amount": "24.32" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetCharge": { + "Currency": "USD", + "Amount": "24.32" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalDutiesAndTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetChargeWithDutiesAndTaxes": { + "Currency": "USD", + "Amount": "24.32" + }, + "Surcharges": [ + { + "SurchargeType": "INSURED_VALUE", + "Level": "PACKAGE", + "Description": "Insured value", + "Amount": { + "Currency": "USD", + "Amount": "0.0" + } + }, + { + "SurchargeType": "FUEL", + "Level": "PACKAGE", + "Description": "FedEx Ground Fuel", + "Amount": { + "Currency": "USD", + "Amount": "1.59" + } + } + ] + }, + "RatedPackages": { + "GroupNumber": 0, + "PackageRateDetail": { + "RateType": "PAYOR_LIST_PACKAGE", + "RatedWeightMethod": "ACTUAL", + "BillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "BaseCharge": { + "Currency": "USD", + "Amount": "22.73" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "NetFreight": { + "Currency": "USD", + "Amount": "22.73" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "1.59" + }, + "NetFedExCharge": { + "Currency": "USD", + "Amount": "24.32" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "NetCharge": { + "Currency": "USD", + "Amount": "24.32" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "Surcharges": [ + { + "SurchargeType": "INSURED_VALUE", + "Level": "PACKAGE", + "Description": "Insured value", + "Amount": { + "Currency": "USD", + "Amount": "0.0" + } + }, + { + "SurchargeType": "FUEL", + "Level": "PACKAGE", + "Description": "FedEx Ground Fuel", + "Amount": { + "Currency": "USD", + "Amount": "1.59" + } + } + ] + } + } + } + ] + } + ] +} \ No newline at end of file diff --git a/dev/tests/api-functional/_files/Magento/TestModuleFedex/_files/mock_response_smart_post_us.json b/dev/tests/api-functional/_files/Magento/TestModuleFedex/_files/mock_response_smart_post_us.json new file mode 100644 index 0000000000000..2670f2be8b363 --- /dev/null +++ b/dev/tests/api-functional/_files/Magento/TestModuleFedex/_files/mock_response_smart_post_us.json @@ -0,0 +1,305 @@ +{ + "HighestSeverity": "SUCCESS", + "Notifications": { + "Severity": "SUCCESS", + "Source": "crs", + "Code": "0", + "Message": "Request was successfully processed. ", + "LocalizedMessage": "Request was successfully processed. " + }, + "Version": { + "ServiceId": "crs", + "Major": 10, + "Intermediate": 0, + "Minor": 0 + }, + "RateReplyDetails": { + "ServiceType": "SMART_POST", + "PackagingType": "YOUR_PACKAGING", + "IneligibleForMoneyBackGuarantee": false, + "SignatureOption": "SERVICE_DEFAULT", + "ActualRateType": "PAYOR_ACCOUNT_PACKAGE", + "RatedShipmentDetails": [ + { + "EffectiveNetDiscount": { + "Currency": "USD", + "Amount": "1.91" + }, + "ShipmentRateDetail": { + "RateType": "PAYOR_ACCOUNT_PACKAGE", + "RateZone": "6", + "RatedWeightMethod": "ACTUAL", + "DimDivisor": 0, + "FuelSurchargePercent": "7.0", + "TotalBillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "TotalBaseCharge": { + "Currency": "USD", + "Amount": "9.49" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetFreight": { + "Currency": "USD", + "Amount": "9.49" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "2.27" + }, + "TotalNetFedExCharge": { + "Currency": "USD", + "Amount": "11.76" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetCharge": { + "Currency": "USD", + "Amount": "11.76" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalDutiesAndTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetChargeWithDutiesAndTaxes": { + "Currency": "USD", + "Amount": "11.76" + }, + "Surcharges": [ + { + "SurchargeType": "DELIVERY_AREA", + "Level": "PACKAGE", + "Description": "Delivery Area Surcharge Extended", + "Amount": { + "Currency": "USD", + "Amount": "1.5" + } + }, + { + "SurchargeType": "FUEL", + "Level": "PACKAGE", + "Description": "SmartPost Fuel", + "Amount": { + "Currency": "USD", + "Amount": "0.77" + } + } + ] + }, + "RatedPackages": { + "GroupNumber": 0, + "EffectiveNetDiscount": { + "Currency": "USD", + "Amount": "1.91" + }, + "PackageRateDetail": { + "RateType": "PAYOR_ACCOUNT_PACKAGE", + "RatedWeightMethod": "ACTUAL", + "BillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "BaseCharge": { + "Currency": "USD", + "Amount": "9.49" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "NetFreight": { + "Currency": "USD", + "Amount": "9.49" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "2.27" + }, + "NetFedExCharge": { + "Currency": "USD", + "Amount": "11.76" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "NetCharge": { + "Currency": "USD", + "Amount": "11.76" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "Surcharges": [ + { + "SurchargeType": "DELIVERY_AREA", + "Level": "PACKAGE", + "Description": "Delivery Area Surcharge Extended", + "Amount": { + "Currency": "USD", + "Amount": "1.5" + } + }, + { + "SurchargeType": "FUEL", + "Level": "PACKAGE", + "Description": "SmartPost Fuel", + "Amount": { + "Currency": "USD", + "Amount": "0.77" + } + } + ] + } + } + }, + { + "ShipmentRateDetail": { + "RateType": "PAYOR_LIST_PACKAGE", + "RateZone": "6", + "RatedWeightMethod": "ACTUAL", + "DimDivisor": 0, + "FuelSurchargePercent": "7.0", + "TotalBillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "TotalBaseCharge": { + "Currency": "USD", + "Amount": "10.82" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetFreight": { + "Currency": "USD", + "Amount": "10.82" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "2.85" + }, + "TotalNetFedExCharge": { + "Currency": "USD", + "Amount": "13.67" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetCharge": { + "Currency": "USD", + "Amount": "13.67" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalDutiesAndTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "TotalNetChargeWithDutiesAndTaxes": { + "Currency": "USD", + "Amount": "13.67" + }, + "Surcharges": [ + { + "SurchargeType": "DELIVERY_AREA", + "Level": "PACKAGE", + "Description": "Delivery Area Surcharge Extended", + "Amount": { + "Currency": "USD", + "Amount": "1.95" + } + }, + { + "SurchargeType": "FUEL", + "Level": "PACKAGE", + "Description": "SmartPost Fuel", + "Amount": { + "Currency": "USD", + "Amount": "0.9" + } + } + ] + }, + "RatedPackages": { + "GroupNumber": 0, + "PackageRateDetail": { + "RateType": "PAYOR_LIST_PACKAGE", + "RatedWeightMethod": "ACTUAL", + "BillingWeight": { + "Units": "LB", + "Value": "2.0" + }, + "BaseCharge": { + "Currency": "USD", + "Amount": "10.82" + }, + "TotalFreightDiscounts": { + "Currency": "USD", + "Amount": "0.0" + }, + "NetFreight": { + "Currency": "USD", + "Amount": "10.82" + }, + "TotalSurcharges": { + "Currency": "USD", + "Amount": "2.85" + }, + "NetFedExCharge": { + "Currency": "USD", + "Amount": "13.67" + }, + "TotalTaxes": { + "Currency": "USD", + "Amount": "0.0" + }, + "NetCharge": { + "Currency": "USD", + "Amount": "13.67" + }, + "TotalRebates": { + "Currency": "USD", + "Amount": "0.0" + }, + "Surcharges": [ + { + "SurchargeType": "DELIVERY_AREA", + "Level": "PACKAGE", + "Description": "Delivery Area Surcharge Extended", + "Amount": { + "Currency": "USD", + "Amount": "1.95" + } + }, + { + "SurchargeType": "FUEL", + "Level": "PACKAGE", + "Description": "SmartPost Fuel", + "Amount": { + "Currency": "USD", + "Amount": "0.9" + } + } + ] + } + } + } + ] + } +} \ No newline at end of file diff --git a/dev/tests/api-functional/_files/Magento/TestModuleFedex/etc/di.xml b/dev/tests/api-functional/_files/Magento/TestModuleFedex/etc/di.xml new file mode 100644 index 0000000000000..87067a1ed7586 --- /dev/null +++ b/dev/tests/api-functional/_files/Magento/TestModuleFedex/etc/di.xml @@ -0,0 +1,14 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © Magento, Inc. 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\Fedex\Model\Carrier"> + <arguments> + <argument name="soapClientFactory" xsi:type="object">Magento\TestModuleFedex\Model\MockSoapClientFactory</argument> + </arguments> + </type> +</config> diff --git a/dev/tests/api-functional/_files/Magento/TestModuleFedex/etc/module.xml b/dev/tests/api-functional/_files/Magento/TestModuleFedex/etc/module.xml new file mode 100644 index 0000000000000..b6edf2f79b4a9 --- /dev/null +++ b/dev/tests/api-functional/_files/Magento/TestModuleFedex/etc/module.xml @@ -0,0 +1,10 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> + <module name="Magento_TestModuleFedex" /> +</config> diff --git a/dev/tests/api-functional/_files/Magento/TestModuleFedex/registration.php b/dev/tests/api-functional/_files/Magento/TestModuleFedex/registration.php new file mode 100644 index 0000000000000..7b11c17ff7ea2 --- /dev/null +++ b/dev/tests/api-functional/_files/Magento/TestModuleFedex/registration.php @@ -0,0 +1,11 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +use Magento\Framework\Component\ComponentRegistrar; + +$registrar = new ComponentRegistrar(); +if ($registrar->getPath(ComponentRegistrar::MODULE, 'Magento_TestModuleFedex') === null) { + ComponentRegistrar::register(ComponentRegistrar::MODULE, 'Magento_TestModuleFedex', __DIR__); +} diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/FedEx/SetFedExShippingMethodsOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/FedEx/SetFedExShippingMethodsOnCartTest.php index 30b746afddf48..9525ab521a5ea 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/FedEx/SetFedExShippingMethodsOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/FedEx/SetFedExShippingMethodsOnCartTest.php @@ -8,7 +8,6 @@ namespace Magento\GraphQl\FedEx; use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; -use Magento\GraphQl\Quote\GetQuoteShippingAddressIdByReservedQuoteId; use Magento\Integration\Api\CustomerTokenServiceInterface; use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\GraphQlAbstract; @@ -50,26 +49,14 @@ class SetFedExShippingMethodsOnCartTest extends GraphQlAbstract */ private $getMaskedQuoteIdByReservedOrderId; - /** - * @var GetQuoteShippingAddressIdByReservedQuoteId - */ - private $getQuoteShippingAddressIdByReservedQuoteId; - /** * @inheritdoc */ protected function setUp() { - $this->markTestSkipped( - 'Need to implement mock instead of real carrier service call ' . - 'https://github.com/magento/graphql-ce/issues/740' - ); $objectManager = Bootstrap::getObjectManager(); $this->customerTokenService = $objectManager->get(CustomerTokenServiceInterface::class); $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); - $this->getQuoteShippingAddressIdByReservedQuoteId = $objectManager->get( - GetQuoteShippingAddressIdByReservedQuoteId::class - ); } /** @@ -89,9 +76,8 @@ public function testSetFedExShippingMethod(string $methodCode, string $methodLab { $quoteReservedId = 'test_quote'; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($quoteReservedId); - $shippingAddressId = $this->getQuoteShippingAddressIdByReservedQuoteId->execute($quoteReservedId); - $query = $this->getQuery($maskedQuoteId, $shippingAddressId, self::CARRIER_CODE, $methodCode); + $query = $this->getQuery($maskedQuoteId, self::CARRIER_CODE, $methodCode); $response = $this->sendRequestWithToken($query); self::assertArrayHasKey('setShippingMethodsOnCart', $response); @@ -108,11 +94,11 @@ public function testSetFedExShippingMethod(string $methodCode, string $methodLab self::assertArrayHasKey('method_code', $shippingAddress['selected_shipping_method']); self::assertEquals($methodCode, $shippingAddress['selected_shipping_method']['method_code']); - self::assertArrayHasKey('label', $shippingAddress['selected_shipping_method']); - self::assertEquals( - self::CARRIER_LABEL . ' - ' . $methodLabel, - $shippingAddress['selected_shipping_method']['label'] - ); + self::assertArrayHasKey('carrier_title', $shippingAddress['selected_shipping_method']); + self::assertEquals(self::CARRIER_LABEL, $shippingAddress['selected_shipping_method']['carrier_title']); + + self::assertArrayHasKey('method_title', $shippingAddress['selected_shipping_method']); + self::assertEquals($methodLabel, $shippingAddress['selected_shipping_method']['method_title']); } /** @@ -147,9 +133,8 @@ public function testSetFedExShippingMethodBasedOnCanadaAddress(string $methodCod { $quoteReservedId = 'test_quote'; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($quoteReservedId); - $shippingAddressId = $this->getQuoteShippingAddressIdByReservedQuoteId->execute($quoteReservedId); - $query = $this->getQuery($maskedQuoteId, $shippingAddressId, self::CARRIER_CODE, $methodCode); + $query = $this->getQuery($maskedQuoteId, self::CARRIER_CODE, $methodCode); $response = $this->sendRequestWithToken($query); self::assertArrayHasKey('setShippingMethodsOnCart', $response); @@ -166,11 +151,11 @@ public function testSetFedExShippingMethodBasedOnCanadaAddress(string $methodCod self::assertArrayHasKey('method_code', $shippingAddress['selected_shipping_method']); self::assertEquals($methodCode, $shippingAddress['selected_shipping_method']['method_code']); - self::assertArrayHasKey('label', $shippingAddress['selected_shipping_method']); - self::assertEquals( - self::CARRIER_LABEL . ' - ' . $methodLabel, - $shippingAddress['selected_shipping_method']['label'] - ); + self::assertArrayHasKey('carrier_title', $shippingAddress['selected_shipping_method']); + self::assertEquals(self::CARRIER_LABEL, $shippingAddress['selected_shipping_method']['carrier_title']); + + self::assertArrayHasKey('method_title', $shippingAddress['selected_shipping_method']); + self::assertEquals($methodLabel, $shippingAddress['selected_shipping_method']['method_title']); } /** @@ -188,7 +173,6 @@ public function dataProviderShippingMethodsBasedOnCanadaAddress(): array /** * Generates query for setting the specified shipping method on cart * - * @param int $shippingAddressId * @param string $maskedQuoteId * @param string $carrierCode * @param string $methodCode @@ -196,7 +180,6 @@ public function dataProviderShippingMethodsBasedOnCanadaAddress(): array */ private function getQuery( string $maskedQuoteId, - int $shippingAddressId, string $carrierCode, string $methodCode ): string { @@ -206,7 +189,6 @@ private function getQuery( cart_id: "$maskedQuoteId" shipping_methods: [ { - cart_address_id: $shippingAddressId carrier_code: "$carrierCode" method_code: "$methodCode" } @@ -217,7 +199,8 @@ private function getQuery( selected_shipping_method { carrier_code method_code - label + carrier_title + method_title } } } diff --git a/dev/tests/integration/testsuite/Magento/GraphQl/FedEx/_files/enable_fedex_shipping_method.php b/dev/tests/integration/testsuite/Magento/GraphQl/FedEx/_files/enable_fedex_shipping_method.php index d7d76f3ebc1d9..1c977dacc6c62 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQl/FedEx/_files/enable_fedex_shipping_method.php +++ b/dev/tests/integration/testsuite/Magento/GraphQl/FedEx/_files/enable_fedex_shipping_method.php @@ -14,26 +14,9 @@ /** @var Writer $configWriter */ $configWriter = $objectManager->get(WriterInterface::class); -/** @var $mutableScopeConfig */ -$mutableScopeConfig = $objectManager->get( - \Magento\Framework\App\Config\MutableScopeConfigInterface::class -); - -/** - * Retrieve data from TESTS_GLOBAL_CONFIG_FILE - */ -$fedexAccount = $mutableScopeConfig->getValue('carriers/fedex/account', 'store'); -$fedexMeterNumber = $mutableScopeConfig->getValue('carriers/fedex/meter_number', 'store'); -$fedexKey = $mutableScopeConfig->getValue('carriers/fedex/key', 'store'); -$fedexPassword = $mutableScopeConfig->getValue('carriers/fedex/password', 'store'); -$fedexEndpointUrl = $mutableScopeConfig->getValue('carriers/fedex/production_webservices_url', 'store'); - -$configWriter->save('carriers/fedex/active', 1); -$configWriter->save('carriers/fedex/account', $fedexAccount); -$configWriter->save('carriers/fedex/meter_number', $fedexMeterNumber); -$configWriter->save('carriers/fedex/key', $fedexKey); -$configWriter->save('carriers/fedex/password', $fedexPassword); -$configWriter->save('carriers/fedex/production_webservices_url', $fedexEndpointUrl); +$configWriter->save('carriers/fedex/active', '1'); +$configWriter->save('carriers/fedex/sandbox_mode', '1'); +$configWriter->save(\Magento\Sales\Model\Order\Shipment::XML_PATH_STORE_ZIP, '90210'); $scopeConfig = $objectManager->get(ScopeConfigInterface::class); $scopeConfig->clean(); diff --git a/dev/tests/integration/testsuite/Magento/GraphQl/FedEx/_files/enable_fedex_shipping_method_rollback.php b/dev/tests/integration/testsuite/Magento/GraphQl/FedEx/_files/enable_fedex_shipping_method_rollback.php index ab0d639c5a2c1..daba4803f8b25 100644 --- a/dev/tests/integration/testsuite/Magento/GraphQl/FedEx/_files/enable_fedex_shipping_method_rollback.php +++ b/dev/tests/integration/testsuite/Magento/GraphQl/FedEx/_files/enable_fedex_shipping_method_rollback.php @@ -18,4 +18,5 @@ $configWriter->delete('carriers/fedex/meter_number'); $configWriter->delete('carriers/fedex/key'); $configWriter->delete('carriers/fedex/password'); -$configWriter->delete('carriers/fedex/production_webservices_url'); +$configWriter->delete('carriers/fedex/sandbox_mode'); +$configWriter->delete(\Magento\Sales\Model\Order\Shipment::XML_PATH_STORE_ZIP); From d87af0cbf0c395e1df2acc2142176b4659ad3bc3 Mon Sep 17 00:00:00 2001 From: OlgaVasyltsun <olga.vasyltsun@gmail.com> Date: Wed, 26 Jun 2019 08:11:33 +0300 Subject: [PATCH 527/773] MC-17755: Message isn't displayed on the error after connection reset and placing order --- .../Checkout/view/frontend/web/js/model/error-processor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/error-processor.js b/app/code/Magento/Checkout/view/frontend/web/js/model/error-processor.js index 14de743be83f3..9187609bbdbfc 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/model/error-processor.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/model/error-processor.js @@ -29,7 +29,7 @@ define([ try { error = JSON.parse(response.responseText); } catch (exception) { - error = {message: $t('Something went wrong with your request. Please try again later.')}; + error = { message: $t('Something went wrong with your request. Please try again later.') }; } messageContainer.addErrorMessage(error); } From 61c4328df9b62a156dce88e90aa265e910f1f1f3 Mon Sep 17 00:00:00 2001 From: OlgaVasyltsun <olga.vasyltsun@gmail.com> Date: Wed, 26 Jun 2019 09:39:13 +0300 Subject: [PATCH 528/773] MC-17755: Message isn't displayed on the error after connection reset and placing order --- .../Checkout/view/frontend/web/js/model/error-processor.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/error-processor.js b/app/code/Magento/Checkout/view/frontend/web/js/model/error-processor.js index 9187609bbdbfc..bf1697650e762 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/model/error-processor.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/model/error-processor.js @@ -29,7 +29,9 @@ define([ try { error = JSON.parse(response.responseText); } catch (exception) { - error = { message: $t('Something went wrong with your request. Please try again later.') }; + error = { + message: $t('Something went wrong with your request. Please try again later.') + }; } messageContainer.addErrorMessage(error); } From 7a91e775e120415d0ae51a64d9e5fe635c3b7249 Mon Sep 17 00:00:00 2001 From: Viktor Petryk <victor.petryk@transoftgroup.com> Date: Wed, 26 Jun 2019 10:11:29 +0300 Subject: [PATCH 529/773] MC-17269: Date format grid is not based on the locale defined in the back-office --- .../Test/AdminCheckingDateAfterChangeInterfaceLocaleTest.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/code/Magento/Ui/Test/Mftf/Test/AdminCheckingDateAfterChangeInterfaceLocaleTest.xml b/app/code/Magento/Ui/Test/Mftf/Test/AdminCheckingDateAfterChangeInterfaceLocaleTest.xml index f839d31c023bf..bfb4adbb2f2c3 100644 --- a/app/code/Magento/Ui/Test/Mftf/Test/AdminCheckingDateAfterChangeInterfaceLocaleTest.xml +++ b/app/code/Magento/Ui/Test/Mftf/Test/AdminCheckingDateAfterChangeInterfaceLocaleTest.xml @@ -19,6 +19,8 @@ <group value="ui"/> </annotations> <before> + <!--Deploy static content with French locale--> + <magentoCLI command="setup:static-content:deploy fr_FR" stepKey="deployStaticContentWithFrenchLocale"/> <!--Create entities--> <createData entity="SimpleProduct2" stepKey="createProduct"/> <createData entity="Simple_US_Customer" stepKey="createCustomer"/> From c50595efe1d3e4a1934363bccb6c42a88a5a561f Mon Sep 17 00:00:00 2001 From: Jeroen Boersma <jeroen@elgentos.nl> Date: Wed, 26 Jun 2019 10:29:25 +0200 Subject: [PATCH 530/773] Revert "Processed phpcs feedback" This reverts commit 211fe95022e5d49cda66278a26c74632344349f3. --- app/code/Magento/Developer/Model/XmlCatalog/Format/PhpStorm.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/code/Magento/Developer/Model/XmlCatalog/Format/PhpStorm.php b/app/code/Magento/Developer/Model/XmlCatalog/Format/PhpStorm.php index 6091c97865b0f..e70fc499915e1 100644 --- a/app/code/Magento/Developer/Model/XmlCatalog/Format/PhpStorm.php +++ b/app/code/Magento/Developer/Model/XmlCatalog/Format/PhpStorm.php @@ -10,6 +10,7 @@ use Magento\Framework\DomDocument\DomDocumentFactory; use Magento\Framework\Exception\FileSystemException; use Magento\Framework\Filesystem\Directory\ReadFactory; +use Magento\Framework\Filesystem\Directory\ReadInterface; use Magento\Framework\Filesystem\File\WriteFactory; /** @@ -31,6 +32,7 @@ class PhpStorm implements FormatInterface private $domDocumentFactory; /** + * @param ReadFactory $readFactory * @param WriteFactory $fileWriteFactory * @param DomDocumentFactory $domDocumentFactory */ From 79a108720a59bcb10246a6f465302c3a6ee517ca Mon Sep 17 00:00:00 2001 From: Jeroen Boersma <jeroen@elgentos.nl> Date: Wed, 26 Jun 2019 10:30:58 +0200 Subject: [PATCH 531/773] Revert "Removed unused parameter from constructor" This reverts commit 0db89b2dd4645827dc05536af0bbfc17db7b0a43. --- .../Magento/Developer/Model/XmlCatalog/Format/PhpStorm.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app/code/Magento/Developer/Model/XmlCatalog/Format/PhpStorm.php b/app/code/Magento/Developer/Model/XmlCatalog/Format/PhpStorm.php index e70fc499915e1..3a9f5d02ea61f 100644 --- a/app/code/Magento/Developer/Model/XmlCatalog/Format/PhpStorm.php +++ b/app/code/Magento/Developer/Model/XmlCatalog/Format/PhpStorm.php @@ -21,6 +21,11 @@ class PhpStorm implements FormatInterface const PROJECT_PATH_IDENTIFIER = '$PROJECT_DIR$'; const IDEA_PATH = '.idea'; + /** + * @var ReadInterface + */ + private $currentDirRead; + /** * @var WriteFactory */ @@ -37,9 +42,11 @@ class PhpStorm implements FormatInterface * @param DomDocumentFactory $domDocumentFactory */ public function __construct( + ReadFactory $readFactory, WriteFactory $fileWriteFactory, DomDocumentFactory $domDocumentFactory = null ) { + $this->currentDirRead = $readFactory->create(getcwd()); $this->fileWriteFactory = $fileWriteFactory; $this->domDocumentFactory = $domDocumentFactory ?: ObjectManager::getInstance()->get(DomDocumentFactory::class); } From d269dddf92f5c93ef0f73a3027f69aa84a5f06c7 Mon Sep 17 00:00:00 2001 From: Jeroen Boersma <jeroen@elgentos.nl> Date: Wed, 26 Jun 2019 08:32:35 +0000 Subject: [PATCH 532/773] Converted internals to private methods * internally used code is no longer public --- .../Developer/Model/XmlCatalog/Format/PhpStorm.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Developer/Model/XmlCatalog/Format/PhpStorm.php b/app/code/Magento/Developer/Model/XmlCatalog/Format/PhpStorm.php index 3a9f5d02ea61f..e3e8b713eea2a 100644 --- a/app/code/Magento/Developer/Model/XmlCatalog/Format/PhpStorm.php +++ b/app/code/Magento/Developer/Model/XmlCatalog/Format/PhpStorm.php @@ -18,8 +18,8 @@ */ class PhpStorm implements FormatInterface { - const PROJECT_PATH_IDENTIFIER = '$PROJECT_DIR$'; - const IDEA_PATH = '.idea'; + private const PROJECT_PATH_IDENTIFIER = '$PROJECT_DIR$'; + private const IDEA_PATH = '.idea'; /** * @var ReadInterface @@ -141,7 +141,7 @@ private function initEmptyFile(\DOMDocument $dom) * @param string $configFilePath * @return string */ - public function resolveProjectPath($configFilePath): string + private function resolveProjectPath($configFilePath): string { return \str_replace('/' . self::IDEA_PATH, '', realpath(dirname($configFilePath))); } @@ -153,7 +153,7 @@ public function resolveProjectPath($configFilePath): string * @param string $xsdPath * @return string */ - public function getFileLocationInProject(string $ideaDir, string $xsdPath): string + private function getFileLocationInProject(string $ideaDir, string $xsdPath): string { return \str_replace($ideaDir, self::PROJECT_PATH_IDENTIFIER, $xsdPath); } From 693a625058c1d0cc675b2727c5b90f8302eadec6 Mon Sep 17 00:00:00 2001 From: Jeroen Boersma <jeroen@elgentos.nl> Date: Wed, 26 Jun 2019 08:50:37 +0000 Subject: [PATCH 533/773] Second iteration use re-added readDirectory relative path Use currentReaddir to make relative paths. Second iteration which uses way less code with the same result. - removed realpath usage - removed dirname usage - removed unused method - removed unused constant --- .../Model/XmlCatalog/Format/PhpStorm.php | 21 +++---------------- 1 file changed, 3 insertions(+), 18 deletions(-) diff --git a/app/code/Magento/Developer/Model/XmlCatalog/Format/PhpStorm.php b/app/code/Magento/Developer/Model/XmlCatalog/Format/PhpStorm.php index e3e8b713eea2a..aef58a9a37e89 100644 --- a/app/code/Magento/Developer/Model/XmlCatalog/Format/PhpStorm.php +++ b/app/code/Magento/Developer/Model/XmlCatalog/Format/PhpStorm.php @@ -19,7 +19,6 @@ class PhpStorm implements FormatInterface { private const PROJECT_PATH_IDENTIFIER = '$PROJECT_DIR$'; - private const IDEA_PATH = '.idea'; /** * @var ReadInterface @@ -63,8 +62,6 @@ public function generateCatalog(array $dictionary, $configFilePath) $componentNode = null; $projectNode = null; - $ideaDir = $this->resolveProjectPath($configFilePath); - try { $file = $this->fileWriteFactory->create( $configFilePath, @@ -100,7 +97,7 @@ public function generateCatalog(array $dictionary, $configFilePath) foreach ($dictionary as $urn => $xsdPath) { $node = $dom->createElement('resource'); $node->setAttribute('url', $urn); - $node->setAttribute('location', $this->getFileLocationInProject($ideaDir, $xsdPath)); + $node->setAttribute('location', $this->getFileLocationInProject($xsdPath)); $componentNode->appendChild($node); } $dom->formatOutput = true; @@ -135,26 +132,14 @@ private function initEmptyFile(\DOMDocument $dom) return $projectNode; } - /** - * Resolve PhpStorm Project Path - * - * @param string $configFilePath - * @return string - */ - private function resolveProjectPath($configFilePath): string - { - return \str_replace('/' . self::IDEA_PATH, '', realpath(dirname($configFilePath))); - } - /** * Resolve xsdpath to xml project path * - * @param string $ideaDir * @param string $xsdPath * @return string */ - private function getFileLocationInProject(string $ideaDir, string $xsdPath): string + private function getFileLocationInProject(string $xsdPath): string { - return \str_replace($ideaDir, self::PROJECT_PATH_IDENTIFIER, $xsdPath); + return self::PROJECT_PATH_IDENTIFIER . DIRECTORY_SEPARATOR . $this->currentDirRead->getRelativePath($xsdPath); } } From 793b420c22fb561ae23a86b969f1c3c9a8cad4cd Mon Sep 17 00:00:00 2001 From: Yuliya Labudova <Yuliya_Labudova@epam.com> Date: Wed, 26 Jun 2019 14:00:25 +0300 Subject: [PATCH 534/773] MC-15524: Unwanted Created/Last Updated fieltes are being displayed. - Fix filter format data. --- .../Ui/Component/Listing/Columns/Date.php | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/app/code/Magento/Ui/Component/Listing/Columns/Date.php b/app/code/Magento/Ui/Component/Listing/Columns/Date.php index ad876b66b6038..f376bae711276 100644 --- a/app/code/Magento/Ui/Component/Listing/Columns/Date.php +++ b/app/code/Magento/Ui/Component/Listing/Columns/Date.php @@ -55,17 +55,19 @@ public function __construct( public function prepare() { $config = $this->getData('config'); - $config['filter'] = [ - 'filterType' => 'dateRange', - 'templates' => [ - 'date' => [ - 'options' => [ - 'dateFormat' => $this->timezone->getDateFormatWithLongYear() + if (isset($config['filter'])) { + $config['filter'] = [ + 'filterType' => 'dateRange', + 'templates' => [ + 'date' => [ + 'options' => [ + 'dateFormat' => $config['dateFormat'] ?? $this->timezone->getDateFormatWithLongYear() + ] ] ] - ] - ]; - $this->setData('config', $config); + ]; + $this->setData('config', $config); + } parent::prepare(); } From 36190fbbb77f1f3f22187f8b65905967b23b283e Mon Sep 17 00:00:00 2001 From: Dmitry Kaplin <jeysmook@gmail.com> Date: Wed, 26 Jun 2019 17:19:00 +0300 Subject: [PATCH 535/773] 23424: fixed search with 0 --- .../Ui/DataProvider/Product/AddFulltextFilterToCollection.php | 2 +- app/code/Magento/Ui/Component/Filters/Type/Search.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/CatalogSearch/Ui/DataProvider/Product/AddFulltextFilterToCollection.php b/app/code/Magento/CatalogSearch/Ui/DataProvider/Product/AddFulltextFilterToCollection.php index 1b05152903aa9..e08a1003b3673 100644 --- a/app/code/Magento/CatalogSearch/Ui/DataProvider/Product/AddFulltextFilterToCollection.php +++ b/app/code/Magento/CatalogSearch/Ui/DataProvider/Product/AddFulltextFilterToCollection.php @@ -37,7 +37,7 @@ public function __construct(SearchCollection $searchCollection) public function addFilter(Collection $collection, $field, $condition = null) { /** @var $collection \Magento\Catalog\Model\ResourceModel\Product\Collection */ - if (isset($condition['fulltext']) && !empty($condition['fulltext'])) { + if (isset($condition['fulltext']) && 0 !== strlen($condition['fulltext'])) { $this->searchCollection->addBackendSearchFilter($condition['fulltext']); $productIds = $this->searchCollection->load()->getAllIds(); $collection->addIdFilter($productIds); diff --git a/app/code/Magento/Ui/Component/Filters/Type/Search.php b/app/code/Magento/Ui/Component/Filters/Type/Search.php index da323e953bedf..ff98539e54558 100644 --- a/app/code/Magento/Ui/Component/Filters/Type/Search.php +++ b/app/code/Magento/Ui/Component/Filters/Type/Search.php @@ -34,7 +34,7 @@ protected function applyFilter() { $value = $this->getContext()->getRequestParam('search'); - if ($value) { + if (0 !== strlen($value)) { $filter = $this->filterBuilder->setConditionType('fulltext') ->setField($this->getName()) ->setValue($value) From 5ec74e261a8ff78a7c8a9b85b9344418df66ead3 Mon Sep 17 00:00:00 2001 From: Dmytro Horytskyi <horytsky@adobe.com> Date: Wed, 26 Jun 2019 10:51:41 -0500 Subject: [PATCH 536/773] MC-17513: cataloginventory_stock_status not populated properly --- .../Model/ResourceModel/Indexer/Stock/DefaultStock.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/CatalogInventory/Model/ResourceModel/Indexer/Stock/DefaultStock.php b/app/code/Magento/CatalogInventory/Model/ResourceModel/Indexer/Stock/DefaultStock.php index ba3b62f554767..58ba0c9db3634 100644 --- a/app/code/Magento/CatalogInventory/Model/ResourceModel/Indexer/Stock/DefaultStock.php +++ b/app/code/Magento/CatalogInventory/Model/ResourceModel/Indexer/Stock/DefaultStock.php @@ -292,6 +292,7 @@ protected function _prepareIndexTable($entityIds = null) */ protected function _updateIndex($entityIds) { + $this->deleteOldRecords($entityIds); $connection = $this->getConnection(); $select = $this->_getStockStatusSelect($entityIds, true); $select = $this->getQueryProcessorComposite()->processQuery($select, $entityIds, true); @@ -314,7 +315,6 @@ protected function _updateIndex($entityIds) } } - $this->deleteOldRecords($entityIds); $this->_updateIndexTable($data); return $this; From d06ffe5e5af1366d7a2ab61c434b9104d6cdb2ed Mon Sep 17 00:00:00 2001 From: Krissy Hiserote <khiserote@magento.com> Date: Wed, 26 Jun 2019 11:48:13 -0500 Subject: [PATCH 537/773] MC-15776: Merge release branch into 2.3-develop - fix merge conflicts --- app/code/Magento/Catalog/Model/Product.php | 61 ++++++++++++++++- .../Catalog/Model/ResourceModel/Product.php | 11 +-- app/code/Magento/Catalog/etc/acl.xml | 7 +- .../CatalogGraphQl/etc/schema.graphqls | 18 ++--- .../ActionGroup/AdminExportActionGroup.xml | 1 + .../view/frontend/templates/cart/coupon.phtml | 6 ++ .../Magento/CmsGraphQl/etc/schema.graphqls | 4 +- .../view/adminhtml/templates/grid.phtml | 26 ++----- .../Customer/Model/AccountManagement.php | 10 +-- app/code/Magento/Dhl/Model/Carrier.php | 24 +++++-- .../Block/Adminhtml/Template/Preview.php | 5 +- .../Magento/Email/Model/Template/Filter.php | 6 +- .../Model/Resolver/UpdateCartItems.php | 37 +++++++++- .../Magento/QuoteGraphQl/etc/schema.graphqls | 5 +- app/code/Magento/Sales/Helper/Admin.php | 68 ++++++++++++------- app/code/Magento/Sitemap/Model/Sitemap.php | 4 +- .../Sitemap/Test/Unit/Model/SitemapTest.php | 7 +- .../Magento/Theme/etc/adminhtml/system.xml | 8 ++- app/code/Magento/Theme/etc/config.xml | 2 +- .../Observer/AfterPaymentSaveObserverTest.php | 12 +++- .../GraphQl/Catalog/MediaGalleryTest.php | 34 ++++++++++ .../Catalog/Model/ProductRepositoryTest.php | 68 ++++++++++++++++--- .../Controller/Adminhtml/Locks/GridTest.php | 2 + .../Controller/Adminhtml/Locks/IndexTest.php | 5 +- .../Framework/Data/Collection/AbstractDb.php | 14 +--- .../Mview/Test/Unit/View/ChangelogTest.php | 4 +- .../Test/Unit/Element/AbstractBlockTest.php | 4 +- 27 files changed, 333 insertions(+), 120 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Product.php b/app/code/Magento/Catalog/Model/Product.php index 61544f8fb5766..fc9fffb2a7e9a 100644 --- a/app/code/Magento/Catalog/Model/Product.php +++ b/app/code/Magento/Catalog/Model/Product.php @@ -5,6 +5,7 @@ */ namespace Magento\Catalog\Model; +use Magento\Authorization\Model\UserContextInterface; use Magento\Catalog\Api\CategoryRepositoryInterface; use Magento\Catalog\Api\Data\ProductAttributeMediaGalleryEntryInterface; use Magento\Catalog\Api\Data\ProductInterface; @@ -14,6 +15,7 @@ use Magento\Framework\Api\AttributeValueFactory; use Magento\Framework\App\Filesystem\DirectoryList; use Magento\Framework\App\ObjectManager; +use Magento\Framework\AuthorizationInterface; use Magento\Framework\DataObject\IdentityInterface; use Magento\Framework\Pricing\SaleableInterface; @@ -353,6 +355,16 @@ class Product extends \Magento\Catalog\Model\AbstractModel implements */ private $filterCustomAttribute; + /** + * @var UserContextInterface + */ + private $userContext; + + /** + * @var AuthorizationInterface + */ + private $authorization; + /** * @param \Magento\Framework\Model\Context $context * @param \Magento\Framework\Registry $registry @@ -485,6 +497,7 @@ protected function _construct() $this->_init(\Magento\Catalog\Model\ResourceModel\Product::class); } + // phpcs:disable Generic.CodeAnalysis.UselessOverridingMethod /** * Get resource instance * phpcs:disable Generic.CodeAnalysis.UselessOverridingMethod @@ -497,6 +510,7 @@ protected function _getResource() { return parent::_getResource(); } + // phpcs:enable /** * Get a list of custom attribute codes that belongs to product attribute set. @@ -858,6 +872,34 @@ public function getAttributes($groupId = null, $skipSuper = false) return $attributes; } + /** + * Get user context. + * + * @return UserContextInterface + */ + private function getUserContext(): UserContextInterface + { + if (!$this->userContext) { + $this->userContext = ObjectManager::getInstance()->get(UserContextInterface::class); + } + + return $this->userContext; + } + + /** + * Get authorization service. + * + * @return AuthorizationInterface + */ + private function getAuthorization(): AuthorizationInterface + { + if (!$this->authorization) { + $this->authorization = ObjectManager::getInstance()->get(AuthorizationInterface::class); + } + + return $this->authorization; + } + /** * Check product options and type options and save them, too * @@ -875,6 +917,22 @@ public function beforeSave() $this->getTypeInstance()->beforeSave($this); + //Validate changing of design. + $userType = $this->getUserContext()->getUserType(); + if (( + $userType === UserContextInterface::USER_TYPE_ADMIN + || $userType === UserContextInterface::USER_TYPE_INTEGRATION + ) + && !$this->getAuthorization()->isAllowed('Magento_Catalog::edit_product_design') + ) { + $this->setData('custom_design', $this->getOrigData('custom_design')); + $this->setData('page_layout', $this->getOrigData('page_layout')); + $this->setData('options_container', $this->getOrigData('options_container')); + $this->setData('custom_layout_update', $this->getOrigData('custom_layout_update')); + $this->setData('custom_design_from', $this->getOrigData('custom_design_from')); + $this->setData('custom_design_to', $this->getOrigData('custom_design_to')); + } + $hasOptions = false; $hasRequiredOptions = false; @@ -1167,7 +1225,8 @@ public function getFormattedPrice() /** * Get formatted by currency product price * - * @return array|double* + * @return array|double + * * @deprecated * @see getFormattedPrice() */ diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product.php b/app/code/Magento/Catalog/Model/ResourceModel/Product.php index 99a7efe6c9895..b0b15cfd69d13 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product.php @@ -8,6 +8,7 @@ use Magento\Catalog\Model\ResourceModel\Product\Website\Link as ProductWebsiteLink; use Magento\Framework\App\ObjectManager; use Magento\Catalog\Model\Indexer\Category\Product\TableMaintainer; +use Magento\Catalog\Model\Product as ProductEntity; use Magento\Eav\Model\Entity\Attribute\UniqueValidationInterface; use Magento\Framework\EntityManager\EntityManager; use Magento\Framework\Model\AbstractModel; @@ -607,7 +608,9 @@ public function countAll() } /** - * @inheritdoc + * @inheritDoc + * + * @param ProductEntity|object $object */ public function validate($object) { @@ -689,7 +692,7 @@ public function save(AbstractModel $object) } /** - * Retrieve entity manager object + * Retrieve entity manager. * * @return EntityManager */ @@ -703,7 +706,7 @@ private function getEntityManager() } /** - * Retrieve ProductWebsiteLink object + * Retrieve ProductWebsiteLink instance. * * @deprecated 101.1.0 * @return ProductWebsiteLink @@ -714,7 +717,7 @@ private function getProductWebsiteLink() } /** - * Retrieve CategoryLink object + * Retrieve CategoryLink instance. * * @deprecated 101.1.0 * @return Product\CategoryLink diff --git a/app/code/Magento/Catalog/etc/acl.xml b/app/code/Magento/Catalog/etc/acl.xml index 4d4b7bdc672d1..c7c0f1f75872d 100644 --- a/app/code/Magento/Catalog/etc/acl.xml +++ b/app/code/Magento/Catalog/etc/acl.xml @@ -12,9 +12,12 @@ <resource id="Magento_Catalog::catalog" title="Catalog" translate="title" sortOrder="30"> <resource id="Magento_Catalog::catalog_inventory" title="Inventory" translate="title" sortOrder="10"> <resource id="Magento_Catalog::products" title="Products" translate="title" sortOrder="10"> - <resource id="Magento_Catalog::update_attributes" title="Update Attributes" translate="title" /> + <resource id="Magento_Catalog::update_attributes" title="Update Attributes" translate="title" sortOrder="10" /> + <resource id="Magento_Catalog::edit_product_design" title="Edit Product Design" translate="title" sortOrder="20" /> + </resource> + <resource id="Magento_Catalog::categories" title="Categories" translate="title" sortOrder="20"> + <resource id="Magento_Catalog::edit_category_design" title="Edit Category Design" translate="title" /> </resource> - <resource id="Magento_Catalog::categories" title="Categories" translate="title" sortOrder="20" /> </resource> </resource> <resource id="Magento_Backend::stores"> diff --git a/app/code/Magento/CatalogGraphQl/etc/schema.graphqls b/app/code/Magento/CatalogGraphQl/etc/schema.graphqls index f4d0990b17049..bbc01ac0854c0 100644 --- a/app/code/Magento/CatalogGraphQl/etc/schema.graphqls +++ b/app/code/Magento/CatalogGraphQl/etc/schema.graphqls @@ -8,12 +8,12 @@ type Query { pageSize: Int = 20 @doc(description: "Specifies the maximum number of results to return at once. This attribute is optional."), currentPage: Int = 1 @doc(description: "Specifies which page of results to return. The default value is 1."), sort: ProductSortInput @doc(description: "Specifies which attribute to sort on, and whether to return the results in ascending or descending order.") - ): Products - @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Products") @doc(description: "The products query searches for products that match the criteria specified in the search and filter attributes.") @cache(cacheTag: "cat_p", cacheIdentity: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\Identity") + ): Products + @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Products") @doc(description: "The products query searches for products that match the criteria specified in the search and filter attributes.") @cache(cacheIdentity: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\Identity") category ( id: Int @doc(description: "Id of the category.") ): CategoryTree - @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\CategoryTree") @doc(description: "The category query searches for categories that match the criteria specified in the search and filter attributes.") @cache(cacheTag: "cat_c", cacheIdentity: "Magento\\CatalogGraphQl\\Model\\Resolver\\Category\\CategoryTreeIdentity") + @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\CategoryTree") @doc(description: "The category query searches for categories that match the criteria specified in the search and filter attributes.") @cache(cacheIdentity: "Magento\\CatalogGraphQl\\Model\\Resolver\\Category\\CategoryTreeIdentity") } type Price @doc(description: "The Price object defines the price of a product as well as any tax-related adjustments.") { @@ -97,7 +97,7 @@ interface ProductInterface @typeResolver(class: "Magento\\CatalogGraphQl\\Model\ price: ProductPrices @doc(description: "A ProductPrices object, indicating the price of an item.") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\Price") gift_message_available: String @doc(description: "Indicates whether a gift message is available.") manufacturer: Int @doc(description: "A number representing the product's manufacturer.") - categories: [CategoryInterface] @doc(description: "The categories assigned to a product.") @cache(cacheTag: "cat_c", cacheIdentity: "Magento\\CatalogGraphQl\\Model\\Resolver\\Category\\CategoriesIdentity") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Categories") + categories: [CategoryInterface] @doc(description: "The categories assigned to a product.") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Categories") @cache(cacheIdentity: "Magento\\CatalogGraphQl\\Model\\Resolver\\Category\\CategoriesIdentity") canonical_url: String @doc(description: "Canonical URL.") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\CanonicalUrl") } @@ -218,7 +218,7 @@ interface CategoryInterface @typeResolver(class: "Magento\\CatalogGraphQl\\Model pageSize: Int = 20 @doc(description: "Specifies the maximum number of results to return at once. This attribute is optional."), currentPage: Int = 1 @doc(description: "Specifies which page of results to return. The default value is 1."), sort: ProductSortInput @doc(description: "Specifies which attribute to sort on, and whether to return the results in ascending or descending order.") - ): CategoryProducts @doc(description: "The list of products assigned to the category.") @cache(cacheTag: "cat_p", cacheIdentity: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\Identity") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Category\\Products") + ): CategoryProducts @doc(description: "The list of products assigned to the category.") @cache(cacheIdentity: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\Identity") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Category\\Products") breadcrumbs: [Breadcrumb] @doc(description: "Breadcrumbs, parent categories info.") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Category\\Breadcrumbs") } @@ -233,7 +233,7 @@ type CustomizableRadioOption implements CustomizableOptionInterface @doc(descrip value: [CustomizableRadioValue] @doc(description: "An array that defines a set of radio buttons.") } -type CustomizableRadioValue @doc(description: "CustomizableRadioValue defines the price and sku of a product whose page contains a customized set of radio buttons.") { +type CustomizableRadioValue @doc(description: "CustomizableRadioValue defines the price and sku of a product whose page contains a customized set of radio buttons.") { option_type_id: Int @doc(description: "The ID assigned to the value.") price: Float @doc(description: "The price assigned to this option.") price_type: PriceTypeEnum @doc(description: "FIXED, PERCENT, or DYNAMIC.") @@ -246,7 +246,7 @@ type CustomizableCheckboxOption implements CustomizableOptionInterface @doc(desc value: [CustomizableCheckboxValue] @doc(description: "An array that defines a set of checkbox values.") } -type CustomizableCheckboxValue @doc(description: "CustomizableCheckboxValue defines the price and sku of a product whose page contains a customized set of checkbox values.") { +type CustomizableCheckboxValue @doc(description: "CustomizableCheckboxValue defines the price and sku of a product whose page contains a customized set of checkbox values.") { option_type_id: Int @doc(description: "The ID assigned to the value.") price: Float @doc(description: "The price assigned to this option.") price_type: PriceTypeEnum @doc(description: "FIXED, PERCENT, or DYNAMIC.") @@ -329,7 +329,7 @@ type ProductMediaGalleryEntriesVideoContent @doc(description: "ProductMediaGalle video_metadata: String @doc(description: "Optional data about the video.") } -input ProductSortInput @doc(description: "ProductSortInput specifies the attribute to use for sorting search results and indicates whether the results are sorted in ascending or descending order.") { +input ProductSortInput @doc(description: "ProductSortInput specifies the attribute to use for sorting search results and indicates whether the results are sorted in ascending or descending order.") { name: SortEnum @doc(description: "The product name. Customers use this name to identify the product.") sku: SortEnum @doc(description: "A number or code assigned to a product to identify the product, options, price, and manufacturer.") description: SortEnum @doc(description: "Detailed information about the product. The value can include simple HTML tags.") @@ -363,7 +363,7 @@ input ProductSortInput @doc(description: "ProductSortInput specifies the attrib gift_message_available: SortEnum @doc(description: "Indicates whether a gift message is available.") } -type MediaGalleryEntry @doc(description: "MediaGalleryEntry defines characteristics about images and videos associated with a specific product.") { +type MediaGalleryEntry @doc(description: "MediaGalleryEntry defines characteristics about images and videos associated with a specific product.") { id: Int @doc(description: "The identifier assigned to the object.") media_type: String @doc(description: "image or video.") label: String @doc(description: "The alt text displayed on the UI when the user points to the image.") diff --git a/app/code/Magento/CatalogImportExport/Test/Mftf/ActionGroup/AdminExportActionGroup.xml b/app/code/Magento/CatalogImportExport/Test/Mftf/ActionGroup/AdminExportActionGroup.xml index 65588daa96cc4..911453cf7b049 100644 --- a/app/code/Magento/CatalogImportExport/Test/Mftf/ActionGroup/AdminExportActionGroup.xml +++ b/app/code/Magento/CatalogImportExport/Test/Mftf/ActionGroup/AdminExportActionGroup.xml @@ -54,6 +54,7 @@ <argument name="rowIndex" type="string"/> </arguments> <amOnPage url="{{AdminExportIndexPage.url}}" stepKey="goToExportIndexPage"/> + <waitForPageLoad time="30" stepKey="waitFormReload"/> <click stepKey="clickSelectBtn" selector="{{AdminExportAttributeSection.selectByIndex(rowIndex)}}"/> <click stepKey="clickOnDelete" selector="{{AdminExportAttributeSection.delete(rowIndex)}}" after="clickSelectBtn"/> <waitForElementVisible selector="{{AdminProductGridConfirmActionSection.title}}" stepKey="waitForConfirmModal"/> diff --git a/app/code/Magento/Checkout/view/frontend/templates/cart/coupon.phtml b/app/code/Magento/Checkout/view/frontend/templates/cart/coupon.phtml index 4522500d395b6..534a80f7fda0c 100644 --- a/app/code/Magento/Checkout/view/frontend/templates/cart/coupon.phtml +++ b/app/code/Magento/Checkout/view/frontend/templates/cart/coupon.phtml @@ -4,6 +4,9 @@ * See COPYING.txt for license details. */ +/** + * @var \Magento\Framework\View\Element\AbstractBlock $block + */ ?> <div class="block discount" id="block-discount" @@ -51,6 +54,9 @@ <?php endif; ?> </div> </div> + <?php if (!strlen($block->getCouponCode())): ?> + <?= /* @noEscape */ $block->getChildHtml('captcha') ?> + <?php endif; ?> </form> </div> </div> diff --git a/app/code/Magento/CmsGraphQl/etc/schema.graphqls b/app/code/Magento/CmsGraphQl/etc/schema.graphqls index 3558d853aa4df..2453cb61b9a6d 100644 --- a/app/code/Magento/CmsGraphQl/etc/schema.graphqls +++ b/app/code/Magento/CmsGraphQl/etc/schema.graphqls @@ -14,10 +14,10 @@ type Query { cmsPage ( id: Int @doc(description: "Id of the CMS page") @deprecated(reason: "The `id` is deprecated. Use `identifier` instead.") @doc(description: "The CMS page query returns information about a CMS page") identifier: String @doc(description: "Identifier of the CMS page") - ): CmsPage @resolver(class: "Magento\\CmsGraphQl\\Model\\Resolver\\Page") @doc(description: "The CMS page query returns information about a CMS page") @cache(cacheTag: "cms_p", cacheIdentity: "Magento\\CmsGraphQl\\Model\\Resolver\\Page\\Identity") + ): CmsPage @resolver(class: "Magento\\CmsGraphQl\\Model\\Resolver\\Page") @doc(description: "The CMS page query returns information about a CMS page") @cache(cacheIdentity: "Magento\\CmsGraphQl\\Model\\Resolver\\Page\\Identity") cmsBlocks ( identifiers: [String] @doc(description: "Identifiers of the CMS blocks") - ): CmsBlocks @resolver(class: "Magento\\CmsGraphQl\\Model\\Resolver\\Blocks") @doc(description: "The CMS block query returns information about CMS blocks") @cache(cacheTag: "cms_b", cacheIdentity: "Magento\\CmsGraphQl\\Model\\Resolver\\Block\\Identity") + ): CmsBlocks @resolver(class: "Magento\\CmsGraphQl\\Model\\Resolver\\Blocks") @doc(description: "The CMS block query returns information about CMS blocks") @cache(cacheIdentity: "Magento\\CmsGraphQl\\Model\\Resolver\\Block\\Identity") } type CmsPage @doc(description: "CMS page defines all CMS page information") { diff --git a/app/code/Magento/CurrencySymbol/view/adminhtml/templates/grid.phtml b/app/code/Magento/CurrencySymbol/view/adminhtml/templates/grid.phtml index 9248337e5c413..397c2598dc3b0 100644 --- a/app/code/Magento/CurrencySymbol/view/adminhtml/templates/grid.phtml +++ b/app/code/Magento/CurrencySymbol/view/adminhtml/templates/grid.phtml @@ -3,8 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ -?> -<?php + /** * @var $block \Magento\CurrencySymbol\Block\Adminhtml\System\Currencysymbol */ @@ -27,7 +26,7 @@ <div class="admin__field admin__field-option"> <input id="custom_currency_symbol_inherit<?= $block->escapeHtmlAttr($code) ?>" class="admin__control-checkbox" type="checkbox" - onclick="toggleUseDefault(<?= '\'' . $block->escapeJs($code) . '\',\'' . $block->escapeJs($data['parentSymbol']) . '\'' ?>)" + onclick="toggleUseDefault(<?= '\'' . $block->escapeHtmlAttr($block->escapeJs($code)) . '\',\'' . $block->escapeJs($data['parentSymbol']) . '\'' ?>)" <?= $data['inherited'] ? ' checked="checked"' : '' ?> value="1" name="inherit_custom_currency_symbol[<?= $block->escapeHtmlAttr($code) ?>]"> @@ -43,25 +42,10 @@ <?php endforeach; ?> </fieldset> </form> -<script> -require(['jquery', "mage/mage", 'prototype'], function(jQuery){ - - jQuery('#currency-symbols-form').mage('form').mage('validation'); - - function toggleUseDefault(code, value) +<script type="text/x-magento-init"> { - checkbox = jQuery('#custom_currency_symbol_inherit'+code); - input = jQuery('#custom_currency_symbol'+code); - - if (checkbox.is(':checked')) { - input.addClass('disabled'); - input.val(value); - input.prop('readonly', true); - } else { - input.removeClass('disabled'); - input.prop('readonly', false); + "#currency-symbols-form": { + "Magento_CurrencySymbol/js/symbols-form": {} } } - window.toggleUseDefault = toggleUseDefault; -}); </script> diff --git a/app/code/Magento/Customer/Model/AccountManagement.php b/app/code/Magento/Customer/Model/AccountManagement.php index 15d98af86b72e..24899a1c5979c 100644 --- a/app/code/Magento/Customer/Model/AccountManagement.php +++ b/app/code/Magento/Customer/Model/AccountManagement.php @@ -579,7 +579,7 @@ public function authenticate($username, $password) } try { $this->getAuthentication()->authenticate($customerId, $password); - // phpcs:disable Magento2.Exceptions.ThrowCatch + // phpcs:ignore Magento2.Exceptions.ThrowCatch } catch (InvalidEmailOrPasswordException $e) { throw new InvalidEmailOrPasswordException(__('Invalid login or password.')); } @@ -890,7 +890,7 @@ public function createAccountWithPasswordHash(CustomerInterface $customer, $hash throw new InputMismatchException( __('A customer with the same email address already exists in an associated website.') ); - // phpcs:disable Magento2.Exceptions.ThrowCatch + // phpcs:ignore Magento2.Exceptions.ThrowCatch } catch (LocalizedException $e) { throw $e; } @@ -910,7 +910,7 @@ public function createAccountWithPasswordHash(CustomerInterface $customer, $hash } } $this->customerRegistry->remove($customer->getId()); - // phpcs:disable Magento2.Exceptions.ThrowCatch + // phpcs:ignore Magento2.Exceptions.ThrowCatch } catch (InputException $e) { $this->customerRepository->delete($customer); throw $e; @@ -1017,7 +1017,7 @@ private function changePasswordForCustomer($customer, $currentPassword, $newPass { try { $this->getAuthentication()->authenticate($customer->getId(), $currentPassword); - // phpcs:disable Magento2.Exceptions.ThrowCatch + // phpcs:ignore Magento2.Exceptions.ThrowCatch } catch (InvalidEmailOrPasswordException $e) { throw new InvalidEmailOrPasswordException( __("The password doesn't match this account. Verify the password and try again.") @@ -1549,7 +1549,7 @@ protected function getFullCustomerObject($customer) */ public function getPasswordHash($password) { - return $this->encryptor->getHash($password); + return $this->encryptor->getHash($password, true); } /** diff --git a/app/code/Magento/Dhl/Model/Carrier.php b/app/code/Magento/Dhl/Model/Carrier.php index e765a81554670..5959294fe6dc7 100644 --- a/app/code/Magento/Dhl/Model/Carrier.php +++ b/app/code/Magento/Dhl/Model/Carrier.php @@ -1088,7 +1088,7 @@ function () use ($deferredResponses, $responseBodies) { protected function _getQuotesFromServer($request) { $client = $this->_httpClientFactory->create(); - $client->setUri((string)$this->getConfigData('gateway_url')); + $client->setUri($this->getGatewayURL()); $client->setConfig(['maxredirects' => 0, 'timeout' => 30]); $client->setRawData(utf8_encode($request)); @@ -1410,7 +1410,7 @@ public function proccessAdditionalValidation(\Magento\Framework\DataObject $requ public function processAdditionalValidation(\Magento\Framework\DataObject $request) { //Skip by item validation if there is no items in request - if (!count($this->getAllItems($request))) { + if (empty($this->getAllItems($request))) { $this->_errors[] = __('There is no items in this order'); } @@ -1681,7 +1681,7 @@ protected function _doRequest() try { $response = $this->httpClient->request( new Request( - (string)$this->getConfigData('gateway_url'), + $this->getGatewayURL(), Request::METHOD_POST, ['Content-Type' => 'application/xml'], $request @@ -1850,7 +1850,7 @@ protected function _getXMLTracking($trackings) try { $response = $this->httpClient->request( new Request( - (string)$this->getConfigData('gateway_url'), + $this->getGatewayURL(), Request::METHOD_POST, ['Content-Type' => 'application/xml'], $request @@ -1883,7 +1883,7 @@ protected function _parseXmlTrackingResponse($trackings, $response) $errorTitle = __('Unable to retrieve tracking'); $resultArr = []; - if (strlen(trim($response)) > 0) { + if (!empty(trim($response))) { $xml = $this->parseXml($response, \Magento\Shipping\Model\Simplexml\Element::class); if (!is_object($xml)) { $errorTitle = __('Response is in the wrong format'); @@ -2131,4 +2131,18 @@ private function buildSoftwareVersion(): string { return substr($this->productMetadata->getVersion(), 0, 10); } + + /** + * Get the gateway URL + * + * @return string + */ + private function getGatewayURL(): string + { + if ($this->getConfigData('sandbox_mode')) { + return (string)$this->getConfigData('sandbox_url'); + } else { + return (string)$this->getConfigData('gateway_url'); + } + } } diff --git a/app/code/Magento/Email/Block/Adminhtml/Template/Preview.php b/app/code/Magento/Email/Block/Adminhtml/Template/Preview.php index 1ea6e3f921bc6..0ca6615b075b2 100644 --- a/app/code/Magento/Email/Block/Adminhtml/Template/Preview.php +++ b/app/code/Magento/Email/Block/Adminhtml/Template/Preview.php @@ -12,7 +12,7 @@ namespace Magento\Email\Block\Adminhtml\Template; /** - * Template Preview Block + * Email template preview block. * * @api * @since 100.0.2 @@ -70,8 +70,6 @@ protected function _toHtml() $template->setTemplateStyles($this->getRequest()->getParam('styles')); } - $template->setTemplateText($this->_maliciousCode->filter($template->getTemplateText())); - \Magento\Framework\Profiler::start($this->profilerName); $template->emulateDesign($storeId); @@ -80,6 +78,7 @@ protected function _toHtml() [$template, 'getProcessedTemplate'] ); $template->revertDesign(); + $templateProcessed = $this->_maliciousCode->filter($templateProcessed); if ($template->isPlain()) { $templateProcessed = "<pre>" . $this->escapeHtml($templateProcessed) . "</pre>"; diff --git a/app/code/Magento/Email/Model/Template/Filter.php b/app/code/Magento/Email/Model/Template/Filter.php index aa018d6fd44d6..0e27b2d4c418b 100644 --- a/app/code/Magento/Email/Model/Template/Filter.php +++ b/app/code/Magento/Email/Model/Template/Filter.php @@ -321,7 +321,7 @@ public function setDesignParams(array $designParams) } /** - * Retrieve CSS processor + * Get CSS processor * * @deprecated 100.1.2 * @return Css\Processor @@ -335,7 +335,7 @@ private function getCssProcessor() } /** - * Retrieve pub directory + * Get pub directory * * @deprecated 100.1.2 * @param string $dirType @@ -855,7 +855,7 @@ public function cssDirective($construction) return $css; } else { // Return CSS comment for debugging purposes - return '/* ' . sprintf(__('Contents of %s could not be loaded or is empty'), $file) . ' */'; + return '/* ' . __('Contents of the specified CSS file could not be loaded or is empty') . ' */'; } } diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/UpdateCartItems.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/UpdateCartItems.php index db6a43513cc30..fd3c6bac9b5df 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/UpdateCartItems.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/UpdateCartItems.php @@ -110,10 +110,45 @@ private function processCartItems(Quote $cart, array $items): void } $quantity = (float)$item['quantity']; + $cartItem = $cart->getItemById($itemId); + if ($cartItem === false) { + throw new GraphQlNoSuchEntityException( + __('Could not find cart item with id: %1.', $item['cart_item_id']) + ); + } + if ($quantity <= 0.0) { $this->cartItemRepository->deleteById((int)$cart->getId(), $itemId); } else { - $this->updateCartItem->execute($cart, $itemId, $quantity, $customizableOptions); + $cartItem->setQty($quantity); + $this->validateCartItem($cartItem); + $this->cartItemRepository->save($cartItem); + } + } + } + + /** + * Validate cart item + * + * @param Item $cartItem + * @return void + * @throws GraphQlInputException + */ + private function validateCartItem(Item $cartItem): void + { + if ($cartItem->getHasError()) { + $errors = []; + foreach ($cartItem->getMessage(false) as $message) { + $errors[] = $message; + } + + if (!empty($errors)) { + throw new GraphQlInputException( + __( + 'Could not update the product with SKU %sku: %message', + ['sku' => $cartItem->getSku(), 'message' => __(implode("\n", $errors))] + ) + ); } } } diff --git a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls index 893a0b9df458d..897227bbcf30b 100644 --- a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls +++ b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls @@ -141,9 +141,6 @@ input PaymentMethodInput { additional_data: PaymentMethodAdditionalDataInput @doc(description: "Additional payment data") } -input PaymentMethodAdditionalDataInput { -} - input SetGuestEmailOnCartInput { cart_id: String! email: String! @@ -198,7 +195,7 @@ type Cart { email: String @resolver (class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\CartEmail") shipping_addresses: [ShippingCartAddress]! @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\ShippingAddresses") billing_address: BillingCartAddress! @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\BillingAddress") - available_payment_methods: [AvailablePaymentMethod] @resolver(class: "Magento\\QuoteGraphQl\\Model\\Resolver\\AvailablePaymentMethods") @doc(description: "Available payment methods") + available_payment_methods: [AvailablePaymentMethod] @resolver(class: "Magento\\QuoteGraphQl\\Model\\Resolver\\AvailablePaymentMethods") @doc(description: "Available payment methods") selected_payment_method: SelectedPaymentMethod @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\SelectedPaymentMethod") prices: CartPrices @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\CartPrices") } diff --git a/app/code/Magento/Sales/Helper/Admin.php b/app/code/Magento/Sales/Helper/Admin.php index ab212f77ce935..0e0d8213cb791 100644 --- a/app/code/Magento/Sales/Helper/Admin.php +++ b/app/code/Magento/Sales/Helper/Admin.php @@ -7,6 +7,8 @@ namespace Magento\Sales\Helper; +use Magento\Framework\App\ObjectManager; + /** * Sales admin helper. */ @@ -32,24 +34,33 @@ class Admin extends \Magento\Framework\App\Helper\AbstractHelper */ protected $escaper; + /** + * @var \DOMDocumentFactory + */ + private $domDocumentFactory; + /** * @param \Magento\Framework\App\Helper\Context $context * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\Sales\Model\Config $salesConfig * @param \Magento\Framework\Pricing\PriceCurrencyInterface $priceCurrency * @param \Magento\Framework\Escaper $escaper + * @param \DOMDocumentFactory|null $domDocumentFactory */ public function __construct( \Magento\Framework\App\Helper\Context $context, \Magento\Store\Model\StoreManagerInterface $storeManager, \Magento\Sales\Model\Config $salesConfig, \Magento\Framework\Pricing\PriceCurrencyInterface $priceCurrency, - \Magento\Framework\Escaper $escaper + \Magento\Framework\Escaper $escaper, + \DOMDocumentFactory $domDocumentFactory = null ) { $this->priceCurrency = $priceCurrency; $this->_storeManager = $storeManager; $this->_salesConfig = $salesConfig; $this->escaper = $escaper; + $this->domDocumentFactory = $domDocumentFactory + ?: ObjectManager::getInstance()->get(\DOMDocumentFactory::class); parent::__construct($context); } @@ -150,30 +161,42 @@ public function applySalableProductTypesFilter($collection) public function escapeHtmlWithLinks($data, $allowedTags = null) { if (!empty($data) && is_array($allowedTags) && in_array('a', $allowedTags)) { - $links = []; - $i = 1; - $data = str_replace('%', '%%', $data); - $regexp = "#(?J)<a" - ."(?:(?:\s+(?:(?:href\s*=\s*(['\"])(?<link>.*?)\\1\s*)|(?:\S+\s*=\s*(['\"])(.*?)\\3)\s*)*)|>)" - .">?(?:(?:(?<text>.*?)(?:<\/a\s*>?|(?=<\w))|(?<text>.*)))#si"; - while (preg_match($regexp, $data, $matches)) { - $text = ''; - if (!empty($matches['text'])) { - $text = str_replace('%%', '%', $matches['text']); + $wrapperElementId = uniqid(); + $domDocument = $this->domDocumentFactory->create(); + + $internalErrors = libxml_use_internal_errors(true); + + $data = mb_convert_encoding($data, 'HTML-ENTITIES', 'UTF-8'); + $domDocument->loadHTML( + '<html><body id="' . $wrapperElementId . '">' . $data . '</body></html>' + ); + + libxml_use_internal_errors($internalErrors); + + $linkTags = $domDocument->getElementsByTagName('a'); + + foreach ($linkTags as $linkNode) { + $linkAttributes = []; + foreach ($linkNode->attributes as $attribute) { + $linkAttributes[$attribute->name] = $attribute->value; + } + + foreach ($linkAttributes as $attributeName => $attributeValue) { + if ($attributeName === 'href') { + $url = $this->filterUrl($attributeValue ?? ''); + $url = $this->escaper->escapeUrl($url); + $linkNode->setAttribute('href', $url); + } else { + $linkNode->removeAttribute($attributeName); + } } - $url = $this->filterUrl($matches['link'] ?? ''); - //Recreate a minimalistic secure a tag - $links[] = sprintf( - '<a href="%s">%s</a>', - $this->escaper->escapeHtml($url), - $this->escaper->escapeHtml($text) - ); - $data = str_replace($matches[0], '%' . $i . '$s', $data); - ++$i; } - $data = $this->escaper->escapeHtml($data, $allowedTags); - return vsprintf($data, $links); + + $result = mb_convert_encoding($domDocument->saveHTML(), 'UTF-8', 'HTML-ENTITIES'); + preg_match('/<body id="' . $wrapperElementId . '">(.+)<\/body><\/html>$/si', $result, $matches); + $data = !empty($matches) ? $matches[1] : ''; } + return $this->escaper->escapeHtml($data, $allowedTags); } @@ -187,7 +210,6 @@ private function filterUrl(string $url): string { if ($url) { //Revert the sprintf escaping - $url = str_replace('%%', '%', $url); // phpcs:ignore Magento2.Functions.DiscouragedFunction $urlScheme = parse_url($url, PHP_URL_SCHEME); $urlScheme = $urlScheme ? strtolower($urlScheme) : ''; diff --git a/app/code/Magento/Sitemap/Model/Sitemap.php b/app/code/Magento/Sitemap/Model/Sitemap.php index d0beac8697f81..95877c626256e 100644 --- a/app/code/Magento/Sitemap/Model/Sitemap.php +++ b/app/code/Magento/Sitemap/Model/Sitemap.php @@ -550,10 +550,10 @@ protected function _getSitemapRow($url, $lastmod = null, $changefreq = null, $pr $row .= '<lastmod>' . $this->_getFormattedLastmodDate($lastmod) . '</lastmod>'; } if ($changefreq) { - $row .= '<changefreq>' . $changefreq . '</changefreq>'; + $row .= '<changefreq>' . $this->_escaper->escapeHtml($changefreq) . '</changefreq>'; } if ($priority) { - $row .= sprintf('<priority>%.1f</priority>', $priority); + $row .= sprintf('<priority>%.1f</priority>', $this->_escaper->escapeHtml($priority)); } if ($images) { // Add Images to sitemap diff --git a/app/code/Magento/Sitemap/Test/Unit/Model/SitemapTest.php b/app/code/Magento/Sitemap/Test/Unit/Model/SitemapTest.php index 86d57815e02be..1becde2eb3498 100644 --- a/app/code/Magento/Sitemap/Test/Unit/Model/SitemapTest.php +++ b/app/code/Magento/Sitemap/Test/Unit/Model/SitemapTest.php @@ -87,7 +87,7 @@ class SitemapTest extends \PHPUnit\Framework\TestCase private $configReaderMock; /** - * Set helper mocks, create resource model mock + * @inheritdoc */ protected function setUp() { @@ -604,9 +604,8 @@ private function getModelConstructorArgs() ->getMockForAbstractClass(); $objectManager = new ObjectManager($this); - $escaper = $objectManager->getObject( - \Magento\Framework\Escaper::class - ); + $escaper = $objectManager->getObject(\Magento\Framework\Escaper::class); + $constructArguments = $objectManager->getConstructArguments( Sitemap::class, [ diff --git a/app/code/Magento/Theme/etc/adminhtml/system.xml b/app/code/Magento/Theme/etc/adminhtml/system.xml index db92aee16c2bb..20500619354e0 100644 --- a/app/code/Magento/Theme/etc/adminhtml/system.xml +++ b/app/code/Magento/Theme/etc/adminhtml/system.xml @@ -7,7 +7,13 @@ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Config:etc/system_file.xsd"> <system> - <section id="dev"> + <section id="dev" translate="label" type="text" sortOrder="920" showInDefault="1" showInWebsite="1" showInStore="1"> + <group id="js"> + <field id="move_script_to_bottom" translate="label" type="select" sortOrder="25" showInDefault="1" showInWebsite="1" showInStore="1" canRestore="1"> + <label>Move JS code to the bottom of the page</label> + <source_model>Magento\Config\Model\Config\Source\Yesno</source_model> + </field> + </group> <group id="css"> <field id="use_css_critical_path" translate="label comment" type="select" sortOrder="30" showInDefault="1" showInWebsite="1" showInStore="1" canRestore="1"> <label>Use CSS critical path</label> diff --git a/app/code/Magento/Theme/etc/config.xml b/app/code/Magento/Theme/etc/config.xml index 3e26204d7788c..1515c357e094e 100644 --- a/app/code/Magento/Theme/etc/config.xml +++ b/app/code/Magento/Theme/etc/config.xml @@ -67,7 +67,7 @@ Disallow: /*SID= <sign>1</sign> </static> <js> - <move_inline_to_bottom>0</move_inline_to_bottom> + <move_script_to_bottom>0</move_script_to_bottom> </js> <css> <use_css_critical_path>0</use_css_critical_path> diff --git a/app/code/Magento/Vault/Test/Unit/Observer/AfterPaymentSaveObserverTest.php b/app/code/Magento/Vault/Test/Unit/Observer/AfterPaymentSaveObserverTest.php index 2ae16e186030d..501ab22a80385 100644 --- a/app/code/Magento/Vault/Test/Unit/Observer/AfterPaymentSaveObserverTest.php +++ b/app/code/Magento/Vault/Test/Unit/Observer/AfterPaymentSaveObserverTest.php @@ -21,7 +21,7 @@ use PHPUnit_Framework_MockObject_MockObject as MockObject; /** - * Tests for AfterPaymentSaveObserver. + * Test for payment observer. */ class AfterPaymentSaveObserverTest extends \PHPUnit\Framework\TestCase { @@ -66,7 +66,7 @@ class AfterPaymentSaveObserverTest extends \PHPUnit\Framework\TestCase protected $salesOrderPaymentMock; /** - * @return void + * @inheritdoc */ protected function setUp() { @@ -74,6 +74,10 @@ protected function setUp() $encryptorRandomGenerator = $this->createMock(Random::class); /** @var DeploymentConfig|MockObject $deploymentConfigMock */ $deploymentConfigMock = $this->createMock(DeploymentConfig::class); + $deploymentConfigMock->expects($this->any()) + ->method('get') + ->with(Encryptor::PARAM_CRYPT_KEY) + ->willReturn('g9mY9KLrcuAVJfsmVUSRkKFLDdUPVkaZ'); $this->encryptorModel = new Encryptor($encryptorRandomGenerator, $deploymentConfigMock); $this->paymentExtension = $this->getMockBuilder(OrderPaymentExtension::class) @@ -122,6 +126,8 @@ protected function setUp() } /** + * Case when payment successfully made. + * * @param int $customerId * @param string $createdAt * @param string $token @@ -173,6 +179,8 @@ public function testPositiveCase($customerId, $createdAt, $token, $isActive, $me } /** + * Data for positiveCase test. + * * @return array */ public function positiveCaseDataProvider() diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/MediaGalleryTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/MediaGalleryTest.php index 49e2a9dd53999..f39feabccd839 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/MediaGalleryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/MediaGalleryTest.php @@ -48,6 +48,40 @@ public function testProductSmallImageUrlWithExistingImage() self::assertTrue($this->checkImageExists($response['products']['items'][0]['small_image']['url'])); } + /** + * @magentoApiDataFixture Magento/Catalog/_files/product_with_multiple_images.php + */ + public function testMediaGalleryTypesAreCorrect() + { + $productSku = 'simple'; + $query = <<<QUERY +{ + products(filter: {sku: {eq: "{$productSku}"}}) { + items { + media_gallery_entries { + label + media_type + file + types + } + } + } +} +QUERY; + $response = $this->graphQlQuery($query); + $this->assertNotEmpty($response['products']['items'][0]['media_gallery_entries']); + $mediaGallery = $response['products']['items'][0]['media_gallery_entries']; + $this->assertCount(2, $mediaGallery); + $this->assertEquals('Image Alt Text', $mediaGallery[0]['label']); + $this->assertEquals('image', $mediaGallery[0]['media_type']); + $this->assertContains('magento_image', $mediaGallery[0]['file']); + $this->assertEquals(['image', 'small_image'], $mediaGallery[0]['types']); + $this->assertEquals('Thumbnail Image', $mediaGallery[1]['label']); + $this->assertEquals('image', $mediaGallery[1]['media_type']); + $this->assertContains('magento_thumbnail', $mediaGallery[1]['file']); + $this->assertEquals(['thumbnail', 'swatch_image'], $mediaGallery[1]['types']); + } + /** * @magentoApiDataFixture Magento/Catalog/_files/product_with_image.php */ diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductRepositoryTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductRepositoryTest.php index cbde2fa1d2b20..65dc2b88e0e0c 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductRepositoryTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductRepositoryTest.php @@ -7,9 +7,13 @@ namespace Magento\Catalog\Model; +use Magento\Backend\Model\Auth; use Magento\Catalog\Api\ProductRepositoryInterface; use Magento\Catalog\Model\ResourceModel\Product as ProductResource; +use Magento\Framework\Api\SearchCriteriaBuilder; use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\Bootstrap as TestBootstrap; +use Magento\Framework\Acl\Builder; /** * Provide tests for ProductRepository model. @@ -28,7 +32,7 @@ class ProductRepositoryTest extends \PHPUnit\Framework\TestCase private $productRepository; /** - * @var \Magento\Framework\Api\SearchCriteriaBuilder + * @var SearchCriteriaBuilder */ private $searchCriteriaBuilder; @@ -42,24 +46,38 @@ class ProductRepositoryTest extends \PHPUnit\Framework\TestCase */ private $productResource; + /* + * @var Auth + */ + private $auth; + + /** + * @var Builder + */ + private $aclBuilder; + /** * Sets up common objects */ protected function setUp() { - $this->productRepository = \Magento\Framework\App\ObjectManager::getInstance()->create( - \Magento\Catalog\Api\ProductRepositoryInterface::class - ); - - $this->searchCriteriaBuilder = \Magento\Framework\App\ObjectManager::getInstance()->create( - \Magento\Framework\Api\SearchCriteriaBuilder::class - ); - + $this->productRepository = Bootstrap::getObjectManager()->create(ProductRepositoryInterface::class); + $this->searchCriteriaBuilder = Bootstrap::getObjectManager()->get(SearchCriteriaBuilder::class); + $this->auth = Bootstrap::getObjectManager()->get(Auth::class); + $this->aclBuilder = Bootstrap::getObjectManager()->get(Builder::class); $this->productFactory = Bootstrap::getObjectManager()->get(ProductFactory::class); - $this->productResource = Bootstrap::getObjectManager()->get(ProductResource::class); + } + + /** + * @inheritDoc + */ + protected function tearDown() + { + parent::tearDown(); - $this->productRepository = Bootstrap::getObjectManager()->get(ProductRepositoryInterface::class); + $this->auth->logout(); + $this->aclBuilder->resetRuntimeAcl(); } /** @@ -186,4 +204,32 @@ public function testUpdateProductSku() //clean up. $this->productRepository->delete($updatedProduct); } + + /* + * Test authorization when saving product's design settings. + * + * @magentoDataFixture Magento/Catalog/_files/product_simple.php + * @magentoAppArea adminhtml + */ + public function testSaveDesign() + { + $product = $this->productRepository->get('simple'); + $this->auth->login(TestBootstrap::ADMIN_NAME, TestBootstrap::ADMIN_PASSWORD); + + //Admin doesn't have access to product's design. + $this->aclBuilder->getAcl()->deny(null, 'Magento_Catalog::edit_product_design'); + + $product->setCustomAttribute('custom_design', 2); + $product = $this->productRepository->save($product); + $this->assertEmpty($product->getCustomAttribute('custom_design')); + + //Admin has access to products' design. + $this->aclBuilder->getAcl() + ->allow(null, ['Magento_Catalog::products','Magento_Catalog::edit_product_design']); + + $product->setCustomAttribute('custom_design', 2); + $product = $this->productRepository->save($product); + $this->assertNotEmpty($product->getCustomAttribute('custom_design')); + $this->assertEquals(2, $product->getCustomAttribute('custom_design')->getValue()); + } } diff --git a/dev/tests/integration/testsuite/Magento/User/Controller/Adminhtml/Locks/GridTest.php b/dev/tests/integration/testsuite/Magento/User/Controller/Adminhtml/Locks/GridTest.php index 69265f33b305a..ccd25f64a4bdd 100644 --- a/dev/tests/integration/testsuite/Magento/User/Controller/Adminhtml/Locks/GridTest.php +++ b/dev/tests/integration/testsuite/Magento/User/Controller/Adminhtml/Locks/GridTest.php @@ -9,6 +9,8 @@ /** * Testing the list of locked users. + * + * @magentoAppArea adminhtml */ class GridTest extends AbstractBackendController { diff --git a/dev/tests/integration/testsuite/Magento/User/Controller/Adminhtml/Locks/IndexTest.php b/dev/tests/integration/testsuite/Magento/User/Controller/Adminhtml/Locks/IndexTest.php index 59cb49c7831eb..4519e52f0678b 100644 --- a/dev/tests/integration/testsuite/Magento/User/Controller/Adminhtml/Locks/IndexTest.php +++ b/dev/tests/integration/testsuite/Magento/User/Controller/Adminhtml/Locks/IndexTest.php @@ -3,10 +3,13 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\User\Controller\Adminhtml\Locks; /** - * Testing locked users list. + * Locked users page test. + * + * @magentoAppArea adminhtml */ class IndexTest extends \Magento\TestFramework\TestCase\AbstractBackendController { diff --git a/lib/internal/Magento/Framework/Data/Collection/AbstractDb.php b/lib/internal/Magento/Framework/Data/Collection/AbstractDb.php index 6082c2c6c5205..8a22c9a1ce4fc 100644 --- a/lib/internal/Magento/Framework/Data/Collection/AbstractDb.php +++ b/lib/internal/Magento/Framework/Data/Collection/AbstractDb.php @@ -733,7 +733,7 @@ public function loadData($printQuery = false, $logQuery = false) public function printLogQuery($printQuery = false, $logQuery = false, $sql = null) { if ($printQuery || $this->getFlag('print_query')) { - // phpcs:ignore Magento2.Security.LanguageConstruct + //phpcs:ignore Magento2.Security.LanguageConstruct echo $sql === null ? $this->getSelect()->__toString() : $sql; } @@ -828,7 +828,7 @@ public function __clone() * @return void * phpcs:disable Magento2.CodeAnalysis.EmptyBlock */ - protected function _initSelect() + protected function _initSelect() //phpcs:ignore Magento2.CodeAnalysis.EmptyBlock { // no implementation, should be overridden in children classes } @@ -896,14 +896,9 @@ private function getMainTableAlias() /** * @inheritdoc * @since 100.0.11 - * - * @SuppressWarnings(PHPMD.SerializationAware) - * @deprecated Do not use PHP serialization. */ public function __sleep() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); - return array_diff( parent::__sleep(), ['_fetchStrategy', '_logger', '_conn', 'extensionAttributesJoinProcessor'] @@ -913,14 +908,9 @@ public function __sleep() /** * @inheritdoc * @since 100.0.11 - * - * @SuppressWarnings(PHPMD.SerializationAware) - * @deprecated Do not use PHP serialization. */ public function __wakeup() { - trigger_error('Using PHP serialization is deprecated', E_USER_DEPRECATED); - parent::__wakeup(); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); $this->_logger = $objectManager->get(Logger::class); diff --git a/lib/internal/Magento/Framework/Mview/Test/Unit/View/ChangelogTest.php b/lib/internal/Magento/Framework/Mview/Test/Unit/View/ChangelogTest.php index 2d585fe33aba3..aaf7d72db161a 100644 --- a/lib/internal/Magento/Framework/Mview/Test/Unit/View/ChangelogTest.php +++ b/lib/internal/Magento/Framework/Mview/Test/Unit/View/ChangelogTest.php @@ -237,7 +237,7 @@ public function testGetListWithException() $this->expectException('Exception'); $this->expectExceptionMessage("Table {$changelogTableName} does not exist"); $this->model->setViewId('viewIdtest'); - $this->model->getList(mt_rand(1, 200), mt_rand(201, 400)); + $this->model->getList(random_int(1, 200), random_int(201, 400)); } public function testClearWithException() @@ -249,7 +249,7 @@ public function testClearWithException() $this->expectException('Exception'); $this->expectExceptionMessage("Table {$changelogTableName} does not exist"); $this->model->setViewId('viewIdtest'); - $this->model->clear(mt_rand(1, 200)); + $this->model->clear(random_int(1, 200)); } /** diff --git a/lib/internal/Magento/Framework/View/Test/Unit/Element/AbstractBlockTest.php b/lib/internal/Magento/Framework/View/Test/Unit/Element/AbstractBlockTest.php index fbaa7ec670794..93192201c7831 100644 --- a/lib/internal/Magento/Framework/View/Test/Unit/Element/AbstractBlockTest.php +++ b/lib/internal/Magento/Framework/View/Test/Unit/Element/AbstractBlockTest.php @@ -99,12 +99,14 @@ protected function setUp() $contextMock->expects($this->once()) ->method('getEscaper') ->willReturn($this->escaperMock); + $contextMock->expects($this->once()) + ->method('getLockGuardedCacheLoader') + ->willReturn($this->lockQuery); $this->block = $this->getMockForAbstractClass( AbstractBlock::class, [ 'context' => $contextMock, 'data' => [], - 'lockQuery' => $this->lockQuery ] ); } From a8f5c0d6c98a04ad88dc4f73580e08f1c572cefe Mon Sep 17 00:00:00 2001 From: jeysmook <jeysmook@gmail.com> Date: Wed, 26 Jun 2019 19:57:54 +0300 Subject: [PATCH 538/773] 23424: upgraded fixed code --- .../Ui/DataProvider/Product/AddFulltextFilterToCollection.php | 4 ++-- app/code/Magento/Ui/Component/Filters/Type/Search.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/CatalogSearch/Ui/DataProvider/Product/AddFulltextFilterToCollection.php b/app/code/Magento/CatalogSearch/Ui/DataProvider/Product/AddFulltextFilterToCollection.php index e08a1003b3673..85909fa4a280b 100644 --- a/app/code/Magento/CatalogSearch/Ui/DataProvider/Product/AddFulltextFilterToCollection.php +++ b/app/code/Magento/CatalogSearch/Ui/DataProvider/Product/AddFulltextFilterToCollection.php @@ -5,8 +5,8 @@ */ namespace Magento\CatalogSearch\Ui\DataProvider\Product; -use Magento\Framework\Data\Collection; use Magento\CatalogSearch\Model\ResourceModel\Search\Collection as SearchCollection; +use Magento\Framework\Data\Collection; use Magento\Ui\DataProvider\AddFilterToCollectionInterface; /** @@ -37,7 +37,7 @@ public function __construct(SearchCollection $searchCollection) public function addFilter(Collection $collection, $field, $condition = null) { /** @var $collection \Magento\Catalog\Model\ResourceModel\Product\Collection */ - if (isset($condition['fulltext']) && 0 !== strlen($condition['fulltext'])) { + if (isset($condition['fulltext']) && (string)$condition['fulltext'] !== '') { $this->searchCollection->addBackendSearchFilter($condition['fulltext']); $productIds = $this->searchCollection->load()->getAllIds(); $collection->addIdFilter($productIds); diff --git a/app/code/Magento/Ui/Component/Filters/Type/Search.php b/app/code/Magento/Ui/Component/Filters/Type/Search.php index ff98539e54558..446534cb82481 100644 --- a/app/code/Magento/Ui/Component/Filters/Type/Search.php +++ b/app/code/Magento/Ui/Component/Filters/Type/Search.php @@ -34,7 +34,7 @@ protected function applyFilter() { $value = $this->getContext()->getRequestParam('search'); - if (0 !== strlen($value)) { + if ((string)$value !== '') { $filter = $this->filterBuilder->setConditionType('fulltext') ->setField($this->getName()) ->setValue($value) From 8926c423fc8a27bee5f4309167f28fd6803582f6 Mon Sep 17 00:00:00 2001 From: Lena Orobei <oorobei@magento.com> Date: Wed, 26 Jun 2019 12:04:18 -0500 Subject: [PATCH 539/773] magento/graphql-ce#710: Links to the downloadable_product_samples are direct links magento/graphql-ce#729: Links to the downloadable_product_links are direct links --- .../Resolver/Product/DownloadableOptions.php | 19 ++++++---- .../DownloadableGraphQl/etc/schema.graphqls | 24 ++++++------ .../DownloadableProductViewTest.php | 38 +++---------------- 3 files changed, 29 insertions(+), 52 deletions(-) diff --git a/app/code/Magento/DownloadableGraphQl/Model/Resolver/Product/DownloadableOptions.php b/app/code/Magento/DownloadableGraphQl/Model/Resolver/Product/DownloadableOptions.php index b62e8d4984743..f7dd8eeba8c85 100644 --- a/app/code/Magento/DownloadableGraphQl/Model/Resolver/Product/DownloadableOptions.php +++ b/app/code/Magento/DownloadableGraphQl/Model/Resolver/Product/DownloadableOptions.php @@ -19,7 +19,6 @@ use Magento\Framework\GraphQl\Config\Element\Field; use Magento\Framework\GraphQl\Query\EnumLookup; use Magento\Framework\GraphQl\Query\ResolverInterface; -use Magento\Framework\App\ObjectManager; use Magento\Framework\UrlInterface; /** @@ -66,13 +65,13 @@ public function __construct( DownloadableHelper $downloadableHelper, SampleCollection $sampleCollection, LinkCollection $linkCollection, - UrlInterface $urlBuilder = null + UrlInterface $urlBuilder ) { $this->enumLookup = $enumLookup; $this->downloadableHelper = $downloadableHelper; $this->sampleCollection = $sampleCollection; $this->linkCollection = $linkCollection; - $this->urlBuilder = $urlBuilder ?: ObjectManager::getInstance()->get(UrlInterface::class); + $this->urlBuilder = $urlBuilder; } /** @@ -154,7 +153,10 @@ private function formatLinks(LinkCollection $links) : array } $resultData[$linkKey]['sample_file'] = $link->getSampleFile(); - $resultData[$linkKey]['sample_url'] = $link->getSampleUrl(); + $resultData[$linkKey]['sample_url'] = $this->urlBuilder->getUrl( + 'downloadable/download/linkSample', + ['link_id' => $link->getId()] + ); } return $resultData; } @@ -165,7 +167,7 @@ private function formatLinks(LinkCollection $links) : array * @param Collection $samples * @return array */ - private function formatSamples(Collection $samples) : array + private function formatSamples(Collection $samples): array { $resultData = []; foreach ($samples as $sampleKey => $sample) { @@ -175,8 +177,11 @@ private function formatSamples(Collection $samples) : array $resultData[$sampleKey]['sort_order'] = $sample->getSortOrder(); $resultData[$sampleKey]['sample_type'] = $this->enumLookup->getEnumValueFromField('DownloadableFileTypeEnum', $sample->getSampleType()); - $resultData[$sampleKey]['sample_file'] = $this->urlBuilder->getUrl('downloadable/download/sample', ['sample_id' => $sample->getId()]); - $resultData[$sampleKey]['sample_url'] = $sample->getSampleUrl(); + $resultData[$sampleKey]['sample_file'] = $sample->getSampleFile(); + $resultData[$sampleKey]['sample_url'] = $this->urlBuilder->getUrl( + 'downloadable/download/sample', + ['sample_id' => $sample->getId()] + ); } return $resultData; } diff --git a/app/code/Magento/DownloadableGraphQl/etc/schema.graphqls b/app/code/Magento/DownloadableGraphQl/etc/schema.graphqls index 788a5fc601ee1..9e4ab3b70c6e0 100644 --- a/app/code/Magento/DownloadableGraphQl/etc/schema.graphqls +++ b/app/code/Magento/DownloadableGraphQl/etc/schema.graphqls @@ -24,29 +24,29 @@ type DownloadableProduct implements ProductInterface, CustomizableProductInterfa links_title: String @doc(description: "The heading above the list of downloadable products") } -enum DownloadableFileTypeEnum @doc(description: "This enumeration specifies whether a link or sample is a file or URL") { +enum DownloadableFileTypeEnum @deprecated(reason: "`sample_url` serves to get the downloadable sample") { FILE URL } type DownloadableProductLinks @doc(description: "DownloadableProductLinks defines characteristics of a downloadable product") { - id: Int @doc(description: "The unique ID for the link to the downloadable product") + id: Int @deprecated(reason: "This information shoud not be exposed on frontend") title: String @doc(description: "The display name of the link") sort_order: Int @doc(description: "A number indicating the sort order") - is_shareable: Boolean @doc(description: "Indicates whether the link is shareable") + is_shareable: Boolean @deprecated(reason: "This information shoud not be exposed on frontend") price: Float @doc(description: "The price of the downloadable product") - number_of_downloads: Int @doc(description: "The maximum number of times the product can be downloaded. A value of 0 means unlimited.") - link_type: DownloadableFileTypeEnum @doc(description: "Either FILE or URL") - sample_type: DownloadableFileTypeEnum @doc(description: "Either FILE or URL") - sample_file: String @doc(description: "The relative path to the downloadable sample") - sample_url: String @doc(description: "The relative URL to the downloadable sample") + number_of_downloads: Int @deprecated(reason: "This information shoud not be exposed on frontend") + link_type: DownloadableFileTypeEnum @deprecated(reason: "`sample_url` serves to get the downloadable sample") + sample_type: DownloadableFileTypeEnum @deprecated(reason: "`sample_url` serves to get the downloadable sample") + sample_file: String @deprecated(reason: "`sample_url` serves to get the downloadable sample") + sample_url: String @doc(description: "URL to the downloadable sample") } type DownloadableProductSamples @doc(description: "DownloadableProductSamples defines characteristics of a downloadable product") { - id: Int @doc(description: "The unique ID for the downloadable product sample") + id: Int @deprecated(reason: "This information shoud not be exposed on frontend") title: String @doc(description: "The display name of the sample") sort_order: Int @doc(description: "A number indicating the sort order") - sample_type: DownloadableFileTypeEnum @doc(description: "Either FILE or URL") - sample_file: String @doc(description: "The relative path to the downloadable sample") - sample_url: String @doc(description: "The relative URL to the downloadable sample") + sample_type: DownloadableFileTypeEnum @deprecated(reason: "`sample_url` serves to get the downloadable sample") + sample_file: String @deprecated(reason: "`sample_url` serves to get the downloadable sample") + sample_url: String @doc(description: "URL to the downloadable sample") } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/DownloadableProduct/DownloadableProductViewTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/DownloadableProduct/DownloadableProductViewTest.php index a7902db259bc3..d84d8bf8bb871 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/DownloadableProduct/DownloadableProductViewTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/DownloadableProduct/DownloadableProductViewTest.php @@ -53,24 +53,16 @@ public function testQueryAllFieldsDownloadableProductsWithDownloadableFileAndSam links_purchased_separately downloadable_product_links{ - id sample_url - sample_type - - is_shareable - number_of_downloads sort_order title - link_type - price } downloadable_product_samples{ title sort_order sort_order - sample_type - sample_file + sample_url } } } @@ -82,8 +74,6 @@ public function testQueryAllFieldsDownloadableProductsWithDownloadableFileAndSam $config = ObjectManager::getInstance()->get(\Magento\Config\Model\ResourceModel\Config::class); $config->saveConfig( \Magento\Downloadable\Model\Link::XML_PATH_CONFIG_IS_SHAREABLE, - 0, - ScopeConfigInterface::SCOPE_TYPE_DEFAULT, 0 ); $response = $this->graphQlQuery($query); @@ -143,22 +133,15 @@ public function testDownloadableProductQueryWithNoSample() links_purchased_separately downloadable_product_links{ - id sample_url - sample_type - is_shareable - number_of_downloads sort_order title - link_type price } downloadable_product_samples{ title sort_order - sort_order - sample_type - sample_file + sample_url } } } @@ -197,12 +180,8 @@ public function testDownloadableProductQueryWithNoSample() $this->assertResponseFields( $response['products']['items'][0]['downloadable_product_links'][0], [ - 'id' => $downloadableProductLink->getId(), - 'is_shareable' => false, - 'number_of_downloads' => $downloadableProductLink->getNumberOfDownloads(), 'sort_order' => $downloadableProductLink->getSortOrder(), 'title' => $downloadableProductLink->getTitle(), - 'link_type' => strtoupper($downloadableProductLink->getLinkType()), 'price' => $downloadableProductLink->getPrice() ] ); @@ -221,18 +200,12 @@ private function assertDownloadableProductLinks($product, $actualResponse) /** @var LinkInterface $downloadableProductLinks */ $downloadableProductLinks = $product->getExtensionAttributes()->getDownloadableProductLinks(); $downloadableProductLink = $downloadableProductLinks[1]; - + $this->assertNotEmpty('sample_url', $actualResponse['downloadable_product_links'][1]); $this->assertResponseFields( $actualResponse['downloadable_product_links'][1], [ - 'id' => $downloadableProductLink->getId(), - 'sample_url' => $downloadableProductLink->getSampleUrl(), - 'sample_type' => strtoupper($downloadableProductLink->getSampleType()), - 'is_shareable' => false, - 'number_of_downloads' => $downloadableProductLink->getNumberOfDownloads(), 'sort_order' => $downloadableProductLink->getSortOrder(), 'title' => $downloadableProductLink->getTitle(), - 'link_type' => strtoupper($downloadableProductLink->getLinkType()), 'price' => $downloadableProductLink->getPrice() ] ); @@ -251,13 +224,12 @@ private function assertDownloadableProductSamples($product, $actualResponse) /** @var SampleInterface $downloadableProductSamples */ $downloadableProductSamples = $product->getExtensionAttributes()->getDownloadableProductSamples(); $downloadableProductSample = $downloadableProductSamples[0]; + $this->assertNotEmpty('sample_url', $actualResponse['downloadable_product_samples'][0]); $this->assertResponseFields( $actualResponse['downloadable_product_samples'][0], [ 'title' => $downloadableProductSample->getTitle(), - 'sort_order' =>$downloadableProductSample->getSortOrder(), - 'sample_type' => strtoupper($downloadableProductSample->getSampleType()), - 'sample_file' => $downloadableProductSample->getSampleFile() + 'sort_order' => $downloadableProductSample->getSortOrder() ] ); } From fa8fb2a1193de4f7d98dddf4523dd568f1f6dd24 Mon Sep 17 00:00:00 2001 From: Dmytro Horytskyi <horytsky@adobe.com> Date: Wed, 26 Jun 2019 12:28:19 -0500 Subject: [PATCH 540/773] MC-17513: cataloginventory_stock_status not populated properly --- .../Model/ResourceModel/Indexer/Stock/DefaultStock.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app/code/Magento/CatalogInventory/Model/ResourceModel/Indexer/Stock/DefaultStock.php b/app/code/Magento/CatalogInventory/Model/ResourceModel/Indexer/Stock/DefaultStock.php index 58ba0c9db3634..c5644060c689f 100644 --- a/app/code/Magento/CatalogInventory/Model/ResourceModel/Indexer/Stock/DefaultStock.php +++ b/app/code/Magento/CatalogInventory/Model/ResourceModel/Indexer/Stock/DefaultStock.php @@ -322,6 +322,7 @@ protected function _updateIndex($entityIds) /** * Delete records by their ids from index table + * * Used to clean table before re-indexation * * @param array $ids @@ -366,6 +367,8 @@ public function getIdxTable($table = null) } /** + * Get status expression + * * @param AdapterInterface $connection * @param bool $isAggregate * @return mixed @@ -391,6 +394,8 @@ protected function getStatusExpression(AdapterInterface $connection, $isAggregat } /** + * Get stock configuration + * * @return StockConfigurationInterface * * @deprecated 100.1.0 @@ -406,6 +411,8 @@ protected function getStockConfiguration() } /** + * Get query processor composite + * * @return QueryProcessorComposite */ private function getQueryProcessorComposite() From 86eb087085b2742dd5b732d0b616bb534c8616cd Mon Sep 17 00:00:00 2001 From: Lena Orobei <oorobei@magento.com> Date: Wed, 26 Jun 2019 13:04:04 -0500 Subject: [PATCH 541/773] magento/graphql-ce#710: Links to the downloadable_product_samples are direct links magento/graphql-ce#729: Links to the downloadable_product_links are direct links - added PHP DocBlock --- .../DownloadableProduct/DownloadableProductViewTest.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/DownloadableProduct/DownloadableProductViewTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/DownloadableProduct/DownloadableProductViewTest.php index d84d8bf8bb871..37f8801a6c2e9 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/DownloadableProduct/DownloadableProductViewTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/DownloadableProduct/DownloadableProductViewTest.php @@ -15,6 +15,9 @@ use Magento\TestFramework\ObjectManager; use Magento\TestFramework\TestCase\GraphQlAbstract; +/** + * Test for downloadable product. + */ class DownloadableProductViewTest extends GraphQlAbstract { /** From 0ba6f6d2e1593f0bb10e595899df139075838e85 Mon Sep 17 00:00:00 2001 From: Krissy Hiserote <khiserote@magento.com> Date: Wed, 26 Jun 2019 13:41:17 -0500 Subject: [PATCH 542/773] MC-15776: Merge release branch into 2.3-develop - update composer.lock file --- composer.lock | 114 +++++++++++++++++++++++++------------------------- 1 file changed, 57 insertions(+), 57 deletions(-) diff --git a/composer.lock b/composer.lock index 413e700c87b15..158aa76a36fff 100644 --- a/composer.lock +++ b/composer.lock @@ -1567,16 +1567,16 @@ }, { "name": "phpseclib/phpseclib", - "version": "2.0.18", + "version": "2.0.20", "source": { "type": "git", "url": "https://github.com/phpseclib/phpseclib.git", - "reference": "60519001db8d791215a822efd366d24cafee9e63" + "reference": "d6819a55b05e123db1e881d8b230d57f912126be" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/60519001db8d791215a822efd366d24cafee9e63", - "reference": "60519001db8d791215a822efd366d24cafee9e63", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/d6819a55b05e123db1e881d8b230d57f912126be", + "reference": "d6819a55b05e123db1e881d8b230d57f912126be", "shasum": "" }, "require": { @@ -1655,7 +1655,7 @@ "x.509", "x509" ], - "time": "2019-06-13T06:15:54+00:00" + "time": "2019-06-23T16:33:11+00:00" }, { "name": "psr/container", @@ -2137,7 +2137,7 @@ }, { "name": "symfony/css-selector", - "version": "v4.3.1", + "version": "v4.3.2", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", @@ -2253,16 +2253,16 @@ }, { "name": "symfony/filesystem", - "version": "v4.3.1", + "version": "v4.3.2", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "bf2af40d738dec5e433faea7b00daa4431d0a4cf" + "reference": "b9896d034463ad6fd2bf17e2bf9418caecd6313d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/bf2af40d738dec5e433faea7b00daa4431d0a4cf", - "reference": "bf2af40d738dec5e433faea7b00daa4431d0a4cf", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/b9896d034463ad6fd2bf17e2bf9418caecd6313d", + "reference": "b9896d034463ad6fd2bf17e2bf9418caecd6313d", "shasum": "" }, "require": { @@ -2299,20 +2299,20 @@ ], "description": "Symfony Filesystem Component", "homepage": "https://symfony.com", - "time": "2019-06-03T20:27:40+00:00" + "time": "2019-06-23T08:51:25+00:00" }, { "name": "symfony/finder", - "version": "v4.3.1", + "version": "v4.3.2", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "b3d4f4c0e4eadfdd8b296af9ca637cfbf51d8176" + "reference": "33c21f7d5d3dc8a140c282854a7e13aeb5d0f91a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/b3d4f4c0e4eadfdd8b296af9ca637cfbf51d8176", - "reference": "b3d4f4c0e4eadfdd8b296af9ca637cfbf51d8176", + "url": "https://api.github.com/repos/symfony/finder/zipball/33c21f7d5d3dc8a140c282854a7e13aeb5d0f91a", + "reference": "33c21f7d5d3dc8a140c282854a7e13aeb5d0f91a", "shasum": "" }, "require": { @@ -2348,7 +2348,7 @@ ], "description": "Symfony Finder Component", "homepage": "https://symfony.com", - "time": "2019-05-26T20:47:49+00:00" + "time": "2019-06-13T11:03:18+00:00" }, { "name": "symfony/polyfill-ctype", @@ -2395,7 +2395,7 @@ }, { "name": "Gert de Pagter", - "email": "backendtea@gmail.com" + "email": "BackEndTea@gmail.com" } ], "description": "Symfony polyfill for ctype functions", @@ -8674,16 +8674,16 @@ }, { "name": "symfony/browser-kit", - "version": "v4.3.1", + "version": "v4.3.2", "source": { "type": "git", "url": "https://github.com/symfony/browser-kit.git", - "reference": "e07d50e84b8cf489590f22244f4f609579b4a2c4" + "reference": "a29dd02a1f3f81b9a15c7730cc3226718ddb55ca" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/browser-kit/zipball/e07d50e84b8cf489590f22244f4f609579b4a2c4", - "reference": "e07d50e84b8cf489590f22244f4f609579b4a2c4", + "url": "https://api.github.com/repos/symfony/browser-kit/zipball/a29dd02a1f3f81b9a15c7730cc3226718ddb55ca", + "reference": "a29dd02a1f3f81b9a15c7730cc3226718ddb55ca", "shasum": "" }, "require": { @@ -8729,20 +8729,20 @@ ], "description": "Symfony BrowserKit Component", "homepage": "https://symfony.com", - "time": "2019-05-30T16:10:05+00:00" + "time": "2019-06-11T15:41:59+00:00" }, { "name": "symfony/config", - "version": "v4.3.1", + "version": "v4.3.2", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "6379ee07398643e09e6ed1e87d9c62dfcad7f4eb" + "reference": "9198eea354be75794a7b1064de00d9ae9ae5090f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/6379ee07398643e09e6ed1e87d9c62dfcad7f4eb", - "reference": "6379ee07398643e09e6ed1e87d9c62dfcad7f4eb", + "url": "https://api.github.com/repos/symfony/config/zipball/9198eea354be75794a7b1064de00d9ae9ae5090f", + "reference": "9198eea354be75794a7b1064de00d9ae9ae5090f", "shasum": "" }, "require": { @@ -8793,20 +8793,20 @@ ], "description": "Symfony Config Component", "homepage": "https://symfony.com", - "time": "2019-05-30T16:10:05+00:00" + "time": "2019-06-08T06:33:08+00:00" }, { "name": "symfony/dependency-injection", - "version": "v4.3.1", + "version": "v4.3.2", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "fea7f73e278ee0337349a5a68b867fc656bb33f3" + "reference": "b851928be349c065197fdc0832f78d85139e3903" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/fea7f73e278ee0337349a5a68b867fc656bb33f3", - "reference": "fea7f73e278ee0337349a5a68b867fc656bb33f3", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/b851928be349c065197fdc0832f78d85139e3903", + "reference": "b851928be349c065197fdc0832f78d85139e3903", "shasum": "" }, "require": { @@ -8866,20 +8866,20 @@ ], "description": "Symfony DependencyInjection Component", "homepage": "https://symfony.com", - "time": "2019-05-30T16:10:05+00:00" + "time": "2019-06-15T04:08:07+00:00" }, { "name": "symfony/dom-crawler", - "version": "v4.3.1", + "version": "v4.3.2", "source": { "type": "git", "url": "https://github.com/symfony/dom-crawler.git", - "reference": "06ee58fbc9a8130f1d35b5280e15235a0515d457" + "reference": "291397232a2eefb3347eaab9170409981eaad0e2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/06ee58fbc9a8130f1d35b5280e15235a0515d457", - "reference": "06ee58fbc9a8130f1d35b5280e15235a0515d457", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/291397232a2eefb3347eaab9170409981eaad0e2", + "reference": "291397232a2eefb3347eaab9170409981eaad0e2", "shasum": "" }, "require": { @@ -8927,20 +8927,20 @@ ], "description": "Symfony DomCrawler Component", "homepage": "https://symfony.com", - "time": "2019-05-31T18:55:30+00:00" + "time": "2019-06-13T11:03:18+00:00" }, { "name": "symfony/http-foundation", - "version": "v4.3.1", + "version": "v4.3.2", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "b7e4945dd9b277cd24e93566e4da0a87956392a9" + "reference": "e1b507fcfa4e87d192281774b5ecd4265370180d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/b7e4945dd9b277cd24e93566e4da0a87956392a9", - "reference": "b7e4945dd9b277cd24e93566e4da0a87956392a9", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/e1b507fcfa4e87d192281774b5ecd4265370180d", + "reference": "e1b507fcfa4e87d192281774b5ecd4265370180d", "shasum": "" }, "require": { @@ -8982,11 +8982,11 @@ ], "description": "Symfony HttpFoundation Component", "homepage": "https://symfony.com", - "time": "2019-06-06T10:05:02+00:00" + "time": "2019-06-26T09:25:00+00:00" }, { "name": "symfony/mime", - "version": "v4.3.1", + "version": "v4.3.2", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", @@ -9045,16 +9045,16 @@ }, { "name": "symfony/options-resolver", - "version": "v4.3.1", + "version": "v4.3.2", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "914e0edcb7cd0c9f494bc023b1d47534f4542332" + "reference": "40762ead607c8f792ee4516881369ffa553fee6f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/914e0edcb7cd0c9f494bc023b1d47534f4542332", - "reference": "914e0edcb7cd0c9f494bc023b1d47534f4542332", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/40762ead607c8f792ee4516881369ffa553fee6f", + "reference": "40762ead607c8f792ee4516881369ffa553fee6f", "shasum": "" }, "require": { @@ -9095,7 +9095,7 @@ "configuration", "options" ], - "time": "2019-05-10T05:38:46+00:00" + "time": "2019-06-13T11:01:17+00:00" }, { "name": "symfony/polyfill-intl-idn", @@ -9275,23 +9275,23 @@ }, { "name": "symfony/service-contracts", - "version": "v1.1.2", + "version": "v1.1.5", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "191afdcb5804db960d26d8566b7e9a2843cab3a0" + "reference": "f391a00de78ec7ec8cf5cdcdae59ec7b883edb8d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/191afdcb5804db960d26d8566b7e9a2843cab3a0", - "reference": "191afdcb5804db960d26d8566b7e9a2843cab3a0", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f391a00de78ec7ec8cf5cdcdae59ec7b883edb8d", + "reference": "f391a00de78ec7ec8cf5cdcdae59ec7b883edb8d", "shasum": "" }, "require": { - "php": "^7.1.3" + "php": "^7.1.3", + "psr/container": "^1.0" }, "suggest": { - "psr/container": "", "symfony/service-implementation": "" }, "type": "library", @@ -9329,11 +9329,11 @@ "interoperability", "standards" ], - "time": "2019-05-28T07:50:59+00:00" + "time": "2019-06-13T11:15:36+00:00" }, { "name": "symfony/stopwatch", - "version": "v4.3.1", + "version": "v4.3.2", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", @@ -9383,7 +9383,7 @@ }, { "name": "symfony/yaml", - "version": "v3.4.28", + "version": "v3.4.29", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", From a43c62b56e938e95b4db2febb7941e2804b7e3fd Mon Sep 17 00:00:00 2001 From: Roman Hanin <rganin@adobe.com> Date: Wed, 26 Jun 2019 14:27:31 -0500 Subject: [PATCH 543/773] MC-17817: Missing Information For Produce Details On Downloadable, Gift Card, Configurable, Bundle Products on Multiple Address Checkout Pages --- .../view/frontend/templates/checkout/item/default.phtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Multishipping/view/frontend/templates/checkout/item/default.phtml b/app/code/Magento/Multishipping/view/frontend/templates/checkout/item/default.phtml index 51d964957c4d5..83aa7a8db7920 100644 --- a/app/code/Magento/Multishipping/view/frontend/templates/checkout/item/default.phtml +++ b/app/code/Magento/Multishipping/view/frontend/templates/checkout/item/default.phtml @@ -12,7 +12,7 @@ <?php foreach ($_options as $_option) : ?> <?php $_formatedOptionValue = $block->getFormatedOptionValue($_option) ?> <dt><?= $block->escapeHtml($_option['label']) ?></dt> - <dd<?= (isset($_formatedOptionValue['full_view']) ? ' class="tooltip wrapper"' : '') ?> + <dd><?= (isset($_formatedOptionValue['full_view']) ? ' class="tooltip wrapper"' : '') ?> <?= $block->escapeHtml($_formatedOptionValue['value']) ?> <?php if (isset($_formatedOptionValue['full_view'])) : ?> <dl class="item options tooltip content"> From 3bf2a6a625a36886950165025cc8ab39a58e2348 Mon Sep 17 00:00:00 2001 From: Roman Hanin <rganin@adobe.com> Date: Wed, 26 Jun 2019 14:56:53 -0500 Subject: [PATCH 544/773] MC-17817: Missing Information For Produce Details On Downloadable, Gift Card, Configurable, Bundle Products on Multiple Address Checkout Pages --- .../view/frontend/templates/checkout/item/default.phtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Multishipping/view/frontend/templates/checkout/item/default.phtml b/app/code/Magento/Multishipping/view/frontend/templates/checkout/item/default.phtml index 83aa7a8db7920..187f13417e0f4 100644 --- a/app/code/Magento/Multishipping/view/frontend/templates/checkout/item/default.phtml +++ b/app/code/Magento/Multishipping/view/frontend/templates/checkout/item/default.phtml @@ -12,7 +12,7 @@ <?php foreach ($_options as $_option) : ?> <?php $_formatedOptionValue = $block->getFormatedOptionValue($_option) ?> <dt><?= $block->escapeHtml($_option['label']) ?></dt> - <dd><?= (isset($_formatedOptionValue['full_view']) ? ' class="tooltip wrapper"' : '') ?> + <dd<?= (isset($_formatedOptionValue['full_view']) ? ' class="tooltip wrapper"' : '') ?>> <?= $block->escapeHtml($_formatedOptionValue['value']) ?> <?php if (isset($_formatedOptionValue['full_view'])) : ?> <dl class="item options tooltip content"> From faf6d59bb01b029cda71a4b8859de2084836e991 Mon Sep 17 00:00:00 2001 From: Viktor Tymchynskyi <vtymchynskyi@magento.com> Date: Wed, 26 Jun 2019 15:16:15 -0500 Subject: [PATCH 545/773] MAGETWO-99867: Braintree - 3D Secure 2.0 Support for 2.3 --- .../view/frontend/requirejs-config.js | 10 +-- .../frontend/web/js/view/payment/3d-secure.js | 90 +++++++++---------- 2 files changed, 46 insertions(+), 54 deletions(-) diff --git a/app/code/Magento/Braintree/view/frontend/requirejs-config.js b/app/code/Magento/Braintree/view/frontend/requirejs-config.js index e2f5fb03e58bf..8e6d7f8062ebe 100644 --- a/app/code/Magento/Braintree/view/frontend/requirejs-config.js +++ b/app/code/Magento/Braintree/view/frontend/requirejs-config.js @@ -6,11 +6,11 @@ var config = { map: { '*': { - braintreeClient: 'https://js.braintreegateway.com/web/3.44.1/js/client.min.js', - braintreeHostedFields: 'https://js.braintreegateway.com/web/3.44.1/js/hosted-fields.min.js', - braintreePayPal: 'https://js.braintreegateway.com/web/3.44.1/js/paypal-checkout.min.js', - braintree3DSecure: 'https://js.braintreegateway.com/web/3.44.1/js/three-d-secure.min.js', - braintreeDataCollector: 'https://js.braintreegateway.com/web/3.44.1/js/data-collector.min.js' + braintreeClient: 'https://js.braintreegateway.com/web/3.46.0-beta-3ds.8/js/client.min.js', + braintreeHostedFields: 'https://js.braintreegateway.com/web/3.46.0-beta-3ds.8/js/hosted-fields.min.js', + braintreePayPal: 'https://js.braintreegateway.com/web/3.46.0-beta-3ds.8/js/paypal-checkout.min.js', + braintree3DSecure: 'https://js.braintreegateway.com/web/3.46.0-beta-3ds.8/js/three-d-secure.min.js', + braintreeDataCollector: 'https://js.braintreegateway.com/web/3.46.0-beta-3ds.8/js/data-collector.min.js' } }, paths: { diff --git a/app/code/Magento/Braintree/view/frontend/web/js/view/payment/3d-secure.js b/app/code/Magento/Braintree/view/frontend/web/js/view/payment/3d-secure.js index 84fa8cf62720f..354c697e2967b 100644 --- a/app/code/Magento/Braintree/view/frontend/web/js/view/payment/3d-secure.js +++ b/app/code/Magento/Braintree/view/frontend/web/js/view/payment/3d-secure.js @@ -41,6 +41,7 @@ define([ braintreeAdapter.getApiClient() .then(function (clientInstance) { return braintree3DSecure.create({ + version: 2, // Will use 3DS 2 whenever possible client: clientInstance }); }) @@ -49,6 +50,7 @@ define([ promise.resolve(self.threeDSecureInstance); }) .catch(function (err) { + fullScreenLoader.stopLoader(); promise.reject(err); }); @@ -84,28 +86,52 @@ define([ var self = this, totalAmount = quote.totals()['base_grand_total'], billingAddress = quote.billingAddress(), + shippingAddress = quote.shippingAddress(), options = { amount: totalAmount, nonce: context.paymentPayload.nonce, - - /** - * Adds iframe to page - * @param {Object} err - * @param {Object} iframe - */ - addFrame: function (err, iframe) { - self.createModal($(iframe)); - fullScreenLoader.stopLoader(); - self.modal.openModal(); + billingAddress: { + givenName: billingAddress.firstname, + surname: billingAddress.lastname, + phoneNumber: billingAddress.telephone, + streetAddress: billingAddress.street[0], + extendedAddress: billingAddress.street[1], + locality: billingAddress.city, + region: billingAddress.regionCode, + postalCode: billingAddress.postcode, + countryCodeAlpha2: billingAddress.countryId }, /** - * Removes iframe from page + * Will be called after receiving ThreeDSecure response, before completing the flow. + * + * @param {Object} data - ThreeDSecure data to consume before continuing + * @param {Function} next - callback to continue flow */ - removeFrame: function () { - self.modal.closeModal(); + onLookupComplete: function (data, next) { + next(); + } + }; + + if (context.paymentPayload.details) { + options.bin = context.paymentPayload.details.bin; + } + + if (shippingAddress) { + options.additionalInformation = { + shippingGivenName: shippingAddress.firstname, + shippingSurname: shippingAddress.lastname, + shippingPhone: shippingAddress.telephone, + shippingAddress: { + streetAddress: shippingAddress.street[0], + extendedAddress: shippingAddress.street[1], + locality: shippingAddress.city, + region: shippingAddress.regionCode, + postalCode: shippingAddress.postcode, + countryCodeAlpha2: shippingAddress.countryId } }; + } if (!this.isAmountAvailable(totalAmount) || !this.isCountryAvailable(billingAddress.countryId)) { self.state.resolve(); @@ -118,6 +144,7 @@ define([ .then(function () { self.threeDSecureInstance.verifyCard(options, function (err, payload) { if (err) { + fullScreenLoader.stopLoader(); self.state.reject(err.message); return; @@ -129,6 +156,7 @@ define([ context.paymentPayload.nonce = payload.nonce; self.state.resolve(); } else { + fullScreenLoader.stopLoader(); self.state.reject($t('Please try again with another form of payment.')); } }); @@ -141,42 +169,6 @@ define([ return self.state.promise(); }, - /** - * Creates modal window - * - * @param {Object} $context - * @private - */ - createModal: function ($context) { - var self = this, - options = { - clickableOverlay: false, - buttons: [], - modalCloseBtnHandler: self.cancelFlow.bind(self), - keyEventHandlers: { - escapeKey: self.cancelFlow.bind(self) - } - }; - - // adjust iframe styles - $context.attr('width', '100%'); - self.modal = Modal(options, $context); - }, - - /** - * Cancels 3D Secure flow - * - * @private - */ - cancelFlow: function () { - var self = this; - - self.threeDSecureInstance.cancelVerifyCard(function () { - self.modal.closeModal(); - self.state.reject(); - }); - }, - /** * Checks minimal amount for 3D Secure activation * From 1b81aabdcdeb4ee5486bb20dae8bbb18c52a2d4c Mon Sep 17 00:00:00 2001 From: Hwashiang Yu <hwyu@adobe.com> Date: Wed, 26 Jun 2019 16:41:22 -0500 Subject: [PATCH 546/773] MC-17825: Price box template incorrect rendering - Resolved incorrect template rendering for price box --- .../adminhtml/templates/sales/order/view/items/renderer.phtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Bundle/view/adminhtml/templates/sales/order/view/items/renderer.phtml b/app/code/Magento/Bundle/view/adminhtml/templates/sales/order/view/items/renderer.phtml index 0a8b759441947..233e57a003397 100644 --- a/app/code/Magento/Bundle/view/adminhtml/templates/sales/order/view/items/renderer.phtml +++ b/app/code/Magento/Bundle/view/adminhtml/templates/sales/order/view/items/renderer.phtml @@ -154,7 +154,7 @@ </td> <td class="col-discont"> <?php if ($block->canShowPriceInfo($_item)) : ?> - <?= $block->escapeHtml($block->displayPriceAttribute('discount_amount')) ?> + <?= /* @noEscape */ $block->displayPriceAttribute('discount_amount') ?> <?php else : ?>   <?php endif; ?> From 7f9ccaa304b28c367a77fd36ce5e12faba0a6737 Mon Sep 17 00:00:00 2001 From: Patrick McLain <pat@pmclain.com> Date: Wed, 26 Jun 2019 20:41:57 -0400 Subject: [PATCH 547/773] Add Test Module Mocking AuthorizenetAcceptjs --- .../Gateway/Http/MockClient.php | 135 ++++++++++++++++++ .../Validator/TransactionHashValidator.php | 28 ++++ .../TestModuleAuthorizenetAcceptjs/etc/di.xml | 11 ++ .../etc/module.xml | 10 ++ .../registration.php | 10 ++ 5 files changed, 194 insertions(+) create mode 100644 dev/tests/api-functional/_files/Magento/TestModuleAuthorizenetAcceptjs/Gateway/Http/MockClient.php create mode 100644 dev/tests/api-functional/_files/Magento/TestModuleAuthorizenetAcceptjs/Gateway/Validator/TransactionHashValidator.php create mode 100644 dev/tests/api-functional/_files/Magento/TestModuleAuthorizenetAcceptjs/etc/di.xml create mode 100644 dev/tests/api-functional/_files/Magento/TestModuleAuthorizenetAcceptjs/etc/module.xml create mode 100644 dev/tests/api-functional/_files/Magento/TestModuleAuthorizenetAcceptjs/registration.php diff --git a/dev/tests/api-functional/_files/Magento/TestModuleAuthorizenetAcceptjs/Gateway/Http/MockClient.php b/dev/tests/api-functional/_files/Magento/TestModuleAuthorizenetAcceptjs/Gateway/Http/MockClient.php new file mode 100644 index 0000000000000..3c82d4eba740f --- /dev/null +++ b/dev/tests/api-functional/_files/Magento/TestModuleAuthorizenetAcceptjs/Gateway/Http/MockClient.php @@ -0,0 +1,135 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\TestModuleAuthorizenetAcceptjs\Gateway\Http; + +use Magento\Framework\Math\Random; +use Magento\Framework\Stdlib\ArrayManager; +use Magento\Payment\Gateway\Http\ClientInterface; +use Magento\Payment\Gateway\Http\TransferInterface; + +/** + * A client for mocking communicate with the Authorize.net API + */ +class MockClient implements ClientInterface +{ + /** + * @var Random + */ + private $random; + + /** + * @var ArrayManager + */ + private $arrayManager; + + /** + * @param Random $random + * @param ArrayManager $arrayManager + */ + public function __construct( + Random $random, + ArrayManager $arrayManager + ) { + $this->random = $random; + $this->arrayManager = $arrayManager; + } + + /** + * Places request to gateway. Returns result as ENV array + * + * @param TransferInterface $transferObject + * @return array + */ + public function placeRequest(TransferInterface $transferObject): array + { + $request = $transferObject->getBody(); + $nonce = $this->arrayManager->get('transactionRequest/payment/opaqueData/dataValue', $request); + $descriptor = $this->arrayManager->get('transactionRequest/payment/opaqueData/dataDescriptor', $request); + + $approve = true; + if ($nonce !== 'fake-nonce' || $descriptor !== 'COMMON.ACCEPT.INAPP.PAYMENT') { + $approve = false; + } + + return $this->createResponse($approve); + } + + /** + * Create mock response body + * + * @param bool $approve + * @return array + * @throws \Magento\Framework\Exception\LocalizedException + */ + private function createResponse(bool $approve): array + { + return [ + 'transactionResponse' => [ + 'responseCode' => $approve ? '1' : '2', + 'authCode' => strtoupper($this->random->getRandomString(6)), + 'avsResultCode' => 'Y', + 'cvvResultCode' => 'P', + 'cavvResultCode' => '2', + 'transId' => random_int(10000000000, 99999999999), + 'refTransId' => '', + 'transHash' => '', + 'testRequest' => '0', + 'accountNumber' => 'XXXX1111', + 'accountType' => 'Visa', + 'messages' => $approve ? $this->getApprovalMessage() : $this->getDeclineMessage(), + 'userFields' => [ + [ + 'name' => 'transactionType', + 'value' => 'authOnlyTransaction', + ], + ], + 'transHashSha2' => 'fake-hash', + 'SupplementalDataQualificationIndicator' => '0', + ], + 'messages' => [ + 'resultCode' => 'Ok', + 'message' => [ + [ + 'code' => 'I00001', + 'text' => 'Successful.', + ], + ], + ], + ]; + } + + /** + * Provide approval message for response + * + * @return array + */ + private function getApprovalMessage(): array + { + return [ + [ + 'code' => '1', + 'description' => 'This transaction has been approved.', + ], + ]; + } + + /** + * Provide decline message for response + * + * @return array + */ + private function getDeclineMessage(): array + { + return [ + [ + 'code' => '2', + 'description' => 'This transaction has been declined.', + ], + ]; + } +} diff --git a/dev/tests/api-functional/_files/Magento/TestModuleAuthorizenetAcceptjs/Gateway/Validator/TransactionHashValidator.php b/dev/tests/api-functional/_files/Magento/TestModuleAuthorizenetAcceptjs/Gateway/Validator/TransactionHashValidator.php new file mode 100644 index 0000000000000..6a5642b39dca5 --- /dev/null +++ b/dev/tests/api-functional/_files/Magento/TestModuleAuthorizenetAcceptjs/Gateway/Validator/TransactionHashValidator.php @@ -0,0 +1,28 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\TestModuleAuthorizenetAcceptjs\Gateway\Validator; + +use Magento\Payment\Gateway\Validator\AbstractValidator; +use Magento\Payment\Gateway\Validator\ResultInterface; + +/** + * Force validation of the transaction hash + */ +class TransactionHashValidator extends AbstractValidator +{ + /** + * Skip validation of transaction hash in mock response + * + * @param array $validationSubject + * @return ResultInterface + */ + public function validate(array $validationSubject): ResultInterface + { + return $this->createResult(true); + } +} diff --git a/dev/tests/api-functional/_files/Magento/TestModuleAuthorizenetAcceptjs/etc/di.xml b/dev/tests/api-functional/_files/Magento/TestModuleAuthorizenetAcceptjs/etc/di.xml new file mode 100644 index 0000000000000..9f19743cfc205 --- /dev/null +++ b/dev/tests/api-functional/_files/Magento/TestModuleAuthorizenetAcceptjs/etc/di.xml @@ -0,0 +1,11 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © Magento, Inc. 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"> + <preference for="Magento\AuthorizenetAcceptjs\Gateway\Http\Client" type="Magento\TestModuleAuthorizenetAcceptjs\Gateway\Http\MockClient" /> + <preference for="Magento\AuthorizenetAcceptjs\Gateway\Validator\TransactionHashValidator" type="Magento\TestModuleAuthorizenetAcceptjs\Gateway\Validator\TransactionHashValidator" /> +</config> diff --git a/dev/tests/api-functional/_files/Magento/TestModuleAuthorizenetAcceptjs/etc/module.xml b/dev/tests/api-functional/_files/Magento/TestModuleAuthorizenetAcceptjs/etc/module.xml new file mode 100644 index 0000000000000..378b61946ef3a --- /dev/null +++ b/dev/tests/api-functional/_files/Magento/TestModuleAuthorizenetAcceptjs/etc/module.xml @@ -0,0 +1,10 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> + <module name="Magento_TestModuleAuthorizenetAcceptjs" /> +</config> \ No newline at end of file diff --git a/dev/tests/api-functional/_files/Magento/TestModuleAuthorizenetAcceptjs/registration.php b/dev/tests/api-functional/_files/Magento/TestModuleAuthorizenetAcceptjs/registration.php new file mode 100644 index 0000000000000..4c773870f189d --- /dev/null +++ b/dev/tests/api-functional/_files/Magento/TestModuleAuthorizenetAcceptjs/registration.php @@ -0,0 +1,10 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +use Magento\Framework\Component\ComponentRegistrar; +$registrar = new ComponentRegistrar(); +if ($registrar->getPath(ComponentRegistrar::MODULE, 'Magento_TestModuleAuthorizenetAcceptjs') === null) { + ComponentRegistrar::register(ComponentRegistrar::MODULE, 'Magento_TestModuleAuthorizenetAcceptjs', __DIR__); +} From 0d0aca150118de7517a31c31a86e2634cf86e8bc Mon Sep 17 00:00:00 2001 From: Patrick McLain <pat@pmclain.com> Date: Wed, 26 Jun 2019 20:44:15 -0400 Subject: [PATCH 548/773] Remove empty PaymentMethodAdditionalDataInput from schema This removes the empty input `PaymentMethodAdditionalDataInput` and provides an update to the backend implementation responislbe for resolving online payment method details. Fixes magento/graphql-ce#751 --- .../AuthorizenetGraphQl/etc/schema.graphqls | 2 +- .../Model/Cart/SetPaymentMethodOnCart.php | 15 +- .../Magento/QuoteGraphQl/etc/schema.graphqls | 4 - .../Validator/TransactionHashValidator.php | 1 + .../registration.php | 2 + .../Customer/SetPaymentMethodTest.php | 211 ++++++++++++++++++ .../Guest/SetPaymentMethodTest.php | 196 ++++++++++++++++ .../_files/enable_authorizenetacceptjs.php | 32 +++ .../enable_authorizenetacceptjs_rollback.php | 26 +++ 9 files changed, 475 insertions(+), 14 deletions(-) create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/AuthorizenetAcceptjs/Customer/SetPaymentMethodTest.php create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/AuthorizenetAcceptjs/Guest/SetPaymentMethodTest.php create mode 100644 dev/tests/integration/testsuite/Magento/GraphQl/AuthorizenetAcceptjs/_files/enable_authorizenetacceptjs.php create mode 100644 dev/tests/integration/testsuite/Magento/GraphQl/AuthorizenetAcceptjs/_files/enable_authorizenetacceptjs_rollback.php diff --git a/app/code/Magento/AuthorizenetGraphQl/etc/schema.graphqls b/app/code/Magento/AuthorizenetGraphQl/etc/schema.graphqls index 1d724bbde3c5d..b6e817cc91d61 100644 --- a/app/code/Magento/AuthorizenetGraphQl/etc/schema.graphqls +++ b/app/code/Magento/AuthorizenetGraphQl/etc/schema.graphqls @@ -1,7 +1,7 @@ # Copyright © Magento, Inc. All rights reserved. # See COPYING.txt for license details. -input PaymentMethodAdditionalDataInput { +input PaymentMethodInput { authorizenet_acceptjs: AuthorizenetInput @doc(description: "Defines the required attributes for Authorize.Net payments") } diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/SetPaymentMethodOnCart.php b/app/code/Magento/QuoteGraphQl/Model/Cart/SetPaymentMethodOnCart.php index ceaebf19e0e03..4deb794761efb 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/SetPaymentMethodOnCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/SetPaymentMethodOnCart.php @@ -68,18 +68,15 @@ public function execute(Quote $cart, array $paymentData): void $paymentMethodCode = $paymentData['code']; $poNumber = $paymentData['purchase_order_number'] ?? null; - $additionalData = isset($paymentData['additional_data']) - ? $this->additionalDataProviderPool->getData($paymentMethodCode, $paymentData['additional_data']) - : []; + $additionalData = $this->additionalDataProviderPool->getData($paymentMethodCode, $paymentData); $payment = $this->paymentFactory->create( [ - 'data' => - [ - PaymentInterface::KEY_METHOD => $paymentMethodCode, - PaymentInterface::KEY_PO_NUMBER => $poNumber, - PaymentInterface::KEY_ADDITIONAL_DATA => $additionalData, - ], + 'data' => [ + PaymentInterface::KEY_METHOD => $paymentMethodCode, + PaymentInterface::KEY_PO_NUMBER => $poNumber, + PaymentInterface::KEY_ADDITIONAL_DATA => $additionalData, + ], ] ); diff --git a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls index 893a0b9df458d..b4c62d8197aa5 100644 --- a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls +++ b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls @@ -138,10 +138,6 @@ input SetPaymentMethodOnCartInput { input PaymentMethodInput { code: String! @doc(description:"Payment method code") purchase_order_number: String @doc(description:"Purchase order number") - additional_data: PaymentMethodAdditionalDataInput @doc(description: "Additional payment data") -} - -input PaymentMethodAdditionalDataInput { } input SetGuestEmailOnCartInput { diff --git a/dev/tests/api-functional/_files/Magento/TestModuleAuthorizenetAcceptjs/Gateway/Validator/TransactionHashValidator.php b/dev/tests/api-functional/_files/Magento/TestModuleAuthorizenetAcceptjs/Gateway/Validator/TransactionHashValidator.php index 6a5642b39dca5..b0e281e9faa5c 100644 --- a/dev/tests/api-functional/_files/Magento/TestModuleAuthorizenetAcceptjs/Gateway/Validator/TransactionHashValidator.php +++ b/dev/tests/api-functional/_files/Magento/TestModuleAuthorizenetAcceptjs/Gateway/Validator/TransactionHashValidator.php @@ -20,6 +20,7 @@ class TransactionHashValidator extends AbstractValidator * * @param array $validationSubject * @return ResultInterface + * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function validate(array $validationSubject): ResultInterface { diff --git a/dev/tests/api-functional/_files/Magento/TestModuleAuthorizenetAcceptjs/registration.php b/dev/tests/api-functional/_files/Magento/TestModuleAuthorizenetAcceptjs/registration.php index 4c773870f189d..42ac558174062 100644 --- a/dev/tests/api-functional/_files/Magento/TestModuleAuthorizenetAcceptjs/registration.php +++ b/dev/tests/api-functional/_files/Magento/TestModuleAuthorizenetAcceptjs/registration.php @@ -3,7 +3,9 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + use Magento\Framework\Component\ComponentRegistrar; + $registrar = new ComponentRegistrar(); if ($registrar->getPath(ComponentRegistrar::MODULE, 'Magento_TestModuleAuthorizenetAcceptjs') === null) { ComponentRegistrar::register(ComponentRegistrar::MODULE, 'Magento_TestModuleAuthorizenetAcceptjs', __DIR__); diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/AuthorizenetAcceptjs/Customer/SetPaymentMethodTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/AuthorizenetAcceptjs/Customer/SetPaymentMethodTest.php new file mode 100644 index 0000000000000..c33360a38bdce --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/AuthorizenetAcceptjs/Customer/SetPaymentMethodTest.php @@ -0,0 +1,211 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQl\AuthorizenetAcceptjs\Customer; + +use Magento\Framework\Registry; +use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; +use Magento\Integration\Api\CustomerTokenServiceInterface; +use Magento\Sales\Api\OrderRepositoryInterface; +use Magento\Sales\Model\ResourceModel\Order\CollectionFactory; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\TestCase\GraphQlAbstract; + +/** + * Test setting payment method and placing order with AuthorizenetAcceptjs + */ +class SetPaymentMethodTest extends GraphQlAbstract +{ + private const VALID_DESCRIPTOR = 'COMMON.ACCEPT.INAPP.PAYMENT'; + private const VALID_NONCE = 'fake-nonce'; + + /** + * @var CustomerTokenServiceInterface + */ + private $customerTokenService; + + /** + * @var GetMaskedQuoteIdByReservedOrderId + */ + private $getMaskedQuoteIdByReservedOrderId; + + /** + * @var CollectionFactory + */ + private $orderCollectionFactory; + + /** + * @var OrderRepositoryInterface + */ + private $orderRepository; + + /** + * @var Registry + */ + private $registry; + + /** + * @inheritdoc + */ + protected function setUp() + { + $objectManager = Bootstrap::getObjectManager(); + $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); + $this->customerTokenService = $objectManager->get(CustomerTokenServiceInterface::class); + $this->orderCollectionFactory = $objectManager->get(CollectionFactory::class); + $this->orderRepository = $objectManager->get(OrderRepositoryInterface::class); + $this->registry = Bootstrap::getObjectManager()->get(Registry::class); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_shipping_methods.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_billing_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_flatrate_shipping_method.php + * @magentoApiDataFixture Magento/Graphql/AuthorizenetAcceptjs/_files/enable_authorizenetacceptjs.php + * @param string $nonce + * @param string $descriptor + * @param bool $expectSuccess + * @dataProvider dataProviderTestPlaceOrder + */ + public function testPlaceOrder(string $nonce, string $descriptor, bool $expectSuccess) + { + $reservedOrderId = 'test_quote'; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($reservedOrderId); + + $setPaymentMutation = $this->getSetPaymentMutation($maskedQuoteId, $descriptor, $nonce); + $setPaymentResponse = $this->graphQlMutation($setPaymentMutation, [], '', $this->getHeaderMap()); + + $this->assertSetPaymentMethodResponse($setPaymentResponse, 'authorizenet_acceptjs'); + + $placeOrderQuery = $this->getPlaceOrderMutation($maskedQuoteId); + + if (!$expectSuccess) { + $this->expectException(\Exception::class); + $this->expectExceptionMessage('Transaction has been declined. Please try again later.'); + } + + $placeOrderResponse = $this->graphQlMutation($placeOrderQuery, [], '', $this->getHeaderMap()); + + $this->assertPlaceOrderResponse($placeOrderResponse, $reservedOrderId); + } + + public function dataProviderTestPlaceOrder(): array + { + return [ + [static::VALID_NONCE, static::VALID_DESCRIPTOR, true], + ['nonce', static::VALID_DESCRIPTOR, false], + [static::VALID_NONCE, 'descriptor', false], + ]; + } + + private function assertPlaceOrderResponse(array $response, string $reservedOrderId): void + { + self::assertArrayHasKey('placeOrder', $response); + self::assertArrayHasKey('order', $response['placeOrder']); + self::assertArrayHasKey('order_id', $response['placeOrder']['order']); + self::assertEquals($reservedOrderId, $response['placeOrder']['order']['order_id']); + } + + private function assertSetPaymentMethodResponse(array $response, string $methodCode): void + { + self::assertArrayHasKey('setPaymentMethodOnCart', $response); + self::assertArrayHasKey('cart', $response['setPaymentMethodOnCart']); + self::assertArrayHasKey('selected_payment_method', $response['setPaymentMethodOnCart']['cart']); + self::assertArrayHasKey('code', $response['setPaymentMethodOnCart']['cart']['selected_payment_method']); + self::assertEquals($methodCode, $response['setPaymentMethodOnCart']['cart']['selected_payment_method']['code']); + } + + /** + * Create setPaymentMethodOnCart mutation + * + * @param string $maskedQuoteId + * @param string $descriptor + * @param string $nonce + * @return string + */ + private function getSetPaymentMutation(string $maskedQuoteId, string $descriptor, string $nonce): string + { + return <<<QUERY +mutation { + setPaymentMethodOnCart(input:{ + cart_id:"{$maskedQuoteId}" + payment_method:{ + code:"authorizenet_acceptjs" + authorizenet_acceptjs:{ + opaque_data_descriptor: "{$descriptor}" + opaque_data_value: "{$nonce}" + cc_last_4: 1111 + } + } + }) { + cart { + selected_payment_method { + code + } + } + } +} +QUERY; + } + + /** + * Create placeOrder mutation + * + * @param string $maskedQuoteId + * @return string + */ + private function getPlaceOrderMutation(string $maskedQuoteId): string + { + return <<<QUERY +mutation { + placeOrder(input: {cart_id: "{$maskedQuoteId}"}) { + order { + order_id + } + } +} +QUERY; + } + + /** + * Get authorization headers for requests + * + * @param string $username + * @param string $password + * @return array + * @throws \Magento\Framework\Exception\AuthenticationException + */ + private function getHeaderMap(string $username = 'customer@example.com', string $password = 'password'): array + { + $customerToken = $this->customerTokenService->createCustomerAccessToken($username, $password); + $headerMap = ['Authorization' => 'Bearer ' . $customerToken]; + return $headerMap; + } + + /** + * @inheritdoc + */ + public function tearDown() + { + $this->registry->unregister('isSecureArea'); + $this->registry->register('isSecureArea', true); + + $orderCollection = $this->orderCollectionFactory->create(); + foreach ($orderCollection as $order) { + $this->orderRepository->delete($order); + } + $this->registry->unregister('isSecureArea'); + $this->registry->register('isSecureArea', false); + + parent::tearDown(); + } +} diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/AuthorizenetAcceptjs/Guest/SetPaymentMethodTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/AuthorizenetAcceptjs/Guest/SetPaymentMethodTest.php new file mode 100644 index 0000000000000..d388980160332 --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/AuthorizenetAcceptjs/Guest/SetPaymentMethodTest.php @@ -0,0 +1,196 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQl\AuthorizenetAcceptjs\Guest; + +use Magento\Framework\Registry; +use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; +use Magento\Integration\Api\CustomerTokenServiceInterface; +use Magento\Sales\Api\OrderRepositoryInterface; +use Magento\Sales\Model\ResourceModel\Order\CollectionFactory; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\TestCase\GraphQlAbstract; + +/** + * Test setting payment method and placing order with AuthorizenetAcceptjs + */ +class SetPaymentMethodTest extends GraphQlAbstract +{ + private const VALID_DESCRIPTOR = 'COMMON.ACCEPT.INAPP.PAYMENT'; + private const VALID_NONCE = 'fake-nonce'; + + /** + * @var CustomerTokenServiceInterface + */ + private $customerTokenService; + + /** + * @var GetMaskedQuoteIdByReservedOrderId + */ + private $getMaskedQuoteIdByReservedOrderId; + + /** + * @var CollectionFactory + */ + private $orderCollectionFactory; + + /** + * @var OrderRepositoryInterface + */ + private $orderRepository; + + /** + * @var Registry + */ + private $registry; + + /** + * @inheritdoc + */ + protected function setUp() + { + $objectManager = Bootstrap::getObjectManager(); + $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); + $this->customerTokenService = $objectManager->get(CustomerTokenServiceInterface::class); + $this->orderCollectionFactory = $objectManager->get(CollectionFactory::class); + $this->orderRepository = $objectManager->get(OrderRepositoryInterface::class); + $this->registry = Bootstrap::getObjectManager()->get(Registry::class); + } + + /** + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_shipping_methods.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/set_guest_email.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_billing_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_flatrate_shipping_method.php + * @magentoApiDataFixture Magento/Graphql/AuthorizenetAcceptjs/_files/enable_authorizenetacceptjs.php + * @param string $nonce + * @param string $descriptor + * @param bool $expectSuccess + * @dataProvider dataProviderTestPlaceOrder + */ + public function testPlaceOrder(string $nonce, string $descriptor, bool $expectSuccess) + { + $reservedOrderId = 'test_quote'; + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute($reservedOrderId); + + $setPaymentMutation = $this->getSetPaymentMutation($maskedQuoteId, $descriptor, $nonce); + $setPaymentResponse = $this->graphQlMutation($setPaymentMutation); + + $this->assertSetPaymentMethodResponse($setPaymentResponse, 'authorizenet_acceptjs'); + + $placeOrderQuery = $this->getPlaceOrderMutation($maskedQuoteId); + + if (!$expectSuccess) { + $this->expectException(\Exception::class); + $this->expectExceptionMessage('Transaction has been declined. Please try again later.'); + } + + $placeOrderResponse = $this->graphQlMutation($placeOrderQuery); + + $this->assertPlaceOrderResponse($placeOrderResponse, $reservedOrderId); + } + + public function dataProviderTestPlaceOrder(): array + { + return [ + [static::VALID_NONCE, static::VALID_DESCRIPTOR, true], + ['nonce', static::VALID_DESCRIPTOR, false], + [static::VALID_NONCE, 'descriptor', false], + ]; + } + + private function assertPlaceOrderResponse(array $response, string $reservedOrderId): void + { + self::assertArrayHasKey('placeOrder', $response); + self::assertArrayHasKey('order', $response['placeOrder']); + self::assertArrayHasKey('order_id', $response['placeOrder']['order']); + self::assertEquals($reservedOrderId, $response['placeOrder']['order']['order_id']); + } + + private function assertSetPaymentMethodResponse(array $response, string $methodCode): void + { + self::assertArrayHasKey('setPaymentMethodOnCart', $response); + self::assertArrayHasKey('cart', $response['setPaymentMethodOnCart']); + self::assertArrayHasKey('selected_payment_method', $response['setPaymentMethodOnCart']['cart']); + self::assertArrayHasKey('code', $response['setPaymentMethodOnCart']['cart']['selected_payment_method']); + self::assertEquals($methodCode, $response['setPaymentMethodOnCart']['cart']['selected_payment_method']['code']); + } + + /** + * Create setPaymentMethodOnCart mutation + * + * @param string $maskedQuoteId + * @param string $descriptor + * @param string $nonce + * @return string + */ + private function getSetPaymentMutation(string $maskedQuoteId, string $descriptor, string $nonce): string + { + return <<<QUERY +mutation { + setPaymentMethodOnCart(input:{ + cart_id:"{$maskedQuoteId}" + payment_method:{ + code:"authorizenet_acceptjs" + authorizenet_acceptjs:{ + opaque_data_descriptor: "{$descriptor}" + opaque_data_value: "{$nonce}" + cc_last_4: 1111 + } + } + }) { + cart { + selected_payment_method { + code + } + } + } +} +QUERY; + } + + /** + * Create placeOrder mutation + * + * @param string $maskedQuoteId + * @return string + */ + private function getPlaceOrderMutation(string $maskedQuoteId): string + { + return <<<QUERY +mutation { + placeOrder(input: {cart_id: "{$maskedQuoteId}"}) { + order { + order_id + } + } +} +QUERY; + } + + /** + * @inheritdoc + */ + public function tearDown() + { + $this->registry->unregister('isSecureArea'); + $this->registry->register('isSecureArea', true); + + $orderCollection = $this->orderCollectionFactory->create(); + foreach ($orderCollection as $order) { + $this->orderRepository->delete($order); + } + $this->registry->unregister('isSecureArea'); + $this->registry->register('isSecureArea', false); + + parent::tearDown(); + } +} diff --git a/dev/tests/integration/testsuite/Magento/GraphQl/AuthorizenetAcceptjs/_files/enable_authorizenetacceptjs.php b/dev/tests/integration/testsuite/Magento/GraphQl/AuthorizenetAcceptjs/_files/enable_authorizenetacceptjs.php new file mode 100644 index 0000000000000..3043a5eaf2ae1 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/GraphQl/AuthorizenetAcceptjs/_files/enable_authorizenetacceptjs.php @@ -0,0 +1,32 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Framework\App\Config\Storage\Writer; +use Magento\Framework\App\Config\Storage\WriterInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Framework\Encryption\EncryptorInterface; +use Magento\AuthorizenetAcceptjs\Gateway\Config; + +$objectManager = Bootstrap::getObjectManager(); +/** @var EncryptorInterface $encryptor */ +$encryptor = $objectManager->get(EncryptorInterface::class); + +/** @var Writer $configWriter */ +$configWriter = $objectManager->get(WriterInterface::class); +$configWriter->save('payment/' . Config::METHOD . '/active', '1'); +$configWriter->save('payment/' . Config::METHOD . '/environment', 'sandbox'); +$configWriter->save('payment/' . Config::METHOD . '/login', $encryptor->encrypt('def_login')); +$configWriter->save('payment/' . Config::METHOD . '/trans_key', $encryptor->encrypt('def_trans_key')); +$configWriter->save('payment/' . Config::METHOD . '/public_client_key', $encryptor->encrypt('def_public_client_key')); +$configWriter->save( + 'payment/' . Config::METHOD . '/trans_signature_key', + $encryptor->encrypt('def_trans_signature_key') +); + +$scopeConfig = $objectManager->get(ScopeConfigInterface::class); +$scopeConfig->clean(); diff --git a/dev/tests/integration/testsuite/Magento/GraphQl/AuthorizenetAcceptjs/_files/enable_authorizenetacceptjs_rollback.php b/dev/tests/integration/testsuite/Magento/GraphQl/AuthorizenetAcceptjs/_files/enable_authorizenetacceptjs_rollback.php new file mode 100644 index 0000000000000..b73883f80f333 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/GraphQl/AuthorizenetAcceptjs/_files/enable_authorizenetacceptjs_rollback.php @@ -0,0 +1,26 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Framework\App\Config\Storage\Writer; +use Magento\Framework\App\Config\Storage\WriterInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\AuthorizenetAcceptjs\Gateway\Config; + +$objectManager = Bootstrap::getObjectManager(); + +/** @var Writer $configWriter */ +$configWriter = $objectManager->get(WriterInterface::class); +$configWriter->delete('payment/' . Config::METHOD . '/active'); +$configWriter->delete('payment/' . Config::METHOD . '/environment'); +$configWriter->delete('payment/' . Config::METHOD . '/login'); +$configWriter->delete('payment/' . Config::METHOD . '/trans_key'); +$configWriter->delete('payment/' . Config::METHOD . '/public_client_key'); +$configWriter->delete('payment/' . Config::METHOD . '/trans_signature_key'); + +$scopeConfig = $objectManager->get(ScopeConfigInterface::class); +$scopeConfig->clean(); From 8b495f2cea079163372d232de39b718bd1d23bd6 Mon Sep 17 00:00:00 2001 From: Krissy Hiserote <khiserote@magento.com> Date: Wed, 26 Jun 2019 20:29:48 -0500 Subject: [PATCH 549/773] MC-15776: Merge release branch into 2.3-develop - fix MFTF ActionGroups and Sections --- .../ActionGroup/AdminProductActionGroup.xml | 26 ++++++++++++++++++ .../Mftf/Section/AdminProductFormSection.xml | 1 + .../AdminDeleteCreatedRoleActionGroup.xml | 24 ----------------- .../AdminDeleteUserRoleActionGroup.xml | 27 +++++++++++++++++++ 4 files changed, 54 insertions(+), 24 deletions(-) delete mode 100644 app/code/Magento/User/Test/Mftf/ActionGroup/AdminDeleteCreatedRoleActionGroup.xml create mode 100644 app/code/Magento/User/Test/Mftf/ActionGroup/AdminDeleteUserRoleActionGroup.xml diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductActionGroup.xml index 07c1dce269240..9deab90b9045b 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductActionGroup.xml @@ -33,6 +33,7 @@ <arguments> <argument name="product" defaultValue="_defaultProduct"/> </arguments> + <scrollToTopOfPage stepKey="scrollToTopOfPage"/> <fillField selector="{{AdminProductFormSection.productName}}" userInput="{{product.name}}" stepKey="fillProductName"/> <fillField selector="{{AdminProductFormSection.productSku}}" userInput="{{product.sku}}" stepKey="fillProductSku"/> <fillField selector="{{AdminProductFormSection.productPrice}}" userInput="{{product.price}}" stepKey="fillProductPrice"/> @@ -498,4 +499,29 @@ <conditionalClick selector="{{AdminProductFormSection.enableProductLabel}}" dependentSelector="{{AdminProductFormSection.productStatusValue('1')}}" visible="true" stepKey="disableProduct"/> <seeElement selector="{{AdminProductFormSection.productStatusValue('2')}}" stepKey="assertThatProductSetToDisabled"/> </actionGroup> + + <!-- You are on product Edit Page --> + <!-- Assert checkbox available for website in Product In Websites --> + <actionGroup name="AssertWebsiteIsAvailableInProductWebsites"> + <arguments> + <argument name="website" type="string"/> + </arguments> + <scrollTo selector="{{ProductInWebsitesSection.sectionHeader}}" stepKey="scrollToProductInWebsitesSection"/> + <conditionalClick selector="{{ProductInWebsitesSection.sectionHeader}}" dependentSelector="{{ProductInWebsitesSection.sectionHeaderOpened}}" visible="false" stepKey="expandProductWebsitesSection"/> + <seeElement selector="{{ProductInWebsitesSection.website(website)}}" stepKey="seeCheckboxForWebsite"/> + </actionGroup> + + <!-- You are on product Edit Page --> + <!-- Assert checkbox not available for website in Product In Websites --> + <actionGroup name="AssertWebsiteIsNotAvailableInProductWebsites" extends="AssertWebsiteIsAvailableInProductWebsites"> + <remove keyForRemoval="seeCheckboxForWebsite"/> + <dontSeeElement selector="{{ProductInWebsitesSection.website(website)}}" after="expandProductWebsitesSection" stepKey="dontSeeCheckboxForWebsite"/> + </actionGroup> + + <!-- You are on product Edit Page --> + <!-- Assert checkbox Is checked for website in Product In Websites --> + <actionGroup name="AssertProductIsAssignedToWebsite" extends="AssertWebsiteIsAvailableInProductWebsites"> + <remove keyForRemoval="seeCheckboxForWebsite"/> + <seeCheckboxIsChecked selector="{{ProductInWebsitesSection.website(website)}}" after="expandProductWebsitesSection" stepKey="seeCustomWebsiteIsChecked"/> + </actionGroup> </actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormSection.xml index ec3552a1180ad..de30137f47ea3 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormSection.xml @@ -77,6 +77,7 @@ </section> <section name="ProductInWebsitesSection"> <element name="sectionHeader" type="button" selector="div[data-index='websites']" timeout="30"/> + <element name="sectionHeaderOpened" type="button" selector="[data-index='websites']._show" timeout="30"/> <element name="website" type="checkbox" selector="//label[contains(text(), '{{var1}}')]/parent::div//input[@type='checkbox']" parameterized="true"/> </section> <section name="ProductDesignSection"> diff --git a/app/code/Magento/User/Test/Mftf/ActionGroup/AdminDeleteCreatedRoleActionGroup.xml b/app/code/Magento/User/Test/Mftf/ActionGroup/AdminDeleteCreatedRoleActionGroup.xml deleted file mode 100644 index 813e22df227c8..0000000000000 --- a/app/code/Magento/User/Test/Mftf/ActionGroup/AdminDeleteCreatedRoleActionGroup.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="AdminDeleteCreatedRoleActionGroup"> - <arguments> - <argument name="role" defaultValue=""/> - </arguments> - <amOnPage url="{{AdminRolesPage.url}}" stepKey="amOnAdminUsersPage"/> - <waitForPageLoad stepKey="waitForUserRolePageLoad"/> - <click stepKey="clickToAddNewRole" selector="{{AdminDeleteRoleSection.role(role.name)}}"/> - <fillField stepKey="TypeCurrentPassword" selector="{{AdminDeleteRoleSection.current_pass}}" userInput="{{_ENV.MAGENTO_ADMIN_PASSWORD}}"/> - <click stepKey="clickToDeleteRole" selector="{{AdminDeleteRoleSection.delete}}"/> - <waitForElementVisible stepKey="wait" selector="{{AdminDeleteRoleSection.confirm}}" time="30"/> - <click stepKey="clickToConfirm" selector="{{AdminDeleteRoleSection.confirm}}"/> - <waitForPageLoad stepKey="waitForPageLoad"/> - <see stepKey="seeSuccessMessage" userInput="You deleted the role."/> - </actionGroup> -</actionGroups> diff --git a/app/code/Magento/User/Test/Mftf/ActionGroup/AdminDeleteUserRoleActionGroup.xml b/app/code/Magento/User/Test/Mftf/ActionGroup/AdminDeleteUserRoleActionGroup.xml new file mode 100644 index 0000000000000..d2c881b771973 --- /dev/null +++ b/app/code/Magento/User/Test/Mftf/ActionGroup/AdminDeleteUserRoleActionGroup.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminDeleteUserRoleActionGroup"> + <arguments> + <argument name="roleName" type="string"/> + </arguments> + <amOnPage url="{{AdminRolesPage.url}}" stepKey="navigateToUserRolesGrid" /> + <fillField selector="{{AdminRoleGridSection.roleNameFilterTextField}}" userInput="{{roleName}}" stepKey="enterRoleName" /> + <click selector="{{AdminDataGridHeaderSection.applyFilters}}" stepKey="clickSearch" /> + <see selector="{{AdminDataGridTableSection.row('1')}}" userInput="{{roleName}}" stepKey="seeUserRole" /> + <click selector="{{AdminDataGridTableSection.row('1')}}" stepKey="openRoleEditPage"/> + <waitForPageLoad stepKey="waitForRoleEditPageLoad"/> + <fillField selector="{{AdminEditRoleInfoSection.password}}" userInput="{{_ENV.MAGENTO_ADMIN_PASSWORD}}" stepKey="enterThePassword" /> + <click selector="{{AdminEditRoleInfoSection.deleteButton}}" stepKey="deleteUserRole"/> + <waitForElementVisible selector="{{AdminConfirmationModalSection.message}}" stepKey="waitForConfirmModal"/> + <click selector="{{AdminConfirmationModalSection.ok}}" stepKey="confirmDelete"/> + <waitForElementVisible selector="{{AdminMessagesSection.successMessage}}" stepKey="waitSuccessMessage"/> + <see selector="{{AdminMessagesSection.successMessage}}" userInput="You deleted the role." stepKey="seeUserRoleDeleteMessage"/> + </actionGroup> +</actionGroups> From cd2d8e0a6de2781c335ec267b741440b0d83a2f1 Mon Sep 17 00:00:00 2001 From: Viktor Petryk <victor.petryk@transoftgroup.com> Date: Thu, 27 Jun 2019 10:58:26 +0300 Subject: [PATCH 550/773] MC-17269: Date format grid is not based on the locale defined in the back-office --- .../Test/Mftf/ActionGroup/SetAdminAccountActionGroup.xml | 2 +- app/code/Magento/Ui/Component/Listing/Columns/Date.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Backend/Test/Mftf/ActionGroup/SetAdminAccountActionGroup.xml b/app/code/Magento/Backend/Test/Mftf/ActionGroup/SetAdminAccountActionGroup.xml index 885f1d3f1ecda..79aa5a02e1599 100644 --- a/app/code/Magento/Backend/Test/Mftf/ActionGroup/SetAdminAccountActionGroup.xml +++ b/app/code/Magento/Backend/Test/Mftf/ActionGroup/SetAdminAccountActionGroup.xml @@ -19,6 +19,6 @@ <fillField selector="{{AdminSystemAccountSection.currentPassword}}" userInput="{{_ENV.MAGENTO_ADMIN_PASSWORD}}" stepKey="fillPassword"/> <click selector="{{AdminMainActionsSection.save}}" stepKey="clickSave"/> <waitForElement selector="{{AdminCustomerMessagesSection.successMessage}}" stepKey="waitSuccessMessage"/> - <see selector="{{AdminCustomerMessagesSection.successMessage}}" userInput="You saved the account." stepKey="seeSuccessMessage"/> + <see selector="{{AdminMessagesSection.successMessage}}" userInput="You saved the account." stepKey="seeSuccessMessage"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/Ui/Component/Listing/Columns/Date.php b/app/code/Magento/Ui/Component/Listing/Columns/Date.php index fb73c52bc345b..1ca82ae321e66 100644 --- a/app/code/Magento/Ui/Component/Listing/Columns/Date.php +++ b/app/code/Magento/Ui/Component/Listing/Columns/Date.php @@ -54,8 +54,8 @@ class Date extends Column * @param BooleanUtils $booleanUtils * @param array $components * @param array $data - * @param ResolverInterface $localeResolver - * @param DataBundle $dataBundle + * @param ResolverInterface|null $localeResolver + * @param DataBundle|null $dataBundle */ public function __construct( ContextInterface $context, From d0ba3b629eed6db7c0971b1f1a0f9c2e8e94b2c7 Mon Sep 17 00:00:00 2001 From: Viktor Petryk <victor.petryk@transoftgroup.com> Date: Thu, 27 Jun 2019 10:58:41 +0300 Subject: [PATCH 551/773] MC-17269: Date format grid is not based on the locale defined in the back-office --- .../Test/AdminCheckingDateAfterChangeInterfaceLocaleTest.xml | 2 ++ 1 file changed, 2 insertions(+) rename app/code/Magento/{Ui => Sales}/Test/Mftf/Test/AdminCheckingDateAfterChangeInterfaceLocaleTest.xml (98%) diff --git a/app/code/Magento/Ui/Test/Mftf/Test/AdminCheckingDateAfterChangeInterfaceLocaleTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCheckingDateAfterChangeInterfaceLocaleTest.xml similarity index 98% rename from app/code/Magento/Ui/Test/Mftf/Test/AdminCheckingDateAfterChangeInterfaceLocaleTest.xml rename to app/code/Magento/Sales/Test/Mftf/Test/AdminCheckingDateAfterChangeInterfaceLocaleTest.xml index bfb4adbb2f2c3..add8f7d2ae2c3 100644 --- a/app/code/Magento/Ui/Test/Mftf/Test/AdminCheckingDateAfterChangeInterfaceLocaleTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminCheckingDateAfterChangeInterfaceLocaleTest.xml @@ -16,7 +16,9 @@ <severity value="MAJOR"/> <testCaseId value="MC-17761"/> <useCaseId value="MC-17269"/> + <group value="backend"/> <group value="ui"/> + <group value="sales"/> </annotations> <before> <!--Deploy static content with French locale--> From f35aaab34e06b5b96045198d850862982528c100 Mon Sep 17 00:00:00 2001 From: Viktor Petryk <victor.petryk@transoftgroup.com> Date: Thu, 27 Jun 2019 11:07:53 +0300 Subject: [PATCH 552/773] MC-17269: Date format grid is not based on the locale defined in the back-office --- .../Test/Mftf/ActionGroup/SetAdminAccountActionGroup.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Backend/Test/Mftf/ActionGroup/SetAdminAccountActionGroup.xml b/app/code/Magento/Backend/Test/Mftf/ActionGroup/SetAdminAccountActionGroup.xml index 79aa5a02e1599..ac9e4581dbefb 100644 --- a/app/code/Magento/Backend/Test/Mftf/ActionGroup/SetAdminAccountActionGroup.xml +++ b/app/code/Magento/Backend/Test/Mftf/ActionGroup/SetAdminAccountActionGroup.xml @@ -18,7 +18,7 @@ <selectOption userInput="{{InterfaceLocaleByValue}}" selector="{{AdminSystemAccountSection.interfaceLocale}}" stepKey="setInterfaceLocate"/> <fillField selector="{{AdminSystemAccountSection.currentPassword}}" userInput="{{_ENV.MAGENTO_ADMIN_PASSWORD}}" stepKey="fillPassword"/> <click selector="{{AdminMainActionsSection.save}}" stepKey="clickSave"/> - <waitForElement selector="{{AdminCustomerMessagesSection.successMessage}}" stepKey="waitSuccessMessage"/> + <waitForElement selector="{{AdminMessagesSection.successMessage}}" stepKey="waitSuccessMessage"/> <see selector="{{AdminMessagesSection.successMessage}}" userInput="You saved the account." stepKey="seeSuccessMessage"/> </actionGroup> </actionGroups> From 610dcff530b79ae89c3bb7ac557b4deec49c4d99 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <engcom-vendorworker-foxtrot@adobe.com> Date: Thu, 27 Jun 2019 13:05:19 +0300 Subject: [PATCH 553/773] magento/magento2#18075: Static test fix. --- setup/src/Magento/Setup/Model/Installer.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/setup/src/Magento/Setup/Model/Installer.php b/setup/src/Magento/Setup/Model/Installer.php index 254d45c14862a..d4ed261a9a945 100644 --- a/setup/src/Magento/Setup/Model/Installer.php +++ b/setup/src/Magento/Setup/Model/Installer.php @@ -363,6 +363,7 @@ public function install($request) foreach ($script as $item) { list($message, $method, $params) = $item; $this->log->log($message); + // phpcs:ignore Magento2.Functions.DiscouragedFunction call_user_func_array([$this, $method], $params); $this->logProgress(); } @@ -1247,6 +1248,7 @@ private function enableCaches() $cacheManager->clean($enabledTypes); $this->log->log('Current status:'); + // phpcs:ignore Magento2.Functions.DiscouragedFunction $this->log->log(print_r($cacheManager->getStatus(), true)); } From 4adee3b19c1396251d29c54df3eb874d5c985388 Mon Sep 17 00:00:00 2001 From: Matti Vapa <matti.vapa@piimega.fi> Date: Thu, 27 Jun 2019 16:19:56 +0300 Subject: [PATCH 554/773] Fix missing attribute_id condition from filter This commit adds a missing attribute_id condition to the addAttributeToFilterAllStores method in product dataprovider. Previously the method did not include the attribute_id as a condition. This meant that it was impossible to filter by status as any value of 1 or 2 in the catalog_product_entity_int table would match the condition. --- .../Catalog/Ui/DataProvider/Product/ProductCollection.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/code/Magento/Catalog/Ui/DataProvider/Product/ProductCollection.php b/app/code/Magento/Catalog/Ui/DataProvider/Product/ProductCollection.php index e5451c8e49847..ea8fc6f2d83b2 100644 --- a/app/code/Magento/Catalog/Ui/DataProvider/Product/ProductCollection.php +++ b/app/code/Magento/Catalog/Ui/DataProvider/Product/ProductCollection.php @@ -84,8 +84,11 @@ private function addAttributeToFilterAllStores(Attribute $attributeModel, array $entity = $this->getEntity(); $fKey = 'e.' . $this->getEntityPkName($entity); $pKey = $tableName . '.' . $this->getEntityPkName($entity); + $attributeId = $attributeModel->getAttributeId(); $condition = "({$pKey} = {$fKey}) AND (" . $this->_getConditionSql("{$tableName}.value", $condition) + . ') AND (' + . $this->_getConditionSql("{$tableName}.attribute_id", $attributeId) . ')'; $selectExistsInAllStores = $this->getConnection()->select()->from($tableName); $this->getSelect()->exists($selectExistsInAllStores, $condition); From 765f3804e919e5f06f4941eb4a227258befe2995 Mon Sep 17 00:00:00 2001 From: Yaroslav Rogoza <enarc@atwix.com> Date: Thu, 27 Jun 2019 16:35:20 +0200 Subject: [PATCH 555/773] Use store from context (extension attributes) --- .../Model/Resolver/Category/SortFields.php | 2 +- .../Model/Resolver/Product/Price.php | 26 +++------ .../Resolver/Product/ProductImage/Label.php | 2 +- .../Model/Resolver/DataProvider/Page.php | 15 ++---- .../CmsGraphQl/Model/Resolver/Page.php | 5 +- .../Model/Customer/CreateCustomerAccount.php | 22 +++----- .../Model/Customer/UpdateCustomerAccount.php | 8 +-- .../Model/Resolver/CreateCustomer.php | 2 +- .../Model/Resolver/UpdateCustomer.php | 2 +- .../Model/Resolver/PaypalExpressToken.php | 3 +- .../Model/Cart/GetCartForUser.php | 16 ++---- .../Resolver/AddSimpleProductsToCart.php | 3 +- .../Model/Resolver/ApplyCouponToCart.php | 3 +- .../QuoteGraphQl/Model/Resolver/Cart.php | 3 +- .../Model/Resolver/PlaceOrder.php | 3 +- .../Model/Resolver/RemoveCouponFromCart.php | 3 +- .../Model/Resolver/RemoveItemFromCart.php | 3 +- .../Resolver/SetBillingAddressOnCart.php | 3 +- .../Model/Resolver/SetGuestEmailOnCart.php | 3 +- .../Resolver/SetPaymentAndPlaceOrder.php | 3 +- .../Model/Resolver/SetPaymentMethodOnCart.php | 3 +- .../Resolver/SetShippingAddressesOnCart.php | 3 +- .../Resolver/SetShippingMethodsOnCart.php | 3 +- .../AvailableShippingMethods.php | 23 ++++---- .../SelectedShippingMethod.php | 17 +----- .../Model/Resolver/UpdateCartItems.php | 3 +- .../Model/Context/AddStoreInfoToContext.php | 43 +++++++++++++++ .../Plugin/Query/Resolver/ContextFactory.php | 53 ------------------- .../Store/StoreConfigDataProvider.php | 25 +++------ .../Model/Resolver/StoreConfigResolver.php | 2 +- .../StoreGraphQl/etc/extension_attributes.xml | 4 +- .../Magento/StoreGraphQl/etc/graphql/di.xml | 8 ++- .../Model/Resolver/EntityUrl.php | 2 +- 33 files changed, 132 insertions(+), 187 deletions(-) create mode 100644 app/code/Magento/StoreGraphQl/Model/Context/AddStoreInfoToContext.php delete mode 100644 app/code/Magento/StoreGraphQl/Model/Plugin/Query/Resolver/ContextFactory.php diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Category/SortFields.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Category/SortFields.php index fc8f6accbb226..44ea0222ba59d 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Resolver/Category/SortFields.php +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Category/SortFields.php @@ -46,7 +46,7 @@ public function __construct( public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null) { $sortFieldsOptions = $this->sortbyAttributeSource->getAllOptions(); - $storeId = $context->getStoreId(); + $storeId = (int)$context->getExtensionAttributes()->getStore()->getId(); array_walk( $sortFieldsOptions, diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/Price.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/Price.php index 4eb85fced8ab6..c542fc26495f7 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/Price.php +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/Price.php @@ -18,32 +18,24 @@ use Magento\Framework\Pricing\Adjustment\AdjustmentInterface; use Magento\Framework\Pricing\Amount\AmountInterface; use Magento\Framework\Pricing\PriceInfo\Factory as PriceInfoFactory; -use Magento\Store\Model\StoreManagerInterface; +use Magento\Store\Api\Data\StoreInterface; /** * Format a product's price information to conform to GraphQL schema representation */ class Price implements ResolverInterface { - /** - * @var StoreManagerInterface - */ - private $storeManager; - /** * @var PriceInfoFactory */ private $priceInfoFactory; /** - * @param StoreManagerInterface $storeManager * @param PriceInfoFactory $priceInfoFactory */ public function __construct( - StoreManagerInterface $storeManager, PriceInfoFactory $priceInfoFactory ) { - $this->storeManager = $storeManager; $this->priceInfoFactory = $priceInfoFactory; } @@ -80,20 +72,20 @@ public function resolve( $minimalPriceAmount = $finalPrice->getMinimalPrice(); $maximalPriceAmount = $finalPrice->getMaximalPrice(); $regularPriceAmount = $priceInfo->getPrice(RegularPrice::PRICE_CODE)->getAmount(); - $storeId = $context->getStoreId(); + $store = $context->getExtensionAttributes()->getStore(); $prices = [ 'minimalPrice' => $this->createAdjustmentsArray( $priceInfo->getAdjustments(), $minimalPriceAmount, - $storeId + $store ), 'regularPrice' => $this->createAdjustmentsArray( $priceInfo->getAdjustments(), $regularPriceAmount, - $storeId + $store ), - 'maximalPrice' => $this->createAdjustmentsArray($priceInfo->getAdjustments(), $maximalPriceAmount, $storeId) + 'maximalPrice' => $this->createAdjustmentsArray($priceInfo->getAdjustments(), $maximalPriceAmount, $store) ]; return $prices; @@ -104,15 +96,11 @@ public function resolve( * * @param AdjustmentInterface[] $adjustments * @param AmountInterface $amount - * @param int $storeId + * @param StoreInterface $store * @return array - * @throws \Magento\Framework\Exception\NoSuchEntityException */ - private function createAdjustmentsArray(array $adjustments, AmountInterface $amount, int $storeId) : array + private function createAdjustmentsArray(array $adjustments, AmountInterface $amount, StoreInterface $store) : array { - /** @var \Magento\Store\Model\Store $store */ - $store = $this->storeManager->getStore($storeId); - $priceArray = [ 'amount' => [ 'value' => $amount->getValue(), diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/ProductImage/Label.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/ProductImage/Label.php index 30de2f33c7da7..978bbfb01ff1b 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/ProductImage/Label.php +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/ProductImage/Label.php @@ -56,7 +56,7 @@ public function resolve( $imageType = $value['image_type']; $imagePath = $product->getData($imageType); $productId = (int)$product->getEntityId(); - $storeId = $context->getStoreId(); + $storeId = (int)$context->getExtensionAttributes()->getStore()->getId(); // null if image is not set if (null === $imagePath) { diff --git a/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/Page.php b/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/Page.php index 40825e70a994e..9ca215368ab5f 100644 --- a/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/Page.php +++ b/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/Page.php @@ -11,7 +11,6 @@ use Magento\Cms\Api\GetPageByIdentifierInterface; use Magento\Cms\Api\PageRepositoryInterface; use Magento\Framework\Exception\NoSuchEntityException; -use Magento\Store\Model\StoreManagerInterface; use Magento\Widget\Model\Template\FilterEmulate; /** @@ -29,11 +28,6 @@ class Page */ private $pageRepository; - /** - * @var StoreManagerInterface - */ - private $storeManager; - /** * @var FilterEmulate */ @@ -43,19 +37,16 @@ class Page * @param PageRepositoryInterface $pageRepository * @param FilterEmulate $widgetFilter * @param GetPageByIdentifierInterface $getPageByIdentifier - * @param StoreManagerInterface $storeManager */ public function __construct( PageRepositoryInterface $pageRepository, FilterEmulate $widgetFilter, - GetPageByIdentifierInterface $getPageByIdentifier, - StoreManagerInterface $storeManager + GetPageByIdentifierInterface $getPageByIdentifier ) { $this->pageRepository = $pageRepository; $this->widgetFilter = $widgetFilter; $this->pageByIdentifier = $getPageByIdentifier; - $this->storeManager = $storeManager; } /** @@ -76,12 +67,12 @@ public function getDataByPageId(int $pageId): array * Returns page data by page identifier * * @param string $pageIdentifier + * @param int $storeId * @return array * @throws NoSuchEntityException */ - public function getDataByPageIdentifier(string $pageIdentifier): array + public function getDataByPageIdentifier(string $pageIdentifier, int $storeId): array { - $storeId = (int)$this->storeManager->getStore()->getId(); $page = $this->pageByIdentifier->execute($pageIdentifier, $storeId); return $this->convertPageData($page); diff --git a/app/code/Magento/CmsGraphQl/Model/Resolver/Page.php b/app/code/Magento/CmsGraphQl/Model/Resolver/Page.php index 64891cfeaa87a..7d03de7c4d0c3 100644 --- a/app/code/Magento/CmsGraphQl/Model/Resolver/Page.php +++ b/app/code/Magento/CmsGraphQl/Model/Resolver/Page.php @@ -55,7 +55,10 @@ public function resolve( if (isset($args['id'])) { $pageData = $this->pageDataProvider->getDataByPageId((int)$args['id']); } elseif (isset($args['identifier'])) { - $pageData = $this->pageDataProvider->getDataByPageIdentifier((string)$args['identifier']); + $pageData = $this->pageDataProvider->getDataByPageIdentifier( + (string)$args['identifier'], + (int)$context->getExtensionAttributes()->getStore()->getId() + ); } } catch (NoSuchEntityException $e) { throw new GraphQlNoSuchEntityException(__($e->getMessage()), $e); diff --git a/app/code/Magento/CustomerGraphQl/Model/Customer/CreateCustomerAccount.php b/app/code/Magento/CustomerGraphQl/Model/Customer/CreateCustomerAccount.php index 285c76874cad4..eada473b61e1f 100644 --- a/app/code/Magento/CustomerGraphQl/Model/Customer/CreateCustomerAccount.php +++ b/app/code/Magento/CustomerGraphQl/Model/Customer/CreateCustomerAccount.php @@ -13,7 +13,7 @@ use Magento\Framework\Api\DataObjectHelper; use Magento\Framework\Exception\LocalizedException; use Magento\Framework\GraphQl\Exception\GraphQlInputException; -use Magento\Store\Model\StoreManagerInterface; +use Magento\Store\Api\Data\StoreInterface; /** * Create new customer account @@ -35,11 +35,6 @@ class CreateCustomerAccount */ private $accountManagement; - /** - * @var StoreManagerInterface - */ - private $storeManager; - /** * @var ChangeSubscriptionStatus */ @@ -48,21 +43,18 @@ class CreateCustomerAccount /** * @param DataObjectHelper $dataObjectHelper * @param CustomerInterfaceFactory $customerFactory - * @param StoreManagerInterface $storeManager * @param AccountManagementInterface $accountManagement * @param ChangeSubscriptionStatus $changeSubscriptionStatus */ public function __construct( DataObjectHelper $dataObjectHelper, CustomerInterfaceFactory $customerFactory, - StoreManagerInterface $storeManager, AccountManagementInterface $accountManagement, ChangeSubscriptionStatus $changeSubscriptionStatus ) { $this->dataObjectHelper = $dataObjectHelper; $this->customerFactory = $customerFactory; $this->accountManagement = $accountManagement; - $this->storeManager = $storeManager; $this->changeSubscriptionStatus = $changeSubscriptionStatus; } @@ -70,14 +62,14 @@ public function __construct( * Creates new customer account * * @param array $data - * @param int $storeId + * @param StoreInterface $store * @return CustomerInterface * @throws GraphQlInputException */ - public function execute(array $data, int $storeId): CustomerInterface + public function execute(array $data, StoreInterface $store): CustomerInterface { try { - $customer = $this->createAccount($data, $storeId); + $customer = $this->createAccount($data, $store); } catch (LocalizedException $e) { throw new GraphQlInputException(__($e->getMessage())); } @@ -92,12 +84,11 @@ public function execute(array $data, int $storeId): CustomerInterface * Create account * * @param array $data - * @param int $storeId + * @param StoreInterface $store * @return CustomerInterface * @throws LocalizedException - * @throws \Magento\Framework\Exception\NoSuchEntityException */ - private function createAccount(array $data, int $storeId): CustomerInterface + private function createAccount(array $data, StoreInterface $store): CustomerInterface { $customerDataObject = $this->customerFactory->create(); $this->dataObjectHelper->populateWithArray( @@ -105,7 +96,6 @@ private function createAccount(array $data, int $storeId): CustomerInterface $data, CustomerInterface::class ); - $store = $this->storeManager->getStore($storeId); $customerDataObject->setWebsiteId($store->getWebsiteId()); $customerDataObject->setStoreId($store->getId()); diff --git a/app/code/Magento/CustomerGraphQl/Model/Customer/UpdateCustomerAccount.php b/app/code/Magento/CustomerGraphQl/Model/Customer/UpdateCustomerAccount.php index 865baaf1faffb..161471c86a561 100644 --- a/app/code/Magento/CustomerGraphQl/Model/Customer/UpdateCustomerAccount.php +++ b/app/code/Magento/CustomerGraphQl/Model/Customer/UpdateCustomerAccount.php @@ -12,6 +12,7 @@ use Magento\Framework\GraphQl\Exception\GraphQlInputException; use Magento\Customer\Api\Data\CustomerInterface; use Magento\Framework\Api\DataObjectHelper; +use Magento\Store\Api\Data\StoreInterface; /** * Update customer account data @@ -69,13 +70,14 @@ public function __construct( * * @param CustomerInterface $customer * @param array $data - * @param int $storeId + * @param StoreInterface $store * @return void * @throws GraphQlAlreadyExistsException * @throws GraphQlAuthenticationException * @throws GraphQlInputException + * @throws \Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException */ - public function execute(CustomerInterface $customer, array $data, int $storeId): void + public function execute(CustomerInterface $customer, array $data, StoreInterface $store): void { if (isset($data['email']) && $customer->getEmail() !== $data['email']) { if (!isset($data['password']) || empty($data['password'])) { @@ -89,7 +91,7 @@ public function execute(CustomerInterface $customer, array $data, int $storeId): $filteredData = array_diff_key($data, array_flip($this->restrictedKeys)); $this->dataObjectHelper->populateWithArray($customer, $filteredData, CustomerInterface::class); - $customer->setStoreId($storeId); + $customer->setStoreId($store->getId()); $this->saveCustomer->execute($customer); diff --git a/app/code/Magento/CustomerGraphQl/Model/Resolver/CreateCustomer.php b/app/code/Magento/CustomerGraphQl/Model/Resolver/CreateCustomer.php index f0546547d4e9e..6bd3cb7f52c85 100644 --- a/app/code/Magento/CustomerGraphQl/Model/Resolver/CreateCustomer.php +++ b/app/code/Magento/CustomerGraphQl/Model/Resolver/CreateCustomer.php @@ -55,7 +55,7 @@ public function resolve( throw new GraphQlInputException(__('"input" value should be specified')); } - $customer = $this->createCustomerAccount->execute($args['input'], $context->getStoreId()); + $customer = $this->createCustomerAccount->execute($args['input'], $context->getExtensionAttributes()->getStore()); $data = $this->extractCustomerData->execute($customer); return ['customer' => $data]; diff --git a/app/code/Magento/CustomerGraphQl/Model/Resolver/UpdateCustomer.php b/app/code/Magento/CustomerGraphQl/Model/Resolver/UpdateCustomer.php index 3547cf4b1a2f5..b585844eb4484 100644 --- a/app/code/Magento/CustomerGraphQl/Model/Resolver/UpdateCustomer.php +++ b/app/code/Magento/CustomerGraphQl/Model/Resolver/UpdateCustomer.php @@ -72,7 +72,7 @@ public function resolve( } $customer = $this->getCustomer->execute($context); - $this->updateCustomerAccount->execute($customer, $args['input'], $context->getStoreId()); + $this->updateCustomerAccount->execute($customer, $args['input'], $context->getExtensionAttributes()->getStore()); $data = $this->extractCustomerData->execute($customer); return ['customer' => $data]; diff --git a/app/code/Magento/PaypalGraphQl/Model/Resolver/PaypalExpressToken.php b/app/code/Magento/PaypalGraphQl/Model/Resolver/PaypalExpressToken.php index 0c6449fc9d230..89db082e715c4 100644 --- a/app/code/Magento/PaypalGraphQl/Model/Resolver/PaypalExpressToken.php +++ b/app/code/Magento/PaypalGraphQl/Model/Resolver/PaypalExpressToken.php @@ -85,7 +85,8 @@ public function resolve( $usedExpressButton = isset($args['input']['express_button']) ? $args['input']['express_button'] : false; $customerId = $context->getUserId(); - $cart = $this->getCartForUser->execute($cartId, $customerId); + $storeId = (int)$context->getExtensionAttributes()->getStore()->getId(); + $cart = $this->getCartForUser->execute($cartId, $customerId, $storeId); $config = $this->configProvider->getConfig($paymentCode); $checkout = $this->checkoutProvider->getCheckout($config, $cart); diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/GetCartForUser.php b/app/code/Magento/QuoteGraphQl/Model/Cart/GetCartForUser.php index 9c57550295413..af70809a1053d 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/GetCartForUser.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/GetCartForUser.php @@ -13,7 +13,6 @@ use Magento\Quote\Api\CartRepositoryInterface; use Magento\Quote\Model\MaskedQuoteIdToQuoteIdInterface; use Magento\Quote\Model\Quote; -use Magento\Store\Model\StoreManagerInterface; /** * Get cart @@ -30,24 +29,16 @@ class GetCartForUser */ private $cartRepository; - /** - * @var StoreManagerInterface - */ - private $storeManager; - /** * @param MaskedQuoteIdToQuoteIdInterface $maskedQuoteIdToQuoteId * @param CartRepositoryInterface $cartRepository - * @param StoreManagerInterface $storeManager */ public function __construct( MaskedQuoteIdToQuoteIdInterface $maskedQuoteIdToQuoteId, - CartRepositoryInterface $cartRepository, - StoreManagerInterface $storeManager + CartRepositoryInterface $cartRepository ) { $this->maskedQuoteIdToQuoteId = $maskedQuoteIdToQuoteId; $this->cartRepository = $cartRepository; - $this->storeManager = $storeManager; } /** @@ -55,12 +46,13 @@ public function __construct( * * @param string $cartHash * @param int|null $customerId + * @param int $storeId * @return Quote * @throws GraphQlAuthorizationException * @throws GraphQlNoSuchEntityException * @throws NoSuchEntityException */ - public function execute(string $cartHash, ?int $customerId): Quote + public function execute(string $cartHash, ?int $customerId, int $storeId): Quote { try { $cartId = $this->maskedQuoteIdToQuoteId->execute($cartHash); @@ -85,7 +77,7 @@ public function execute(string $cartHash, ?int $customerId): Quote ); } - if ((int)$cart->getStoreId() !== (int)$this->storeManager->getStore()->getId()) { + if ((int)$cart->getStoreId() !== $storeId) { throw new GraphQlNoSuchEntityException( __( 'Wrong store code specified for cart "%masked_cart_id"', diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/AddSimpleProductsToCart.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/AddSimpleProductsToCart.php index 9876938c08bc6..2948994cf0ba3 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/AddSimpleProductsToCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/AddSimpleProductsToCart.php @@ -59,7 +59,8 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value } $cartItems = $args['input']['cart_items']; - $cart = $this->getCartForUser->execute($maskedCartId, $context->getUserId()); + $storeId = (int)$context->getExtensionAttributes()->getStore()->getId(); + $cart = $this->getCartForUser->execute($maskedCartId, $context->getUserId(), $storeId); $this->addProductsToCart->execute($cart, $cartItems); return [ diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/ApplyCouponToCart.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/ApplyCouponToCart.php index 84d2183eeac73..ddd7d25943baa 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/ApplyCouponToCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/ApplyCouponToCart.php @@ -61,7 +61,8 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value $couponCode = $args['input']['coupon_code']; $currentUserId = $context->getUserId(); - $cart = $this->getCartForUser->execute($maskedCartId, $currentUserId); + $storeId = (int)$context->getExtensionAttributes()->getStore()->getId(); + $cart = $this->getCartForUser->execute($maskedCartId, $currentUserId, $storeId); $cartId = $cart->getId(); /* Check current cart does not have coupon code applied */ diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/Cart.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/Cart.php index 16fd639685b82..34812c3eac410 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/Cart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/Cart.php @@ -43,7 +43,8 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value $maskedCartId = $args['cart_id']; $currentUserId = $context->getUserId(); - $cart = $this->getCartForUser->execute($maskedCartId, $currentUserId); + $storeId = $storeId = (int)$context->getExtensionAttributes()->getStore()->getId(); + $cart = $this->getCartForUser->execute($maskedCartId, $currentUserId, $storeId); return [ 'model' => $cart, diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/PlaceOrder.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/PlaceOrder.php index 51cea7e3b3652..1a0740a75c8f8 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/PlaceOrder.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/PlaceOrder.php @@ -72,7 +72,8 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value } $maskedCartId = $args['input']['cart_id']; - $cart = $this->getCartForUser->execute($maskedCartId, $context->getUserId()); + $storeId = (int)$context->getExtensionAttributes()->getStore()->getId(); + $cart = $this->getCartForUser->execute($maskedCartId, $context->getUserId(), $storeId); $this->checkCartCheckoutAllowance->execute($cart); if ((int)$context->getUserId() === 0) { diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/RemoveCouponFromCart.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/RemoveCouponFromCart.php index 291dd9c507ebd..f5b768d0dcb0b 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/RemoveCouponFromCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/RemoveCouponFromCart.php @@ -56,7 +56,8 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value $maskedCartId = $args['input']['cart_id']; $currentUserId = $context->getUserId(); - $cart = $this->getCartForUser->execute($maskedCartId, $currentUserId); + $storeId = (int)$context->getExtensionAttributes()->getStore()->getId(); + $cart = $this->getCartForUser->execute($maskedCartId, $currentUserId, $storeId); $cartId = $cart->getId(); try { diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/RemoveItemFromCart.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/RemoveItemFromCart.php index 0dc7274bd474e..bf9ccef8ae44a 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/RemoveItemFromCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/RemoveItemFromCart.php @@ -59,7 +59,8 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value } $itemId = $args['input']['cart_item_id']; - $cart = $this->getCartForUser->execute($maskedCartId, $context->getUserId()); + $storeId = (int)$context->getExtensionAttributes()->getStore()->getId(); + $cart = $this->getCartForUser->execute($maskedCartId, $context->getUserId(), $storeId); try { $this->cartItemRepository->deleteById((int)$cart->getId(), $itemId); diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/SetBillingAddressOnCart.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/SetBillingAddressOnCart.php index a56fabae2732b..c315aa9b14146 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/SetBillingAddressOnCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/SetBillingAddressOnCart.php @@ -65,7 +65,8 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value } $billingAddress = $args['input']['billing_address']; - $cart = $this->getCartForUser->execute($maskedCartId, $context->getUserId()); + $storeId = $storeId = (int)$context->getExtensionAttributes()->getStore()->getId(); + $cart = $this->getCartForUser->execute($maskedCartId, $context->getUserId(), $storeId); $this->checkCartCheckoutAllowance->execute($cart); $this->setBillingAddressOnCart->execute($context, $cart, $billingAddress); diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/SetGuestEmailOnCart.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/SetGuestEmailOnCart.php index a029f447e369f..b951151e27c68 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/SetGuestEmailOnCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/SetGuestEmailOnCart.php @@ -86,7 +86,8 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value throw new GraphQlInputException(__('The request is not allowed for logged in customers')); } - $cart = $this->getCartForUser->execute($maskedCartId, $currentUserId); + $storeId = (int)$context->getExtensionAttributes()->getStore()->getId(); + $cart = $this->getCartForUser->execute($maskedCartId, $currentUserId, $storeId); $this->checkCartCheckoutAllowance->execute($cart); $cart->setCustomerEmail($email); diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/SetPaymentAndPlaceOrder.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/SetPaymentAndPlaceOrder.php index 10ce62e49c53d..0efbde5d6b218 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/SetPaymentAndPlaceOrder.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/SetPaymentAndPlaceOrder.php @@ -77,7 +77,8 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value } $paymentData = $args['input']['payment_method']; - $cart = $this->getCartForUser->execute($maskedCartId, $context->getUserId()); + $storeId = (int)$context->getExtensionAttributes()->getStore()->getId(); + $cart = $this->getCartForUser->execute($maskedCartId, $context->getUserId(), $storeId); if ((int)$context->getUserId() === 0) { if (!$cart->getCustomerEmail()) { diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/SetPaymentMethodOnCart.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/SetPaymentMethodOnCart.php index e8b663ed612e5..fb6c1e678f1f0 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/SetPaymentMethodOnCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/SetPaymentMethodOnCart.php @@ -65,7 +65,8 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value } $paymentData = $args['input']['payment_method']; - $cart = $this->getCartForUser->execute($maskedCartId, $context->getUserId()); + $storeId = (int)$context->getExtensionAttributes()->getStore()->getId(); + $cart = $this->getCartForUser->execute($maskedCartId, $context->getUserId(), $storeId); $this->checkCartCheckoutAllowance->execute($cart); $this->setPaymentMethodOnCart->execute($cart, $paymentData); diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/SetShippingAddressesOnCart.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/SetShippingAddressesOnCart.php index b61addabf417a..d86244b2d8fc3 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/SetShippingAddressesOnCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/SetShippingAddressesOnCart.php @@ -65,7 +65,8 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value } $shippingAddresses = $args['input']['shipping_addresses']; - $cart = $this->getCartForUser->execute($maskedCartId, $context->getUserId()); + $storeId = (int)$context->getExtensionAttributes()->getStore()->getId(); + $cart = $this->getCartForUser->execute($maskedCartId, $context->getUserId(), $storeId); $this->checkCartCheckoutAllowance->execute($cart); $this->setShippingAddressesOnCart->execute($context, $cart, $shippingAddresses); diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/SetShippingMethodsOnCart.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/SetShippingMethodsOnCart.php index 6c8bb4b24f46c..e1cd9c18d9873 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/SetShippingMethodsOnCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/SetShippingMethodsOnCart.php @@ -65,7 +65,8 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value } $shippingMethods = $args['input']['shipping_methods']; - $cart = $this->getCartForUser->execute($maskedCartId, $context->getUserId()); + $storeId = (int)$context->getExtensionAttributes()->getStore()->getId(); + $cart = $this->getCartForUser->execute($maskedCartId, $context->getUserId(), $storeId); $this->checkCartCheckoutAllowance->execute($cart); $this->setShippingMethodsOnCart->execute($context, $cart, $shippingMethods); diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/AvailableShippingMethods.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/AvailableShippingMethods.php index 958934ed18032..e5dd1d73b80b5 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/AvailableShippingMethods.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/AvailableShippingMethods.php @@ -16,7 +16,7 @@ use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; use Magento\Quote\Api\Data\ShippingMethodInterface; use Magento\Quote\Model\Cart\ShippingMethodConverter; -use Magento\Store\Model\StoreManagerInterface; +use Magento\Store\Api\Data\StoreInterface; /** * @inheritdoc @@ -33,24 +33,16 @@ class AvailableShippingMethods implements ResolverInterface */ private $shippingMethodConverter; - /** - * @var StoreManagerInterface - */ - private $storeManager; - /** * @param ExtensibleDataObjectConverter $dataObjectConverter * @param ShippingMethodConverter $shippingMethodConverter - * @param StoreManagerInterface $storeManager */ public function __construct( ExtensibleDataObjectConverter $dataObjectConverter, - ShippingMethodConverter $shippingMethodConverter, - StoreManagerInterface $storeManager + ShippingMethodConverter $shippingMethodConverter ) { $this->dataObjectConverter = $dataObjectConverter; $this->shippingMethodConverter = $shippingMethodConverter; - $this->storeManager = $storeManager; } /** @@ -81,7 +73,11 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value [], ShippingMethodInterface::class ); - $methods[] = $this->processMoneyTypeData($methodData, $cart->getQuoteCurrencyCode()); + $methods[] = $this->processMoneyTypeData( + $methodData, + $cart->getQuoteCurrencyCode(), + $context->getExtensionAttributes()->getStore() + ); } } return $methods; @@ -92,10 +88,11 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value * * @param array $data * @param string $quoteCurrencyCode + * @param StoreInterface $store * @return array * @throws NoSuchEntityException */ - private function processMoneyTypeData(array $data, string $quoteCurrencyCode): array + private function processMoneyTypeData(array $data, string $quoteCurrencyCode, StoreInterface $store): array { if (isset($data['amount'])) { $data['amount'] = ['value' => $data['amount'], 'currency' => $quoteCurrencyCode]; @@ -103,7 +100,7 @@ private function processMoneyTypeData(array $data, string $quoteCurrencyCode): a if (isset($data['base_amount'])) { /** @var Currency $currency */ - $currency = $this->storeManager->getStore()->getBaseCurrency(); + $currency = $store->getBaseCurrency(); $data['base_amount'] = ['value' => $data['base_amount'], 'currency' => $currency->getCode()]; } diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/SelectedShippingMethod.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/SelectedShippingMethod.php index b359971880036..f2dacf6d007f3 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/SelectedShippingMethod.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/SelectedShippingMethod.php @@ -14,27 +14,12 @@ use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; use Magento\Quote\Model\Quote\Address; use Magento\Quote\Model\Quote\Address\Rate; -use Magento\Store\Model\StoreManagerInterface; /** * @inheritdoc */ class SelectedShippingMethod implements ResolverInterface { - /** - * @var StoreManagerInterface - */ - private $storeManager; - - /** - * @param StoreManagerInterface $storeManager - */ - public function __construct( - StoreManagerInterface $storeManager - ) { - $this->storeManager = $storeManager; - } - /** * @inheritdoc */ @@ -62,7 +47,7 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value } /** @var Currency $currency */ - $currency = $this->storeManager->getStore()->getBaseCurrency(); + $currency = $context->getExtensionAttributes()->getStore()->getBaseCurrency(); $data = [ 'carrier_code' => $carrierCode, diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/UpdateCartItems.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/UpdateCartItems.php index fa115db144e32..968d25ddd68b5 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/UpdateCartItems.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/UpdateCartItems.php @@ -63,7 +63,8 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value } $cartItems = $args['input']['cart_items']; - $cart = $this->getCartForUser->execute($maskedCartId, $context->getUserId()); + $storeId = (int)$context->getExtensionAttributes()->getStore()->getId(); + $cart = $this->getCartForUser->execute($maskedCartId, $context->getUserId(), $storeId); try { $this->processCartItems($cart, $cartItems); diff --git a/app/code/Magento/StoreGraphQl/Model/Context/AddStoreInfoToContext.php b/app/code/Magento/StoreGraphQl/Model/Context/AddStoreInfoToContext.php new file mode 100644 index 0000000000000..f894b1251ecb8 --- /dev/null +++ b/app/code/Magento/StoreGraphQl/Model/Context/AddStoreInfoToContext.php @@ -0,0 +1,43 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\StoreGraphQl\Model\Context; + +use Magento\GraphQl\Model\Query\ContextParametersInterface; +use Magento\GraphQl\Model\Query\ContextParametersProcessorInterface; +use Magento\Store\Model\StoreManagerInterface; + +/** + * @inheritdoc + */ +class AddStoreInfoToContext implements ContextParametersProcessorInterface +{ + /** + * @var StoreManagerInterface + */ + private $storeManager; + + /** + * @param StoreManagerInterface $storeManager + */ + public function __construct( + StoreManagerInterface $storeManager + ) { + $this->storeManager = $storeManager; + } + + /** + * @inheritdoc + */ + public function execute(ContextParametersInterface $contextParameters): ContextParametersInterface + { + $currentStore = $this->storeManager->getStore(); + $contextParameters->addExtensionAttribute('store', $currentStore); + + return $contextParameters; + } +} diff --git a/app/code/Magento/StoreGraphQl/Model/Plugin/Query/Resolver/ContextFactory.php b/app/code/Magento/StoreGraphQl/Model/Plugin/Query/Resolver/ContextFactory.php deleted file mode 100644 index 8025a87c4d6c4..0000000000000 --- a/app/code/Magento/StoreGraphQl/Model/Plugin/Query/Resolver/ContextFactory.php +++ /dev/null @@ -1,53 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -declare(strict_types=1); - -namespace Magento\StoreGraphQl\Model\Plugin\Query\Resolver; - -use Magento\Framework\GraphQl\Query\Resolver\ContextInterface; -use Magento\Store\Model\StoreManagerInterface; -use Magento\GraphQl\Model\Query\Resolver\ContextFactory as ResolverContextFactory; -use Magento\Framework\Exception\NoSuchEntityException; - -/** - * Plugin for injecting store information into resolver context - */ -class ContextFactory -{ - /** - * @var StoreManagerInterface - */ - private $storeManager; - - /** - * @param StoreManagerInterface $storeManager - */ - public function __construct( - StoreManagerInterface $storeManager - ) { - $this->storeManager = $storeManager; - } - - - /** - * @param ResolverContextFactory $subject - * @param ContextInterface $resultContext - * @return ContextInterface - * - * @throws NoSuchEntityException - * @SuppressWarnings(PHPMD.UnusedFormalParameter) - */ - public function afterCreate( - ResolverContextFactory $subject, - ContextInterface $resultContext - ) { - $extensionAttributes = $resultContext->getExtensionAttributes(); - $extensionAttributes->setStoreId((int)$this->storeManager->getStore()->getId()); - $resultContext->setExtensionAttributes($extensionAttributes); - - return $resultContext; - } -} diff --git a/app/code/Magento/StoreGraphQl/Model/Resolver/Store/StoreConfigDataProvider.php b/app/code/Magento/StoreGraphQl/Model/Resolver/Store/StoreConfigDataProvider.php index c101a33adfdbc..59f9831789a35 100644 --- a/app/code/Magento/StoreGraphQl/Model/Resolver/Store/StoreConfigDataProvider.php +++ b/app/code/Magento/StoreGraphQl/Model/Resolver/Store/StoreConfigDataProvider.php @@ -10,7 +10,7 @@ use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Store\Api\StoreConfigManagerInterface; use Magento\Store\Model\ScopeInterface; -use Magento\Store\Model\StoreManagerInterface; +use Magento\Store\Api\Data\StoreInterface; /** * StoreConfig field data provider, used for GraphQL request processing. @@ -22,11 +22,6 @@ class StoreConfigDataProvider */ private $storeConfigManager; - /** - * @var StoreManagerInterface - */ - private $storeManager; - /** * @var ScopeConfigInterface */ @@ -39,18 +34,15 @@ class StoreConfigDataProvider /** * @param StoreConfigManagerInterface $storeConfigManager - * @param StoreManagerInterface $storeManager * @param ScopeConfigInterface $scopeConfig * @param array $extendedConfigData */ public function __construct( StoreConfigManagerInterface $storeConfigManager, - StoreManagerInterface $storeManager, ScopeConfigInterface $scopeConfig, array $extendedConfigData = [] ) { $this->storeConfigManager = $storeConfigManager; - $this->storeManager = $storeManager; $this->scopeConfig = $scopeConfig; $this->extendedConfigData = $extendedConfigData; } @@ -58,15 +50,14 @@ public function __construct( /** * Get store config data * - * @param int $storeId + * @param StoreInterface $store * @return array - * @throws \Magento\Framework\Exception\NoSuchEntityException */ - public function getStoreConfigData(int $storeId): array + public function getStoreConfigData(StoreInterface $store): array { $storeConfigData = array_merge( - $this->getBaseConfigData($storeId), - $this->getExtendedConfigData($storeId) + $this->getBaseConfigData($store), + $this->getExtendedConfigData((int)$store->getId()) ); return $storeConfigData; } @@ -74,13 +65,11 @@ public function getStoreConfigData(int $storeId): array /** * Get base config data * - * @param int $storeId + * @param StoreInterface $store * @return array - * @throws \Magento\Framework\Exception\NoSuchEntityException */ - private function getBaseConfigData(int $storeId) : array + private function getBaseConfigData(StoreInterface $store) : array { - $store = $this->storeManager->getStore($storeId); $storeConfig = current($this->storeConfigManager->getStoreConfigs([$store->getCode()])); $storeConfigData = [ diff --git a/app/code/Magento/StoreGraphQl/Model/Resolver/StoreConfigResolver.php b/app/code/Magento/StoreGraphQl/Model/Resolver/StoreConfigResolver.php index da183a30e015c..d93790298c1b4 100644 --- a/app/code/Magento/StoreGraphQl/Model/Resolver/StoreConfigResolver.php +++ b/app/code/Magento/StoreGraphQl/Model/Resolver/StoreConfigResolver.php @@ -41,6 +41,6 @@ public function resolve( array $value = null, array $args = null ) { - return $this->storeConfigDataProvider->getStoreConfigData($context->getStoreId()); + return $this->storeConfigDataProvider->getStoreConfigData($context->getExtensionAttributes()->getStore()); } } diff --git a/app/code/Magento/StoreGraphQl/etc/extension_attributes.xml b/app/code/Magento/StoreGraphQl/etc/extension_attributes.xml index bad6906bc994a..d1f2638df10b3 100644 --- a/app/code/Magento/StoreGraphQl/etc/extension_attributes.xml +++ b/app/code/Magento/StoreGraphQl/etc/extension_attributes.xml @@ -6,7 +6,7 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Api/etc/extension_attributes.xsd"> - <extension_attributes for="Magento\Framework\GraphQl\Query\Resolver\ContextInterface"> - <attribute code="store_id" type="int" /> + <extension_attributes for="Magento\GraphQl\Model\Query\ContextInterface"> + <attribute code="store" type="Magento\Store\Api\Data\StoreInterface" /> </extension_attributes> </config> diff --git a/app/code/Magento/StoreGraphQl/etc/graphql/di.xml b/app/code/Magento/StoreGraphQl/etc/graphql/di.xml index f9682354ac704..3a0143821d8b9 100644 --- a/app/code/Magento/StoreGraphQl/etc/graphql/di.xml +++ b/app/code/Magento/StoreGraphQl/etc/graphql/di.xml @@ -16,7 +16,11 @@ </argument> </arguments> </type> - <type name="Magento\GraphQl\Model\Query\Resolver\ContextFactory"> - <plugin name="add_store_id_to_resolver_context" type="Magento\StoreGraphQl\Model\Plugin\Query\Resolver\ContextFactory"/> + <type name="Magento\GraphQl\Model\Query\ContextFactory"> + <arguments> + <argument name="contextParametersProcessors" xsi:type="array"> + <item name="add_store_info_to_context" xsi:type="object">Magento\StoreGraphQl\Model\Context\AddStoreInfoToContext</item> + </argument> + </arguments> </type> </config> diff --git a/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/EntityUrl.php b/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/EntityUrl.php index 15571d5997da1..c5ccfae5bf129 100644 --- a/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/EntityUrl.php +++ b/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/EntityUrl.php @@ -64,7 +64,7 @@ public function resolve( } $customUrl = $this->customUrlLocator->locateUrl($url); $url = $customUrl ?: $url; - $urlRewrite = $this->findCanonicalUrl($url, $context->getStoreId()); + $urlRewrite = $this->findCanonicalUrl($url, (int)$context->getExtensionAttributes()->getStore()->getId()); if ($urlRewrite) { if (!$urlRewrite->getEntityId()) { throw new GraphQlNoSuchEntityException( From d623287b0617f27f8a1c04d1cd9d0342d8032221 Mon Sep 17 00:00:00 2001 From: Yaroslav Rogoza <enarc@atwix.com> Date: Thu, 27 Jun 2019 16:38:33 +0200 Subject: [PATCH 556/773] Unnecessary factory removed --- .../Model/Query/Resolver/ContextFactory.php | 35 ------------------- 1 file changed, 35 deletions(-) delete mode 100644 app/code/Magento/GraphQl/Model/Query/Resolver/ContextFactory.php diff --git a/app/code/Magento/GraphQl/Model/Query/Resolver/ContextFactory.php b/app/code/Magento/GraphQl/Model/Query/Resolver/ContextFactory.php deleted file mode 100644 index 898c677615afd..0000000000000 --- a/app/code/Magento/GraphQl/Model/Query/Resolver/ContextFactory.php +++ /dev/null @@ -1,35 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -declare(strict_types=1); - -namespace Magento\GraphQl\Model\Query\Resolver; - -use Magento\Framework\ObjectManagerInterface; -use Magento\Framework\GraphQl\Query\Resolver\ContextInterface; - -class ContextFactory -{ - /** - * @var ObjectManagerInterface - */ - protected $objectManager; - - /** - * @param ObjectManagerInterface $objectManager - */ - public function __construct(ObjectManagerInterface $objectManager) - { - $this->objectManager = $objectManager; - } - - /** - * @return ContextInterface - */ - public function create() - { - return $this->objectManager->create(ContextInterface::class); - } -} From 7122e6ec9a53ee7cc1b7b844ed760d109354b75f Mon Sep 17 00:00:00 2001 From: Yaroslav Rogoza <enarc@atwix.com> Date: Thu, 27 Jun 2019 16:41:36 +0200 Subject: [PATCH 557/773] UrlRewrite composer.json reverted --- app/code/Magento/UrlRewriteGraphQl/composer.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/UrlRewriteGraphQl/composer.json b/app/code/Magento/UrlRewriteGraphQl/composer.json index e063903a5170f..6a6f1dce30b09 100644 --- a/app/code/Magento/UrlRewriteGraphQl/composer.json +++ b/app/code/Magento/UrlRewriteGraphQl/composer.json @@ -5,7 +5,8 @@ "require": { "php": "~7.1.3||~7.2.0", "magento/framework": "*", - "magento/module-url-rewrite": "*" + "magento/module-url-rewrite": "*", + "magento/module-store": "*" }, "suggest": { "magento/module-graph-ql": "*" @@ -22,4 +23,4 @@ "Magento\\UrlRewriteGraphQl\\": "" } } -} +} \ No newline at end of file From 9d1f640a7db78d20600ba9a88f92444dc5e08acd Mon Sep 17 00:00:00 2001 From: Yaroslav Rogoza <enarc@atwix.com> Date: Thu, 27 Jun 2019 16:42:29 +0200 Subject: [PATCH 558/773] Update composer.json --- app/code/Magento/UrlRewriteGraphQl/composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/UrlRewriteGraphQl/composer.json b/app/code/Magento/UrlRewriteGraphQl/composer.json index 6a6f1dce30b09..1c99276269aa7 100644 --- a/app/code/Magento/UrlRewriteGraphQl/composer.json +++ b/app/code/Magento/UrlRewriteGraphQl/composer.json @@ -23,4 +23,4 @@ "Magento\\UrlRewriteGraphQl\\": "" } } -} \ No newline at end of file +} From 6d6f11b3ff4dc290c1e53c8822e136547b38f05e Mon Sep 17 00:00:00 2001 From: Krissy Hiserote <khiserote@magento.com> Date: Thu, 27 Jun 2019 10:53:28 -0500 Subject: [PATCH 559/773] MC-15776: Merge release branch into 2.3-develop - fix static failures --- .../Magento/Captcha/Model/DefaultModel.php | 2 +- .../Captcha/Test/Unit/Model/DefaultTest.php | 14 +- app/code/Magento/Catalog/Model/Category.php | 12 +- .../Catalog/Model/Category/DataProvider.php | 11 +- .../Product/Form/Modifier/EavTest.php | 71 +++-- .../Catalog/Ui/Component/ColumnFactory.php | 21 +- .../Product/Form/Modifier/Eav.php | 75 ++--- .../Test/Unit/Model/Import/UploaderTest.php | 40 +-- .../Indexer/Fulltext/Action/DataProvider.php | 9 +- .../view/frontend/templates/cart/coupon.phtml | 4 +- app/code/Magento/Cms/Model/PageRepository.php | 7 +- .../Magento/Cms/Model/Template/Filter.php | 1 + .../Listing/Column/BlockActionsTest.php | 8 +- .../Adminhtml/System/AbstractConfig.php | 1 + .../Adminhtml/System/Config/Save.php | 8 +- .../Test/Unit/Model/AccountManagementTest.php | 12 +- .../Unit/Ui/Component/ColumnFactoryTest.php | 3 + .../Unit/Ui/Component/FilterFactoryTest.php | 3 + .../Listing/AttributeRepositoryTest.php | 3 + .../Customer/Ui/Component/ColumnFactory.php | 19 +- .../Listing/Column/Group/Options.php | 9 +- .../Controller/Download/LinkSampleTest.php | 29 +- .../Unit/Controller/Download/SampleTest.php | 29 +- .../Model/Client/Elasticsearch.php | 37 +-- .../Model/Client/Elasticsearch.php | 20 +- .../Model/Client/ElasticsearchTest.php | 248 +++++++++-------- .../FieldProvider/DynamicFieldTest.php | 92 ++++--- .../Model/Client/Elasticsearch.php | 20 +- .../Unit/Model/Client/ElasticsearchTest.php | 258 +++++++++--------- .../Block/Adminhtml/Template/PreviewTest.php | 26 +- .../Model/Plugin/Query/Resolver.php | 30 +- .../Adminhtml/Export/File/Download.php | 1 + .../Test/Unit/Model/ImportTest.php | 140 +++++----- .../Magento/Sales/Model/Rss/OrderStatus.php | 8 +- .../Unit/Block/Order/Info/Buttons/RssTest.php | 13 +- .../Test/Unit/Model/Rss/OrderStatusTest.php | 36 ++- .../Listing/Column/Status/Options.php | 9 +- .../Model/Coupon/AdminCodeLimitManager.php | 1 + app/code/Magento/Store/Model/Store.php | 18 +- .../Model/System/Message/Notifications.php | 1 + .../Magento/Ui/Controller/Index/Render.php | 10 +- .../Test/Unit/Controller/Index/RenderTest.php | 10 +- 42 files changed, 752 insertions(+), 617 deletions(-) diff --git a/app/code/Magento/Captcha/Model/DefaultModel.php b/app/code/Magento/Captcha/Model/DefaultModel.php index 8ed434e420f94..bbbbfb0a36e08 100644 --- a/app/code/Magento/Captcha/Model/DefaultModel.php +++ b/app/code/Magento/Captcha/Model/DefaultModel.php @@ -507,7 +507,7 @@ private function getWords() /** * Set captcha word * - * @param string $word + * @param string $word * @return $this * @since 100.2.0 */ diff --git a/app/code/Magento/Captcha/Test/Unit/Model/DefaultTest.php b/app/code/Magento/Captcha/Test/Unit/Model/DefaultTest.php index a1206a06dccd0..b569803078457 100644 --- a/app/code/Magento/Captcha/Test/Unit/Model/DefaultTest.php +++ b/app/code/Magento/Captcha/Test/Unit/Model/DefaultTest.php @@ -257,13 +257,15 @@ protected function _getSessionStub() ->getMock(); $session->expects($this->any())->method('isLoggedIn')->will($this->returnValue(false)); - $session->setData([ - 'user_create_word' => [ - 'data' => 'AbCdEf5', - 'words' => 'AbCdEf5', - 'expires' => time() + self::EXPIRE_FRAME + $session->setData( + [ + 'user_create_word' => [ + 'data' => 'AbCdEf5', + 'words' => 'AbCdEf5', + 'expires' => time() + self::EXPIRE_FRAME + ] ] - ]); + ); return $session; } diff --git a/app/code/Magento/Catalog/Model/Category.php b/app/code/Magento/Catalog/Model/Category.php index 6f45787fbd4f1..9d6d7e41ff34e 100644 --- a/app/code/Magento/Catalog/Model/Category.php +++ b/app/code/Magento/Catalog/Model/Category.php @@ -621,11 +621,13 @@ public function getUrl() return $this->getData('url'); } - $rewrite = $this->urlFinder->findOneByData([ - UrlRewrite::ENTITY_ID => $this->getId(), - UrlRewrite::ENTITY_TYPE => CategoryUrlRewriteGenerator::ENTITY_TYPE, - UrlRewrite::STORE_ID => $this->getStoreId(), - ]); + $rewrite = $this->urlFinder->findOneByData( + [ + UrlRewrite::ENTITY_ID => $this->getId(), + UrlRewrite::ENTITY_TYPE => CategoryUrlRewriteGenerator::ENTITY_TYPE, + UrlRewrite::STORE_ID => $this->getStoreId(), + ] + ); if ($rewrite) { $this->setData('url', $this->getUrlInstance()->getDirectUrl($rewrite->getRequestPath())); Profiler::stop('REWRITE: ' . __METHOD__); diff --git a/app/code/Magento/Catalog/Model/Category/DataProvider.php b/app/code/Magento/Catalog/Model/Category/DataProvider.php index 174c90ae1635c..c96b2aae36059 100644 --- a/app/code/Magento/Catalog/Model/Category/DataProvider.php +++ b/app/code/Magento/Catalog/Model/Category/DataProvider.php @@ -272,10 +272,13 @@ private function addUseDefaultValueCheckbox(Category $category, array $meta) */ public function prepareMeta($meta) { - $meta = array_replace_recursive($meta, $this->prepareFieldsMeta( - $this->getFieldsMap(), - $this->getAttributesMeta($this->eavConfig->getEntityType('catalog_category')) - )); + $meta = array_replace_recursive( + $meta, + $this->prepareFieldsMeta( + $this->getFieldsMap(), + $this->getAttributesMeta($this->eavConfig->getEntityType('catalog_category')) + ) + ); return $meta; } diff --git a/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/EavTest.php b/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/EavTest.php index 91a09c907de65..88075b13f1430 100755 --- a/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/EavTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/EavTest.php @@ -266,15 +266,17 @@ protected function setUp() $this->searchResultsMock = $this->getMockBuilder(SearchResultsInterface::class) ->getMockForAbstractClass(); $this->eavAttributeMock = $this->getMockBuilder(Attribute::class) - ->setMethods([ - 'load', - 'getAttributeGroupCode', - 'getApplyTo', - 'getFrontendInput', - 'getAttributeCode', - 'usesSource', - 'getSource', - ]) + ->setMethods( + [ + 'load', + 'getAttributeGroupCode', + 'getApplyTo', + 'getFrontendInput', + 'getAttributeCode', + 'usesSource', + 'getSource', + ] + ) ->disableOriginalConstructor() ->getMock(); $this->productAttributeMock = $this->getMockBuilder(ProductAttributeInterface::class) @@ -307,9 +309,7 @@ protected function setUp() ->willReturnSelf(); $this->groupCollectionMock->expects($this->any()) ->method('getIterator') - ->willReturn(new \ArrayIterator([ - $this->groupMock, - ])); + ->willReturn(new \ArrayIterator([$this->groupMock])); $this->attributeCollectionMock->expects($this->any()) ->method('addFieldToSelect') ->willReturnSelf(); @@ -324,9 +324,7 @@ protected function setUp() ->willReturn($this->attributeCollectionMock); $this->productMock->expects($this->any()) ->method('getAttributes') - ->willReturn([ - $this->attributeMock, - ]); + ->willReturn([$this->attributeMock,]); $this->storeMock = $this->getMockBuilder(StoreInterface::class) ->setMethods(['load', 'getId', 'getConfig', 'getBaseCurrencyCode']) ->getMockForAbstractClass(); @@ -355,24 +353,27 @@ protected function setUp() */ protected function createModel() { - return $this->objectManager->getObject(Eav::class, [ - 'locator' => $this->locatorMock, - 'eavValidationRules' => $this->eavValidationRulesMock, - 'eavConfig' => $this->eavConfigMock, - 'request' => $this->requestMock, - 'groupCollectionFactory' => $this->groupCollectionFactoryMock, - 'storeManager' => $this->storeManagerMock, - 'formElementMapper' => $this->formElementMapperMock, - 'metaPropertiesMapper' => $this->metaPropertiesMapperMock, - 'searchCriteriaBuilder' => $this->searchCriteriaBuilderMock, - 'attributeGroupRepository' => $this->attributeGroupRepositoryMock, - 'sortOrderBuilder' => $this->sortOrderBuilderMock, - 'attributeRepository' => $this->attributeRepositoryMock, - 'arrayManager' => $this->arrayManagerMock, - 'eavAttributeFactory' => $this->eavAttributeFactoryMock, - '_eventManager' => $this->eventManagerMock, - 'attributeCollectionFactory' => $this->attributeCollectionFactoryMock - ]); + return $this->objectManager->getObject( + Eav::class, + [ + 'locator' => $this->locatorMock, + 'eavValidationRules' => $this->eavValidationRulesMock, + 'eavConfig' => $this->eavConfigMock, + 'request' => $this->requestMock, + 'groupCollectionFactory' => $this->groupCollectionFactoryMock, + 'storeManager' => $this->storeManagerMock, + 'formElementMapper' => $this->formElementMapperMock, + 'metaPropertiesMapper' => $this->metaPropertiesMapperMock, + 'searchCriteriaBuilder' => $this->searchCriteriaBuilderMock, + 'attributeGroupRepository' => $this->attributeGroupRepositoryMock, + 'sortOrderBuilder' => $this->sortOrderBuilderMock, + 'attributeRepository' => $this->attributeRepositoryMock, + 'arrayManager' => $this->arrayManagerMock, + 'eavAttributeFactory' => $this->eavAttributeFactoryMock, + '_eventManager' => $this->eventManagerMock, + 'attributeCollectionFactory' => $this->attributeCollectionFactoryMock + ] + ); } public function testModifyData() @@ -389,9 +390,7 @@ public function testModifyData() ->willReturn($this->attributeCollectionMock); $this->attributeCollectionMock->expects($this->any())->method('getItems') - ->willReturn([ - $this->eavAttributeMock - ]); + ->willReturn([$this->eavAttributeMock]); $this->locatorMock->expects($this->any())->method('getProduct') ->willReturn($this->productMock); diff --git a/app/code/Magento/Catalog/Ui/Component/ColumnFactory.php b/app/code/Magento/Catalog/Ui/Component/ColumnFactory.php index f7554219c6c31..9a6a22fcb0985 100644 --- a/app/code/Magento/Catalog/Ui/Component/ColumnFactory.php +++ b/app/code/Magento/Catalog/Ui/Component/ColumnFactory.php @@ -65,15 +65,18 @@ public function create($attribute, $context, array $config = []) $filterModifiers = $context->getRequestParam(FilterModifier::FILTER_MODIFIER, []); $columnName = $attribute->getAttributeCode(); - $config = array_merge([ - 'label' => __($attribute->getDefaultFrontendLabel()), - 'dataType' => $this->getDataType($attribute), - 'add_field' => true, - 'visible' => $attribute->getIsVisibleInGrid(), - 'filter' => ($attribute->getIsFilterableInGrid() || array_key_exists($columnName, $filterModifiers)) - ? $this->getFilterType($attribute->getFrontendInput()) - : null, - ], $config); + $config = array_merge( + [ + 'label' => __($attribute->getDefaultFrontendLabel()), + 'dataType' => $this->getDataType($attribute), + 'add_field' => true, + 'visible' => $attribute->getIsVisibleInGrid(), + 'filter' => ($attribute->getIsFilterableInGrid() || array_key_exists($columnName, $filterModifiers)) + ? $this->getFilterType($attribute->getFrontendInput()) + : null, + ], + $config + ); if ($attribute->usesSource()) { $config['options'] = $attribute->getSource()->getAllOptions(); diff --git a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php index 6f60a114737b0..2d705cb2357af 100755 --- a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php +++ b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php @@ -667,20 +667,24 @@ public function setupAttributeMeta(ProductAttributeInterface $attribute, $groupC { $configPath = ltrim(static::META_CONFIG_PATH, ArrayManager::DEFAULT_PATH_DELIMITER); $attributeCode = $attribute->getAttributeCode(); - $meta = $this->arrayManager->set($configPath, [], [ - 'dataType' => $attribute->getFrontendInput(), - 'formElement' => $this->getFormElementsMapValue($attribute->getFrontendInput()), - 'visible' => $attribute->getIsVisible(), - 'required' => $attribute->getIsRequired(), - 'notice' => $attribute->getNote() === null ? null : __($attribute->getNote()), - 'default' => (!$this->isProductExists()) ? $this->getAttributeDefaultValue($attribute) : null, - 'label' => __($attribute->getDefaultFrontendLabel()), - 'code' => $attributeCode, - 'source' => $groupCode, - 'scopeLabel' => $this->getScopeLabel($attribute), - 'globalScope' => $this->isScopeGlobal($attribute), - 'sortOrder' => $sortOrder * self::SORT_ORDER_MULTIPLIER, - ]); + $meta = $this->arrayManager->set( + $configPath, + [], + [ + 'dataType' => $attribute->getFrontendInput(), + 'formElement' => $this->getFormElementsMapValue($attribute->getFrontendInput()), + 'visible' => $attribute->getIsVisible(), + 'required' => $attribute->getIsRequired(), + 'notice' => $attribute->getNote() === null ? null : __($attribute->getNote()), + 'default' => (!$this->isProductExists()) ? $this->getAttributeDefaultValue($attribute) : null, + 'label' => __($attribute->getDefaultFrontendLabel()), + 'code' => $attributeCode, + 'source' => $groupCode, + 'scopeLabel' => $this->getScopeLabel($attribute), + 'globalScope' => $this->isScopeGlobal($attribute), + 'sortOrder' => $sortOrder * self::SORT_ORDER_MULTIPLIER, + ] + ); // TODO: Refactor to $attribute->getOptions() when MAGETWO-48289 is done $attributeModel = $this->getAttributeModel($attribute); @@ -689,39 +693,39 @@ public function setupAttributeMeta(ProductAttributeInterface $attribute, $groupC foreach ($options as &$option) { $option['__disableTmpl'] = true; } - $meta = $this->arrayManager->merge($configPath, $meta, [ - 'options' => $this->convertOptionsValueToString($options), - ]); + $meta = $this->arrayManager->merge( + $configPath, + $meta, + ['options' => $this->convertOptionsValueToString($options)] + ); } if ($this->canDisplayUseDefault($attribute)) { - $meta = $this->arrayManager->merge($configPath, $meta, [ - 'service' => [ - 'template' => 'ui/form/element/helper/service', + $meta = $this->arrayManager->merge( + $configPath, + $meta, + [ + 'service' => [ + 'template' => 'ui/form/element/helper/service', + ] ] - ]); + ); } if (!$this->arrayManager->exists($configPath . '/componentType', $meta)) { - $meta = $this->arrayManager->merge($configPath, $meta, [ - 'componentType' => Field::NAME, - ]); + $meta = $this->arrayManager->merge($configPath, $meta, ['componentType' => Field::NAME]); } $product = $this->locator->getProduct(); if (in_array($attributeCode, $this->attributesToDisable) || $product->isLockedAttribute($attributeCode)) { - $meta = $this->arrayManager->merge($configPath, $meta, [ - 'disabled' => true, - ]); + $meta = $this->arrayManager->merge($configPath, $meta, ['disabled' => true]); } // TODO: getAttributeModel() should not be used when MAGETWO-48284 is complete $childData = $this->arrayManager->get($configPath, $meta, []); if (($rules = $this->catalogEavValidationRules->build($this->getAttributeModel($attribute), $childData))) { - $meta = $this->arrayManager->merge($configPath, $meta, [ - 'validation' => $rules, - ]); + $meta = $this->arrayManager->merge($configPath, $meta, ['validation' => $rules]); } $meta = $this->addUseDefaultValueCheckbox($attribute, $meta); @@ -789,11 +793,14 @@ private function getAttributeDefaultValue(ProductAttributeInterface $attribute) */ private function convertOptionsValueToString(array $options) : array { - array_walk($options, function (&$value) { - if (isset($value['value']) && is_scalar($value['value'])) { - $value['value'] = (string)$value['value']; + array_walk( + $options, + function (&$value) { + if (isset($value['value']) && is_scalar($value['value'])) { + $value['value'] = (string)$value['value']; + } } - }); + ); return $options; } diff --git a/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/UploaderTest.php b/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/UploaderTest.php index 186d1e8e422fd..2c6aa6535c10e 100644 --- a/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/UploaderTest.php +++ b/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/UploaderTest.php @@ -100,16 +100,18 @@ protected function setUp() ->getMock(); $this->uploader = $this->getMockBuilder(\Magento\CatalogImportExport\Model\Import\Uploader::class) - ->setConstructorArgs([ - $this->coreFileStorageDb, - $this->coreFileStorage, - $this->imageFactory, - $this->validator, - $this->filesystem, - $this->readFactory, - null, - $this->random - ]) + ->setConstructorArgs( + [ + $this->coreFileStorageDb, + $this->coreFileStorage, + $this->imageFactory, + $this->validator, + $this->filesystem, + $this->readFactory, + null, + $this->random + ] + ) ->setMethods(['_setUploadFile', 'save', 'getTmpDir', 'checkAllowedExtension']) ->getMock(); } @@ -224,14 +226,16 @@ public function testMoveFileUrlDrivePool($fileUrl, $expectedHost, $expectedDrive ->willReturn($driverMock); $uploaderMock = $this->getMockBuilder(\Magento\CatalogImportExport\Model\Import\Uploader::class) - ->setConstructorArgs([ - $this->coreFileStorageDb, - $this->coreFileStorage, - $this->imageFactory, - $this->validator, - $this->filesystem, - $readFactory, - ]) + ->setConstructorArgs( + [ + $this->coreFileStorageDb, + $this->coreFileStorage, + $this->imageFactory, + $this->validator, + $this->filesystem, + $readFactory, + ] + ) ->getMock(); $result = $uploaderMock->move($fileUrl); diff --git a/app/code/Magento/CatalogSearch/Model/Indexer/Fulltext/Action/DataProvider.php b/app/code/Magento/CatalogSearch/Model/Indexer/Fulltext/Action/DataProvider.php index 7c86099ae86e9..09d4f0068459a 100644 --- a/app/code/Magento/CatalogSearch/Model/Indexer/Fulltext/Action/DataProvider.php +++ b/app/code/Magento/CatalogSearch/Model/Indexer/Fulltext/Action/DataProvider.php @@ -705,9 +705,12 @@ private function filterOutOfStockProducts($indexData, $storeId): array $stockStatusCriteria->setProductsFilter($productIds); $stockStatusCollection = $this->getStockStatusRepository()->getList($stockStatusCriteria); $stockStatuses = $stockStatusCollection->getItems(); - $stockStatuses = array_filter($stockStatuses, function (StockStatusInterface $stockStatus) { - return StockStatusInterface::STATUS_IN_STOCK == $stockStatus->getStockStatus(); - }); + $stockStatuses = array_filter( + $stockStatuses, + function (StockStatusInterface $stockStatus) { + return StockStatusInterface::STATUS_IN_STOCK == $stockStatus->getStockStatus(); + } + ); $indexData = array_intersect_key($indexData, $stockStatuses); } return $indexData; diff --git a/app/code/Magento/Checkout/view/frontend/templates/cart/coupon.phtml b/app/code/Magento/Checkout/view/frontend/templates/cart/coupon.phtml index 534a80f7fda0c..bf8490affea0c 100644 --- a/app/code/Magento/Checkout/view/frontend/templates/cart/coupon.phtml +++ b/app/code/Magento/Checkout/view/frontend/templates/cart/coupon.phtml @@ -54,8 +54,8 @@ <?php endif; ?> </div> </div> - <?php if (!strlen($block->getCouponCode())): ?> - <?= /* @noEscape */ $block->getChildHtml('captcha') ?> + <?php if (!strlen($block->getCouponCode())) : ?> + <?= /* @noEscape */ $block->getChildHtml('captcha') ?> <?php endif; ?> </form> </div> diff --git a/app/code/Magento/Cms/Model/PageRepository.php b/app/code/Magento/Cms/Model/PageRepository.php index 1d2959103fc5d..e6777659d7d88 100644 --- a/app/code/Magento/Cms/Model/PageRepository.php +++ b/app/code/Magento/Cms/Model/PageRepository.php @@ -246,10 +246,9 @@ public function delete(\Magento\Cms\Api\Data\PageInterface $page) try { $this->resource->delete($page); } catch (\Exception $exception) { - throw new CouldNotDeleteException(__( - 'Could not delete the page: %1', - $exception->getMessage() - )); + throw new CouldNotDeleteException( + __('Could not delete the page: %1', $exception->getMessage()) + ); } return true; } diff --git a/app/code/Magento/Cms/Model/Template/Filter.php b/app/code/Magento/Cms/Model/Template/Filter.php index 4f86dfe07dee2..7e71a06de1f31 100644 --- a/app/code/Magento/Cms/Model/Template/Filter.php +++ b/app/code/Magento/Cms/Model/Template/Filter.php @@ -39,6 +39,7 @@ public function setUseSessionInUrl($flag) */ public function mediaDirective($construction) { + // phpcs:ignore Magento2.Functions.DiscouragedFunction $params = $this->getParameters(html_entity_decode($construction[2], ENT_QUOTES)); if (preg_match('/\.\.(\\\|\/)/', $params['url'])) { throw new \InvalidArgumentException('Image path must be absolute'); diff --git a/app/code/Magento/Cms/Test/Unit/Ui/Component/Listing/Column/BlockActionsTest.php b/app/code/Magento/Cms/Test/Unit/Ui/Component/Listing/Column/BlockActionsTest.php index 6981a7983049e..8741e37016b64 100644 --- a/app/code/Magento/Cms/Test/Unit/Ui/Component/Listing/Column/BlockActionsTest.php +++ b/app/code/Magento/Cms/Test/Unit/Ui/Component/Listing/Column/BlockActionsTest.php @@ -56,10 +56,10 @@ protected function setUp() ->setMethods(['escapeHtmlAttr']) ->getMock(); - $this->blockActions = $objectManager->getObject(BlockActions::class, [ - 'context' => $context, - 'urlBuilder' => $this->urlBuilder - ]); + $this->blockActions = $objectManager->getObject( + BlockActions::class, + ['context' => $context, 'urlBuilder' => $this->urlBuilder] + ); $objectManager->setBackwardCompatibleProperty($this->blockActions, 'escaper', $this->escaper); } diff --git a/app/code/Magento/Config/Controller/Adminhtml/System/AbstractConfig.php b/app/code/Magento/Config/Controller/Adminhtml/System/AbstractConfig.php index 7b626ccbd333c..274ee3b8d2a6e 100644 --- a/app/code/Magento/Config/Controller/Adminhtml/System/AbstractConfig.php +++ b/app/code/Magento/Config/Controller/Adminhtml/System/AbstractConfig.php @@ -10,6 +10,7 @@ /** * System Configuration Abstract Controller + * phpcs:disable Magento2.Classes.AbstractApi * @api * @since 100.0.2 * diff --git a/app/code/Magento/Config/Controller/Adminhtml/System/Config/Save.php b/app/code/Magento/Config/Controller/Adminhtml/System/Config/Save.php index 38b9a0076c3ad..91bcb632cf73b 100644 --- a/app/code/Magento/Config/Controller/Adminhtml/System/Config/Save.php +++ b/app/code/Magento/Config/Controller/Adminhtml/System/Config/Save.php @@ -224,10 +224,10 @@ public function execute() /** @var \Magento\Config\Model\Config $configModel */ $configModel = $this->_configFactory->create(['data' => $configData]); $configModel->save(); - $this->_eventManager->dispatch('admin_system_config_save', [ - 'configData' => $configData, - 'request' => $this->getRequest() - ]); + $this->_eventManager->dispatch( + 'admin_system_config_save', + ['configData' => $configData, 'request' => $this->getRequest()] + ); $this->messageManager->addSuccess(__('You saved the configuration.')); } catch (\Magento\Framework\Exception\LocalizedException $e) { $messages = explode("\n", $e->getMessage()); diff --git a/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php b/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php index 340492674bb16..3c38cd0f7b4e2 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php @@ -816,14 +816,18 @@ public function testCreateAccountWithPasswordInputException( if ($testNumber == 1) { $this->expectException(\Magento\Framework\Exception\InputException::class); - $this->expectExceptionMessage('The password needs at least ' . $minPasswordLength . ' characters. ' - . 'Create a new password and try again.'); + $this->expectExceptionMessage( + 'The password needs at least ' . $minPasswordLength . ' characters. ' + . 'Create a new password and try again.' + ); } if ($testNumber == 2) { $this->expectException(\Magento\Framework\Exception\InputException::class); - $this->expectExceptionMessage('Minimum of different classes of characters in password is ' . - $minCharacterSetsNum . '. Classes of characters: Lower Case, Upper Case, Digits, Special Characters.'); + $this->expectExceptionMessage( + 'Minimum of different classes of characters in password is ' . + $minCharacterSetsNum . '. Classes of characters: Lower Case, Upper Case, Digits, Special Characters.' + ); } $customer = $this->getMockBuilder(Customer::class)->disableOriginalConstructor()->getMock(); diff --git a/app/code/Magento/Customer/Test/Unit/Ui/Component/ColumnFactoryTest.php b/app/code/Magento/Customer/Test/Unit/Ui/Component/ColumnFactoryTest.php index dfc9af2a35498..d917cc4908ac8 100644 --- a/app/code/Magento/Customer/Test/Unit/Ui/Component/ColumnFactoryTest.php +++ b/app/code/Magento/Customer/Test/Unit/Ui/Component/ColumnFactoryTest.php @@ -7,6 +7,9 @@ use Magento\Customer\Ui\Component\ColumnFactory; +/** + * Test ColumnFactory Class + */ class ColumnFactoryTest extends \PHPUnit\Framework\TestCase { /** @var \Magento\Customer\Api\Data\OptionInterface|\PHPUnit_Framework_MockObject_MockObject */ diff --git a/app/code/Magento/Customer/Test/Unit/Ui/Component/FilterFactoryTest.php b/app/code/Magento/Customer/Test/Unit/Ui/Component/FilterFactoryTest.php index a0681ce6e94a5..f3c0a56262622 100644 --- a/app/code/Magento/Customer/Test/Unit/Ui/Component/FilterFactoryTest.php +++ b/app/code/Magento/Customer/Test/Unit/Ui/Component/FilterFactoryTest.php @@ -7,6 +7,9 @@ use Magento\Customer\Ui\Component\FilterFactory; +/** + * Test FilterFactory Class + */ class FilterFactoryTest extends \PHPUnit\Framework\TestCase { /** @var \Magento\Customer\Api\Data\OptionInterface|\PHPUnit_Framework_MockObject_MockObject */ diff --git a/app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/AttributeRepositoryTest.php b/app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/AttributeRepositoryTest.php index 187f385bc9107..c12dec865cde8 100644 --- a/app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/AttributeRepositoryTest.php +++ b/app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/AttributeRepositoryTest.php @@ -7,6 +7,9 @@ use Magento\Customer\Ui\Component\Listing\AttributeRepository; +/** + * Test AttributeRepository Class + */ class AttributeRepositoryTest extends \PHPUnit\Framework\TestCase { /** @var \Magento\Customer\Api\CustomerMetadataManagementInterface|\PHPUnit_Framework_MockObject_MockObject */ diff --git a/app/code/Magento/Customer/Ui/Component/ColumnFactory.php b/app/code/Magento/Customer/Ui/Component/ColumnFactory.php index 8cdf53f35387e..f19ae03189eaa 100644 --- a/app/code/Magento/Customer/Ui/Component/ColumnFactory.php +++ b/app/code/Magento/Customer/Ui/Component/ColumnFactory.php @@ -68,14 +68,17 @@ public function __construct( */ public function create(array $attributeData, $columnName, $context, array $config = []) { - $config = array_merge([ - 'label' => __($attributeData[AttributeMetadata::FRONTEND_LABEL]), - 'dataType' => $this->getDataType($attributeData[AttributeMetadata::FRONTEND_INPUT]), - 'align' => 'left', - 'visible' => (bool)$attributeData[AttributeMetadata::IS_VISIBLE_IN_GRID], - 'component' => $this->getJsComponent($this->getDataType($attributeData[AttributeMetadata::FRONTEND_INPUT])), - '__disableTmpl' => 'true' - ], $config); + $config = array_merge( + [ + 'label' => __($attributeData[AttributeMetadata::FRONTEND_LABEL]), + 'dataType' => $this->getDataType($attributeData[AttributeMetadata::FRONTEND_INPUT]), + 'align' => 'left', + 'visible' => (bool)$attributeData[AttributeMetadata::IS_VISIBLE_IN_GRID], + 'component' => $this->getJsComponent($this->getDataType($attributeData[AttributeMetadata::FRONTEND_INPUT])), + '__disableTmpl' => 'true' + ], + $config + ); if ($attributeData[AttributeMetadata::FRONTEND_INPUT] == 'date') { $config['dateFormat'] = 'MMM d, y'; $config['timezone'] = false; diff --git a/app/code/Magento/Customer/Ui/Component/Listing/Column/Group/Options.php b/app/code/Magento/Customer/Ui/Component/Listing/Column/Group/Options.php index 615ad2243a467..61cb06cf77e0d 100644 --- a/app/code/Magento/Customer/Ui/Component/Listing/Column/Group/Options.php +++ b/app/code/Magento/Customer/Ui/Component/Listing/Column/Group/Options.php @@ -44,9 +44,12 @@ public function toOptionArray() $this->options = $this->collectionFactory->create()->toOptionArray(); } - array_walk($this->options, function (&$item) { - $item['__disableTmpl'] = true; - }); + array_walk( + $this->options, + function (&$item) { + $item['__disableTmpl'] = true; + } + ); return $this->options; } diff --git a/app/code/Magento/Downloadable/Test/Unit/Controller/Download/LinkSampleTest.php b/app/code/Magento/Downloadable/Test/Unit/Controller/Download/LinkSampleTest.php index 78b707619f994..fa989c9e94991 100644 --- a/app/code/Magento/Downloadable/Test/Unit/Controller/Download/LinkSampleTest.php +++ b/app/code/Magento/Downloadable/Test/Unit/Controller/Download/LinkSampleTest.php @@ -90,32 +90,39 @@ protected function setUp() ] ); - $this->helperData = $this->createPartialMock(\Magento\Downloadable\Helper\Data::class, [ - 'getIsShareable' - ]); - $this->downloadHelper = $this->createPartialMock(\Magento\Downloadable\Helper\Download::class, [ + $this->helperData = $this->createPartialMock( + \Magento\Downloadable\Helper\Data::class, + ['getIsShareable'] + ); + $this->downloadHelper = $this->createPartialMock( + \Magento\Downloadable\Helper\Download::class, + [ 'setResource', 'getFilename', 'getContentType', 'getFileSize', 'getContentDisposition', 'output' - ]); - $this->product = $this->createPartialMock(\Magento\Catalog\Model\Product::class, [ + ] + ); + $this->product = $this->createPartialMock( + \Magento\Catalog\Model\Product::class, + [ '_wakeup', 'load', 'getId', 'getProductUrl', 'getName' - ]); + ] + ); $this->messageManager = $this->createMock(\Magento\Framework\Message\ManagerInterface::class); $this->redirect = $this->createMock(\Magento\Framework\App\Response\RedirectInterface::class); $this->urlInterface = $this->createMock(\Magento\Framework\UrlInterface::class); $this->salabilityCheckerMock = $this->createMock(\Magento\Catalog\Model\Product\SalabilityChecker::class); - $this->objectManager = $this->createPartialMock(\Magento\Framework\ObjectManager\ObjectManager::class, [ - 'create', - 'get' - ]); + $this->objectManager = $this->createPartialMock( + \Magento\Framework\ObjectManager\ObjectManager::class, + ['create', 'get'] + ); $this->linkSample = $this->objectManagerHelper->getObject( \Magento\Downloadable\Controller\Download\LinkSample::class, [ diff --git a/app/code/Magento/Downloadable/Test/Unit/Controller/Download/SampleTest.php b/app/code/Magento/Downloadable/Test/Unit/Controller/Download/SampleTest.php index 501ed58a3961b..5e711b61e6a5a 100644 --- a/app/code/Magento/Downloadable/Test/Unit/Controller/Download/SampleTest.php +++ b/app/code/Magento/Downloadable/Test/Unit/Controller/Download/SampleTest.php @@ -90,32 +90,39 @@ protected function setUp() ] ); - $this->helperData = $this->createPartialMock(\Magento\Downloadable\Helper\Data::class, [ - 'getIsShareable' - ]); - $this->downloadHelper = $this->createPartialMock(\Magento\Downloadable\Helper\Download::class, [ + $this->helperData = $this->createPartialMock( + \Magento\Downloadable\Helper\Data::class, + ['getIsShareable'] + ); + $this->downloadHelper = $this->createPartialMock( + \Magento\Downloadable\Helper\Download::class, + [ 'setResource', 'getFilename', 'getContentType', 'getFileSize', 'getContentDisposition', 'output' - ]); - $this->product = $this->createPartialMock(\Magento\Catalog\Model\Product::class, [ + ] + ); + $this->product = $this->createPartialMock( + \Magento\Catalog\Model\Product::class, + [ '_wakeup', 'load', 'getId', 'getProductUrl', 'getName' - ]); + ] + ); $this->messageManager = $this->createMock(\Magento\Framework\Message\ManagerInterface::class); $this->redirect = $this->createMock(\Magento\Framework\App\Response\RedirectInterface::class); $this->urlInterface = $this->createMock(\Magento\Framework\UrlInterface::class); $this->salabilityCheckerMock = $this->createMock(\Magento\Catalog\Model\Product\SalabilityChecker::class); - $this->objectManager = $this->createPartialMock(\Magento\Framework\ObjectManager\ObjectManager::class, [ - 'create', - 'get' - ]); + $this->objectManager = $this->createPartialMock( + \Magento\Framework\ObjectManager\ObjectManager::class, + ['create', 'get'] + ); $this->sample = $this->objectManagerHelper->getObject( \Magento\Downloadable\Controller\Download\Sample::class, [ diff --git a/app/code/Magento/Elasticsearch/Elasticsearch5/Model/Client/Elasticsearch.php b/app/code/Magento/Elasticsearch/Elasticsearch5/Model/Client/Elasticsearch.php index f28eb78057fa8..93f4caa10adf9 100644 --- a/app/code/Magento/Elasticsearch/Elasticsearch5/Model/Client/Elasticsearch.php +++ b/app/code/Magento/Elasticsearch/Elasticsearch5/Model/Client/Elasticsearch.php @@ -146,10 +146,12 @@ public function bulkQuery($query) */ public function createIndex($index, $settings) { - $this->getClient()->indices()->create([ - 'index' => $index, - 'body' => $settings, - ]); + $this->getClient()->indices()->create( + [ + 'index' => $index, + 'body' => $settings, + ] + ); } /** @@ -252,10 +254,12 @@ public function addFieldsMapping(array $fields, $index, $entityType) 'type' => $entityType, 'body' => [ $entityType => [ - '_all' => $this->prepareFieldInfo([ - 'enabled' => true, - 'type' => 'text', - ]), + '_all' => $this->prepareFieldInfo( + [ + 'enabled' => true, + 'type' => 'text', + ] + ), 'properties' => [], 'dynamic_templates' => [ [ @@ -282,10 +286,12 @@ public function addFieldsMapping(array $fields, $index, $entityType) 'string_mapping' => [ 'match' => '*', 'match_mapping_type' => 'string', - 'mapping' => $this->prepareFieldInfo([ - 'type' => 'text', - 'index' => false, - ]), + 'mapping' => $this->prepareFieldInfo( + [ + 'type' => 'text', + 'index' => false, + ] + ), ], ] ], @@ -332,10 +338,9 @@ private function prepareFieldInfo($fieldInfo) */ public function deleteMapping($index, $entityType) { - $this->getClient()->indices()->deleteMapping([ - 'index' => $index, - 'type' => $entityType, - ]); + $this->getClient()->indices()->deleteMapping( + ['index' => $index, 'type' => $entityType] + ); } /** diff --git a/app/code/Magento/Elasticsearch/Model/Client/Elasticsearch.php b/app/code/Magento/Elasticsearch/Model/Client/Elasticsearch.php index e91508f80e964..f9b827304446d 100644 --- a/app/code/Magento/Elasticsearch/Model/Client/Elasticsearch.php +++ b/app/code/Magento/Elasticsearch/Model/Client/Elasticsearch.php @@ -141,10 +141,12 @@ public function bulkQuery($query) */ public function createIndex($index, $settings) { - $this->getClient()->indices()->create([ - 'index' => $index, - 'body' => $settings, - ]); + $this->getClient()->indices()->create( + [ + 'index' => $index, + 'body' => $settings, + ] + ); } /** @@ -302,10 +304,12 @@ public function addFieldsMapping(array $fields, $index, $entityType) */ public function deleteMapping($index, $entityType) { - $this->getClient()->indices()->deleteMapping([ - 'index' => $index, - 'type' => $entityType, - ]); + $this->getClient()->indices()->deleteMapping( + [ + 'index' => $index, + 'type' => $entityType, + ] + ); } /** diff --git a/app/code/Magento/Elasticsearch/Test/Unit/Elasticsearch5/Model/Client/ElasticsearchTest.php b/app/code/Magento/Elasticsearch/Test/Unit/Elasticsearch5/Model/Client/ElasticsearchTest.php index 2a98a8b0ea62a..5f5807e212961 100644 --- a/app/code/Magento/Elasticsearch/Test/Unit/Elasticsearch5/Model/Client/ElasticsearchTest.php +++ b/app/code/Magento/Elasticsearch/Test/Unit/Elasticsearch5/Model/Client/ElasticsearchTest.php @@ -41,30 +41,34 @@ class ElasticsearchTest extends \PHPUnit\Framework\TestCase protected function setUp() { $this->elasticsearchClientMock = $this->getMockBuilder(\Elasticsearch\Client::class) - ->setMethods([ - 'indices', - 'ping', - 'bulk', - 'search', - 'scroll', - 'suggest', - 'info', - ]) + ->setMethods( + [ + 'indices', + 'ping', + 'bulk', + 'search', + 'scroll', + 'suggest', + 'info', + ] + ) ->disableOriginalConstructor() ->getMock(); $this->indicesMock = $this->getMockBuilder(\Elasticsearch\Namespaces\IndicesNamespace::class) - ->setMethods([ - 'exists', - 'getSettings', - 'create', - 'delete', - 'putMapping', - 'deleteMapping', - 'stats', - 'updateAliases', - 'existsAlias', - 'getAlias', - ]) + ->setMethods( + [ + 'exists', + 'getSettings', + 'create', + 'delete', + 'putMapping', + 'deleteMapping', + 'stats', + 'updateAliases', + 'existsAlias', + 'getAlias', + ] + ) ->disableOriginalConstructor() ->getMock(); $this->elasticsearchClientMock->expects($this->any()) @@ -177,10 +181,12 @@ public function testCreateIndexExists() { $this->indicesMock->expects($this->once()) ->method('create') - ->with([ - 'index' => 'indexName', - 'body' => [], - ]); + ->with( + [ + 'index' => 'indexName', + 'body' => [], + ] + ); $this->model->createIndex('indexName', []); } @@ -266,9 +272,7 @@ public function testIndexExists() { $this->indicesMock->expects($this->once()) ->method('exists') - ->with([ - 'index' => 'indexName', - ]) + ->with(['index' => 'indexName']) ->willReturn(true); $this->model->indexExists('indexName'); } @@ -324,10 +328,12 @@ public function testCreateIndexFailure() { $this->indicesMock->expects($this->once()) ->method('create') - ->with([ - 'index' => 'indexName', - 'body' => [], - ]) + ->with( + [ + 'index' => 'indexName', + 'body' => [], + ] + ) ->willThrowException(new \Exception('Something went wrong')); $this->model->createIndex('indexName', []); } @@ -339,55 +345,57 @@ public function testAddFieldsMapping() { $this->indicesMock->expects($this->once()) ->method('putMapping') - ->with([ - 'index' => 'indexName', - 'type' => 'product', - 'body' => [ - 'product' => [ - '_all' => [ - 'enabled' => true, - 'type' => 'text', - ], - 'properties' => [ - 'name' => [ + ->with( + [ + 'index' => 'indexName', + 'type' => 'product', + 'body' => [ + 'product' => [ + '_all' => [ + 'enabled' => true, 'type' => 'text', ], - ], - 'dynamic_templates' => [ - [ - 'price_mapping' => [ - 'match' => 'price_*', - 'match_mapping_type' => 'string', - 'mapping' => [ - 'type' => 'float', - 'store' => true, - ], + 'properties' => [ + 'name' => [ + 'type' => 'text', ], ], - [ - 'position_mapping' => [ - 'match' => 'position_*', - 'match_mapping_type' => 'string', - 'mapping' => [ - 'type' => 'integer', - 'index' => false + 'dynamic_templates' => [ + [ + 'price_mapping' => [ + 'match' => 'price_*', + 'match_mapping_type' => 'string', + 'mapping' => [ + 'type' => 'float', + 'store' => true, + ], ], ], - ], - [ - 'string_mapping' => [ - 'match' => '*', - 'match_mapping_type' => 'string', - 'mapping' => [ - 'type' => 'text', - 'index' => false, + [ + 'position_mapping' => [ + 'match' => 'position_*', + 'match_mapping_type' => 'string', + 'mapping' => [ + 'type' => 'integer', + 'index' => false + ], + ], + ], + [ + 'string_mapping' => [ + 'match' => '*', + 'match_mapping_type' => 'string', + 'mapping' => [ + 'type' => 'text', + 'index' => false, + ], ], ], ], ], ], - ], - ]); + ] + ); $this->model->addFieldsMapping( [ 'name' => [ @@ -407,55 +415,57 @@ public function testAddFieldsMappingFailure() { $this->indicesMock->expects($this->once()) ->method('putMapping') - ->with([ - 'index' => 'indexName', - 'type' => 'product', - 'body' => [ - 'product' => [ - '_all' => [ - 'enabled' => true, - 'type' => 'text', - ], - 'properties' => [ - 'name' => [ + ->with( + [ + 'index' => 'indexName', + 'type' => 'product', + 'body' => [ + 'product' => [ + '_all' => [ + 'enabled' => true, 'type' => 'text', ], - ], - 'dynamic_templates' => [ - [ - 'price_mapping' => [ - 'match' => 'price_*', - 'match_mapping_type' => 'string', - 'mapping' => [ - 'type' => 'float', - 'store' => true, - ], + 'properties' => [ + 'name' => [ + 'type' => 'text', ], ], - [ - 'position_mapping' => [ - 'match' => 'position_*', - 'match_mapping_type' => 'string', - 'mapping' => [ - 'type' => 'integer', - 'index' => false + 'dynamic_templates' => [ + [ + 'price_mapping' => [ + 'match' => 'price_*', + 'match_mapping_type' => 'string', + 'mapping' => [ + 'type' => 'float', + 'store' => true, + ], ], ], - ], - [ - 'string_mapping' => [ - 'match' => '*', - 'match_mapping_type' => 'string', - 'mapping' => [ - 'type' => 'text', - 'index' => false, + [ + 'position_mapping' => [ + 'match' => 'position_*', + 'match_mapping_type' => 'string', + 'mapping' => [ + 'type' => 'integer', + 'index' => false + ], ], ], - ] + [ + 'string_mapping' => [ + 'match' => '*', + 'match_mapping_type' => 'string', + 'mapping' => [ + 'type' => 'text', + 'index' => false, + ], + ], + ] + ], ], ], - ], - ]) + ] + ) ->willThrowException(new \Exception('Something went wrong')); $this->model->addFieldsMapping( [ @@ -475,10 +485,12 @@ public function testDeleteMapping() { $this->indicesMock->expects($this->once()) ->method('deleteMapping') - ->with([ - 'index' => 'indexName', - 'type' => 'product', - ]); + ->with( + [ + 'index' => 'indexName', + 'type' => 'product', + ] + ); $this->model->deleteMapping( 'indexName', 'product' @@ -493,10 +505,12 @@ public function testDeleteMappingFailure() { $this->indicesMock->expects($this->once()) ->method('deleteMapping') - ->with([ - 'index' => 'indexName', - 'type' => 'product', - ]) + ->with( + [ + 'index' => 'indexName', + 'type' => 'product', + ] + ) ->willThrowException(new \Exception('Something went wrong')); $this->model->deleteMapping( 'indexName', diff --git a/app/code/Magento/Elasticsearch/Test/Unit/Model/Adapter/FieldMapper/Product/FieldProvider/DynamicFieldTest.php b/app/code/Magento/Elasticsearch/Test/Unit/Model/Adapter/FieldMapper/Product/FieldProvider/DynamicFieldTest.php index 8f3fc068411df..ca7ffbb7dccdf 100644 --- a/app/code/Magento/Elasticsearch/Test/Unit/Model/Adapter/FieldMapper/Product/FieldProvider/DynamicFieldTest.php +++ b/app/code/Magento/Elasticsearch/Test/Unit/Model/Adapter/FieldMapper/Product/FieldProvider/DynamicFieldTest.php @@ -184,21 +184,23 @@ public function testGetAllAttributesTypes( $this->fieldNameResolver->expects($this->any()) ->method('getFieldName') - ->will($this->returnCallback( - function ($attribute) use ($categoryId) { - static $callCount = []; - $attributeCode = $attribute->getAttributeCode(); - $callCount[$attributeCode] = !isset($callCount[$attributeCode]) ? 1 : ++$callCount[$attributeCode]; + ->will( + $this->returnCallback( + function ($attribute) use ($categoryId) { + static $callCount = []; + $attributeCode = $attribute->getAttributeCode(); + $callCount[$attributeCode] = !isset($callCount[$attributeCode]) ? 1 : ++$callCount[$attributeCode]; - if ($attributeCode === 'category') { - return 'category_name_' . $categoryId; - } elseif ($attributeCode === 'position') { - return 'position_' . $categoryId; - } elseif ($attributeCode === 'price') { - return 'price_' . $categoryId . '_1'; + if ($attributeCode === 'category') { + return 'category_name_' . $categoryId; + } elseif ($attributeCode === 'position') { + return 'position_' . $categoryId; + } elseif ($attributeCode === 'price') { + return 'price_' . $categoryId . '_1'; + } } - } - )); + ) + ); $priceAttributeMock = $this->getMockBuilder(AttributeAdapter::class) ->disableOriginalConstructor() ->setMethods(['getAttributeCode']) @@ -215,43 +217,47 @@ function ($attribute) use ($categoryId) { $this->attributeAdapterProvider->expects($this->any()) ->method('getByAttributeCode') ->with($this->anything()) - ->will($this->returnCallback( - function ($code) use ( - $categoryAttributeMock, - $positionAttributeMock, - $priceAttributeMock - ) { - static $callCount = []; - $callCount[$code] = !isset($callCount[$code]) ? 1 : ++$callCount[$code]; + ->will( + $this->returnCallback( + function ($code) use ( + $categoryAttributeMock, + $positionAttributeMock, + $priceAttributeMock + ) { + static $callCount = []; + $callCount[$code] = !isset($callCount[$code]) ? 1 : ++$callCount[$code]; - if ($code === 'position') { - return $positionAttributeMock; - } elseif ($code === 'category_name') { - return $categoryAttributeMock; - } elseif ($code === 'price') { - return $priceAttributeMock; + if ($code === 'position') { + return $positionAttributeMock; + } elseif ($code === 'category_name') { + return $categoryAttributeMock; + } elseif ($code === 'price') { + return $priceAttributeMock; + } } - } - )); + ) + ); $this->fieldTypeConverter->expects($this->any()) ->method('convert') ->with($this->anything()) - ->will($this->returnCallback( - function ($type) use ($complexType) { - static $callCount = []; - $callCount[$type] = !isset($callCount[$type]) ? 1 : ++$callCount[$type]; + ->will( + $this->returnCallback( + function ($type) use ($complexType) { + static $callCount = []; + $callCount[$type] = !isset($callCount[$type]) ? 1 : ++$callCount[$type]; - if ($type === 'string') { - return 'string'; - } elseif ($type === 'float') { - return 'float'; - } elseif ($type === 'integer') { - return 'integer'; - } else { - return $complexType; + if ($type === 'string') { + return 'string'; + } elseif ($type === 'float') { + return 'float'; + } elseif ($type === 'integer') { + return 'integer'; + } else { + return $complexType; + } } - } - )); + ) + ); $this->assertEquals( $expected, diff --git a/app/code/Magento/Elasticsearch6/Model/Client/Elasticsearch.php b/app/code/Magento/Elasticsearch6/Model/Client/Elasticsearch.php index 3cddec4263396..34129a5af0012 100644 --- a/app/code/Magento/Elasticsearch6/Model/Client/Elasticsearch.php +++ b/app/code/Magento/Elasticsearch6/Model/Client/Elasticsearch.php @@ -141,10 +141,12 @@ public function bulkQuery($query) */ public function createIndex($index, $settings) { - $this->getClient()->indices()->create([ - 'index' => $index, - 'body' => $settings, - ]); + $this->getClient()->indices()->create( + [ + 'index' => $index, + 'body' => $settings, + ] + ); } /** @@ -305,10 +307,12 @@ public function addFieldsMapping(array $fields, $index, $entityType) */ public function deleteMapping($index, $entityType) { - $this->getClient()->indices()->deleteMapping([ - 'index' => $index, - 'type' => $entityType, - ]); + $this->getClient()->indices()->deleteMapping( + [ + 'index' => $index, + 'type' => $entityType, + ] + ); } /** diff --git a/app/code/Magento/Elasticsearch6/Test/Unit/Model/Client/ElasticsearchTest.php b/app/code/Magento/Elasticsearch6/Test/Unit/Model/Client/ElasticsearchTest.php index 11392bb0369fc..487a5a886f951 100644 --- a/app/code/Magento/Elasticsearch6/Test/Unit/Model/Client/ElasticsearchTest.php +++ b/app/code/Magento/Elasticsearch6/Test/Unit/Model/Client/ElasticsearchTest.php @@ -41,30 +41,34 @@ class ElasticsearchTest extends \PHPUnit\Framework\TestCase protected function setUp() { $this->elasticsearchClientMock = $this->getMockBuilder(\Elasticsearch\Client::class) - ->setMethods([ - 'indices', - 'ping', - 'bulk', - 'search', - 'scroll', - 'suggest', - 'info', - ]) + ->setMethods( + [ + 'indices', + 'ping', + 'bulk', + 'search', + 'scroll', + 'suggest', + 'info', + ] + ) ->disableOriginalConstructor() ->getMock(); $this->indicesMock = $this->getMockBuilder(\Elasticsearch\Namespaces\IndicesNamespace::class) - ->setMethods([ - 'exists', - 'getSettings', - 'create', - 'delete', - 'putMapping', - 'deleteMapping', - 'stats', - 'updateAliases', - 'existsAlias', - 'getAlias', - ]) + ->setMethods( + [ + 'exists', + 'getSettings', + 'create', + 'delete', + 'putMapping', + 'deleteMapping', + 'stats', + 'updateAliases', + 'existsAlias', + 'getAlias', + ] + ) ->disableOriginalConstructor() ->getMock(); $this->elasticsearchClientMock->expects($this->any()) @@ -177,10 +181,12 @@ public function testCreateIndexExists() { $this->indicesMock->expects($this->once()) ->method('create') - ->with([ - 'index' => 'indexName', - 'body' => [], - ]); + ->with( + [ + 'index' => 'indexName', + 'body' => [], + ] + ); $this->model->createIndex('indexName', []); } @@ -266,9 +272,7 @@ public function testIndexExists() { $this->indicesMock->expects($this->once()) ->method('exists') - ->with([ - 'index' => 'indexName', - ]) + ->with(['index' => 'indexName']) ->willReturn(true); $this->model->indexExists('indexName'); } @@ -324,10 +328,12 @@ public function testCreateIndexFailure() { $this->indicesMock->expects($this->once()) ->method('create') - ->with([ - 'index' => 'indexName', - 'body' => [], - ]) + ->with( + [ + 'index' => 'indexName', + 'body' => [], + ] + ) ->willThrowException(new \Exception('Something went wrong')); $this->model->createIndex('indexName', []); } @@ -339,55 +345,57 @@ public function testAddFieldsMapping() { $this->indicesMock->expects($this->once()) ->method('putMapping') - ->with([ - 'index' => 'indexName', - 'type' => 'product', - 'body' => [ - 'product' => [ - 'properties' => [ - '_search' => [ - 'type' => 'text', - ], - 'name' => [ - 'type' => 'text', - ], - ], - 'dynamic_templates' => [ - [ - 'price_mapping' => [ - 'match' => 'price_*', - 'match_mapping_type' => 'string', - 'mapping' => [ - 'type' => 'float', - 'store' => true, - ], + ->with( + [ + 'index' => 'indexName', + 'type' => 'product', + 'body' => [ + 'product' => [ + 'properties' => [ + '_search' => [ + 'type' => 'text', + ], + 'name' => [ + 'type' => 'text', ], ], - [ - 'position_mapping' => [ - 'match' => 'position_*', - 'match_mapping_type' => 'string', - 'mapping' => [ - 'type' => 'integer', - 'index' => false + 'dynamic_templates' => [ + [ + 'price_mapping' => [ + 'match' => 'price_*', + 'match_mapping_type' => 'string', + 'mapping' => [ + 'type' => 'float', + 'store' => true, + ], ], ], - ], - [ - 'string_mapping' => [ - 'match' => '*', - 'match_mapping_type' => 'string', - 'mapping' => [ - 'type' => 'text', - 'index' => false, - 'copy_to' => '_search' + [ + 'position_mapping' => [ + 'match' => 'position_*', + 'match_mapping_type' => 'string', + 'mapping' => [ + 'type' => 'integer', + 'index' => false + ], ], ], - ] + [ + 'string_mapping' => [ + 'match' => '*', + 'match_mapping_type' => 'string', + 'mapping' => [ + 'type' => 'text', + 'index' => false, + 'copy_to' => '_search' + ], + ], + ] + ], ], ], - ], - ]); + ] + ); $this->model->addFieldsMapping( [ 'name' => [ @@ -407,55 +415,57 @@ public function testAddFieldsMappingFailure() { $this->indicesMock->expects($this->once()) ->method('putMapping') - ->with([ - 'index' => 'indexName', - 'type' => 'product', - 'body' => [ - 'product' => [ - 'properties' => [ - '_search' => [ - 'type' => 'text', - ], - 'name' => [ - 'type' => 'text', - ], - ], - 'dynamic_templates' => [ - [ - 'price_mapping' => [ - 'match' => 'price_*', - 'match_mapping_type' => 'string', - 'mapping' => [ - 'type' => 'float', - 'store' => true, - ], + ->with( + [ + 'index' => 'indexName', + 'type' => 'product', + 'body' => [ + 'product' => [ + 'properties' => [ + '_search' => [ + 'type' => 'text', + ], + 'name' => [ + 'type' => 'text', ], ], - [ - 'position_mapping' => [ - 'match' => 'position_*', - 'match_mapping_type' => 'string', - 'mapping' => [ - 'type' => 'integer', - 'index' => false + 'dynamic_templates' => [ + [ + 'price_mapping' => [ + 'match' => 'price_*', + 'match_mapping_type' => 'string', + 'mapping' => [ + 'type' => 'float', + 'store' => true, + ], ], ], - ], - [ - 'string_mapping' => [ - 'match' => '*', - 'match_mapping_type' => 'string', - 'mapping' => [ - 'type' => 'text', - 'index' => false, - 'copy_to' => '_search' + [ + 'position_mapping' => [ + 'match' => 'position_*', + 'match_mapping_type' => 'string', + 'mapping' => [ + 'type' => 'integer', + 'index' => false + ], ], ], - ] + [ + 'string_mapping' => [ + 'match' => '*', + 'match_mapping_type' => 'string', + 'mapping' => [ + 'type' => 'text', + 'index' => false, + 'copy_to' => '_search' + ], + ], + ] + ], ], ], - ], - ]) + ] + ) ->willThrowException(new \Exception('Something went wrong')); $this->model->addFieldsMapping( [ @@ -475,10 +485,12 @@ public function testDeleteMapping() { $this->indicesMock->expects($this->once()) ->method('deleteMapping') - ->with([ - 'index' => 'indexName', - 'type' => 'product', - ]); + ->with( + [ + 'index' => 'indexName', + 'type' => 'product', + ] + ); $this->model->deleteMapping( 'indexName', 'product' @@ -493,10 +505,12 @@ public function testDeleteMappingFailure() { $this->indicesMock->expects($this->once()) ->method('deleteMapping') - ->with([ - 'index' => 'indexName', - 'type' => 'product', - ]) + ->with( + [ + 'index' => 'indexName', + 'type' => 'product', + ] + ) ->willThrowException(new \Exception('Something went wrong')); $this->model->deleteMapping( 'indexName', diff --git a/app/code/Magento/Email/Test/Unit/Block/Adminhtml/Template/PreviewTest.php b/app/code/Magento/Email/Test/Unit/Block/Adminhtml/Template/PreviewTest.php index b91d94edb589e..286e9a989d4d8 100644 --- a/app/code/Magento/Email/Test/Unit/Block/Adminhtml/Template/PreviewTest.php +++ b/app/code/Magento/Email/Test/Unit/Block/Adminhtml/Template/PreviewTest.php @@ -38,14 +38,16 @@ public function testToHtml($requestParamMap) { $storeId = 1; $template = $this->getMockBuilder(\Magento\Email\Model\Template::class) - ->setMethods([ - 'setDesignConfig', - 'getDesignConfig', - '__wakeup', - 'getProcessedTemplate', - 'getAppState', - 'revertDesign' - ]) + ->setMethods( + [ + 'setDesignConfig', + 'getDesignConfig', + '__wakeup', + 'getProcessedTemplate', + 'getAppState', + 'revertDesign' + ] + ) ->disableOriginalConstructor() ->getMock(); $template->expects($this->once()) @@ -55,9 +57,7 @@ public function testToHtml($requestParamMap) $designConfigData = []; $template->expects($this->atLeastOnce()) ->method('getDesignConfig') - ->willReturn(new \Magento\Framework\DataObject( - $designConfigData - )); + ->willReturn(new \Magento\Framework\DataObject($designConfigData)); $emailFactory = $this->createPartialMock(\Magento\Email\Model\TemplateFactory::class, ['create']); $emailFactory->expects($this->any()) ->method('create') @@ -79,9 +79,7 @@ public function testToHtml($requestParamMap) $storeManager->expects($this->any())->method('getDefaultStoreView')->willReturn(null); $storeManager->expects($this->any())->method('getStores')->willReturn([$store]); $appState = $this->getMockBuilder(\Magento\Framework\App\State::class) - ->setConstructorArgs([ - $scopeConfig - ]) + ->setConstructorArgs([$scopeConfig]) ->setMethods(['emulateAreaCode']) ->disableOriginalConstructor() ->getMock(); diff --git a/app/code/Magento/GraphQlCache/Model/Plugin/Query/Resolver.php b/app/code/Magento/GraphQlCache/Model/Plugin/Query/Resolver.php index 9ce391fe0e176..d505ca6fbb6ea 100644 --- a/app/code/Magento/GraphQlCache/Model/Plugin/Query/Resolver.php +++ b/app/code/Magento/GraphQlCache/Model/Plugin/Query/Resolver.php @@ -63,21 +63,23 @@ public function afterResolve( $cacheAnnotation ); } elseif ($resolvedValue instanceof \Magento\Framework\GraphQl\Query\Resolver\Value) { - $resolvedValue->then(function () use ($resolvedValue, $field, $cacheAnnotation) { - if (is_array($resolvedValue->promise->result)) { - $this->cacheableQueryHandler->handleCacheFromResolverResponse( - $resolvedValue->promise->result, - $cacheAnnotation - ); - } else { - // case if string or integer we pass in a single array element - $this->cacheableQueryHandler->handleCacheFromResolverResponse( - $resolvedValue->promise->result === null ? - [] : [$field->getName() => $resolvedValue->promise->result], - $cacheAnnotation - ); + $resolvedValue->then( + function () use ($resolvedValue, $field, $cacheAnnotation) { + if (is_array($resolvedValue->promise->result)) { + $this->cacheableQueryHandler->handleCacheFromResolverResponse( + $resolvedValue->promise->result, + $cacheAnnotation + ); + } else { + // case if string or integer we pass in a single array element + $this->cacheableQueryHandler->handleCacheFromResolverResponse( + $resolvedValue->promise->result === null ? + [] : [$field->getName() => $resolvedValue->promise->result], + $cacheAnnotation + ); + } } - }); + ); } else { // case if string or integer we pass in a single array element $this->cacheableQueryHandler->handleCacheFromResolverResponse( diff --git a/app/code/Magento/ImportExport/Controller/Adminhtml/Export/File/Download.php b/app/code/Magento/ImportExport/Controller/Adminhtml/Export/File/Download.php index 8dbd9a0ae44ba..0e6bca26d2062 100644 --- a/app/code/Magento/ImportExport/Controller/Adminhtml/Export/File/Download.php +++ b/app/code/Magento/ImportExport/Controller/Adminhtml/Export/File/Download.php @@ -72,6 +72,7 @@ public function execute() DirectoryList::VAR_DIR ); } + // phpcs:ignore Magento2.Exceptions.ThrowCatch } catch (LocalizedException | \Exception $exception) { throw new LocalizedException(__('There are no export file with such name %1', $fileName)); } diff --git a/app/code/Magento/ImportExport/Test/Unit/Model/ImportTest.php b/app/code/Magento/ImportExport/Test/Unit/Model/ImportTest.php index 6fdf9b04450c0..50e71512c3d28 100644 --- a/app/code/Magento/ImportExport/Test/Unit/Model/ImportTest.php +++ b/app/code/Magento/ImportExport/Test/Unit/Model/ImportTest.php @@ -141,19 +141,23 @@ protected function setUp() ->disableOriginalConstructor() ->getMock(); - $this->errorAggregatorMock = $this->getErrorAggregatorObject([ - 'initValidationStrategy', - 'getErrorsCount', - ]); + $this->errorAggregatorMock = $this->getErrorAggregatorObject( + [ + 'initValidationStrategy', + 'getErrorsCount', + ] + ); $this->_entityAdapter = $this->getMockBuilder(\Magento\ImportExport\Model\Import\Entity\AbstractEntity::class) ->disableOriginalConstructor() - ->setMethods([ - 'importData', - '_saveValidatedBunches', - 'getErrorAggregator', - 'setSource', - 'validateData', - ]) + ->setMethods( + [ + 'importData', + '_saveValidatedBunches', + 'getErrorAggregator', + 'setSource', + 'validateData', + ] + ) ->getMockForAbstractClass(); $this->_entityAdapter->method('getErrorAggregator') ->willReturn($this->errorAggregatorMock); @@ -201,33 +205,37 @@ protected function setUp() ->method('getDriver') ->willReturn($this->_driver); $this->import = $this->getMockBuilder(\Magento\ImportExport\Model\Import::class) - ->setConstructorArgs([ - $logger, - $this->_filesystem, - $this->_importExportData, - $this->_coreConfig, - $this->_importConfig, - $this->_entityFactory, - $this->_importData, - $this->_csvFactory, - $this->_httpFactory, - $this->_uploaderFactory, - $this->_behaviorFactory, - $this->indexerRegistry, - $this->historyModel, - $this->dateTime - ]) - ->setMethods([ - 'getDataSourceModel', - 'setData', - 'getData', - 'getProcessedEntitiesCount', - 'getProcessedRowsCount', - 'getEntity', - 'getBehavior', - 'isReportEntityType', - '_getEntityAdapter' - ]) + ->setConstructorArgs( + [ + $logger, + $this->_filesystem, + $this->_importExportData, + $this->_coreConfig, + $this->_importConfig, + $this->_entityFactory, + $this->_importData, + $this->_csvFactory, + $this->_httpFactory, + $this->_uploaderFactory, + $this->_behaviorFactory, + $this->indexerRegistry, + $this->historyModel, + $this->dateTime + ] + ) + ->setMethods( + [ + 'getDataSourceModel', + 'setData', + 'getData', + 'getProcessedEntitiesCount', + 'getProcessedRowsCount', + 'getEntity', + 'getBehavior', + 'isReportEntityType', + '_getEntityAdapter' + ] + ) ->getMock(); $this->setPropertyValue($this->import, '_varDirectory', $this->_varDirectory); } @@ -459,10 +467,12 @@ public function testValidateSource() $this->import->expects($this->any()) ->method('getData') - ->willReturnMap([ - [Import::FIELD_NAME_VALIDATION_STRATEGY, null, $validationStrategy], - [Import::FIELD_NAME_ALLOWED_ERROR_COUNT, null, $allowedErrorCount], - ]); + ->willReturnMap( + [ + [Import::FIELD_NAME_VALIDATION_STRATEGY, null, $validationStrategy], + [Import::FIELD_NAME_ALLOWED_ERROR_COUNT, null, $allowedErrorCount], + ] + ); $this->assertTrue($this->import->validateSource($csvMock)); @@ -500,15 +510,15 @@ public function testInvalidateIndex() ->method('getRelatedIndexers') ->willReturn($indexers); $this->_importConfig->method('getEntities') - ->willReturn([ - 'test' => [] - ]); + ->willReturn(['test' => []]); $this->indexerRegistry->expects($this->any()) ->method('get') - ->willReturnMap([ - ['indexer_1', $indexer1], - ['indexer_2', $indexer2], - ]); + ->willReturnMap( + [ + ['indexer_1', $indexer1], + ['indexer_2', $indexer2], + ] + ); $import = new Import( $logger, @@ -537,9 +547,7 @@ public function testInvalidateIndexWithoutIndexers() ->method('getRelatedIndexers') ->willReturn([]); $this->_importConfig->method('getEntities') - ->willReturn([ - 'test' => [] - ]); + ->willReturn(['test' => []]); $logger = $this->getMockBuilder(\Psr\Log\LoggerInterface::class) ->disableOriginalConstructor() @@ -569,9 +577,7 @@ public function testInvalidateIndexWithoutIndexers() public function testGetKnownEntity() { $this->_importConfig->method('getEntities') - ->willReturn([ - 'test' => [] - ]); + ->willReturn(['test' => []]); $logger = $this->getMockBuilder(\Psr\Log\LoggerInterface::class) ->disableOriginalConstructor() @@ -607,9 +613,7 @@ public function testGetKnownEntity() public function testGetUnknownEntity($entity) { $this->_importConfig->method('getEntities') - ->willReturn([ - 'test' => [] - ]); + ->willReturn(['test' => []]); $logger = $this->getMockBuilder(\Psr\Log\LoggerInterface::class) ->disableOriginalConstructor() @@ -661,9 +665,9 @@ public function testIsReportEntityType($entity, $getEntityResult, $expectedResul { $importMock = $this->getMockBuilder(\Magento\ImportExport\Model\Import::class) ->disableOriginalConstructor() - ->setMethods([ - 'getEntity', '_getEntityAdapter', 'getEntityTypeCode', 'isNeedToLogInHistory' - ]) + ->setMethods( + ['getEntity', '_getEntityAdapter', 'getEntityTypeCode', 'isNeedToLogInHistory'] + ) ->getMock(); $importMock->expects($this->any())->method('_getEntityAdapter')->willReturnSelf(); $importMock->expects($this->any())->method('getEntityTypeCode')->willReturn('catalog_product'); @@ -699,9 +703,9 @@ public function testIsReportEntityTypeException($entity, $getEntitiesResult, $ge { $importMock = $this->getMockBuilder(\Magento\ImportExport\Model\Import::class) ->disableOriginalConstructor() - ->setMethods([ - 'getEntity', '_getEntityAdapter', 'getEntityTypeCode', 'isNeedToLogInHistory' - ]) + ->setMethods( + ['getEntity', '_getEntityAdapter', 'getEntityTypeCode', 'isNeedToLogInHistory'] + ) ->getMock(); $importMock->expects($this->any())->method('_getEntityAdapter')->willReturnSelf(); $importMock->expects($this->any())->method('getEntityTypeCode')->willReturn('catalog_product'); @@ -912,9 +916,11 @@ public function testCreateHistoryReportThrowException() $this->_driver ->expects($this->any()) ->method('fileGetContents') - ->willReturnCallback(function () use ($phrase) { - throw new \Magento\Framework\Exception\FileSystemException($phrase); - }); + ->willReturnCallback( + function () use ($phrase) { + throw new \Magento\Framework\Exception\FileSystemException($phrase); + } + ); $this->dateTime ->expects($this->once()) ->method('gmtTimestamp') diff --git a/app/code/Magento/Sales/Model/Rss/OrderStatus.php b/app/code/Magento/Sales/Model/Rss/OrderStatus.php index 3f184b57107a1..c3c4456c6b7ca 100644 --- a/app/code/Magento/Sales/Model/Rss/OrderStatus.php +++ b/app/code/Magento/Sales/Model/Rss/OrderStatus.php @@ -229,9 +229,11 @@ protected function getEntries() $entries[] = ['title' => $title, 'link' => $url, 'description' => $description]; } } - $title = __('Order #%1 created at %2', $this->order->getIncrementId(), $this->localeDate->formatDate( - $this->order->getCreatedAt() - )); + $title = __( + 'Order #%1 created at %2', + $this->order->getIncrementId(), + $this->localeDate->formatDate($this->order->getCreatedAt()) + ); $url = $this->urlBuilder->getUrl('sales/order/view', ['order_id' => $this->order->getId()]); $description = '<p>' . __('Current Status: %1<br/>', $this->order->getStatusLabel()) . __('Total: %1<br/>', $this->order->formatPrice($this->order->getGrandTotal())) . '</p>'; diff --git a/app/code/Magento/Sales/Test/Unit/Block/Order/Info/Buttons/RssTest.php b/app/code/Magento/Sales/Test/Unit/Block/Order/Info/Buttons/RssTest.php index 965a80ef189f6..80780d91a68d6 100644 --- a/app/code/Magento/Sales/Test/Unit/Block/Order/Info/Buttons/RssTest.php +++ b/app/code/Magento/Sales/Test/Unit/Block/Order/Info/Buttons/RssTest.php @@ -91,11 +91,14 @@ public function testGetLink() $this->signature->expects($this->once())->method('signData')->willReturn($signature); $link = 'http://magento.com/rss/feed/index/type/order_status?data=' . $data .'&signature='.$signature; $this->urlBuilderInterface->expects($this->once())->method('getUrl') - ->with([ - 'type' => 'order_status', - '_secure' => true, - '_query' => ['data' => $data, 'signature' => $signature], - ])->willReturn($link); + ->with( + [ + 'type' => 'order_status', + '_secure' => true, + '_query' => ['data' => $data, 'signature' => $signature], + ] + ) + ->willReturn($link); $this->assertEquals($link, $this->rss->getLink()); } diff --git a/app/code/Magento/Sales/Test/Unit/Model/Rss/OrderStatusTest.php b/app/code/Magento/Sales/Test/Unit/Model/Rss/OrderStatusTest.php index f04e102cccf32..03080bc0479be 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Rss/OrderStatusTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Rss/OrderStatusTest.php @@ -111,17 +111,21 @@ protected function setUp() $this->scopeConfigInterface = $this->createMock(\Magento\Framework\App\Config\ScopeConfigInterface::class); $this->order = $this->getMockBuilder(\Magento\Sales\Model\Order::class) - ->setMethods([ - '__sleep', - '__wakeup', - 'getIncrementId', - 'getId', - 'getCustomerId', - 'load', - 'getStatusLabel', - 'formatPrice', - 'getGrandTotal', - ])->disableOriginalConstructor()->getMock(); + ->setMethods( + [ + '__sleep', + '__wakeup', + 'getIncrementId', + 'getId', + 'getCustomerId', + 'load', + 'getStatusLabel', + 'formatPrice', + 'getGrandTotal', + ] + ) + ->disableOriginalConstructor() + ->getMock(); $this->order->expects($this->any())->method('getId')->will($this->returnValue(1)); $this->order->expects($this->any())->method('getIncrementId')->will($this->returnValue('100000001')); $this->order->expects($this->any())->method('getCustomerId')->will($this->returnValue(1)); @@ -264,10 +268,12 @@ public function testIsAllowed() public function testGetCacheKey($requestData, $result) { $this->requestInterface->expects($this->any())->method('getParam') - ->willReturnMap([ - ['data', null, $requestData], - ['signature', null, 'signature'], - ]); + ->willReturnMap( + [ + ['data', null, $requestData], + ['signature', null, 'signature'], + ] + ); $this->signature->expects($this->never())->method('signData'); $this->signature->expects($this->any()) ->method('isValid') diff --git a/app/code/Magento/Sales/Ui/Component/Listing/Column/Status/Options.php b/app/code/Magento/Sales/Ui/Component/Listing/Column/Status/Options.php index 4a597b1f42540..14964f16b701e 100644 --- a/app/code/Magento/Sales/Ui/Component/Listing/Column/Status/Options.php +++ b/app/code/Magento/Sales/Ui/Component/Listing/Column/Status/Options.php @@ -43,9 +43,12 @@ public function toOptionArray() if ($this->options === null) { $options = $this->collectionFactory->create()->toOptionArray(); - array_walk($options, function (&$option) { - $option['__disableTmpl'] = true; - }); + array_walk( + $options, + function (&$option) { + $option['__disableTmpl'] = true; + } + ); $this->options = $options; } diff --git a/app/code/Magento/SalesRule/Model/Coupon/AdminCodeLimitManager.php b/app/code/Magento/SalesRule/Model/Coupon/AdminCodeLimitManager.php index 25f2f30952054..92217f4b8b567 100644 --- a/app/code/Magento/SalesRule/Model/Coupon/AdminCodeLimitManager.php +++ b/app/code/Magento/SalesRule/Model/Coupon/AdminCodeLimitManager.php @@ -21,6 +21,7 @@ class AdminCodeLimitManager implements CodeLimitManagerInterface */ public function checkRequest(string $code): void { + //phpcs:ignore Squiz.PHP.NonExecutableCode.ReturnNotRequired return; } } diff --git a/app/code/Magento/Store/Model/Store.php b/app/code/Magento/Store/Model/Store.php index 6870437ac1c37..dab9c55c216d9 100644 --- a/app/code/Magento/Store/Model/Store.php +++ b/app/code/Magento/Store/Model/Store.php @@ -1086,9 +1086,11 @@ public function afterSave() $event = $this->_eventPrefix . '_edit'; } $store = $this; - $this->getResource()->addCommitCallback(function () use ($event, $store) { - $this->eventManager->dispatch($event, ['store' => $store]); - }); + $this->getResource()->addCommitCallback( + function () use ($event, $store) { + $this->eventManager->dispatch($event, ['store' => $store]); + } + ); $this->pillPut->put(); return parent::afterSave(); } @@ -1289,10 +1291,12 @@ public function beforeDelete() public function afterDelete() { $store = $this; - $this->getResource()->addCommitCallback(function () use ($store) { - $this->_storeManager->reinitStores(); - $this->eventManager->dispatch($this->_eventPrefix . '_delete', ['store' => $store]); - }); + $this->getResource()->addCommitCallback( + function () use ($store) { + $this->_storeManager->reinitStores(); + $this->eventManager->dispatch($this->_eventPrefix . '_delete', ['store' => $store]); + } + ); parent::afterDelete(); $this->_configCacheType->clean(); diff --git a/app/code/Magento/Tax/Model/System/Message/Notifications.php b/app/code/Magento/Tax/Model/System/Message/Notifications.php index b90b8c3af3c58..52d6efd089e06 100644 --- a/app/code/Magento/Tax/Model/System/Message/Notifications.php +++ b/app/code/Magento/Tax/Model/System/Message/Notifications.php @@ -89,6 +89,7 @@ public function __construct( */ public function getIdentity() { + // phpcs:ignore Magento2.Functions.DiscouragedFunction return md5('TAX_NOTIFICATION'); } diff --git a/app/code/Magento/Ui/Controller/Index/Render.php b/app/code/Magento/Ui/Controller/Index/Render.php index 6f0cc0b6595a4..faab203547064 100644 --- a/app/code/Magento/Ui/Controller/Index/Render.php +++ b/app/code/Magento/Ui/Controller/Index/Render.php @@ -113,10 +113,12 @@ public function execute() \Zend\Http\AbstractMessage::VERSION_11, 'Forbidden' ); - return $resultJson->setData([ - 'error' => $this->escaper->escapeHtml('Forbidden'), - 'errorcode' => 403 - ]); + return $resultJson->setData( + [ + 'error' => $this->escaper->escapeHtml('Forbidden'), + 'errorcode' => 403 + ] + ); } } catch (\Magento\Framework\Exception\LocalizedException $e) { $this->logger->critical($e); diff --git a/app/code/Magento/Ui/Test/Unit/Controller/Index/RenderTest.php b/app/code/Magento/Ui/Test/Unit/Controller/Index/RenderTest.php index 5d6bdffa12c7a..646cea81212f9 100644 --- a/app/code/Magento/Ui/Test/Unit/Controller/Index/RenderTest.php +++ b/app/code/Magento/Ui/Test/Unit/Controller/Index/RenderTest.php @@ -322,10 +322,12 @@ public function testExecuteWithoutPermissions(array $dataProviderConfig, $isAllo $jsonResultMock->expects($this->at(1)) ->method('setData') - ->with([ - 'error' => 'Forbidden', - 'errorcode' => 403 - ]) + ->with( + [ + 'error' => 'Forbidden', + 'errorcode' => 403 + ] + ) ->willReturnSelf(); $this->resultJsonFactoryMock->expects($this->any()) From 27955561dcc2b428397ebf596307bac15540a725 Mon Sep 17 00:00:00 2001 From: Dan Mooney <dmooney@adobe.com> Date: Thu, 27 Jun 2019 11:22:13 -0500 Subject: [PATCH 560/773] MC-17814: Insert Widget Slide Out --- .../Magento/Widget/Block/Adminhtml/Widget/Form.php | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Widget/Block/Adminhtml/Widget/Form.php b/app/code/Magento/Widget/Block/Adminhtml/Widget/Form.php index 82f5fd92c1536..e4b85c36a4bf4 100644 --- a/app/code/Magento/Widget/Block/Adminhtml/Widget/Form.php +++ b/app/code/Magento/Widget/Block/Adminhtml/Widget/Form.php @@ -11,6 +11,9 @@ */ namespace Magento\Widget\Block\Adminhtml\Widget; +/** + * Widget Form Block class + */ class Form extends \Magento\Backend\Block\Widget\Form\Generic { /** @@ -47,8 +50,12 @@ protected function _prepareForm() $form = $this->_formFactory->create(); // Add messages container to fieldset - $fieldset = $form->addFieldset('base_fieldset', ['legend' => '<div data-role="messages"></div>', - 'comment' => __('Inserting a widget does not create a widget instance.')]); + $fieldset = $form->addFieldset( + 'base_fieldset', + [ + 'comment' => __('Inserting a widget does not create a widget instance.'), + ] + ); $fieldset->addField( 'select_widget_type', From d0fff402703d2dbf1a48f0bf8254aa3973b06105 Mon Sep 17 00:00:00 2001 From: Dan Mooney <dmooney@adobe.com> Date: Thu, 27 Jun 2019 12:07:49 -0500 Subject: [PATCH 561/773] MC-17814: Insert Widget Slide Out --- .../adminhtml/templates/widget/form/renderer/fieldset.phtml | 3 +++ app/code/Magento/Widget/Block/Adminhtml/Widget/Form.php | 1 + 2 files changed, 4 insertions(+) diff --git a/app/code/Magento/Backend/view/adminhtml/templates/widget/form/renderer/fieldset.phtml b/app/code/Magento/Backend/view/adminhtml/templates/widget/form/renderer/fieldset.phtml index a708871c7ed00..7eb6e95fa85bf 100644 --- a/app/code/Magento/Backend/view/adminhtml/templates/widget/form/renderer/fieldset.phtml +++ b/app/code/Magento/Backend/view/adminhtml/templates/widget/form/renderer/fieldset.phtml @@ -53,6 +53,9 @@ if ($isField) { <?php if (!$element->getNoContainer()) : ?> <fieldset class="<?= $block->escapeHtmlAttr($cssClass) ?>" id="<?= $block->escapeHtmlAttr($id) ?>"> + <?php if (strlen($element->getBeforeElementHtml())) : ?> + <?= $element->getBeforeElementHtml() ?> + <?php endif ?> <?php if ($element->getLegend() && !$isWrapped) : ?> <legend class="<?= /* @noEscape */ $isField ? 'label admin__field-label' : 'admin__legend legend' ?>"> <span><?= $block->escapeHtml($element->getLegend()) ?></span> diff --git a/app/code/Magento/Widget/Block/Adminhtml/Widget/Form.php b/app/code/Magento/Widget/Block/Adminhtml/Widget/Form.php index e4b85c36a4bf4..04447219464aa 100644 --- a/app/code/Magento/Widget/Block/Adminhtml/Widget/Form.php +++ b/app/code/Magento/Widget/Block/Adminhtml/Widget/Form.php @@ -53,6 +53,7 @@ protected function _prepareForm() $fieldset = $form->addFieldset( 'base_fieldset', [ + 'before_element_html' => '<div data-role="messages"></div>', 'comment' => __('Inserting a widget does not create a widget instance.'), ] ); From cee3f859ad02ff025bc2e5a118b1e51fccc425dd Mon Sep 17 00:00:00 2001 From: Krissy Hiserote <khiserote@magento.com> Date: Thu, 27 Jun 2019 15:18:55 -0500 Subject: [PATCH 562/773] MC-15776: Merge release branch into 2.3-develop - fix static failures --- .../Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php | 1 + app/code/Magento/Customer/Ui/Component/ColumnFactory.php | 4 +++- .../FieldMapper/Product/FieldProvider/DynamicFieldTest.php | 4 +++- app/code/Magento/Tax/Model/System/Message/Notifications.php | 2 +- 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php index 2d705cb2357af..5d1e853cef3d1 100755 --- a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php +++ b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php @@ -660,6 +660,7 @@ private function isProductExists() * @throws \Magento\Framework\Exception\LocalizedException * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) * @api * @since 101.0.0 */ diff --git a/app/code/Magento/Customer/Ui/Component/ColumnFactory.php b/app/code/Magento/Customer/Ui/Component/ColumnFactory.php index f19ae03189eaa..cb66dc3db7c77 100644 --- a/app/code/Magento/Customer/Ui/Component/ColumnFactory.php +++ b/app/code/Magento/Customer/Ui/Component/ColumnFactory.php @@ -74,7 +74,9 @@ public function create(array $attributeData, $columnName, $context, array $confi 'dataType' => $this->getDataType($attributeData[AttributeMetadata::FRONTEND_INPUT]), 'align' => 'left', 'visible' => (bool)$attributeData[AttributeMetadata::IS_VISIBLE_IN_GRID], - 'component' => $this->getJsComponent($this->getDataType($attributeData[AttributeMetadata::FRONTEND_INPUT])), + 'component' => $this->getJsComponent( + $this->getDataType($attributeData[AttributeMetadata::FRONTEND_INPUT]) + ), '__disableTmpl' => 'true' ], $config diff --git a/app/code/Magento/Elasticsearch/Test/Unit/Model/Adapter/FieldMapper/Product/FieldProvider/DynamicFieldTest.php b/app/code/Magento/Elasticsearch/Test/Unit/Model/Adapter/FieldMapper/Product/FieldProvider/DynamicFieldTest.php index ca7ffbb7dccdf..cdb4ea4021f79 100644 --- a/app/code/Magento/Elasticsearch/Test/Unit/Model/Adapter/FieldMapper/Product/FieldProvider/DynamicFieldTest.php +++ b/app/code/Magento/Elasticsearch/Test/Unit/Model/Adapter/FieldMapper/Product/FieldProvider/DynamicFieldTest.php @@ -189,7 +189,9 @@ public function testGetAllAttributesTypes( function ($attribute) use ($categoryId) { static $callCount = []; $attributeCode = $attribute->getAttributeCode(); - $callCount[$attributeCode] = !isset($callCount[$attributeCode]) ? 1 : ++$callCount[$attributeCode]; + $callCount[$attributeCode] = !isset($callCount[$attributeCode]) + ? 1 + : ++$callCount[$attributeCode]; if ($attributeCode === 'category') { return 'category_name_' . $categoryId; diff --git a/app/code/Magento/Tax/Model/System/Message/Notifications.php b/app/code/Magento/Tax/Model/System/Message/Notifications.php index 52d6efd089e06..ca59ab9eec3bf 100644 --- a/app/code/Magento/Tax/Model/System/Message/Notifications.php +++ b/app/code/Magento/Tax/Model/System/Message/Notifications.php @@ -89,7 +89,7 @@ public function __construct( */ public function getIdentity() { - // phpcs:ignore Magento2.Functions.DiscouragedFunction + // phpcs:ignore Magento2.Security.InsecureFunction return md5('TAX_NOTIFICATION'); } From 21027270d0682872d97d43487feecfe561f51b7f Mon Sep 17 00:00:00 2001 From: Tom Reece <treece@adobe.com> Date: Thu, 27 Jun 2019 16:20:53 -0500 Subject: [PATCH 563/773] MQE-1596: Fix skipped tests that originated from the MTF to MFTF conversion --- .../Mftf/Section/StorefrontProductActionSection.xml | 2 +- .../Test/Mftf/Section/CheckoutCartSummarySection.xml | 2 +- .../Mftf/Section/CheckoutShippingMethodsSection.xml | 2 +- .../Test/Mftf/Section/StorefrontMiniCartSection.xml | 2 +- .../Config/Test/Mftf/Section/GeneralSection.xml | 4 ++-- .../StorefrontCustomerLogoutActionGroup.xml | 1 + .../Mftf/Section/StorefrontCustomerSidebarSection.xml | 2 +- .../Mftf/Test/VerifyDisabledCustomerGroupFieldTest.xml | 1 + .../Test/Mftf/Section/NewsletterTemplateSection.xml | 6 +++--- .../VerifyTinyMCEv4IsNativeWYSIWYGOnNewsletterTest.xml | 1 + .../Test/Mftf/Section/OrderReportMainSection.xml | 4 ++-- .../Mftf/Test/CancelOrdersInOrderSalesReportTest.xml | 5 ++--- .../Test/Mftf/ActionGroup/AdminOrderActionGroup.xml | 2 ++ .../Mftf/ActionGroup/AdminOrderGridActionGroup.xml | 4 ++++ .../Section/AdminInvoicePaymentShippingSection.xml | 4 ++-- .../Test/Mftf/Section/AdminOrderStatusGridSection.xml | 2 +- .../Sales/Test/Mftf/Section/AdminOrdersGridSection.xml | 10 +++++----- .../Sales/Test/Mftf/Section/OrdersGridSection.xml | 4 ++-- .../AdminMassOrdersCancelCompleteAndClosedTest.xml | 3 --- .../AdminMassOrdersCancelProcessingAndClosedTest.xml | 3 --- .../Mftf/Test/AdminMassOrdersHoldOnCompleteTest.xml | 3 --- .../AdminMassOrdersHoldOnPendingAndProcessingTest.xml | 3 --- .../Test/AdminMassOrdersReleasePendingOrderTest.xml | 3 --- .../AdminMassOrdersUpdateCancelPendingOrderTest.xml | 3 --- .../Mftf/Test/AdminOrdersReleaseInUnholdStatusTest.xml | 3 --- ...signCustomOrderStatusNotVisibleOnStorefrontTest.xml | 3 --- .../AssignCustomOrderStatusVisibleOnStorefrontTest.xml | 3 --- .../MoveLastOrderedSimpleProductOnOrderPageTest.xml | 3 --- .../Mftf/Section/AdminShipmentMainActionsSection.xml | 2 +- .../Ui/Test/Mftf/Section/AdminDataGridTableSection.xml | 2 +- 30 files changed, 35 insertions(+), 57 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductActionSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductActionSection.xml index 98dc5e764fd77..5ee754904b702 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductActionSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductActionSection.xml @@ -9,7 +9,7 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="StorefrontProductActionSection"> <element name="quantity" type="input" selector="#qty"/> - <element name="addToCart" type="button" selector="#product-addtocart-button"/> + <element name="addToCart" type="button" selector="#product-addtocart-button" timeout="60"/> <element name="addToCartButtonTitleIsAdding" type="text" selector="//button/span[text()='Adding...']"/> <element name="addToCartButtonTitleIsAdded" type="text" selector="//button/span[text()='Added']"/> <element name="addToCartButtonTitleIsAddToCart" type="text" selector="//button/span[text()='Add to Cart']"/> diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartSummarySection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartSummarySection.xml index 59c5054245ad6..e6637bec76583 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartSummarySection.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartSummarySection.xml @@ -20,7 +20,7 @@ <element name="totalAmount" type="text" selector="//*[@id='cart-totals']//tr[@class='grand totals']//td//span[@class='price' and contains(text(), '{{amount}}')]" parameterized="true"/> <element name="proceedToCheckout" type="button" selector=".action.primary.checkout span" timeout="30"/> <element name="discountAmount" type="text" selector="td[data-th='Discount']"/> - <element name="shippingHeading" type="button" selector="#block-shipping-heading"/> + <element name="shippingHeading" type="button" selector="#block-shipping-heading" timeout="60"/> <element name="postcode" type="input" selector="input[name='postcode']" timeout="10"/> <element name="stateProvince" type="select" selector="select[name='region_id']" timeout="10"/> <element name="stateProvinceInput" type="input" selector="input[name='region']"/> diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingMethodsSection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingMethodsSection.xml index 5b546e6d37c0a..2f49e4f422a6e 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingMethodsSection.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingMethodsSection.xml @@ -14,7 +14,7 @@ <element name="shippingMethodRow" type="text" selector=".form.methods-shipping table tbody tr"/> <element name="checkShippingMethodByName" type="radio" selector="//div[@id='checkout-shipping-method-load']//td[contains(., '{{var1}}')]/..//input" parameterized="true"/> <element name="shippingMethodFlatRate" type="radio" selector="#checkout-shipping-method-load input[value='flatrate_flatrate']"/> - <element name="shippingMethodFreeShipping" type="radio" selector="#checkout-shipping-method-load input[value='freeshipping_freeshipping']"/> + <element name="shippingMethodFreeShipping" type="radio" selector="#checkout-shipping-method-load input[value='freeshipping_freeshipping']" timeout="60"/> <element name="shippingMethodRowByName" type="text" selector="//div[@id='checkout-shipping-method-load']//td[contains(., '{{var1}}')]/.." parameterized="true"/> <element name="shipHereButton" type="button" selector="//div/following-sibling::div/button[contains(@class, 'action-select-shipping-item')]"/> <element name="shippingMethodLoader" type="button" selector="//div[contains(@class, 'checkout-shipping-method')]/following-sibling::div[contains(@class, 'loading-mask')]"/> diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/StorefrontMiniCartSection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/StorefrontMiniCartSection.xml index 81ac53b318109..621cd1d3a7bae 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Section/StorefrontMiniCartSection.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Section/StorefrontMiniCartSection.xml @@ -16,7 +16,7 @@ <element name="productName" type="text" selector=".product-item-name"/> <element name="productOptionsDetailsByName" type="button" selector="//header//ol[@id='mini-cart']//div[@class='product-item-details'][.//a[contains(text(), '{{var1}}')]]//span[.='See Details']" parameterized="true"/> <element name="productOptionByNameAndAttribute" type="text" selector="//header//ol[@id='mini-cart']//div[@class='product-item-details'][.//a[contains(text(), '{{var1}}')]]//dt[@class='label' and .='{{var2}}']/following-sibling::dd[@class='values']//span" parameterized="true"/> - <element name="showCart" type="button" selector="a.showcart"/> + <element name="showCart" type="button" selector="a.showcart" timeout="60"/> <element name="quantity" type="button" selector="span.counter-number"/> <element name="miniCartOpened" type="button" selector="a.showcart.active"/> <element name="goToCheckout" type="button" selector="#top-cart-btn-checkout" timeout="30"/> diff --git a/app/code/Magento/Config/Test/Mftf/Section/GeneralSection.xml b/app/code/Magento/Config/Test/Mftf/Section/GeneralSection.xml index d007c860782aa..9bce5065317f8 100644 --- a/app/code/Magento/Config/Test/Mftf/Section/GeneralSection.xml +++ b/app/code/Magento/Config/Test/Mftf/Section/GeneralSection.xml @@ -9,11 +9,11 @@ <sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="ContentManagementSection"> - <element name="WYSIWYGOptions" type="button" selector="#cms_wysiwyg-head"/> + <element name="WYSIWYGOptions" type="button" selector="#cms_wysiwyg-head" timeout="60"/> <element name="CheckIfTabExpand" type="button" selector="#cms_wysiwyg-head:not(.open)"/> <element name="EnableSystemValue" type="button" selector="#cms_wysiwyg_enabled_inherit"/> <element name="EnableWYSIWYG" type="button" selector="#cms_wysiwyg_enabled"/> - <element name="SwitcherSystemValue" type="button" selector="#cms_wysiwyg_editor_inherit"/> + <element name="SwitcherSystemValue" type="button" selector="#cms_wysiwyg_editor_inherit" timeout="60"/> <element name="Switcher" type="button" selector="#cms_wysiwyg_editor" /> <element name="StaticURL" type="button" selector="#cms_wysiwyg_use_static_urls_in_catalog" /> <element name="Save" type="button" selector="#save" timeout="30"/> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontCustomerLogoutActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontCustomerLogoutActionGroup.xml index de97bb47de796..295346875e3cc 100644 --- a/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontCustomerLogoutActionGroup.xml +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontCustomerLogoutActionGroup.xml @@ -10,6 +10,7 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="StorefrontCustomerLogoutActionGroup"> <amOnPage url="{{StorefrontCustomerLogoutPage.url}}" stepKey="storefrontSignOut"/> + <waitForPageLoad stepKey="waitForSignOut"/> </actionGroup> <actionGroup name="StorefrontSignOutActionGroup"> diff --git a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerSidebarSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerSidebarSection.xml index 407c6480e9dde..c6b9aa0372edc 100644 --- a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerSidebarSection.xml +++ b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerSidebarSection.xml @@ -9,7 +9,7 @@ <sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="StorefrontCustomerSidebarSection"> - <element name="sidebarTab" type="text" selector="//div[@id='block-collapsible-nav']//a[text()='{{tabName}}']" parameterized="true"/> + <element name="sidebarTab" type="text" selector="//div[@id='block-collapsible-nav']//a[text()='{{tabName}}']" parameterized="true" timeout="60"/> <element name="sidebarCurrentTab" type="text" selector="//div[@id='block-collapsible-nav']//*[contains(text(), '{{var}}')]" parameterized="true"/> </section> </sections> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/VerifyDisabledCustomerGroupFieldTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/VerifyDisabledCustomerGroupFieldTest.xml index 648c30b1ca0bb..9979f61681864 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/VerifyDisabledCustomerGroupFieldTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/VerifyDisabledCustomerGroupFieldTest.xml @@ -27,6 +27,7 @@ <!-- 2. Navigate to Customers > Customer Groups --> <amOnPage url="{{AdminCustomerGroupPage.url}}" stepKey="amOnCustomerGroupPage" /> <waitForPageLoad stepKey="waitForCustomerGroupsPageLoad" /> + <conditionalClick selector="{{AdminDataGridHeaderSection.clearFilters}}" dependentSelector="{{AdminDataGridHeaderSection.clearFilters}}" visible="true" stepKey="clearFilters"/> <!-- 3. Select system Customer Group specified in data set from grid --> <click selector="{{AdminCustomerGroupMainSection.editButtonByCustomerGroupCode(NotLoggedInCustomerGroup.code)}}" stepKey="clickOnEditCustomerGroup" /> diff --git a/app/code/Magento/Newsletter/Test/Mftf/Section/NewsletterTemplateSection.xml b/app/code/Magento/Newsletter/Test/Mftf/Section/NewsletterTemplateSection.xml index d0dfd21cc2e1f..3525a976cd1c7 100644 --- a/app/code/Magento/Newsletter/Test/Mftf/Section/NewsletterTemplateSection.xml +++ b/app/code/Magento/Newsletter/Test/Mftf/Section/NewsletterTemplateSection.xml @@ -12,14 +12,14 @@ <element name="templateSubject" type="input" selector="#subject"/> <element name="senderName" type="input" selector="#sender_name"/> <element name="senderEmail" type="input" selector="#sender_email"/> - <element name="save" type="button" selector="button[data-role='template-save']"/> + <element name="save" type="button" selector="button[data-role='template-save']" timeout="60"/> <element name="searchButton" type="button" selector=".admin__filter-actions button[title=Search]"/> <element name="searchInput" type="input" selector="input[name=code]"/> </section> <section name="NewsletterWYSIWYGSection"> <element name="TextArea" type="text" selector="#text" /> <element name="TinyMCE4" type="text" selector=".mce-branding-powered-by" /> - <element name="ShowHideBtn" type="button" selector="#toggletext"/> + <element name="ShowHideBtn" type="button" selector="#toggletext" timeout="60"/> <element name="InsertWidgetBtn" type="button" selector=".action-add-widget"/> <element name="InsertWidgetIcon" type="button" selector="div[aria-label='Insert Widget']"/> <element name="InsertVariableIcon" type="button" selector="div[aria-label='Insert Variable']"/> @@ -51,6 +51,6 @@ <element name="InsertImage" type="button" selector=".mce-i-image" /> <element name="InsertTable" type="button" selector=".mce-i-table" /> <element name="SpecialCharacter" type="button" selector=".mce-i-charmap" /> - <element name="Preview" type="text" selector="//td[contains(text(),'{{var1}}')]//following-sibling::td/select//option[contains(text(), 'Preview')]" parameterized="true"/> + <element name="Preview" type="text" selector="//td[contains(text(),'{{var1}}')]//following-sibling::td/select//option[contains(text(), 'Preview')]" parameterized="true" timeout="60"/> </section> </sections> diff --git a/app/code/Magento/Newsletter/Test/Mftf/Test/VerifyTinyMCEv4IsNativeWYSIWYGOnNewsletterTest.xml b/app/code/Magento/Newsletter/Test/Mftf/Test/VerifyTinyMCEv4IsNativeWYSIWYGOnNewsletterTest.xml index 3c19a3fa99d3c..c4636fea3fb91 100644 --- a/app/code/Magento/Newsletter/Test/Mftf/Test/VerifyTinyMCEv4IsNativeWYSIWYGOnNewsletterTest.xml +++ b/app/code/Magento/Newsletter/Test/Mftf/Test/VerifyTinyMCEv4IsNativeWYSIWYGOnNewsletterTest.xml @@ -29,6 +29,7 @@ <fillField selector="{{BasicFieldNewsletterSection.senderName}}" userInput="{{_defaultNewsletter.senderName}}" stepKey="fillSenderName" /> <fillField selector="{{BasicFieldNewsletterSection.senderEmail}}" userInput="{{_defaultNewsletter.senderEmail}}" stepKey="fillSenderEmail" /> <conditionalClick selector="#toggletext" dependentSelector=".mce-tinymce" visible="false" stepKey="clickBtnIfTinyMCEHidden"/> + <waitForPageLoad stepKey="waitForTinyMce"/> <actionGroup ref="VerifyTinyMCEActionGroup" stepKey="verifyTinyMCE4"/> <actionGroup ref="VerifyMagentoEntityActionGroup" stepKey="verifyMagentoEntities"/> <executeJS function="tinyMCE.get('text').setContent('Hello World From Newsletter Template!');" stepKey="executeJSFillContent"/> diff --git a/app/code/Magento/Reports/Test/Mftf/Section/OrderReportMainSection.xml b/app/code/Magento/Reports/Test/Mftf/Section/OrderReportMainSection.xml index 6b1dcbb110583..bc8ac46424040 100644 --- a/app/code/Magento/Reports/Test/Mftf/Section/OrderReportMainSection.xml +++ b/app/code/Magento/Reports/Test/Mftf/Section/OrderReportMainSection.xml @@ -9,8 +9,8 @@ <sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="OrderReportMainSection"> - <element name="showReport" type="button" selector="#filter_form_submit"/> - <element name="here" type="text" selector="//a[contains(text(), 'here')]"/> + <element name="showReport" type="button" selector="#filter_form_submit" timeout="60"/> + <element name="here" type="text" selector="//a[contains(text(), 'here')]" timeout="60"/> </section> <section name="OrderReportFilterSection"> diff --git a/app/code/Magento/Reports/Test/Mftf/Test/CancelOrdersInOrderSalesReportTest.xml b/app/code/Magento/Reports/Test/Mftf/Test/CancelOrdersInOrderSalesReportTest.xml index ee39eac1e3719..0412e945362e4 100644 --- a/app/code/Magento/Reports/Test/Mftf/Test/CancelOrdersInOrderSalesReportTest.xml +++ b/app/code/Magento/Reports/Test/Mftf/Test/CancelOrdersInOrderSalesReportTest.xml @@ -17,9 +17,6 @@ <severity value="MAJOR"/> <testCaseId value="MAGETWO-95960"/> <useCaseId value="MAGETWO-95823"/> - <skip> - <issueId value="MC-17274"/> - </skip> </annotations> <before> @@ -69,6 +66,7 @@ <!-- Generate Order report for statuses --> <amOnPage url="{{OrdersReportPage.url}}" stepKey="goToOrdersReportPage1"/> + <waitForPageLoad stepKey="waitForOrdersReportPageLoad1"/> <!-- Get date --> <generateDate stepKey="generateEndDate" date="+0 day" format="m/d/Y"/> <generateDate stepKey="generateStartDate" date="-1 day" format="m/d/Y"/> @@ -81,6 +79,7 @@ <grabTextFrom selector="{{GeneratedReportSection.ordersCount}}" stepKey="grabCanceledOrdersSpecified"/> <!-- Generate Order report --> <amOnPage url="{{OrdersReportPage.url}}" stepKey="goToOrdersReportPage2"/> + <waitForPageLoad stepKey="waitForOrdersReportPageLoad2"/> <!-- Get date --> <actionGroup ref="GenerateOrderReportActionGroup" stepKey="generateReportAfterCancelOrder"> <argument name="orderFromDate" value="$generateStartDate"/> diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOrderActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOrderActionGroup.xml index f7d24cda34142..bf04d88fcb818 100644 --- a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOrderActionGroup.xml +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOrderActionGroup.xml @@ -418,6 +418,7 @@ <click selector="{{OrdersGridSection.addProducts}}" stepKey="clickOnAddProducts"/> <waitForPageLoad stepKey="waitForProductsListForOrder"/> <click selector="{{AdminOrdersGridSection.productForOrder(product.sku)}}" stepKey="chooseTheProduct"/> + <waitForPageLoad stepKey="waitForClickProduct"/> <click selector="{{AdminOrderFormItemsSection.addSelected}}" stepKey="addSelectedProductToOrder"/> <waitForPageLoad stepKey="waitForProductAddedInOrder"/> <click selector="{{AdminInvoicePaymentShippingSection.getShippingMethodAndRates}}" stepKey="openShippingMethod"/> @@ -425,6 +426,7 @@ <click selector="{{AdminInvoicePaymentShippingSection.shippingMethod}}" stepKey="chooseShippingMethod"/> <waitForPageLoad stepKey="waitForShippingMethodsThickened"/> <click selector="{{OrdersGridSection.submitOrder}}" stepKey="submitOrder"/> + <waitForPageLoad stepKey="waitForSubmitOrder"/> <see stepKey="seeSuccessMessageForOrder" userInput="You created the order."/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOrderGridActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOrderGridActionGroup.xml index a116a23dc02cd..19bf96f50a536 100644 --- a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOrderGridActionGroup.xml +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOrderGridActionGroup.xml @@ -14,10 +14,14 @@ <argument name="orderId" type="string"/> </arguments> <amOnPage url="{{AdminOrdersPage.url}}" stepKey="navigateToOrderGridPage"/> + <waitForPageLoad stepKey="waitForOrdersPage"/> <conditionalClick selector="{{AdminOrdersGridSection.clearFilters}}" dependentSelector="{{AdminOrdersGridSection.clearFilters}}" visible="true" stepKey="clearExistingOrderFilters"/> + <waitForPageLoad stepKey="waitForClearFilters"/> <click selector="{{AdminOrdersGridSection.filters}}" stepKey="openOrderGridFilters"/> + <waitForPageLoad stepKey="waitForClickFilters"/> <fillField selector="{{AdminOrdersGridSection.idFilter}}" userInput="{{orderId}}" stepKey="fillOrderIdFilter"/> <click selector="{{AdminOrdersGridSection.applyFilters}}" stepKey="clickOrderApplyFilters"/> + <waitForPageLoad stepKey="waitForApplyFilters"/> </actionGroup> <!--Filter order grid by the billing name field--> diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminInvoicePaymentShippingSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminInvoicePaymentShippingSection.xml index 8d7c64733972e..fda886a839802 100644 --- a/app/code/Magento/Sales/Test/Mftf/Section/AdminInvoicePaymentShippingSection.xml +++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminInvoicePaymentShippingSection.xml @@ -15,7 +15,7 @@ <element name="ShippingMethod" type="text" selector=".order-shipping-address .shipping-description-title"/> <element name="ShippingPrice" type="text" selector=".order-shipping-address .shipping-description-content .price"/> <element name="CreateShipment" type="checkbox" selector=".order-shipping-address input[name='invoice[do_shipment]']"/> - <element name="getShippingMethodAndRates" type="button" selector="//span[text()='Get shipping methods and rates']"/> - <element name="shippingMethod" type="button" selector="//label[contains(text(), 'Fixed')]"/> + <element name="getShippingMethodAndRates" type="button" selector="//span[text()='Get shipping methods and rates']" timeout="60"/> + <element name="shippingMethod" type="button" selector="//label[contains(text(), 'Fixed')]" timeout="60"/> </section> </sections> \ No newline at end of file diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderStatusGridSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderStatusGridSection.xml index 815016ab1beb6..4234d76e21ba9 100644 --- a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderStatusGridSection.xml +++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderStatusGridSection.xml @@ -19,6 +19,6 @@ <element name="search" type="button" selector="[data-action='grid-filter-apply']" timeout="30"/> <element name="gridCell" type="text" selector="//tr['{{row}}']//td[count(//div[contains(concat(' ',normalize-space(@class),' '),' admin__data-grid-wrap ')]//tr//th[contains(., '{{cellName}}')]/preceding-sibling::th) +1 ]" parameterized="true" timeout="30"/> <element name="stateCodeAndTitleDataColumn" type="input" selector="[data-role=row] [data-column=state]"/> - <element name="unassign" type="text" selector="[data-role=row] [data-column=unassign]"/> + <element name="unassign" type="text" selector="[data-role=row] [data-column=unassign]" timeout="60"/> </section> </sections> diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrdersGridSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrdersGridSection.xml index 7373ff0715336..ace64cdaa1032 100644 --- a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrdersGridSection.xml +++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrdersGridSection.xml @@ -16,7 +16,7 @@ <element name="submitSearch22" type="button" selector=".//*[@class="admin__data-grid-filters-wrap"]/parent::*/div[@class="data-grid-search-control-wrap"]/button"/> <element name="filters" type="button" selector="button[data-action='grid-filter-expand']" timeout="30"/> <element name="idFilter" type="input" selector=".admin__data-grid-filters input[name='increment_id']"/> - <element name="selectStatus" type="select" selector="select[name='status']"/> + <element name="selectStatus" type="select" selector="select[name='status']" timeout="60"/> <element name="billToNameFilter" type="input" selector=".admin__data-grid-filters input[name='billing_name']"/> <element name="enabledFilters" type="block" selector=".admin__data-grid-header .admin__data-grid-filters-current._show"/> <element name="clearFilters" type="button" selector=".admin__data-grid-header [data-action='grid-filter-reset']" timeout="30"/> @@ -30,14 +30,14 @@ <element name="viewBookmark" type="button" selector="//div[contains(@class, 'admin__data-grid-action-bookmarks')]/ul/li/div/a[text() = '{{label}}']" parameterized="true" timeout="30"/> <element name="columnsDropdown" type="button" selector="div.admin__data-grid-action-columns button" timeout="30"/> <element name="viewColumnCheckbox" type="checkbox" selector="//div[contains(@class,'admin__data-grid-action-columns')]//div[contains(@class, 'admin__field-option')]//label[text() = '{{column}}']/preceding-sibling::input" parameterized="true"/> - <element name="customerInOrdersSection" type="button" selector="(//td[contains(text(),'{{customer}}')])[1]" parameterized="true"/> - <element name="productForOrder" type="button" selector="//td[contains(text(),'{{var}}')]" parameterized="true"/> + <element name="customerInOrdersSection" type="button" selector="(//td[contains(text(),'{{customer}}')])[1]" parameterized="true" timeout="60"/> + <element name="productForOrder" type="button" selector="//td[contains(text(),'{{var}}')]" parameterized="true" timeout="60"/> <element name="selectActions" type="button" selector=".action-select-wrap > .action-select" timeout="30"/> <element name="dropdownActionItem" type="button" selector="(//div[contains(@class, 'action-menu-items')]//span[text()='{{action}}'])[1]" timeout="30" parameterized="true"/> <element name="checkOrder" type="input" selector="//td[count(//div[@data-role='grid-wrapper'])]//input"/> - <element name="orderActions" type="button" selector="//div[contains(concat(' ',normalize-space(@class),' '),' row-gutter ')]//button[@title='Select Items']"/> + <element name="orderActions" type="button" selector="//div[contains(concat(' ',normalize-space(@class),' '),' row-gutter ')]//button[@title='Select Items']" timeout="60"/> <element name="changeOrderStatus" type="button" selector="//div[contains(concat(' ',normalize-space(@class),' '),' row-gutter ')]//span[text()='{{status}}']" parameterized="true" timeout="30"/> <element name="viewLink" type="text" selector="//td/div[contains(.,'{{orderID}}')]/../..//a[@class='action-menu-item']" parameterized="true"/> - <element name="selectOrderID" type="checkbox" selector="//td/div[text()='{{orderId}}']/../preceding-sibling::td//input" parameterized="true"/> + <element name="selectOrderID" type="checkbox" selector="//td/div[text()='{{orderId}}']/../preceding-sibling::td//input" parameterized="true" timeout="60"/> </section> </sections> diff --git a/app/code/Magento/Sales/Test/Mftf/Section/OrdersGridSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/OrdersGridSection.xml index b716047a39008..a6b856f9f814f 100644 --- a/app/code/Magento/Sales/Test/Mftf/Section/OrdersGridSection.xml +++ b/app/code/Magento/Sales/Test/Mftf/Section/OrdersGridSection.xml @@ -18,7 +18,7 @@ <element name="createNewOrder" type="button" selector="button[title='Create New Order'"/> <element name="website" type="radio" selector="//label[contains(text(), '{{arg}}')]" parameterized="true"/> - <element name="addProducts" type="button" selector="#add_products"/> + <element name="addProducts" type="button" selector="#add_products" timeout="60"/> <element name="selectProduct" type="checkbox" selector="//td[contains(text(), '{{arg}}')]/following-sibling::td[contains(@class, 'col-select col-in_products')]/label/input" parameterized="true"/> <element name="setQuantity" type="checkbox" selector="//td[contains(text(), '{{arg}}')]/following-sibling::td[contains(@class, 'col-qty')]/input" parameterized="true"/> <element name="addProductsToOrder" type="button" selector="//span[text()='Add Selected Product(s) to Order']"/> @@ -29,6 +29,6 @@ <element name="productPrice" type="text" selector="//span[text()='{{arg}}']/parent::td/following-sibling::td[@class='col-price col-row-subtotal']/span" parameterized="true"/> <element name="removeItems" type="select" selector="//span[text()='{{arg}}']/parent::td/following-sibling::td/select[@class='admin__control-select']" parameterized="true"/> <element name="applyCoupon" type="input" selector="#coupons:code"/> - <element name="submitOrder" type="button" selector="#submit_order_top_button"/> + <element name="submitOrder" type="button" selector="#submit_order_top_button" timeout="60"/> </section> </sections> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminMassOrdersCancelCompleteAndClosedTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminMassOrdersCancelCompleteAndClosedTest.xml index e5f43818c1524..ec624a80f1613 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminMassOrdersCancelCompleteAndClosedTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminMassOrdersCancelCompleteAndClosedTest.xml @@ -17,9 +17,6 @@ <testCaseId value="MC-16183"/> <group value="sales"/> <group value="mtf_migrated"/> - <skip> - <issueId value="MC-17274"/> - </skip> </annotations> <before> <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminMassOrdersCancelProcessingAndClosedTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminMassOrdersCancelProcessingAndClosedTest.xml index b9e7106676e2c..5e524bcf6e05c 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminMassOrdersCancelProcessingAndClosedTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminMassOrdersCancelProcessingAndClosedTest.xml @@ -17,9 +17,6 @@ <testCaseId value="MC-16184"/> <group value="sales"/> <group value="mtf_migrated"/> - <skip> - <issueId value="MC-17274"/> - </skip> </annotations> <before> <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminMassOrdersHoldOnCompleteTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminMassOrdersHoldOnCompleteTest.xml index 913361c77cdd2..179e1aa35a4e9 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminMassOrdersHoldOnCompleteTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminMassOrdersHoldOnCompleteTest.xml @@ -17,9 +17,6 @@ <testCaseId value="MC-16186"/> <group value="sales"/> <group value="mtf_migrated"/> - <skip> - <issueId value="MC-17274"/> - </skip> </annotations> <before> <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminMassOrdersHoldOnPendingAndProcessingTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminMassOrdersHoldOnPendingAndProcessingTest.xml index 8e3b3b5361437..ec0ec8ca222da 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminMassOrdersHoldOnPendingAndProcessingTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminMassOrdersHoldOnPendingAndProcessingTest.xml @@ -17,9 +17,6 @@ <testCaseId value="MC-16185"/> <group value="sales"/> <group value="mtf_migrated"/> - <skip> - <issueId value="MC-17274"/> - </skip> </annotations> <before> <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminMassOrdersReleasePendingOrderTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminMassOrdersReleasePendingOrderTest.xml index e7a936b088f4f..6c97c4add6313 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminMassOrdersReleasePendingOrderTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminMassOrdersReleasePendingOrderTest.xml @@ -17,9 +17,6 @@ <testCaseId value="MC-16188"/> <group value="sales"/> <group value="mtf_migrated"/> - <skip> - <issueId value="MC-17274"/> - </skip> </annotations> <before> <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminMassOrdersUpdateCancelPendingOrderTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminMassOrdersUpdateCancelPendingOrderTest.xml index f2995f07d137d..d7c9664b8bce2 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminMassOrdersUpdateCancelPendingOrderTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminMassOrdersUpdateCancelPendingOrderTest.xml @@ -17,9 +17,6 @@ <testCaseId value="MC-16182"/> <group value="sales"/> <group value="mtf_migrated"/> - <skip> - <issueId value="MC-17274"/> - </skip> </annotations> <before> <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminOrdersReleaseInUnholdStatusTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminOrdersReleaseInUnholdStatusTest.xml index 30f66cb9fd312..009f86256a910 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminOrdersReleaseInUnholdStatusTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminOrdersReleaseInUnholdStatusTest.xml @@ -17,9 +17,6 @@ <testCaseId value="MC-16187"/> <group value="sales"/> <group value="mtf_migrated"/> - <skip> - <issueId value="MC-17274"/> - </skip> </annotations> <before> <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AssignCustomOrderStatusNotVisibleOnStorefrontTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AssignCustomOrderStatusNotVisibleOnStorefrontTest.xml index d66078e245aee..c292afe65cdf3 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AssignCustomOrderStatusNotVisibleOnStorefrontTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AssignCustomOrderStatusNotVisibleOnStorefrontTest.xml @@ -18,9 +18,6 @@ <testCaseId value="MC-16053"/> <group value="sales"/> <group value="mtf_migrated"/> - <skip> - <issueId value="MC-17274"/> - </skip> </annotations> <before> <!-- Create customer --> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AssignCustomOrderStatusVisibleOnStorefrontTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AssignCustomOrderStatusVisibleOnStorefrontTest.xml index 102fec494d125..d81baf7755eab 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AssignCustomOrderStatusVisibleOnStorefrontTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AssignCustomOrderStatusVisibleOnStorefrontTest.xml @@ -18,9 +18,6 @@ <testCaseId value="MC-16054"/> <group value="sales"/> <group value="mtf_migrated"/> - <skip> - <issueId value="MC-17274"/> - </skip> </annotations> <remove keyForRemoval="seeEmptyMessage"/> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/MoveLastOrderedSimpleProductOnOrderPageTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/MoveLastOrderedSimpleProductOnOrderPageTest.xml index 66f0a14ea2712..f13a934276e35 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/MoveLastOrderedSimpleProductOnOrderPageTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/MoveLastOrderedSimpleProductOnOrderPageTest.xml @@ -18,9 +18,6 @@ <testCaseId value="MC-16154"/> <group value="sales"/> <group value="mtf_migrated"/> - <skip> - <issueId value="MC-17274"/> - </skip> </annotations> <before> <!-- Login as admin --> diff --git a/app/code/Magento/Shipping/Test/Mftf/Section/AdminShipmentMainActionsSection.xml b/app/code/Magento/Shipping/Test/Mftf/Section/AdminShipmentMainActionsSection.xml index 9f66b269b96ac..828d006478e24 100644 --- a/app/code/Magento/Shipping/Test/Mftf/Section/AdminShipmentMainActionsSection.xml +++ b/app/code/Magento/Shipping/Test/Mftf/Section/AdminShipmentMainActionsSection.xml @@ -9,6 +9,6 @@ <sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="AdminShipmentMainActionsSection"> - <element name="submitShipment" type="button" selector="button.action-default.save.submit-button"/> + <element name="submitShipment" type="button" selector="button.action-default.save.submit-button" timeout="60"/> </section> </sections> \ No newline at end of file diff --git a/app/code/Magento/Ui/Test/Mftf/Section/AdminDataGridTableSection.xml b/app/code/Magento/Ui/Test/Mftf/Section/AdminDataGridTableSection.xml index 8a61bf76cc5ea..8ca875a808ef5 100644 --- a/app/code/Magento/Ui/Test/Mftf/Section/AdminDataGridTableSection.xml +++ b/app/code/Magento/Ui/Test/Mftf/Section/AdminDataGridTableSection.xml @@ -9,7 +9,7 @@ <sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="AdminDataGridTableSection"> - <element name="firstRow" type="button" selector="tr.data-row:nth-of-type(1)"/> + <element name="firstRow" type="button" selector="tr.data-row:nth-of-type(1)" timeout="60"/> <element name="columnHeader" type="button" selector="//div[@data-role='grid-wrapper']//table[contains(@class, 'data-grid')]/thead/tr/th[contains(@class, 'data-grid-th')]/span[text() = '{{label}}']" parameterized="true" timeout="30"/> <element name="column" type="text" selector="//tr//td[count(//div[@data-role='grid-wrapper']//tr//th[contains(., '{{col}}')]/preceding-sibling::th) +1 ]" parameterized="true"/> <element name="rowCheckbox" type="checkbox" selector="table.data-grid tbody > tr:nth-of-type({{row}}) td.data-grid-checkbox-cell input" parameterized="true"/> From d90b1b9bc8416ad80f9fe1a2012b6623a6c2d713 Mon Sep 17 00:00:00 2001 From: Lena Orobei <oorobei@magento.com> Date: Thu, 27 Jun 2019 16:40:48 -0500 Subject: [PATCH 564/773] magento/graphql-ce#736: Configurable products with "out of stock" return as product: null - added tests --- .../Model/Variant/Collection.php | 57 +++-------- .../ConfigurableProductStockStatusTest.php | 99 +++++++++++++++++++ 2 files changed, 113 insertions(+), 43 deletions(-) create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/ConfigurableProductStockStatusTest.php diff --git a/app/code/Magento/ConfigurableProductGraphQl/Model/Variant/Collection.php b/app/code/Magento/ConfigurableProductGraphQl/Model/Variant/Collection.php index 11c22e9ff5e6f..d517c9aa29bd3 100644 --- a/app/code/Magento/ConfigurableProductGraphQl/Model/Variant/Collection.php +++ b/app/code/Magento/ConfigurableProductGraphQl/Model/Variant/Collection.php @@ -9,14 +9,11 @@ use Magento\Catalog\Api\Data\ProductInterface; use Magento\Catalog\Model\Product; -use Magento\Catalog\Model\ProductFactory; use Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable\Product\Collection as ChildCollection; use Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable\Product\CollectionFactory; use Magento\Framework\EntityManager\MetadataPool; use Magento\Framework\Api\SearchCriteriaBuilder; -use Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\Product as DataProvider; -use Magento\CatalogInventory\Helper\Stock; -use Magento\CatalogInventory\Api\StockConfigurationInterface; +use Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\Product\CollectionProcessorInterface; /** * Collection for fetching configurable child product data. @@ -28,31 +25,11 @@ class Collection */ private $childCollectionFactory; - /** - * @var ProductFactory - */ - private $productFactory; - /** * @var SearchCriteriaBuilder */ private $searchCriteriaBuilder; - /** - * @var DataProvider - */ - private $productDataProvider; - - /** - * @var Stock - */ - private $stockHelper; - - /** - * @var StockConfigurationInterface - */ - private $stockConfig; - /** * @var MetadataPool */ @@ -73,31 +50,27 @@ class Collection */ private $attributeCodes = []; + /** + * @var CollectionProcessorInterface + */ + private $collectionProcessor; + /** * @param CollectionFactory $childCollectionFactory - * @param ProductFactory $productFactory * @param SearchCriteriaBuilder $searchCriteriaBuilder - * @param DataProvider $productDataProvider * @param MetadataPool $metadataPool - * @param Stock $stockHelper - * @param StockConfigurationInterface $stockConfig + * @param CollectionProcessorInterface $collectionProcessor */ public function __construct( CollectionFactory $childCollectionFactory, - ProductFactory $productFactory, SearchCriteriaBuilder $searchCriteriaBuilder, - DataProvider $productDataProvider, MetadataPool $metadataPool, - Stock $stockHelper, - StockConfigurationInterface $stockConfig + CollectionProcessorInterface $collectionProcessor ) { $this->childCollectionFactory = $childCollectionFactory; - $this->productFactory = $productFactory; $this->searchCriteriaBuilder = $searchCriteriaBuilder; - $this->productDataProvider = $productDataProvider; $this->metadataPool = $metadataPool; - $this->stockHelper = $stockHelper; - $this->stockConfig = $stockConfig; + $this->collectionProcessor = $collectionProcessor; } /** @@ -161,18 +134,16 @@ private function fetch() : array return $this->childrenMap; } - $showOutOfStock = $this->stockConfig->isShowOutOfStock(); - foreach ($this->parentProducts as $product) { $attributeData = $this->getAttributesCodes($product); /** @var ChildCollection $childCollection */ $childCollection = $this->childCollectionFactory->create(); $childCollection->setProductFilter($product); - $childCollection->addAttributeToSelect($attributeData); - - if (!$showOutOfStock) { - $this->stockHelper->addInStockFilterToCollection($childCollection); - } + $this->collectionProcessor->process( + $childCollection, + $this->searchCriteriaBuilder->create(), + $attributeData + ); /** @var Product $childProduct */ foreach ($childCollection->getItems() as $childProduct) { diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/ConfigurableProductStockStatusTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/ConfigurableProductStockStatusTest.php new file mode 100644 index 0000000000000..b33b96daf839e --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/ConfigurableProductStockStatusTest.php @@ -0,0 +1,99 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQl\ConfigurableProduct; + +use Magento\TestFramework\TestCase\GraphQlAbstract; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\CatalogInventory\Api\StockRegistryInterface; + +/** + * Checks if stock status correctly displays for configurable variants. + */ +class ConfigurableProductStockStatusTest extends GraphQlAbstract +{ + /** + * @var StockRegistryInterface + */ + private $stockRegistry; + + /** + * @inheritdoc + */ + protected function setUp() + { + $this->stockRegistry = Bootstrap::getObjectManager()->create(StockRegistryInterface::class); + } + + /** + * @magentoApiDataFixture Magento/Framework/Search/_files/product_configurable.php + * @magentoConfigFixture default_store cataloginventory/options/show_out_of_stock 1 + */ + public function testConfigurableProductShowOutOfStock() + { + $parentSku = 'configurable'; + $childSkuOutOfStock = 'simple_1010'; + $stockItem = $this->stockRegistry->getStockItemBySku($childSkuOutOfStock); + $stockItem->setQty(0); + $this->stockRegistry->updateStockItemBySku($childSkuOutOfStock, $stockItem); + $query = $this->getQuery($parentSku); + $response = $this->graphQlQuery($query); + + foreach ($response['products']['items'][0]['variants'] as $children) { + if ($children['product']['sku'] === $childSkuOutOfStock) { + $this->assertEquals('OUT_OF_STOCK', $children['product']['stock_status']); + } else { + $this->assertEquals('IN_STOCK', $children['product']['stock_status']); + } + } + } + + /** + * @magentoApiDataFixture Magento/Framework/Search/_files/product_configurable.php + * @magentoConfigFixture default_store cataloginventory/options/show_out_of_stock 0 + */ + public function testConfigurableProductDoNotShowOutOfStock() + { + $parentSku = 'configurable'; + $childSkuOutOfStock = 'simple_1010'; + $stockItem = $this->stockRegistry->getStockItemBySku($childSkuOutOfStock); + $stockItem->setQty(0); + $this->stockRegistry->updateStockItemBySku($childSkuOutOfStock, $stockItem); + $query = $this->getQuery($parentSku); + $response = $this->graphQlQuery($query); + $this->assertEquals( + [['product' => ['sku' => 'simple_1020', 'stock_status' => 'IN_STOCK']]], + $response['products']['items'][0]['variants'] + ); + } + + /** + * @param string $sku + * @return string + */ + private function getQuery(string $sku) + { + return <<<QUERY + { + products(filter: {sku: {eq: "{$sku}"}}) + { + items { + sku + ... on ConfigurableProduct { + variants { + product { + sku + stock_status + } + } + } + } + } + } +QUERY; + } +} From d4a859ddd085b235668e0f3d210c29e28af4fc9b Mon Sep 17 00:00:00 2001 From: Patrick McLain <pat@pmclain.com> Date: Thu, 27 Jun 2019 18:41:39 -0400 Subject: [PATCH 565/773] Fix fixture path --- .../AuthorizenetAcceptjs/Customer/SetPaymentMethodTest.php | 2 +- .../GraphQl/AuthorizenetAcceptjs/Guest/SetPaymentMethodTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/AuthorizenetAcceptjs/Customer/SetPaymentMethodTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/AuthorizenetAcceptjs/Customer/SetPaymentMethodTest.php index c33360a38bdce..385598e49462b 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/AuthorizenetAcceptjs/Customer/SetPaymentMethodTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/AuthorizenetAcceptjs/Customer/SetPaymentMethodTest.php @@ -70,7 +70,7 @@ protected function setUp() * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_billing_address.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_flatrate_shipping_method.php - * @magentoApiDataFixture Magento/Graphql/AuthorizenetAcceptjs/_files/enable_authorizenetacceptjs.php + * @magentoApiDataFixture Magento/GraphQl/AuthorizenetAcceptjs/_files/enable_authorizenetacceptjs.php * @param string $nonce * @param string $descriptor * @param bool $expectSuccess diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/AuthorizenetAcceptjs/Guest/SetPaymentMethodTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/AuthorizenetAcceptjs/Guest/SetPaymentMethodTest.php index d388980160332..de5ba83d1e14b 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/AuthorizenetAcceptjs/Guest/SetPaymentMethodTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/AuthorizenetAcceptjs/Guest/SetPaymentMethodTest.php @@ -70,7 +70,7 @@ protected function setUp() * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_billing_address.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_flatrate_shipping_method.php - * @magentoApiDataFixture Magento/Graphql/AuthorizenetAcceptjs/_files/enable_authorizenetacceptjs.php + * @magentoApiDataFixture Magento/GraphQl/AuthorizenetAcceptjs/_files/enable_authorizenetacceptjs.php * @param string $nonce * @param string $descriptor * @param bool $expectSuccess From 326cf5e8ef9d787b697ab34541d5e0511536a368 Mon Sep 17 00:00:00 2001 From: Krissy Hiserote <khiserote@magento.com> Date: Thu, 27 Jun 2019 19:21:47 -0500 Subject: [PATCH 566/773] MC-15776: Merge release branch into 2.3-develop - fix failing MFTF test --- .../StorefrontClearAllCompareProductsTest.xml | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontClearAllCompareProductsTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontClearAllCompareProductsTest.xml index 2b88657c6ca2b..d7372b07de14b 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontClearAllCompareProductsTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontClearAllCompareProductsTest.xml @@ -38,6 +38,30 @@ <createData entity="ApiConfigurableProduct" stepKey="createConfigProduct1"> <requiredEntity createDataKey="createSimpleCategory1"/> </createData> + <createData entity="productAttributeWithTwoOptions" stepKey="createConfigProductAttribute"/> + <createData entity="productAttributeOption1" stepKey="createConfigProductAttributeOption"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + </createData> + <createData entity="AddToDefaultSet" stepKey="createConfigAddToAttributeSet"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + </createData> + <getData entity="ProductAttributeOptionGetter" index="1" stepKey="getConfigAttributeOption"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + </getData> + <createData entity="ApiSimpleOne" stepKey="createConfigChildProduct"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + <requiredEntity createDataKey="getConfigAttributeOption"/> + <requiredEntity createDataKey="createSimpleCategory1"/> + </createData> + <createData entity="ConfigurableProductTwoOptions" stepKey="createConfigProductOption"> + <requiredEntity createDataKey="createConfigProduct1"/> + <requiredEntity createDataKey="createConfigProductAttribute"/> + <requiredEntity createDataKey="getConfigAttributeOption"/> + </createData> + <createData entity="ConfigurableProductAddChild" stepKey="createConfigProductAddChild"> + <requiredEntity createDataKey="createConfigProduct1"/> + <requiredEntity createDataKey="createConfigChildProduct"/> + </createData> <!-- Create Virtual Product --> <createData entity="VirtualProduct" stepKey="createVirtualProduct1"> @@ -77,6 +101,9 @@ <requiredEntity createDataKey="createDownloadableProduct1"/> </createData> + <magentoCLI command="indexer:reindex" stepKey="reindex"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> + <!-- Login --> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin1"/> </before> From 68240af314ea28e00e2d951a0ea2a402c197f214 Mon Sep 17 00:00:00 2001 From: UlyanaKiklevich <ulya.kik@mail.ru> Date: Fri, 28 Jun 2019 08:42:26 +0300 Subject: [PATCH 567/773] Update CartTotalRepository.php Update devdocs for CartTotalRepository. --- app/code/Magento/Quote/Model/Cart/CartTotalRepository.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/code/Magento/Quote/Model/Cart/CartTotalRepository.php b/app/code/Magento/Quote/Model/Cart/CartTotalRepository.php index 60e5ad9f4caff..2c487cdea63fa 100644 --- a/app/code/Magento/Quote/Model/Cart/CartTotalRepository.php +++ b/app/code/Magento/Quote/Model/Cart/CartTotalRepository.php @@ -8,7 +8,6 @@ use Magento\Quote\Api; use Magento\Quote\Api\CartRepositoryInterface; use Magento\Quote\Api\CartTotalRepositoryInterface; -use Magento\Catalog\Helper\Product\ConfigurationPool; use Magento\Framework\Api\DataObjectHelper; use Magento\Framework\Api\ExtensibleDataInterface; use Magento\Quote\Model\Cart\Totals\ItemConverter; @@ -40,7 +39,7 @@ class CartTotalRepository implements CartTotalRepositoryInterface private $dataObjectHelper; /** - * @var ConfigurationPool + * @var ItemConverter */ private $itemConverter; From 334fefe7ac14a23c26eb3b228af9eff588cefcc8 Mon Sep 17 00:00:00 2001 From: Vikalp Saxena <vikalpsaxena@cedcommerce.com> Date: Fri, 28 Jun 2019 11:16:14 +0530 Subject: [PATCH 568/773] Removed usage of escapeNotVerified. Removed usage of escapeNotVerified. --- .../view/frontend/templates/checkout/addresses.phtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Multishipping/view/frontend/templates/checkout/addresses.phtml b/app/code/Magento/Multishipping/view/frontend/templates/checkout/addresses.phtml index a57224e471dca..17afd7b2fc8ba 100644 --- a/app/code/Magento/Multishipping/view/frontend/templates/checkout/addresses.phtml +++ b/app/code/Magento/Multishipping/view/frontend/templates/checkout/addresses.phtml @@ -18,7 +18,7 @@ data-mage-init='{ "multiShipping":{}, "cartUpdate": { - "validationURL": "<?= /* @escapeNotVerified */ $block->getUrl('multishipping/checkout/checkItems') ?>", + "validationURL": "<?= $block->escapeUrl($block->getUrl('multishipping/checkout/checkItems')) ?>", "eventName": "updateMulticartItemQty" }}' action="<?= $block->escapeUrl($block->getPostActionUrl()) ?>" From 259534d7f7fe143a7f5846a931657205fee24003 Mon Sep 17 00:00:00 2001 From: yuriichayka <yurii_chayka@outlook.com> Date: Fri, 28 Jun 2019 10:12:43 +0300 Subject: [PATCH 569/773] magento/magento2#22814: Product stock alert - unsubscribe not working Setting StoreId for Unsubscribe controller --- .../Controller/Unsubscribe/Stock.php | 96 ++++++++++++++----- 1 file changed, 71 insertions(+), 25 deletions(-) diff --git a/app/code/Magento/ProductAlert/Controller/Unsubscribe/Stock.php b/app/code/Magento/ProductAlert/Controller/Unsubscribe/Stock.php index 7a6aeb40eb5b7..cd2f3134c84c6 100644 --- a/app/code/Magento/ProductAlert/Controller/Unsubscribe/Stock.php +++ b/app/code/Magento/ProductAlert/Controller/Unsubscribe/Stock.php @@ -4,43 +4,72 @@ * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\ProductAlert\Controller\Unsubscribe; -use Magento\ProductAlert\Controller\Unsubscribe as UnsubscribeController; -use Magento\Framework\App\Action\Context; -use Magento\Customer\Model\Session as CustomerSession; use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Customer\Model\Session as CustomerSession; +use Magento\Framework\App\Action\Context; +use Magento\Framework\App\Action\HttpPostActionInterface; +use Magento\Framework\App\ObjectManager; +use Magento\Framework\Controller\Result\Redirect; use Magento\Framework\Controller\ResultFactory; use Magento\Framework\Exception\NoSuchEntityException; +use Magento\ProductAlert\Controller\Unsubscribe as UnsubscribeController; +use Magento\ProductAlert\Model\StockFactory; +use Magento\Store\Model\StoreManagerInterface; +use Magento\Catalog\Api\Data\ProductInterface; -class Stock extends UnsubscribeController +/** + * Unsubscribing from 'back in stock alert'. + */ +class Stock extends UnsubscribeController implements HttpPostActionInterface { /** - * @var \Magento\Catalog\Api\ProductRepositoryInterface + * @var ProductRepositoryInterface */ protected $productRepository; /** - * @param \Magento\Framework\App\Action\Context $context - * @param \Magento\Customer\Model\Session $customerSession - * @param \Magento\Catalog\Api\ProductRepositoryInterface $productRepository + * @var StoreManagerInterface + */ + private $storeManager; + + /** + * @var StockFactory|null + */ + private $stockFactory; + + /** + * @param Context $context + * @param CustomerSession $customerSession + * @param ProductRepositoryInterface $productRepository + * @param StoreManagerInterface|null $storeManager + * @param StockFactory|null $stockFactory */ public function __construct( Context $context, CustomerSession $customerSession, - ProductRepositoryInterface $productRepository + ProductRepositoryInterface $productRepository, + StoreManagerInterface $storeManager = null, + StockFactory $stockFactory = null ) { $this->productRepository = $productRepository; + $this->storeManager = $storeManager ?? ObjectManager::getInstance()->get(StoreManagerInterface::class); + $this->stockFactory = $stockFactory ?? ObjectManager::getInstance()->get(StockFactory::class); parent::__construct($context, $customerSession); } /** - * @return \Magento\Framework\Controller\Result\Redirect + * Unsubscribing from 'back in stock alert'. + * + * @return Redirect */ public function execute() { $productId = (int)$this->getRequest()->getParam('product'); - /** @var \Magento\Framework\Controller\Result\Redirect $resultRedirect */ + /** @var Redirect $resultRedirect */ $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT); if (!$productId) { $resultRedirect->setPath('/'); @@ -48,20 +77,20 @@ public function execute() } try { - $product = $this->productRepository->getById($productId); - if (!$product->isVisibleInCatalog()) { - throw new NoSuchEntityException(); - } - - $model = $this->_objectManager->create(\Magento\ProductAlert\Model\Stock::class) - ->setCustomerId($this->customerSession->getCustomerId()) - ->setProductId($product->getId()) - ->setWebsiteId( - $this->_objectManager->get(\Magento\Store\Model\StoreManagerInterface::class) - ->getStore() - ->getWebsiteId() - ) - ->loadByParam(); + $product = $this->retrieveProduct($productId); + $model = $this->stockFactory->create() + ->setCustomerId($this->customerSession->getCustomerId()) + ->setProductId($product->getId()) + ->setWebsiteId( + $this->storeManager + ->getStore() + ->getWebsiteId() + )->setStoreId( + $this->storeManager + ->getStore() + ->getId() + ) + ->loadByParam(); if ($model->getId()) { $model->delete(); } @@ -79,4 +108,21 @@ public function execute() $resultRedirect->setUrl($product->getProductUrl()); return $resultRedirect; } + + /** + * Retrieving product + * + * @param int $productId + * + * @return ProductInterface + * @throws NoSuchEntityException + */ + private function retrieveProduct(int $productId): ProductInterface + { + $product = $this->productRepository->getById($productId); + if (!$product->isVisibleInCatalog()) { + throw new NoSuchEntityException(); + } + return $product; + } } From e2b58cd92e8229dd1b95c6a8412ebd1f16dc4f6f Mon Sep 17 00:00:00 2001 From: yuriichayka <yurii_chayka@outlook.com> Date: Fri, 28 Jun 2019 11:31:38 +0300 Subject: [PATCH 570/773] magento/magento2#22814: Product stock alert - unsubscribe not working Small formatting changes --- .../Controller/Unsubscribe/Stock.php | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/app/code/Magento/ProductAlert/Controller/Unsubscribe/Stock.php b/app/code/Magento/ProductAlert/Controller/Unsubscribe/Stock.php index cd2f3134c84c6..1b729f988e4a5 100644 --- a/app/code/Magento/ProductAlert/Controller/Unsubscribe/Stock.php +++ b/app/code/Magento/ProductAlert/Controller/Unsubscribe/Stock.php @@ -32,7 +32,7 @@ class Stock extends UnsubscribeController implements HttpPostActionInterface protected $productRepository; /** - * @var StoreManagerInterface + * @var StoreManagerInterface|null */ private $storeManager; @@ -79,18 +79,18 @@ public function execute() try { $product = $this->retrieveProduct($productId); $model = $this->stockFactory->create() - ->setCustomerId($this->customerSession->getCustomerId()) - ->setProductId($product->getId()) - ->setWebsiteId( - $this->storeManager - ->getStore() - ->getWebsiteId() - )->setStoreId( - $this->storeManager - ->getStore() - ->getId() - ) - ->loadByParam(); + ->setCustomerId($this->customerSession->getCustomerId()) + ->setProductId($product->getId()) + ->setWebsiteId( + $this->storeManager + ->getStore() + ->getWebsiteId() + )->setStoreId( + $this->storeManager + ->getStore() + ->getId() + ) + ->loadByParam(); if ($model->getId()) { $model->delete(); } From ab2f3de4534dd63a55436503e383b2c30553ec55 Mon Sep 17 00:00:00 2001 From: Tobias Westfeld <tobias.westfeld@eshaker.de> Date: Fri, 28 Jun 2019 12:02:10 +0200 Subject: [PATCH 571/773] #758: Cart applied_taxes of empty cart can be null --- app/code/Magento/QuoteGraphQl/Model/Resolver/CartPrices.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/CartPrices.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/CartPrices.php index 48711ec38c4f8..22b59b060450c 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/CartPrices.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/CartPrices.php @@ -73,7 +73,7 @@ private function getAppliedTaxes(Total $total, string $currency): array $appliedTaxesData = []; $appliedTaxes = $total->getAppliedTaxes(); - if (count($appliedTaxes) === 0) { + if ($appliedTaxes === null || count($appliedTaxes) === 0) { return $appliedTaxesData; } From 1e1b9f4dec1ae15f2f556f8e00f9f1c2b4c660f3 Mon Sep 17 00:00:00 2001 From: Krissy Hiserote <khiserote@magento.com> Date: Fri, 28 Jun 2019 08:24:19 -0500 Subject: [PATCH 572/773] MC-15776: Merge release branch into 2.3-develop - fix web-api failures --- .../Model/Resolver/UpdateCartItems.php | 37 +------------------ .../Quote/Customer/UpdateCartItemsTest.php | 2 +- .../Quote/Guest/UpdateCartItemsTest.php | 2 +- 3 files changed, 3 insertions(+), 38 deletions(-) diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/UpdateCartItems.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/UpdateCartItems.php index fd3c6bac9b5df..db6a43513cc30 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/UpdateCartItems.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/UpdateCartItems.php @@ -110,45 +110,10 @@ private function processCartItems(Quote $cart, array $items): void } $quantity = (float)$item['quantity']; - $cartItem = $cart->getItemById($itemId); - if ($cartItem === false) { - throw new GraphQlNoSuchEntityException( - __('Could not find cart item with id: %1.', $item['cart_item_id']) - ); - } - if ($quantity <= 0.0) { $this->cartItemRepository->deleteById((int)$cart->getId(), $itemId); } else { - $cartItem->setQty($quantity); - $this->validateCartItem($cartItem); - $this->cartItemRepository->save($cartItem); - } - } - } - - /** - * Validate cart item - * - * @param Item $cartItem - * @return void - * @throws GraphQlInputException - */ - private function validateCartItem(Item $cartItem): void - { - if ($cartItem->getHasError()) { - $errors = []; - foreach ($cartItem->getMessage(false) as $message) { - $errors[] = $message; - } - - if (!empty($errors)) { - throw new GraphQlInputException( - __( - 'Could not update the product with SKU %sku: %message', - ['sku' => $cartItem->getSku(), 'message' => __(implode("\n", $errors))] - ) - ); + $this->updateCartItem->execute($cart, $itemId, $quantity, $customizableOptions); } } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/UpdateCartItemsTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/UpdateCartItemsTest.php index bc88bd1ddb438..48ea4ab7a15e3 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/UpdateCartItemsTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/UpdateCartItemsTest.php @@ -285,7 +285,7 @@ public function dataProviderUpdateWithMissedRequiredParameters(): array ], 'missed_cart_item_qty' => [ 'cart_items: [{ cart_item_id: 1 }]', - 'Field CartItemUpdateInput.quantity of required type Float! was not provided.' + 'Required parameter "quantity" for "cart_items" is missing.' ], ]; } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/UpdateCartItemsTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/UpdateCartItemsTest.php index 1e1fb0a176992..988ead7d86df3 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/UpdateCartItemsTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/UpdateCartItemsTest.php @@ -236,7 +236,7 @@ public function dataProviderUpdateWithMissedRequiredParameters(): array ], 'missed_cart_item_qty' => [ 'cart_items: [{ cart_item_id: 1 }]', - 'Field CartItemUpdateInput.quantity of required type Float! was not provided.' + 'Required parameter "quantity" for "cart_items" is missing.' ], ]; } From b3a9bcfdecaa0db9356a143843c7940279093129 Mon Sep 17 00:00:00 2001 From: Lena Orobei <oorobei@magento.com> Date: Fri, 28 Jun 2019 10:30:13 -0500 Subject: [PATCH 573/773] magento/graphql-ce#736: Configurable products with "out of stock" return as product: null - marked tests incomplete due to the bug with `@magentoConfigFixture` --- .../ConfigurableProductStockStatusTest.php | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/ConfigurableProductStockStatusTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/ConfigurableProductStockStatusTest.php index b33b96daf839e..2d95c8a44fb02 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/ConfigurableProductStockStatusTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/ConfigurableProductStockStatusTest.php @@ -35,6 +35,7 @@ protected function setUp() */ public function testConfigurableProductShowOutOfStock() { + $this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/167'); $parentSku = 'configurable'; $childSkuOutOfStock = 'simple_1010'; $stockItem = $this->stockRegistry->getStockItemBySku($childSkuOutOfStock); @@ -42,14 +43,9 @@ public function testConfigurableProductShowOutOfStock() $this->stockRegistry->updateStockItemBySku($childSkuOutOfStock, $stockItem); $query = $this->getQuery($parentSku); $response = $this->graphQlQuery($query); - - foreach ($response['products']['items'][0]['variants'] as $children) { - if ($children['product']['sku'] === $childSkuOutOfStock) { - $this->assertEquals('OUT_OF_STOCK', $children['product']['stock_status']); - } else { - $this->assertEquals('IN_STOCK', $children['product']['stock_status']); - } - } + $this->assertArraySubset([ + ['product' => ['sku' => $childSkuOutOfStock, 'stock_status' => 'OUT_OF_STOCK']]], + $response['products']['items'][0]['variants']); } /** @@ -58,6 +54,7 @@ public function testConfigurableProductShowOutOfStock() */ public function testConfigurableProductDoNotShowOutOfStock() { + $this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/167'); $parentSku = 'configurable'; $childSkuOutOfStock = 'simple_1010'; $stockItem = $this->stockRegistry->getStockItemBySku($childSkuOutOfStock); From 23ecf93961fe766e0e952f359932cfaaf882d2ea Mon Sep 17 00:00:00 2001 From: Ani Tumanyan <ani_tumanyan@epam.com> Date: Fri, 28 Jun 2019 20:00:23 +0400 Subject: [PATCH 574/773] MC-17387: Fatal error appears when adding bundle product to Cart from Wish list page - Added automated test script --- ...undleProductToCartFromWishListPageTest.xml | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 app/code/Magento/Catalog/Test/Mftf/Test/AdminAddBundleProductToCartFromWishListPageTest.xml diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminAddBundleProductToCartFromWishListPageTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminAddBundleProductToCartFromWishListPageTest.xml new file mode 100644 index 0000000000000..76a2c4c739e09 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminAddBundleProductToCartFromWishListPageTest.xml @@ -0,0 +1,83 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AdminAddBundleProductToCartFromWishListPageTest"> + <annotations> + <features value="Catalog"/> + <title value="Add bundle product to Cart from Wish list page"/> + <description value="Add bundle product to Cart from Wish list page"/> + <severity value="MAJOR"/> + <testCaseId value="MC-17782"/> + <useCaseId value="MC-17387"/> + <group value="catalog"/> + </annotations> + <before> + <!-- Login as Admin --> + <comment userInput="Login as Admin" stepKey="commentLoginAsAdmin"/> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + <!-- Create customer on Storefront and bundle product --> + <comment userInput="Create customer on Storefront and bundle product" stepKey="commentCreateData"/> + <createData entity="SimpleSubCategory" stepKey="createCategory"/> + <createData entity="CustomerEntityOne" stepKey="createCustomerViaTheStorefront"/> + <createData entity="_defaultProduct" stepKey="createSimpleProduct1"> + <requiredEntity createDataKey="createCategory"/> + </createData> + <createData entity="_defaultProduct" stepKey="createSimpleProduct2"> + <requiredEntity createDataKey="createCategory"/> + </createData> + <createData entity="ApiBundleProductPriceViewRange" stepKey="createProduct"> + <requiredEntity createDataKey="createCategory"/> + </createData> + <!-- Create Attribute --> + <comment userInput="Create Attribute" stepKey="commentCreateAttribute"/> + <createData entity="DropDownBundleOption" stepKey="bundleOption"> + <requiredEntity createDataKey="createProduct"/> + </createData> + <createData entity="ApiBundleLink" stepKey="createBundleLink1"> + <requiredEntity createDataKey="createProduct"/> + <requiredEntity createDataKey="bundleOption"/> + <requiredEntity createDataKey="createSimpleProduct1"/> + </createData> + <createData entity="ApiBundleLink" stepKey="createBundleLink2"> + <requiredEntity createDataKey="createProduct"/> + <requiredEntity createDataKey="bundleOption"/> + <requiredEntity createDataKey="createSimpleProduct2"/> + </createData> + <amOnPage url="{{AdminProductEditPage.url($$createProduct.id$$)}}" stepKey="goToProductEditPage"/> + <actionGroup ref="saveProductForm" stepKey="saveProduct"/> + </before> + <after> + <!-- Delete created data --> + <comment userInput="Delete created data" stepKey="commentDeleteCreatedData"/> + <deleteData createDataKey="createCustomerViaTheStorefront" stepKey="deleteCustomerViaTheStorefront"/> + <deleteData createDataKey="createProduct" stepKey="deleteProduct" /> + <!-- Log out --> + <comment userInput="Log out" stepKey="commentLogOut"/> + <actionGroup ref="logout" stepKey="logout"/> + </after> + <!-- Login to the Storefront as created customer --> + <comment userInput="Login to the Storefront as created customer" stepKey="commentLoginAsCustomer"/> + <actionGroup ref="LoginToStorefrontActionGroup" stepKey="loginAsCustomer"> + <argument name="Customer" value="$$createCustomerViaTheStorefront$$"/> + </actionGroup> + <!-- Add product to Wish List --> + <comment userInput="Add product to Wish List" stepKey="commentAddProductToWishList"/> + <amOnPage url="{{StorefrontProductPage.url($$createProduct.custom_attributes[url_key]$$)}}" stepKey="amOnBundleProductPage"/> + <waitForPageLoad stepKey="waitForProductPage"/> + <actionGroup ref="StorefrontCustomerAddProductToWishlistActionGroup" stepKey="addToWishlistProduct"> + <argument name="productVar" value="$$createProduct$$"/> + </actionGroup> + <moveMouseOver selector="{{StorefrontCategoryProductSection.ProductInfoByName($$createProduct.name$$)}}" stepKey="moveMouseOverProduct" /> + <click selector="{{StorefrontCategoryProductSection.ProductAddToCartByName($$createProduct.name$$)}}" stepKey="clickAddToCart" /> + <waitForPageLoad stepKey="waitForProductBundlePage"/> + <!-- See error message --> + <comment userInput="See error message" stepKey="commentSeeErrorMessage"/> + <see userInput=" Please specify product option(s)." stepKey="seeErrorMessage"/> + </test> +</tests> From 661874a7ddc9e8efda797bfc7419f5fa064ed869 Mon Sep 17 00:00:00 2001 From: "al.kravchuk" <al.kravchuk@ism-ukraine.com> Date: Fri, 28 Jun 2019 19:06:30 +0300 Subject: [PATCH 575/773] magento/magento2#23386: Copy Service does not works properly for Entities which extends Data Object and implements ExtensibleDataInterface. Add unit tests coverage. --- .../DataObject/Test/Unit/CopyTest.php | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/lib/internal/Magento/Framework/DataObject/Test/Unit/CopyTest.php b/lib/internal/Magento/Framework/DataObject/Test/Unit/CopyTest.php index 1d27628448bb7..6e29f1a61a7a1 100644 --- a/lib/internal/Magento/Framework/DataObject/Test/Unit/CopyTest.php +++ b/lib/internal/Magento/Framework/DataObject/Test/Unit/CopyTest.php @@ -6,6 +6,8 @@ namespace Magento\Framework\DataObject\Test\Unit; +use Magento\Quote\Model\Quote\Address; + class CopyTest extends \PHPUnit\Framework\TestCase { /** @@ -300,4 +302,86 @@ public function testGetDataFromFieldsetWhenFieldDoesNotExists() $this->copy->getDataFromFieldset('fieldset', 'aspect', $this->sourceMock) ); } + + public function testGetExtensionAttributeForDataObjectChild() + { + $fields['code']['aspect'] = '*'; + $this->fieldsetConfigMock + ->expects($this->once()) + ->method('getFieldset') + ->with('fieldset', 'global') + ->will($this->returnValue($fields)); + + $sourceMock = $this->createPartialMock(Address::class, [ + 'getExtensionAttributes', 'getCode' + ]); + $targetMock = $this->createPartialMock( + Address::class, [ + 'getExtensionAttributes', + 'setCode', + 'setExtensionAttributes' + ]); + + $sourceMock + ->expects($this->any()) + ->method('getExtensionAttributes') + ->willReturnSelf(); + $sourceMock + ->expects($this->once()) + ->method('getCode') + ->willReturn('code'); + + $targetMock + ->expects($this->any()) + ->method('getExtensionAttributes') + ->willReturnSelf(); + $targetMock + ->expects($this->any()) + ->method('setExtensionAttributes') + ->willReturnSelf(); + $targetMock + ->expects($this->once()) + ->method('setCode') + ->with('code'); + + $this->eventManagerMock->expects($this->once())->method('dispatch'); + $result = $this->copy->copyFieldsetToTarget('fieldset', 'aspect', $sourceMock, $targetMock); + $this->assertEquals($result, $targetMock); + } + + public function testGetDataObjectFieldFromExtensbielEntity() + { + $fields['code']['aspect'] = '*'; + $this->fieldsetConfigMock + ->expects($this->once()) + ->method('getFieldset') + ->with('fieldset', 'global') + ->will($this->returnValue($fields)); + + $sourceMock = $this->createPartialMock(Address::class, [ + 'getExtensionAttributes' + ]); + $targetMock = $this->createPartialMock( + Address::class, [ + 'getExtensionAttributes' + ]); + + $sourceMock + ->expects($this->any()) + ->method('getExtensionAttributes') + ->willReturn(null); + $value = 'code'; + $sourceMock->setData('code', $value); + + $targetMock + ->expects($this->any()) + ->method('getExtensionAttributes') + ->willReturn(null); + + + $this->eventManagerMock->expects($this->once())->method('dispatch'); + $result = $this->copy->copyFieldsetToTarget('fieldset', 'aspect', $sourceMock, $targetMock); + $this->assertEquals($result, $targetMock); + $this->assertEquals($value, $result->getCode()); + } } From f69c8e844e65492543a5ac0710b3a0ea108a3109 Mon Sep 17 00:00:00 2001 From: Lena Orobei <oorobei@magento.com> Date: Fri, 28 Jun 2019 11:22:30 -0500 Subject: [PATCH 576/773] magento/graphql-ce#736: Configurable products with "out of stock" return as product: null - code style fixes --- .../ConfigurableProductStockStatusTest.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/ConfigurableProductStockStatusTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/ConfigurableProductStockStatusTest.php index 2d95c8a44fb02..2826d61022c78 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/ConfigurableProductStockStatusTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/ConfigurableProductStockStatusTest.php @@ -43,9 +43,10 @@ public function testConfigurableProductShowOutOfStock() $this->stockRegistry->updateStockItemBySku($childSkuOutOfStock, $stockItem); $query = $this->getQuery($parentSku); $response = $this->graphQlQuery($query); - $this->assertArraySubset([ - ['product' => ['sku' => $childSkuOutOfStock, 'stock_status' => 'OUT_OF_STOCK']]], - $response['products']['items'][0]['variants']); + $this->assertArraySubset( + [['product' => ['sku' => $childSkuOutOfStock, 'stock_status' => 'OUT_OF_STOCK']]], + $response['products']['items'][0]['variants'] + ); } /** From 62747f489f9399a6b0bdec0e01213634b9c50fb4 Mon Sep 17 00:00:00 2001 From: Krissy Hiserote <khiserote@magento.com> Date: Fri, 28 Jun 2019 11:51:15 -0500 Subject: [PATCH 577/773] MC-15776: Merge release branch into 2.3-develop - fix integration failures --- .../Model/ResourceModel/SynonymReader.php | 1 + .../Catalog/Model/ProductRepositoryTest.php | 2 +- .../Framework/DB/Helper/Mysql/Fulltext.php | 18 ++++++++++++++++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Search/Model/ResourceModel/SynonymReader.php b/app/code/Magento/Search/Model/ResourceModel/SynonymReader.php index 1ac1547eb8d0a..d589498cdaa3e 100644 --- a/app/code/Magento/Search/Model/ResourceModel/SynonymReader.php +++ b/app/code/Magento/Search/Model/ResourceModel/SynonymReader.php @@ -85,6 +85,7 @@ protected function _construct() */ private function queryByPhrase($phrase) { + $phrase = $this->fullTextSelect->removeSpecialCharacters($phrase); $matchQuery = $this->fullTextSelect->getMatchQuery( ['synonyms' => 'synonyms'], $this->escapePhrase($phrase), diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductRepositoryTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductRepositoryTest.php index 65dc2b88e0e0c..fa2a0e5cb34b7 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductRepositoryTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductRepositoryTest.php @@ -205,7 +205,7 @@ public function testUpdateProductSku() $this->productRepository->delete($updatedProduct); } - /* + /** * Test authorization when saving product's design settings. * * @magentoDataFixture Magento/Catalog/_files/product_simple.php diff --git a/lib/internal/Magento/Framework/DB/Helper/Mysql/Fulltext.php b/lib/internal/Magento/Framework/DB/Helper/Mysql/Fulltext.php index 5660098157ace..5c50faf71a854 100644 --- a/lib/internal/Magento/Framework/DB/Helper/Mysql/Fulltext.php +++ b/lib/internal/Magento/Framework/DB/Helper/Mysql/Fulltext.php @@ -14,6 +14,13 @@ */ class Fulltext { + /** + * Characters that have special meaning in fulltext match syntax + * + * @var string + */ + const SPECIAL_CHARACTERS = '-+<>*()~'; + /** * FULLTEXT search in MySQL search mode "natural language" */ @@ -99,4 +106,15 @@ public function match($select, $columns, $expression, $isCondition = true, $mode return $select; } + + /** + * Remove special characters from fulltext query expression + * + * @param string $expression + * @return string + */ + public function removeSpecialCharacters(string $expression): string + { + return str_replace(str_split(static::SPECIAL_CHARACTERS), '', $expression); + } } From 0e269791748eb8b06cc81ffef68bba086c31e699 Mon Sep 17 00:00:00 2001 From: Krissy Hiserote <khiserote@magento.com> Date: Fri, 28 Jun 2019 16:21:01 -0500 Subject: [PATCH 578/773] MC-15776: Merge release branch into 2.3-develop - fix merge conflict --- .../Controller/Adminhtml/Product/Delete.php | 52 ++++++++++++++++++- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Review/Controller/Adminhtml/Product/Delete.php b/app/code/Magento/Review/Controller/Adminhtml/Product/Delete.php index 955706e124c15..1b9c9eaa22be7 100644 --- a/app/code/Magento/Review/Controller/Adminhtml/Product/Delete.php +++ b/app/code/Magento/Review/Controller/Adminhtml/Product/Delete.php @@ -5,15 +5,21 @@ */ namespace Magento\Review\Controller\Adminhtml\Product; +use Magento\Framework\App\Action\HttpPostActionInterface; use Magento\Review\Controller\Adminhtml\Product as ProductController; use Magento\Framework\Controller\ResultFactory; -use Magento\Framework\App\Action\HttpPostActionInterface; +use Magento\Review\Model\Review; /** * Delete review action. */ class Delete extends ProductController implements HttpPostActionInterface { + /** + * @var Review + */ + private $model; + /** * Execute action. * @@ -25,7 +31,7 @@ public function execute() $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT); $reviewId = $this->getRequest()->getParam('id', false); try { - $this->reviewFactory->create()->setId($reviewId)->aggregate()->delete(); + $this->getModel()->aggregate()->delete(); $this->messageManager->addSuccess(__('The review has been deleted.')); if ($this->getRequest()->getParam('ret') == 'pending') { @@ -42,4 +48,46 @@ public function execute() return $resultRedirect->setPath('review/*/edit/', ['id' => $reviewId]); } + + /** + * @inheritdoc + */ + protected function _isAllowed() + { + if (parent::_isAllowed()) { + return true; + } + + if (!$this->_authorization->isAllowed('Magento_Review::pending')) { + return false; + } + + if ($this->getModel()->getStatusId() != Review::STATUS_PENDING) { + $this->messageManager->addErrorMessage( + __( + 'You don’t have permission to perform this operation.' + . ' The selected review must be in Pending Status.' + ) + ); + + return false; + } + + return true; + } + + /** + * Returns requested model. + * + * @return Review + */ + private function getModel(): Review + { + if ($this->model === null) { + $this->model = $this->reviewFactory->create() + ->load($this->getRequest()->getParam('id', false)); + } + + return $this->model; + } } From c8dba0b497d0ee94bbc44ef23f89c8a832ec75df Mon Sep 17 00:00:00 2001 From: Kajal Solanki <kajal.solanki@krishtechnolabs.com> Date: Sat, 29 Jun 2019 11:35:33 +0530 Subject: [PATCH 579/773] fix tooltip designing issue --- .../backend/web/css/source/forms/_fields.less | 14 -------------- lib/web/mage/validation.js | 4 ++++ 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/app/design/adminhtml/Magento/backend/web/css/source/forms/_fields.less b/app/design/adminhtml/Magento/backend/web/css/source/forms/_fields.less index e23f362863c1c..f47ddcece1c79 100644 --- a/app/design/adminhtml/Magento/backend/web/css/source/forms/_fields.less +++ b/app/design/adminhtml/Magento/backend/web/css/source/forms/_fields.less @@ -32,20 +32,6 @@ width: @field-size__l; } -.admin__field { - &.field { - &.field-basic_behavior.with-addon { - .admin__field-control { - position: relative; - .mage-error { - position: absolute; - width: 100%; - } - } - } - } -} - .abs-field-sizes { &.admin__field-x-small { > .admin__field-control { diff --git a/lib/web/mage/validation.js b/lib/web/mage/validation.js index dfa35473176b9..f695100b07c88 100644 --- a/lib/web/mage/validation.js +++ b/lib/web/mage/validation.js @@ -1868,6 +1868,10 @@ //logic for control with tooltip if (element.siblings('.tooltip').length) { errorPlacement = element.siblings('.tooltip'); + } + //logic for select with tooltip in after element + if (element.next().find('.tooltip').length) { + errorPlacement = element.next(); } errorPlacement.after(error); } From d0d5615a8d9325f827f7b493a316524b4d51ecb5 Mon Sep 17 00:00:00 2001 From: Kajal Solanki <kajal.solanki@krishtechnolabs.com> Date: Sat, 29 Jun 2019 12:30:30 +0530 Subject: [PATCH 580/773] update validation.js --- lib/web/mage/validation.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/web/mage/validation.js b/lib/web/mage/validation.js index f695100b07c88..725f2c0144bde 100644 --- a/lib/web/mage/validation.js +++ b/lib/web/mage/validation.js @@ -1869,7 +1869,7 @@ if (element.siblings('.tooltip').length) { errorPlacement = element.siblings('.tooltip'); } - //logic for select with tooltip in after element + //logic for select with tooltip in after element if (element.next().find('.tooltip').length) { errorPlacement = element.next(); } From 5a0c19d7616551e8171af9044b34918f7a876424 Mon Sep 17 00:00:00 2001 From: dipeshrangani <dipeshrangani23@gmail.com> Date: Sat, 29 Jun 2019 07:27:50 +0000 Subject: [PATCH 581/773] Fixed tooltip missing at store view lable in Cms page and Cms block --- .../Cms/view/adminhtml/ui_component/cms_block_form.xml | 4 ++++ .../Magento/Cms/view/adminhtml/ui_component/cms_page_form.xml | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/app/code/Magento/Cms/view/adminhtml/ui_component/cms_block_form.xml b/app/code/Magento/Cms/view/adminhtml/ui_component/cms_block_form.xml index 4b4a1a9bfe4db..9218676a7f880 100644 --- a/app/code/Magento/Cms/view/adminhtml/ui_component/cms_block_form.xml +++ b/app/code/Magento/Cms/view/adminhtml/ui_component/cms_block_form.xml @@ -123,6 +123,10 @@ <rule name="required-entry" xsi:type="boolean">true</rule> </validation> <dataType>int</dataType> + <tooltip> + <link>https://docs.magento.com/m2/ce/user_guide/configuration/scope.html</link> + <description>What is this?</description> + </tooltip> <label translate="true">Store View</label> <dataScope>store_id</dataScope> </settings> diff --git a/app/code/Magento/Cms/view/adminhtml/ui_component/cms_page_form.xml b/app/code/Magento/Cms/view/adminhtml/ui_component/cms_page_form.xml index 9fd8b3efb3ea8..dd58d17cbf577 100644 --- a/app/code/Magento/Cms/view/adminhtml/ui_component/cms_page_form.xml +++ b/app/code/Magento/Cms/view/adminhtml/ui_component/cms_page_form.xml @@ -207,6 +207,10 @@ <rule name="required-entry" xsi:type="boolean">true</rule> </validation> <dataType>int</dataType> + <tooltip> + <link>https://docs.magento.com/m2/ce/user_guide/configuration/scope.html</link> + <description>What is this?</description> + </tooltip> <label translate="true">Store View</label> <dataScope>store_id</dataScope> </settings> From 6735bc5d68117f139d4b7376fc8ffcf756df5211 Mon Sep 17 00:00:00 2001 From: Nirmal Raval <nirmal.raval@krishtechnolabs.com> Date: Sat, 29 Jun 2019 13:08:23 +0530 Subject: [PATCH 582/773] Added quantity validation on Shipping Multiple Address Page --- .../view/frontend/templates/checkout/addresses.phtml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Multishipping/view/frontend/templates/checkout/addresses.phtml b/app/code/Magento/Multishipping/view/frontend/templates/checkout/addresses.phtml index faf08f77c02f3..170304fb630ec 100644 --- a/app/code/Magento/Multishipping/view/frontend/templates/checkout/addresses.phtml +++ b/app/code/Magento/Multishipping/view/frontend/templates/checkout/addresses.phtml @@ -62,8 +62,9 @@ name="ship[<?= $block->escapeHtml($_index) ?>][<?= $block->escapeHtml($_item->getQuoteItemId()) ?>][qty]" value="<?= $block->escapeHtml($_item->getQty()) ?>" size="2" + min="0" class="input-text qty" - data-validate="{number: true}"/> + data-validate="{number: true,'validate-greater-than-zero':true}"/> </div> </div> </td> From 2d7d8a85d23f928b64e769038009b05fb6bcbf68 Mon Sep 17 00:00:00 2001 From: Kazim Noorani <kazim.noorani@krishtechnolabs.com> Date: Sat, 29 Jun 2019 16:52:13 +0530 Subject: [PATCH 583/773] Removed editor from phone and zipcode --- .../view/adminhtml/ui_component/customer_listing.xml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/app/code/Magento/Customer/view/adminhtml/ui_component/customer_listing.xml b/app/code/Magento/Customer/view/adminhtml/ui_component/customer_listing.xml index f845d407d401a..04371685b63d2 100644 --- a/app/code/Magento/Customer/view/adminhtml/ui_component/customer_listing.xml +++ b/app/code/Magento/Customer/view/adminhtml/ui_component/customer_listing.xml @@ -157,18 +157,12 @@ <column name="billing_telephone" sortOrder="60"> <settings> <filter>text</filter> - <editor> - <editorType>text</editorType> - </editor> <label translate="true">Phone</label> </settings> </column> <column name="billing_postcode" sortOrder="70"> <settings> <filter>text</filter> - <editor> - <editorType>text</editorType> - </editor> <label translate="true">ZIP</label> </settings> </column> From 538f69036bbb4f75e44061816996ccfcb4a0df73 Mon Sep 17 00:00:00 2001 From: Sarfaraz Bheda <sarfaraz.bheda@krishtechnolabs.com> Date: Sat, 29 Jun 2019 16:54:19 +0530 Subject: [PATCH 584/773] Resolved + character issue in custom widget --- .../Framework/Filter/Template/Tokenizer/AbstractTokenizer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/Filter/Template/Tokenizer/AbstractTokenizer.php b/lib/internal/Magento/Framework/Filter/Template/Tokenizer/AbstractTokenizer.php index 20fd7c2669c95..620fb16d2bca9 100644 --- a/lib/internal/Magento/Framework/Filter/Template/Tokenizer/AbstractTokenizer.php +++ b/lib/internal/Magento/Framework/Filter/Template/Tokenizer/AbstractTokenizer.php @@ -94,7 +94,7 @@ public function char() */ public function setString($value) { - $this->_string = urldecode($value); + $this->_string = $value; $this->reset(); } From 45e211f0ee5a3f7fb5606915d2b2eb326967d3b5 Mon Sep 17 00:00:00 2001 From: manish <manish.goswamij@gmail.com> Date: Sat, 29 Jun 2019 17:33:40 +0530 Subject: [PATCH 585/773] Fixed issue #23383 --- .../Ui/DataProvider/Product/Form/Modifier/Websites.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Websites.php b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Websites.php index 7d1d5d4d77d1b..b9d8fc56a91d9 100644 --- a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Websites.php +++ b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Websites.php @@ -175,11 +175,9 @@ protected function getFieldsForFieldset() $label = __('Websites'); $defaultWebsiteId = $this->websiteRepository->getDefault()->getId(); - $isOnlyOneWebsiteAvailable = count($websitesList) === 1; foreach ($websitesList as $website) { $isChecked = in_array($website['id'], $websiteIds) - || ($defaultWebsiteId == $website['id'] && $isNewProduct) - || $isOnlyOneWebsiteAvailable; + || ($defaultWebsiteId == $website['id'] && $isNewProduct); $children[$website['id']] = [ 'arguments' => [ 'data' => [ From bfa6074cab9b99a5daf26c1dbe4a6100f18d4855 Mon Sep 17 00:00:00 2001 From: Sarfaraz Bheda <sarfaraz.bheda@krishtechnolabs.com> Date: Sat, 29 Jun 2019 18:01:34 +0530 Subject: [PATCH 586/773] Replaced urldecode with rawurldecode that not converting + into space --- .../Framework/Filter/Template/Tokenizer/AbstractTokenizer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/Filter/Template/Tokenizer/AbstractTokenizer.php b/lib/internal/Magento/Framework/Filter/Template/Tokenizer/AbstractTokenizer.php index 620fb16d2bca9..b72305c6f5bdc 100644 --- a/lib/internal/Magento/Framework/Filter/Template/Tokenizer/AbstractTokenizer.php +++ b/lib/internal/Magento/Framework/Filter/Template/Tokenizer/AbstractTokenizer.php @@ -94,7 +94,7 @@ public function char() */ public function setString($value) { - $this->_string = $value; + $this->_string = rawurldecode($value); $this->reset(); } From 731a4fce46a9f33ea16af7404839740efdf23371 Mon Sep 17 00:00:00 2001 From: "al.kravchuk" <al.kravchuk@ism-ukraine.com> Date: Sat, 29 Jun 2019 21:05:40 +0300 Subject: [PATCH 587/773] magento/magento2#23386: Copy Service does not works properly for Entities which extends Data Object and implements ExtensibleDataInterface. Reformat code. --- .../DataObject/Test/Unit/CopyTest.php | 82 ++++++++++++------- 1 file changed, 54 insertions(+), 28 deletions(-) diff --git a/lib/internal/Magento/Framework/DataObject/Test/Unit/CopyTest.php b/lib/internal/Magento/Framework/DataObject/Test/Unit/CopyTest.php index 6e29f1a61a7a1..c6f86fd9d4cf9 100644 --- a/lib/internal/Magento/Framework/DataObject/Test/Unit/CopyTest.php +++ b/lib/internal/Magento/Framework/DataObject/Test/Unit/CopyTest.php @@ -8,6 +8,9 @@ use Magento\Quote\Model\Quote\Address; +/** + * Unit tests coverage for @see \Magento\Framework\DataObject\Copy + */ class CopyTest extends \PHPUnit\Framework\TestCase { /** @@ -91,7 +94,7 @@ public function testCopyFieldsetToTargetWhenFieldExists() $data = [ 'target' => new \Magento\Framework\DataObject([$this->targetMock]), 'source' => $this->sourceMock, - 'root' => 'global', + 'root' => 'global', ]; $this->eventManagerMock->expects($this->once())->method('dispatch')->with($eventName, $data); $this->assertEquals( @@ -124,7 +127,7 @@ public function testCopyFieldsetToTargetWhenTargetNotArray() $data = [ 'target' => $this->targetMock, 'source' => $this->sourceMock, - 'root' => 'global', + 'root' => 'global', ]; $this->eventManagerMock->expects($this->once())->method('dispatch')->with($eventName, $data); $this->assertEquals( @@ -160,7 +163,7 @@ public function testGetCopyFieldsetToTargetWhenTargetIsArray() $data = [ 'target' => new \Magento\Framework\DataObject($newTarget), 'source' => $this->sourceMock, - 'root' => 'global', + 'root' => 'global', ]; $this->eventManagerMock->expects($this->once())->method('dispatch')->with($eventName, $data); $this->assertEquals( @@ -178,14 +181,21 @@ public function testGetCopyFieldsetToTargetWhenTargetIsExtensibleDataInterface() ->with('fieldset', 'global') ->will($this->returnValue($fields)); - $sourceMock = $this->createPartialMock(\Magento\Framework\Api\ExtensibleDataInterface::class, [ - 'getExtensionAttributes', 'getCode' - ]); - $targetMock = $this->createPartialMock(\Magento\Framework\Api\ExtensibleDataInterface::class, [ + $sourceMock = $this->createPartialMock( + \Magento\Framework\Api\ExtensibleDataInterface::class, + [ + 'getExtensionAttributes', + 'getCode' + ] + ); + $targetMock = $this->createPartialMock( + \Magento\Framework\Api\ExtensibleDataInterface::class, + [ 'getExtensionAttributes', 'setCode', 'setExtensionAttributes' - ]); + ] + ); $sourceMock ->expects($this->any()) @@ -224,12 +234,18 @@ public function testGetCopyFieldsetToTargetWhenTargetIsAbstractSimpleObject() ->with('fieldset', 'global') ->will($this->returnValue($fields)); - $sourceMock = $this->createPartialMock(\Magento\Framework\Api\AbstractSimpleObject::class, [ + $sourceMock = $this->createPartialMock( + \Magento\Framework\Api\AbstractSimpleObject::class, + [ '__toArray' - ]); - $targetMock = $this->createPartialMock(\Magento\Framework\Api\AbstractSimpleObject::class, [ + ] + ); + $targetMock = $this->createPartialMock( + \Magento\Framework\Api\AbstractSimpleObject::class, + [ 'setData' - ]); + ] + ); $sourceMock ->expects($this->once()) @@ -312,15 +328,21 @@ public function testGetExtensionAttributeForDataObjectChild() ->with('fieldset', 'global') ->will($this->returnValue($fields)); - $sourceMock = $this->createPartialMock(Address::class, [ - 'getExtensionAttributes', 'getCode' - ]); + $sourceMock = $this->createPartialMock( + Address::class, + [ + 'getExtensionAttributes', + 'getCode' + ] + ); $targetMock = $this->createPartialMock( - Address::class, [ - 'getExtensionAttributes', - 'setCode', - 'setExtensionAttributes' - ]); + Address::class, + [ + 'getExtensionAttributes', + 'setCode', + 'setExtensionAttributes' + ] + ); $sourceMock ->expects($this->any()) @@ -349,7 +371,7 @@ public function testGetExtensionAttributeForDataObjectChild() $this->assertEquals($result, $targetMock); } - public function testGetDataObjectFieldFromExtensbielEntity() + public function testGetDataObjectFieldFromExtensibleEntity() { $fields['code']['aspect'] = '*'; $this->fieldsetConfigMock @@ -358,13 +380,18 @@ public function testGetDataObjectFieldFromExtensbielEntity() ->with('fieldset', 'global') ->will($this->returnValue($fields)); - $sourceMock = $this->createPartialMock(Address::class, [ - 'getExtensionAttributes' - ]); + $sourceMock = $this->createPartialMock( + Address::class, + [ + 'getExtensionAttributes' + ] + ); $targetMock = $this->createPartialMock( - Address::class, [ - 'getExtensionAttributes' - ]); + Address::class, + [ + 'getExtensionAttributes' + ] + ); $sourceMock ->expects($this->any()) @@ -378,7 +405,6 @@ public function testGetDataObjectFieldFromExtensbielEntity() ->method('getExtensionAttributes') ->willReturn(null); - $this->eventManagerMock->expects($this->once())->method('dispatch'); $result = $this->copy->copyFieldsetToTarget('fieldset', 'aspect', $sourceMock, $targetMock); $this->assertEquals($result, $targetMock); From 79f2f77de3b6cd2da7e5a1a7a4d79b3b90487db7 Mon Sep 17 00:00:00 2001 From: Yaroslav Rogoza <enarc@atwix.com> Date: Sun, 30 Jun 2019 11:31:45 +0200 Subject: [PATCH 588/773] Fixed URL retrieving --- app/code/Magento/UrlRewriteGraphQl/Model/Resolver/EntityUrl.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/EntityUrl.php b/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/EntityUrl.php index c5ccfae5bf129..0acece9271f7c 100644 --- a/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/EntityUrl.php +++ b/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/EntityUrl.php @@ -100,7 +100,7 @@ private function findCanonicalUrl(string $requestPath, int $storeId) : ?UrlRewri $urlRewrite = $this->findUrlFromTargetPath($requestPath, $storeId); } if ($urlRewrite && !$urlRewrite->getEntityId() && !$urlRewrite->getIsAutogenerated()) { - $urlRewrite = $this->findUrlFromTargetPath($urlRewrite->getTargetPath()); + $urlRewrite = $this->findUrlFromTargetPath($urlRewrite->getTargetPath(), $storeId); } return $urlRewrite; From 8780dcf3bf60fda6076cad6ef7bb16e955b88405 Mon Sep 17 00:00:00 2001 From: Yaroslav Rogoza <enarc@atwix.com> Date: Sun, 30 Jun 2019 11:37:44 +0200 Subject: [PATCH 589/773] Fixes for failing static tests --- .../CustomerGraphQl/Model/Resolver/CreateCustomer.php | 5 ++++- .../CustomerGraphQl/Model/Resolver/UpdateCustomer.php | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/CustomerGraphQl/Model/Resolver/CreateCustomer.php b/app/code/Magento/CustomerGraphQl/Model/Resolver/CreateCustomer.php index 6bd3cb7f52c85..1f730f2a5c7e6 100644 --- a/app/code/Magento/CustomerGraphQl/Model/Resolver/CreateCustomer.php +++ b/app/code/Magento/CustomerGraphQl/Model/Resolver/CreateCustomer.php @@ -55,7 +55,10 @@ public function resolve( throw new GraphQlInputException(__('"input" value should be specified')); } - $customer = $this->createCustomerAccount->execute($args['input'], $context->getExtensionAttributes()->getStore()); + $customer = $this->createCustomerAccount->execute( + $args['input'], + $context->getExtensionAttributes()->getStore() + ); $data = $this->extractCustomerData->execute($customer); return ['customer' => $data]; diff --git a/app/code/Magento/CustomerGraphQl/Model/Resolver/UpdateCustomer.php b/app/code/Magento/CustomerGraphQl/Model/Resolver/UpdateCustomer.php index b585844eb4484..509052c3a031c 100644 --- a/app/code/Magento/CustomerGraphQl/Model/Resolver/UpdateCustomer.php +++ b/app/code/Magento/CustomerGraphQl/Model/Resolver/UpdateCustomer.php @@ -72,7 +72,10 @@ public function resolve( } $customer = $this->getCustomer->execute($context); - $this->updateCustomerAccount->execute($customer, $args['input'], $context->getExtensionAttributes()->getStore()); + $this->updateCustomerAccount->execute( + $customer, + $args['input'], $context->getExtensionAttributes()->getStore() + ); $data = $this->extractCustomerData->execute($customer); return ['customer' => $data]; From 0c08e248b5f84f940b084649fc9bc5a187bdeecd Mon Sep 17 00:00:00 2001 From: Tobias Westfeld <tobias.westfeld@eshaker.de> Date: Sun, 30 Jun 2019 16:15:27 +0200 Subject: [PATCH 590/773] #758: apply suggestion and add test cases --- .../Model/Resolver/CartPrices.php | 2 +- .../GraphQl/Quote/Customer/CartTotalsTest.php | 27 +++++++++++++++++++ .../GraphQl/Quote/Guest/CartTotalsTest.php | 26 ++++++++++++++++++ 3 files changed, 54 insertions(+), 1 deletion(-) mode change 100644 => 100755 app/code/Magento/QuoteGraphQl/Model/Resolver/CartPrices.php mode change 100644 => 100755 dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CartTotalsTest.php mode change 100644 => 100755 dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CartTotalsTest.php diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/CartPrices.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/CartPrices.php old mode 100644 new mode 100755 index 22b59b060450c..6a57a7662af09 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/CartPrices.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/CartPrices.php @@ -73,7 +73,7 @@ private function getAppliedTaxes(Total $total, string $currency): array $appliedTaxesData = []; $appliedTaxes = $total->getAppliedTaxes(); - if ($appliedTaxes === null || count($appliedTaxes) === 0) { + if (empty($appliedTaxes)) { return $appliedTaxesData; } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CartTotalsTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CartTotalsTest.php old mode 100644 new mode 100755 index bb8acfce629ff..cb1406e77de23 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CartTotalsTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CartTotalsTest.php @@ -64,6 +64,33 @@ public function testGetCartTotalsWithTaxApplied() self::assertEquals('USD', $appliedTaxesResponse[0]['amount']['currency']); } + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Tax/_files/tax_rule_for_region_1.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/apply_tax_for_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_billing_address.php + */ + public function testGetCartTotalsWithEmptyCart() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId); + $response = $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + + self::assertArrayHasKey('prices', $response['cart']); + $pricesResponse = $response['cart']['prices']; + self::assertEquals(0, $pricesResponse['grand_total']['value']); + self::assertEquals(0, $pricesResponse['subtotal_including_tax']['value']); + self::assertEquals(0, $pricesResponse['subtotal_excluding_tax']['value']); + self::assertEquals(0, $pricesResponse['subtotal_with_discount_excluding_tax']['value']); + + $appliedTaxesResponse = $pricesResponse['applied_taxes']; + + self::assertCount(0, $appliedTaxesResponse); + } + /** * @magentoApiDataFixture Magento/Customer/_files/customer.php * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CartTotalsTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CartTotalsTest.php old mode 100644 new mode 100755 index 7eb09cf301bf4..3691a772a48cf --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CartTotalsTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CartTotalsTest.php @@ -59,6 +59,32 @@ public function testGetCartTotalsWithTaxApplied() self::assertEquals('USD', $appliedTaxesResponse[0]['amount']['currency']); } + /** + * @magentoApiDataFixture Magento/GraphQl/Tax/_files/tax_rule_for_region_1.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/apply_tax_for_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_billing_address.php + */ + public function testGetCartTotalsWithEmptyCart() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId); + $response = $this->graphQlQuery($query); + + self::assertArrayHasKey('prices', $response['cart']); + $pricesResponse = $response['cart']['prices']; + self::assertEquals(0, $pricesResponse['grand_total']['value']); + self::assertEquals(0, $pricesResponse['subtotal_including_tax']['value']); + self::assertEquals(0, $pricesResponse['subtotal_excluding_tax']['value']); + self::assertEquals(0, $pricesResponse['subtotal_with_discount_excluding_tax']['value']); + + $appliedTaxesResponse = $pricesResponse['applied_taxes']; + + self::assertCount(0, $appliedTaxesResponse); + } + /** * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php From 2f766b115832e0bcb995f0f7feebc201cfc4a5ef Mon Sep 17 00:00:00 2001 From: Tobias Westfeld <tobias.westfeld@eshaker.de> Date: Sun, 30 Jun 2019 16:47:38 +0200 Subject: [PATCH 591/773] #758: fix code style in tests --- .../GraphQl/Quote/Customer/CartTotalsTest.php | 52 +++++++++---------- .../GraphQl/Quote/Guest/CartTotalsTest.php | 50 +++++++++--------- 2 files changed, 51 insertions(+), 51 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CartTotalsTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CartTotalsTest.php index cb1406e77de23..f449f6db3c39b 100755 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CartTotalsTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CartTotalsTest.php @@ -64,32 +64,32 @@ public function testGetCartTotalsWithTaxApplied() self::assertEquals('USD', $appliedTaxesResponse[0]['amount']['currency']); } - /** - * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/GraphQl/Tax/_files/tax_rule_for_region_1.php - * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php - * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/apply_tax_for_simple_product.php - * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php - * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php - * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_billing_address.php - */ - public function testGetCartTotalsWithEmptyCart() - { - $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); - $query = $this->getQuery($maskedQuoteId); - $response = $this->graphQlQuery($query, [], '', $this->getHeaderMap()); - - self::assertArrayHasKey('prices', $response['cart']); - $pricesResponse = $response['cart']['prices']; - self::assertEquals(0, $pricesResponse['grand_total']['value']); - self::assertEquals(0, $pricesResponse['subtotal_including_tax']['value']); - self::assertEquals(0, $pricesResponse['subtotal_excluding_tax']['value']); - self::assertEquals(0, $pricesResponse['subtotal_with_discount_excluding_tax']['value']); - - $appliedTaxesResponse = $pricesResponse['applied_taxes']; - - self::assertCount(0, $appliedTaxesResponse); - } + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Tax/_files/tax_rule_for_region_1.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/apply_tax_for_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_billing_address.php + */ + public function testGetCartTotalsWithEmptyCart() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId); + $response = $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + + self::assertArrayHasKey('prices', $response['cart']); + $pricesResponse = $response['cart']['prices']; + self::assertEquals(0, $pricesResponse['grand_total']['value']); + self::assertEquals(0, $pricesResponse['subtotal_including_tax']['value']); + self::assertEquals(0, $pricesResponse['subtotal_excluding_tax']['value']); + self::assertEquals(0, $pricesResponse['subtotal_with_discount_excluding_tax']['value']); + + $appliedTaxesResponse = $pricesResponse['applied_taxes']; + + self::assertCount(0, $appliedTaxesResponse); + } /** * @magentoApiDataFixture Magento/Customer/_files/customer.php diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CartTotalsTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CartTotalsTest.php index 3691a772a48cf..3334a98e8feb9 100755 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CartTotalsTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CartTotalsTest.php @@ -59,31 +59,31 @@ public function testGetCartTotalsWithTaxApplied() self::assertEquals('USD', $appliedTaxesResponse[0]['amount']['currency']); } - /** - * @magentoApiDataFixture Magento/GraphQl/Tax/_files/tax_rule_for_region_1.php - * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php - * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/apply_tax_for_simple_product.php - * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php - * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php - * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_billing_address.php - */ - public function testGetCartTotalsWithEmptyCart() - { - $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); - $query = $this->getQuery($maskedQuoteId); - $response = $this->graphQlQuery($query); - - self::assertArrayHasKey('prices', $response['cart']); - $pricesResponse = $response['cart']['prices']; - self::assertEquals(0, $pricesResponse['grand_total']['value']); - self::assertEquals(0, $pricesResponse['subtotal_including_tax']['value']); - self::assertEquals(0, $pricesResponse['subtotal_excluding_tax']['value']); - self::assertEquals(0, $pricesResponse['subtotal_with_discount_excluding_tax']['value']); - - $appliedTaxesResponse = $pricesResponse['applied_taxes']; - - self::assertCount(0, $appliedTaxesResponse); - } + /** + * @magentoApiDataFixture Magento/GraphQl/Tax/_files/tax_rule_for_region_1.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/apply_tax_for_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_billing_address.php + */ + public function testGetCartTotalsWithEmptyCart() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId); + $response = $this->graphQlQuery($query); + + self::assertArrayHasKey('prices', $response['cart']); + $pricesResponse = $response['cart']['prices']; + self::assertEquals(0, $pricesResponse['grand_total']['value']); + self::assertEquals(0, $pricesResponse['subtotal_including_tax']['value']); + self::assertEquals(0, $pricesResponse['subtotal_excluding_tax']['value']); + self::assertEquals(0, $pricesResponse['subtotal_with_discount_excluding_tax']['value']); + + $appliedTaxesResponse = $pricesResponse['applied_taxes']; + + self::assertCount(0, $appliedTaxesResponse); + } /** * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php From 56ba3b49ed02856d6455e33285fe0000d56a886e Mon Sep 17 00:00:00 2001 From: Ankur Raiyani <ankurvr7003@gmail.com> Date: Mon, 1 Jul 2019 17:04:17 +0530 Subject: [PATCH 592/773] Setting right shipper street1 in addressline1 In UPS there is limit of 35 chars in address each lines, so currently in model it was setting address line 1 with concatenated street1 and street2 from origin setting which was exceeding chars limit of address lines. So not setting right street1 inside address line 1 data. Previously it was giving error "Missing or invalid ship from address line 1" in response of UPS request because of character limit. --- app/code/Magento/Ups/Model/Carrier.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Ups/Model/Carrier.php b/app/code/Magento/Ups/Model/Carrier.php index b64ab75179aad..5320aeb5bcc8a 100644 --- a/app/code/Magento/Ups/Model/Carrier.php +++ b/app/code/Magento/Ups/Model/Carrier.php @@ -1380,7 +1380,7 @@ protected function _formShipmentRequest(\Magento\Framework\DataObject $request) $shipperPart->addChild('PhoneNumber', $request->getShipperContactPhoneNumber()); $addressPart = $shipperPart->addChild('Address'); - $addressPart->addChild('AddressLine1', $request->getShipperAddressStreet()); + $addressPart->addChild('AddressLine1', $request->getShipperAddressStreet1()); $addressPart->addChild('AddressLine2', $request->getShipperAddressStreet2()); $addressPart->addChild('City', $request->getShipperAddressCity()); $addressPart->addChild('CountryCode', $request->getShipperAddressCountryCode()); From 439831f03bf1ff03902315d5bda490107c4aaa3a Mon Sep 17 00:00:00 2001 From: Sunil Patel <patelsunil42@gmail.com> Date: Mon, 1 Jul 2019 17:11:39 +0530 Subject: [PATCH 593/773] remove html tag from option --- .../Sales/view/adminhtml/templates/items/column/name.phtml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Sales/view/adminhtml/templates/items/column/name.phtml b/app/code/Magento/Sales/view/adminhtml/templates/items/column/name.phtml index 6797083afcc47..6e4d67ef51f22 100644 --- a/app/code/Magento/Sales/view/adminhtml/templates/items/column/name.phtml +++ b/app/code/Magento/Sales/view/adminhtml/templates/items/column/name.phtml @@ -28,9 +28,9 @@ <?php else : ?> <?php $_option = $block->getFormattedOption($_option['value']); ?> <?php $dots = 'dots' . uniqid(); ?> - <?= $block->escapeHtml($_option['value']) ?><?php if (isset($_option['remainder']) && $_option['remainder']) : ?> <span id="<?= /* @noEscape */ $dots; ?>"> ...</span> + <?= $block->escapeHtml($_option['value'], ['a']) ?><?php if (isset($_option['remainder']) && $_option['remainder']) : ?> <span id="<?= /* @noEscape */ $dots; ?>"> ...</span> <?php $id = 'id' . uniqid(); ?> - <span id="<?= /* @noEscape */ $id; ?>"><?= $block->escapeHtml($_option['remainder']) ?></span> + <span id="<?= /* @noEscape */ $id; ?>"><?= $block->escapeHtml($_option['remainder'], ['a']) ?></span> <script> require(['prototype'], function() { $('<?= /* @noEscape */ $id; ?>').hide(); From fc8a2ba8a71ad3ef565ac4a9679924112f9ae19a Mon Sep 17 00:00:00 2001 From: Stas Puga <stas.puga@transoftgroup.com> Date: Mon, 1 Jul 2019 15:23:53 +0300 Subject: [PATCH 594/773] MC-3268: Admin should be able to create Single Future Update with end date from CMS Block Page --- .../AdminOpentCmsBlockActionGroup.xml | 16 ++++++++++++++++ .../Magento/Cms/Test/Mftf/Data/BlockPageData.xml | 2 +- .../Cms/Test/Mftf/Page/AdminCmsEditBlockPage.xml | 2 +- 3 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminOpentCmsBlockActionGroup.xml diff --git a/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminOpentCmsBlockActionGroup.xml b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminOpentCmsBlockActionGroup.xml new file mode 100644 index 0000000000000..0f87ee90b7ce0 --- /dev/null +++ b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminOpentCmsBlockActionGroup.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminOpenCmsBlockActionGroup"> + <arguments> + <argument name="block_id" type="string"/> + </arguments> + <amOnPage url="{{AdminEditBlockPage.url(block_id)}}" stepKey="openEditCmsBlock"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Cms/Test/Mftf/Data/BlockPageData.xml b/app/code/Magento/Cms/Test/Mftf/Data/BlockPageData.xml index 368df3baa561f..98cd9ae30b8be 100644 --- a/app/code/Magento/Cms/Test/Mftf/Data/BlockPageData.xml +++ b/app/code/Magento/Cms/Test/Mftf/Data/BlockPageData.xml @@ -9,7 +9,7 @@ <entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd"> <entity name="_defaultBlock" type="block"> - <data key="title">Default Block</data> + <data key="title" unique="suffix">Default Block</data> <data key="identifier" unique="suffix" >block</data> <data key="content">Here is a block test. Yeah!</data> <data key="active">true</data> diff --git a/app/code/Magento/Cms/Test/Mftf/Page/AdminCmsEditBlockPage.xml b/app/code/Magento/Cms/Test/Mftf/Page/AdminCmsEditBlockPage.xml index 3fd100ee02aa2..f7ee5f5aca9b1 100644 --- a/app/code/Magento/Cms/Test/Mftf/Page/AdminCmsEditBlockPage.xml +++ b/app/code/Magento/Cms/Test/Mftf/Page/AdminCmsEditBlockPage.xml @@ -8,7 +8,7 @@ <pages xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/PageObject.xsd"> - <page name="AdminEditBlockPage" url="cms/block/edit/block_id" area="admin" module="Magento_Cms"> + <page name="AdminEditBlockPage" url="cms/block/edit/block_id/{{id}}" area="admin" module="Magento_Cms" parameterized="true"> <section name="AdminUpdateBlockSection"/> </page> </pages> From c06c1d84424a3390428c163e8f4f81950f0e58ee Mon Sep 17 00:00:00 2001 From: bobemoe <inbox.github@jhodges.co.uk> Date: Mon, 1 Jul 2019 15:34:34 +0100 Subject: [PATCH 595/773] move breakpoint by -1px to make nav work correctly at viweport width of 768px --- lib/web/mage/menu.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/web/mage/menu.js b/lib/web/mage/menu.js index b1875947cd54e..4853ba221c29a 100644 --- a/lib/web/mage/menu.js +++ b/lib/web/mage/menu.js @@ -22,7 +22,7 @@ define([ showDelay: 42, hideDelay: 300, delay: 0, - mediaBreakpoint: '(max-width: 768px)' + mediaBreakpoint: '(max-width: 767px)' }, /** From f6c957cb0c92776f4dc10a0ebc1c9a1b4884db51 Mon Sep 17 00:00:00 2001 From: Lieven Pouwelse <l.pouwelse@xsarus.nl> Date: Mon, 1 Jul 2019 20:57:35 +0200 Subject: [PATCH 596/773] Testing configurable option update based on product and attribute_id --- .../Model/OptionRepository.php | 22 +++++++-- .../Api/OptionRepositoryTest.php | 48 +++++++++++++++++++ 2 files changed, 65 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/ConfigurableProduct/Model/OptionRepository.php b/app/code/Magento/ConfigurableProduct/Model/OptionRepository.php index b4db0a4db5fcd..368ecad192410 100644 --- a/app/code/Magento/ConfigurableProduct/Model/OptionRepository.php +++ b/app/code/Magento/ConfigurableProduct/Model/OptionRepository.php @@ -22,6 +22,7 @@ use Magento\Store\Model\Store; /** + * Repository for performing CRUD operations for a configurable product's options. * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class OptionRepository implements \Magento\ConfigurableProduct\Api\OptionRepositoryInterface @@ -112,7 +113,7 @@ public function __construct( } /** - * {@inheritdoc} + * @inheritdoc */ public function get($sku, $id) { @@ -131,7 +132,7 @@ public function get($sku, $id) } /** - * {@inheritdoc} + * @inheritdoc */ public function getList($sku) { @@ -141,7 +142,7 @@ public function getList($sku) } /** - * {@inheritdoc} + * @inheritdoc */ public function delete(OptionInterface $option) { @@ -167,7 +168,7 @@ public function delete(OptionInterface $option) } /** - * {@inheritdoc} + * @inheritdoc */ public function deleteById($sku, $id) { @@ -184,7 +185,7 @@ public function deleteById($sku, $id) } /** - * {@inheritdoc} + * @inheritdoc * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ public function save($sku, OptionInterface $option) @@ -213,6 +214,16 @@ public function save($sku, OptionInterface $option) throw new \InvalidArgumentException('Incompatible product type'); } $option->setProductId($product->getData($metadata->getLinkField())); + if (!empty($option->getProductId() && !empty($option->getAttributeId()))) { + $id = $this->optionResource->getIdByProductIdAndAttributeId( + $option, + $option->getProductId(), + $option->getAttributeId() + ); + if (!empty($id)) { + $option->setId($id); + } + } } try { @@ -296,6 +307,7 @@ public function validateNewOptionData(OptionInterface $option) /** * Get MetadataPool instance + * * @return MetadataPool */ private function getMetadataPool() diff --git a/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/OptionRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/OptionRepositoryTest.php index 43d5a5b63b8a0..a293c3db5b5b3 100644 --- a/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/OptionRepositoryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/OptionRepositoryTest.php @@ -10,6 +10,9 @@ use Magento\TestFramework\Helper\Bootstrap; use Magento\Eav\Api\AttributeRepositoryInterface; +/** + * Class OptionRepositoryTest for testing ConfigurableProductoption integration + */ class OptionRepositoryTest extends \Magento\TestFramework\TestCase\WebapiAbstract { const SERVICE_NAME = 'configurableProductOptionRepositoryV1'; @@ -210,6 +213,51 @@ public function testUpdate() $this->assertEquals($requestBody['option']['label'], $configurableAttribute[0]['label']); } + /** + * @magentoApiDataFixture Magento/ConfigurableProduct/_files/product_configurable.php + */ + public function testUpdateWithoutOptionId() + { + $productSku = 'configurable'; + /** @var AttributeRepositoryInterface $attributeRepository */ + + $attributeRepository = Bootstrap::getObjectManager()->create(AttributeRepositoryInterface::class); + + /** @var \Magento\Eav\Api\Data\AttributeInterface $attribute */ + $attribute = $attributeRepository->get('catalog_product', 'test_configurable'); + + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => self::RESOURCE_PATH . '/' . $productSku . '/options', + 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST + ], + 'soap' => [ + 'service' => self::SERVICE_NAME, + 'serviceVersion' => self::SERVICE_VERSION, + 'operation' => self::SERVICE_NAME . 'Save' + ] + ]; + + $option = [ + 'attribute_id' => $attribute->getAttributeId(), + 'label' => 'Update Test Configurable with sku and attribute_id', + 'values' => [ + [ + 'value_index' => 1, + ] + ], + ]; + + if (TESTS_WEB_API_ADAPTER == self::ADAPTER_SOAP) { + $requestBody['sku'] = $productSku; + } + + $result = $this->_webApiCall($serviceInfo, ['sku' => $productSku, 'option' => $option]); + $this->assertGreaterThan(0, $result); + $configurableAttribute = $this->getConfigurableAttribute($productSku); + $this->assertEquals($option['label'], $configurableAttribute[0]['label']); + } + /** * @param string $productSku * @return array From c0a360fadc542dabead1425244d5080321328f1c Mon Sep 17 00:00:00 2001 From: Lieven Pouwelse <l.pouwelse@xsarus.nl> Date: Mon, 1 Jul 2019 21:00:44 +0200 Subject: [PATCH 597/773] Fix mass detection issue --- .../Magento/ConfigurableProduct/Api/OptionRepositoryTest.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/OptionRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/OptionRepositoryTest.php index a293c3db5b5b3..2aabf376e8943 100644 --- a/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/OptionRepositoryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/OptionRepositoryTest.php @@ -248,10 +248,6 @@ public function testUpdateWithoutOptionId() ], ]; - if (TESTS_WEB_API_ADAPTER == self::ADAPTER_SOAP) { - $requestBody['sku'] = $productSku; - } - $result = $this->_webApiCall($serviceInfo, ['sku' => $productSku, 'option' => $option]); $this->assertGreaterThan(0, $result); $configurableAttribute = $this->getConfigurableAttribute($productSku); From 1969add3052aaf39cb4bada0ce192e4ac969535c Mon Sep 17 00:00:00 2001 From: Patrick McLain <pat@pmclain.com> Date: Mon, 1 Jul 2019 22:43:09 -0400 Subject: [PATCH 598/773] Correct SendFriend Visibility Check The existing check would return an error if sending a product with search only visibility. --- .../SendFriendGraphQl/Model/Provider/GetVisibleProduct.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/SendFriendGraphQl/Model/Provider/GetVisibleProduct.php b/app/code/Magento/SendFriendGraphQl/Model/Provider/GetVisibleProduct.php index 9ff771afd57fe..64a17a868c307 100644 --- a/app/code/Magento/SendFriendGraphQl/Model/Provider/GetVisibleProduct.php +++ b/app/code/Magento/SendFriendGraphQl/Model/Provider/GetVisibleProduct.php @@ -49,8 +49,9 @@ public function execute(int $productId): ProductInterface $product = $this->productRepository->getById($productId); if (!in_array( - $product->getVisibility(), - $this->visibility->getVisibleInCatalogIds() + (int) $product->getVisibility(), + $this->visibility->getVisibleInSiteIds(), + true )) { throw new GraphQlNoSuchEntityException( __("The product that was requested doesn't exist. Verify the product and try again.") From 1b401076fc7939e532936363948dd49b8c58701e Mon Sep 17 00:00:00 2001 From: Patrick McLain <pat@pmclain.com> Date: Mon, 1 Jul 2019 22:49:03 -0400 Subject: [PATCH 599/773] Correct array type hints The visibility consts returned the the arrays are `int` not `string` --- app/code/Magento/Catalog/Model/Product/Visibility.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Product/Visibility.php b/app/code/Magento/Catalog/Model/Product/Visibility.php index c863526898a24..3a397969fdeac 100644 --- a/app/code/Magento/Catalog/Model/Product/Visibility.php +++ b/app/code/Magento/Catalog/Model/Product/Visibility.php @@ -55,7 +55,7 @@ public function __construct( /** * Retrieve visible in catalog ids array * - * @return string[] + * @return int[] */ public function getVisibleInCatalogIds() { @@ -65,7 +65,7 @@ public function getVisibleInCatalogIds() /** * Retrieve visible in search ids array * - * @return string[] + * @return int[] */ public function getVisibleInSearchIds() { @@ -75,7 +75,7 @@ public function getVisibleInSearchIds() /** * Retrieve visible in site ids array * - * @return string[] + * @return int[] */ public function getVisibleInSiteIds() { From 11b1c2bf64f4650add22371e39b5a7e510231e01 Mon Sep 17 00:00:00 2001 From: Kazim Noorani <kazim.noorani@krishtechnolabs.com> Date: Tue, 2 Jul 2019 10:23:04 +0530 Subject: [PATCH 600/773] Removed editors from all dependable customer billing address fields --- .../ui_component/customer_listing.xml | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/app/code/Magento/Customer/view/adminhtml/ui_component/customer_listing.xml b/app/code/Magento/Customer/view/adminhtml/ui_component/customer_listing.xml index 04371685b63d2..97ae9a9953eb6 100644 --- a/app/code/Magento/Customer/view/adminhtml/ui_component/customer_listing.xml +++ b/app/code/Magento/Customer/view/adminhtml/ui_component/customer_listing.xml @@ -263,9 +263,6 @@ <column name="billing_city" sortOrder="210"> <settings> <filter>text</filter> - <editor> - <editorType>text</editorType> - </editor> <label translate="true">City</label> <visible>false</visible> </settings> @@ -273,9 +270,6 @@ <column name="billing_fax" sortOrder="220"> <settings> <filter>text</filter> - <editor> - <editorType>text</editorType> - </editor> <label translate="true">Fax</label> <visible>false</visible> </settings> @@ -283,9 +277,6 @@ <column name="billing_vat_id" sortOrder="230"> <settings> <filter>text</filter> - <editor> - <editorType>text</editorType> - </editor> <label translate="true">VAT Number</label> <visible>false</visible> </settings> @@ -293,9 +284,6 @@ <column name="billing_company" sortOrder="240"> <settings> <filter>text</filter> - <editor> - <editorType>text</editorType> - </editor> <label translate="true">Company</label> <visible>false</visible> </settings> @@ -303,9 +291,6 @@ <column name="billing_firstname" sortOrder="250"> <settings> <filter>text</filter> - <editor> - <editorType>text</editorType> - </editor> <label translate="true">Billing Firstname</label> <visible>false</visible> </settings> @@ -313,9 +298,6 @@ <column name="billing_lastname" sortOrder="260"> <settings> <filter>text</filter> - <editor> - <editorType>text</editorType> - </editor> <label translate="true">Billing Lastname</label> <visible>false</visible> </settings> From b38e9ccf5f8d43950c20efdc46d642d55086bd11 Mon Sep 17 00:00:00 2001 From: natalia <natalia_marozava@epam.com> Date: Tue, 2 Jul 2019 09:39:28 +0300 Subject: [PATCH 601/773] MAGETWO-54438: Simple Product don't appear on Storefront after order cancelation with Bundle - Changed actionGroup name - Added actionGroup argument - Changed comment stepKeys --- ...ontAssertProductStockStatusActionGroup.xml | 6 +- ...erWithCheckMoneyOrderPaymentMethodTest.xml | 76 +++++++++---------- 2 files changed, 42 insertions(+), 40 deletions(-) diff --git a/app/code/Magento/CatalogInventory/Test/Mftf/ActionGroup/StorefrontAssertProductStockStatusActionGroup.xml b/app/code/Magento/CatalogInventory/Test/Mftf/ActionGroup/StorefrontAssertProductStockStatusActionGroup.xml index 04d37c2a9042c..30fddba4241b7 100644 --- a/app/code/Magento/CatalogInventory/Test/Mftf/ActionGroup/StorefrontAssertProductStockStatusActionGroup.xml +++ b/app/code/Magento/CatalogInventory/Test/Mftf/ActionGroup/StorefrontAssertProductStockStatusActionGroup.xml @@ -8,14 +8,16 @@ <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="storefrontCheckProductStockStatus"> + <actionGroup name="StorefrontCheckProductStockStatus"> <arguments> <argument name="productUrlKey" type="string"/> <argument name="productName" type="string"/> + <argument name="stockStatus" type="string" defaultValue="IN STOCK"/> </arguments> <amOnPage url="{{StorefrontProductPage.url(productUrlKey)}}" stepKey="navigateToProductPage"/> <waitForPageLoad stepKey="waitForProductPageLoad"/> <see selector="{{StorefrontProductInfoMainSection.productName}}" userInput="{{productName}}" stepKey="seeProductName"/> - <see userInput="IN STOCK" stepKey="assertProductStockStatus"/> + <see userInput="{{stockStatus}}" stepKey="assertProductStockStatus"/> </actionGroup> </actionGroups> + \ No newline at end of file diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminCancelTheCreatedOrderWithCheckMoneyOrderPaymentMethodTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCancelTheCreatedOrderWithCheckMoneyOrderPaymentMethodTest.xml index 232eaf566d8db..116b8e7d6ca71 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminCancelTheCreatedOrderWithCheckMoneyOrderPaymentMethodTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminCancelTheCreatedOrderWithCheckMoneyOrderPaymentMethodTest.xml @@ -21,26 +21,26 @@ <before> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> <!-- Set default flat rate shipping method settings --> - <comment userInput="Set default flat rate shipping method settings" stepKey="SetDefaultFlatRateShippingMethodSetting"/> + <comment userInput="Set default flat rate shipping method settings" stepKey="setDefaultFlatRateShippingMethodComment"/> <createData entity="FlatRateShippingMethodDefault" stepKey="setDefaultFlatRateShippingMethod"/> <!-- Create simple customer --> - <comment userInput="Create simple customer" stepKey="CreateSimpleCustomer"/> + <comment userInput="Create simple customer" stepKey="createSimpleCustomerComment"/> <createData entity="Simple_US_Customer_CA" stepKey="simpleCustomer"/> <!-- Create the category --> - <comment userInput="Create the category" stepKey="CreateTheCategory"/> + <comment userInput="Create the category" stepKey="createCategoryComment"/> <createData entity="ApiCategory" stepKey="createCategory"/> <!-- Create Virtual Product --> - <comment userInput="Create Virtual Product" stepKey="CreateVirtualProduct"/> + <comment userInput="Create Virtual Product" stepKey="createVirtualProductComment"/> <createData entity="VirtualProductPrice10Qty1" stepKey="virtualProduct"> <requiredEntity createDataKey="createCategory"/> </createData> <!-- Create Simple Product --> - <comment userInput="Create Simple Product" stepKey="CreateSimpleProduct"/> + <comment userInput="Create Simple Product" stepKey="createSimpleProductComment"/> <createData entity="SimpleProductPrice10Qty1" stepKey="simpleProduct"> <requiredEntity createDataKey="createCategory"/> </createData> <!-- Create Bundle product --> - <comment userInput="Create Bundle Product" stepKey="CreateBundleProduct"/> + <comment userInput="Create Bundle Product" stepKey="createBundleProductComment"/> <createData entity="SimpleProduct2Price10Qty1" stepKey="simpleProduct1"/> <createData entity="BundleProductPriceViewRange" stepKey="createBundleProduct"> <requiredEntity createDataKey="createCategory"/> @@ -55,41 +55,41 @@ <requiredEntity createDataKey="simpleProduct1"/> </createData> <!-- Create configurable product and add it to the category --> - <comment userInput="Create configurable product and add it to the category" stepKey="CreateConfigProduct"/> + <comment userInput="Create configurable product and add it to the category" stepKey="createConfigProductComment"/> <createData entity="ConfigurableProductPrice10Qty1" stepKey="createConfigProduct"> <requiredEntity createDataKey="createCategory"/> </createData> <!-- Create an attribute with two options to be used in the first child product --> - <comment userInput="Create an attribute with two options to be used in the first child product" stepKey="CreateOptionsOfTheFirstChildProduct"/> + <comment userInput="Create an attribute with two options to be used in the first child product" stepKey="createOptionsOfTheFirstChildProductComment"/> <createData entity="productAttributeWithTwoOptions" stepKey="createConfigProductAttribute"/> <createData entity="productAttributeOption1" stepKey="createConfigProductAttributeOption1"> <requiredEntity createDataKey="createConfigProductAttribute"/> </createData> <!-- Add the attribute we just created to default attribute set --> - <comment userInput="Add the attribute we just created to default attribute set" stepKey="AddAttributeToDefaultAttrSet"/> + <comment userInput="Add the attribute we just created to default attribute set" stepKey="addAttributeToDefaultAttrSetComment"/> <createData entity="AddToDefaultSet" stepKey="createConfigAddToAttributeSet"> <requiredEntity createDataKey="createConfigProductAttribute"/> </createData> <!-- Get the option of the attribute we created --> - <comment userInput="Get the option of the attribute we created" stepKey="GetAttributeOption"/> + <comment userInput="Get the option of the attribute we created" stepKey="getAttributeOptionComment"/> <getData entity="ProductAttributeOptionGetter" index="1" stepKey="getConfigAttributeOption1"> <requiredEntity createDataKey="createConfigProductAttribute"/> </getData> <!-- Create a simple product and give it the attribute with option --> - <comment userInput="Create a simple product and give it the attribute with option" stepKey="CreateSimpleProductWithOptions"/> + <comment userInput="Create a simple product and give it the attribute with option" stepKey="createSimpleProductWithOptionsComment"/> <createData entity="SimpleProduct3Price10Qty1" stepKey="createConfigChildProduct1"> <requiredEntity createDataKey="createConfigProductAttribute"/> <requiredEntity createDataKey="getConfigAttributeOption1"/> </createData> <!-- Create the configurable product --> - <comment userInput="Create the configurable product" stepKey="CreateTheConfigurableProduct"/> + <comment userInput="Create the configurable product" stepKey="createConfigurableProductComment"/> <createData entity="ConfigurableProductTwoOptions" stepKey="createConfigProductOption"> <requiredEntity createDataKey="createConfigProduct"/> <requiredEntity createDataKey="createConfigProductAttribute"/> <requiredEntity createDataKey="getConfigAttributeOption1"/> </createData> <!-- Add simple product to the configurable product --> - <comment userInput="Add simple product to the configurable product" stepKey="AddSimpleProductToConfigurable"/> + <comment userInput="Add simple product to the configurable product" stepKey="addSimpleProductToConfigurableComment"/> <createData entity="ConfigurableProductAddChild" stepKey="createConfigProductAddChild1"> <requiredEntity createDataKey="createConfigProduct"/> <requiredEntity createDataKey="createConfigChildProduct1"/> @@ -110,48 +110,48 @@ <actionGroup ref="logout" stepKey="logout"/> </after> <!-- Create new customer order --> - <comment userInput="Create new customer order" stepKey="CreateNewCustomerOrder"/> + <comment userInput="Create new customer order" stepKey="createNewCustomerOrderComment"/> <actionGroup ref="navigateToNewOrderPageExistingCustomer" stepKey="navigateToNewOrderWithExistingCustomer"> <argument name="customer" value="$$simpleCustomer$$"/> </actionGroup> <!-- Add bundle product to order and check product price in grid --> - <comment userInput="Add bundle product to order and check product price in grid" stepKey="AddBundleProductToOrder"/> + <comment userInput="Add bundle product to order and check product price in grid" stepKey="addBundleProductToOrderComment"/> <actionGroup ref="addBundleProductToOrder" stepKey="addBundleProductToOrder"> <argument name="product" value="$$createBundleProduct$$"/> <argument name="quantity" value="1"/> </actionGroup> <!-- Add configurable product to order --> - <comment userInput="Add configurable product to order" stepKey="AddConfigurableProductToOrder"/> + <comment userInput="Add configurable product to order" stepKey="addConfigurableProductToOrderComment"/> <actionGroup ref="newAddConfigurableProductToOrder" stepKey="addConfigurableProductToOrder"> <argument name="product" value="$$createConfigProduct$$"/> <argument name="attribute" value="$$createConfigProductAttribute$$"/> <argument name="option" value="$$getConfigAttributeOption1$$"/> </actionGroup> <!-- Add Simple product to order --> - <comment userInput="Add Simple product to order" stepKey="AddSimpleProductToOrder"/> + <comment userInput="Add Simple product to order" stepKey="addSimpleProductToOrderComment"/> <actionGroup ref="addSimpleProductToOrder" stepKey="addSimpleProductToTheOrder"> <argument name="product" value="$$simpleProduct$$"/> </actionGroup> <!-- Add Virtual product to order --> - <comment userInput="Add Virtual product to order" stepKey="AddVirtualProductToOrder"/> + <comment userInput="Add Virtual product to order" stepKey="addVirtualProductToOrderComment"/> <actionGroup ref="addSimpleProductToOrder" stepKey="addVirtualProductToTheOrder"> <argument name="product" value="$$virtualProduct$$"/> </actionGroup> <!-- Select FlatRate shipping method --> - <comment userInput="Select FlatRate shipping method" stepKey="SelectFlatRateShippingMethod"/> + <comment userInput="Select FlatRate shipping method" stepKey="selectFlatRateShippingMethodComment"/> <actionGroup ref="AdminSelectFlatRateShippingMethodActionGroup" stepKey="selectFlatRateShippingMethod"/> <!-- Submit order --> - <comment userInput="Submit order" stepKey="SubmitOrder"/> + <comment userInput="Submit order" stepKey="submitOrderComment"/> <click selector="{{AdminOrderFormActionSection.SubmitOrder}}" stepKey="submitOrder"/> <!-- Verify order information --> - <comment userInput="Verify order information" stepKey="VerifyOrderInformation"/> + <comment userInput="Verify order information" stepKey="verifyOrderInformationComment"/> <actionGroup ref="verifyCreatedOrderInformation" stepKey="verifyCreatedOrderInformation"/> <grabTextFrom selector="|Order # (\d+)|" stepKey="orderId"/> <!-- Cancel the Order --> - <comment userInput="Cancel the Order" stepKey="CancelTheOrder"/> + <comment userInput="Cancel the Order" stepKey="cancelTheOrder"/> <actionGroup ref="cancelPendingOrder" stepKey="cancelPendingOrder"/> <!-- Assert Simple Product Quantity in backend after order Canceled --> - <comment userInput="Assert Simple Product Quantity in backend after order Canceled" stepKey="AssertSimpleProductQuantityAfterOrderCanceled"/> + <comment userInput="Assert Simple Product Quantity in backend after order Canceled" stepKey="assertSimpleProductQuantityAfterOrderCanceledComment"/> <actionGroup ref="filterAndSelectProduct" stepKey="filterAndSelectTheProduct"> <argument name="productSku" value="$$simpleProduct.sku$$"/> </actionGroup> @@ -160,13 +160,13 @@ <seeInField selector="{{AdminProductFormSection.productQuantity}}" userInput="1" stepKey="seeProductQuantity"/> <seeInField selector="{{AdminProductFormSection.productStockStatus}}" userInput="In Stock" stepKey="seeProductStockStatus"/> <!-- Assert Simple Product Stock Status in frontend after order canceled --> - <comment userInput="Assert Simple Product Stock Status in frontend after order Canceled" stepKey="AssertSimpleProductStockStatus"/> - <actionGroup ref="storefrontCheckProductStockStatus" stepKey="checkProductQtyOfSimpleProduct"> + <comment userInput="Assert Simple Product Stock Status in frontend after order Canceled" stepKey="assertSimpleProductStockStatusComment"/> + <actionGroup ref="StorefrontCheckProductStockStatus" stepKey="checkProductQtyOfSimpleProduct"> <argument name="productUrlKey" value="$$simpleProduct.custom_attributes[url_key]$$"/> <argument name="productName" value="$$simpleProduct.name$$"/> </actionGroup> <!-- Assert Virtual Product Quantity in backend after order canceled --> - <comment userInput="Assert Virtual Product Quantity in backend after order canceled" stepKey="AssertVirtualProductQuantityAfterOrderCanceled"/> + <comment userInput="Assert Virtual Product Quantity in backend after order canceled" stepKey="assertVirtualProductQuantityAfterOrderCanceledComment"/> <actionGroup ref="filterAndSelectProduct" stepKey="filterAndSelectTheVirtualProduct"> <argument name="productSku" value="$$virtualProduct.sku$$"/> </actionGroup> @@ -175,13 +175,13 @@ <seeInField selector="{{AdminProductFormSection.productQuantity}}" userInput="1" stepKey="seeVirtualProductQuantity"/> <seeInField selector="{{AdminProductFormSection.productStockStatus}}" userInput="In Stock" stepKey="seeVirtualProductStockStatus"/> <!-- Assert Virtual Product Stock Status in frontend after order canceled --> - <comment userInput="Assert Virtual Product Stock Status in frontend after order Canceled" stepKey="AssertVirtualProductStockStatus"/> - <actionGroup ref="storefrontCheckProductStockStatus" stepKey="checkProductQtyOfVirtualProduct"> + <comment userInput="Assert Virtual Product Stock Status in frontend after order Canceled" stepKey="assertVirtualProductStockStatusComment"/> + <actionGroup ref="StorefrontCheckProductStockStatus" stepKey="checkProductQtyOfVirtualProduct"> <argument name="productUrlKey" value="$$virtualProduct.custom_attributes[url_key]$$"/> <argument name="productName" value="$$virtualProduct.name$$"/> </actionGroup> <!-- Assert Bundle Product Quantity in backend after order canceled --> - <comment userInput="Assert Bundle Product Quantity in backend after order canceled" stepKey="AssertBundleProductQuantityAfterOrderCanceled"/> + <comment userInput="Assert Bundle Product Quantity in backend after order canceled" stepKey="assertBundleProductQuantityAfterOrderCanceledComment"/> <actionGroup ref="filterAndSelectProduct" stepKey="filterAndSelectTheBundleProduct"> <argument name="productSku" value="$$simpleProduct1.sku$$"/> </actionGroup> @@ -190,13 +190,13 @@ <seeInField selector="{{AdminProductFormSection.productQuantity}}" userInput="1" stepKey="seeBundleProductQuantity"/> <seeInField selector="{{AdminProductFormSection.productStockStatus}}" userInput="In Stock" stepKey="seeBundleProductStockStatus"/> <!-- Assert Bundle Product Stock Status in frontend after order canceled --> - <comment userInput="Assert Bundle Product Stock Status in frontend after order Canceled" stepKey="AssertBundleProductStockStatus"/> - <actionGroup ref="storefrontCheckProductStockStatus" stepKey="checkProductQtyOfBundleProduct"> + <comment userInput="Assert Bundle Product Stock Status in frontend after order Canceled" stepKey="assertBundleProductStockStatusComment"/> + <actionGroup ref="StorefrontCheckProductStockStatus" stepKey="checkProductQtyOfBundleProduct"> <argument name="productUrlKey" value="$$createBundleProduct.custom_attributes[url_key]$$"/> <argument name="productName" value="$$createBundleProduct.name$$"/> </actionGroup> <!-- Assert Configurable Product Quantity in backend after order canceled --> - <comment userInput="Assert Configurable Product quantity in backend after order canceled" stepKey="AssertConfigurableProductQuantityAfterOrderCanceled"/> + <comment userInput="Assert Configurable Product quantity in backend after order canceled" stepKey="assertConfigurableProductQuantityAfterOrderCanceledComment"/> <actionGroup ref="filterAndSelectProduct" stepKey="filterAndSelectTheConfigProduct"> <argument name="productSku" value="$$createConfigChildProduct1.sku$$"/> </actionGroup> @@ -205,29 +205,29 @@ <seeInField selector="{{AdminProductFormSection.productQuantity}}" userInput="1" stepKey="seeConfigProductQuantity"/> <seeInField selector="{{AdminProductFormSection.productStockStatus}}" userInput="In Stock" stepKey="seeConfigProductStockStatus"/> <!-- Assert Configurable Product Stock Status in frontend after order canceled --> - <comment userInput="Assert Configurable Product Stock Status in frontend after order Canceled" stepKey="AssertConfigurableProductStockStatus"/> - <actionGroup ref="storefrontCheckProductStockStatus" stepKey="checkProductQtyOfConfigProductInFrontend"> + <comment userInput="Assert Configurable Product Stock Status in frontend after order Canceled" stepKey="assertConfigurableProductStockStatusComment"/> + <actionGroup ref="StorefrontCheckProductStockStatus" stepKey="checkProductQtyOfConfigProductInFrontend"> <argument name="productUrlKey" value="$$createConfigProduct.custom_attributes[url_key]$$"/> <argument name="productName" value="$$createConfigProduct.name$$"/> </actionGroup> <!-- Open Order Index Page --> - <comment userInput="Open Order Index Page" stepKey="OpenOrderIndexPage"/> + <comment userInput="Open Order Index Page" stepKey="openOrderIndexPageComemnt"/> <amOnPage url="{{AdminOrdersPage.url}}" stepKey="goToOrders"/> <waitForPageLoad stepKey="waitForPageLoad5"/> <!-- Filter order using orderId --> - <comment userInput="Filter order using orderId" stepKey="FilterOrderUsingOrderId"/> + <comment userInput="Filter order using orderId" stepKey="filterOrderUsingOrderIdComment"/> <actionGroup ref="filterOrderGridById" stepKey="filterOrderGridById"> <argument name="orderId" value="$orderId"/> </actionGroup> <see selector="{{AdminOrdersGridSection.firstRow}}" userInput="$orderId" stepKey="seeOrderIdInGrid"/> <see selector="{{AdminOrdersGridSection.firstRow}}" userInput="Canceled" stepKey="seeStatusInGrid"/> <!-- Log in to Storefront as Customer --> - <comment userInput="Log in to Storefront as Customer" stepKey="LogInAsCustomer"/> + <comment userInput="Log in to Storefront as Customer" stepKey="logInAsCustomerComment"/> <actionGroup ref="LoginToStorefrontActionGroup" stepKey="signUp"> <argument name="Customer" value="$$simpleCustomer$$"/> </actionGroup> <!-- Assert Order status in frontend order grid --> - <comment userInput="Assert Order status in frontend order grid " stepKey="AssertOrderStatusInFrontend"/> + <comment userInput="Assert Order status in frontend order grid " stepKey="assertOrderStatusInFrontendComment"/> <click selector="{{StorefrontCustomerSidebarSection.sidebarCurrentTab('My Orders')}}" stepKey="clickOnMyOrders"/> <waitForPageLoad stepKey="waitForOrderDetailsToLoad"/> <seeElement selector="{{StorefrontCustomerOrderViewSection.orderStatusInGrid('$orderId', 'Canceled')}}" stepKey="seeOrderStatusInGrid"/> From fa030f284662ea698ea149b1b5de50cc9ea10e68 Mon Sep 17 00:00:00 2001 From: Graham Wharton <graham@gwharton.me.uk> Date: Tue, 2 Jul 2019 11:27:10 +0100 Subject: [PATCH 602/773] Update Framework/Mail::Message to send all emails as MIME, not just HTML emails. --- .../Magento/Framework/Mail/Message.php | 31 ++++++++++++++++--- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/lib/internal/Magento/Framework/Mail/Message.php b/lib/internal/Magento/Framework/Mail/Message.php index 71da6e673bf29..f246889b070d6 100644 --- a/lib/internal/Magento/Framework/Mail/Message.php +++ b/lib/internal/Magento/Framework/Mail/Message.php @@ -23,7 +23,7 @@ class Message implements MailMessageInterface * * @var string */ - private $messageType = self::TYPE_TEXT; + private $messageType = Mime::TYPE_TEXT; /** * Initialize dependencies. @@ -58,8 +58,8 @@ public function setMessageType($type) */ public function setBody($body) { - if (is_string($body) && $this->messageType === MailMessageInterface::TYPE_HTML) { - $body = self::createHtmlMimeFromString($body); + if (is_string($body)) { + $body = self::createMimeFromString($body, $this->messageType); } $this->zendMessage->setBody($body); return $this; @@ -161,6 +161,10 @@ public function getRawMessage() * * @param string $htmlBody * @return \Zend\Mime\Message + * + * @deprecated All emails that Magento sends should be mime encoded. Therefore + * use generic function createMimeFromString + * @see createMimeFromString() */ private function createHtmlMimeFromString($htmlBody) { @@ -172,12 +176,29 @@ private function createHtmlMimeFromString($htmlBody) return $mimeMessage; } + /** + * Create mime message from the string. + * + * @param string $body + * @param string $messageType + * @return \Zend\Mime\Message + */ + private function createMimeFromString($body, $messageType) + { + $part = new Part($body); + $part->setCharset($this->zendMessage->getEncoding()); + $part->setType($messageType); + $mimeMessage = new \Zend\Mime\Message(); + $mimeMessage->addPart($part); + return $mimeMessage; + } + /** * @inheritdoc */ public function setBodyHtml($html) { - $this->setMessageType(self::TYPE_HTML); + $this->setMessageType(Mime::TYPE_HTML); return $this->setBody($html); } @@ -186,7 +207,7 @@ public function setBodyHtml($html) */ public function setBodyText($text) { - $this->setMessageType(self::TYPE_TEXT); + $this->setMessageType(Mime::TYPE_TEXT); return $this->setBody($text); } } From 449cc814a7bcdb3b8f6837f59803a7f6b2453907 Mon Sep 17 00:00:00 2001 From: "rostyslav.hymon" <rostyslav.hymon@transoftgroup.com> Date: Tue, 2 Jul 2019 14:22:16 +0300 Subject: [PATCH 603/773] MC-17919: In stock products are showing as out of stock after they are enabled via a Scheduled Update --- .../Model/ResourceModel/Indexer/Stock/DefaultStock.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/code/Magento/CatalogInventory/Model/ResourceModel/Indexer/Stock/DefaultStock.php b/app/code/Magento/CatalogInventory/Model/ResourceModel/Indexer/Stock/DefaultStock.php index ba3b62f554767..86e4f3cc81e7e 100644 --- a/app/code/Magento/CatalogInventory/Model/ResourceModel/Indexer/Stock/DefaultStock.php +++ b/app/code/Magento/CatalogInventory/Model/ResourceModel/Indexer/Stock/DefaultStock.php @@ -248,8 +248,7 @@ protected function _getStockStatusSelect($entityIds = null, $usePrimaryTable = f )->joinInner( ['mcpei' => $this->getTable('catalog_product_entity_int')], 'e.' . $linkField . ' = mcpei.' . $linkField - . ' AND mcpei.attribute_id = ' . $this->_getAttribute('status')->getId() - . ' AND mcpei.value = ' . ProductStatus::STATUS_ENABLED, + . ' AND mcpei.attribute_id = ' . $this->_getAttribute('status')->getId(), [] )->columns( ['qty' => $qtyExpr] From 7e3bc7154913af3c53b955a14c1f8f7dc78e7cfd Mon Sep 17 00:00:00 2001 From: Graham Wharton <graham@gwharton.me.uk> Date: Tue, 2 Jul 2019 12:27:17 +0100 Subject: [PATCH 604/773] Updated unit test --- .../Framework/Mail/Test/Unit/MessageTest.php | 37 ++++++++----------- 1 file changed, 15 insertions(+), 22 deletions(-) diff --git a/lib/internal/Magento/Framework/Mail/Test/Unit/MessageTest.php b/lib/internal/Magento/Framework/Mail/Test/Unit/MessageTest.php index 0c33e25e0d9d0..478998230a276 100644 --- a/lib/internal/Magento/Framework/Mail/Test/Unit/MessageTest.php +++ b/lib/internal/Magento/Framework/Mail/Test/Unit/MessageTest.php @@ -8,41 +8,34 @@ class MessageTest extends \PHPUnit\Framework\TestCase { /** - * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\Mail\Message + * @var \Magento\Framework\Mail\Message */ - protected $_messageMock; + protected $message; protected function setUp() { - $this->_messageMock = $this->createPartialMock( - \Magento\Framework\Mail\Message::class, - ['setBody', 'setMessageType'] - ); + $this->message = new \Magento\Framework\Mail\Message(); } public function testSetBodyHtml() { - $this->_messageMock->expects($this->once()) - ->method('setMessageType') - ->with('text/html'); + $this->message->setBodyHtml('body'); - $this->_messageMock->expects($this->once()) - ->method('setBody') - ->with('body'); - - $this->_messageMock->setBodyHtml('body'); + $part = $this->message->getBody()->getParts()[0]; + $this->assertEquals('text/html', $part->getType()); + $this->assertEquals('8bit', $part->getEncoding()); + $this->assertEquals('utf-8', $part->getCharset()); + $this->assertEquals('body', $part->getContent()); } public function testSetBodyText() { - $this->_messageMock->expects($this->once()) - ->method('setMessageType') - ->with('text/plain'); - - $this->_messageMock->expects($this->once()) - ->method('setBody') - ->with('body'); + $this->message->setBodyText('body'); - $this->_messageMock->setBodyText('body'); + $part = $this->message->getBody()->getParts()[0]; + $this->assertEquals('text/plain', $part->getType()); + $this->assertEquals('8bit', $part->getEncoding()); + $this->assertEquals('utf-8', $part->getCharset()); + $this->assertEquals('body', $part->getContent()); } } From b3e1aedd6dc63141411e5cbc67fe6b8169aa98cb Mon Sep 17 00:00:00 2001 From: Graham Wharton <graham@gwharton.me.uk> Date: Tue, 2 Jul 2019 13:14:57 +0100 Subject: [PATCH 605/773] Fixed coding standards violations --- .../Magento/Framework/Mail/Message.php | 20 ------------------- .../Framework/Mail/Test/Unit/MessageTest.php | 3 +++ 2 files changed, 3 insertions(+), 20 deletions(-) diff --git a/lib/internal/Magento/Framework/Mail/Message.php b/lib/internal/Magento/Framework/Mail/Message.php index f246889b070d6..a9996c0a4f12a 100644 --- a/lib/internal/Magento/Framework/Mail/Message.php +++ b/lib/internal/Magento/Framework/Mail/Message.php @@ -156,26 +156,6 @@ public function getRawMessage() return $this->zendMessage->toString(); } - /** - * Create HTML mime message from the string. - * - * @param string $htmlBody - * @return \Zend\Mime\Message - * - * @deprecated All emails that Magento sends should be mime encoded. Therefore - * use generic function createMimeFromString - * @see createMimeFromString() - */ - private function createHtmlMimeFromString($htmlBody) - { - $htmlPart = new Part($htmlBody); - $htmlPart->setCharset($this->zendMessage->getEncoding()); - $htmlPart->setType(Mime::TYPE_HTML); - $mimeMessage = new \Zend\Mime\Message(); - $mimeMessage->addPart($htmlPart); - return $mimeMessage; - } - /** * Create mime message from the string. * diff --git a/lib/internal/Magento/Framework/Mail/Test/Unit/MessageTest.php b/lib/internal/Magento/Framework/Mail/Test/Unit/MessageTest.php index 478998230a276..bea2a9ea91d38 100644 --- a/lib/internal/Magento/Framework/Mail/Test/Unit/MessageTest.php +++ b/lib/internal/Magento/Framework/Mail/Test/Unit/MessageTest.php @@ -5,6 +5,9 @@ */ namespace Magento\Framework\Mail\Test\Unit; +/** + * test Magento\Framework\Mail\Message + */ class MessageTest extends \PHPUnit\Framework\TestCase { /** From b48baca357814c7abc625011912939acb4188fb8 Mon Sep 17 00:00:00 2001 From: Stas Puga <stas.puga@transoftgroup.com> Date: Tue, 2 Jul 2019 15:46:45 +0300 Subject: [PATCH 606/773] MC-3269: Admin should be able to create Single Future Update with no end date from CMS Block Page --- .../ActionGroup/AdminOpenCmsBlockActionGroup.xml | 16 ++++++++++++++++ .../Magento/Cms/Test/Mftf/Data/BlockPageData.xml | 2 +- .../Cms/Test/Mftf/Page/AdminCmsEditBlockPage.xml | 2 +- 3 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminOpenCmsBlockActionGroup.xml diff --git a/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminOpenCmsBlockActionGroup.xml b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminOpenCmsBlockActionGroup.xml new file mode 100644 index 0000000000000..0f87ee90b7ce0 --- /dev/null +++ b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminOpenCmsBlockActionGroup.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminOpenCmsBlockActionGroup"> + <arguments> + <argument name="block_id" type="string"/> + </arguments> + <amOnPage url="{{AdminEditBlockPage.url(block_id)}}" stepKey="openEditCmsBlock"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Cms/Test/Mftf/Data/BlockPageData.xml b/app/code/Magento/Cms/Test/Mftf/Data/BlockPageData.xml index 368df3baa561f..98cd9ae30b8be 100644 --- a/app/code/Magento/Cms/Test/Mftf/Data/BlockPageData.xml +++ b/app/code/Magento/Cms/Test/Mftf/Data/BlockPageData.xml @@ -9,7 +9,7 @@ <entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd"> <entity name="_defaultBlock" type="block"> - <data key="title">Default Block</data> + <data key="title" unique="suffix">Default Block</data> <data key="identifier" unique="suffix" >block</data> <data key="content">Here is a block test. Yeah!</data> <data key="active">true</data> diff --git a/app/code/Magento/Cms/Test/Mftf/Page/AdminCmsEditBlockPage.xml b/app/code/Magento/Cms/Test/Mftf/Page/AdminCmsEditBlockPage.xml index 3fd100ee02aa2..f7ee5f5aca9b1 100644 --- a/app/code/Magento/Cms/Test/Mftf/Page/AdminCmsEditBlockPage.xml +++ b/app/code/Magento/Cms/Test/Mftf/Page/AdminCmsEditBlockPage.xml @@ -8,7 +8,7 @@ <pages xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/PageObject.xsd"> - <page name="AdminEditBlockPage" url="cms/block/edit/block_id" area="admin" module="Magento_Cms"> + <page name="AdminEditBlockPage" url="cms/block/edit/block_id/{{id}}" area="admin" module="Magento_Cms" parameterized="true"> <section name="AdminUpdateBlockSection"/> </page> </pages> From 675ea2986b2cd1e3c79a4c0475a4c77ec70b9a18 Mon Sep 17 00:00:00 2001 From: "rostyslav.hymon" <rostyslav.hymon@transoftgroup.com> Date: Tue, 2 Jul 2019 15:56:43 +0300 Subject: [PATCH 607/773] MC-17919: In stock products are showing as out of stock after they are enabled via a Scheduled Update --- .../Model/ResourceModel/Indexer/Stock/DefaultStock.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/CatalogInventory/Model/ResourceModel/Indexer/Stock/DefaultStock.php b/app/code/Magento/CatalogInventory/Model/ResourceModel/Indexer/Stock/DefaultStock.php index 86e4f3cc81e7e..f1da5c3df22bc 100644 --- a/app/code/Magento/CatalogInventory/Model/ResourceModel/Indexer/Stock/DefaultStock.php +++ b/app/code/Magento/CatalogInventory/Model/ResourceModel/Indexer/Stock/DefaultStock.php @@ -320,7 +320,8 @@ protected function _updateIndex($entityIds) } /** - * Delete records by their ids from index table + * Delete records by their ids from index table. + * * Used to clean table before re-indexation * * @param array $ids @@ -365,6 +366,8 @@ public function getIdxTable($table = null) } /** + * Get status expression + * * @param AdapterInterface $connection * @param bool $isAggregate * @return mixed @@ -390,6 +393,8 @@ protected function getStatusExpression(AdapterInterface $connection, $isAggregat } /** + * Get stock configuration + * * @return StockConfigurationInterface * * @deprecated 100.1.0 @@ -405,6 +410,8 @@ protected function getStockConfiguration() } /** + * Get query processor composite + * * @return QueryProcessorComposite */ private function getQueryProcessorComposite() From 9e95177e73b029e8d3f1a40752d9f80d4df04405 Mon Sep 17 00:00:00 2001 From: Sunil Patel <patelsunil42@gmail.com> Date: Tue, 2 Jul 2019 18:58:43 +0530 Subject: [PATCH 608/773] fix validation class for max-words --- lib/web/mage/validation.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/web/mage/validation.js b/lib/web/mage/validation.js index 619ad3fa72616..450cc86ba30f1 100644 --- a/lib/web/mage/validation.js +++ b/lib/web/mage/validation.js @@ -226,7 +226,7 @@ rules = { 'max-words': [ function (value, element, params) { - return this.optional(element) || $.mage.stripHtml(value).match(/\b\w+\b/g).length < params; + return this.optional(element) || $.mage.stripHtml(value).match(/\b\w+\b/g).length <= params; }, $.mage.__('Please enter {0} words or less.') ], From 8698a6959f5163ee26b4a900e8749e24ca33e319 Mon Sep 17 00:00:00 2001 From: OlgaVasyltsun <olga.vasyltsun@gmail.com> Date: Wed, 3 Jul 2019 10:32:47 +0300 Subject: [PATCH 609/773] MC-17865: Finalize @codingStandardsIgnoreFile elimination in CE --- .../system/config/testconnection.phtml | 1 - .../view/frontend/templates/search_data.phtml | 6 +- .../templates/dashboard/section.phtml | 1 - .../templates/directpost/iframe.phtml | 10 +- .../adminhtml/templates/directpost/info.phtml | 17 ++- .../order/view/info/fraud_details.phtml | 15 +-- .../view/adminhtml/templates/form/cc.phtml | 15 +-- .../adminhtml/templates/backup/list.phtml | 3 - .../view/adminhtml/templates/form/cc.phtml | 10 +- .../templates/form/paypal/vault.phtml | 4 +- .../view/adminhtml/templates/form/vault.phtml | 4 +- .../view/adminhtml/templates/default.phtml | 2 - .../view/frontend/templates/default.phtml | 2 - .../frontend/templates/js/components.phtml | 3 - .../view/adminhtml/templates/confirm.phtml | 3 - .../templates/product/widget/conditions.phtml | 2 - .../product/widget/content/grid.phtml | 38 +++--- .../adminhtml/templates/browser/content.phtml | 2 - .../templates/browser/content/files.phtml | 14 +- .../templates/browser/content/uploader.phtml | 2 - .../adminhtml/templates/browser/tree.phtml | 4 +- .../page/edit/form/renderer/content.phtml | 7 +- .../Cms/view/frontend/templates/content.phtml | 3 - .../Cms/view/frontend/templates/meta.phtml | 7 +- .../page/system/config/robots/reset.phtml | 8 +- .../view/frontend/templates/form.phtml | 9 +- .../frontend/templates/html/notices.phtml | 4 +- .../view/adminhtml/templates/edit/js.phtml | 3 - .../create/address/form/renderer/vat.phtml | 12 +- .../templates/system/config/validatevat.phtml | 2 - .../view/adminhtml/templates/tab/cart.phtml | 124 +++++++++--------- .../adminhtml/templates/tab/newsletter.phtml | 3 - .../templates/tab/view/personal_info.phtml | 6 +- .../adminhtml/templates/tab/view/sales.phtml | 54 ++++---- .../account/authentication-popup.phtml | 2 - .../frontend/templates/account/customer.phtml | 11 +- .../templates/account/dashboard/address.phtml | 2 - .../templates/account/dashboard/info.phtml | 8 +- .../account/link/authorization.phtml | 2 - .../templates/account/link/back.phtml | 3 - .../templates/additionalinfocustomer.phtml | 5 +- .../frontend/templates/address/book.phtml | 10 +- .../frontend/templates/address/edit.phtml | 40 +++--- .../frontend/templates/address/grid.phtml | 32 +++-- .../templates/form/confirmation.phtml | 2 - .../view/frontend/templates/form/edit.phtml | 22 ++-- .../templates/form/forgotpassword.phtml | 2 - .../view/frontend/templates/form/login.phtml | 6 +- .../frontend/templates/form/newsletter.phtml | 4 +- .../frontend/templates/form/register.phtml | 52 ++++---- .../form/resetforgottenpassword.phtml | 4 +- .../frontend/templates/js/components.phtml | 3 - .../js/customer-data/invalidation-rules.phtml | 1 - .../view/frontend/templates/newcustomer.phtml | 4 +- .../frontend/templates/widget/company.phtml | 8 +- .../view/frontend/templates/widget/dob.phtml | 2 - .../view/frontend/templates/widget/fax.phtml | 8 +- .../frontend/templates/widget/gender.phtml | 12 +- .../view/frontend/templates/widget/name.phtml | 44 +++---- .../frontend/templates/widget/taxvat.phtml | 6 +- .../frontend/templates/widget/telephone.phtml | 8 +- .../templates/js/optional_zip_countries.phtml | 3 +- .../view/frontend/templates/currency.phtml | 51 ++++--- .../frontend/templates/currency/switch.phtml | 2 - .../templates/attribute/edit/js.phtml | 6 +- .../adminhtml/templates/template/edit.phtml | 12 +- .../adminhtml/templates/template/list.phtml | 3 - .../templates/preview/iframeswitcher.phtml | 2 - .../adminhtml/templates/preview/store.phtml | 19 ++- .../adminhtml/templates/problem/list.phtml | 6 +- .../view/adminhtml/templates/queue/edit.phtml | 6 +- .../view/adminhtml/templates/queue/list.phtml | 3 - .../adminhtml/templates/subscriber/list.phtml | 6 +- .../adminhtml/templates/template/edit.phtml | 2 - .../adminhtml/templates/template/list.phtml | 3 - .../frontend/templates/js/components.phtml | 3 - .../view/frontend/templates/subscribe.phtml | 3 - .../templates/form/banktransfer.phtml | 3 +- .../templates/form/cashondelivery.phtml | 4 +- .../adminhtml/templates/form/checkmo.phtml | 5 +- .../templates/form/purchaseorder.phtml | 1 - .../adminhtml/templates/info/checkmo.phtml | 7 +- .../templates/info/pdf/checkmo.phtml | 7 +- .../base/templates/info/pdf/checkmo.phtml | 7 +- .../templates/form/banktransfer.phtml | 3 +- .../templates/form/cashondelivery.phtml | 4 +- .../frontend/templates/form/checkmo.phtml | 7 +- .../templates/form/purchaseorder.phtml | 1 - .../frontend/templates/info/checkmo.phtml | 7 +- .../frontend/templates/js/components.phtml | 2 - .../view/adminhtml/templates/form/cc.phtml | 15 +-- .../adminhtml/templates/info/default.phtml | 5 +- .../templates/info/instructions.phtml | 3 +- .../templates/info/pdf/default.phtml | 5 +- .../templates/info/substitution.phtml | 1 - .../templates/transparent/form.phtml | 16 +-- .../templates/transparent/iframe.phtml | 13 +- .../templates/transparent/info.phtml | 2 - .../base/templates/info/pdf/default.phtml | 5 +- .../view/frontend/templates/form/cc.phtml | 15 +-- .../frontend/templates/info/default.phtml | 6 +- .../templates/info/instructions.phtml | 3 +- .../frontend/templates/info/pdf/default.phtml | 5 +- .../frontend/templates/transparent/form.phtml | 18 ++- .../templates/transparent/iframe.phtml | 14 +- .../frontend/templates/transparent/info.phtml | 2 - .../templates/billing/agreement/form.phtml | 3 +- .../templates/payflowpro/vault.phtml | 12 +- .../payment/form/billing/agreement.phtml | 3 +- .../system/config/fieldset/hint.phtml | 12 +- .../system/config/payflowlink/advanced.phtml | 1 - .../system/config/payflowlink/info.phtml | 1 - .../templates/transparent/form.phtml | 18 ++- .../templates/transparent/iframe.phtml | 13 +- .../templates/billing/agreement/view.phtml | 23 ++-- .../templates/billing/agreements.phtml | 13 +- .../checkout/onepage/review/totals.phtml | 16 +-- .../frontend/templates/express/review.phtml | 43 +++--- .../templates/express/review/details.phtml | 3 +- .../express/review/shipping/method.phtml | 15 +-- .../frontend/templates/express/shortcut.phtml | 3 +- .../express/shortcut/container.phtml | 3 +- .../templates/express/shortcut_button.phtml | 2 - .../view/frontend/templates/hss/info.phtml | 2 +- .../frontend/templates/js/components.phtml | 2 - .../templates/payflowadvanced/info.phtml | 1 - .../payment/form/billing/agreement.phtml | 3 +- .../frontend/templates/payment/mark.phtml | 1 - .../frontend/templates/payment/redirect.phtml | 3 +- .../view/frontend/templates/additional.phtml | 2 +- .../view/frontend/templates/remember_me.phtml | 4 +- .../view/frontend/templates/email/price.phtml | 59 ++++----- .../view/frontend/templates/email/stock.phtml | 55 ++++---- .../templates/report/refresh/statistics.phtml | 3 - .../frontend/templates/js/components.phtml | 3 - .../product/widget/viewed/item.phtml | 10 +- .../column/compared_default_list.phtml | 9 +- .../compared/column/compared_names_list.phtml | 7 +- .../compared/content/compared_grid.phtml | 10 +- .../compared/content/compared_list.phtml | 12 +- .../viewed/column/viewed_default_list.phtml | 8 +- .../viewed/column/viewed_names_list.phtml | 6 +- .../widget/viewed/content/viewed_grid.phtml | 10 +- .../widget/viewed/content/viewed_list.phtml | 12 +- .../adminhtml/templates/rating/detailed.phtml | 14 +- .../adminhtml/templates/rating/form.phtml | 2 - .../adminhtml/templates/rating/options.phtml | 9 +- .../templates/rating/stars/detailed.phtml | 21 ++- .../templates/rating/stars/summary.phtml | 6 +- .../adminhtml/templates/rss/grid/link.phtml | 4 +- .../frontend/templates/customer/list.phtml | 14 +- .../frontend/templates/customer/recent.phtml | 10 +- .../frontend/templates/customer/view.phtml | 32 +++-- .../view/frontend/templates/detailed.phtml | 8 +- .../view/frontend/templates/empty.phtml | 2 - .../Review/view/frontend/templates/form.phtml | 14 +- .../frontend/templates/helper/summary.phtml | 58 ++++---- .../templates/helper/summary_short.phtml | 42 +++--- .../templates/product/view/count.phtml | 3 +- .../templates/product/view/list.phtml | 16 +-- .../templates/product/view/other.phtml | 2 - .../view/frontend/templates/redirect.phtml | 5 +- .../Review/view/frontend/templates/view.phtml | 18 ++- .../view/frontend/templates/robots.phtml | 2 +- .../Rss/view/frontend/templates/feeds.phtml | 8 +- .../templates/session/activity.phtml | 13 +- .../view/frontend/templates/send.phtml | 8 +- .../view/adminhtml/templates/case_info.phtml | 9 +- .../view/frontend/templates/fingerprint.phtml | 4 +- .../frontend/templates/switch/flags.phtml | 6 +- .../frontend/templates/switch/languages.phtml | 54 ++++---- .../frontend/templates/switch/stores.phtml | 48 ++++--- .../frontend/templates/swagger-ui/index.phtml | 5 +- .../templates/toolbar/class/add.phtml | 1 - .../templates/toolbar/class/save.phtml | 1 - .../templates/toolbar/rule/add.phtml | 1 - .../templates/toolbar/rule/save.phtml | 1 - .../templates/translate_inline.phtml | 2 - .../view/base/templates/translate.phtml | 4 +- .../frontend/templates/translate_inline.phtml | 2 - .../system/shipping/carrier_config.phtml | 4 +- .../view/adminhtml/templates/categories.phtml | 14 +- .../view/adminhtml/templates/edit.phtml | 4 +- .../view/adminhtml/templates/selector.phtml | 6 +- .../view/adminhtml/templates/form/vault.phtml | 2 - .../view/frontend/templates/cards_list.phtml | 5 +- .../view/frontend/templates/token_list.phtml | 5 +- .../catalog/category/widget/tree.phtml | 4 +- .../templates/instance/edit/layout.phtml | 8 +- .../customer/edit/tab/wishlist.phtml | 2 - .../frontend/templates/button/share.phtml | 4 +- .../frontend/templates/button/tocart.phtml | 4 +- .../frontend/templates/button/update.phtml | 4 +- .../renderer/actions/move_to_wishlist.phtml | 4 +- .../catalog/product/list/addto/wishlist.phtml | 4 +- .../catalog/product/view/addto/wishlist.phtml | 2 - .../view/frontend/templates/email/items.phtml | 72 +++++----- .../templates/item/column/actions.phtml | 6 +- .../frontend/templates/item/column/cart.phtml | 14 +- .../templates/item/column/comment.phtml | 4 +- .../frontend/templates/item/column/edit.phtml | 4 +- .../templates/item/column/image.phtml | 2 - .../frontend/templates/item/column/name.phtml | 2 - .../templates/item/column/price.phtml | 4 +- .../templates/item/column/remove.phtml | 2 - .../templates/item/configure/addto.phtml | 8 +- .../item/configure/addto/wishlist.phtml | 6 +- .../view/frontend/templates/item/list.phtml | 13 +- .../frontend/templates/js/components.phtml | 3 - .../view/frontend/templates/link.phtml | 2 - .../messages/addProductSuccessMessage.phtml | 2 +- .../removeWishlistItemSuccessMessage.phtml | 2 +- .../frontend/templates/options_list.phtml | 36 +++-- .../view/frontend/templates/rss/email.phtml | 6 +- .../frontend/templates/rss/wishlist.phtml | 4 +- .../view/frontend/templates/shared.phtml | 18 ++- .../view/frontend/templates/sharing.phtml | 4 +- .../view/frontend/templates/sidebar.phtml | 6 +- .../view/frontend/templates/view.phtml | 8 +- 219 files changed, 880 insertions(+), 1298 deletions(-) diff --git a/app/code/Magento/AdvancedSearch/view/adminhtml/templates/system/config/testconnection.phtml b/app/code/Magento/AdvancedSearch/view/adminhtml/templates/system/config/testconnection.phtml index 1d962cc6b329d..a583b2d51e461 100644 --- a/app/code/Magento/AdvancedSearch/view/adminhtml/templates/system/config/testconnection.phtml +++ b/app/code/Magento/AdvancedSearch/view/adminhtml/templates/system/config/testconnection.phtml @@ -3,7 +3,6 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile ?> <button class="scalable" type="button" id="<?= $block->getHtmlId() ?>" data-mage-init='{"testConnection":{ "url": "<?= $block->escapeUrl($block->getAjaxUrl()) ?>", diff --git a/app/code/Magento/AdvancedSearch/view/frontend/templates/search_data.phtml b/app/code/Magento/AdvancedSearch/view/frontend/templates/search_data.phtml index 053670ca19dac..1fa23cf3d624a 100644 --- a/app/code/Magento/AdvancedSearch/view/frontend/templates/search_data.phtml +++ b/app/code/Magento/AdvancedSearch/view/frontend/templates/search_data.phtml @@ -3,7 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile + /** * @var \Magento\AdvancedSearch\Block\SearchData $block */ @@ -11,14 +11,14 @@ <?php /** @var \Magento\Search\Model\QueryResult[] $data */ $data = $block->getItems(); -if (count($data)):?> +if (count($data)) : ?> <dl class="block"> <dt class="title"><?= $block->escapeHtml(__($block->getTitle())) ?></dt> <?php foreach ($data as $additionalInfo) : ?> <dd class="item"> <a href="<?= $block->escapeUrl($block->getLink($additionalInfo->getQueryText())) ?>" ><?= $block->escapeHtml($additionalInfo->getQueryText()) ?></a> - <?php if ($block->isShowResultsCount()): ?> + <?php if ($block->isShowResultsCount()) : ?> <span class="count"><?= /* @noEscape */ (int)$additionalInfo->getResultsCount() ?></span> <?php endif; ?> </dd> diff --git a/app/code/Magento/Analytics/view/adminhtml/templates/dashboard/section.phtml b/app/code/Magento/Analytics/view/adminhtml/templates/dashboard/section.phtml index a22c603b2a8b3..b056ffce1fa3d 100644 --- a/app/code/Magento/Analytics/view/adminhtml/templates/dashboard/section.phtml +++ b/app/code/Magento/Analytics/view/adminhtml/templates/dashboard/section.phtml @@ -3,7 +3,6 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile ?> <section class="dashboard-advanced-reports" data-index="dashboard-advanced-reports"> diff --git a/app/code/Magento/Authorizenet/view/adminhtml/templates/directpost/iframe.phtml b/app/code/Magento/Authorizenet/view/adminhtml/templates/directpost/iframe.phtml index 2ef93aca480c7..3088713989453 100644 --- a/app/code/Magento/Authorizenet/view/adminhtml/templates/directpost/iframe.phtml +++ b/app/code/Magento/Authorizenet/view/adminhtml/templates/directpost/iframe.phtml @@ -4,8 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** * @var $block \Magento\Authorizenet\Block\Transparent\Iframe */ @@ -15,15 +13,15 @@ $helper = $block->getHelper('adminhtml'); <html> <head> <script> - <?php if (isset($params['redirect'])): ?> + <?php if (isset($params['redirect'])) : ?> window.location="<?= $block->escapeUrl($params['redirect']) ?>"; <?php endif; ?> - <?php if (isset($params['redirect_parent'])): ?> + <?php if (isset($params['redirect_parent'])) : ?> window.top.location="<?= $block->escapeUrl($params['redirect_parent']) ?>"; <?php endif; ?> - <?php if (isset($params['error_msg'])): ?> + <?php if (isset($params['error_msg'])) : ?> window.top.directPostModel.showError(<?= /* @noEscape */ json_encode((array)$params['error_msg']) ?>); - <?php if (isset($params['x_invoice_num'])): ?> + <?php if (isset($params['x_invoice_num'])) : ?> window.top.directPostModel.successUrl="<?= $block->escapeUrl($helper->getSuccessOrderUrl($params)) ?>"; <?php endif; ?> <?php endif; ?> diff --git a/app/code/Magento/Authorizenet/view/adminhtml/templates/directpost/info.phtml b/app/code/Magento/Authorizenet/view/adminhtml/templates/directpost/info.phtml index 95040255f13c6..bec87738a83c1 100644 --- a/app/code/Magento/Authorizenet/view/adminhtml/templates/directpost/info.phtml +++ b/app/code/Magento/Authorizenet/view/adminhtml/templates/directpost/info.phtml @@ -4,7 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile /** * @var \Magento\Authorizenet\Block\Transparent\Iframe $block * @see \Magento\Authorizenet\Block\Transparent\Iframe @@ -12,7 +11,7 @@ $code = $block->escapeHtml($block->getMethodCode()); $method = $block->getMethod(); $controller = $block->escapeHtml($block->getRequest()->getControllerName()); -$orderUrl = $block->escapeUrl($this->helper('Magento\Authorizenet\Helper\Backend\Data')->getPlaceOrderAdminUrl()); +$orderUrl = $block->escapeUrl($block->getHelper('adminhtml')->getPlaceOrderAdminUrl()); $ccType = $block->getInfoData('cc_type'); $ccExpMonth = $block->getInfoData('cc_exp_month'); $ccExpYear = $block->getInfoData('cc_exp_year'); @@ -41,9 +40,9 @@ $ccExpYear = $block->getInfoData('cc_exp_year'); 'validate-cc-type-select':'#<?= /* @noEscape */ $code ?>_cc_number' }"> <option value=""><?= $block->escapeHtml(__('Please Select')) ?></option> - <?php foreach ($block->getCcAvailableTypes() as $typeCode => $typeName): ?> + <?php foreach ($block->getCcAvailableTypes() as $typeCode => $typeName) : ?> <option value="<?= $block->escapeHtml($typeCode) ?>" - <?php if ($typeCode == $ccType): ?>selected="selected"<?php endif; ?>> + <?php if ($typeCode == $ccType) : ?>selected="selected"<?php endif; ?>> <?= $block->escapeHtml($typeName) ?> </option> <?php endforeach; ?> @@ -81,9 +80,9 @@ $ccExpYear = $block->getInfoData('cc_exp_year'); 'required':true, 'validate-cc-exp':'#<?= /* @noEscape */ $code ?>_expiration_yr' }"> - <?php foreach ($block->getCcMonths() as $k => $v): ?> + <?php foreach ($block->getCcMonths() as $k => $v) : ?> <option value="<?= $block->escapeHtml($k) ?>" - <?php if ($k == $ccExpMonth): ?>selected="selected"<?php endif; ?>> + <?php if ($k == $ccExpMonth) : ?>selected="selected"<?php endif; ?>> <?= $block->escapeHtml($v) ?> </option> <?php endforeach; ?> @@ -93,9 +92,9 @@ $ccExpYear = $block->getInfoData('cc_exp_year'); class="admin__control-select admin__control-select-year" data-container="<?= /* @noEscape */ $code ?>-cc-year" data-validate="{required:true}"> - <?php foreach ($block->getCcYears() as $k => $v): ?> + <?php foreach ($block->getCcYears() as $k => $v) : ?> <option value="<?= /* @noEscape */ $k ? $block->escapeHtml($k) : '' ?>" - <?php if ($k == $ccExpYear): ?>selected="selected"<?php endif; ?>> + <?php if ($k == $ccExpYear) : ?>selected="selected"<?php endif; ?>> <?= $block->escapeHtml($v) ?> </option> <?php endforeach; ?> @@ -103,7 +102,7 @@ $ccExpYear = $block->getInfoData('cc_exp_year'); </div> </div> - <?php if ($block->hasVerification()): ?> + <?php if ($block->hasVerification()) : ?> <div class="admin__field _required field-cvv"> <label class="admin__field-label" for="<?= /* @noEscape */ $code ?>_cc_cid" diff --git a/app/code/Magento/Authorizenet/view/adminhtml/templates/order/view/info/fraud_details.phtml b/app/code/Magento/Authorizenet/view/adminhtml/templates/order/view/info/fraud_details.phtml index ac91fa30bfbe0..15325e15de1e1 100644 --- a/app/code/Magento/Authorizenet/view/adminhtml/templates/order/view/info/fraud_details.phtml +++ b/app/code/Magento/Authorizenet/view/adminhtml/templates/order/view/info/fraud_details.phtml @@ -4,7 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile /** * @var \Magento\Authorizenet\Block\Adminhtml\Order\View\Info\FraudDetails $block */ @@ -12,41 +11,41 @@ $payment = $block->getPayment(); $fraudDetails = $payment->getAdditionalInformation('fraud_details'); ?> -<?php if (!empty($fraudDetails)): ?> +<?php if (!empty($fraudDetails)) : ?> <div class="admin__page-section-item-title"> <span class="title"><?= $block->escapeHtml(__('Fraud Detection ')) ?></span> </div> <div class="admin__page-section-item-content"> <div class="order-payment-additional"> - <?php if(!empty($fraudDetails['fds_filter_action'])): ?> + <?php if (!empty($fraudDetails['fds_filter_action'])) : ?> <?= $block->escapeHtml(__('FDS Filter Action')) ?>: <?= $block->escapeHtml($fraudDetails['fds_filter_action']) ?> </br> <?php endif; ?> - <?php if(!empty($fraudDetails['avs_response'])): ?> + <?php if (!empty($fraudDetails['avs_response'])) : ?> <?= $block->escapeHtml(__('AVS Response')) ?>: <?= $block->escapeHtml($fraudDetails['avs_response']) ?> </br> <?php endif; ?> - <?php if(!empty($fraudDetails['card_code_response'])): ?> + <?php if (!empty($fraudDetails['card_code_response'])) : ?> <?= $block->escapeHtml(__('Card Code Response')) ?>: <?= $block->escapeHtml($fraudDetails['card_code_response']) ?> </br> <?php endif; ?> - <?php if(!empty($fraudDetails['cavv_response']) || ($fraudDetails['cavv_response'] === 0)): ?> + <?php if (!empty($fraudDetails['cavv_response']) || ($fraudDetails['cavv_response'] === 0)) : ?> <?= $block->escapeHtml(__('CAVV Response')) ?>: <?= $block->escapeHtml($fraudDetails['cavv_response']) ?> </br> <?php endif; ?> - <?php if(!empty($fraudDetails['fraud_filters'])): ?> + <?php if (!empty($fraudDetails['fraud_filters'])) : ?> <strong><?= $block->escapeHtml(__('Fraud Filters')) ?>: </strong></br> - <?php foreach($fraudDetails['fraud_filters'] as $filter): ?> + <?php foreach ($fraudDetails['fraud_filters'] as $filter) : ?> <?= $block->escapeHtml($filter['name']) ?>: <?= $block->escapeHtml($filter['action']) ?> </br> diff --git a/app/code/Magento/AuthorizenetAcceptjs/view/adminhtml/templates/form/cc.phtml b/app/code/Magento/AuthorizenetAcceptjs/view/adminhtml/templates/form/cc.phtml index 045bd5cfd81b2..b757e55aaddee 100644 --- a/app/code/Magento/AuthorizenetAcceptjs/view/adminhtml/templates/form/cc.phtml +++ b/app/code/Magento/AuthorizenetAcceptjs/view/adminhtml/templates/form/cc.phtml @@ -4,7 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile /** * @var Magento\AuthorizenetAcceptjs\Block\Form $block */ @@ -23,8 +22,8 @@ $ccExpYear = $block->getInfoData('cc_exp_year'); <select id="<?= /* @noEscape */ $code ?>_cc_type" name="payment[cc_type]" class="required-entry validate-cc-type-select admin__control-select"> <option value=""></option> - <?php foreach ($block->getCcAvailableTypes() as $typeCode => $typeName): ?> - <option value="<?= $block->escapeHtml($typeCode) ?>" <?php if ($typeCode == $ccType): ?>selected="selected"<?php endif ?>> + <?php foreach ($block->getCcAvailableTypes() as $typeCode => $typeName) : ?> + <option value="<?= $block->escapeHtml($typeCode) ?>" <?php if ($typeCode == $ccType) : ?>selected="selected"<?php endif ?>> <?= $block->escapeHtml($typeName) ?> </option> <?php endforeach ?> @@ -48,18 +47,18 @@ $ccExpYear = $block->getInfoData('cc_exp_year'); <div class="admin__field-control"> <select id="<?= /* @noEscape */ $code ?>_cc_exp_month" name="payment[cc_exp_month]" class="admin__control-select admin__control-select-month validate-cc-exp required-entry"> - <?php foreach ($block->getCcMonths() as $k => $v): ?> + <?php foreach ($block->getCcMonths() as $k => $v) : ?> <option value="<?= $block->escapeHtml($k) ?>" - <?php if ($k == $ccExpMonth): ?>selected="selected"<?php endif ?>> + <?php if ($k == $ccExpMonth) : ?>selected="selected"<?php endif ?>> <?= $block->escapeHtml($v) ?> </option> <?php endforeach; ?> </select> <select id="<?= /* @noEscape */ $code ?>_cc_exp_year" name="payment[cc_exp_year]" class="admin__control-select admin__control-select-year required-entry"> - <?php foreach ($block->getCcYears() as $k => $v): ?> + <?php foreach ($block->getCcYears() as $k => $v) : ?> <option value="<?= /* @noEscape */ $k ? $block->escapeHtml($k) : '' ?>" - <?php if ($k == $ccExpYear): ?>selected="selected"<?php endif ?>> + <?php if ($k == $ccExpYear) : ?>selected="selected"<?php endif ?>> <?= $block->escapeHtml($v) ?> </option> <?php endforeach ?> @@ -67,7 +66,7 @@ $ccExpYear = $block->getInfoData('cc_exp_year'); </div> </div> - <?php if ($block->isCvvEnabled()): ?> + <?php if ($block->isCvvEnabled()) : ?> <div class="field-number required admin__field _required"> <label class="admin__field-label" for="<?= /* @noEscape */ $code ?>_cc_cid"> <span><?= $block->escapeHtml(__('Card Verification Number')) ?></span> diff --git a/app/code/Magento/Backup/view/adminhtml/templates/backup/list.phtml b/app/code/Magento/Backup/view/adminhtml/templates/backup/list.phtml index 9ac9dd496e066..4982953e314d3 100644 --- a/app/code/Magento/Backup/view/adminhtml/templates/backup/list.phtml +++ b/app/code/Magento/Backup/view/adminhtml/templates/backup/list.phtml @@ -3,9 +3,6 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ - -// @codingStandardsIgnoreFile - ?> <?= $block->getChildHtml('grid') ?> <?= $block->getGridHtml() ?> diff --git a/app/code/Magento/Braintree/view/adminhtml/templates/form/cc.phtml b/app/code/Magento/Braintree/view/adminhtml/templates/form/cc.phtml index 4c15fffa8189f..0d2599ff45f25 100644 --- a/app/code/Magento/Braintree/view/adminhtml/templates/form/cc.phtml +++ b/app/code/Magento/Braintree/view/adminhtml/templates/form/cc.phtml @@ -4,8 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var Magento\Braintree\Block\Form $block */ $code = $block->escapeHtml($block->getMethodCode()); @@ -22,9 +20,9 @@ $ccType = $block->getInfoData('cc_type'); <div class="admin__field-control control"> <select id="<?= /* @noEscape */ $code ?>_cc_type" name="payment[cc_type]" class="required-entry select admin__control-select validate-cc-type-select"> - <?php foreach ($block->getCcAvailableTypes() as $typeCode => $typeName): ?> + <?php foreach ($block->getCcAvailableTypes() as $typeCode => $typeName) : ?> <option value="<?= $block->escapeHtml($typeCode) ?>" - <?php if($typeCode == $ccType): ?> selected="selected"<?php endif; ?>> + <?php if ($typeCode == $ccType) : ?> selected="selected"<?php endif; ?>> <?= $block->escapeHtml($typeName) ?> </option> <?php endforeach; ?> @@ -61,7 +59,7 @@ $ccType = $block->getInfoData('cc_type'); </div> </div> </div> - <?php if($block->hasVerification()): ?> + <?php if ($block->hasVerification()) : ?> <div class="admin__field _required"> <label class="label admin__field-label"> <span><?= $block->escapeHtml(__('Card Verification Number')) ?></span> @@ -77,7 +75,7 @@ $ccType = $block->getInfoData('cc_type'); </div> <?php endif; ?> - <?php if($block->isVaultEnabled()): ?> + <?php if ($block->isVaultEnabled()) : ?> <div class="field-tooltip-content"> <input type="checkbox" id="<?= /* @noEscape */ $code ?>_vault" diff --git a/app/code/Magento/Braintree/view/adminhtml/templates/form/paypal/vault.phtml b/app/code/Magento/Braintree/view/adminhtml/templates/form/paypal/vault.phtml index 22a0f8d8c987d..132f053d3bf89 100644 --- a/app/code/Magento/Braintree/view/adminhtml/templates/form/paypal/vault.phtml +++ b/app/code/Magento/Braintree/view/adminhtml/templates/form/paypal/vault.phtml @@ -1,10 +1,10 @@ <?php -use Magento\Vault\Model\Ui\TokenUiComponentProviderInterface; /** * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile + +use Magento\Vault\Model\Ui\TokenUiComponentProviderInterface; /** @var \Magento\Framework\View\Element\Template $block */ $details = $block->getData(TokenUiComponentProviderInterface::COMPONENT_DETAILS); diff --git a/app/code/Magento/Braintree/view/adminhtml/templates/form/vault.phtml b/app/code/Magento/Braintree/view/adminhtml/templates/form/vault.phtml index 77d08dbc5273c..49ce2cc7c065c 100644 --- a/app/code/Magento/Braintree/view/adminhtml/templates/form/vault.phtml +++ b/app/code/Magento/Braintree/view/adminhtml/templates/form/vault.phtml @@ -1,10 +1,10 @@ <?php -use Magento\Vault\Model\Ui\TokenUiComponentProviderInterface; /** * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile + +use Magento\Vault\Model\Ui\TokenUiComponentProviderInterface; /** @var \Magento\Framework\View\Element\Template $block */ $details = $block->getData(TokenUiComponentProviderInterface::COMPONENT_DETAILS); diff --git a/app/code/Magento/Captcha/view/adminhtml/templates/default.phtml b/app/code/Magento/Captcha/view/adminhtml/templates/default.phtml index 1be4bd19cd4ba..88e0d5edc2a7d 100644 --- a/app/code/Magento/Captcha/view/adminhtml/templates/default.phtml +++ b/app/code/Magento/Captcha/view/adminhtml/templates/default.phtml @@ -4,8 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Captcha\Block\Captcha\DefaultCaptcha $block */ /** @var \Magento\Captcha\Model\DefaultModel $captcha */ diff --git a/app/code/Magento/Captcha/view/frontend/templates/default.phtml b/app/code/Magento/Captcha/view/frontend/templates/default.phtml index 6c9a5fe85f596..ead8c590eee94 100644 --- a/app/code/Magento/Captcha/view/frontend/templates/default.phtml +++ b/app/code/Magento/Captcha/view/frontend/templates/default.phtml @@ -4,8 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Captcha\Block\Captcha\DefaultCaptcha $block */ /** @var \Magento\Captcha\Model\DefaultModel $captcha */ diff --git a/app/code/Magento/Captcha/view/frontend/templates/js/components.phtml b/app/code/Magento/Captcha/view/frontend/templates/js/components.phtml index bad5acc209b5f..5902a9f25cc4b 100644 --- a/app/code/Magento/Captcha/view/frontend/templates/js/components.phtml +++ b/app/code/Magento/Captcha/view/frontend/templates/js/components.phtml @@ -3,8 +3,5 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ - -// @codingStandardsIgnoreFile - ?> <?= $block->getChildHtml() ?> diff --git a/app/code/Magento/CatalogUrlRewrite/view/adminhtml/templates/confirm.phtml b/app/code/Magento/CatalogUrlRewrite/view/adminhtml/templates/confirm.phtml index 698872054faec..800ecfd8a6e2f 100644 --- a/app/code/Magento/CatalogUrlRewrite/view/adminhtml/templates/confirm.phtml +++ b/app/code/Magento/CatalogUrlRewrite/view/adminhtml/templates/confirm.phtml @@ -3,9 +3,6 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ - -// @codingStandardsIgnoreFile - ?> <script> require([ diff --git a/app/code/Magento/CatalogWidget/view/adminhtml/templates/product/widget/conditions.phtml b/app/code/Magento/CatalogWidget/view/adminhtml/templates/product/widget/conditions.phtml index d40cc3dc6d9ba..0e21f9e42c995 100644 --- a/app/code/Magento/CatalogWidget/view/adminhtml/templates/product/widget/conditions.phtml +++ b/app/code/Magento/CatalogWidget/view/adminhtml/templates/product/widget/conditions.phtml @@ -4,8 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\CatalogWidget\Block\Product\Widget\Conditions $block */ $element = $block->getElement(); diff --git a/app/code/Magento/CatalogWidget/view/frontend/templates/product/widget/content/grid.phtml b/app/code/Magento/CatalogWidget/view/frontend/templates/product/widget/content/grid.phtml index 29efe8a8c1c6a..881d8b28dfaeb 100644 --- a/app/code/Magento/CatalogWidget/view/frontend/templates/product/widget/content/grid.phtml +++ b/app/code/Magento/CatalogWidget/view/frontend/templates/product/widget/content/grid.phtml @@ -5,11 +5,9 @@ */ use Magento\Framework\App\Action\Action; -// @codingStandardsIgnoreFile - /** @var \Magento\CatalogWidget\Block\Product\ProductsList $block */ ?> -<?php if ($exist = ($block->getProductCollection() && $block->getProductCollection()->getSize())): ?> +<?php if ($exist = ($block->getProductCollection() && $block->getProductCollection()->getSize())) : ?> <?php $type = 'widget-product-grid'; @@ -25,7 +23,7 @@ use Magento\Framework\App\Action\Action; $description = false; ?> <div class="block widget block-products-list <?= /* @noEscape */ $mode ?>"> - <?php if ($block->getTitle()): ?> + <?php if ($block->getTitle()) : ?> <div class="block-title"> <strong><?= $block->escapeHtml(__($block->getTitle())) ?></strong> </div> @@ -35,7 +33,7 @@ use Magento\Framework\App\Action\Action; <div class="products-<?= /* @noEscape */ $mode ?> <?= /* @noEscape */ $mode ?>"> <ol class="product-items <?= /* @noEscape */ $type ?>"> <?php $iterator = 1; ?> - <?php foreach ($items as $_item): ?> + <?php foreach ($items as $_item) : ?> <?= /* @noEscape */ ($iterator++ == 1) ? '<li class="product-item">' : '</li><li class="product-item">' ?> <div class="product-item-info"> <a href="<?= $block->escapeUrl($block->getProductUrl($_item)) ?>" class="product-item-photo"> @@ -49,7 +47,7 @@ use Magento\Framework\App\Action\Action; <?= $block->escapeHtml($_item->getName()) ?> </a> </strong> - <?php if ($templateType): ?> + <?php if ($templateType) : ?> <?= $block->getReviewsSummaryHtml($_item, $templateType) ?> <?php endif; ?> @@ -57,42 +55,42 @@ use Magento\Framework\App\Action\Action; <?= $block->getProductDetailsHtml($_item) ?> - <?php if ($showWishlist || $showCompare || $showCart): ?> + <?php if ($showWishlist || $showCompare || $showCart) : ?> <div class="product-item-inner"> <div class="product-item-actions"> - <?php if ($showCart): ?> + <?php if ($showCart) : ?> <div class="actions-primary"> - <?php if ($_item->isSaleable()): ?> + <?php if ($_item->isSaleable()) : ?> <?php $postParams = $block->getAddToCartPostParams($_item); ?> - <form data-role="tocart-form" data-product-sku="<?= $block->escapeHtml($_item->getSku()) ?>" action="<?= /* @NoEscape */ $postParams['action'] ?>" method="post"> - <input type="hidden" name="product" value="<?= /* @escapeNotVerified */ $postParams['data']['product'] ?>"> - <input type="hidden" name="<?= /* @escapeNotVerified */ Action::PARAM_NAME_URL_ENCODED ?>" value="<?= /* @escapeNotVerified */ $postParams['data'][Action::PARAM_NAME_URL_ENCODED] ?>"> + <form data-role="tocart-form" data-product-sku="<?= $block->escapeHtml($_item->getSku()) ?>" action="<?= $block->escapeUrl($postParams['action']) ?>" method="post"> + <input type="hidden" name="product" value="<?= $block->escapeHtmlAttr($postParams['data']['product']) ?>"> + <input type="hidden" name="<?= /* @noEscape */ Action::PARAM_NAME_URL_ENCODED ?>" value="<?= /* @noEscape */ $postParams['data'][Action::PARAM_NAME_URL_ENCODED] ?>"> <?= $block->getBlockHtml('formkey') ?> <button type="submit" title="<?= $block->escapeHtml(__('Add to Cart')) ?>" class="action tocart primary"> - <span><?= /* @escapeNotVerified */ __('Add to Cart') ?></span> + <span><?= $block->escapeHtml(__('Add to Cart')) ?></span> </button> </form> - <?php else: ?> - <?php if ($_item->getIsSalable()): ?> + <?php else : ?> + <?php if ($_item->getIsSalable()) : ?> <div class="stock available"><span><?= $block->escapeHtml(__('In stock')) ?></span></div> - <?php else: ?> + <?php else : ?> <div class="stock unavailable"><span><?= $block->escapeHtml(__('Out of stock')) ?></span></div> <?php endif; ?> <?php endif; ?> </div> <?php endif; ?> - <?php if ($showWishlist || $showCompare): ?> + <?php if ($showWishlist || $showCompare) : ?> <div class="actions-secondary" data-role="add-to-links"> - <?php if ($this->helper('Magento\Wishlist\Helper\Data')->isAllow() && $showWishlist): ?> + <?php if ($this->helper(\Magento\Wishlist\Helper\Data::class)->isAllow() && $showWishlist) : ?> <a href="#" data-post='<?= /* @noEscape */ $block->getAddToWishlistParams($_item) ?>' class="action towishlist" data-action="add-to-wishlist" title="<?= $block->escapeHtmlAttr(__('Add to Wish List')) ?>"> <span><?= $block->escapeHtml(__('Add to Wish List')) ?></span> </a> <?php endif; ?> - <?php if ($block->getAddToCompareUrl() && $showCompare): ?> - <?php $compareHelper = $this->helper('Magento\Catalog\Helper\Product\Compare');?> + <?php if ($block->getAddToCompareUrl() && $showCompare) : ?> + <?php $compareHelper = $this->helper(\Magento\Catalog\Helper\Product\Compare::class);?> <a href="#" class="action tocompare" data-post='<?= /* @noEscape */ $compareHelper->getPostDataParams($_item) ?>' title="<?= $block->escapeHtmlAttr(__('Add to Compare')) ?>"> <span><?= $block->escapeHtml(__('Add to Compare')) ?></span> </a> diff --git a/app/code/Magento/Cms/view/adminhtml/templates/browser/content.phtml b/app/code/Magento/Cms/view/adminhtml/templates/browser/content.phtml index ed376781dfaa2..5bba11cad7938 100644 --- a/app/code/Magento/Cms/view/adminhtml/templates/browser/content.phtml +++ b/app/code/Magento/Cms/view/adminhtml/templates/browser/content.phtml @@ -4,8 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var $block \Magento\Cms\Block\Adminhtml\Wysiwyg\Images\Content */ ?> diff --git a/app/code/Magento/Cms/view/adminhtml/templates/browser/content/files.phtml b/app/code/Magento/Cms/view/adminhtml/templates/browser/content/files.phtml index 44bd7d3ba3dda..ff3d5f24dd5a1 100644 --- a/app/code/Magento/Cms/view/adminhtml/templates/browser/content/files.phtml +++ b/app/code/Magento/Cms/view/adminhtml/templates/browser/content/files.phtml @@ -4,16 +4,14 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - - /** @var $block \Magento\Cms\Block\Adminhtml\Wysiwyg\Images\Content\Files */ +/** @var $block \Magento\Cms\Block\Adminhtml\Wysiwyg\Images\Content\Files */ $_width = $block->getImagesWidth(); $_height = $block->getImagesHeight(); ?> -<?php if ($block->getFilesCount() > 0): ?> - <?php foreach ($block->getFiles() as $file): ?> +<?php if ($block->getFilesCount() > 0) : ?> + <?php foreach ($block->getFiles() as $file) : ?> <div data-row="file" class="filecnt" @@ -22,16 +20,16 @@ $_height = $block->getImagesHeight(); data-mime-type="<?= $block->escapeHtmlAttr($file->getMimeType()) ?>" > <p class="nm" style="height:<?= $block->escapeHtmlAttr($_height) ?>px;"> - <?php if ($block->getFileThumbUrl($file)):?> + <?php if ($block->getFileThumbUrl($file)) : ?> <img src="<?= $block->escapeHtmlAttr($block->getFileThumbUrl($file)) ?>" alt="<?= $block->escapeHtmlAttr($block->getFileName($file)) ?>"/> <?php endif; ?> </p> - <?php if ($block->getFileWidth($file)): ?> + <?php if ($block->getFileWidth($file)) : ?> <small><?= $block->escapeHtml($block->getFileWidth($file)) ?>x<?= $block->escapeHtml($block->getFileHeight($file)) ?> <?= $block->escapeHtml(__('px.')) ?></small><br/> <?php endif; ?> <small><?= $block->escapeHtml($block->getFileShortName($file)) ?></small> </div> <?php endforeach; ?> -<?php else: ?> +<?php else : ?> <div class="empty"><?= $block->escapeHtml(__('No files found')) ?></div> <?php endif; ?> diff --git a/app/code/Magento/Cms/view/adminhtml/templates/browser/content/uploader.phtml b/app/code/Magento/Cms/view/adminhtml/templates/browser/content/uploader.phtml index 414d42cb45382..2f789763ded44 100644 --- a/app/code/Magento/Cms/view/adminhtml/templates/browser/content/uploader.phtml +++ b/app/code/Magento/Cms/view/adminhtml/templates/browser/content/uploader.phtml @@ -4,8 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var $block \Magento\Cms\Block\Adminhtml\Wysiwyg\Images\Content\Uploader */ $filters = $block->getConfig()->getFilters() ?? []; diff --git a/app/code/Magento/Cms/view/adminhtml/templates/browser/tree.phtml b/app/code/Magento/Cms/view/adminhtml/templates/browser/tree.phtml index 4f0ba000c1d12..9603bb4f1a412 100644 --- a/app/code/Magento/Cms/view/adminhtml/templates/browser/tree.phtml +++ b/app/code/Magento/Cms/view/adminhtml/templates/browser/tree.phtml @@ -4,8 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Cms\Block\Adminhtml\Wysiwyg\Images\Tree $block */ ?> <div class="tree-panel" > @@ -16,6 +14,6 @@ <a onclick="jQuery('[data-role=tree]').jstree('open_all');"><?= $block->escapeHtml(__('Expand All')) ?></a> </div> </div> - <div data-role="tree" data-mage-init='<?= $block->escapeHtml($this->helper('Magento\Framework\Json\Helper\Data')->jsonEncode($block->getTreeWidgetOptions())) ?>'> + <div data-role="tree" data-mage-init='<?= $block->escapeHtml($this->helper(\Magento\Framework\Json\Helper\Data::class)->jsonEncode($block->getTreeWidgetOptions())) ?>'> </div> </div> diff --git a/app/code/Magento/Cms/view/adminhtml/templates/page/edit/form/renderer/content.phtml b/app/code/Magento/Cms/view/adminhtml/templates/page/edit/form/renderer/content.phtml index c773750e5d6c6..54fe4c71fb98a 100644 --- a/app/code/Magento/Cms/view/adminhtml/templates/page/edit/form/renderer/content.phtml +++ b/app/code/Magento/Cms/view/adminhtml/templates/page/edit/form/renderer/content.phtml @@ -3,14 +3,11 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ - -// @codingStandardsIgnoreFile - ?> <?php $_element = $block->getElement() ?> -<?php if (!$_element->getNoDisplay()): ?> +<?php if (!$_element->getNoDisplay()) : ?> <div class="cms-manage-content-actions"> - <?= trim($_element->getElementHtml()) ?> + <?= /* @noEscape */ trim($_element->getElementHtml()) ?> </div> <?php endif; ?> diff --git a/app/code/Magento/Cms/view/frontend/templates/content.phtml b/app/code/Magento/Cms/view/frontend/templates/content.phtml index d3baf14444762..f83edeb9dee61 100644 --- a/app/code/Magento/Cms/view/frontend/templates/content.phtml +++ b/app/code/Magento/Cms/view/frontend/templates/content.phtml @@ -3,8 +3,5 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ - -// @codingStandardsIgnoreFile - ?> <?= /* @noEscape */ $pageData->getPageContent() ?> diff --git a/app/code/Magento/Cms/view/frontend/templates/meta.phtml b/app/code/Magento/Cms/view/frontend/templates/meta.phtml index 3c03fa7d9ae67..40820ba37e7c6 100644 --- a/app/code/Magento/Cms/view/frontend/templates/meta.phtml +++ b/app/code/Magento/Cms/view/frontend/templates/meta.phtml @@ -3,13 +3,10 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ - -// @codingStandardsIgnoreFile - ?> -<?php if ($pageData->getPageMetaKeywords()): ?> +<?php if ($pageData->getPageMetaKeywords()) : ?> <meta name="keywords" content="<?= /* @noEscape */ $pageData->getPageMetaKeywords() ?>"/> <?php endif; ?> -<?php if ($pageData->getPageMetaDescription()): ?> +<?php if ($pageData->getPageMetaDescription()) : ?> <meta name="description" content="<?= /* @noEscape */ $pageData->getPageMetaDescription() ?>"/> <?php endif; ?> diff --git a/app/code/Magento/Config/view/adminhtml/templates/page/system/config/robots/reset.phtml b/app/code/Magento/Config/view/adminhtml/templates/page/system/config/robots/reset.phtml index e8082dae94d98..49a75d36fd8a5 100644 --- a/app/code/Magento/Config/view/adminhtml/templates/page/system/config/robots/reset.phtml +++ b/app/code/Magento/Config/view/adminhtml/templates/page/system/config/robots/reset.phtml @@ -4,14 +4,12 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** * @deprecated * @var $block \Magento\Backend\Block\Page\System\Config\Robots\Reset * @var $jsonHelper \Magento\Framework\Json\Helper\Data */ -$jsonHelper = $this->helper('Magento\Framework\Json\Helper\Data'); +$jsonHelper = $this->helper(\Magento\Framework\Json\Helper\Data::class); ?> <script> @@ -19,8 +17,8 @@ $jsonHelper = $this->helper('Magento\Framework\Json\Helper\Data'); 'jquery' ], function ($) { window.resetRobotsToDefault = function(){ - $('#design_search_engine_robots_custom_instructions').val(<?php - /* @escapeNotVerified */ echo $jsonHelper->jsonEncode($block->getRobotsDefaultCustomInstructions()) + $('#design_search_engine_robots_custom_instructions').val(<?= + /* @noEscape */ $jsonHelper->jsonEncode($block->getRobotsDefaultCustomInstructions()) ?>); } }); diff --git a/app/code/Magento/Contact/view/frontend/templates/form.phtml b/app/code/Magento/Contact/view/frontend/templates/form.phtml index d64a991bcafad..673bdc73840dc 100644 --- a/app/code/Magento/Contact/view/frontend/templates/form.phtml +++ b/app/code/Magento/Contact/view/frontend/templates/form.phtml @@ -4,7 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile /** @var \Magento\Contact\Block\ContactForm $block */ ?> <form class="form contact" @@ -19,25 +18,25 @@ <div class="field name required"> <label class="label" for="name"><span><?= $block->escapeHtml(__('Name')) ?></span></label> <div class="control"> - <input name="name" id="name" title="<?= $block->escapeHtmlAttr(__('Name')) ?>" value="<?= $block->escapeHtmlAttr($this->helper('Magento\Contact\Helper\Data')->getPostValue('name') ?: $this->helper('Magento\Contact\Helper\Data')->getUserName()) ?>" class="input-text" type="text" data-validate="{required:true}"/> + <input name="name" id="name" title="<?= $block->escapeHtmlAttr(__('Name')) ?>" value="<?= $block->escapeHtmlAttr($this->helper(\Magento\Contact\Helper\Data::class)->getPostValue('name') ?: $this->helper(\Magento\Contact\Helper\Data::class)->getUserName()) ?>" class="input-text" type="text" data-validate="{required:true}"/> </div> </div> <div class="field email required"> <label class="label" for="email"><span><?= $block->escapeHtml(__('Email')) ?></span></label> <div class="control"> - <input name="email" id="email" title="<?= $block->escapeHtmlAttr(__('Email')) ?>" value="<?= $block->escapeHtmlAttr($this->helper('Magento\Contact\Helper\Data')->getPostValue('email') ?: $this->helper('Magento\Contact\Helper\Data')->getUserEmail()) ?>" class="input-text" type="email" data-validate="{required:true, 'validate-email':true}"/> + <input name="email" id="email" title="<?= $block->escapeHtmlAttr(__('Email')) ?>" value="<?= $block->escapeHtmlAttr($this->helper(\Magento\Contact\Helper\Data::class)->getPostValue('email') ?: $this->helper(\Magento\Contact\Helper\Data::class)->getUserEmail()) ?>" class="input-text" type="email" data-validate="{required:true, 'validate-email':true}"/> </div> </div> <div class="field telephone"> <label class="label" for="telephone"><span><?= $block->escapeHtml(__('Phone Number')) ?></span></label> <div class="control"> - <input name="telephone" id="telephone" title="<?= $block->escapeHtmlAttr(__('Phone Number')) ?>" value="<?= $block->escapeHtmlAttr($this->helper('Magento\Contact\Helper\Data')->getPostValue('telephone')) ?>" class="input-text" type="text" /> + <input name="telephone" id="telephone" title="<?= $block->escapeHtmlAttr(__('Phone Number')) ?>" value="<?= $block->escapeHtmlAttr($this->helper(\Magento\Contact\Helper\Data::class)->getPostValue('telephone')) ?>" class="input-text" type="text" /> </div> </div> <div class="field comment required"> <label class="label" for="comment"><span><?= $block->escapeHtml(__('What’s on your mind?')) ?></span></label> <div class="control"> - <textarea name="comment" id="comment" title="<?= $block->escapeHtmlAttr(__('What’s on your mind?')) ?>" class="input-text" cols="5" rows="3" data-validate="{required:true}"><?= $block->escapeHtml($this->helper('Magento\Contact\Helper\Data')->getPostValue('comment')) ?></textarea> + <textarea name="comment" id="comment" title="<?= $block->escapeHtmlAttr(__('What’s on your mind?')) ?>" class="input-text" cols="5" rows="3" data-validate="{required:true}"><?= $block->escapeHtml($this->helper(\Magento\Contact\Helper\Data::class)->getPostValue('comment')) ?></textarea> </div> </div> <?= $block->getChildHtml('form.additional.info') ?> diff --git a/app/code/Magento/Cookie/view/frontend/templates/html/notices.phtml b/app/code/Magento/Cookie/view/frontend/templates/html/notices.phtml index c5cfda8cd7d15..8712f31e71b36 100644 --- a/app/code/Magento/Cookie/view/frontend/templates/html/notices.phtml +++ b/app/code/Magento/Cookie/view/frontend/templates/html/notices.phtml @@ -4,11 +4,9 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Cookie\Block\Html\Notices $block */ ?> -<?php if ($this->helper(\Magento\Cookie\Helper\Cookie::class)->isCookieRestrictionModeEnabled()): ?> +<?php if ($this->helper(\Magento\Cookie\Helper\Cookie::class)->isCookieRestrictionModeEnabled()) : ?> <div role="alertdialog" tabindex="-1" class="message global cookie" diff --git a/app/code/Magento/Customer/view/adminhtml/templates/edit/js.phtml b/app/code/Magento/Customer/view/adminhtml/templates/edit/js.phtml index 143b4be507af9..14aa3f4763e6c 100644 --- a/app/code/Magento/Customer/view/adminhtml/templates/edit/js.phtml +++ b/app/code/Magento/Customer/view/adminhtml/templates/edit/js.phtml @@ -3,7 +3,4 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ - -// @codingStandardsIgnoreFile - ?> diff --git a/app/code/Magento/Customer/view/adminhtml/templates/sales/order/create/address/form/renderer/vat.phtml b/app/code/Magento/Customer/view/adminhtml/templates/sales/order/create/address/form/renderer/vat.phtml index f55562682d9be..b792bc27f5b64 100644 --- a/app/code/Magento/Customer/view/adminhtml/templates/sales/order/create/address/form/renderer/vat.phtml +++ b/app/code/Magento/Customer/view/adminhtml/templates/sales/order/create/address/form/renderer/vat.phtml @@ -4,8 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Customer\Block\Adminhtml\Sales\Order\Address\Form\Renderer\Vat $block */ $_element = $block->getElement(); @@ -13,16 +11,16 @@ $_note = $_element->getNote(); $_class = $_element->getFieldsetHtmlClass(); $_validateButton = $block->getValidateButton(); ?> -<?php if (!$_element->getNoDisplay()): ?> +<?php if (!$_element->getNoDisplay()) : ?> <div class="admin__field field-vat-number"> - <?php if ($_element->getType() == 'hidden'): ?> + <?php if ($_element->getType() == 'hidden') : ?> <div class="hidden"><?= $_element->getElementHtml() ?></div> - <?php else: ?> + <?php else : ?> <?= $_element->getLabelHtml() ?> <div class="admin__field-control <?= /* @noEscape */ $_element->hasValueClass() ? $block->escapeHtmlAttr($_element->getValueClass()) : 'value' ?><?= $_class ? $block->escapeHtmlAttr($_class) . '-value' : '' ?>"> <?= $_element->getElementHtml() ?> - <?php if ($_note): ?> - <div class="admin__field-note<?= $_class ? " {$_class}-note" : '' ?>" id="note_<?= $block->escapeHtmlAttr($_element->getId()) ?>"> + <?php if ($_note) : ?> + <div class="admin__field-note<?= /* @noEscape */ $_class ? " {$block->escapeHtmlAttr($_class)}-note" : '' ?>" id="note_<?= $block->escapeHtmlAttr($_element->getId()) ?>"> <span><?= $block->escapeHtml($_note) ?></span> </div> <?php endif; ?> diff --git a/app/code/Magento/Customer/view/adminhtml/templates/system/config/validatevat.phtml b/app/code/Magento/Customer/view/adminhtml/templates/system/config/validatevat.phtml index 8eb3057d0a390..ab1671ede6e8a 100644 --- a/app/code/Magento/Customer/view/adminhtml/templates/system/config/validatevat.phtml +++ b/app/code/Magento/Customer/view/adminhtml/templates/system/config/validatevat.phtml @@ -4,8 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Customer\Block\Adminhtml\System\Config\Validatevat $block */ ?> <script> diff --git a/app/code/Magento/Customer/view/adminhtml/templates/tab/cart.phtml b/app/code/Magento/Customer/view/adminhtml/templates/tab/cart.phtml index 76fa53c12548d..434e5606cd032 100644 --- a/app/code/Magento/Customer/view/adminhtml/templates/tab/cart.phtml +++ b/app/code/Magento/Customer/view/adminhtml/templates/tab/cart.phtml @@ -4,11 +4,9 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /* @var \Magento\Customer\Block\Adminhtml\Edit\Tab\Cart $block */ ?> -<?php if ($block->getCartHeader()): ?> +<?php if ($block->getCartHeader()) : ?> <div class="content-header skip-header"> <table> <tr> @@ -19,76 +17,74 @@ <?php endif ?> <?= $block->getGridParentHtml() ?> <?php if ($block->canDisplayContainer()) : ?> -<?php - $listType = $block->getJsObjectName(); -?> -<script> -require([ - "Magento_Ui/js/modal/alert", - "Magento_Ui/js/modal/confirm", - "Magento_Catalog/catalog/product/composite/configure" -], function(alert, confirm){ + <?php $listType = $block->getJsObjectName(); ?> + <script> + require([ + "Magento_Ui/js/modal/alert", + "Magento_Ui/js/modal/confirm", + "Magento_Catalog/catalog/product/composite/configure" + ], function(alert, confirm){ -<?= $block->escapeJs($block->getJsObjectName()) ?>cartControl = { - reload: function (params) { - if (!params) { - params = {}; - } - <?= $block->escapeJs($block->getJsObjectName()) ?>.reloadParams = params; - <?= $block->escapeJs($block->getJsObjectName()) ?>.reload(); - <?= $block->escapeJs($block->getJsObjectName()) ?>.reloadParams = {}; - }, + <?= $block->escapeJs($block->getJsObjectName()) ?>cartControl = { + reload: function (params) { + if (!params) { + params = {}; + } + <?= $block->escapeJs($block->getJsObjectName()) ?>.reloadParams = params; + <?= $block->escapeJs($block->getJsObjectName()) ?>.reload(); + <?= $block->escapeJs($block->getJsObjectName()) ?>.reloadParams = {}; + }, - configureItem: function (itemId) { - productConfigure.setOnLoadIFrameCallback('<?= $block->escapeJs($listType) ?>', this.cbOnLoadIframe.bind(this)); - productConfigure.showItemConfiguration('<?= $block->escapeJs($listType) ?>', itemId); - return false; - }, + configureItem: function (itemId) { + productConfigure.setOnLoadIFrameCallback('<?= $block->escapeJs($listType) ?>', this.cbOnLoadIframe.bind(this)); + productConfigure.showItemConfiguration('<?= $block->escapeJs($listType) ?>', itemId); + return false; + }, - cbOnLoadIframe: function (response) { - if (!response.ok) { - return; - } - this.reload(); - }, + cbOnLoadIframe: function (response) { + if (!response.ok) { + return; + } + this.reload(); + }, - removeItem: function (itemId) { - var self = this; + removeItem: function (itemId) { + var self = this; - if (!itemId) { - alert({ - content: '<?= $block->escapeJs(__('No item specified.')) ?>' - }); + if (!itemId) { + alert({ + content: '<?= $block->escapeJs(__('No item specified.')) ?>' + }); - return false; - } + return false; + } - confirm({ - content: '<?= $block->escapeJs(__('Are you sure you want to remove this item?')) ?>', - actions: { - confirm: function(){ - self.reload({'delete':itemId}); + confirm({ + content: '<?= $block->escapeJs(__('Are you sure you want to remove this item?')) ?>', + actions: { + confirm: function(){ + self.reload({'delete':itemId}); + } } - } - }); - } -}; + }); + } + }; -<?php -$params = [ - 'customer_id' => $block->getCustomerId(), - 'website_id' => $block->getWebsiteId(), -]; -?> -productConfigure.addListType( - '<?= $block->escapeJs($listType) ?>', - { - urlFetch: '<?= $block->escapeJs($block->escapeUrl($block->getUrl('customer/cart_product_composite_cart/configure', $params))) ?>', - urlConfirm: '<?= $block->escapeJs($block->escapeUrl($block->getUrl('customer/cart_product_composite_cart/update', $params))) ?>' - } -); + <?php + $params = [ + 'customer_id' => $block->getCustomerId(), + 'website_id' => $block->getWebsiteId(), + ]; + ?> + productConfigure.addListType( + '<?= $block->escapeJs($listType) ?>', + { + urlFetch: '<?= $block->escapeJs($block->escapeUrl($block->getUrl('customer/cart_product_composite_cart/configure', $params))) ?>', + urlConfirm: '<?= $block->escapeJs($block->escapeUrl($block->getUrl('customer/cart_product_composite_cart/update', $params))) ?>' + } + ); -}); -</script> + }); + </script> <?php endif ?> <br /> diff --git a/app/code/Magento/Customer/view/adminhtml/templates/tab/newsletter.phtml b/app/code/Magento/Customer/view/adminhtml/templates/tab/newsletter.phtml index 30acb16c158d2..12d4902fb1892 100644 --- a/app/code/Magento/Customer/view/adminhtml/templates/tab/newsletter.phtml +++ b/app/code/Magento/Customer/view/adminhtml/templates/tab/newsletter.phtml @@ -3,9 +3,6 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ - -// @codingStandardsIgnoreFile - ?> <div class="entry-edit"> <?= $block->getForm()->getHtml() ?> diff --git a/app/code/Magento/Customer/view/adminhtml/templates/tab/view/personal_info.phtml b/app/code/Magento/Customer/view/adminhtml/templates/tab/view/personal_info.phtml index f43cb8ab5f0de..b3baeace89731 100644 --- a/app/code/Magento/Customer/view/adminhtml/templates/tab/view/personal_info.phtml +++ b/app/code/Magento/Customer/view/adminhtml/templates/tab/view/personal_info.phtml @@ -4,8 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Customer\Block\Adminhtml\Edit\Tab\View\PersonalInfo $block */ $lastLoginDateAdmin = $block->getLastLoginDate(); @@ -25,7 +23,7 @@ $createDateStore = $block->getStoreCreateDate(); <th><?= $block->escapeHtml(__('Last Logged In:')) ?></th> <td><?= $block->escapeHtml($lastLoginDateAdmin) ?> (<?= $block->escapeHtml($block->getCurrentStatus()) ?>)</td> </tr> - <?php if ($lastLoginDateAdmin != $lastLoginDateStore): ?> + <?php if ($lastLoginDateAdmin != $lastLoginDateStore) : ?> <tr> <th><?= $block->escapeHtml(__('Last Logged In (%1):', $block->getStoreLastLoginDateTimezone())) ?></th> <td><?= $block->escapeHtml($lastLoginDateStore) ?> (<?= $block->escapeHtml($block->getCurrentStatus()) ?>)</td> @@ -43,7 +41,7 @@ $createDateStore = $block->getStoreCreateDate(); <th><?= $block->escapeHtml(__('Account Created:')) ?></th> <td><?= $block->escapeHtml($createDateAdmin) ?></td> </tr> - <?php if ($createDateAdmin != $createDateStore): ?> + <?php if ($createDateAdmin != $createDateStore) : ?> <tr> <th><?= $block->escapeHtml(__('Account Created on (%1):', $block->getStoreCreateDateTimezone())) ?></th> <td><?= $block->escapeHtml($createDateStore) ?></td> diff --git a/app/code/Magento/Customer/view/adminhtml/templates/tab/view/sales.phtml b/app/code/Magento/Customer/view/adminhtml/templates/tab/view/sales.phtml index 12eae5cac9b1a..7b888c040463f 100644 --- a/app/code/Magento/Customer/view/adminhtml/templates/tab/view/sales.phtml +++ b/app/code/Magento/Customer/view/adminhtml/templates/tab/view/sales.phtml @@ -4,8 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Customer\Block\Adminhtml\Edit\Tab\View\Sales $block */ $singleStoreMode = $block->isSingleStoreMode(); @@ -19,7 +17,7 @@ $singleStoreMode = $block->isSingleStoreMode(); <table class="data-table"> <thead> <tr> - <?php if (!$singleStoreMode): ?> + <?php if (!$singleStoreMode) : ?> <th><?= $block->escapeHtml(__('Web Site')) ?></th> <th><?= $block->escapeHtml(__('Store')) ?></th> <th><?= $block->escapeHtml(__('Store View')) ?></th> @@ -28,7 +26,7 @@ $singleStoreMode = $block->isSingleStoreMode(); <th class="last"><?= $block->escapeHtml(__('Average Sale')) ?></th> </tr> </thead> - <?php if (!$singleStoreMode): ?> + <?php if (!$singleStoreMode) : ?> <tfoot> <tr> <td colspan="3"><strong><?= $block->escapeHtml(__('All Store Views')) ?></strong></td> @@ -37,40 +35,40 @@ $singleStoreMode = $block->isSingleStoreMode(); </tr> </tfoot> <?php endif; ?> - <?php if ($block->getRows()): ?> + <?php if ($block->getRows()) : ?> <tbody> <?php $_i = 0; ?> - <?php foreach ($block->getRows() as $_websiteId => $_groups): ?> - <?php $_websiteRow = false; ?> - <?php foreach ($_groups as $_groupId => $_stores): ?> - <?php $_groupRow = false; ?> - <?php foreach ($_stores as $_row): ?> - <?php if (!$singleStoreMode): ?> - <?php if ($_row->getStoreId() == 0): ?> - <td colspan="3"><?= $block->escapeHtml($_row->getStoreName()) ?></td> - <?php else: ?> - <tr<?= ($_i++ % 2 ? ' class="even"' : '') ?>> - <?php if (!$_websiteRow): ?> - <td rowspan="<?= $block->escapeHtmlAttr($block->getWebsiteCount($_websiteId)) ?>"><?= $block->escapeHtml($_row->getWebsiteName()) ?></td> - <?php $_websiteRow = true; ?> + <?php foreach ($block->getRows() as $_websiteId => $_groups) : ?> + <?php $_websiteRow = false; ?> + <?php foreach ($_groups as $_groupId => $_stores) : ?> + <?php $_groupRow = false; ?> + <?php foreach ($_stores as $_row) : ?> + <?php if (!$singleStoreMode) : ?> + <?php if ($_row->getStoreId() == 0) : ?> + <td colspan="3"><?= $block->escapeHtml($_row->getStoreName()) ?></td> + <?php else : ?> + <tr<?= ($_i++ % 2 ? ' class="even"' : '') ?>> + <?php if (!$_websiteRow) : ?> + <td rowspan="<?= $block->escapeHtmlAttr($block->getWebsiteCount($_websiteId)) ?>"><?= $block->escapeHtml($_row->getWebsiteName()) ?></td> + <?php $_websiteRow = true; ?> <?php endif; ?> - <?php if (!$_groupRow): ?> - <td rowspan="<?= count($_stores) ?>"><?= $block->escapeHtml($_row->getGroupName()) ?></td> - <?php $_groupRow = true; ?> + <?php if (!$_groupRow) : ?> + <td rowspan="<?= count($_stores) ?>"><?= $block->escapeHtml($_row->getGroupName()) ?></td> + <?php $_groupRow = true; ?> <?php endif; ?> - <td><?= $block->escapeHtml($_row->getStoreName()) ?></td> + <td><?= $block->escapeHtml($_row->getStoreName()) ?></td> <?php endif; ?> - <?php else: ?> - <tr> + <?php else : ?> + <tr> <?php endif; ?> - <td><?= $block->escapeHtml($block->formatCurrency($_row->getLifetime(), $_row->getWebsiteId())) ?></td> - <td><?= $block->escapeHtml($block->formatCurrency($_row->getAvgsale(), $_row->getWebsiteId())) ?></td> - </tr> + <td><?= $block->escapeHtml($block->formatCurrency($_row->getLifetime(), $_row->getWebsiteId())) ?></td> + <td><?= $block->escapeHtml($block->formatCurrency($_row->getAvgsale(), $_row->getWebsiteId())) ?></td> + </tr> <?php endforeach; ?> <?php endforeach; ?> <?php endforeach; ?> </tbody> - <?php else: ?> + <?php else : ?> <tbody> <tr class="hidden"><td colspan="<?= /* @noEscape */ $singleStoreMode ? 2 : 5 ?>"></td></tr> </tbody> diff --git a/app/code/Magento/Customer/view/frontend/templates/account/authentication-popup.phtml b/app/code/Magento/Customer/view/frontend/templates/account/authentication-popup.phtml index ca7393f2129e0..0d4cf3c721d14 100644 --- a/app/code/Magento/Customer/view/frontend/templates/account/authentication-popup.phtml +++ b/app/code/Magento/Customer/view/frontend/templates/account/authentication-popup.phtml @@ -4,8 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Customer\Block\Account\AuthenticationPopup $block */ ?> <div id="authenticationPopup" data-bind="scope:'authenticationPopup'" style="display: none;"> diff --git a/app/code/Magento/Customer/view/frontend/templates/account/customer.phtml b/app/code/Magento/Customer/view/frontend/templates/account/customer.phtml index b7b8796142de8..11c55b1dc557c 100644 --- a/app/code/Magento/Customer/view/frontend/templates/account/customer.phtml +++ b/app/code/Magento/Customer/view/frontend/templates/account/customer.phtml @@ -4,10 +4,9 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile /** @var Magento\Customer\Block\Account\Customer $block */ ?> -<?php if($block->customerLoggedIn()): ?> +<?php if ($block->customerLoggedIn()) : ?> <li class="customer-welcome"> <span class="customer-name" role="link" @@ -36,10 +35,10 @@ } } </script> - <?php if($block->getChildHtml()):?> - <div class="customer-menu" data-target="dropdown"> - <?= $block->getChildHtml() ?> - </div> + <?php if ($block->getChildHtml()) :?> + <div class="customer-menu" data-target="dropdown"> + <?= $block->getChildHtml() ?> + </div> <?php endif; ?> </li> <?php endif; ?> diff --git a/app/code/Magento/Customer/view/frontend/templates/account/dashboard/address.phtml b/app/code/Magento/Customer/view/frontend/templates/account/dashboard/address.phtml index 8186bae50940c..d306e8c7c734f 100644 --- a/app/code/Magento/Customer/view/frontend/templates/account/dashboard/address.phtml +++ b/app/code/Magento/Customer/view/frontend/templates/account/dashboard/address.phtml @@ -4,8 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Customer\Block\Account\Dashboard\Address $block */ ?> <div class="block block-dashboard-addresses"> diff --git a/app/code/Magento/Customer/view/frontend/templates/account/dashboard/info.phtml b/app/code/Magento/Customer/view/frontend/templates/account/dashboard/info.phtml index ac8e1298b29b9..c4b3c9d657f3d 100644 --- a/app/code/Magento/Customer/view/frontend/templates/account/dashboard/info.phtml +++ b/app/code/Magento/Customer/view/frontend/templates/account/dashboard/info.phtml @@ -4,8 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Customer\Block\Account\Dashboard\Info $block */ ?> <div class="block block-dashboard-info"> @@ -31,16 +29,16 @@ </a> </div> </div> - <?php if ($block->isNewsletterEnabled()): ?> + <?php if ($block->isNewsletterEnabled()) : ?> <div class="box box-newsletter"> <strong class="box-title"> <span><?= $block->escapeHtml(__('Newsletters')) ?></span> </strong> <div class="box-content"> <p> - <?php if ($block->getIsSubscribed()): ?> + <?php if ($block->getIsSubscribed()) : ?> <?= $block->escapeHtml(__('You are subscribed to "General Subscription".')) ?> - <?php else: ?> + <?php else : ?> <?= $block->escapeHtml(__('You aren\'t subscribed to our newsletter.')) ?> <?php endif; ?> </p> diff --git a/app/code/Magento/Customer/view/frontend/templates/account/link/authorization.phtml b/app/code/Magento/Customer/view/frontend/templates/account/link/authorization.phtml index 24657a6846cae..14827388e3894 100644 --- a/app/code/Magento/Customer/view/frontend/templates/account/link/authorization.phtml +++ b/app/code/Magento/Customer/view/frontend/templates/account/link/authorization.phtml @@ -4,8 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Customer\Block\Account\AuthorizationLink $block */ $dataPostParam = ''; diff --git a/app/code/Magento/Customer/view/frontend/templates/account/link/back.phtml b/app/code/Magento/Customer/view/frontend/templates/account/link/back.phtml index 20638b798d728..4816632ef9a1b 100644 --- a/app/code/Magento/Customer/view/frontend/templates/account/link/back.phtml +++ b/app/code/Magento/Customer/view/frontend/templates/account/link/back.phtml @@ -3,9 +3,6 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ - -// @codingStandardsIgnoreFile - ?> <div class="actions-toolbar"> <div class="secondary"><a class="action back" href="<?= $block->escapeUrl($block->getBackUrl()) ?>"><span><?= $block->escapeHtml(__('Back')) ?></span></a></div> diff --git a/app/code/Magento/Customer/view/frontend/templates/additionalinfocustomer.phtml b/app/code/Magento/Customer/view/frontend/templates/additionalinfocustomer.phtml index 74b13830c915e..3bfc1ca9c6382 100644 --- a/app/code/Magento/Customer/view/frontend/templates/additionalinfocustomer.phtml +++ b/app/code/Magento/Customer/view/frontend/templates/additionalinfocustomer.phtml @@ -3,9 +3,6 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ - -// @codingStandardsIgnoreFile - ?> <?php /** @@ -13,6 +10,6 @@ * */ ?> -<?php if ($this->helper('Magento\Checkout\Helper\Data')->isContextCheckout()): ?> +<?php if ($this->helper(\Magento\Checkout\Helper\Data::class)->isContextCheckout()) : ?> <input name="context" type="hidden" value="checkout" /> <?php endif; ?> diff --git a/app/code/Magento/Customer/view/frontend/templates/address/book.phtml b/app/code/Magento/Customer/view/frontend/templates/address/book.phtml index 9d09a090deac1..8e401f51509f6 100644 --- a/app/code/Magento/Customer/view/frontend/templates/address/book.phtml +++ b/app/code/Magento/Customer/view/frontend/templates/address/book.phtml @@ -4,14 +4,12 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Customer\Block\Address\Book $block */ ?> <div class="block block-addresses-default"> <div class="block-title"><strong><?= $block->escapeHtml(__('Default Addresses')) ?></strong></div> <div class="block-content"> - <?php if ($_pAddsses = $block->getDefaultBilling()): ?> + <?php if ($_pAddsses = $block->getDefaultBilling()) : ?> <div class="box box-address-billing"> <strong class="box-title"> <span><?= $block->escapeHtml(__('Default Billing Address')) ?></span> @@ -27,7 +25,7 @@ </a> </div> </div> - <?php else: ?> + <?php else : ?> <div class="box box-billing-address"> <strong class="box-title"><span><?= $block->escapeHtml(__('Default Billing Address')) ?></span></strong> <div class="box-content"> @@ -36,7 +34,7 @@ </div> <?php endif ?> - <?php if ($_pAddsses = $block->getDefaultShipping()): ?> + <?php if ($_pAddsses = $block->getDefaultShipping()) : ?> <div class="box box-address-shipping"> <strong class="box-title"> <span><?= $block->escapeHtml(__('Default Shipping Address')) ?></span> @@ -52,7 +50,7 @@ </a> </div> </div> - <?php else: ?> + <?php else : ?> <div class="box box-shipping-address"> <strong class="box-title"><span><?= $block->escapeHtml(__('Default Shipping Address')) ?></span></strong> <div class="box-content"> diff --git a/app/code/Magento/Customer/view/frontend/templates/address/edit.phtml b/app/code/Magento/Customer/view/frontend/templates/address/edit.phtml index df3f000410830..cf5b60568ad05 100644 --- a/app/code/Magento/Customer/view/frontend/templates/address/edit.phtml +++ b/app/code/Magento/Customer/view/frontend/templates/address/edit.phtml @@ -4,13 +4,11 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Customer\Block\Address\Edit $block */ ?> -<?php $_company = $block->getLayout()->createBlock('Magento\Customer\Block\Widget\Company') ?> -<?php $_telephone = $block->getLayout()->createBlock('Magento\Customer\Block\Widget\Telephone') ?> -<?php $_fax = $block->getLayout()->createBlock('Magento\Customer\Block\Widget\Fax') ?> +<?php $_company = $block->getLayout()->createBlock(\Magento\Customer\Block\Widget\Company::class) ?> +<?php $_telephone = $block->getLayout()->createBlock(\Magento\Customer\Block\Widget\Telephone::class) ?> +<?php $_fax = $block->getLayout()->createBlock(\Magento\Customer\Block\Widget\Fax::class) ?> <form class="form-address-edit" action="<?= $block->escapeUrl($block->getSaveUrl()) ?>" method="post" @@ -24,22 +22,22 @@ <input type="hidden" name="error_url" value="<?= $block->escapeUrl($block->getErrorUrl()) ?>"> <?= $block->getNameBlockHtml() ?> - <?php if ($_company->isEnabled()): ?> + <?php if ($_company->isEnabled()) : ?> <?= $_company->setCompany($block->getAddress()->getCompany())->toHtml() ?> <?php endif ?> - <?php if ($_telephone->isEnabled()): ?> + <?php if ($_telephone->isEnabled()) : ?> <?= $_telephone->setTelephone($block->getAddress()->getTelephone())->toHtml() ?> <?php endif ?> - <?php if ($_fax->isEnabled()): ?> + <?php if ($_fax->isEnabled()) : ?> <?= $_fax->setFax($block->getAddress()->getFax())->toHtml() ?> <?php endif ?> </fieldset> <fieldset class="fieldset"> <legend class="legend"><span><?= $block->escapeHtml(__('Address')) ?></span></legend><br> - <?php $_streetValidationClass = $this->helper('Magento\Customer\Helper\Address')->getAttributeValidationClass('street'); ?> + <?php $_streetValidationClass = $this->helper(\Magento\Customer\Helper\Address::class)->getAttributeValidationClass('street'); ?> <div class="field street required"> <label for="street_1" class="label"> <span><?= /* @noEscape */ $block->getAttributeData()->getFrontendLabel('street') ?></span> @@ -53,7 +51,7 @@ class="input-text <?= $block->escapeHtmlAttr($_streetValidationClass) ?>"/> <div class="nested"> <?php $_streetValidationClass = trim(str_replace('required-entry', '', $_streetValidationClass)); ?> - <?php for ($_i = 1, $_n = $this->helper('Magento\Customer\Helper\Address')->getStreetLines(); $_i < $_n; $_i++): ?> + <?php for ($_i = 1, $_n = $this->helper(\Magento\Customer\Helper\Address::class)->getStreetLines(); $_i < $_n; $_i++) : ?> <div class="field additional"> <label class="label" for="street_<?= /* @noEscape */ $_i + 1 ?>"> <span><?= $block->escapeHtml(__('Street Address %1', $_i + 1)) ?></span> @@ -71,7 +69,7 @@ </div> </div> - <?php if ($this->helper('Magento\Customer\Helper\Address')->isVatAttributeVisible()) : ?> + <?php if ($this->helper(\Magento\Customer\Helper\Address::class)->isVatAttributeVisible()) : ?> <div class="field taxvat"> <label class="label" for="vat_id"> <span><?= /* @noEscape */ $block->getAttributeData()->getFrontendLabel('vat_id') ?></span> @@ -81,7 +79,7 @@ name="vat_id" value="<?= $block->escapeHtmlAttr($block->getAddress()->getVatId()) ?>" title="<?= /* @noEscape */ $block->getAttributeData()->getFrontendLabel('vat_id') ?>" - class="input-text <?= $block->escapeHtmlAttr($this->helper('Magento\Customer\Helper\Address')->getAttributeValidationClass('vat_id')) ?>" + class="input-text <?= $block->escapeHtmlAttr($this->helper(\Magento\Customer\Helper\Address::class)->getAttributeValidationClass('vat_id')) ?>" id="vat_id"> </div> </div> @@ -93,7 +91,7 @@ name="city" value="<?= $block->escapeHtmlAttr($block->getAddress()->getCity()) ?>" title="<?= $block->escapeHtmlAttr(__('City')) ?>" - class="input-text <?= $block->escapeHtmlAttr($this->helper('Magento\Customer\Helper\Address')->getAttributeValidationClass('city')) ?>" + class="input-text <?= $block->escapeHtmlAttr($this->helper(\Magento\Customer\Helper\Address::class)->getAttributeValidationClass('city')) ?>" id="city"> </div> </div> @@ -112,7 +110,7 @@ name="region" value="<?= $block->escapeHtmlAttr($block->getRegion()) ?>" title="<?= /* @noEscape */ $block->getAttributeData()->getFrontendLabel('region') ?>" - class="input-text validate-not-number-first <?= $block->escapeHtmlAttr($this->helper('Magento\Customer\Helper\Address')->getAttributeValidationClass('region')) ?>"<?= !$block->getConfig('general/region/display_all') ? ' disabled="disabled"' : '' ?>/> + class="input-text validate-not-number-first <?= $block->escapeHtmlAttr($this->helper(\Magento\Customer\Helper\Address::class)->getAttributeValidationClass('region')) ?>"<?= !$block->getConfig('general/region/display_all') ? ' disabled="disabled"' : '' ?>/> </div> </div> <div class="field zip required"> @@ -125,7 +123,7 @@ value="<?= $block->escapeHtmlAttr($block->getAddress()->getPostcode()) ?>" title="<?= /* @noEscape */ $block->getAttributeData()->getFrontendLabel('postcode') ?>" id="zip" - class="input-text validate-zip-international <?= $block->escapeHtmlAttr($this->helper('Magento\Customer\Helper\Address')->getAttributeValidationClass('postcode')) ?>"> + class="input-text validate-zip-international <?= $block->escapeHtmlAttr($this->helper(\Magento\Customer\Helper\Address::class)->getAttributeValidationClass('postcode')) ?>"> <div role="alert" class="message warning" style="display:none"> <span></span> </div> @@ -138,33 +136,33 @@ </div> </div> - <?php if ($block->isDefaultBilling()): ?> + <?php if ($block->isDefaultBilling()) : ?> <div class="message info"> <span><?= $block->escapeHtml(__("It's a default billing address.")) ?></span> </div> - <?php elseif ($block->canSetAsDefaultBilling()): ?> + <?php elseif ($block->canSetAsDefaultBilling()) : ?> <div class="field choice set billing"> <input type="checkbox" id="primary_billing" name="default_billing" value="1" class="checkbox"> <label class="label" for="primary_billing"> <span><?= $block->escapeHtml(__('Use as my default billing address')) ?></span> </label> </div> - <?php else: ?> + <?php else : ?> <input type="hidden" name="default_billing" value="1" /> <?php endif; ?> - <?php if ($block->isDefaultShipping()): ?> + <?php if ($block->isDefaultShipping()) : ?> <div class="message info"> <span><?= $block->escapeHtml(__("It's a default shipping address.")) ?></span> </div> - <?php elseif ($block->canSetAsDefaultShipping()): ?> + <?php elseif ($block->canSetAsDefaultShipping()) : ?> <div class="field choice set shipping"> <input type="checkbox" id="primary_shipping" name="default_shipping" value="1" class="checkbox"> <label class="label" for="primary_shipping"> <span><?= $block->escapeHtml(__('Use as my default shipping address')) ?></span> </label> </div> - <?php else: ?> + <?php else : ?> <input type="hidden" name="default_shipping" value="1"> <?php endif; ?> </fieldset> diff --git a/app/code/Magento/Customer/view/frontend/templates/address/grid.phtml b/app/code/Magento/Customer/view/frontend/templates/address/grid.phtml index 7af5b5af2e7a1..0dc8214fd2894 100644 --- a/app/code/Magento/Customer/view/frontend/templates/address/grid.phtml +++ b/app/code/Magento/Customer/view/frontend/templates/address/grid.phtml @@ -4,8 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Customer\Block\Address\Grid $block */ $customerAddressView = $block->getData('customer_address'); ?> @@ -13,33 +11,33 @@ $customerAddressView = $block->getData('customer_address'); <div class="block block-addresses-list"> <div class="block-title"><strong><?= $block->escapeHtml(__('Additional Address Entries')) ?></strong></div> <div class="block-content"> - <?php if ($_pAddsses = $block->getAdditionalAddresses()): ?> + <?php if ($_pAddsses = $block->getAdditionalAddresses()) : ?> <div class="table-wrapper additional-addresses"> <table class="data table table-additional-addresses-items history" id="additional-addresses-table"> - <caption class="table-caption"><?= /* @escapeNotVerified */ __('Additional addresses') ?></caption> + <caption class="table-caption"><?= $block->escapeHtml(__('Additional addresses')) ?></caption> <thead> <tr> - <th scope="col" class="col firstname"><?= /* @escapeNotVerified */ __('First Name') ?></th> - <th scope="col" class="col lastname"><?= /* @escapeNotVerified */ __('Last Name') ?></th> - <th scope="col" class="col streetaddress"><?= /* @escapeNotVerified */ __('Street Address') ?></th> - <th scope="col" class="col city"><?= /* @escapeNotVerified */ __('City') ?></th> - <th scope="col" class="col country"><?= /* @escapeNotVerified */ __('Country') ?></th> - <th scope="col" class="col state"><?= /* @escapeNotVerified */ __('State') ?></th> - <th scope="col" class="col zip"><?= /* @escapeNotVerified */ __('Zip/Postal Code') ?></th> - <th scope="col" class="col phone"><?= /* @escapeNotVerified */ __('Phone') ?></th> + <th scope="col" class="col firstname"><?= $block->escapeHtml(__('First Name')) ?></th> + <th scope="col" class="col lastname"><?= $block->escapeHtml(__('Last Name')) ?></th> + <th scope="col" class="col streetaddress"><?= $block->escapeHtml(__('Street Address')) ?></th> + <th scope="col" class="col city"><?= $block->escapeHtml(__('City')) ?></th> + <th scope="col" class="col country"><?= $block->escapeHtml(__('Country')) ?></th> + <th scope="col" class="col state"><?= $block->escapeHtml(__('State')) ?></th> + <th scope="col" class="col zip"><?= $block->escapeHtml(__('Zip/Postal Code')) ?></th> + <th scope="col" class="col phone"><?= $block->escapeHtml(__('Phone')) ?></th> <th scope="col" class="col actions"> </th> </tr> </thead> <tbody> - <?php foreach ($_pAddsses as $address): ?> + <?php foreach ($_pAddsses as $address) : ?> <tr> <td data-th="<?= $block->escapeHtml(__('First Name')) ?>" class="col firstname"><?= $block->escapeHtml($address->getFirstname()) ?></td> <td data-th="<?= $block->escapeHtml(__('Last Name')) ?>" class="col lastname"><?= $block->escapeHtml($address->getLastname()) ?></td> <td data-th="<?= $block->escapeHtml(__('Street Address')) ?>" class="col streetaddress"><?= $block->escapeHtml($block->getStreetAddress($address)) ?></td> <td data-th="<?= $block->escapeHtml(__('City')) ?>" class="col city"><?= $block->escapeHtml($address->getCity()) ?></td> - <td data-th="<?= $block->escapeHtml(__('Country')) ?>" class="col country"><?= /* @escapeNotVerified */ $block->getCountryByCode($address->getCountryId()) ?></td> - <td data-th="<?= $block->escapeHtml(__('State')) ?>" class="col state"><?= /* @escapeNotVerified */ $address->getRegion()->getRegion() ?></td> + <td data-th="<?= $block->escapeHtml(__('Country')) ?>" class="col country"><?= $block->escapeHtml($block->getCountryByCode($address->getCountryId())) ?></td> + <td data-th="<?= $block->escapeHtml(__('State')) ?>" class="col state"><?= $block->escapeHtml($address->getRegion()->getRegion()) ?></td> <td data-th="<?= $block->escapeHtml(__('Zip/Postal Code')) ?>" class="col zip"><?= $block->escapeHtml($address->getPostcode()) ?></td> <td data-th="<?= $block->escapeHtml(__('Phone')) ?>" class="col phone"><?= $block->escapeHtml($address->getTelephone()) ?></td> <td data-th="<?= $block->escapeHtml(__('Actions')) ?>" class="col actions"> @@ -51,10 +49,10 @@ $customerAddressView = $block->getData('customer_address'); </tbody> </table> </div> - <?php if ($block->getChildHtml('pager')): ?> + <?php if ($block->getChildHtml('pager')) : ?> <div class="customer-addresses-toolbar toolbar bottom"><?= $block->getChildHtml('pager') ?></div> <?php endif ?> - <?php else: ?> + <?php else : ?> <p class="empty"><?= $block->escapeHtml(__('You have no other address entries in your address book.')) ?></p> <?php endif ?> </div> diff --git a/app/code/Magento/Customer/view/frontend/templates/form/confirmation.phtml b/app/code/Magento/Customer/view/frontend/templates/form/confirmation.phtml index 8edb21ac8e1e9..f558d305e70ab 100644 --- a/app/code/Magento/Customer/view/frontend/templates/form/confirmation.phtml +++ b/app/code/Magento/Customer/view/frontend/templates/form/confirmation.phtml @@ -4,8 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Framework\View\Element\Template $block */ ?> <form action="" method="post" id="form-validate" class="form send confirmation" data-mage-init='{"validation":{}}'> diff --git a/app/code/Magento/Customer/view/frontend/templates/form/edit.phtml b/app/code/Magento/Customer/view/frontend/templates/form/edit.phtml index 75c7d9cffedbe..2718f03909be2 100644 --- a/app/code/Magento/Customer/view/frontend/templates/form/edit.phtml +++ b/app/code/Magento/Customer/view/frontend/templates/form/edit.phtml @@ -4,26 +4,24 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Customer\Block\Form\Edit $block */ ?> <form class="form form-edit-account" action="<?= $block->escapeUrl($block->getUrl('customer/account/editPost')) ?>" method="post" id="form-validate" enctype="multipart/form-data" data-hasrequired="<?= $block->escapeHtmlAttr(__('* Required Fields')) ?>" autocomplete="off"> <fieldset class="fieldset info"> <?= $block->getBlockHtml('formkey') ?> <legend class="legend"><span><?= $block->escapeHtml(__('Account Information')) ?></span></legend><br> - <?= $block->getLayout()->createBlock('Magento\Customer\Block\Widget\Name')->setObject($block->getCustomer())->toHtml() ?> + <?= $block->getLayout()->createBlock(\Magento\Customer\Block\Widget\Name::class)->setObject($block->getCustomer())->toHtml() ?> - <?php $_dob = $block->getLayout()->createBlock('Magento\Customer\Block\Widget\Dob') ?> - <?php $_taxvat = $block->getLayout()->createBlock('Magento\Customer\Block\Widget\Taxvat') ?> - <?php $_gender = $block->getLayout()->createBlock('Magento\Customer\Block\Widget\Gender') ?> - <?php if ($_dob->isEnabled()): ?> + <?php $_dob = $block->getLayout()->createBlock(\Magento\Customer\Block\Widget\Dob::class) ?> + <?php $_taxvat = $block->getLayout()->createBlock(\Magento\Customer\Block\Widget\Taxvat::class) ?> + <?php $_gender = $block->getLayout()->createBlock(\Magento\Customer\Block\Widget\Gender::class) ?> + <?php if ($_dob->isEnabled()) : ?> <?= $_dob->setDate($block->getCustomer()->getDob())->toHtml() ?> <?php endif ?> - <?php if ($_taxvat->isEnabled()): ?> + <?php if ($_taxvat->isEnabled()) : ?> <?= $_taxvat->setTaxvat($block->getCustomer()->getTaxvat())->toHtml() ?> <?php endif ?> - <?php if ($_gender->isEnabled()): ?> + <?php if ($_gender->isEnabled()) : ?> <?= $_gender->setGender($block->getCustomer()->getGender())->toHtml() ?> <?php endif ?> <div class="field choice"> @@ -31,7 +29,7 @@ <label class="label" for="change-email"><span><?= $block->escapeHtml(__('Change Email')) ?></span></label> </div> <div class="field choice"> - <input type="checkbox" name="change_password" id="change-password" data-role="change-password" value="1" title="<?= $block->escapeHtmlAttr(__('Change Password')) ?>"<?php if ($block->getChangePassword()): ?> checked="checked"<?php endif; ?> class="checkbox" /> + <input type="checkbox" name="change_password" id="change-password" data-role="change-password" value="1" title="<?= $block->escapeHtmlAttr(__('Change Password')) ?>"<?php if ($block->getChangePassword()) : ?> checked="checked"<?php endif; ?> class="checkbox" /> <label class="label" for="change-password"><span><?= $block->escapeHtml(__('Change Password')) ?></span></label> </div> </fieldset> @@ -97,7 +95,7 @@ var ignore = <?= /* @noEscape */ $_dob->isEnabled() ? '\'input[id$="full"]\'' : 'null' ?>; dataForm.mage('validation', { - <?php if ($_dob->isEnabled()): ?> + <?php if ($_dob->isEnabled()) : ?> errorPlacement: function(error, element) { if (element.prop('id').search('full') !== -1) { var dobElement = $(element).parents('.customer-dob'), @@ -111,7 +109,7 @@ } }, ignore: ':hidden:not(' + ignore + ')' - <?php else: ?> + <?php else : ?> ignore: ignore ? ':hidden:not(' + ignore + ')' : ':hidden' <?php endif ?> }); diff --git a/app/code/Magento/Customer/view/frontend/templates/form/forgotpassword.phtml b/app/code/Magento/Customer/view/frontend/templates/form/forgotpassword.phtml index f8eb0bd44b681..be201afa8f66c 100644 --- a/app/code/Magento/Customer/view/frontend/templates/form/forgotpassword.phtml +++ b/app/code/Magento/Customer/view/frontend/templates/form/forgotpassword.phtml @@ -6,8 +6,6 @@ * @var $block \Magento\Customer\Block\Account\Forgotpassword */ -// @codingStandardsIgnoreFile - /** @var \Magento\Customer\Block\Account\Forgotpassword $block */ ?> <form class="form password forget" diff --git a/app/code/Magento/Customer/view/frontend/templates/form/login.phtml b/app/code/Magento/Customer/view/frontend/templates/form/login.phtml index d85e76e4cbc3f..ef74b0062c023 100644 --- a/app/code/Magento/Customer/view/frontend/templates/form/login.phtml +++ b/app/code/Magento/Customer/view/frontend/templates/form/login.phtml @@ -4,8 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Customer\Block\Form\Login $block */ ?> <div class="block block-customer-login"> @@ -24,13 +22,13 @@ <div class="field email required"> <label class="label" for="email"><span><?= $block->escapeHtml(__('Email')) ?></span></label> <div class="control"> - <input name="login[username]" value="<?= $block->escapeHtmlAttr($block->getUsername()) ?>" <?php if ($block->isAutocompleteDisabled()): ?> autocomplete="off"<?php endif; ?> id="email" type="email" class="input-text" title="<?= $block->escapeHtmlAttr(__('Email')) ?>" data-mage-init='{"mage/trim-input":{}}' data-validate="{required:true, 'validate-email':true}"> + <input name="login[username]" value="<?= $block->escapeHtmlAttr($block->getUsername()) ?>" <?php if ($block->isAutocompleteDisabled()) : ?> autocomplete="off"<?php endif; ?> id="email" type="email" class="input-text" title="<?= $block->escapeHtmlAttr(__('Email')) ?>" data-mage-init='{"mage/trim-input":{}}' data-validate="{required:true, 'validate-email':true}"> </div> </div> <div class="field password required"> <label for="pass" class="label"><span><?= $block->escapeHtml(__('Password')) ?></span></label> <div class="control"> - <input name="login[password]" type="password" <?php if ($block->isAutocompleteDisabled()): ?> autocomplete="off"<?php endif; ?> class="input-text" id="pass" title="<?= $block->escapeHtmlAttr(__('Password')) ?>" data-validate="{required:true}"> + <input name="login[password]" type="password" <?php if ($block->isAutocompleteDisabled()) : ?> autocomplete="off"<?php endif; ?> class="input-text" id="pass" title="<?= $block->escapeHtmlAttr(__('Password')) ?>" data-validate="{required:true}"> </div> </div> <?= $block->getChildHtml('form_additional_info') ?> diff --git a/app/code/Magento/Customer/view/frontend/templates/form/newsletter.phtml b/app/code/Magento/Customer/view/frontend/templates/form/newsletter.phtml index f7b7217a9b477..83059fab1b32d 100644 --- a/app/code/Magento/Customer/view/frontend/templates/form/newsletter.phtml +++ b/app/code/Magento/Customer/view/frontend/templates/form/newsletter.phtml @@ -4,8 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Customer\Block\Newsletter $block */ ?> <?= $block->getChildHtml('form_before') ?> @@ -14,7 +12,7 @@ <?= $block->getBlockHtml('formkey') ?> <legend class="legend"><span><?= $block->escapeHtml(__('Subscription option')) ?></span></legend><br> <div class="field choice"> - <input type="checkbox" name="is_subscribed" id="subscription" value="1" title="<?= $block->escapeHtmlAttr(__('General Subscription')) ?>"<?php if ($block->getIsSubscribed()): ?> checked="checked"<?php endif; ?> class="checkbox"> + <input type="checkbox" name="is_subscribed" id="subscription" value="1" title="<?= $block->escapeHtmlAttr(__('General Subscription')) ?>"<?php if ($block->getIsSubscribed()) : ?> checked="checked"<?php endif; ?> class="checkbox"> <label for="subscription" class="label"><span><?= $block->escapeHtml(__('General Subscription')) ?></span></label> </div> <?php /* Extensions placeholder */ ?> diff --git a/app/code/Magento/Customer/view/frontend/templates/form/register.phtml b/app/code/Magento/Customer/view/frontend/templates/form/register.phtml index f11177ae19f7c..da0bb6e4cbc8b 100644 --- a/app/code/Magento/Customer/view/frontend/templates/form/register.phtml +++ b/app/code/Magento/Customer/view/frontend/templates/form/register.phtml @@ -4,8 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Customer\Block\Form\Register $block */ ?> <?= $block->getChildHtml('form_fields_before') ?> @@ -17,52 +15,52 @@ <legend class="legend"><span><?= $block->escapeHtml(__('Personal Information')) ?></span></legend><br> <input type="hidden" name="success_url" value="<?= $block->escapeUrl($block->getSuccessUrl()) ?>"> <input type="hidden" name="error_url" value="<?= $block->escapeUrl($block->getErrorUrl()) ?>"> - <?= $block->getLayout()->createBlock('Magento\Customer\Block\Widget\Name')->setObject($block->getFormData())->setForceUseCustomerAttributes(true)->toHtml() ?> - <?php if ($block->isNewsletterEnabled()): ?> + <?= $block->getLayout()->createBlock(\Magento\Customer\Block\Widget\Name::class)->setObject($block->getFormData())->setForceUseCustomerAttributes(true)->toHtml() ?> + <?php if ($block->isNewsletterEnabled()) : ?> <div class="field choice newsletter"> - <input type="checkbox" name="is_subscribed" title="<?= $block->escapeHtmlAttr(__('Sign Up for Newsletter')) ?>" value="1" id="is_subscribed"<?php if ($block->getFormData()->getIsSubscribed()): ?> checked="checked"<?php endif; ?> class="checkbox"> + <input type="checkbox" name="is_subscribed" title="<?= $block->escapeHtmlAttr(__('Sign Up for Newsletter')) ?>" value="1" id="is_subscribed"<?php if ($block->getFormData()->getIsSubscribed()) : ?> checked="checked"<?php endif; ?> class="checkbox"> <label for="is_subscribed" class="label"><span><?= $block->escapeHtml(__('Sign Up for Newsletter')) ?></span></label> </div> <?php /* Extensions placeholder */ ?> <?= $block->getChildHtml('customer.form.register.newsletter') ?> <?php endif ?> - <?php $_dob = $block->getLayout()->createBlock('Magento\Customer\Block\Widget\Dob') ?> - <?php if ($_dob->isEnabled()): ?> + <?php $_dob = $block->getLayout()->createBlock(\Magento\Customer\Block\Widget\Dob::class) ?> + <?php if ($_dob->isEnabled()) : ?> <?= $_dob->setDate($block->getFormData()->getDob())->toHtml() ?> <?php endif ?> - <?php $_taxvat = $block->getLayout()->createBlock('Magento\Customer\Block\Widget\Taxvat') ?> - <?php if ($_taxvat->isEnabled()): ?> + <?php $_taxvat = $block->getLayout()->createBlock(\Magento\Customer\Block\Widget\Taxvat::class) ?> + <?php if ($_taxvat->isEnabled()) : ?> <?= $_taxvat->setTaxvat($block->getFormData()->getTaxvat())->toHtml() ?> <?php endif ?> - <?php $_gender = $block->getLayout()->createBlock('Magento\Customer\Block\Widget\Gender') ?> - <?php if ($_gender->isEnabled()): ?> + <?php $_gender = $block->getLayout()->createBlock(\Magento\Customer\Block\Widget\Gender::class) ?> + <?php if ($_gender->isEnabled()) : ?> <?= $_gender->setGender($block->getFormData()->getGender())->toHtml() ?> <?php endif ?> </fieldset> - <?php if ($block->getShowAddressFields()): ?> + <?php if ($block->getShowAddressFields()) : ?> <fieldset class="fieldset address"> <legend class="legend"><span><?= $block->escapeHtml(__('Address Information')) ?></span></legend><br> <input type="hidden" name="create_address" value="1" /> - <?php $_company = $block->getLayout()->createBlock('Magento\Customer\Block\Widget\Company') ?> - <?php if ($_company->isEnabled()): ?> + <?php $_company = $block->getLayout()->createBlock(\Magento\Customer\Block\Widget\Company::class) ?> + <?php if ($_company->isEnabled()) : ?> <?= $_company->setCompany($block->getFormData()->getCompany())->toHtml() ?> <?php endif ?> - <?php $_telephone = $block->getLayout()->createBlock('Magento\Customer\Block\Widget\Telephone') ?> - <?php if ($_telephone->isEnabled()): ?> + <?php $_telephone = $block->getLayout()->createBlock(\Magento\Customer\Block\Widget\Telephone::class) ?> + <?php if ($_telephone->isEnabled()) : ?> <?= $_telephone->setTelephone($block->getFormData()->getTelephone())->toHtml() ?> <?php endif ?> - <?php $_fax = $block->getLayout()->createBlock('Magento\Customer\Block\Widget\Fax') ?> - <?php if ($_fax->isEnabled()): ?> + <?php $_fax = $block->getLayout()->createBlock(\Magento\Customer\Block\Widget\Fax::class) ?> + <?php if ($_fax->isEnabled()) : ?> <?= $_fax->setFax($block->getFormData()->getFax())->toHtml() ?> <?php endif ?> - <?php $_streetValidationClass = $this->helper('Magento\Customer\Helper\Address')->getAttributeValidationClass('street'); ?> + <?php $_streetValidationClass = $this->helper(\Magento\Customer\Helper\Address::class)->getAttributeValidationClass('street'); ?> <div class="field street required"> <label for="street_1" class="label"><span><?= /* @noEscape */ $block->getAttributeData()->getFrontendLabel('street') ?></span></label> @@ -70,7 +68,7 @@ <input type="text" name="street[]" value="<?= $block->escapeHtmlAttr($block->getFormData()->getStreet(0)) ?>" title="<?= /* @noEscape */ $block->getAttributeData()->getFrontendLabel('street') ?>" id="street_1" class="input-text <?= $block->escapeHtmlAttr($_streetValidationClass) ?>"> <div class="nested"> <?php $_streetValidationClass = trim(str_replace('required-entry', '', $_streetValidationClass)); ?> - <?php for ($_i = 2, $_n = $this->helper('Magento\Customer\Helper\Address')->getStreetLines(); $_i <= $_n; $_i++): ?> + <?php for ($_i = 2, $_n = $this->helper(\Magento\Customer\Helper\Address::class)->getStreetLines(); $_i <= $_n; $_i++) : ?> <div class="field additional"> <label class="label" for="street_<?= /* @noEscape */ $_i ?>"> <span><?= $block->escapeHtml(__('Address')) ?></span> @@ -87,7 +85,7 @@ <div class="field required"> <label for="city" class="label"><span><?= /* @noEscape */ $block->getAttributeData()->getFrontendLabel('city') ?></span></label> <div class="control"> - <input type="text" name="city" value="<?= $block->escapeHtmlAttr($block->getFormData()->getCity()) ?>" title="<?= /* @noEscape */ $block->getAttributeData()->getFrontendLabel('city') ?>" class="input-text <?= $block->escapeHtmlAttr($this->helper('Magento\Customer\Helper\Address')->getAttributeValidationClass('city')) ?>" id="city"> + <input type="text" name="city" value="<?= $block->escapeHtmlAttr($block->getFormData()->getCity()) ?>" title="<?= /* @noEscape */ $block->getAttributeData()->getFrontendLabel('city') ?>" class="input-text <?= $block->escapeHtmlAttr($this->helper(\Magento\Customer\Helper\Address::class)->getAttributeValidationClass('city')) ?>" id="city"> </div> </div> @@ -97,14 +95,14 @@ <select id="region_id" name="region_id" title="<?= /* @noEscape */ $block->getAttributeData()->getFrontendLabel('region') ?>" class="validate-select region_id" style="display:none;"> <option value=""><?= $block->escapeHtml(__('Please select a region, state or province.')) ?></option> </select> - <input type="text" id="region" name="region" value="<?= $block->escapeHtml($block->getRegion()) ?>" title="<?= /* @noEscape */ $block->getAttributeData()->getFrontendLabel('region') ?>" class="input-text <?= $block->escapeHtmlAttr($this->helper('Magento\Customer\Helper\Address')->getAttributeValidationClass('region')) ?>" style="display:none;"> + <input type="text" id="region" name="region" value="<?= $block->escapeHtml($block->getRegion()) ?>" title="<?= /* @noEscape */ $block->getAttributeData()->getFrontendLabel('region') ?>" class="input-text <?= $block->escapeHtmlAttr($this->helper(\Magento\Customer\Helper\Address::class)->getAttributeValidationClass('region')) ?>" style="display:none;"> </div> </div> <div class="field zip required"> <label for="zip" class="label"><span><?= /* @noEscape */ $block->getAttributeData()->getFrontendLabel('postcode') ?></span></label> <div class="control"> - <input type="text" name="postcode" value="<?= $block->escapeHtmlAttr($block->getFormData()->getPostcode()) ?>" title="<?= /* @noEscape */ $block->getAttributeData()->getFrontendLabel('postcode') ?>" id="zip" class="input-text validate-zip-international <?= $block->escapeHtmlAttr($this->helper('Magento\Customer\Helper\Address')->getAttributeValidationClass('postcode')) ?>"> + <input type="text" name="postcode" value="<?= $block->escapeHtmlAttr($block->getFormData()->getPostcode()) ?>" title="<?= /* @noEscape */ $block->getAttributeData()->getFrontendLabel('postcode') ?>" id="zip" class="input-text validate-zip-international <?= $block->escapeHtmlAttr($this->helper(\Magento\Customer\Helper\Address::class)->getAttributeValidationClass('postcode')) ?>"> </div> </div> @@ -115,7 +113,7 @@ </div> </div> <?php $addressAttributes = $block->getChildBlock('customer_form_address_user_attributes');?> - <?php if ($addressAttributes): ?> + <?php if ($addressAttributes) : ?> <?php $addressAttributes->setEntityType('customer_address'); ?> <?php $addressAttributes->setFieldIdFormat('address:%1$s')->setFieldNameFormat('address[%1$s]');?> <?php $block->restoreSessionData($addressAttributes->getMetadataForm(), 'address');?> @@ -182,7 +180,7 @@ require([ var ignore = <?= /* @noEscape */ $_dob->isEnabled() ? '\'input[id$="full"]\'' : 'null' ?>; dataForm.mage('validation', { - <?php if ($_dob->isEnabled()): ?> + <?php if ($_dob->isEnabled()) : ?> errorPlacement: function(error, element) { if (element.prop('id').search('full') !== -1) { var dobElement = $(element).parents('.customer-dob'), @@ -196,14 +194,14 @@ require([ } }, ignore: ':hidden:not(' + ignore + ')' - <?php else: ?> + <?php else : ?> ignore: ignore ? ':hidden:not(' + ignore + ')' : ':hidden' <?php endif ?> }).find('input:text').attr('autocomplete', 'off'); }); </script> -<?php if ($block->getShowAddressFields()): ?> +<?php if ($block->getShowAddressFields()) : ?> <script type="text/x-magento-init"> { "#country": { diff --git a/app/code/Magento/Customer/view/frontend/templates/form/resetforgottenpassword.phtml b/app/code/Magento/Customer/view/frontend/templates/form/resetforgottenpassword.phtml index e79cea80ac838..76a755bab6e4d 100644 --- a/app/code/Magento/Customer/view/frontend/templates/form/resetforgottenpassword.phtml +++ b/app/code/Magento/Customer/view/frontend/templates/form/resetforgottenpassword.phtml @@ -4,13 +4,11 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Customer\Block\Account\Resetpassword $block */ ?> <form action="<?= $block->escapeUrl($block->getUrl('*/*/resetpasswordpost', ['_query' => ['token' => $block->getResetPasswordLinkToken()]])) ?>" method="post" - <?php if ($block->isAutocompleteDisabled()) :?> autocomplete="off"<?php endif; ?> + <?php if ($block->isAutocompleteDisabled()) : ?> autocomplete="off"<?php endif; ?> id="form-validate" class="form password reset" data-mage-init='{"validation":{}}'> diff --git a/app/code/Magento/Customer/view/frontend/templates/js/components.phtml b/app/code/Magento/Customer/view/frontend/templates/js/components.phtml index bad5acc209b5f..5902a9f25cc4b 100644 --- a/app/code/Magento/Customer/view/frontend/templates/js/components.phtml +++ b/app/code/Magento/Customer/view/frontend/templates/js/components.phtml @@ -3,8 +3,5 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ - -// @codingStandardsIgnoreFile - ?> <?= $block->getChildHtml() ?> diff --git a/app/code/Magento/Customer/view/frontend/templates/js/customer-data/invalidation-rules.phtml b/app/code/Magento/Customer/view/frontend/templates/js/customer-data/invalidation-rules.phtml index f8e9c3bdcf1d7..15d0f52265770 100644 --- a/app/code/Magento/Customer/view/frontend/templates/js/customer-data/invalidation-rules.phtml +++ b/app/code/Magento/Customer/view/frontend/templates/js/customer-data/invalidation-rules.phtml @@ -4,7 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile /* @var $block \Magento\Customer\Block\CustomerScopeData */ ?> <script type="text/x-magento-init"> diff --git a/app/code/Magento/Customer/view/frontend/templates/newcustomer.phtml b/app/code/Magento/Customer/view/frontend/templates/newcustomer.phtml index 83c803ac8d79c..3235fa56ccac8 100644 --- a/app/code/Magento/Customer/view/frontend/templates/newcustomer.phtml +++ b/app/code/Magento/Customer/view/frontend/templates/newcustomer.phtml @@ -4,11 +4,9 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Customer\Block\Form\Login\Info $block */ ?> -<?php if ($block->getRegistration()->isAllowed()): ?> +<?php if ($block->getRegistration()->isAllowed()) : ?> <div class="block block-new-customer"> <div class="block-title"> <strong id="block-new-customer-heading" role="heading" aria-level="2"><?= $block->escapeHtml(__('New Customers')) ?></strong> diff --git a/app/code/Magento/Customer/view/frontend/templates/widget/company.phtml b/app/code/Magento/Customer/view/frontend/templates/widget/company.phtml index 001a4107d9405..c38ef1a4aedd4 100644 --- a/app/code/Magento/Customer/view/frontend/templates/widget/company.phtml +++ b/app/code/Magento/Customer/view/frontend/templates/widget/company.phtml @@ -4,8 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Customer\Block\Widget\Company $block */ ?> <div class="field company <?= $block->isRequired() ? 'required' : '' ?>"> @@ -15,12 +13,12 @@ </span> </label> <div class="control"> - <?php + <?php $_validationClass = $block->escapeHtmlAttr( - $this->helper('Magento\Customer\Helper\Address') + $this->helper(\Magento\Customer\Helper\Address::class) ->getAttributeValidationClass('company') ); - ?> + ?> <input type="text" name="company" id="company" diff --git a/app/code/Magento/Customer/view/frontend/templates/widget/dob.phtml b/app/code/Magento/Customer/view/frontend/templates/widget/dob.phtml index 31510a65ef741..ac4b9f93e0c54 100644 --- a/app/code/Magento/Customer/view/frontend/templates/widget/dob.phtml +++ b/app/code/Magento/Customer/view/frontend/templates/widget/dob.phtml @@ -4,8 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Customer\Block\Widget\Dob $block */ /* diff --git a/app/code/Magento/Customer/view/frontend/templates/widget/fax.phtml b/app/code/Magento/Customer/view/frontend/templates/widget/fax.phtml index d7a1eb280a0e9..eff081f533927 100644 --- a/app/code/Magento/Customer/view/frontend/templates/widget/fax.phtml +++ b/app/code/Magento/Customer/view/frontend/templates/widget/fax.phtml @@ -4,8 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Customer\Block\Widget\Fax $block */ ?> @@ -16,12 +14,12 @@ </span> </label> <div class="control"> - <?php + <?php $_validationClass = $block->escapeHtmlAttr( - $this->helper('Magento\Customer\Helper\Address') + $this->helper(\Magento\Customer\Helper\Address::class) ->getAttributeValidationClass('fax') ); - ?> + ?> <input type="text" name="fax" id="fax" diff --git a/app/code/Magento/Customer/view/frontend/templates/widget/gender.phtml b/app/code/Magento/Customer/view/frontend/templates/widget/gender.phtml index 8b45618a891ef..515b44afe7548 100644 --- a/app/code/Magento/Customer/view/frontend/templates/widget/gender.phtml +++ b/app/code/Magento/Customer/view/frontend/templates/widget/gender.phtml @@ -4,18 +4,16 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Customer\Block\Widget\Gender $block */ ?> -<div class="field gender<?php if ($block->isRequired()) echo ' required' ?>"> +<div class="field gender<?= $block->isRequired() ? ' required' : ''?>"> <label class="label" for="<?= $block->escapeHtmlAttr($block->getFieldId('gender')) ?>"><span><?= $block->escapeHtml($block->getStoreLabel('gender')) ?></span></label> <div class="control"> - <select id="<?= $block->escapeHtmlAttr($block->getFieldId('gender')) ?>" name="<?= $block->escapeHtmlAttr($block->getFieldName('gender')) ?>" title="<?= $block->escapeHtmlAttr($block->getStoreLabel('gender')) ?>"<?php if ($block->isRequired()):?> class="validate-select" data-validate="{required:true}"<?php endif; ?>> + <select id="<?= $block->escapeHtmlAttr($block->getFieldId('gender')) ?>" name="<?= $block->escapeHtmlAttr($block->getFieldName('gender')) ?>" title="<?= $block->escapeHtmlAttr($block->getStoreLabel('gender')) ?>"<?php if ($block->isRequired()) : ?> class="validate-select" data-validate="{required:true}"<?php endif; ?>> <?php $options = $block->getGenderOptions(); ?> - <?php $value = $block->getGender();?> - <?php foreach ($options as $option):?> - <option value="<?= $block->escapeHtmlAttr($option->getValue()) ?>"<?php if ($option->getValue() == $value) echo ' selected="selected"' ?>><?= $block->escapeHtml(__($option->getLabel())) ?></option> + <?php $value = $block->getGender(); ?> + <?php foreach ($options as $option) : ?> + <option value="<?= $block->escapeHtmlAttr($option->getValue()) ?>"<?= ($option->getValue() == $value) ? ' selected="selected"' : '' ?>><?= $block->escapeHtml(__($option->getLabel())) ?></option> <?php endforeach;?> </select> </div> diff --git a/app/code/Magento/Customer/view/frontend/templates/widget/name.phtml b/app/code/Magento/Customer/view/frontend/templates/widget/name.phtml index 223e43c9bb897..00c1f124bd263 100644 --- a/app/code/Magento/Customer/view/frontend/templates/widget/name.phtml +++ b/app/code/Magento/Customer/view/frontend/templates/widget/name.phtml @@ -4,8 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Customer\Block\Widget\Name $block */ /* @@ -26,7 +24,7 @@ $prefix = $block->showPrefix(); $middle = $block->showMiddlename(); $suffix = $block->showSuffix(); ?> -<?php if (($prefix || $middle || $suffix) && !$block->getNoWrap()): ?> +<?php if (($prefix || $middle || $suffix) && !$block->getNoWrap()) : ?> <div class="field required fullname <?= $block->escapeHtmlAttr($block->getContainerClassName()) ?>"> <label for="<?= $block->escapeHtmlAttr($block->getFieldId('firstname')) ?>" class="label"><span><?= $block->escapeHtml(__('Name')) ?></span></label> <div class="control"> @@ -34,23 +32,23 @@ $suffix = $block->showSuffix(); <div class="fields"> <?php endif; ?> - <?php if ($prefix): ?> - <div class="field field-name-prefix<?php if ($block->isPrefixRequired()) echo ' required' ?>"> + <?php if ($prefix) : ?> + <div class="field field-name-prefix<?= $block->isPrefixRequired() ? ' required' : '' ?>"> <label class="label" for="<?= $block->escapeHtmlAttr($block->getFieldId('prefix')) ?>"><span><?= $block->escapeHtml($block->getStoreLabel('prefix')) ?></span></label> <div class="control"> - <?php if ($block->getPrefixOptions() === false): ?> + <?php if ($block->getPrefixOptions() === false) : ?> <input type="text" id="<?= $block->escapeHtmlAttr($block->getFieldId('prefix')) ?>" name="<?= $block->escapeHtmlAttr($block->getFieldName('prefix')) ?>" value="<?= $block->escapeHtmlAttr($block->getObject()->getPrefix()) ?>" title="<?= $block->escapeHtmlAttr($block->getStoreLabel('prefix')) ?>" - class="input-text <?= $block->escapeHtmlAttr($block->getAttributeValidationClass('prefix')) ?>" <?php if ($block->isPrefixRequired()) echo ' data-validate="{required:true}"' ?>> - <?php else: ?> + class="input-text <?= $block->escapeHtmlAttr($block->getAttributeValidationClass('prefix')) ?>" <?= $block->isPrefixRequired() ? ' data-validate="{required:true}"' : '' ?>> + <?php else : ?> <select id="<?= $block->escapeHtmlAttr($block->getFieldId('prefix')) ?>" name="<?= $block->escapeHtmlAttr($block->getFieldName('prefix')) ?>" title="<?= $block->escapeHtmlAttr($block->getStoreLabel('prefix')) ?>" - class="<?= $block->escapeHtmlAttr($block->getAttributeValidationClass('prefix')) ?>" <?php if ($block->isPrefixRequired()) echo ' data-validate="{required:true}"' ?> > - <?php foreach ($block->getPrefixOptions() as $_option): ?> - <option value="<?= $block->escapeHtmlAttr($_option) ?>"<?php if ($block->getObject()->getPrefix() == $_option): ?> selected="selected"<?php endif; ?>> + class="<?= $block->escapeHtmlAttr($block->getAttributeValidationClass('prefix')) ?>" <?= $block->isPrefixRequired() ? ' data-validate="{required:true}"' : '' ?> > + <?php foreach ($block->getPrefixOptions() as $_option) : ?> + <option value="<?= $block->escapeHtmlAttr($_option) ?>"<?php if ($block->getObject()->getPrefix() == $_option) : ?> selected="selected"<?php endif; ?>> <?= $block->escapeHtml(__($_option)) ?> </option> <?php endforeach; ?> @@ -66,10 +64,10 @@ $suffix = $block->showSuffix(); name="<?= $block->escapeHtmlAttr($block->getFieldName('firstname')) ?>" value="<?= $block->escapeHtmlAttr($block->getObject()->getFirstname()) ?>" title="<?= $block->escapeHtmlAttr($block->getStoreLabel('firstname')) ?>" - class="input-text <?= $block->escapeHtmlAttr($block->getAttributeValidationClass('firstname')) ?>" <?php if ($block->getAttributeValidationClass('firstname') == 'required-entry') echo ' data-validate="{required:true}"' ?>> + class="input-text <?= $block->escapeHtmlAttr($block->getAttributeValidationClass('firstname')) ?>" <?= ($block->getAttributeValidationClass('firstname') == 'required-entry') ? ' data-validate="{required:true}"' : '' ?>> </div> </div> - <?php if ($middle): ?> + <?php if ($middle) : ?> <?php $isMiddlenameRequired = $block->isMiddlenameRequired(); ?> <div class="field field-name-middlename<?= $isMiddlenameRequired ? ' required' : '' ?>"> <label class="label" for="<?= $block->escapeHtmlAttr($block->getFieldId('middlename')) ?>"><span><?= $block->escapeHtml($block->getStoreLabel('middlename')) ?></span></label> @@ -89,26 +87,26 @@ $suffix = $block->showSuffix(); name="<?= $block->escapeHtmlAttr($block->getFieldName('lastname')) ?>" value="<?= $block->escapeHtmlAttr($block->getObject()->getLastname()) ?>" title="<?= $block->escapeHtmlAttr($block->getStoreLabel('lastname')) ?>" - class="input-text <?= $block->escapeHtmlAttr($block->getAttributeValidationClass('lastname')) ?>" <?php if ($block->getAttributeValidationClass('lastname') == 'required-entry') echo ' data-validate="{required:true}"' ?>> + class="input-text <?= $block->escapeHtmlAttr($block->getAttributeValidationClass('lastname')) ?>" <?= ($block->getAttributeValidationClass('lastname') == 'required-entry') ? ' data-validate="{required:true}"' : '' ?>> </div> </div> - <?php if ($suffix): ?> - <div class="field field-name-suffix<?php if ($block->isSuffixRequired()) echo ' required' ?>"> + <?php if ($suffix) : ?> + <div class="field field-name-suffix<?= $block->isSuffixRequired() ? ' required' : '' ?>"> <label class="label" for="<?= $block->escapeHtmlAttr($block->getFieldId('suffix')) ?>"><span><?= $block->escapeHtml($block->getStoreLabel('suffix')) ?></span></label> <div class="control"> - <?php if ($block->getSuffixOptions() === false): ?> + <?php if ($block->getSuffixOptions() === false) : ?> <input type="text" id="<?= $block->escapeHtmlAttr($block->getFieldId('suffix')) ?>" name="<?= $block->escapeHtmlAttr($block->getFieldName('suffix')) ?>" value="<?= $block->escapeHtmlAttr($block->getObject()->getSuffix()) ?>" title="<?= $block->escapeHtmlAttr($block->getStoreLabel('suffix')) ?>" - class="input-text <?= $block->escapeHtmlAttr($block->getAttributeValidationClass('suffix')) ?>" <?php if ($block->isSuffixRequired()) echo ' data-validate="{required:true}"' ?>> - <?php else: ?> + class="input-text <?= $block->escapeHtmlAttr($block->getAttributeValidationClass('suffix')) ?>" <?= $block->isSuffixRequired() ? ' data-validate="{required:true}"' : '' ?>> + <?php else : ?> <select id="<?= $block->escapeHtmlAttr($block->getFieldId('suffix')) ?>" name="<?= $block->escapeHtmlAttr($block->getFieldName('suffix')) ?>" title="<?= $block->escapeHtmlAttr($block->getStoreLabel('suffix')) ?>" - class="<?= $block->escapeHtmlAttr($block->getAttributeValidationClass('suffix')) ?>" <?php if ($block->isSuffixRequired()) echo ' data-validate="{required:true}"' ?>> - <?php foreach ($block->getSuffixOptions() as $_option): ?> - <option value="<?= $block->escapeHtmlAttr($_option) ?>"<?php if ($block->getObject()->getSuffix() == $_option): ?> selected="selected"<?php endif; ?>> + class="<?= $block->escapeHtmlAttr($block->getAttributeValidationClass('suffix')) ?>" <?= $block->isSuffixRequired() ? ' data-validate="{required:true}"' : '' ?>> + <?php foreach ($block->getSuffixOptions() as $_option) : ?> + <option value="<?= $block->escapeHtmlAttr($_option) ?>"<?php if ($block->getObject()->getSuffix() == $_option) : ?> selected="selected"<?php endif; ?>> <?= $block->escapeHtml(__($_option)) ?> </option> <?php endforeach; ?> @@ -118,7 +116,7 @@ $suffix = $block->showSuffix(); </div> <?php endif; ?> - <?php if (($prefix || $middle || $suffix) && !$block->getNoWrap()): ?> + <?php if (($prefix || $middle || $suffix) && !$block->getNoWrap()) : ?> </div> </fieldset> </div> diff --git a/app/code/Magento/Customer/view/frontend/templates/widget/taxvat.phtml b/app/code/Magento/Customer/view/frontend/templates/widget/taxvat.phtml index bb60845a64e6d..1551ea9609449 100644 --- a/app/code/Magento/Customer/view/frontend/templates/widget/taxvat.phtml +++ b/app/code/Magento/Customer/view/frontend/templates/widget/taxvat.phtml @@ -4,13 +4,11 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Customer\Block\Widget\Taxvat $block */ ?> -<div class="field taxvat<?php if ($block->isRequired()) echo ' required'; ?>"> +<div class="field taxvat<?= $block->isRequired() ? ' required' : ''; ?>"> <label class="label" for="<?= $block->escapeHtmlAttr($block->getFieldId('taxvat')) ?>"><span><?= $block->escapeHtml($block->getStoreLabel('taxvat')) ?></span></label> <div class="control"> - <input type="text" id="<?= $block->escapeHtmlAttr($block->getFieldId('taxvat')) ?>" name="<?= $block->escapeHtmlAttr($block->getFieldName('taxvat')) ?>" value="<?= $block->escapeHtmlAttr($block->getTaxvat()) ?>" title="<?= $block->escapeHtmlAttr($block->getStoreLabel('taxvat')) ?>" class="input-text <?= $block->escapeHtmlAttr($this->helper('Magento\Customer\Helper\Address')->getAttributeValidationClass('taxvat')) ?>" <?php if ($block->isRequired()) echo ' data-validate="{required:true}"' ?>> + <input type="text" id="<?= $block->escapeHtmlAttr($block->getFieldId('taxvat')) ?>" name="<?= $block->escapeHtmlAttr($block->getFieldName('taxvat')) ?>" value="<?= $block->escapeHtmlAttr($block->getTaxvat()) ?>" title="<?= $block->escapeHtmlAttr($block->getStoreLabel('taxvat')) ?>" class="input-text <?= $block->escapeHtmlAttr($this->helper(\Magento\Customer\Helper\Address::class)->getAttributeValidationClass('taxvat')) ?>" <?= $block->isRequired() ? ' data-validate="{required:true}"' : '' ?>> </div> </div> diff --git a/app/code/Magento/Customer/view/frontend/templates/widget/telephone.phtml b/app/code/Magento/Customer/view/frontend/templates/widget/telephone.phtml index 6367bf10bbade..c444a15705909 100644 --- a/app/code/Magento/Customer/view/frontend/templates/widget/telephone.phtml +++ b/app/code/Magento/Customer/view/frontend/templates/widget/telephone.phtml @@ -4,8 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Customer\Block\Widget\Telephone $block */ ?> @@ -16,12 +14,12 @@ </span> </label> <div class="control"> - <?php + <?php $_validationClass = $block->escapeHtmlAttr( - $this->helper('Magento\Customer\Helper\Address') + $this->helper(\Magento\Customer\Helper\Address::class) ->getAttributeValidationClass('telephone') ); - ?> + ?> <input type="text" name="telephone" id="telephone" diff --git a/app/code/Magento/Directory/view/adminhtml/templates/js/optional_zip_countries.phtml b/app/code/Magento/Directory/view/adminhtml/templates/js/optional_zip_countries.phtml index bae7a08143cce..524c86fbaf604 100644 --- a/app/code/Magento/Directory/view/adminhtml/templates/js/optional_zip_countries.phtml +++ b/app/code/Magento/Directory/view/adminhtml/templates/js/optional_zip_countries.phtml @@ -4,7 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile /** * JS block for including Countries with Optional Zip * @@ -19,7 +18,7 @@ require([ ], function(){ //<![CDATA[ -optionalZipCountries = <?= /* @noEscape */ $this->helper('Magento\Directory\Helper\Data')->getCountriesWithOptionalZip(true) ?>; +optionalZipCountries = <?= /* @noEscape */ $this->helper(\Magento\Directory\Helper\Data::class)->getCountriesWithOptionalZip(true) ?>; function onAddressCountryChanged (countryElement) { var zipElementId = countryElement.id.replace(/country_id/, 'postcode'); diff --git a/app/code/Magento/Directory/view/frontend/templates/currency.phtml b/app/code/Magento/Directory/view/frontend/templates/currency.phtml index 30283effe4bb7..15cf9435bc5d1 100644 --- a/app/code/Magento/Directory/view/frontend/templates/currency.phtml +++ b/app/code/Magento/Directory/view/frontend/templates/currency.phtml @@ -4,7 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile /** * Currency switcher * @@ -12,31 +11,31 @@ */ ?> -<?php if ($block->getCurrencyCount() > 1): ?> -<?php $currencies = $block->getCurrencies(); ?> -<?php $currentCurrencyCode = $block->getCurrentCurrencyCode(); ?> -<?php $id = $block->getIdModifier() ? '-' . $block->getIdModifier() : '' ?> -<div class="switcher currency switcher-currency" id="switcher-currency<?= $block->escapeHtmlAttr($id) ?>"> - <strong class="label switcher-label"><span><?= $block->escapeHtml(__('Currency')) ?></span></strong> - <div class="actions dropdown options switcher-options"> - <div class="action toggle switcher-trigger" - id="switcher-currency-trigger<?= $block->escapeHtmlAttr($id) ?>" - data-mage-init='{"dropdown":{}}' - data-toggle="dropdown" - data-trigger-keypress-button="true"> - <strong class="language-<?= $block->escapeHtml($block->getCurrentCurrencyCode()) ?>"> - <span><?= $block->escapeHtml($currentCurrencyCode) ?> - <?= @$block->escapeHtml($currencies[$currentCurrencyCode]) ?></span> - </strong> +<?php if ($block->getCurrencyCount() > 1) : ?> + <?php $currencies = $block->getCurrencies(); ?> + <?php $currentCurrencyCode = $block->getCurrentCurrencyCode(); ?> + <?php $id = $block->getIdModifier() ? '-' . $block->getIdModifier() : '' ?> + <div class="switcher currency switcher-currency" id="switcher-currency<?= $block->escapeHtmlAttr($id) ?>"> + <strong class="label switcher-label"><span><?= $block->escapeHtml(__('Currency')) ?></span></strong> + <div class="actions dropdown options switcher-options"> + <div class="action toggle switcher-trigger" + id="switcher-currency-trigger<?= $block->escapeHtmlAttr($id) ?>" + data-mage-init='{"dropdown":{}}' + data-toggle="dropdown" + data-trigger-keypress-button="true"> + <strong class="language-<?= $block->escapeHtml($block->getCurrentCurrencyCode()) ?>"> + <span><?= $block->escapeHtml($currentCurrencyCode) ?> - <?= $currencies[$currentCurrencyCode] ? $block->escapeHtml($currencies[$currentCurrencyCode]) : '' ?></span> + </strong> + </div> + <ul class="dropdown switcher-dropdown" data-target="dropdown"> + <?php foreach ($currencies as $_code => $_name) : ?> + <?php if ($_code != $currentCurrencyCode) : ?> + <li class="currency-<?= $block->escapeHtmlAttr($_code) ?> switcher-option"> + <a href="#" data-post='<?= /* @noEscape */ $block->getSwitchCurrencyPostData($_code) ?>'><?= $block->escapeHtml($_code) ?> - <?= $block->escapeHtml($_name) ?></a> + </li> + <?php endif; ?> + <?php endforeach; ?> + </ul> </div> - <ul class="dropdown switcher-dropdown" data-target="dropdown"> - <?php foreach ($currencies as $_code => $_name): ?> - <?php if ($_code != $currentCurrencyCode): ?> - <li class="currency-<?= $block->escapeHtmlAttr($_code) ?> switcher-option"> - <a href="#" data-post='<?= /* @noEscape */ $block->getSwitchCurrencyPostData($_code) ?>'><?= $block->escapeHtml($_code) ?> - <?= $block->escapeHtml($_name) ?></a> - </li> - <?php endif; ?> - <?php endforeach; ?> - </ul> </div> -</div> <?php endif; ?> diff --git a/app/code/Magento/Directory/view/frontend/templates/currency/switch.phtml b/app/code/Magento/Directory/view/frontend/templates/currency/switch.phtml index 4411aa2579e66..50995dbd1d06d 100644 --- a/app/code/Magento/Directory/view/frontend/templates/currency/switch.phtml +++ b/app/code/Magento/Directory/view/frontend/templates/currency/switch.phtml @@ -4,8 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Framework\View\Element\Template $block */ ?> diff --git a/app/code/Magento/Eav/view/adminhtml/templates/attribute/edit/js.phtml b/app/code/Magento/Eav/view/adminhtml/templates/attribute/edit/js.phtml index b7b29d7cdcd10..ff74eb50f722f 100644 --- a/app/code/Magento/Eav/view/adminhtml/templates/attribute/edit/js.phtml +++ b/app/code/Magento/Eav/view/adminhtml/templates/attribute/edit/js.phtml @@ -5,15 +5,13 @@ */ /** @var \Magento\Eav\Block\Adminhtml\Attribute\Edit\Js $block */ - -// @codingStandardsIgnoreFile ?> <script type="text/x-magento-init"> { "*": { "eavInputTypes": { - "inputTypes": <?= /* @escapeNotVerified */ json_encode($block->getComaptibleInputTypes())?>, - "hints": <?= /* @escapeNotVerified */ json_encode($block->getInputTypeHints())?> + "inputTypes": <?= /* @noEscape */ json_encode($block->getComaptibleInputTypes())?>, + "hints": <?= /* @noEscape */ json_encode($block->getInputTypeHints())?> } } } diff --git a/app/code/Magento/Email/view/adminhtml/templates/template/edit.phtml b/app/code/Magento/Email/view/adminhtml/templates/template/edit.phtml index 05a873f8ddd5a..8b1f50095d984 100644 --- a/app/code/Magento/Email/view/adminhtml/templates/template/edit.phtml +++ b/app/code/Magento/Email/view/adminhtml/templates/template/edit.phtml @@ -6,11 +6,9 @@ use Magento\Framework\App\TemplateTypesInterface; -// @codingStandardsIgnoreFile - /** @var $block \Magento\Email\Block\Adminhtml\Template\Edit */ ?> -<?php if (!$block->getEditMode()): ?> +<?php if (!$block->getEditMode()) : ?> <form action="<?= $block->escapeUrl($block->getLoadUrl()) ?>" method="post" id="email_template_load_form"> <?= $block->getBlockHtml('formkey') ?> <fieldset class="admin__fieldset form-inline"> @@ -19,14 +17,14 @@ use Magento\Framework\App\TemplateTypesInterface; <label class="admin__field-label" for="template_select"><?= $block->escapeHtml(__('Template')) ?></label> <div class="admin__field-control"> <select id="template_select" name="code" class="admin__control-select required-entry"> - <?php foreach ($block->getTemplateOptions() as $group => $options): ?> - <?php if ($group): ?> + <?php foreach ($block->getTemplateOptions() as $group => $options) : ?> + <?php if ($group) : ?> <optgroup label="<?= $block->escapeHtmlAttr($group) ?>"> <?php endif; ?> - <?php foreach ($options as $option): ?> + <?php foreach ($options as $option) : ?> <option value="<?= $block->escapeHtmlAttr($option['value']) ?>"<?= /* @noEscape */ $block->getOrigTemplateCode() == $option['value'] ? ' selected="selected"' : '' ?>><?= $block->escapeHtml($option['label']) ?></option> <?php endforeach; ?> - <?php if ($group): ?> + <?php if ($group) : ?> </optgroup> <?php endif; ?> <?php endforeach; ?> diff --git a/app/code/Magento/Email/view/adminhtml/templates/template/list.phtml b/app/code/Magento/Email/view/adminhtml/templates/template/list.phtml index b0e7206005071..d6a72889cbbd9 100644 --- a/app/code/Magento/Email/view/adminhtml/templates/template/list.phtml +++ b/app/code/Magento/Email/view/adminhtml/templates/template/list.phtml @@ -3,9 +3,6 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ - -// @codingStandardsIgnoreFile - ?> <div data-mage-init='{"floatingHeader": {}}' class="page-actions"><?= $block->getChildHtml('add_button') ?></div> <?= $block->getChildHtml('grid') ?> diff --git a/app/code/Magento/Newsletter/view/adminhtml/templates/preview/iframeswitcher.phtml b/app/code/Magento/Newsletter/view/adminhtml/templates/preview/iframeswitcher.phtml index 532ecde456077..00f430cd14b8d 100644 --- a/app/code/Magento/Newsletter/view/adminhtml/templates/preview/iframeswitcher.phtml +++ b/app/code/Magento/Newsletter/view/adminhtml/templates/preview/iframeswitcher.phtml @@ -4,8 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Backend\Block\Page $block */ ?> <div id="preview" class="cms-revision-preview"> diff --git a/app/code/Magento/Newsletter/view/adminhtml/templates/preview/store.phtml b/app/code/Magento/Newsletter/view/adminhtml/templates/preview/store.phtml index 2583ccea6fca4..d5a24fad2ac91 100644 --- a/app/code/Magento/Newsletter/view/adminhtml/templates/preview/store.phtml +++ b/app/code/Magento/Newsletter/view/adminhtml/templates/preview/store.phtml @@ -3,12 +3,9 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ - -// @codingStandardsIgnoreFile - ?> -<?php if ($websites = $block->getWebsites()): ?> +<?php if ($websites = $block->getWebsites()) : ?> <div class="field field-store-switcher"> <label class="label" for="store_switcher"><?= $block->escapeHtml(__('Choose Store View:')) ?></label> <div class="control"> @@ -16,22 +13,22 @@ id="store_switcher" class="admin__control-select" name="store_switcher"> - <?php foreach ($websites as $website): ?> + <?php foreach ($websites as $website) : ?> <?php $showWebsite = false; ?> - <?php foreach ($website->getGroups() as $group): ?> + <?php foreach ($website->getGroups() as $group) : ?> <?php $showGroup = false; ?> - <?php foreach ($block->getStores($group) as $store): ?> - <?php if ($showWebsite == false): ?> + <?php foreach ($block->getStores($group) as $store) : ?> + <?php if ($showWebsite == false) : ?> <?php $showWebsite = true; ?> <optgroup label="<?= $block->escapeHtmlAttr($website->getName()) ?>"></optgroup> <?php endif; ?> - <?php if ($showGroup == false): ?> + <?php if ($showGroup == false) : ?> <?php $showGroup = true; ?> <optgroup label="   <?= $block->escapeHtmlAttr($group->getName()) ?>"> <?php endif; ?> - <option value="<?= $block->escapeHtmlAttr($store->getId()) ?>"<?php if ($block->getStoreId() == $store->getId()): ?> selected="selected"<?php endif; ?>>    <?= $block->escapeHtml($store->getName()) ?></option> + <option value="<?= $block->escapeHtmlAttr($store->getId()) ?>"<?php if ($block->getStoreId() == $store->getId()) : ?> selected="selected"<?php endif; ?>>    <?= $block->escapeHtml($store->getName()) ?></option> <?php endforeach; ?> - <?php if ($showGroup): ?> + <?php if ($showGroup) : ?> </optgroup> <?php endif; ?> <?php endforeach; ?> diff --git a/app/code/Magento/Newsletter/view/adminhtml/templates/problem/list.phtml b/app/code/Magento/Newsletter/view/adminhtml/templates/problem/list.phtml index 51808cab7f7a0..a3d88de9d35b2 100644 --- a/app/code/Magento/Newsletter/view/adminhtml/templates/problem/list.phtml +++ b/app/code/Magento/Newsletter/view/adminhtml/templates/problem/list.phtml @@ -3,13 +3,10 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ - -// @codingStandardsIgnoreFile - ?> <?= $block->getChildHtml('grid') ?> -<?php if ($block->getShowButtons()): ?> +<?php if ($block->getShowButtons()) : ?> <div class="form-buttons"> <?= $block->getUnsubscribeButtonHtml() ?> <?= $block->getDeleteButtonHtml() ?> @@ -18,7 +15,6 @@ <script> require(["prototype", "mage/adminhtml/events"], function(){ - <!-- problemController = { checkCheckboxes:function (controlCheckbox) { var elements = $('problemGrid').getElementsByClassName('problemCheckbox'); diff --git a/app/code/Magento/Newsletter/view/adminhtml/templates/queue/edit.phtml b/app/code/Magento/Newsletter/view/adminhtml/templates/queue/edit.phtml index 52c94d0c3f89c..3d52cc0dee777 100644 --- a/app/code/Magento/Newsletter/view/adminhtml/templates/queue/edit.phtml +++ b/app/code/Magento/Newsletter/view/adminhtml/templates/queue/edit.phtml @@ -4,19 +4,17 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /* @var $block \Magento\Newsletter\Block\Adminhtml\Queue\Edit */ ?> <div data-mage-init='{"floatingHeader": {}}' class="page-actions"> <?= $block->getBackButtonHtml() ?> <?= $block->getPreviewButtonHtml() ?> - <?php if (!$block->getIsPreview()): ?> + <?php if (!$block->getIsPreview()) : ?> <?= $block->getResetButtonHtml() ?> <?= $block->getSaveButtonHtml() ?> <?php endif ?> - <?php if ($block->getCanResume()): ?> + <?php if ($block->getCanResume()) : ?> <?= $block->getResumeButtonHtml() ?> <?php endif ?> </div> diff --git a/app/code/Magento/Newsletter/view/adminhtml/templates/queue/list.phtml b/app/code/Magento/Newsletter/view/adminhtml/templates/queue/list.phtml index 902c6932f0ae1..c0928f4723b50 100644 --- a/app/code/Magento/Newsletter/view/adminhtml/templates/queue/list.phtml +++ b/app/code/Magento/Newsletter/view/adminhtml/templates/queue/list.phtml @@ -3,8 +3,5 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ - -// @codingStandardsIgnoreFile - ?> <?= $block->getChildHtml('grid') ?> diff --git a/app/code/Magento/Newsletter/view/adminhtml/templates/subscriber/list.phtml b/app/code/Magento/Newsletter/view/adminhtml/templates/subscriber/list.phtml index a405a6895b1d3..13bd5d5118be0 100644 --- a/app/code/Magento/Newsletter/view/adminhtml/templates/subscriber/list.phtml +++ b/app/code/Magento/Newsletter/view/adminhtml/templates/subscriber/list.phtml @@ -4,16 +4,14 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Newsletter\Block\Adminhtml\Subscriber $block */ ?> <?= $block->getChildHtml('grid') ?> -<?php if (count($block->getQueueAsOptions())>0 && $block->getShowQueueAdd()): ?> +<?php if (count($block->getQueueAsOptions())>0 && $block->getShowQueueAdd()) : ?> <div class="form-buttons"> <select id="queueList" name="queue"> - <?php foreach ($block->getQueueAsOptions() as $_queue): ?> + <?php foreach ($block->getQueueAsOptions() as $_queue) : ?> <option value="<?= $block->escapeHtmlAttr($_queue['value']) ?>"><?= $block->escapeHtml($_queue['label']) ?> #<?= $block->escapeHtml($_queue['value']) ?></option> <?php endforeach; ?> </select> diff --git a/app/code/Magento/Newsletter/view/adminhtml/templates/template/edit.phtml b/app/code/Magento/Newsletter/view/adminhtml/templates/template/edit.phtml index 279afe2c28e7a..c49a5c61a7172 100644 --- a/app/code/Magento/Newsletter/view/adminhtml/templates/template/edit.phtml +++ b/app/code/Magento/Newsletter/view/adminhtml/templates/template/edit.phtml @@ -6,8 +6,6 @@ use Magento\Framework\App\TemplateTypesInterface; -// @codingStandardsIgnoreFile - /* @var $block \Magento\Newsletter\Block\Adminhtml\Template\Edit */ ?> diff --git a/app/code/Magento/Newsletter/view/adminhtml/templates/template/list.phtml b/app/code/Magento/Newsletter/view/adminhtml/templates/template/list.phtml index 902c6932f0ae1..c0928f4723b50 100644 --- a/app/code/Magento/Newsletter/view/adminhtml/templates/template/list.phtml +++ b/app/code/Magento/Newsletter/view/adminhtml/templates/template/list.phtml @@ -3,8 +3,5 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ - -// @codingStandardsIgnoreFile - ?> <?= $block->getChildHtml('grid') ?> diff --git a/app/code/Magento/Newsletter/view/frontend/templates/js/components.phtml b/app/code/Magento/Newsletter/view/frontend/templates/js/components.phtml index bad5acc209b5f..5902a9f25cc4b 100644 --- a/app/code/Magento/Newsletter/view/frontend/templates/js/components.phtml +++ b/app/code/Magento/Newsletter/view/frontend/templates/js/components.phtml @@ -3,8 +3,5 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ - -// @codingStandardsIgnoreFile - ?> <?= $block->getChildHtml() ?> diff --git a/app/code/Magento/Newsletter/view/frontend/templates/subscribe.phtml b/app/code/Magento/Newsletter/view/frontend/templates/subscribe.phtml index 554437095f36c..bd6f12e1811a6 100644 --- a/app/code/Magento/Newsletter/view/frontend/templates/subscribe.phtml +++ b/app/code/Magento/Newsletter/view/frontend/templates/subscribe.phtml @@ -4,10 +4,7 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Newsletter\Block\Subscribe $block */ - ?> <div class="block newsletter"> <div class="title"><strong><?= $block->escapeHtml(__('Newsletter')) ?></strong></div> diff --git a/app/code/Magento/OfflinePayments/view/adminhtml/templates/form/banktransfer.phtml b/app/code/Magento/OfflinePayments/view/adminhtml/templates/form/banktransfer.phtml index e1ffd7bdaf7a8..a251c609ea324 100644 --- a/app/code/Magento/OfflinePayments/view/adminhtml/templates/form/banktransfer.phtml +++ b/app/code/Magento/OfflinePayments/view/adminhtml/templates/form/banktransfer.phtml @@ -4,13 +4,12 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile /** * @var $block \Magento\OfflinePayments\Block\Form\Banktransfer */ $instructions = $block->getInstructions(); ?> -<?php if ($instructions): ?> +<?php if ($instructions) : ?> <?php $methodCode = $block->escapeHtml($block->getMethodCode());?> <ul class="form-list checkout-agreements" id="payment_form_<?= /* @noEscape */ $methodCode ?>" style="display:none;"> <li> diff --git a/app/code/Magento/OfflinePayments/view/adminhtml/templates/form/cashondelivery.phtml b/app/code/Magento/OfflinePayments/view/adminhtml/templates/form/cashondelivery.phtml index ac72b5f5707ea..8e8730640a8a7 100644 --- a/app/code/Magento/OfflinePayments/view/adminhtml/templates/form/cashondelivery.phtml +++ b/app/code/Magento/OfflinePayments/view/adminhtml/templates/form/cashondelivery.phtml @@ -4,14 +4,12 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** * @var $block \Magento\OfflinePayments\Block\Form\Cashondelivery */ $instructions = $block->getInstructions(); ?> -<?php if ($instructions): ?> +<?php if ($instructions) : ?> <?php $methodCode = $block->escapeHtml($block->getMethodCode());?> <ul class="form-list checkout-agreements" id="payment_form_<?= /* @noEscape */ $methodCode ?>" style="display:none;"> <li> diff --git a/app/code/Magento/OfflinePayments/view/adminhtml/templates/form/checkmo.phtml b/app/code/Magento/OfflinePayments/view/adminhtml/templates/form/checkmo.phtml index 2a1de9df69ecd..db1d7c87ada0e 100644 --- a/app/code/Magento/OfflinePayments/view/adminhtml/templates/form/checkmo.phtml +++ b/app/code/Magento/OfflinePayments/view/adminhtml/templates/form/checkmo.phtml @@ -4,16 +4,15 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile /** * @var $block \Magento\OfflinePayments\Block\Form\Checkmo */ ?> <fieldset class="admin__fieldset payment-method" id="payment_form_<?= $block->escapeHtml($block->getMethodCode()) ?>" style="display:none"> - <?php if ($block->getMethod()->getPayableTo()): ?> + <?php if ($block->getMethod()->getPayableTo()) : ?> <label class="label"><span><?= $block->escapeHtml(__('Make Check payable to:')) ?></span></label> <?= $block->escapeHtml($block->getMethod()->getPayableTo()) ?> <?php endif; ?> - <?php if ($block->getMethod()->getMailingAddress()): ?> + <?php if ($block->getMethod()->getMailingAddress()) : ?> <div class="admin__field"> <label class="admin__field-label"><span><?= $block->escapeHtml(__('Send Check to:')) ?></span></label> <div class="admin__field-control checkmo-mailing-address"> diff --git a/app/code/Magento/OfflinePayments/view/adminhtml/templates/form/purchaseorder.phtml b/app/code/Magento/OfflinePayments/view/adminhtml/templates/form/purchaseorder.phtml index d6ee0d53eaaae..c115765697fc5 100644 --- a/app/code/Magento/OfflinePayments/view/adminhtml/templates/form/purchaseorder.phtml +++ b/app/code/Magento/OfflinePayments/view/adminhtml/templates/form/purchaseorder.phtml @@ -4,7 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile /** * @var $block \Magento\OfflinePayments\Block\Form\Purchaseorder */ diff --git a/app/code/Magento/OfflinePayments/view/adminhtml/templates/info/checkmo.phtml b/app/code/Magento/OfflinePayments/view/adminhtml/templates/info/checkmo.phtml index 0882619db8fe3..36f9d35327fce 100644 --- a/app/code/Magento/OfflinePayments/view/adminhtml/templates/info/checkmo.phtml +++ b/app/code/Magento/OfflinePayments/view/adminhtml/templates/info/checkmo.phtml @@ -4,17 +4,16 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile /** * @var $block \Magento\OfflinePayments\Block\Info\Checkmo */ ?> <?= $block->escapeHtml($block->getMethod()->getTitle()) ?> -<?php if ($block->getInfo()->getAdditionalInformation()): ?> - <?php if ($block->getPayableTo()): ?> +<?php if ($block->getInfo()->getAdditionalInformation()) : ?> + <?php if ($block->getPayableTo()) : ?> <br /><?= $block->escapeHtml(__('Make Check payable to: %1', $block->getPayableTo())) ?> <?php endif; ?> - <?php if ($block->getMailingAddress()): ?> + <?php if ($block->getMailingAddress()) : ?> <label><?= $block->escapeHtml(__('Send Check to:')) ?></label> <div class="checkmo-mailing-address"> <?= /* @noEscape */ nl2br($block->escapeHtml($block->getMailingAddress())) ?> diff --git a/app/code/Magento/OfflinePayments/view/adminhtml/templates/info/pdf/checkmo.phtml b/app/code/Magento/OfflinePayments/view/adminhtml/templates/info/pdf/checkmo.phtml index 4d63577319d5b..d8d952526e67b 100644 --- a/app/code/Magento/OfflinePayments/view/adminhtml/templates/info/pdf/checkmo.phtml +++ b/app/code/Magento/OfflinePayments/view/adminhtml/templates/info/pdf/checkmo.phtml @@ -4,20 +4,19 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile /** * @var $block \Magento\OfflinePayments\Block\Info\Checkmo */ ?> <?= $block->escapeHtml($block->getMethod()->getTitle()) ?> {{pdf_row_separator}} -<?php if ($block->getInfo()->getAdditionalInformation()): ?> +<?php if ($block->getInfo()->getAdditionalInformation()) : ?> {{pdf_row_separator}} - <?php if ($block->getPayableTo()): ?> + <?php if ($block->getPayableTo()) : ?> <?= $block->escapeHtml(__('Make Check payable to: %1', $block->getPayableTo())) ?> {{pdf_row_separator}} <?php endif; ?> - <?php if ($block->getMailingAddress()): ?> + <?php if ($block->getMailingAddress()) : ?> <?= $block->escapeHtml(__('Send Check to:')) ?> {{pdf_row_separator}} <?= /* @noEscape */ nl2br($block->escapeHtml($block->getMailingAddress())) ?> diff --git a/app/code/Magento/OfflinePayments/view/base/templates/info/pdf/checkmo.phtml b/app/code/Magento/OfflinePayments/view/base/templates/info/pdf/checkmo.phtml index 4d63577319d5b..d8d952526e67b 100644 --- a/app/code/Magento/OfflinePayments/view/base/templates/info/pdf/checkmo.phtml +++ b/app/code/Magento/OfflinePayments/view/base/templates/info/pdf/checkmo.phtml @@ -4,20 +4,19 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile /** * @var $block \Magento\OfflinePayments\Block\Info\Checkmo */ ?> <?= $block->escapeHtml($block->getMethod()->getTitle()) ?> {{pdf_row_separator}} -<?php if ($block->getInfo()->getAdditionalInformation()): ?> +<?php if ($block->getInfo()->getAdditionalInformation()) : ?> {{pdf_row_separator}} - <?php if ($block->getPayableTo()): ?> + <?php if ($block->getPayableTo()) : ?> <?= $block->escapeHtml(__('Make Check payable to: %1', $block->getPayableTo())) ?> {{pdf_row_separator}} <?php endif; ?> - <?php if ($block->getMailingAddress()): ?> + <?php if ($block->getMailingAddress()) : ?> <?= $block->escapeHtml(__('Send Check to:')) ?> {{pdf_row_separator}} <?= /* @noEscape */ nl2br($block->escapeHtml($block->getMailingAddress())) ?> diff --git a/app/code/Magento/OfflinePayments/view/frontend/templates/form/banktransfer.phtml b/app/code/Magento/OfflinePayments/view/frontend/templates/form/banktransfer.phtml index 7c21047fbb90d..568ef7c3f69f2 100644 --- a/app/code/Magento/OfflinePayments/view/frontend/templates/form/banktransfer.phtml +++ b/app/code/Magento/OfflinePayments/view/frontend/templates/form/banktransfer.phtml @@ -4,13 +4,12 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile /** * @var $block \Magento\OfflinePayments\Block\Form\Banktransfer */ $instructions = $block->getInstructions(); ?> -<?php if ($instructions): ?> +<?php if ($instructions) : ?> <?php $methodCode = $block->escapeHtml($block->getMethodCode());?> <div class="items <?= /* @noEscape */ $methodCode ?> instructions agreement checkout-agreement-item-content" id="payment_form_<?= /* @noEscape */ $methodCode ?>" style="display: none;"> <?= /* @noEscape */ nl2br($block->escapeHtml($instructions)) ?> diff --git a/app/code/Magento/OfflinePayments/view/frontend/templates/form/cashondelivery.phtml b/app/code/Magento/OfflinePayments/view/frontend/templates/form/cashondelivery.phtml index f6f019bc84ce4..2943f59be4ab3 100644 --- a/app/code/Magento/OfflinePayments/view/frontend/templates/form/cashondelivery.phtml +++ b/app/code/Magento/OfflinePayments/view/frontend/templates/form/cashondelivery.phtml @@ -4,14 +4,12 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** * @var $block \Magento\OfflinePayments\Block\Form\Cashondelivery */ $instructions = $block->getInstructions(); ?> -<?php if ($instructions): ?> +<?php if ($instructions) : ?> <?php $methodCode = $block->escapeHtml($block->getMethodCode());?> <div class="items <?= /* @noEscape */ $methodCode ?> instructions agreement" id="payment_form_<?= /* @noEscape */ $methodCode ?>" style="display: none;"> <?= /* @noEscape */ nl2br($block->escapeHtml($instructions)) ?> diff --git a/app/code/Magento/OfflinePayments/view/frontend/templates/form/checkmo.phtml b/app/code/Magento/OfflinePayments/view/frontend/templates/form/checkmo.phtml index de4b6ac66cf29..36f58fc155a18 100644 --- a/app/code/Magento/OfflinePayments/view/frontend/templates/form/checkmo.phtml +++ b/app/code/Magento/OfflinePayments/view/frontend/templates/form/checkmo.phtml @@ -4,18 +4,17 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile /** * @var $block \Magento\OfflinePayments\Block\Form\Checkmo */ ?> -<?php if ($block->getMethod()->getMailingAddress() || $block->getMethod()->getPayableTo()): ?> +<?php if ($block->getMethod()->getMailingAddress() || $block->getMethod()->getPayableTo()) : ?> <dl class="items check payable" id="payment_form_<?= $block->escapeHtml($block->getMethodCode()) ?>" style="display:none;"> - <?php if ($block->getMethod()->getPayableTo()): ?> + <?php if ($block->getMethod()->getPayableTo()) : ?> <dt class="title"><?= $block->escapeHtml(__('Make Check payable to:')) ?></dt> <dd class="content"><?= $block->escapeHtml($block->getMethod()->getPayableTo()) ?></dd> <?php endif; ?> - <?php if ($block->getMethod()->getMailingAddress()): ?> + <?php if ($block->getMethod()->getMailingAddress()) : ?> <dt class="title"><?= $block->escapeHtml(__('Send Check to:')) ?></dt> <dd class="content"> <address class="checkmo mailing address"> diff --git a/app/code/Magento/OfflinePayments/view/frontend/templates/form/purchaseorder.phtml b/app/code/Magento/OfflinePayments/view/frontend/templates/form/purchaseorder.phtml index 5d04977ab3455..52b7df9fb9187 100644 --- a/app/code/Magento/OfflinePayments/view/frontend/templates/form/purchaseorder.phtml +++ b/app/code/Magento/OfflinePayments/view/frontend/templates/form/purchaseorder.phtml @@ -4,7 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile /** * @var $block \Magento\OfflinePayments\Block\Form\Purchaseorder */ diff --git a/app/code/Magento/OfflinePayments/view/frontend/templates/info/checkmo.phtml b/app/code/Magento/OfflinePayments/view/frontend/templates/info/checkmo.phtml index cf7496b7c566f..2dc226db4264c 100644 --- a/app/code/Magento/OfflinePayments/view/frontend/templates/info/checkmo.phtml +++ b/app/code/Magento/OfflinePayments/view/frontend/templates/info/checkmo.phtml @@ -4,21 +4,20 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile /** * @var $block \Magento\OfflinePayments\Block\Info\Checkmo */ ?> <dl class="payment-method checkmemo"> <dt class="title"><?= $block->escapeHtml($block->getMethod()->getTitle()) ?></dt> - <?php if ($block->getInfo()->getAdditionalInformation()): ?> - <?php if ($block->getPayableTo()): ?> + <?php if ($block->getInfo()->getAdditionalInformation()) : ?> + <?php if ($block->getPayableTo()) : ?> <dd class="content"> <strong><?= $block->escapeHtml(__('Make Check payable to')) ?></strong> <?= $block->escapeHtml($block->getPayableTo()) ?> </dd> <?php endif; ?> - <?php if ($block->getMailingAddress()): ?> + <?php if ($block->getMailingAddress()) : ?> <dd class="content"> <strong><?= $block->escapeHtml(__('Send Check to')) ?></strong> <address class="checkmo mailing address"> diff --git a/app/code/Magento/PageCache/view/frontend/templates/js/components.phtml b/app/code/Magento/PageCache/view/frontend/templates/js/components.phtml index 52a280651da78..adba26397a798 100644 --- a/app/code/Magento/PageCache/view/frontend/templates/js/components.phtml +++ b/app/code/Magento/PageCache/view/frontend/templates/js/components.phtml @@ -4,8 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Framework\View\Element\Js\Components $block */ ?> <?= $block->getChildHtml() ?> diff --git a/app/code/Magento/Payment/view/adminhtml/templates/form/cc.phtml b/app/code/Magento/Payment/view/adminhtml/templates/form/cc.phtml index 8e4127c4cbb11..678bde815d370 100644 --- a/app/code/Magento/Payment/view/adminhtml/templates/form/cc.phtml +++ b/app/code/Magento/Payment/view/adminhtml/templates/form/cc.phtml @@ -4,7 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile /** * @var \Magento\Payment\Block\Adminhtml\Transparent\Form $block */ @@ -23,8 +22,8 @@ $ccExpYear = $block->getInfoData('cc_exp_year'); <select id="<?= /* @noEscape */ $code ?>_cc_type" name="payment[cc_type]" class="required-entry validate-cc-type-select admin__control-select"> <option value=""></option> - <?php foreach ($block->getCcAvailableTypes() as $typeCode => $typeName): ?> - <option value="<?= $block->escapeHtml($typeCode) ?>" <?php if ($typeCode == $ccType): ?>selected="selected"<?php endif ?>> + <?php foreach ($block->getCcAvailableTypes() as $typeCode => $typeName) : ?> + <option value="<?= $block->escapeHtml($typeCode) ?>" <?php if ($typeCode == $ccType) : ?>selected="selected"<?php endif ?>> <?= $block->escapeHtml($typeName) ?> </option> <?php endforeach ?> @@ -48,18 +47,18 @@ $ccExpYear = $block->getInfoData('cc_exp_year'); <div class="admin__field-control"> <select id="<?= /* @noEscape */ $code ?>_expiration" name="payment[cc_exp_month]" class="admin__control-select admin__control-select-month validate-cc-exp required-entry"> - <?php foreach ($block->getCcMonths() as $k => $v): ?> + <?php foreach ($block->getCcMonths() as $k => $v) : ?> <option value="<?= $block->escapeHtml($k) ?>" - <?php if ($k == $ccExpMonth): ?>selected="selected"<?php endif ?>> + <?php if ($k == $ccExpMonth) : ?>selected="selected"<?php endif ?>> <?= $block->escapeHtml($v) ?> </option> <?php endforeach; ?> </select> <select id="<?= /* @noEscape */ $code ?>_expiration_yr" name="payment[cc_exp_year]" class="admin__control-select admin__control-select-year required-entry"> - <?php foreach ($block->getCcYears() as $k => $v): ?> + <?php foreach ($block->getCcYears() as $k => $v) : ?> <option value="<?= /* @noEscape */ $k ? $block->escapeHtml($k) : '' ?>" - <?php if ($k == $ccExpYear): ?>selected="selected"<?php endif ?>> + <?php if ($k == $ccExpYear) : ?>selected="selected"<?php endif ?>> <?= $block->escapeHtml($v) ?> </option> <?php endforeach ?> @@ -67,7 +66,7 @@ $ccExpYear = $block->getInfoData('cc_exp_year'); </div> </div> - <?php if ($block->hasVerification()): ?> + <?php if ($block->hasVerification()) : ?> <div class="field-number required admin__field _required"> <label class="admin__field-label" for="<?= /* @noEscape */ $code ?>_cc_cid"> <span><?= $block->escapeHtml(__('Card Verification Number')) ?></span> diff --git a/app/code/Magento/Payment/view/adminhtml/templates/info/default.phtml b/app/code/Magento/Payment/view/adminhtml/templates/info/default.phtml index 3c55e97ec580d..8b9c37f112560 100644 --- a/app/code/Magento/Payment/view/adminhtml/templates/info/default.phtml +++ b/app/code/Magento/Payment/view/adminhtml/templates/info/default.phtml @@ -4,7 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile /** * @var \Magento\Payment\Block\Info $block * @see \Magento\Payment\Block\Info @@ -13,9 +12,9 @@ $specificInfo = $block->getSpecificInformation(); ?> <?= $block->escapeHtml($block->getMethod()->getTitle()) ?> -<?php if ($specificInfo): ?> +<?php if ($specificInfo) : ?> <table class="data-table admin__table-secondary"> - <?php foreach ($specificInfo as $label => $value):?> + <?php foreach ($specificInfo as $label => $value) : ?> <tr> <th><?= $block->escapeHtml($label) ?>:</th> <td> diff --git a/app/code/Magento/Payment/view/adminhtml/templates/info/instructions.phtml b/app/code/Magento/Payment/view/adminhtml/templates/info/instructions.phtml index e95237cc82021..f60c1d063addf 100644 --- a/app/code/Magento/Payment/view/adminhtml/templates/info/instructions.phtml +++ b/app/code/Magento/Payment/view/adminhtml/templates/info/instructions.phtml @@ -4,14 +4,13 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile /** * @var \Magento\Payment\Block\Info $block * @see \Magento\Payment\Block\Info */ ?> <p><?= $block->escapeHtml($block->getMethod()->getTitle()) ?></p> -<?php if ($block->getInstructions()): ?> +<?php if ($block->getInstructions()) : ?> <table> <tbody> <tr> diff --git a/app/code/Magento/Payment/view/adminhtml/templates/info/pdf/default.phtml b/app/code/Magento/Payment/view/adminhtml/templates/info/pdf/default.phtml index 7acac62f65d38..a8583ea5549fe 100644 --- a/app/code/Magento/Payment/view/adminhtml/templates/info/pdf/default.phtml +++ b/app/code/Magento/Payment/view/adminhtml/templates/info/pdf/default.phtml @@ -4,7 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile /** * @see \Magento\Payment\Block\Info * @var \Magento\Payment\Block\Info $block @@ -12,8 +11,8 @@ ?> <?= $block->escapeHtml($block->getMethod()->getTitle()) ?>{{pdf_row_separator}} -<?php if ($specificInfo = $block->getSpecificInformation()):?> - <?php foreach ($specificInfo as $label => $value):?> +<?php if ($specificInfo = $block->getSpecificInformation()) : ?> + <?php foreach ($specificInfo as $label => $value) : ?> <?= $block->escapeHtml($label) ?>: <?= $block->escapeHtml(implode(' ', $block->getValueAsArray($value))) ?> {{pdf_row_separator}} diff --git a/app/code/Magento/Payment/view/adminhtml/templates/info/substitution.phtml b/app/code/Magento/Payment/view/adminhtml/templates/info/substitution.phtml index 582b8ca8a24be..d187b64683e45 100644 --- a/app/code/Magento/Payment/view/adminhtml/templates/info/substitution.phtml +++ b/app/code/Magento/Payment/view/adminhtml/templates/info/substitution.phtml @@ -4,7 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile /** * @var \Magento\Payment\Block\Info $block */ diff --git a/app/code/Magento/Payment/view/adminhtml/templates/transparent/form.phtml b/app/code/Magento/Payment/view/adminhtml/templates/transparent/form.phtml index 5b65bbaa3d9b7..36b8c978c339f 100644 --- a/app/code/Magento/Payment/view/adminhtml/templates/transparent/form.phtml +++ b/app/code/Magento/Payment/view/adminhtml/templates/transparent/form.phtml @@ -4,8 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Payment\Block\Transparent\Form $block */ $code = $block->escapeHtml($block->getMethodCode()); $ccType = $block->getInfoData('cc_type'); @@ -48,9 +46,9 @@ $ccExpMonth = $block->getInfoData('cc_exp_month'); data-validate='{required:true, "validate-cc-type-select":"#<?= /* @noEscape */ $code ?>_cc_number"}' class="admin__control-select"> <option value=""><?= $block->escapeHtml(__('Please Select')) ?></option> - <?php foreach ($block->getCcAvailableTypes() as $typeCode => $typeName): ?> + <?php foreach ($block->getCcAvailableTypes() as $typeCode => $typeName) : ?> <option - value="<?= $block->escapeHtml($typeCode) ?>"<?php if ($typeCode == $ccType): ?> selected="selected"<?php endif ?>> + value="<?= $block->escapeHtml($typeCode) ?>"<?php if ($typeCode == $ccType) : ?> selected="selected"<?php endif ?>> <?= $block->escapeHtml($typeName) ?> </option> <?php endforeach ?> @@ -88,10 +86,10 @@ $ccExpMonth = $block->getInfoData('cc_exp_month'); data-container="<?= /* @noEscape */ $code ?>-cc-month" class="admin__control-select admin__control-select-month" data-validate='{required:true, "validate-cc-exp":"#<?= /* @noEscape */ $code ?>_expiration_yr"}'> - <?php foreach ($block->getCcMonths() as $k => $v): ?> + <?php foreach ($block->getCcMonths() as $k => $v) : ?> <option value="<?= /* @noEscape */ $k ? $block->escapeHtml($k) : '' ?>" - <?php if ($k == $ccExpMonth): ?> selected="selected"<?php endif; ?>> + <?php if ($k == $ccExpMonth) : ?> selected="selected"<?php endif; ?>> <?= $block->escapeHtml($v) ?> </option> <?php endforeach ?> @@ -100,17 +98,17 @@ $ccExpMonth = $block->getInfoData('cc_exp_month'); <select id="<?= /* @noEscape */ $code ?>_expiration_yr" name="payment[cc_exp_year]" class="admin__control-select admin__control-select-year" data-container="<?= /* @noEscape */ $code ?>-cc-year" data-validate='{required:true}'> - <?php foreach ($block->getCcYears() as $k => $v): ?> + <?php foreach ($block->getCcYears() as $k => $v) : ?> <option value="<?= /* @noEscape */ $k ? $block->escapeHtml($k) : '' ?>" - <?php if ($k == $ccExpYear): ?> selected="selected"<?php endif ?>> + <?php if ($k == $ccExpYear) : ?> selected="selected"<?php endif ?>> <?= $block->escapeHtml($v) ?> </option> <?php endforeach ?> </select> </div> </div> - <?php if ($block->hasVerification()): ?> + <?php if ($block->hasVerification()) : ?> <div class="admin__field _required field-cvv" id="<?= /* @noEscape */ $code ?>_cc_type_cvv_div"> <label for="<?= /* @noEscape */ $code ?>_cc_cid" class="admin__field-label"> <span><?= $block->escapeHtml(__('Card Verification Number')) ?></span> diff --git a/app/code/Magento/Payment/view/adminhtml/templates/transparent/iframe.phtml b/app/code/Magento/Payment/view/adminhtml/templates/transparent/iframe.phtml index 8ef51d4794f00..ece7106e91236 100644 --- a/app/code/Magento/Payment/view/adminhtml/templates/transparent/iframe.phtml +++ b/app/code/Magento/Payment/view/adminhtml/templates/transparent/iframe.phtml @@ -4,7 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile /** * @var \Magento\Payment\Block\Transparent\Iframe $block */ @@ -14,15 +13,15 @@ $params = $block->getParams(); <html> <head> <script> -<?php if (isset($params['redirect'])): ?> +<?php if (isset($params['redirect'])) : ?> window.location="<?= $block->escapeUrl($params['redirect']) ?>"; -<?php elseif (isset($params['redirect_parent'])): ?> +<?php elseif (isset($params['redirect_parent'])) : ?> window.top.location="<?= $block->escapeUrl($params['redirect_parent']) ?>"; -<?php elseif (isset($params['error_msg'])): ?> - window.top.alert(<?= /* @noEscape */ $this->helper('Magento\Framework\Json\Helper\Data')->jsonEncode($params['error_msg']) ?>); -<?php elseif (isset($params['order_success'])): ?> +<?php elseif (isset($params['error_msg'])) : ?> + window.top.alert(<?= /* @noEscape */ $this->helper(\Magento\Framework\Json\Helper\Data::class)->jsonEncode($params['error_msg']) ?>); +<?php elseif (isset($params['order_success'])) : ?> window.top.location = "<?= $block->escapeUrl($params['order_success']) ?>"; -<?php else: ?> +<?php else : ?> var require = window.top.require; require(['jquery'], function($) { $('#edit_form').trigger('processStop'); diff --git a/app/code/Magento/Payment/view/adminhtml/templates/transparent/info.phtml b/app/code/Magento/Payment/view/adminhtml/templates/transparent/info.phtml index 636779667f2b4..fb06f1a4dbf33 100644 --- a/app/code/Magento/Payment/view/adminhtml/templates/transparent/info.phtml +++ b/app/code/Magento/Payment/view/adminhtml/templates/transparent/info.phtml @@ -4,8 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** * @var \Magento\Payment\Block\Transparent\Info $block * @see \Magento\Payment\Block\Transparent\Info diff --git a/app/code/Magento/Payment/view/base/templates/info/pdf/default.phtml b/app/code/Magento/Payment/view/base/templates/info/pdf/default.phtml index 7acac62f65d38..a8583ea5549fe 100644 --- a/app/code/Magento/Payment/view/base/templates/info/pdf/default.phtml +++ b/app/code/Magento/Payment/view/base/templates/info/pdf/default.phtml @@ -4,7 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile /** * @see \Magento\Payment\Block\Info * @var \Magento\Payment\Block\Info $block @@ -12,8 +11,8 @@ ?> <?= $block->escapeHtml($block->getMethod()->getTitle()) ?>{{pdf_row_separator}} -<?php if ($specificInfo = $block->getSpecificInformation()):?> - <?php foreach ($specificInfo as $label => $value):?> +<?php if ($specificInfo = $block->getSpecificInformation()) : ?> + <?php foreach ($specificInfo as $label => $value) : ?> <?= $block->escapeHtml($label) ?>: <?= $block->escapeHtml(implode(' ', $block->getValueAsArray($value))) ?> {{pdf_row_separator}} diff --git a/app/code/Magento/Payment/view/frontend/templates/form/cc.phtml b/app/code/Magento/Payment/view/frontend/templates/form/cc.phtml index 926139e60c958..5f61a3ee1d400 100644 --- a/app/code/Magento/Payment/view/frontend/templates/form/cc.phtml +++ b/app/code/Magento/Payment/view/frontend/templates/form/cc.phtml @@ -4,7 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile /** * @var \Magento\Payment\Block\Transparent\Form $block */ @@ -30,9 +29,9 @@ $ccExpYear = $block->getInfoData('cc_exp_year'); }' class="select"> <option value=""><?= $block->escapeHtml(__('--Please Select--')) ?></option> - <?php foreach ($block->getCcAvailableTypes() as $typeCode => $typeName): ?> + <?php foreach ($block->getCcAvailableTypes() as $typeCode => $typeName) : ?> <option value="<?= $block->escapeHtml($typeCode) ?>" - <?php if ($typeCode == $ccType): ?> selected="selected"<?php endif; ?>> + <?php if ($typeCode == $ccType) : ?> selected="selected"<?php endif; ?>> <?= $block->escapeHtml($typeName) ?> </option> <?php endforeach; ?> @@ -63,9 +62,9 @@ $ccExpYear = $block->getInfoData('cc_exp_year'); <div class="control"> <select id="<?= /* @noEscape */ $code ?>_expiration" name="payment[cc_exp_month]" class="select month" data-validate='{required:true, "validate-cc-exp":"#<?= /* @noEscape */ $code ?>_expiration_yr"}'> - <?php foreach ($block->getCcMonths() as $k => $v): ?> + <?php foreach ($block->getCcMonths() as $k => $v) : ?> <option value="<?= /* @noEscape */ $k ? $block->escapeHtml($k) : '' ?>" - <?php if ($k == $ccExpMonth): ?> selected="selected"<?php endif; ?>> + <?php if ($k == $ccExpMonth) : ?> selected="selected"<?php endif; ?>> <?= $block->escapeHtml($v) ?> </option> <?php endforeach; ?> @@ -76,9 +75,9 @@ $ccExpYear = $block->getInfoData('cc_exp_year'); <div class="control"> <select id="<?= /* @noEscape */ $code ?>_expiration_yr" name="payment[cc_exp_year]" class="select year" data-validate='{required:true}'> - <?php foreach ($block->getCcYears() as $k => $v): ?> + <?php foreach ($block->getCcYears() as $k => $v) : ?> <option value="<?= /* @noEscape */ $k ? $block->escapeHtml($k) : '' ?> - "<?php if ($k == $ccExpYear): ?> selected="selected"<?php endif; ?>> + "<?php if ($k == $ccExpYear) : ?> selected="selected"<?php endif; ?>> <?= $block->escapeHtml($v) ?> </option> <?php endforeach; ?> @@ -88,7 +87,7 @@ $ccExpYear = $block->getInfoData('cc_exp_year'); </div> </div> </div> - <?php if ($block->hasVerification()): ?> + <?php if ($block->hasVerification()) : ?> <div class="field cvv required" id="<?= /* @noEscape */ $code ?>_cc_type_cvv_div"> <label for="<?= /* @noEscape */ $code ?>_cc_cid" class="label"> <span><?= $block->escapeHtml(__('Card Verification Number')) ?></span> diff --git a/app/code/Magento/Payment/view/frontend/templates/info/default.phtml b/app/code/Magento/Payment/view/frontend/templates/info/default.phtml index a6311b8ca0de6..8649c0416f124 100644 --- a/app/code/Magento/Payment/view/frontend/templates/info/default.phtml +++ b/app/code/Magento/Payment/view/frontend/templates/info/default.phtml @@ -4,8 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** * @var \Magento\Payment\Block\Info $block * @see \Magento\Payment\Block\Info @@ -15,11 +13,11 @@ $title = $block->escapeHtml($block->getMethod()->getTitle()); ?> <dl class="payment-method"> <dt class="title"><?= /* @noEscape */ $title ?></dt> -<?php if ($specificInfo):?> +<?php if ($specificInfo) : ?> <dd class="content"> <table class="data table"> <caption class="table-caption"><?= /* @noEscape */ $title ?></caption> - <?php foreach ($specificInfo as $label => $value):?> + <?php foreach ($specificInfo as $label => $value) : ?> <tr> <th scope="row"><?= $block->escapeHtml($label) ?></th> <td> diff --git a/app/code/Magento/Payment/view/frontend/templates/info/instructions.phtml b/app/code/Magento/Payment/view/frontend/templates/info/instructions.phtml index 653d0502c6354..60efae16b1711 100644 --- a/app/code/Magento/Payment/view/frontend/templates/info/instructions.phtml +++ b/app/code/Magento/Payment/view/frontend/templates/info/instructions.phtml @@ -4,7 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile /** * @var \Magento\Payment\Block\Info $block * @see \Magento\Payment\Block\Info @@ -12,7 +11,7 @@ ?> <dl class="payment-method"> <dt class="title"><?= $block->escapeHtml($block->getMethod()->getTitle()) ?></dt> -<?php if ($block->getInstructions()): ?> +<?php if ($block->getInstructions()) : ?> <dd class="content"><?= /* @noEscape */ nl2br($block->escapeHtml($block->getInstructions())) ?></dd> <?php endif; ?> </dl> diff --git a/app/code/Magento/Payment/view/frontend/templates/info/pdf/default.phtml b/app/code/Magento/Payment/view/frontend/templates/info/pdf/default.phtml index 7acac62f65d38..a8583ea5549fe 100644 --- a/app/code/Magento/Payment/view/frontend/templates/info/pdf/default.phtml +++ b/app/code/Magento/Payment/view/frontend/templates/info/pdf/default.phtml @@ -4,7 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile /** * @see \Magento\Payment\Block\Info * @var \Magento\Payment\Block\Info $block @@ -12,8 +11,8 @@ ?> <?= $block->escapeHtml($block->getMethod()->getTitle()) ?>{{pdf_row_separator}} -<?php if ($specificInfo = $block->getSpecificInformation()):?> - <?php foreach ($specificInfo as $label => $value):?> +<?php if ($specificInfo = $block->getSpecificInformation()) : ?> + <?php foreach ($specificInfo as $label => $value) : ?> <?= $block->escapeHtml($label) ?>: <?= $block->escapeHtml(implode(' ', $block->getValueAsArray($value))) ?> {{pdf_row_separator}} diff --git a/app/code/Magento/Payment/view/frontend/templates/transparent/form.phtml b/app/code/Magento/Payment/view/frontend/templates/transparent/form.phtml index 47390e321f6d4..c1d1156d273cf 100644 --- a/app/code/Magento/Payment/view/frontend/templates/transparent/form.phtml +++ b/app/code/Magento/Payment/view/frontend/templates/transparent/form.phtml @@ -4,8 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Payment\Block\Transparent\Form $block */ $code = $block->escapeHtml($block->getMethodCode()); $ccExpMonth = $block->getInfoData('cc_exp_month'); @@ -17,7 +15,7 @@ $content = '<img src=\"' . $block->getViewFileUrl('Magento_Checkout::cvv.png') . ?> <!-- IFRAME for request to Payment Gateway --> -<iframe width="0" height="0" id="<?= /* @noescape */ $code ?>-transparent-iframe" +<iframe width="0" height="0" id="<?= /* @noEscape */ $code ?>-transparent-iframe" data-container="<?= /* @noEscape */ $code ?>-transparent-iframe" allowtransparency="true" frameborder="0" name="iframeTransparent" style="display:none;width:100%;background-color:transparent" src="<?= $block->escapeUrl($block->getViewFileUrl('blank.html')) ?>"></iframe> @@ -47,9 +45,9 @@ $content = '<img src=\"' . $block->getViewFileUrl('Magento_Checkout::cvv.png') . "validate-cc-type-select":"#<?= /* @noEscape */ $code ?>_cc_number" }'> <option value=""><?= $block->escapeHtml(__('--Please Select--')) ?></option> - <?php foreach ($block->getCcAvailableTypes() as $typeCode => $typeName): ?> + <?php foreach ($block->getCcAvailableTypes() as $typeCode => $typeName) : ?> <option value="<?= $block->escapeHtml($typeCode) ?>" - <?php if ($typeCode == $ccType): ?> selected="selected"<?php endif; ?>> + <?php if ($typeCode == $ccType) : ?> selected="selected"<?php endif; ?>> <?= $block->escapeHtml($typeName) ?></option> <?php endforeach ?> </select> @@ -85,9 +83,9 @@ $content = '<img src=\"' . $block->getViewFileUrl('Magento_Checkout::cvv.png') . required:true, "validate-cc-exp":"#<?= /* @noEscape */ $code ?>_expiration_yr" }'> - <?php foreach ($block->getCcMonths() as $k => $v): ?> + <?php foreach ($block->getCcMonths() as $k => $v) : ?> <option value="<?= /* @noEscape */ $k ? $block->escapeHtml($k) : '' ?>" - <?php if ($k == $ccExpMonth): ?> selected="selected"<?php endif; ?>> + <?php if ($k == $ccExpMonth) : ?> selected="selected"<?php endif; ?>> <?= $block->escapeHtml($v) ?> </option> <?php endforeach ?> @@ -99,9 +97,9 @@ $content = '<img src=\"' . $block->getViewFileUrl('Magento_Checkout::cvv.png') . <select id="<?= /* @noEscape */ $code ?>_expiration_yr" name="payment[cc_exp_year]" class="year" data-container="<?= /* @noEscape */ $code ?>-cc-year" data-validate='{required:true}'> - <?php foreach ($block->getCcYears() as $k => $v): ?> + <?php foreach ($block->getCcYears() as $k => $v) : ?> <option value="<?= /* @noEscape */ $k ? $block->escapeHtml($k) : '' ?>" - <?php if ($k == $ccExpYear): ?> selected="selected"<?php endif; ?>> + <?php if ($k == $ccExpYear) : ?> selected="selected"<?php endif; ?>> <?= $block->escapeHtml($v) ?> </option> <?php endforeach ?> @@ -111,7 +109,7 @@ $content = '<img src=\"' . $block->getViewFileUrl('Magento_Checkout::cvv.png') . </div> </div> </div> - <?php if ($block->hasVerification()): ?> + <?php if ($block->hasVerification()) : ?> <div class="field required cvv" id="<?= /* @noEscape */ $code ?>_cc_type_cvv_div"> <label for="<?= /* @noEscape */ $code ?>_cc_cid" class="label"> <span><?= $block->escapeHtml(__('Card Verification Number')) ?></span> diff --git a/app/code/Magento/Payment/view/frontend/templates/transparent/iframe.phtml b/app/code/Magento/Payment/view/frontend/templates/transparent/iframe.phtml index ea06c60c30e20..d99cc0155c28e 100644 --- a/app/code/Magento/Payment/view/frontend/templates/transparent/iframe.phtml +++ b/app/code/Magento/Payment/view/frontend/templates/transparent/iframe.phtml @@ -4,17 +4,15 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Payment\Block\Transparent\Iframe $block */ $params = $block->getParams(); ?> <html> <head> <script> - <?php if (isset($params['redirect'])): ?> + <?php if (isset($params['redirect'])) : ?> window.location="<?= $block->escapeUrl($params['redirect']) ?>"; - <?php elseif (isset($params['redirect_parent'])): ?> + <?php elseif (isset($params['redirect_parent'])) : ?> var require = window.top.require; require( [ @@ -26,7 +24,7 @@ $params = $block->getParams(); parent.location="<?= $block->escapeUrl($params['redirect_parent']) ?>"; } ); - <?php elseif (isset($params['error_msg'])): ?> + <?php elseif (isset($params['error_msg'])) : ?> var require = window.top.require; require( [ @@ -44,7 +42,7 @@ $params = $block->getParams(); }); } ); - <?php elseif (isset($params['multishipping'])): ?> + <?php elseif (isset($params['multishipping'])) : ?> var require = window.top.require; require( [ @@ -56,9 +54,9 @@ $params = $block->getParams(); $(parent.document).find('#multishipping-billing-form').submit(); } ); - <?php elseif (isset($params['order_success'])): ?> + <?php elseif (isset($params['order_success'])) : ?> window.top.location = "<?= $block->escapeUrl($params['order_success']) ?>"; - <?php else: ?> + <?php else : ?> var require = window.top.require; require( [ diff --git a/app/code/Magento/Payment/view/frontend/templates/transparent/info.phtml b/app/code/Magento/Payment/view/frontend/templates/transparent/info.phtml index 9304f24a3b4b1..084e1e0ebf329 100644 --- a/app/code/Magento/Payment/view/frontend/templates/transparent/info.phtml +++ b/app/code/Magento/Payment/view/frontend/templates/transparent/info.phtml @@ -4,8 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** * @var \Magento\Payment\Block\Transparent\Info $block * @see \Magento\Payment\Block\Transparent\Info diff --git a/app/code/Magento/Paypal/view/adminhtml/templates/billing/agreement/form.phtml b/app/code/Magento/Paypal/view/adminhtml/templates/billing/agreement/form.phtml index a474be1e8b881..19cebe863b7ef 100644 --- a/app/code/Magento/Paypal/view/adminhtml/templates/billing/agreement/form.phtml +++ b/app/code/Magento/Paypal/view/adminhtml/templates/billing/agreement/form.phtml @@ -4,7 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile /** @var \Magento\Paypal\Block\Adminhtml\Billing\Agreement\View\Form $block */ ?> <?php $code = $block->escapeHtml($block->getMethodCode()) ?> @@ -18,7 +17,7 @@ name="payment[<?= $block->escapeHtml($block->getTransportBAId()) ?>]" class="required-entry admin__control-select"> <option value=""><?= $block->escapeHtml(__('Please Select')) ?></option> - <?php foreach ($block->getBillingAgreements() as $id => $referenceId): ?> + <?php foreach ($block->getBillingAgreements() as $id => $referenceId) : ?> <option value="<?= $block->escapeHtml($id) ?>"> <?= $block->escapeHtml($referenceId) ?> </option> diff --git a/app/code/Magento/Paypal/view/adminhtml/templates/payflowpro/vault.phtml b/app/code/Magento/Paypal/view/adminhtml/templates/payflowpro/vault.phtml index 74c020e4d5e8a..5cba96518f28e 100644 --- a/app/code/Magento/Paypal/view/adminhtml/templates/payflowpro/vault.phtml +++ b/app/code/Magento/Paypal/view/adminhtml/templates/payflowpro/vault.phtml @@ -1,10 +1,10 @@ <?php -use Magento\Vault\Model\Ui\TokenUiComponentProviderInterface; /** * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile + +use Magento\Vault\Model\Ui\TokenUiComponentProviderInterface; /** @var \Magento\Framework\View\Element\Template $block */ $details = $block->getData('details'); @@ -14,9 +14,7 @@ $id = $block->escapeHtml($block->getData('id')); <div data-mage-init='{ "Magento_Paypal/js/payflowpro/vault": { "container": "payment_<?= /* @noEscape */ $id ?>", - "publicHash": "<?= $block->escapeHtml( - $block->getData(TokenUiComponentProviderInterface::COMPONENT_PUBLIC_HASH) - ); ?>" + "publicHash": "<?= $block->escapeHtml($block->getData(TokenUiComponentProviderInterface::COMPONENT_PUBLIC_HASH)); ?>" } }' id="payment_<?= /* @noEscape */ $id ?>" class="admin__field"> <div class="admin__field-control control"> @@ -28,8 +26,6 @@ $id = $block->escapeHtml($block->getData('id')); <span><?= $block->escapeHtml(__('ending')) ?></span> <span><?= $block->escapeHtml($details['cc_last_4']) ?></span> (<span><?= $block->escapeHtml(__('expires')) ?></span>: - <span><?php /* @noEscape */ echo $block->escapeHtml( - $details['cc_exp_month'] . "/" . $details['cc_exp_year'] - ); ?></span>) + <span><?= /* @noEscape */ $block->escapeHtml($details['cc_exp_month'] . "/" . $details['cc_exp_year']); ?></span>) </div> </div> diff --git a/app/code/Magento/Paypal/view/adminhtml/templates/payment/form/billing/agreement.phtml b/app/code/Magento/Paypal/view/adminhtml/templates/payment/form/billing/agreement.phtml index 64017a72b94dc..a4e7b6974c737 100644 --- a/app/code/Magento/Paypal/view/adminhtml/templates/payment/form/billing/agreement.phtml +++ b/app/code/Magento/Paypal/view/adminhtml/templates/payment/form/billing/agreement.phtml @@ -4,7 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile /* @var $block \Magento\Paypal\Block\Payment\Form\Billing\Agreement */ ?> <?php $code = $block->escapeHtml($block->getMethodCode()) ?> @@ -20,7 +19,7 @@ name="payment[<?= $block->escapeHtml($block->getTransportName()) ?>]" class="required-entry admin__control-select"> <option value=""><?= $block->escapeHtml(__('Please Select')) ?></option> - <?php foreach ($block->getBillingAgreements() as $id => $referenceId): ?> + <?php foreach ($block->getBillingAgreements() as $id => $referenceId) : ?> <option value="<?= $block->escapeHtml($id) ?>" <?= ($id == $block->getInfoData($block->getTransportName())) ? ' selected="selected"' : ''; diff --git a/app/code/Magento/Paypal/view/adminhtml/templates/system/config/fieldset/hint.phtml b/app/code/Magento/Paypal/view/adminhtml/templates/system/config/fieldset/hint.phtml index e2e52d03982ef..831c03a77980e 100644 --- a/app/code/Magento/Paypal/view/adminhtml/templates/system/config/fieldset/hint.phtml +++ b/app/code/Magento/Paypal/view/adminhtml/templates/system/config/fieldset/hint.phtml @@ -4,22 +4,16 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile /** * @see \Magento\Paypal\Block\System\Config\Fieldset\Hint * @var \Magento\Paypal\Block\Adminhtml\System\Config\Fieldset\Hint $block */ $helpLink = $block->escapeUrl($block->getHelpLink()); ?> -<?php -if ($helpLink): -?> +<?php if ($helpLink) : ?> <div class="paypal-payment-notice"> <?= $block->escapeHtml(__('Not sure what PayPal payment method to use? Click ')) ?> - <a href="<?php /* @noEscape */ - echo $helpLink; ?>" target="_blank"><?= $block->escapeHtml(__('here')) ?></a> + <a href="<?= /* @noEscape */$helpLink; ?>" target="_blank"><?= $block->escapeHtml(__('here')) ?></a> <?= $block->escapeHtml(__(' to learn more.')) ?> </div> -<?php -endif; -?> +<?php endif; ?> diff --git a/app/code/Magento/Paypal/view/adminhtml/templates/system/config/payflowlink/advanced.phtml b/app/code/Magento/Paypal/view/adminhtml/templates/system/config/payflowlink/advanced.phtml index 127d5bd14db42..d33e4ea1ebdb0 100644 --- a/app/code/Magento/Paypal/view/adminhtml/templates/system/config/payflowlink/advanced.phtml +++ b/app/code/Magento/Paypal/view/adminhtml/templates/system/config/payflowlink/advanced.phtml @@ -4,7 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile /* * @var $block \Magento\Paypal\Block\Adminhtml\System\Config\Payflowlink\Advanced */ diff --git a/app/code/Magento/Paypal/view/adminhtml/templates/system/config/payflowlink/info.phtml b/app/code/Magento/Paypal/view/adminhtml/templates/system/config/payflowlink/info.phtml index ad53e6358081e..8ff97bd872569 100644 --- a/app/code/Magento/Paypal/view/adminhtml/templates/system/config/payflowlink/info.phtml +++ b/app/code/Magento/Paypal/view/adminhtml/templates/system/config/payflowlink/info.phtml @@ -4,7 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile /** * @see \Magento\Paypal\Block\Adminhtml\System\Config\Payflowlink\Info * @var \Magento\Paypal\Block\Adminhtml\System\Config\Payflowlink\Info $block diff --git a/app/code/Magento/Paypal/view/adminhtml/templates/transparent/form.phtml b/app/code/Magento/Paypal/view/adminhtml/templates/transparent/form.phtml index 532fa88c4986a..f4318b40fef1c 100644 --- a/app/code/Magento/Paypal/view/adminhtml/templates/transparent/form.phtml +++ b/app/code/Magento/Paypal/view/adminhtml/templates/transparent/form.phtml @@ -4,8 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Paypal\Block\Adminhtml\Payflowpro\CcForm $block */ $code = $block->escapeHtml($block->getMethodCode()); $ccType = $block->getInfoData('cc_type'); @@ -48,9 +46,9 @@ $ccExpMonth = $block->getInfoData('cc_exp_month'); data-validate='{required:true, "validate-cc-type-select":"#<?= /* @noEscape */ $code ?>_cc_number"}' class="admin__control-select"> <option value=""><?= $block->escapeHtml(__('Please Select')) ?></option> - <?php foreach ($block->getCcAvailableTypes() as $typeCode => $typeName): ?> + <?php foreach ($block->getCcAvailableTypes() as $typeCode => $typeName) : ?> <option - value="<?= $block->escapeHtml($typeCode) ?>"<?php if ($typeCode == $ccType): ?> selected="selected"<?php endif ?>> + value="<?= $block->escapeHtml($typeCode) ?>"<?php if ($typeCode == $ccType) : ?> selected="selected"<?php endif ?>> <?= $block->escapeHtml($typeName) ?> </option> <?php endforeach ?> @@ -88,10 +86,10 @@ $ccExpMonth = $block->getInfoData('cc_exp_month'); data-container="<?= /* @noEscape */ $code ?>-cc-month" class="admin__control-select admin__control-select-month" data-validate='{required:true, "validate-cc-exp":"#<?= /* @noEscape */ $code ?>_expiration_yr"}'> - <?php foreach ($block->getCcMonths() as $k => $v): ?> + <?php foreach ($block->getCcMonths() as $k => $v) : ?> <option value="<?= /* @noEscape */ $k ? $block->escapeHtml($k) : '' ?>" - <?php if ($k == $ccExpMonth): ?> selected="selected"<?php endif; ?>> + <?php if ($k == $ccExpMonth) : ?> selected="selected"<?php endif; ?>> <?= $block->escapeHtml($v) ?> </option> <?php endforeach ?> @@ -100,17 +98,17 @@ $ccExpMonth = $block->getInfoData('cc_exp_month'); <select id="<?= /* @noEscape */ $code ?>_expiration_yr" name="payment[cc_exp_year]" class="admin__control-select admin__control-select-year" data-container="<?= /* @noEscape */ $code ?>-cc-year" data-validate='{required:true}'> - <?php foreach ($block->getCcYears() as $k => $v): ?> + <?php foreach ($block->getCcYears() as $k => $v) : ?> <option value="<?= /* @noEscape */ $k ? $block->escapeHtml($k) : '' ?>" - <?php if ($k == $ccExpYear): ?> selected="selected"<?php endif ?>> + <?php if ($k == $ccExpYear) : ?> selected="selected"<?php endif ?>> <?= $block->escapeHtml($v) ?> </option> <?php endforeach ?> </select> </div> </div> - <?php if ($block->hasVerification()): ?> + <?php if ($block->hasVerification()) : ?> <div class="admin__field _required field-cvv" id="<?= /* @noEscape */ $code ?>_cc_type_cvv_div"> <label for="<?= /* @noEscape */ $code ?>_cc_cid" class="admin__field-label"> <span><?= $block->escapeHtml(__('Card Verification Number')) ?></span> @@ -128,7 +126,7 @@ $ccExpMonth = $block->getInfoData('cc_exp_month'); </div> <?php endif; ?> - <?php if($block->isVaultEnabled()): ?> + <?php if ($block->isVaultEnabled()) : ?> <div class="admin__field admin__field-option field-tooltip-content"> <input type="checkbox" id="<?= /* @noEscape */ $code ?>_vault" diff --git a/app/code/Magento/Paypal/view/adminhtml/templates/transparent/iframe.phtml b/app/code/Magento/Paypal/view/adminhtml/templates/transparent/iframe.phtml index 63d2d437503a9..4edb109d6a4b9 100644 --- a/app/code/Magento/Paypal/view/adminhtml/templates/transparent/iframe.phtml +++ b/app/code/Magento/Paypal/view/adminhtml/templates/transparent/iframe.phtml @@ -4,7 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile /** * @var \Magento\Payment\Block\Transparent\Iframe $block */ @@ -14,15 +13,15 @@ $params = $block->getParams(); <html> <head> <script> -<?php if (isset($params['redirect'])): ?> +<?php if (isset($params['redirect'])) : ?> window.location="<?= $block->escapeUrl($params['redirect']) ?>"; -<?php elseif (isset($params['redirect_parent'])): ?> +<?php elseif (isset($params['redirect_parent'])) : ?> window.top.location="<?= $block->escapeUrl($params['redirect_parent']) ?>"; -<?php elseif (isset($params['error_msg'])): ?> - window.top.alert(<?= /* @noEscape */ $this->helper('Magento\Framework\Json\Helper\Data')->jsonEncode($params['error_msg']) ?>); -<?php elseif (isset($params['order_success'])): ?> +<?php elseif (isset($params['error_msg'])) : ?> + window.top.alert(<?= /* @noEscape */ $this->helper(\Magento\Framework\Json\Helper\Data::class)->jsonEncode($params['error_msg']) ?>); +<?php elseif (isset($params['order_success'])) : ?> window.top.location = "<?= $block->escapeUrl($params['order_success']) ?>"; -<?php else: ?> +<?php else : ?> var require = window.top.require; require(['jquery'], function($) { var cc_number = $("input[name='payment[cc_number]']").val(); diff --git a/app/code/Magento/Paypal/view/frontend/templates/billing/agreement/view.phtml b/app/code/Magento/Paypal/view/frontend/templates/billing/agreement/view.phtml index 7b06c19d639e9..40f56fb946260 100644 --- a/app/code/Magento/Paypal/view/frontend/templates/billing/agreement/view.phtml +++ b/app/code/Magento/Paypal/view/frontend/templates/billing/agreement/view.phtml @@ -4,7 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile /** * @var \Magento\Paypal\Block\Billing\Agreement\View $block */ @@ -16,7 +15,7 @@ $relatedOrders = $block->getRelatedOrders(); <?= $block->escapeHtml(__('Billing Agreement # ')) ?> <?= $block->escapeHtml($block->getReferenceId()) ?> </strong> - <?php if ($block->getCanCancel()): ?> + <?php if ($block->getCanCancel()) : ?> <button data-mage-init='{"Magento_Paypal/js/in-context/billing-agreement": { "cancelMessage" : "<?= $block->escapeHtml(__('Are you sure you want to do this?')) ?>", "cancelUrl" : "<?= $block->escapeUrl($block->getCancelUrl()) ?>" @@ -39,7 +38,7 @@ $relatedOrders = $block->getRelatedOrders(); <th scope="col" class="col id"><?= $block->escapeHtml(__('Reference ID:')) ?></th> <th scope="col" class="col status"><?= $block->escapeHtml(__('Status:')) ?></th> <th scope="col" class="col created"><?= $block->escapeHtml(__('Created:')) ?></th> - <?php if ($block->getAgreementUpdatedAt()): ?> + <?php if ($block->getAgreementUpdatedAt()) : ?> <th scope="col" class="col updated"><?= $block->escapeHtml(__('Updated:')) ?></th> <?php endif; ?> <th scope="col" class="col payment"><?= $block->escapeHtml(__('Payment Method:')) ?></th> @@ -56,7 +55,7 @@ $relatedOrders = $block->getRelatedOrders(); <td data-th="<?= $block->escapeHtml(__('Created:')) ?>" class="col created"> <?= $block->escapeHtml($block->getAgreementCreatedAt()) ?> </td> - <?php if ($block->getAgreementUpdatedAt()): ?> + <?php if ($block->getAgreementUpdatedAt()) : ?> <td data-th="<?= $block->escapeHtml(__('Updated:')) ?>" class="col updated"> <?= $block->escapeHtml($block->getAgreementUpdatedAt()) ?> </td> @@ -70,7 +69,7 @@ $relatedOrders = $block->getRelatedOrders(); </div> </div> </div> -<?php if (count($relatedOrders) > 0): ?> +<?php if (count($relatedOrders) > 0) : ?> <div class="block block-billing-orders-view"> <?= $block->getChildHtml('pager') ?> <div class="block-title"> @@ -91,11 +90,12 @@ $relatedOrders = $block->getRelatedOrders(); </tr> </thead> <tbody> - <?php foreach ($relatedOrders as $order): ?> + <?php foreach ($relatedOrders as $order) : ?> <tr> <td data-th="<?= $block->escapeHtml(__('Order #')) ?>" class="col id"> <?= $block->escapeHtml($block->getOrderItemValue( - $order, 'order_increment_id' + $order, + 'order_increment_id' )); ?> </td> <td data-th="<?= $block->escapeHtml(__('Date')) ?>" class="col date"> @@ -103,7 +103,8 @@ $relatedOrders = $block->getRelatedOrders(); </td> <td data-th="<?= $block->escapeHtml(__('Ship To')) ?>" class="col shipto"> <?= $block->escapeHtml($block->getOrderItemValue( - $order, 'shipping_address' + $order, + 'shipping_address' )); ?> </td> <td data-th="<?= $block->escapeHtml(__('Order Total')) ?>" class="col total"> @@ -111,12 +112,14 @@ $relatedOrders = $block->getRelatedOrders(); </td> <td data-th="<?= $block->escapeHtml(__('Order Status')) ?>" class="col status"> <?= $block->escapeHtml($block->getOrderItemValue( - $order, 'status_label' + $order, + 'status_label' )); ?> </td> <td data-th="" class="col actions"> <a href="<?= $block->escapeUrl($block->getOrderItemValue( - $order, 'view_url' + $order, + 'view_url' )); ?>" class="action view"> <span><?= $block->escapeHtml(__('View Order')) ?></span> </a> diff --git a/app/code/Magento/Paypal/view/frontend/templates/billing/agreements.phtml b/app/code/Magento/Paypal/view/frontend/templates/billing/agreements.phtml index 77987c948b686..c8fc6fcb36b66 100644 --- a/app/code/Magento/Paypal/view/frontend/templates/billing/agreements.phtml +++ b/app/code/Magento/Paypal/view/frontend/templates/billing/agreements.phtml @@ -4,7 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile /** * @var \Magento\Paypal\Block\Billing\Agreements $block */ @@ -13,7 +12,7 @@ $billingAgreements = $block->getBillingAgreements(); $paymentMethods = $block->getWizardPaymentMethodOptions(); ?> <div class="account-billing-agreements"> - <?php if (count($billingAgreements) > 0): ?> + <?php if (count($billingAgreements) > 0) : ?> <?= $block->getChildHtml('pager') ?> <div class="table-wrapper billing-agreements"> <table id="billing-agreements" class="data table table-billing-agreements"> @@ -29,7 +28,7 @@ $paymentMethods = $block->getWizardPaymentMethodOptions(); </tr> </thead> <tbody> - <?php foreach ($billingAgreements as $item): ?> + <?php foreach ($billingAgreements as $item) : ?> <tr> <td data-th="<?= $block->escapeHtml(__('Reference ID')) ?>" class="col id"> <?= $block->escapeHtml($block->getItemValue($item, 'reference_id')) ?> @@ -57,13 +56,13 @@ $paymentMethods = $block->getWizardPaymentMethodOptions(); </tbody> </table> </div> - <?php else: ?> + <?php else : ?> <div class="message info empty"> <span><?= $block->escapeHtml(__('There are no billing agreements yet.')) ?></span> </div> <?php endif; ?> - <?php if ($paymentMethods): ?> + <?php if ($paymentMethods) : ?> <form action="<?= $block->escapeUrl($block->getCreateUrl()) ?>" method="post" class="form form-new-agreement"> <fieldset class="fieldset"> @@ -79,7 +78,7 @@ $paymentMethods = $block->getWizardPaymentMethodOptions(); <div class="control"> <select id="payment_method" name="payment_method"> <option value=""><?= $block->escapeHtml(__('-- Please Select --')) ?></option> - <?php foreach ($paymentMethods as $code => $title): ?> + <?php foreach ($paymentMethods as $code => $title) : ?> <option value="<?= $block->escapeHtml($code) ?>"> <?= $block->escapeHtml($title) ?> </option> @@ -101,7 +100,7 @@ $paymentMethods = $block->getWizardPaymentMethodOptions(); </div> </fieldset> </form> - <?php else: ?> + <?php else : ?> <div class="actions-toolbar"> <div class="secondary"> <a href="<?= $block->escapeUrl($block->getBackUrl()) ?>" class="action back"> diff --git a/app/code/Magento/Paypal/view/frontend/templates/checkout/onepage/review/totals.phtml b/app/code/Magento/Paypal/view/frontend/templates/checkout/onepage/review/totals.phtml index 2f7191b247203..05e3321cad765 100644 --- a/app/code/Magento/Paypal/view/frontend/templates/checkout/onepage/review/totals.phtml +++ b/app/code/Magento/Paypal/view/frontend/templates/checkout/onepage/review/totals.phtml @@ -4,23 +4,21 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** * @see \Magento\Checkout\Block\Cart\Totals */ ?> -<?php if ($block->getTotals()): ?> +<?php if ($block->getTotals()) : ?> <?php $_colspan = 3; ?> - <?= /* @escapeNotVerified */ $block->renderTotals(null, $_colspan) ?> - <?= /* @escapeNotVerified */ $block->renderTotals('footer', $_colspan) ?> - <?php if ($block->needDisplayBaseGrandtotal()):?> + <?= /* @noEscape */ $block->renderTotals(null, $_colspan) ?> + <?= /* @noEscape */ $block->renderTotals('footer', $_colspan) ?> + <?php if ($block->needDisplayBaseGrandtotal()) : ?> <tr class="totals charge"> - <th class="mark" colspan="<?= /* @escapeNotVerified */ $_colspan ?>" scope="row"> - <?= /* @escapeNotVerified */ __('Your credit card will be charged for') ?> + <th class="mark" colspan="<?= /* @noEscape */ $_colspan ?>" scope="row"> + <?= $block->escapeHtml(__('Your credit card will be charged for')) ?> </th> <td class="amount" data-th="<?= $block->escapeHtml(__('Your credit card will be charged for')) ?>"> - <?= /* @escapeNotVerified */ $block->displayBaseGrandtotal() ?> + <?= /* @noEscape */ $block->displayBaseGrandtotal() ?> </td> </tr> <?php endif?> diff --git a/app/code/Magento/Paypal/view/frontend/templates/express/review.phtml b/app/code/Magento/Paypal/view/frontend/templates/express/review.phtml index 93b5d57b3182d..7a94ac56232bc 100644 --- a/app/code/Magento/Paypal/view/frontend/templates/express/review.phtml +++ b/app/code/Magento/Paypal/view/frontend/templates/express/review.phtml @@ -4,7 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile /** * @var \Magento\Paypal\Block\Express\Review $block */ @@ -12,7 +11,7 @@ <div class="paypal-review view"> <div class="block block-order-details-view"> <div class="block-content"> - <?php if ($block->getShippingAddress()): ?> + <?php if ($block->getShippingAddress()) : ?> <div class="box box-order-shipping-method"> <strong class="box-title"> <span><?= $block->escapeHtml(__('Shipping Method')) ?></span> @@ -21,30 +20,26 @@ <form method="post" id="shipping-method-form" action="<?= $block->escapeUrl($block->getShippingMethodSubmitUrl()) ?>" class="form"> - <?php if ($block->canEditShippingMethod()): ?> - <?php if ($groups = $block->getShippingRateGroups()): ?> + <?php if ($block->canEditShippingMethod()) : ?> + <?php if ($groups = $block->getShippingRateGroups()) : ?> <?php $currentRate = $block->getCurrentShippingRate(); ?> <div class="field shipping required"> <select name="shipping_method" id="shipping-method" class="select"> - <?php if (!$currentRate): ?> - <option value=""><?= $block->escapeHtml(__( - 'Please select a shipping method...' - )); ?></option> + <?php if (!$currentRate) : ?> + <option value=""><?= $block->escapeHtml(__('Please select a shipping method...')); ?></option> <?php endif; ?> - <?php foreach ($groups as $code => $rates): ?> - <optgroup label="<?= $block->escapeHtml($block->getCarrierName( - $code - )); ?>"> - <?php foreach ($rates as $rate): ?> - <option value="<?= $block->escapeHtml( - $block->renderShippingRateValue($rate) - ); ?>" + <?php foreach ($groups as $code => $rates) : ?> + <optgroup label="<?= $block->escapeHtml($block->getCarrierName($code)); ?>"> + <?php foreach ($rates as $rate) : ?> + <option value="<?= + $block->escapeHtml( + $block->renderShippingRateValue($rate) + ); + ?>" <?= ($currentRate === $rate) ? ' selected="selected"' : ''; ?>> - <?php /* @noEscape */ echo - $block->renderShippingRateOption($rate); - ?> + <?= /* @noEscape */ $block->renderShippingRateOption($rate); ?> </option> <?php endforeach; ?> </optgroup> @@ -61,16 +56,16 @@ </button> </div> </div> - <?php else: ?> + <?php else : ?> <p> <?= $block->escapeHtml(__( 'Sorry, no quotes are available for this order right now.' )); ?> </p> <?php endif; ?> - <?php else: ?> + <?php else : ?> <p> - <?php /* @noEscape */ echo $block->renderShippingRateOption( + <?= /* @noEscape */ $block->renderShippingRateOption( $block->getCurrentShippingRate() ); ?> </p> @@ -90,7 +85,7 @@ );?> </address> </div> - <?php if ($block->getCanEditShippingAddress()): ?> + <?php if ($block->getCanEditShippingAddress()) : ?> <div class="box-actions"> <a href="<?= $block->escapeUrl($block->getEditUrl()) ?>" class="action edit"> <span><?= $block->escapeHtml(__('Edit')) ?></span> @@ -107,7 +102,7 @@ <img src="https://www.paypalobjects.com/webstatic/en_US/i/buttons/pp-acceptance-medium.png" alt="<?= $block->escapeHtml(__('Buy now with PayPal')) ?>"/> </div> - <?php if ($block->getEditUrl()): ?> + <?php if ($block->getEditUrl()) : ?> <div class="box-actions"> <a href="<?= $block->escapeUrl($block->getEditUrl()) ?>" class="action edit"> <span><?= $block->escapeHtml(__('Edit Payment Information')) ?></span> diff --git a/app/code/Magento/Paypal/view/frontend/templates/express/review/details.phtml b/app/code/Magento/Paypal/view/frontend/templates/express/review/details.phtml index 0d61b6cdc2c9f..976ad328663d1 100644 --- a/app/code/Magento/Paypal/view/frontend/templates/express/review/details.phtml +++ b/app/code/Magento/Paypal/view/frontend/templates/express/review/details.phtml @@ -4,7 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile /** * @see \Magento\Paypal\Block\Express\Review\Details * @var \Magento\Paypal\Block\Express\Review\Details $block @@ -21,7 +20,7 @@ <th class="col subtotal" scope="col"><?= $block->escapeHtml(__('Subtotal')) ?></th> </tr> </thead> - <?php foreach ($block->getItems() as $item): ?> + <?php foreach ($block->getItems() as $item) : ?> <?= $block->getItemHtml($item) ?> <?php endforeach ?> <tfoot class="opc-block-summary"> diff --git a/app/code/Magento/Paypal/view/frontend/templates/express/review/shipping/method.phtml b/app/code/Magento/Paypal/view/frontend/templates/express/review/shipping/method.phtml index ca84b0829ea9e..839d278ed227c 100644 --- a/app/code/Magento/Paypal/view/frontend/templates/express/review/shipping/method.phtml +++ b/app/code/Magento/Paypal/view/frontend/templates/express/review/shipping/method.phtml @@ -4,23 +4,22 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile /** @var $block \Magento\Paypal\Block\Express\Review */ ?> <div id="shipping-method-container"> - <?php if ($block->getCanEditShippingMethod() || !$block->getCurrentShippingRate()): ?> - <?php if ($groups = $block->getShippingRateGroups()): ?> + <?php if ($block->getCanEditShippingMethod() || !$block->getCurrentShippingRate()) : ?> + <?php if ($groups = $block->getShippingRateGroups()) : ?> <?php $currentRate = $block->getCurrentShippingRate(); ?> <select name="shipping_method" id="shipping_method" class="required-entry"> - <?php if (!$currentRate): ?> + <?php if (!$currentRate) : ?> <option value=""> <?= $block->escapeHtml(__('Please select a shipping method...')) ?> </option> <?php endif; ?> - <?php foreach ($groups as $code => $rates): ?> + <?php foreach ($groups as $code => $rates) : ?> <optgroup label="<?= $block->escapeHtml($block->getCarrierName($code)) ?>" style="font-style:normal;"> - <?php foreach ($rates as $rate): ?> + <?php foreach ($rates as $rate) : ?> <option value="<?= $block->escapeHtml($block->renderShippingRateValue($rate)) ?>" <?= ($currentRate === $rate) ? ' selected="selected"' : '' ?>> @@ -30,14 +29,14 @@ </optgroup> <?php endforeach; ?> </select> - <?php else: ?> + <?php else : ?> <p> <strong> <?= $block->escapeHtml(__('Sorry, no quotes are available for this order right now.')) ?> </strong> </p> <?php endif; ?> - <?php else: ?> + <?php else : ?> <p> <strong> <?= /* @noEscape */ $block->renderShippingRateOption($block->getCurrentShippingRate()) ?> diff --git a/app/code/Magento/Paypal/view/frontend/templates/express/shortcut.phtml b/app/code/Magento/Paypal/view/frontend/templates/express/shortcut.phtml index ce8a0e940230b..1e7787817b558 100644 --- a/app/code/Magento/Paypal/view/frontend/templates/express/shortcut.phtml +++ b/app/code/Magento/Paypal/view/frontend/templates/express/shortcut.phtml @@ -4,7 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile /** * @var \Magento\Paypal\Block\Express\Shortcut $block */ @@ -37,7 +36,7 @@ if ($block->getIsInCatalogProduct()) { src="<?= $block->escapeUrl($block->getImageUrl()) ?>" alt="<?= $block->escapeHtml(__('Checkout with PayPal')) ?>" title="<?= $block->escapeHtml(__('Checkout with PayPal')) ?>"/> - <?php if ($block->getAdditionalLinkImage()): ?> + <?php if ($block->getAdditionalLinkImage()) : ?> <?php $linkImage = $block->getAdditionalLinkImage(); ?> <a href="<?= $block->escapeUrl($linkImage['href']) ?>"> <img src="<?= $block->escapeHtml($linkImage['src']) ?>" /> diff --git a/app/code/Magento/Paypal/view/frontend/templates/express/shortcut/container.phtml b/app/code/Magento/Paypal/view/frontend/templates/express/shortcut/container.phtml index 9a9bac2c74164..acaff92065d7c 100644 --- a/app/code/Magento/Paypal/view/frontend/templates/express/shortcut/container.phtml +++ b/app/code/Magento/Paypal/view/frontend/templates/express/shortcut/container.phtml @@ -4,11 +4,10 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile /** * @var $block Magento\Paypal\Block\Express\Shortcut */ ?> -<?php if ($block->getIsInCatalogProduct()): ?> +<?php if ($block->getIsInCatalogProduct()) : ?> <input type="hidden" id="pp-checkout-url" name="return_url" value=""/> <?php endif; ?> diff --git a/app/code/Magento/Paypal/view/frontend/templates/express/shortcut_button.phtml b/app/code/Magento/Paypal/view/frontend/templates/express/shortcut_button.phtml index ef24c5376aac2..a30bc2cce6d4f 100644 --- a/app/code/Magento/Paypal/view/frontend/templates/express/shortcut_button.phtml +++ b/app/code/Magento/Paypal/view/frontend/templates/express/shortcut_button.phtml @@ -1,11 +1,9 @@ - <?php /** * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile /** * @var \Magento\Paypal\Block\Express\Shortcut $block */ diff --git a/app/code/Magento/Paypal/view/frontend/templates/hss/info.phtml b/app/code/Magento/Paypal/view/frontend/templates/hss/info.phtml index 28daa150b8888..c2339f85b7ca5 100644 --- a/app/code/Magento/Paypal/view/frontend/templates/hss/info.phtml +++ b/app/code/Magento/Paypal/view/frontend/templates/hss/info.phtml @@ -3,7 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile + /** * @var \Magento\Paypal\Block\Payment\Info $block */ diff --git a/app/code/Magento/Paypal/view/frontend/templates/js/components.phtml b/app/code/Magento/Paypal/view/frontend/templates/js/components.phtml index 7ba9307742031..5902a9f25cc4b 100644 --- a/app/code/Magento/Paypal/view/frontend/templates/js/components.phtml +++ b/app/code/Magento/Paypal/view/frontend/templates/js/components.phtml @@ -3,7 +3,5 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ - -// @codingStandardsIgnoreFile ?> <?= $block->getChildHtml() ?> diff --git a/app/code/Magento/Paypal/view/frontend/templates/payflowadvanced/info.phtml b/app/code/Magento/Paypal/view/frontend/templates/payflowadvanced/info.phtml index 06cbc9f3e354c..d5944a6f22f5f 100644 --- a/app/code/Magento/Paypal/view/frontend/templates/payflowadvanced/info.phtml +++ b/app/code/Magento/Paypal/view/frontend/templates/payflowadvanced/info.phtml @@ -4,7 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile /** * @var \Magento\Paypal\Block\Payflow\Advanced\Form $block */ diff --git a/app/code/Magento/Paypal/view/frontend/templates/payment/form/billing/agreement.phtml b/app/code/Magento/Paypal/view/frontend/templates/payment/form/billing/agreement.phtml index d9095c202f88f..75ee08111bd7a 100644 --- a/app/code/Magento/Paypal/view/frontend/templates/payment/form/billing/agreement.phtml +++ b/app/code/Magento/Paypal/view/frontend/templates/payment/form/billing/agreement.phtml @@ -4,7 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile /** * @var \Magento\Paypal\Block\Payment\Form\Billing\Agreement $block */ @@ -18,7 +17,7 @@ $code = $block->escapeHtml($block->getMethodCode()); <select id="<?= /* @noEscape */ $code ?>_ba_agreement_id" name="payment[<?= $block->escapeHtml($block->getTransportName()) ?>]" class="select"> <option value=""><?= $block->escapeHtml(__('-- Please Select Billing Agreement--')) ?></option> - <?php foreach ($block->getBillingAgreements() as $id => $referenceId): ?> + <?php foreach ($block->getBillingAgreements() as $id => $referenceId) : ?> <option value="<?= $block->escapeHtml($id) ?>"> <?= $block->escapeHtml($referenceId) ?> </option> diff --git a/app/code/Magento/Paypal/view/frontend/templates/payment/mark.phtml b/app/code/Magento/Paypal/view/frontend/templates/payment/mark.phtml index 934136281746c..d9fb5fb43bcc7 100644 --- a/app/code/Magento/Paypal/view/frontend/templates/payment/mark.phtml +++ b/app/code/Magento/Paypal/view/frontend/templates/payment/mark.phtml @@ -4,7 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile /** * Note: This mark is a requirement of PayPal * @var \Magento\Paypal\Block\Express\Form $block diff --git a/app/code/Magento/Paypal/view/frontend/templates/payment/redirect.phtml b/app/code/Magento/Paypal/view/frontend/templates/payment/redirect.phtml index d954eab92c6f7..683153b12db7a 100644 --- a/app/code/Magento/Paypal/view/frontend/templates/payment/redirect.phtml +++ b/app/code/Magento/Paypal/view/frontend/templates/payment/redirect.phtml @@ -4,7 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile /** * @var \Magento\PayPal\Block\Express\Form $block * @see \Magento\PayPal\Block\Express\Form @@ -15,7 +14,7 @@ $code = $block->escapeHtml($block->getBillingAgreementCode()); id="payment_form_<?= $block->escapeHtml($block->getMethodCode()) ?>"> <div><?= $block->escapeHtml($block->getRedirectMessage()) ?></div> <?php ?> - <?php if ($code): ?> + <?php if ($code) : ?> <input type="checkbox" id="<?= /* @noEscape */ $code ?>" value="1" class="checkbox" name="payment[<?= /* @noEscape */ $code ?>]"> <label for="<?= /* @noEscape */ $code ?>" class="label"> diff --git a/app/code/Magento/Persistent/view/frontend/templates/additional.phtml b/app/code/Magento/Persistent/view/frontend/templates/additional.phtml index 28dce5dc23cc9..40c8674bc025a 100644 --- a/app/code/Magento/Persistent/view/frontend/templates/additional.phtml +++ b/app/code/Magento/Persistent/view/frontend/templates/additional.phtml @@ -6,7 +6,7 @@ ?> <?php if ($block->getCustomerId()) :?> <span> - <a <?= /* @escapeNotVerified */ $block->getLinkAttributes()?>><?= $block->escapeHtml(__('Not you?'));?></a> + <a <?= /* @noEscape */ $block->getLinkAttributes()?>><?= $block->escapeHtml(__('Not you?'));?></a> </span> <?php endif;?> <script type="application/javascript"> diff --git a/app/code/Magento/Persistent/view/frontend/templates/remember_me.phtml b/app/code/Magento/Persistent/view/frontend/templates/remember_me.phtml index 1e04e8ae3b407..0447b3e1b9cef 100644 --- a/app/code/Magento/Persistent/view/frontend/templates/remember_me.phtml +++ b/app/code/Magento/Persistent/view/frontend/templates/remember_me.phtml @@ -4,8 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** * Customer "Remember Me" template */ @@ -15,7 +13,7 @@ ?> <div id="remember-me-box" class="field choice persistent"> <?php $rememberMeId = 'remember_me' . $block->getRandomString(10); ?> - <input type="checkbox" name="persistent_remember_me" class="checkbox" id="<?= $block->escapeHtmlAttr($rememberMeId) ?>"<?php if ($block->isRememberMeChecked()): ?> checked="checked"<?php endif; ?> title="<?= $block->escapeHtmlAttr(__('Remember Me')) ?>" /> + <input type="checkbox" name="persistent_remember_me" class="checkbox" id="<?= $block->escapeHtmlAttr($rememberMeId) ?>"<?php if ($block->isRememberMeChecked()) : ?> checked="checked"<?php endif; ?> title="<?= $block->escapeHtmlAttr(__('Remember Me')) ?>" /> <label for="<?= $block->escapeHtmlAttr($rememberMeId) ?>" class="label"><span><?= $block->escapeHtml(__('Remember Me')) ?></span></label> <span class="tooltip wrapper"> <a class="link tooltip toggle" href="#"><?= $block->escapeHtml(__('What\'s this?')) ?></a> diff --git a/app/code/Magento/ProductAlert/view/frontend/templates/email/price.phtml b/app/code/Magento/ProductAlert/view/frontend/templates/email/price.phtml index 9942c94ea887d..054871be52613 100644 --- a/app/code/Magento/ProductAlert/view/frontend/templates/email/price.phtml +++ b/app/code/Magento/ProductAlert/view/frontend/templates/email/price.phtml @@ -4,43 +4,42 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var $block \Magento\ProductAlert\Block\Email\Price */ ?> -<?php if ($_products = $block->getProducts()): ?> -<p><?= /* @escapeNotVerified */ __('Price change alert! We wanted you to know that prices have changed for these products:') ?></p> -<table> -<?php /** @var $_product \Magento\Catalog\Model\Product */ ?> -<?php foreach ($_products as $_product): ?> - <tr> - <td class="col photo"> - <a href="<?= /* @escapeNotVerified */ $_product->getProductUrl() ?>" title="<?= $block->escapeHtml($_product->getName()) ?>" class="product photo"> - <?= $block->getImage($_product, 'product_thumbnail_image', ['class' => 'photo image'])->toHtml() ?> - </a> - </td> - <td class="col item"> - <p> - <strong class="product name"> - <a href="<?= /* @escapeNotVerified */ $_product->getProductUrl() ?>"><?= $block->escapeHtml($_product->getName()) ?></a> - </strong> - </p> - <?php if ($shortDescription = $block->getFilteredContent($_product->getShortDescription())): ?> - <p><small><?= /* @escapeNotVerified */ $shortDescription ?></small></p> - <?php endif; ?> - <?= $block->getProductPriceHtml( +<?php if ($_products = $block->getProducts()) : ?> + <p><?= $block->escapeHtml(__('Price change alert! We wanted you to know that prices have changed for these products:')) ?></p> + <table> + <?php /** @var $_product \Magento\Catalog\Model\Product */ ?> + <?php foreach ($_products as $_product) : ?> + <tr> + <td class="col photo"> + <a href="<?= $block->escapeUrl($_product->getProductUrl()) ?>" title="<?= $block->escapeHtml($_product->getName()) ?>" class="product photo"> + <?= $block->getImage($_product, 'product_thumbnail_image', ['class' => 'photo image'])->toHtml() ?> + </a> + </td> + <td class="col item"> + <p> + <strong class="product name"> + <a href="<?= $block->escapeUrl($_product->getProductUrl()) ?>"><?= $block->escapeHtml($_product->getName()) ?></a> + </strong> + </p> + <?php if ($shortDescription = $block->getFilteredContent($_product->getShortDescription())) : ?> + <p><small><?= /* @noEscape */ $shortDescription ?></small></p> + <?php endif; ?> + <?= + $block->getProductPriceHtml( $_product, \Magento\Catalog\Pricing\Price\FinalPrice::PRICE_CODE, \Magento\Framework\Pricing\Render::ZONE_EMAIL, [ - 'display_label' => __('Price:') + 'display_label' => __('Price:'), ] ); ?> - <p><small><a href="<?= /* @escapeNotVerified */ $block->getProductUnsubscribeUrl($_product->getId()) ?>"><?= /* @escapeNotVerified */ __('Click here to stop alerts for this product.') ?></a></small></p> - </td> - </tr> -<?php endforeach; ?> -</table> -<p><a href="<?= /* @escapeNotVerified */ $block->getUnsubscribeUrl() ?>"><?= /* @escapeNotVerified */ __('Unsubscribe from all price alerts') ?></a></p> + <p><small><a href="<?= $block->escapeUrl($block->getProductUnsubscribeUrl($_product->getId())) ?>"><?= $block->escapeHtml(__('Click here to stop alerts for this product.')) ?></a></small></p> + </td> + </tr> + <?php endforeach; ?> + </table> + <p><a href="<?= $block->escapeUrl($block->getUnsubscribeUrl()) ?>"><?= $block->escapeHtml(__('Unsubscribe from all price alerts')) ?></a></p> <?php endif; ?> diff --git a/app/code/Magento/ProductAlert/view/frontend/templates/email/stock.phtml b/app/code/Magento/ProductAlert/view/frontend/templates/email/stock.phtml index ffacd605517bc..d90a458b4422a 100644 --- a/app/code/Magento/ProductAlert/view/frontend/templates/email/stock.phtml +++ b/app/code/Magento/ProductAlert/view/frontend/templates/email/stock.phtml @@ -4,30 +4,29 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var $block \Magento\ProductAlert\Block\Email\Stock */ ?> -<?php if ($_products = $block->getProducts()): ?> -<p><?= /* @escapeNotVerified */ __('In stock alert! We wanted you to know that these products are now available:') ?></p> -<table> -<?php foreach ($_products as $_product): ?> - <tr> - <td class="col photo"> - <a href="<?= /* @escapeNotVerified */ $_product->getProductUrl() ?>" title="<?= $block->escapeHtml($_product->getName()) ?>" class="product photo"> - <?= $block->getImage($_product, 'product_thumbnail_image', ['class' => 'photo image'])->toHtml() ?> - </a> - </td> - <td class="col item"> - <p> - <strong class="product name"> - <a href="<?= /* @escapeNotVerified */ $_product->getProductUrl() ?>"><?= $block->escapeHtml($_product->getName()) ?></a> - </strong> - </p> - <?php if ($shortDescription = $block->getFilteredContent($_product->getShortDescription())): ?> - <p><small><?= /* @escapeNotVerified */ $shortDescription ?></small></p> - <?php endif; ?> - <?= $block->getProductPriceHtml( +<?php if ($_products = $block->getProducts()) : ?> + <p><?= $block->escapeHtml(__('In stock alert! We wanted you to know that these products are now available:')) ?></p> + <table> + <?php foreach ($_products as $_product) : ?> + <tr> + <td class="col photo"> + <a href="<?= $block->escapeUrl($_product->getProductUrl()) ?>" title="<?= $block->escapeHtml($_product->getName()) ?>" class="product photo"> + <?= $block->getImage($_product, 'product_thumbnail_image', ['class' => 'photo image'])->toHtml() ?> + </a> + </td> + <td class="col item"> + <p> + <strong class="product name"> + <a href="<?= $block->escapeUrl($_product->getProductUrl()) ?>"><?= $block->escapeHtml($_product->getName()) ?></a> + </strong> + </p> + <?php if ($shortDescription = $block->getFilteredContent($_product->getShortDescription())) : ?> + <p><small><?= /* @noEscape */ $shortDescription ?></small></p> + <?php endif; ?> + <?= + $block->getProductPriceHtml( $_product, \Magento\Catalog\Pricing\Price\FinalPrice::PRICE_CODE, \Magento\Framework\Pricing\Render::ZONE_EMAIL, @@ -36,10 +35,10 @@ ] ); ?> - <p><small><a href="<?= /* @escapeNotVerified */ $block->getProductUnsubscribeUrl($_product->getId()) ?>"><?= /* @escapeNotVerified */ __('Click here to stop alerts for this product.') ?></a></small></p> - </td> - </tr> -<?php endforeach; ?> -</table> -<p><a href="<?= /* @escapeNotVerified */ $block->getUnsubscribeUrl() ?>"><?= /* @escapeNotVerified */ __('Unsubscribe from all stock alerts') ?></a></p> + <p><small><a href="<?= $block->escapeUrl($block->getProductUnsubscribeUrl($_product->getId())) ?>"><?= $block->escapeHtml(__('Click here to stop alerts for this product.')) ?></a></small></p> + </td> + </tr> + <?php endforeach; ?> + </table> + <p><a href="<?= $block->escapeUrl($block->getUnsubscribeUrl()) ?>"><?= $block->escapeHtml(__('Unsubscribe from all stock alerts')) ?></a></p> <?php endif; ?> diff --git a/app/code/Magento/Reports/view/adminhtml/templates/report/refresh/statistics.phtml b/app/code/Magento/Reports/view/adminhtml/templates/report/refresh/statistics.phtml index 1c448f966375a..4ce64f0bd0036 100644 --- a/app/code/Magento/Reports/view/adminhtml/templates/report/refresh/statistics.phtml +++ b/app/code/Magento/Reports/view/adminhtml/templates/report/refresh/statistics.phtml @@ -3,9 +3,6 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ - -// @codingStandardsIgnoreFile - ?> <div data-mage-init='{"floatingHeader": {}}' class="page-actions"><?= $block->getButtonsHtml() ?></div> <?= $block->getChildHtml('grid') ?> diff --git a/app/code/Magento/Reports/view/frontend/templates/js/components.phtml b/app/code/Magento/Reports/view/frontend/templates/js/components.phtml index bad5acc209b5f..5902a9f25cc4b 100644 --- a/app/code/Magento/Reports/view/frontend/templates/js/components.phtml +++ b/app/code/Magento/Reports/view/frontend/templates/js/components.phtml @@ -3,8 +3,5 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ - -// @codingStandardsIgnoreFile - ?> <?= $block->getChildHtml() ?> diff --git a/app/code/Magento/Reports/view/frontend/templates/product/widget/viewed/item.phtml b/app/code/Magento/Reports/view/frontend/templates/product/widget/viewed/item.phtml index b76d79a26c040..562c9a2b63a99 100644 --- a/app/code/Magento/Reports/view/frontend/templates/product/widget/viewed/item.phtml +++ b/app/code/Magento/Reports/view/frontend/templates/product/widget/viewed/item.phtml @@ -8,10 +8,6 @@ * @deprecated */ -/** - * @codingStandardsIgnoreFile - */ - /* @var $block \Magento\Reports\Block\Product\Widget\Viewed\Item */ $type = $block->getType() . '-' . $block->getViewMode(); @@ -54,7 +50,7 @@ $rating = 'short'; <span><?= $block->escapeHtml(__('Add to Cart')) ?></span> </button> <?php else : ?> - <?php $postDataHelper = $this->helper('Magento\Framework\Data\Helper\PostHelper'); + <?php $postDataHelper = $this->helper(\Magento\Framework\Data\Helper\PostHelper::class); $postData = $postDataHelper->getPostData($block->getAddToCartUrl($item), ['product' => $item->getEntityId()]) ?> <button class="action tocart" @@ -73,14 +69,14 @@ $rating = 'short'; </div> <div class="secondary-addto-links" data-role="add-to-links"> - <?php if ($this->helper('Magento\Wishlist\Helper\Data')->isAllow()) : ?> + <?php if ($this->helper(\Magento\Wishlist\Helper\Data::class)->isAllow()) : ?> <a href="#" data-post='<?= /* @noEscape */ $block->getAddToWishlistParams($item) ?>' class="action towishlist" data-action="add-to-wishlist" title="<?= $block->escapeHtmlAttr(__('Add to Wish List')) ?>"> <span><?= $block->escapeHtml(__('Add to Wish List')) ?></span> </a> <?php endif; ?> <?php if ($block->getAddToCompareUrl()) : ?> <?php - $compareHelper = $this->helper('Magento\Catalog\Helper\Product\Compare'); + $compareHelper = $this->helper(\Magento\Catalog\Helper\Product\Compare::class); ?> <a href="#" class="action tocompare" data-post='<?= /* @noEscape */ $compareHelper->getPostDataParams($item) ?>' diff --git a/app/code/Magento/Reports/view/frontend/templates/widget/compared/column/compared_default_list.phtml b/app/code/Magento/Reports/view/frontend/templates/widget/compared/column/compared_default_list.phtml index 0d8ea99e4e767..a54259280e381 100644 --- a/app/code/Magento/Reports/view/frontend/templates/widget/compared/column/compared_default_list.phtml +++ b/app/code/Magento/Reports/view/frontend/templates/widget/compared/column/compared_default_list.phtml @@ -7,11 +7,6 @@ /** * @deprecated */ - -/** - * @codingStandardsIgnoreFile - */ - ?> <?php if ($exist = $block->getRecentlyComparedProducts()) { @@ -50,7 +45,7 @@ if ($exist = $block->getRecentlyComparedProducts()) { <strong class="product-item-name"> <a href="<?= $block->escapeUrl($_product->getProductUrl()) ?>" title="<?= $block->escapeHtmlAttr($block->stripTags($_product->getName(), null, true)) ?>)"> - <?= $block->escapeHtml($this->helper('Magento\Catalog\Helper\Output')->productAttribute($_product, $_product->getName(), 'name')) ?> + <?= $block->escapeHtml($this->helper(\Magento\Catalog\Helper\Output::class)->productAttribute($_product, $_product->getName(), 'name')) ?> </a> </strong> <?= /* @noEscape */ $block->getProductPriceHtml( @@ -72,7 +67,7 @@ if ($exist = $block->getRecentlyComparedProducts()) { </button> <?php else : ?> <?php - $postDataHelper = $this->helper('Magento\Framework\Data\Helper\PostHelper'); + $postDataHelper = $this->helper(\Magento\Framework\Data\Helper\PostHelper::class); $postData = $postDataHelper->getPostData($block->getAddToCartUrl($_product), ['product' => $_product->getEntityId()]) ?> <button class="action tocart primary" diff --git a/app/code/Magento/Reports/view/frontend/templates/widget/compared/column/compared_names_list.phtml b/app/code/Magento/Reports/view/frontend/templates/widget/compared/column/compared_names_list.phtml index 08ebffad3e618..b37aef8e29803 100644 --- a/app/code/Magento/Reports/view/frontend/templates/widget/compared/column/compared_names_list.phtml +++ b/app/code/Magento/Reports/view/frontend/templates/widget/compared/column/compared_names_list.phtml @@ -7,11 +7,6 @@ /** * @deprecated */ - -/** - * @codingStandardsIgnoreFile - */ - ?> <?php if ($_products = $block->getRecentlyComparedProducts()) : ?> <div class="block widget block-compared-products-names"> @@ -24,7 +19,7 @@ <li class="product-item"> <strong class="product-item-name"> <a href="<?= $block->escapeUrl($_product->getProductUrl()) ?>" class="product-item-link"> - <?= $block->escapeHtml($this->helper('Magento\Catalog\Helper\Output')->productAttribute($_product, $_product->getName(), 'name')) ?> + <?= $block->escapeHtml($this->helper(\Magento\Catalog\Helper\Output::class)->productAttribute($_product, $_product->getName(), 'name')) ?> </a> </strong> </li> diff --git a/app/code/Magento/Reports/view/frontend/templates/widget/compared/content/compared_grid.phtml b/app/code/Magento/Reports/view/frontend/templates/widget/compared/content/compared_grid.phtml index a321b78e6db00..ad6b33820c752 100644 --- a/app/code/Magento/Reports/view/frontend/templates/widget/compared/content/compared_grid.phtml +++ b/app/code/Magento/Reports/view/frontend/templates/widget/compared/content/compared_grid.phtml @@ -8,10 +8,6 @@ * @deprecated */ -/** - * @codingStandardsIgnoreFile - */ - /** @var \Magento\Catalog\Block\Product\Compare\ListCompare $block */ if ($exist = $block->getRecentlyComparedProducts()) { $type = 'widget-compared'; @@ -77,7 +73,7 @@ if ($exist = $block->getRecentlyComparedProducts()) { </button> <?php else : ?> <?php - $postDataHelper = $this->helper('Magento\Framework\Data\Helper\PostHelper'); + $postDataHelper = $this->helper(\Magento\Framework\Data\Helper\PostHelper::class); $postData = $postDataHelper->getPostData($block->getAddToCartUrl($_item), ['product' => $_item->getEntityId()]) ?> <button class="action tocart primary" @@ -98,7 +94,7 @@ if ($exist = $block->getRecentlyComparedProducts()) { <?php if ($showWishlist || $showCompare) : ?> <div class="actions-secondary" data-role="add-to-links"> - <?php if ($this->helper('Magento\Wishlist\Helper\Data')->isAllow() && $showWishlist) : ?> + <?php if ($this->helper(\Magento\Wishlist\Helper\Data::class)->isAllow() && $showWishlist) : ?> <a href="#" data-post='<?= /* @noEscape */ $block->getAddToWishlistParams($_item) ?>' data-action="add-to-wishlist" @@ -108,7 +104,7 @@ if ($exist = $block->getRecentlyComparedProducts()) { </a> <?php endif; ?> <?php if ($block->getAddToCompareUrl() && $showCompare) : ?> - <?php $compareHelper = $this->helper('Magento\Catalog\Helper\Product\Compare'); ?> + <?php $compareHelper = $this->helper(\Magento\Catalog\Helper\Product\Compare::class); ?> <a href="#" class="action tocompare" data-post='<?= /* @noEscape */ $compareHelper->getPostDataParams($_item) ?>' title="<?= $block->escapeHtmlAttr(__('Add to Compare')) ?>"> diff --git a/app/code/Magento/Reports/view/frontend/templates/widget/compared/content/compared_list.phtml b/app/code/Magento/Reports/view/frontend/templates/widget/compared/content/compared_list.phtml index 87c647526c9cf..ba7a50eef6485 100644 --- a/app/code/Magento/Reports/view/frontend/templates/widget/compared/content/compared_list.phtml +++ b/app/code/Magento/Reports/view/frontend/templates/widget/compared/content/compared_list.phtml @@ -8,10 +8,6 @@ * @deprecated */ -/** - * @codingStandardsIgnoreFile - */ - /** @var \Magento\Catalog\Block\Product\Compare\ListCompare $block */ if ($exist = $block->getRecentlyComparedProducts()) { $type = 'widget-compared'; @@ -22,7 +18,7 @@ if ($exist = $block->getRecentlyComparedProducts()) { $image = 'recently_compared_products_list_content_widget'; $title = __('Recently Compared'); $items = $exist; - $_helper = $this->helper('Magento\Catalog\Helper\Output'); + $_helper = $this->helper(\Magento\Catalog\Helper\Output::class); $showWishlist = true; $showCompare = true; @@ -78,7 +74,7 @@ if ($exist = $block->getRecentlyComparedProducts()) { </button> <?php else : ?> <?php - $postDataHelper = $this->helper('Magento\Framework\Data\Helper\PostHelper'); + $postDataHelper = $this->helper(\Magento\Framework\Data\Helper\PostHelper::class); $postData = $postDataHelper->getPostData($block->getAddToCartUrl($_item), ['product' => $_item->getEntityId()]) ?> <button class="action tocart primary" @@ -99,7 +95,7 @@ if ($exist = $block->getRecentlyComparedProducts()) { <?php if ($showWishlist || $showCompare) : ?> <div class="actions-secondary" data-role="add-to-links"> - <?php if ($this->helper('Magento\Wishlist\Helper\Data')->isAllow() && $showWishlist) : ?> + <?php if ($this->helper(\Magento\Wishlist\Helper\Data::class)->isAllow() && $showWishlist) : ?> <a href="#" data-post='<?= /* @noEscape */ $block->getAddToWishlistParams($_item) ?>' data-action="add-to-wishlist" @@ -109,7 +105,7 @@ if ($exist = $block->getRecentlyComparedProducts()) { </a> <?php endif; ?> <?php if ($block->getAddToCompareUrl() && $showCompare) : ?> - <?php $compareHelper = $this->helper('Magento\Catalog\Helper\Product\Compare');?> + <?php $compareHelper = $this->helper(\Magento\Catalog\Helper\Product\Compare::class);?> <a href="#" class="action tocompare" data-post='<?= /* @noEscape */ $compareHelper->getPostDataParams($_item) ?>' title="<?= $block->escapeHtmlAttr(__('Add to Compare')) ?>"> diff --git a/app/code/Magento/Reports/view/frontend/templates/widget/viewed/column/viewed_default_list.phtml b/app/code/Magento/Reports/view/frontend/templates/widget/viewed/column/viewed_default_list.phtml index 0d285a827a2f3..16fc2b070b95c 100644 --- a/app/code/Magento/Reports/view/frontend/templates/widget/viewed/column/viewed_default_list.phtml +++ b/app/code/Magento/Reports/view/frontend/templates/widget/viewed/column/viewed_default_list.phtml @@ -8,10 +8,6 @@ * @deprecated */ -/** - * @codingStandardsIgnoreFile - */ - /** * @var $block \Magento\Reports\Block\Product\Viewed */ @@ -54,7 +50,7 @@ if ($exist = ($block->getRecentlyViewedProducts() && $block->getRecentlyViewedPr <a href="<?= $block->escapeUrl($_product->getProductUrl()) ?>" title="<?= $block->escapeHtmlAttr($block->stripTags($_product->getName(), null, true)) ?>" class="product-item-link"> - <?= $block->escapeHtml($this->helper('Magento\Catalog\Helper\Output')->productAttribute($_product, $_product->getName(), 'name')) ?> + <?= $block->escapeHtml($this->helper(\Magento\Catalog\Helper\Output::class)->productAttribute($_product, $_product->getName(), 'name')) ?> </a> </strong> <?= /* @noEscape */ $block->getProductPriceHtml( @@ -76,7 +72,7 @@ if ($exist = ($block->getRecentlyViewedProducts() && $block->getRecentlyViewedPr </button> <?php else : ?> <?php - $postDataHelper = $this->helper('Magento\Framework\Data\Helper\PostHelper'); + $postDataHelper = $this->helper(\Magento\Framework\Data\Helper\PostHelper::class); $postData = $postDataHelper->getPostData($block->getAddToCartUrl($_product), ['product' => $_product->getEntityId()]); ?> <button type="button" class="action tocart primary" data-post='<?= /* @noEscape */ $postData ?>'> diff --git a/app/code/Magento/Reports/view/frontend/templates/widget/viewed/column/viewed_names_list.phtml b/app/code/Magento/Reports/view/frontend/templates/widget/viewed/column/viewed_names_list.phtml index 076af9125065e..d2ea09ebdbfeb 100644 --- a/app/code/Magento/Reports/view/frontend/templates/widget/viewed/column/viewed_names_list.phtml +++ b/app/code/Magento/Reports/view/frontend/templates/widget/viewed/column/viewed_names_list.phtml @@ -8,10 +8,6 @@ * @deprecated */ -/** - * @codingStandardsIgnoreFile - */ - /** * @var $block \Magento\Reports\Block\Product\Viewed */ @@ -28,7 +24,7 @@ <li class="product-item"> <strong class="product-item-name"> <a href="<?= $block->escapeUrl($_product->getProductUrl()) ?>" class="product-item-link"> - <?= $block->escapeHtml($this->helper('Magento\Catalog\Helper\Output')->productAttribute($_product, $_product->getName(), 'name')) ?> + <?= $block->escapeHtml($this->helper(\Magento\Catalog\Helper\Output::class)->productAttribute($_product, $_product->getName(), 'name')) ?> </a> </strong> </li> diff --git a/app/code/Magento/Reports/view/frontend/templates/widget/viewed/content/viewed_grid.phtml b/app/code/Magento/Reports/view/frontend/templates/widget/viewed/content/viewed_grid.phtml index c2b727e7e1c25..567c3ebc57f9b 100644 --- a/app/code/Magento/Reports/view/frontend/templates/widget/viewed/content/viewed_grid.phtml +++ b/app/code/Magento/Reports/view/frontend/templates/widget/viewed/content/viewed_grid.phtml @@ -8,10 +8,6 @@ * @deprecated */ -/** - * @codingStandardsIgnoreFile - */ - /** * @var $block \Magento\Reports\Block\Product\Viewed */ @@ -80,7 +76,7 @@ if ($exist = ($block->getRecentlyViewedProducts() && $block->getRecentlyViewedPr </button> <?php else : ?> <?php - $postDataHelper = $this->helper('Magento\Framework\Data\Helper\PostHelper'); + $postDataHelper = $this->helper(\Magento\Framework\Data\Helper\PostHelper::class); $postData = $postDataHelper->getPostData($block->getAddToCartUrl($_item), ['product' => $_item->getEntityId()]) ?> <button class="action tocart primary" @@ -100,7 +96,7 @@ if ($exist = ($block->getRecentlyViewedProducts() && $block->getRecentlyViewedPr <?php endif; ?> <?php if ($showWishlist || $showCompare) : ?> <div class="actions-secondary" data-role="add-to-links"> - <?php if ($this->helper('Magento\Wishlist\Helper\Data')->isAllow() && $showWishlist) : ?> + <?php if ($this->helper(\Magento\Wishlist\Helper\Data::class)->isAllow() && $showWishlist) : ?> <a href="#" class="action towishlist" data-action="add-to-wishlist" data-post='<?= /* @noEscape */ $block->getAddToWishlistParams($_item) ?>' @@ -109,7 +105,7 @@ if ($exist = ($block->getRecentlyViewedProducts() && $block->getRecentlyViewedPr </a> <?php endif; ?> <?php if ($block->getAddToCompareUrl() && $showCompare) : ?> - <?php $compareHelper = $this->helper('Magento\Catalog\Helper\Product\Compare');?> + <?php $compareHelper = $this->helper(\Magento\Catalog\Helper\Product\Compare::class);?> <a href="#" class="action tocompare" data-post='<?= /* @noEscape */ $compareHelper->getPostDataParams($_item) ?>' title="<?= $block->escapeHtmlAttr(__('Add to Compare')) ?>"> diff --git a/app/code/Magento/Reports/view/frontend/templates/widget/viewed/content/viewed_list.phtml b/app/code/Magento/Reports/view/frontend/templates/widget/viewed/content/viewed_list.phtml index 36c1f127929d5..9a8bb9c3b734f 100644 --- a/app/code/Magento/Reports/view/frontend/templates/widget/viewed/content/viewed_list.phtml +++ b/app/code/Magento/Reports/view/frontend/templates/widget/viewed/content/viewed_list.phtml @@ -8,10 +8,6 @@ * @deprecated */ -/** - * @codingStandardsIgnoreFile - */ - /** * @var $block \Magento\Reports\Block\Product\Viewed */ @@ -26,7 +22,7 @@ if ($exist = ($block->getRecentlyViewedProducts() && $block->getRecentlyViewedPr $image = 'recently_viewed_products_list_content_widget'; $title = __('Recently Viewed'); $items = $block->getRecentlyViewedProducts(); - $_helper = $this->helper('Magento\Catalog\Helper\Output'); + $_helper = $this->helper(\Magento\Catalog\Helper\Output::class); $showWishlist = true; $showCompare = true; @@ -82,7 +78,7 @@ if ($exist = ($block->getRecentlyViewedProducts() && $block->getRecentlyViewedPr </button> <?php else : ?> <?php - $postDataHelper = $this->helper('Magento\Framework\Data\Helper\PostHelper'); + $postDataHelper = $this->helper(\Magento\Framework\Data\Helper\PostHelper::class); $postData = $postDataHelper->getPostData($block->getAddToCartUrl($_item), ['product' => $_item->getEntityId()]); ?> <button class="action tocart primary" @@ -103,7 +99,7 @@ if ($exist = ($block->getRecentlyViewedProducts() && $block->getRecentlyViewedPr <?php if ($showWishlist || $showCompare) : ?> <div class="actions-secondary" data-role="add-to-links"> - <?php if ($this->helper('Magento\Wishlist\Helper\Data')->isAllow() && $showWishlist) : ?> + <?php if ($this->helper(\Magento\Wishlist\Helper\Data::class)->isAllow() && $showWishlist) : ?> <a href="#" class="action towishlist" data-action="add-to-wishlist" data-post='<?= /* @noEscape */ $block->getAddToWishlistParams($_item) ?>' @@ -112,7 +108,7 @@ if ($exist = ($block->getRecentlyViewedProducts() && $block->getRecentlyViewedPr </a> <?php endif; ?> <?php if ($block->getAddToCompareUrl() && $showCompare) : ?> - <?php $compareHelper = $this->helper('Magento\Catalog\Helper\Product\Compare');?> + <?php $compareHelper = $this->helper(\Magento\Catalog\Helper\Product\Compare::class);?> <a href="#" class="action tocompare" data-post='<?= /* @noEscape */ $compareHelper->getPostDataParams($_item) ?>' title="<?= $block->escapeHtmlAttr(__('Add to Compare')) ?>"> diff --git a/app/code/Magento/Review/view/adminhtml/templates/rating/detailed.phtml b/app/code/Magento/Review/view/adminhtml/templates/rating/detailed.phtml index 013c5d87a88bb..bf0cab4c621f5 100644 --- a/app/code/Magento/Review/view/adminhtml/templates/rating/detailed.phtml +++ b/app/code/Magento/Review/view/adminhtml/templates/rating/detailed.phtml @@ -4,22 +4,20 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Review\Block\Adminhtml\Rating\Detailed $block */ ?> -<?php if ($block->getRating() && $block->getRating()->getSize()): ?> - <?php foreach ($block->getRating() as $_rating): ?> +<?php if ($block->getRating() && $block->getRating()->getSize()) : ?> + <?php foreach ($block->getRating() as $_rating) : ?> <div class="admin__field admin__field-rating"> <label class="admin__field-label"><span><?= $block->escapeHtml($_rating->getRatingCode()) ?></span></label> <?php $_iterator = 1; ?> <?php $_options = ($_rating->getRatingOptions()) ? $_rating->getRatingOptions() : $_rating->getOptions() ?> <div class="admin__field-control" data-widget="ratingControl"> - <?php foreach (array_reverse($_options) as $_option): ?> - <input type="radio" name="ratings[<?= $block->escapeHtmlAttr($_rating->getVoteId() ? $_rating->getVoteId() : $_rating->getId()) ?>]" id="<?= $block->escapeHtmlAttr($_rating->getRatingCode()) ?>_<?= $block->escapeHtmlAttr($_option->getValue()) ?>" value="<?= $block->escapeHtmlAttr($_option->getId()) ?>" <?php if ($block->isSelected($_option, $_rating)): ?>checked="checked"<?php endif; ?> /> + <?php foreach (array_reverse($_options) as $_option) : ?> + <input type="radio" name="ratings[<?= $block->escapeHtmlAttr($_rating->getVoteId() ? $_rating->getVoteId() : $_rating->getId()) ?>]" id="<?= $block->escapeHtmlAttr($_rating->getRatingCode()) ?>_<?= $block->escapeHtmlAttr($_option->getValue()) ?>" value="<?= $block->escapeHtmlAttr($_option->getId()) ?>" <?php if ($block->isSelected($_option, $_rating)) : ?>checked="checked"<?php endif; ?> /> <label for="<?= $block->escapeHtmlAttr($_rating->getRatingCode()) ?>_<?= $block->escapeHtmlAttr($_option->getValue()) ?>">★</label> - <?php $_iterator++ ?> + <?php $_iterator++ ?> <?php endforeach; ?> </div> </div> @@ -36,6 +34,6 @@ require([ $('[data-widget=ratingControl]').ratingControl(); }); </script> -<?php else: ?> +<?php else : ?> <?= $block->escapeHtml(__("Rating isn't Available")) ?> <?php endif; ?> diff --git a/app/code/Magento/Review/view/adminhtml/templates/rating/form.phtml b/app/code/Magento/Review/view/adminhtml/templates/rating/form.phtml index 0779d0fcbea3e..3d49d3c31e34f 100644 --- a/app/code/Magento/Review/view/adminhtml/templates/rating/form.phtml +++ b/app/code/Magento/Review/view/adminhtml/templates/rating/form.phtml @@ -4,8 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Review\Block\Adminhtml\Rating\Edit\Tab\Form $block */ ?> <div class="messages"> diff --git a/app/code/Magento/Review/view/adminhtml/templates/rating/options.phtml b/app/code/Magento/Review/view/adminhtml/templates/rating/options.phtml index 779ee425e26f1..6e1dae94298c0 100644 --- a/app/code/Magento/Review/view/adminhtml/templates/rating/options.phtml +++ b/app/code/Magento/Review/view/adminhtml/templates/rating/options.phtml @@ -4,22 +4,21 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile // @deprecated ?> <div class="entry-edit-head"> <h4 class="icon-head head-edit-form fieldset-legend"><?= $block->escapeHtml(__('Assigned Options')) ?></h4> </div> <fieldset id="options_form"> -<?php if (!$options): ?> - <?php for ($_i = 1; $_i <= 5; $_i++): ?> +<?php if (!$options) : ?> + <?php for ($_i = 1; $_i <= 5; $_i++) : ?> <span class="field-row"> <label for="option_<?= /* @noEscape */ $_i ?>"><?= $block->escapeHtml(__('Option Title:')) ?></label> <input id="option_<?= /* @noEscape */ $_i ?>" name="option[<?= /* @noEscape */ $_i ?>][code]" value="<?= /* @noEscape */ $_i ?>" class="input-text" type="text" /> </span> <?php endfor; ?> -<?php elseif ($options->getSize() > 0): ?> - <?php foreach ($options->getItems() as $_item): ?> +<?php elseif ($options->getSize() > 0) : ?> + <?php foreach ($options->getItems() as $_item) : ?> <span class="field-row"> <label for="option_<?= $block->escapeHtmlAttr($_item->getId()) ?>"><?= $block->escapeHtml(__('Option Title:')) ?></label> <input id="option_<?= $block->escapeHtmlAttr($_item->getId()) ?>" name="option[<?= $block->escapeHtmlAttr($_item->getId()) ?>][code]" value="<?= $block->escapeHtmlAttr($_item->getCode()) ?>" class="input-text" type="text" /> diff --git a/app/code/Magento/Review/view/adminhtml/templates/rating/stars/detailed.phtml b/app/code/Magento/Review/view/adminhtml/templates/rating/stars/detailed.phtml index e36344997c806..085c445cae1f7 100644 --- a/app/code/Magento/Review/view/adminhtml/templates/rating/stars/detailed.phtml +++ b/app/code/Magento/Review/view/adminhtml/templates/rating/stars/detailed.phtml @@ -4,22 +4,21 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile // @deprecated ?> -<?php if ($block->getRating() && $block->getRating()->getSize()): ?> +<?php if ($block->getRating() && $block->getRating()->getSize()) : ?> <div class="ratings-container"> - <?php foreach ($block->getRating() as $_rating): ?> - <?php if ($_rating->getPercent()): ?> - <div class="ratings"> - <?= $block->escapeHtml($_rating->getRatingCode()) ?> - <div class="rating-box"> - <div class="rating" style="width:<?= /* @noEscape */ ceil($_rating->getPercent()) ?>%;"></div> + <?php foreach ($block->getRating() as $_rating) : ?> + <?php if ($_rating->getPercent()) : ?> + <div class="ratings"> + <?= $block->escapeHtml($_rating->getRatingCode()) ?> + <div class="rating-box"> + <div class="rating" style="width:<?= /* @noEscape */ ceil($_rating->getPercent()) ?>%;"></div> + </div> </div> - </div> - <?php endif; ?> + <?php endif; ?> <?php endforeach; ?> </div> -<?php else: ?> +<?php else : ?> <?= $block->escapeHtml(__("Rating isn't Available")) ?> <?php endif; ?> diff --git a/app/code/Magento/Review/view/adminhtml/templates/rating/stars/summary.phtml b/app/code/Magento/Review/view/adminhtml/templates/rating/stars/summary.phtml index 56f5186b92524..1f27db795f8c9 100644 --- a/app/code/Magento/Review/view/adminhtml/templates/rating/stars/summary.phtml +++ b/app/code/Magento/Review/view/adminhtml/templates/rating/stars/summary.phtml @@ -4,14 +4,12 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Review\Block\Adminhtml\Rating\Summary $block */ ?> -<?php if ($block->getRatingSummary()->getCount()): ?> +<?php if ($block->getRatingSummary()->getCount()) : ?> <div class="rating-box"> <div class="rating" style="width:<?= /* @noEscape */ ceil($block->getRatingSummary()->getSum() / ($block->getRatingSummary()->getCount())) ?>%;"></div> </div> -<?php else: ?> +<?php else : ?> <?= $block->escapeHtml(__("Rating isn't Available")) ?> <?php endif; ?> diff --git a/app/code/Magento/Review/view/adminhtml/templates/rss/grid/link.phtml b/app/code/Magento/Review/view/adminhtml/templates/rss/grid/link.phtml index 375e983b267e4..b50d618601fc3 100644 --- a/app/code/Magento/Review/view/adminhtml/templates/rss/grid/link.phtml +++ b/app/code/Magento/Review/view/adminhtml/templates/rss/grid/link.phtml @@ -4,10 +4,8 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var $block \Magento\Review\Block\Adminhtml\Grid\Rss\Link */ ?> -<?php if ($block->isRssAllowed() && $block->getLink()): ?> +<?php if ($block->isRssAllowed() && $block->getLink()) : ?> <a href="<?= $block->escapeUrl($block->getLink()) ?>" class="link-feed"><?= $block->escapeHtml($block->getLabel()) ?></a> <?php endif; ?> diff --git a/app/code/Magento/Review/view/frontend/templates/customer/list.phtml b/app/code/Magento/Review/view/frontend/templates/customer/list.phtml index a65ec01d626eb..11ea987b74cec 100644 --- a/app/code/Magento/Review/view/frontend/templates/customer/list.phtml +++ b/app/code/Magento/Review/view/frontend/templates/customer/list.phtml @@ -4,11 +4,9 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Review\Block\Customer\ListCustomer $block */ ?> -<?php if ($block->getReviews() && count($block->getReviews())): ?> +<?php if ($block->getReviews() && count($block->getReviews())) : ?> <div class="table-wrapper reviews"> <table class="data table table-reviews" id="my-reviews-table"> <caption class="table-caption"><?= $block->escapeHtml(__('Product Reviews')) ?></caption> @@ -22,7 +20,7 @@ </tr> </thead> <tbody> - <?php foreach ($block->getReviews() as $review): ?> + <?php foreach ($block->getReviews() as $review) : ?> <tr> <td data-th="<?= $block->escapeHtml(__('Created')) ?>" class="col date"><?= $block->escapeHtml($block->dateFormat($review->getReviewCreatedAt())) ?></td> <td data-th="<?= $block->escapeHtml(__('Product Name')) ?>" class="col item"> @@ -31,7 +29,7 @@ </strong> </td> <td data-th="<?= $block->escapeHtml(__('Rating')) ?>" class="col summary"> - <?php if ($review->getSum()): ?> + <?php if ($review->getSum()) : ?> <div class="rating-summary"> <span class="label"><span><?= $block->escapeHtml(__('Rating')) ?>:</span></span> <div class="rating-result" title="<?= /* @noEscape */ ((int)$review->getSum() / (int)$review->getCount()) ?>%"> @@ -41,7 +39,7 @@ <?php endif; ?> </td> <td data-th="<?= $block->escapeHtmlAttr(__('Review')) ?>" class="col description"> - <?= $this->helper('Magento\Review\Helper\Data')->getDetailHtml($review->getDetail()) ?> + <?= $this->helper(\Magento\Review\Helper\Data::class)->getDetailHtml($review->getDetail()) ?> </td> <td data-th="<?= $block->escapeHtmlAttr(__('Actions')) ?>" class="col actions"> <a href="<?= $block->escapeUrl($block->getReviewUrl($review)) ?>" class="action more"> @@ -53,12 +51,12 @@ </tbody> </table> </div> - <?php if ($block->getToolbarHtml()): ?> + <?php if ($block->getToolbarHtml()) : ?> <div class="toolbar products-reviews-toolbar bottom"> <?= $block->getToolbarHtml() ?> </div> <?php endif; ?> -<?php else: ?> +<?php else : ?> <div class="message info empty"><span><?= $block->escapeHtml(__('You have submitted no reviews.')) ?></span></div> <?php endif; ?> <div class="actions-toolbar"> diff --git a/app/code/Magento/Review/view/frontend/templates/customer/recent.phtml b/app/code/Magento/Review/view/frontend/templates/customer/recent.phtml index ed58e3832577b..5cd81a2f17cbc 100644 --- a/app/code/Magento/Review/view/frontend/templates/customer/recent.phtml +++ b/app/code/Magento/Review/view/frontend/templates/customer/recent.phtml @@ -4,11 +4,9 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Review\Block\Customer\Recent $block */ ?> -<?php if ($block->getReviews() && count($block->getReviews())): ?> +<?php if ($block->getReviews() && count($block->getReviews())) : ?> <div class="block block-reviews-dashboard"> <div class="block-title"> <strong><?= $block->escapeHtml(__('My Recent Reviews')) ?></strong> @@ -16,11 +14,11 @@ </div> <div class="block-content"> <ol class="items"> - <?php foreach ($block->getReviews() as $_review): ?> + <?php foreach ($block->getReviews() as $_review) : ?> <li class="item"> <strong class="product-name"><a href="<?= $block->escapeUrl($block->getReviewUrl($_review->getReviewId())) ?>"><?= $block->escapeHtml($_review->getName()) ?></a></strong> - <?php if ($_review->getSum()): ?> - <?php $rating = $_review->getSum() / $_review->getCount() ?> + <?php if ($_review->getSum()) : ?> + <?php $rating = $_review->getSum() / $_review->getCount() ?> <div class="rating-summary"> <span class="label"><span><?= $block->escapeHtml(__('Rating')) ?>:</span></span> <div class="rating-result" title="<?= $block->escapeHtmlAttr($rating) ?>%"> diff --git a/app/code/Magento/Review/view/frontend/templates/customer/view.phtml b/app/code/Magento/Review/view/frontend/templates/customer/view.phtml index 4903b154d9f13..f92282848b1b7 100644 --- a/app/code/Magento/Review/view/frontend/templates/customer/view.phtml +++ b/app/code/Magento/Review/view/frontend/templates/customer/view.phtml @@ -4,13 +4,11 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Review\Block\Customer\View $block */ $product = $block->getProductData(); ?> -<?php if ($product->getId()): ?> +<?php if ($product->getId()) : ?> <div class="customer-review view"> <div class="product-details"> <div class="product-media"> @@ -21,7 +19,7 @@ $product = $block->getProductData(); </div> <div class="product-info"> <h2 class="product-name"><?= $block->escapeHtml($product->getName()) ?></h2> - <?php if ($block->getRating() && $block->getRating()->getSize()): ?> + <?php if ($block->getRating() && $block->getRating()->getSize()) : ?> <span class="rating-average-label"><?= $block->escapeHtml(__('Average Customer Rating:')) ?></span> <?= $block->getReviewsSummaryHtml($product) ?> <?php endif; ?> @@ -29,29 +27,29 @@ $product = $block->getProductData(); </div> <div class="review-details"> - <?php if ($block->getRating() && $block->getRating()->getSize()): ?> + <?php if ($block->getRating() && $block->getRating()->getSize()) : ?> <div class="title"> <strong><?= $block->escapeHtml(__('Your Review')) ?></strong> </div> <div class="customer-review-rating"> - <?php foreach ($block->getRating() as $_rating): ?> - <?php if ($_rating->getPercent()): ?> - <?php $rating = ceil($_rating->getPercent()) ?> - <div class="rating-summary item"> - <span class="rating-label"><span><?= $block->escapeHtml($_rating->getRatingCode()) ?></span></span> - <div class="rating-result" title="<?= /* @noEscape */ $rating ?>%"> - <span style="width:<?= /* @noEscape */ $rating ?>%"> - <span><?= /* @noEscape */ $rating ?>%</span> - </span> + <?php foreach ($block->getRating() as $_rating) : ?> + <?php if ($_rating->getPercent()) : ?> + <?php $rating = ceil($_rating->getPercent()) ?> + <div class="rating-summary item"> + <span class="rating-label"><span><?= $block->escapeHtml($_rating->getRatingCode()) ?></span></span> + <div class="rating-result" title="<?= /* @noEscape */ $rating ?>%"> + <span style="width:<?= /* @noEscape */ $rating ?>%"> + <span><?= /* @noEscape */ $rating ?>%</span> + </span> + </div> </div> - </div> - <?php endif; ?> + <?php endif; ?> <?php endforeach; ?> </div> <?php endif; ?> <div class="review-title"><?= $block->escapeHtml($block->getReviewData()->getTitle()) ?></div> - <div class="review-content"><?= nl2br($block->escapeHtml($block->getReviewData()->getDetail())) ?></div> + <div class="review-content"><?= /* @noEscape */ nl2br($block->escapeHtml($block->getReviewData()->getDetail())) ?></div> <div class="review-date"> <?= $block->escapeHtml(__('Submitted on %1', '<time class="date">' . $block->dateFormat($block->getReviewData()->getCreatedAt()) . '</time>'), ['time']) ?> </div> diff --git a/app/code/Magento/Review/view/frontend/templates/detailed.phtml b/app/code/Magento/Review/view/frontend/templates/detailed.phtml index df14955a29ea6..7b3b0e2dd6d02 100644 --- a/app/code/Magento/Review/view/frontend/templates/detailed.phtml +++ b/app/code/Magento/Review/view/frontend/templates/detailed.phtml @@ -4,17 +4,15 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Review\Block\Rating\Entity\Detailed $block */ ?> -<?php if (!empty($collection) && $collection->getSize()): ?> +<?php if (!empty($collection) && $collection->getSize()) : ?> <div class="table-wrapper"> <table class="data table ratings review summary"> <caption class="table-caption"><?= $block->escapeHtml(__('Ratings Review Summary')) ?></caption> <tbody> - <?php foreach ($collection as $_rating): ?> - <?php if ($_rating->getSummary()): ?> + <?php foreach ($collection as $_rating) : ?> + <?php if ($_rating->getSummary()) : ?> <tr> <th class="label" scope="row"><?= $block->escapeHtml(__($_rating->getRatingCode())) ?></th> <td class="value"> diff --git a/app/code/Magento/Review/view/frontend/templates/empty.phtml b/app/code/Magento/Review/view/frontend/templates/empty.phtml index 4328a135a98f3..9efdd34081429 100644 --- a/app/code/Magento/Review/view/frontend/templates/empty.phtml +++ b/app/code/Magento/Review/view/frontend/templates/empty.phtml @@ -4,8 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Review\Block\Rating\Entity\Detailed $block */ ?> <p class="no-rating"><a href="#review-form"><?= $block->escapeHtml(__('Be the first to review this product')) ?></a></p> diff --git a/app/code/Magento/Review/view/frontend/templates/form.phtml b/app/code/Magento/Review/view/frontend/templates/form.phtml index 71295d15f8622..f1340945043e9 100644 --- a/app/code/Magento/Review/view/frontend/templates/form.phtml +++ b/app/code/Magento/Review/view/frontend/templates/form.phtml @@ -4,31 +4,29 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Review\Block\Form $block */ ?> <div class="block review-add"> <div class="block-title"><strong><?= $block->escapeHtml(__('Write Your Own Review')) ?></strong></div> <div class="block-content"> -<?php if ($block->getAllowWriteReviewFlag()): ?> +<?php if ($block->getAllowWriteReviewFlag()) : ?> <form action="<?= $block->escapeUrl($block->getAction()) ?>" class="review-form" method="post" id="review-form" data-role="product-review-form" data-bind="scope: 'review-form'"> <?= $block->getBlockHtml('formkey') ?> <?= $block->getChildHtml('form_fields_before') ?> <fieldset class="fieldset review-fieldset" data-hasrequired="<?= $block->escapeHtmlAttr(__('* Required Fields')) ?>"> <legend class="legend review-legend"><span><?= $block->escapeHtml(__("You're reviewing:")) ?></span><strong><?= $block->escapeHtml($block->getProductInfo()->getName()) ?></strong></legend><br /> - <?php if ($block->getRatings() && $block->getRatings()->getSize()): ?> + <?php if ($block->getRatings() && $block->getRatings()->getSize()) : ?> <span id="input-message-box"></span> <fieldset class="field required review-field-ratings"> <legend class="label"><span><?= $block->escapeHtml(__('Your Rating')) ?></span></legend><br/> <div class="control"> <div class="nested" id="product-review-table"> - <?php foreach ($block->getRatings() as $_rating): ?> + <?php foreach ($block->getRatings() as $_rating) : ?> <div class="field choice review-field-rating"> <label class="label" id="<?= $block->escapeHtml($_rating->getRatingCode()) ?>_rating_label"><span><?= $block->escapeHtml($_rating->getRatingCode()) ?></span></label> <div class="control review-control-vote"> <?php $options = $_rating->getOptions();?> - <?php $iterator = 1; foreach ($options as $_option): ?> + <?php $iterator = 1; foreach ($options as $_option) : ?> <input type="radio" name="ratings[<?= $block->escapeHtmlAttr($_rating->getId()) ?>]" @@ -44,7 +42,7 @@ id="<?= $block->escapeHtmlAttr($_rating->getRatingCode()) ?>_<?= $block->escapeHtmlAttr($_option->getValue()) ?>_label"> <span><?= $block->escapeHtml(__('%1 %2', $iterator, $iterator > 1 ? __('stars') : __('star'))) ?></span> </label> - <?php $iterator++; ?> + <?php $iterator++; ?> <?php endforeach; ?> </div> </div> @@ -90,7 +88,7 @@ } } </script> -<?php else: ?> +<?php else : ?> <div class="message info notlogged" id="review-form"> <div> <?= $block->escapeHtml(__('Only registered users can write reviews. Please <a href="%1">Sign in</a> or <a href="%2">create an account</a>', $block->getLoginLink(), $block->getRegisterUrl()), ['a']) ?> diff --git a/app/code/Magento/Review/view/frontend/templates/helper/summary.phtml b/app/code/Magento/Review/view/frontend/templates/helper/summary.phtml index 23cb6699aeb21..b042b5e92cbac 100644 --- a/app/code/Magento/Review/view/frontend/templates/helper/summary.phtml +++ b/app/code/Magento/Review/view/frontend/templates/helper/summary.phtml @@ -4,43 +4,41 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Review\Block\Product\ReviewRenderer $block */ $url = $block->getReviewsUrl() . '#reviews'; $urlForm = $block->getReviewsUrl() . '#review-form'; ?> -<?php if ($block->isReviewEnabled() && $block->getReviewsCount()): ?> -<?php $rating = $block->getRatingSummary(); ?> -<div class="product-reviews-summary<?= !$rating ? ' no-rating' : '' ?>" itemprop="aggregateRating" itemscope itemtype="http://schema.org/AggregateRating"> - <?php if ($rating):?> - <div class="rating-summary"> - <span class="label"><span><?= $block->escapeHtml(__('Rating')) ?>:</span></span> - <div class="rating-result" title="<?= $block->escapeHtmlAttr($rating); ?>%"> - <span style="width:<?= $block->escapeHtmlAttr($rating); ?>%"> - <span> - <span itemprop="ratingValue"><?= $block->escapeHtml($rating); ?></span>% of <span itemprop="bestRating">100</span> +<?php if ($block->isReviewEnabled() && $block->getReviewsCount()) : ?> + <?php $rating = $block->getRatingSummary(); ?> + <div class="product-reviews-summary<?= !$rating ? ' no-rating' : '' ?>" itemprop="aggregateRating" itemscope itemtype="http://schema.org/AggregateRating"> + <?php if ($rating) :?> + <div class="rating-summary"> + <span class="label"><span><?= $block->escapeHtml(__('Rating')) ?>:</span></span> + <div class="rating-result" title="<?= $block->escapeHtmlAttr($rating); ?>%"> + <span style="width:<?= $block->escapeHtmlAttr($rating); ?>%"> + <span> + <span itemprop="ratingValue"><?= $block->escapeHtml($rating); ?></span>% of <span itemprop="bestRating">100</span> + </span> </span> - </span> + </div> </div> - </div> - <?php endif;?> - <div class="reviews-actions"> - <a class="action view" - href="<?= $block->escapeUrl($url) ?>"> - <span itemprop="reviewCount"><?= $block->escapeHtml($block->getReviewsCount()) ?></span>  - <span><?= ($block->getReviewsCount() == 1) ? $block->escapeHtml(__('Review')) : $block->escapeHtml(__('Reviews')) ?></span> - </a> - <a class="action add" href="<?= $block->escapeUrl($urlForm) ?>"><?= $block->escapeHtml(__('Add Your Review')) ?></a> + <?php endif;?> + <div class="reviews-actions"> + <a class="action view" + href="<?= $block->escapeUrl($url) ?>"> + <span itemprop="reviewCount"><?= $block->escapeHtml($block->getReviewsCount()) ?></span>  + <span><?= ($block->getReviewsCount() == 1) ? $block->escapeHtml(__('Review')) : $block->escapeHtml(__('Reviews')) ?></span> + </a> + <a class="action add" href="<?= $block->escapeUrl($urlForm) ?>"><?= $block->escapeHtml(__('Add Your Review')) ?></a> + </div> </div> -</div> -<?php elseif ($block->isReviewEnabled() && $block->getDisplayIfEmpty()): ?> -<div class="product-reviews-summary empty"> - <div class="reviews-actions"> - <a class="action add" href="<?= $block->escapeUrl($urlForm) ?>"> - <?= $block->escapeHtml(__('Be the first to review this product')) ?> - </a> +<?php elseif ($block->isReviewEnabled() && $block->getDisplayIfEmpty()) : ?> + <div class="product-reviews-summary empty"> + <div class="reviews-actions"> + <a class="action add" href="<?= $block->escapeUrl($urlForm) ?>"> + <?= $block->escapeHtml(__('Be the first to review this product')) ?> + </a> + </div> </div> -</div> <?php endif; ?> diff --git a/app/code/Magento/Review/view/frontend/templates/helper/summary_short.phtml b/app/code/Magento/Review/view/frontend/templates/helper/summary_short.phtml index a3ff56505f06f..7ea84c952eaaa 100644 --- a/app/code/Magento/Review/view/frontend/templates/helper/summary_short.phtml +++ b/app/code/Magento/Review/view/frontend/templates/helper/summary_short.phtml @@ -4,34 +4,32 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Review\Block\Product\ReviewRenderer $block */ $url = $block->getReviewsUrl() . '#reviews'; $urlForm = $block->getReviewsUrl() . '#review-form'; ?> -<?php if ($block->isReviewEnabled() && $block->getReviewsCount()): ?> -<?php $rating = $block->getRatingSummary(); ?> -<div class="product-reviews-summary short<?= !$rating ? ' no-rating' : '' ?>"> - <?php if ($rating):?> - <div class="rating-summary"> - <span class="label"><span><?= $block->escapeHtml(__('Rating')) ?>:</span></span> - <div class="rating-result" title="<?= $block->escapeHtmlAttr($rating) ?>%"> - <span style="width:<?= $block->escapeHtmlAttr($rating) ?>%"><span><?= $block->escapeHtml($rating) ?>%</span></span> +<?php if ($block->isReviewEnabled() && $block->getReviewsCount()) : ?> + <?php $rating = $block->getRatingSummary(); ?> + <div class="product-reviews-summary short<?= !$rating ? ' no-rating' : '' ?>"> + <?php if ($rating) :?> + <div class="rating-summary"> + <span class="label"><span><?= $block->escapeHtml(__('Rating')) ?>:</span></span> + <div class="rating-result" title="<?= $block->escapeHtmlAttr($rating) ?>%"> + <span style="width:<?= $block->escapeHtmlAttr($rating) ?>%"><span><?= $block->escapeHtml($rating) ?>%</span></span> + </div> + </div> + <?php endif;?> + <div class="reviews-actions"> + <a class="action view" href="<?= $block->escapeUrl($url) ?>"><?= $block->escapeHtml($block->getReviewsCount()) ?> <span><?= ($block->getReviewsCount() == 1) ? $block->escapeHtml(__('Review')) : $block->escapeHtml(__('Reviews')) ?></span></a> </div> </div> - <?php endif;?> - <div class="reviews-actions"> - <a class="action view" href="<?= $block->escapeUrl($url) ?>"><?= $block->escapeHtml($block->getReviewsCount()) ?> <span><?= ($block->getReviewsCount() == 1) ? $block->escapeHtml(__('Review')) : $block->escapeHtml(__('Reviews')) ?></span></a> - </div> -</div> -<?php elseif ($block->isReviewEnabled() && $block->getDisplayIfEmpty()): ?> -<div class="product-reviews-summary short empty"> - <div class="reviews-actions"> - <a class="action add" href="<?= $block->escapeUrl($urlForm) ?>"> - <?= $block->escapeHtml(__('Be the first to review this product')) ?> - </a> +<?php elseif ($block->isReviewEnabled() && $block->getDisplayIfEmpty()) : ?> + <div class="product-reviews-summary short empty"> + <div class="reviews-actions"> + <a class="action add" href="<?= $block->escapeUrl($urlForm) ?>"> + <?= $block->escapeHtml(__('Be the first to review this product')) ?> + </a> + </div> </div> -</div> <?php endif; ?> diff --git a/app/code/Magento/Review/view/frontend/templates/product/view/count.phtml b/app/code/Magento/Review/view/frontend/templates/product/view/count.phtml index bff1c48508e11..cd98ab3c4cc78 100644 --- a/app/code/Magento/Review/view/frontend/templates/product/view/count.phtml +++ b/app/code/Magento/Review/view/frontend/templates/product/view/count.phtml @@ -4,9 +4,8 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile // @deprecated ?> -<?php if (!empty($count)):?> +<?php if (!empty($count)) : ?> <a href="#customer-reviews" class="nobr"><?= $block->escapeHtml(__('%1 Review(s)', $count)) ?></a> <?php endif;?> diff --git a/app/code/Magento/Review/view/frontend/templates/product/view/list.phtml b/app/code/Magento/Review/view/frontend/templates/product/view/list.phtml index dc02853e77b18..347686d5c2ba4 100644 --- a/app/code/Magento/Review/view/frontend/templates/product/view/list.phtml +++ b/app/code/Magento/Review/view/frontend/templates/product/view/list.phtml @@ -4,14 +4,12 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var Magento\Review\Block\Product\View\ListView $block */ $_items = $block->getReviewsCollection()->getItems(); $format = $block->getDateFormat() ?: \IntlDateFormatter::SHORT; ?> -<?php if (count($_items)):?> +<?php if (count($_items)) : ?> <div class="block review-list" id="customer-reviews"> <div class="block-title"> <strong><?= $block->escapeHtml(__('Customer Reviews')) ?></strong> @@ -21,17 +19,17 @@ $format = $block->getDateFormat() ?: \IntlDateFormatter::SHORT; <?= $block->getChildHtml('toolbar') ?> </div> <ol class="items review-items"> - <?php foreach ($_items as $_review):?> + <?php foreach ($_items as $_review) : ?> <li class="item review-item" itemscope itemprop="review" itemtype="http://schema.org/Review"> <div class="review-title" itemprop="name"><?= $block->escapeHtml($_review->getTitle()) ?></div> - <?php if (count($_review->getRatingVotes())): ?> + <?php if (count($_review->getRatingVotes())) : ?> <div class="review-ratings"> - <?php foreach ($_review->getRatingVotes() as $_vote): ?> + <?php foreach ($_review->getRatingVotes() as $_vote) : ?> <div class="rating-summary item" itemprop="reviewRating" itemscope itemtype="http://schema.org/Rating"> <span class="label rating-label"><span><?= $block->escapeHtml($_vote->getRatingCode()) ?></span></span> <div class="rating-result" title="<?= $block->escapeHtmlAttr($_vote->getPercent()) ?>%"> - <meta itemprop="worstRating" content = "1"/> - <meta itemprop="bestRating" content = "100"/> + <meta itemprop="worstRating" content = "1"/> + <meta itemprop="bestRating" content = "100"/> <span style="width:<?= $block->escapeHtmlAttr($_vote->getPercent()) ?>%"> <span itemprop="ratingValue"><?= $block->escapeHtml($_vote->getPercent()) ?>%</span> </span> @@ -41,7 +39,7 @@ $format = $block->getDateFormat() ?: \IntlDateFormatter::SHORT; </div> <?php endif; ?> <div class="review-content" itemprop="description"> - <?= nl2br($block->escapeHtml($_review->getDetail())) ?> + <?= /* @noEscape */ nl2br($block->escapeHtml($_review->getDetail())) ?> </div> <div class="review-details"> <p class="review-author"> diff --git a/app/code/Magento/Review/view/frontend/templates/product/view/other.phtml b/app/code/Magento/Review/view/frontend/templates/product/view/other.phtml index 48d668ca85a0d..686bd8b117b6e 100644 --- a/app/code/Magento/Review/view/frontend/templates/product/view/other.phtml +++ b/app/code/Magento/Review/view/frontend/templates/product/view/other.phtml @@ -4,8 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Review\Block\Product\View\Other $block */ ?> <?php $_product = $block->getProduct(); ?> diff --git a/app/code/Magento/Review/view/frontend/templates/redirect.phtml b/app/code/Magento/Review/view/frontend/templates/redirect.phtml index 2fdb5e90a9c18..aad4d9066cb45 100644 --- a/app/code/Magento/Review/view/frontend/templates/redirect.phtml +++ b/app/code/Magento/Review/view/frontend/templates/redirect.phtml @@ -3,11 +3,10 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ - -// @codingStandardsIgnoreFile - ?> <?php + // phpcs:ignore Magento2.Functions.DiscouragedFunction header("Location:{$block->getProduct()->getProductUrl()}#info-product_reviews"); + // phpcs:ignore Magento2.Security.LanguageConstruct.ExitUsage exit; ?> diff --git a/app/code/Magento/Review/view/frontend/templates/view.phtml b/app/code/Magento/Review/view/frontend/templates/view.phtml index 205ce5c20572a..1c3d1942dd2e7 100644 --- a/app/code/Magento/Review/view/frontend/templates/view.phtml +++ b/app/code/Magento/Review/view/frontend/templates/view.phtml @@ -4,11 +4,9 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Review\Block\View $block */ ?> -<?php if ($block->getProductData()->getId()): ?> +<?php if ($block->getProductData()->getId()) : ?> <div class="product-review"> <div class="page-title-wrapper"> <h1><?= $block->escapeHtml(__('Review Details')) ?></h1> @@ -17,20 +15,20 @@ <a href="<?= $block->escapeUrl($block->getProductData()->getProductUrl()) ?>"> <?= $block->getImage($block->getProductData(), 'product_base_image', ['class' => 'product-image'])->toHtml() ?> </a> - <?php if ($block->getRating() && $block->getRating()->getSize()): ?> - <p><?= $block->escapeHtml(__('Average Customer Rating')) ?>:</p> - <?= $block->getReviewsSummaryHtml($block->getProductData()) ?> + <?php if ($block->getRating() && $block->getRating()->getSize()) : ?> + <p><?= $block->escapeHtml(__('Average Customer Rating')) ?>:</p> + <?= $block->getReviewsSummaryHtml($block->getProductData()) ?> <?php endif; ?> </div> <div class="details"> <h3 class="product-name"><?= $block->escapeHtml($block->getProductData()->getName()) ?></h3> - <?php if ($block->getRating() && $block->getRating()->getSize()): ?> + <?php if ($block->getRating() && $block->getRating()->getSize()) : ?> <h4><?= $block->escapeHtml(__('Product Rating:')) ?></h4> <div class="table-wrapper"> <table class="data-table review-summary-table"> <caption class="table-caption"><?= $block->escapeHtml(__('Product Rating')) ?></caption> - <?php foreach ($block->getRating() as $_rating): ?> - <?php if ($_rating->getPercent()): ?> + <?php foreach ($block->getRating() as $_rating) : ?> + <?php if ($_rating->getPercent()) : ?> <tr> <td class="label"><?= $block->escapeHtml(__($_rating->getRatingCode())) ?></td> <td class="value"> @@ -44,7 +42,7 @@ </div> <?php endif; ?> <p class="date"><?= $block->escapeHtml(__('Product Review (submitted on %1):', $block->dateFormat($block->getReviewData()->getCreatedAt()))) ?></p> - <p><?= nl2br($block->escapeHtml($block->getReviewData()->getDetail())) ?></p> + <p><?= /* @noEscape */ nl2br($block->escapeHtml($block->getReviewData()->getDetail())) ?></p> </div> <div class="actions"> <div class="secondary"> diff --git a/app/code/Magento/Robots/view/frontend/templates/robots.phtml b/app/code/Magento/Robots/view/frontend/templates/robots.phtml index 644445bf10640..e5f14b98d6565 100644 --- a/app/code/Magento/Robots/view/frontend/templates/robots.phtml +++ b/app/code/Magento/Robots/view/frontend/templates/robots.phtml @@ -3,4 +3,4 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ -?><?= $layoutContent; +?><?= /* @noEscape */ $layoutContent; ?> diff --git a/app/code/Magento/Rss/view/frontend/templates/feeds.phtml b/app/code/Magento/Rss/view/frontend/templates/feeds.phtml index 22328e9188ea5..267973f51c7a4 100644 --- a/app/code/Magento/Rss/view/frontend/templates/feeds.phtml +++ b/app/code/Magento/Rss/view/frontend/templates/feeds.phtml @@ -4,8 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Rss\Block\Feeds $block */ ?> @@ -13,15 +11,15 @@ <caption class="table-caption"><?= $block->escapeHtml(__('Feed')) ?></caption> <tbody> <th colspan="2" scope="col"><?= $block->escapeHtml(__('Miscellaneous Feeds')) ?></th> - <?php foreach ($block->getFeeds() as $feed): ?> - <?php if (!isset($feed['group'])): ?> + <?php foreach ($block->getFeeds() as $feed) : ?> + <?php if (!isset($feed['group'])) : ?> <tr> <td class="col feed"><?= $block->escapeHtml($feed['label']) ?></td> <td class="col action"> <a href="<?= $block->escapeUrl($feed['link']) ?>" class="action get"><span><?= $block->escapeHtml(__('Get Feed')) ?></span></a> </td> </tr> - <?php else: ?> + <?php else : ?> <th colspan="2" scope="col"><?= $block->escapeHtml($feed['group']) ?></th> <?php foreach ($feed['feeds'] as $item) :?> <tr> diff --git a/app/code/Magento/Security/view/adminhtml/templates/session/activity.phtml b/app/code/Magento/Security/view/adminhtml/templates/session/activity.phtml index 88a3ff433a033..a4c70be6b469d 100644 --- a/app/code/Magento/Security/view/adminhtml/templates/session/activity.phtml +++ b/app/code/Magento/Security/view/adminhtml/templates/session/activity.phtml @@ -7,7 +7,6 @@ /** * Account activity template * - * @codingStandardsIgnoreFile * @var $block \Magento\Security\Block\Adminhtml\Session\Activity */ @@ -39,21 +38,18 @@ $sessionInfoCollection = $block->getSessionInfoCollection(); </thead> <tbody> <?php - foreach ($sessionInfoCollection as $item): ?> + foreach ($sessionInfoCollection as $item) : ?> <tr> <td><?= $block->escapeHtml($item->getFormattedIp()) ?></td> <td><?= $block->escapeHtml($block->formatDateTime($item->getCreatedAt())) ?></td> </tr> - <?php - endforeach; - ?> + <?php endforeach; ?> </tbody> </table> <div class="button-container"> <button type="button" - <?php - if ($block->areMultipleSessionsActive()): ?> + <?php if ($block->areMultipleSessionsActive()) : ?> data-mage-init='{"confirmRedirect":{ "message": "<?= $block->escapeJs(__('Are you sure that you want to log out all other sessions?')) @@ -62,8 +58,7 @@ $sessionInfoCollection = $block->getSessionInfoCollection(); $block->escapeJs($block->escapeUrl($block->getUrl('security/session/logoutAll'))) ?>" }}' - <?php - else: ?>disabled<?php + <?php else : ?>disabled<?php endif ?> title="<?= $block->escapeHtmlAttr(__('Log out all other sessions')) ?>"> <?= $block->escapeHtml(__('Log out all other sessions')) ?> diff --git a/app/code/Magento/SendFriend/view/frontend/templates/send.phtml b/app/code/Magento/SendFriend/view/frontend/templates/send.phtml index 3e00353a9157d..eb9318271c1d8 100644 --- a/app/code/Magento/SendFriend/view/frontend/templates/send.phtml +++ b/app/code/Magento/SendFriend/view/frontend/templates/send.phtml @@ -4,8 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** * Send to friend form */ @@ -93,14 +91,14 @@ <legend class="legend"><span><?= $block->escapeHtml(__('Invitee')) ?></span></legend> <br /> <div id="recipients-options"></div> - <?php if ($block->getMaxRecipients()): ?> + <?php if ($block->getMaxRecipients()) : ?> <div id="max-recipient-message" style="display: none;" class="message notice limit" role="alert"> <span><?= $block->escapeHtml(__('Maximum %1 email addresses allowed.', $block->getMaxRecipients())) ?></span> </div> <?php endif; ?> <div class="actions-toolbar"> <div class="secondary"> - <?php if (1 < $block->getMaxRecipients()): ?> + <?php if (1 < $block->getMaxRecipients()) : ?> <button type="button" id="add-recipient-button" class="action add"> <span><?= $block->escapeHtml(__('Add Invitee')) ?></span></button> <?php endif; ?> @@ -112,7 +110,7 @@ <div class="actions-toolbar"> <div class="primary"> <button type="submit" - class="action submit primary"<?php if (!$block->canSend()): ?> disabled="disabled"<?php endif ?>> + class="action submit primary"<?php if (!$block->canSend()) : ?> disabled="disabled"<?php endif ?>> <span><?= $block->escapeHtml(__('Send Email')) ?></span></button> </div> <div class="secondary"> diff --git a/app/code/Magento/Signifyd/view/adminhtml/templates/case_info.phtml b/app/code/Magento/Signifyd/view/adminhtml/templates/case_info.phtml index a42b7f93b5b92..07f1b2c2e4ae6 100644 --- a/app/code/Magento/Signifyd/view/adminhtml/templates/case_info.phtml +++ b/app/code/Magento/Signifyd/view/adminhtml/templates/case_info.phtml @@ -3,15 +3,12 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ - -// @codingStandardsIgnoreFile ?> <?php /** @var $block Magento\Signifyd\Block\Adminhtml\CaseInfo */ ?> <?php - - if ($block->isEmptyCase()) { - return ''; - } +if ($block->isEmptyCase()) { + return ''; +} ?> <section class="admin__page-section order-case-info"> <div class="admin__page-section-title"> diff --git a/app/code/Magento/Signifyd/view/frontend/templates/fingerprint.phtml b/app/code/Magento/Signifyd/view/frontend/templates/fingerprint.phtml index 356bab9c62ded..657043b895f60 100644 --- a/app/code/Magento/Signifyd/view/frontend/templates/fingerprint.phtml +++ b/app/code/Magento/Signifyd/view/frontend/templates/fingerprint.phtml @@ -4,11 +4,9 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var $block Magento\Signifyd\Block\Fingerprint */ ?> -<?php if ($block->isModuleActive()): ?> +<?php if ($block->isModuleActive()) : ?> <script async id="sig-api" diff --git a/app/code/Magento/Store/view/frontend/templates/switch/flags.phtml b/app/code/Magento/Store/view/frontend/templates/switch/flags.phtml index 5ceb4b3f856d7..9c48469e9d560 100644 --- a/app/code/Magento/Store/view/frontend/templates/switch/flags.phtml +++ b/app/code/Magento/Store/view/frontend/templates/switch/flags.phtml @@ -4,15 +4,13 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - // @deprecated ?> -<?php if (count($block->getStores())>1): ?> +<?php if (count($block->getStores())>1) : ?> <div class="form-language"> <label for="select-language"><?= $block->escapeHtml(__('Your Language:')) ?></label> <select id="select-language" title="<?= $block->escapeHtmlAttr(__('Your Language')) ?>" onchange="window.location.href=this.value" class="flags"> - <?php foreach ($block->getStores() as $_lang): ?> + <?php foreach ($block->getStores() as $_lang) : ?> <?php $_selected = ($_lang->getId() == $block->getCurrentStoreId()) ? ' selected="selected"' : '' ?> <option value="<?= $block->escapeUrl($_lang->getCurrentUrl()) ?>" style="background-image:url('<?= $block->escapeUrl($block->getViewFileUrl('images/flags/flag_' . $_lang->getCode() . '.gif')) ?>');"<?= /* @noEscape */ $_selected ?>><?= $block->escapeHtml($_lang->getName()) ?></option> <?php endforeach; ?> diff --git a/app/code/Magento/Store/view/frontend/templates/switch/languages.phtml b/app/code/Magento/Store/view/frontend/templates/switch/languages.phtml index a620c2ce71407..87a2c40fddaa1 100644 --- a/app/code/Magento/Store/view/frontend/templates/switch/languages.phtml +++ b/app/code/Magento/Store/view/frontend/templates/switch/languages.phtml @@ -4,36 +4,34 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Store\Block\Switcher $block */ ?> -<?php if (count($block->getStores())>1): ?> -<?php $id = $block->getIdModifier() ? '-' . $block->getIdModifier() : '' ?> -<div class="switcher language switcher-language" data-ui-id="language-switcher" id="switcher-language<?= $block->escapeHtmlAttr($id) ?>"> - <strong class="label switcher-label"><span><?= $block->escapeHtml(__('Language')) ?></span></strong> - <div class="actions dropdown options switcher-options"> - <div class="action toggle switcher-trigger" - id="switcher-language-trigger<?= $block->escapeHtmlAttr($id) ?>" - data-mage-init='{"dropdown":{}}' - data-toggle="dropdown" - data-trigger-keypress-button="true"> - <strong class="view-<?= $block->escapeHtml($block->getCurrentStoreCode()) ?>"> - <span><?= $block->escapeHtml($block->getStoreName()) ?></span> - </strong> +<?php if (count($block->getStores())>1) : ?> + <?php $id = $block->getIdModifier() ? '-' . $block->getIdModifier() : '' ?> + <div class="switcher language switcher-language" data-ui-id="language-switcher" id="switcher-language<?= $block->escapeHtmlAttr($id) ?>"> + <strong class="label switcher-label"><span><?= $block->escapeHtml(__('Language')) ?></span></strong> + <div class="actions dropdown options switcher-options"> + <div class="action toggle switcher-trigger" + id="switcher-language-trigger<?= $block->escapeHtmlAttr($id) ?>" + data-mage-init='{"dropdown":{}}' + data-toggle="dropdown" + data-trigger-keypress-button="true"> + <strong class="view-<?= $block->escapeHtml($block->getCurrentStoreCode()) ?>"> + <span><?= $block->escapeHtml($block->getStoreName()) ?></span> + </strong> + </div> + <ul class="dropdown switcher-dropdown" + data-target="dropdown"> + <?php foreach ($block->getStores() as $_lang) : ?> + <?php if ($_lang->getId() != $block->getCurrentStoreId()) : ?> + <li class="view-<?= $block->escapeHtml($_lang->getCode()) ?> switcher-option"> + <a href="<?= $block->escapeUrl($block->getViewModel()->getTargetStoreRedirectUrl($_lang)) ?>"> + <?= $block->escapeHtml($_lang->getName()) ?> + </a> + </li> + <?php endif; ?> + <?php endforeach; ?> + </ul> </div> - <ul class="dropdown switcher-dropdown" - data-target="dropdown"> - <?php foreach ($block->getStores() as $_lang): ?> - <?php if ($_lang->getId() != $block->getCurrentStoreId()): ?> - <li class="view-<?= $block->escapeHtml($_lang->getCode()) ?> switcher-option"> - <a href="<?= $block->escapeUrl($block->getViewModel()->getTargetStoreRedirectUrl($_lang)) ?>"> - <?= $block->escapeHtml($_lang->getName()) ?> - </a> - </li> - <?php endif; ?> - <?php endforeach; ?> - </ul> </div> -</div> <?php endif; ?> diff --git a/app/code/Magento/Store/view/frontend/templates/switch/stores.phtml b/app/code/Magento/Store/view/frontend/templates/switch/stores.phtml index fb3f316bc16c8..e0c49401a6ce5 100644 --- a/app/code/Magento/Store/view/frontend/templates/switch/stores.phtml +++ b/app/code/Magento/Store/view/frontend/templates/switch/stores.phtml @@ -4,38 +4,36 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Store\Block\Switcher $block */ ?> -<?php if (count($block->getGroups())>1): ?> +<?php if (count($block->getGroups())>1) : ?> <div class="switcher store switcher-store" id="switcher-store"> <strong class="label switcher-label"><span><?= $block->escapeHtml(__('Select Store')) ?></span></strong> <div class="actions dropdown options switcher-options"> - <?php foreach ($block->getGroups() as $_group): ?> - <?php if ($_group->getId() == $block->getCurrentGroupId()): ?> - <div class="action toggle switcher-trigger" - role="button" - tabindex="0" - data-mage-init='{"dropdown":{}}' - data-toggle="dropdown" - data-trigger-keypress-button="true" - id="switcher-store-trigger"> - <strong> - <span><?= $block->escapeHtml($_group->getName()) ?></span> - </strong> - </div> - <?php endif; ?> + <?php foreach ($block->getGroups() as $_group) : ?> + <?php if ($_group->getId() == $block->getCurrentGroupId()) : ?> + <div class="action toggle switcher-trigger" + role="button" + tabindex="0" + data-mage-init='{"dropdown":{}}' + data-toggle="dropdown" + data-trigger-keypress-button="true" + id="switcher-store-trigger"> + <strong> + <span><?= $block->escapeHtml($_group->getName()) ?></span> + </strong> + </div> + <?php endif; ?> <?php endforeach; ?> <ul class="dropdown switcher-dropdown" data-target="dropdown"> - <?php foreach ($block->getGroups() as $_group): ?> - <?php if (!($_group->getId() == $block->getCurrentGroupId())): ?> - <li class="switcher-option"> - <a href="#" data-post='<?= /* @noEscape */ $block->getTargetStorePostData($_group->getDefaultStore()) ?>'> - <?= $block->escapeHtml($_group->getName()) ?> - </a> - </li> - <?php endif; ?> + <?php foreach ($block->getGroups() as $_group) : ?> + <?php if (!($_group->getId() == $block->getCurrentGroupId())) : ?> + <li class="switcher-option"> + <a href="#" data-post='<?= /* @noEscape */ $block->getTargetStorePostData($_group->getDefaultStore()) ?>'> + <?= $block->escapeHtml($_group->getName()) ?> + </a> + </li> + <?php endif; ?> <?php endforeach; ?> </ul> </div> diff --git a/app/code/Magento/Swagger/view/frontend/templates/swagger-ui/index.phtml b/app/code/Magento/Swagger/view/frontend/templates/swagger-ui/index.phtml index 26ef4847a1267..520fed29e9e12 100644 --- a/app/code/Magento/Swagger/view/frontend/templates/swagger-ui/index.phtml +++ b/app/code/Magento/Swagger/view/frontend/templates/swagger-ui/index.phtml @@ -12,9 +12,8 @@ * Modified by Magento, Modifications Copyright © Magento, Inc. All rights reserved. */ -/** @var \Magento\Swagger\Block\Index $block - * - * @codingStandardsIgnoreFile +/** + * @var \Magento\Swagger\Block\Index $block */ $schemaUrl = $block->getSchemaUrl(); diff --git a/app/code/Magento/Tax/view/adminhtml/templates/toolbar/class/add.phtml b/app/code/Magento/Tax/view/adminhtml/templates/toolbar/class/add.phtml index a674424f723ca..d5017f83affe4 100644 --- a/app/code/Magento/Tax/view/adminhtml/templates/toolbar/class/add.phtml +++ b/app/code/Magento/Tax/view/adminhtml/templates/toolbar/class/add.phtml @@ -4,7 +4,6 @@ * See COPYING.txt for license details. */ // @deprecated -// @codingStandardsIgnoreFile ?> <div data-mage-init='{"floatingHeader": {}}' class="page-actions"> <button type="button" onclick="window.location.href='<?= $block->escapeUrl($createUrl) ?>'"> diff --git a/app/code/Magento/Tax/view/adminhtml/templates/toolbar/class/save.phtml b/app/code/Magento/Tax/view/adminhtml/templates/toolbar/class/save.phtml index cfe5a7d14785a..fa9fcb8fbcfcd 100644 --- a/app/code/Magento/Tax/view/adminhtml/templates/toolbar/class/save.phtml +++ b/app/code/Magento/Tax/view/adminhtml/templates/toolbar/class/save.phtml @@ -4,7 +4,6 @@ * See COPYING.txt for license details. */ // @deprecated -// @codingStandardsIgnoreFile ?> <div data-mage-init='{"floatingHeader": {}}' class="page-actions"> <?= $block->getBackButtonHtml() ?> diff --git a/app/code/Magento/Tax/view/adminhtml/templates/toolbar/rule/add.phtml b/app/code/Magento/Tax/view/adminhtml/templates/toolbar/rule/add.phtml index b0ad610272f80..e21dbb099ff5d 100644 --- a/app/code/Magento/Tax/view/adminhtml/templates/toolbar/rule/add.phtml +++ b/app/code/Magento/Tax/view/adminhtml/templates/toolbar/rule/add.phtml @@ -4,7 +4,6 @@ * See COPYING.txt for license details. */ // @deprecated -// @codingStandardsIgnoreFile ?> <div data-mage-init='{"floatingHeader": {}}' class="page-actions"> <button type="button" onclick="window.location.href='<?= $block->escapeUrl($createUrl) ?>'"> diff --git a/app/code/Magento/Tax/view/adminhtml/templates/toolbar/rule/save.phtml b/app/code/Magento/Tax/view/adminhtml/templates/toolbar/rule/save.phtml index 7c5de950469ab..10251e2805f2f 100644 --- a/app/code/Magento/Tax/view/adminhtml/templates/toolbar/rule/save.phtml +++ b/app/code/Magento/Tax/view/adminhtml/templates/toolbar/rule/save.phtml @@ -4,7 +4,6 @@ * See COPYING.txt for license details. */ // @deprecated -// @codingStandardsIgnoreFile ?> <div data-mage-init='{"floatingHeader": {}}' class="page-actions"> <?= $block->getBackButtonHtml() ?> diff --git a/app/code/Magento/Translation/view/adminhtml/templates/translate_inline.phtml b/app/code/Magento/Translation/view/adminhtml/templates/translate_inline.phtml index 0d6582d0b21e9..6b6327a5679ea 100644 --- a/app/code/Magento/Translation/view/adminhtml/templates/translate_inline.phtml +++ b/app/code/Magento/Translation/view/adminhtml/templates/translate_inline.phtml @@ -4,8 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Framework\View\Element\Template $block */ ?> <link rel="stylesheet" type="text/css" href="<?= $block->escapeUrl($block->getViewFileUrl('prototype/windows/themes/default.css')) ?>"/> diff --git a/app/code/Magento/Translation/view/base/templates/translate.phtml b/app/code/Magento/Translation/view/base/templates/translate.phtml index ec88b1d092026..9ee6c62827292 100644 --- a/app/code/Magento/Translation/view/base/templates/translate.phtml +++ b/app/code/Magento/Translation/view/base/templates/translate.phtml @@ -4,11 +4,9 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Translation\Block\Js $block */ ?> -<?php if ($block->dictionaryEnabled()): ?> +<?php if ($block->dictionaryEnabled()) : ?> <script> require.config({ deps: [ diff --git a/app/code/Magento/Translation/view/frontend/templates/translate_inline.phtml b/app/code/Magento/Translation/view/frontend/templates/translate_inline.phtml index 5b082d32c40d6..bec7dca9359c0 100644 --- a/app/code/Magento/Translation/view/frontend/templates/translate_inline.phtml +++ b/app/code/Magento/Translation/view/frontend/templates/translate_inline.phtml @@ -4,8 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Framework\View\Element\Template $block */ ?> <link rel="stylesheet" type="text/css" href="<?= $block->escapeUrl($block->getViewFileUrl('prototype/windows/themes/default.css')) ?>"/> diff --git a/app/code/Magento/Ups/view/adminhtml/templates/system/shipping/carrier_config.phtml b/app/code/Magento/Ups/view/adminhtml/templates/system/shipping/carrier_config.phtml index 411bec20cde57..9a2703729662a 100644 --- a/app/code/Magento/Ups/view/adminhtml/templates/system/shipping/carrier_config.phtml +++ b/app/code/Magento/Ups/view/adminhtml/templates/system/shipping/carrier_config.phtml @@ -4,8 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var $upsModel \Magento\Ups\Helper\Config */ /** @var $block \Magento\Ups\Block\Backend\System\CarrierConfig */ $upsCarrierConfig = $block->getCarrierConfig(); @@ -87,7 +85,7 @@ require(["prototype"], function(){ this.storedOriginShipment = '<?= /* @noEscape */ $storedOriginShipment ?>'; this.storedFreeShipment = '<?= /* @noEscape */ $storedFreeShipment ?>'; this.storedUpsType = '<?= /* @noEscape */ $storedUpsType ?>'; - <?php /** @var $jsonHelper \Magento\Framework\Json\Helper\Data */ $jsonHelper = $this->helper('Magento\Framework\Json\Helper\Data'); ?> + <?php /** @var $jsonHelper \Magento\Framework\Json\Helper\Data */ $jsonHelper = $this->helper(\Magento\Framework\Json\Helper\Data::class); ?> this.storedAllowedMethods = <?= /* @noEscape */ $jsonHelper->jsonEncode($storedAllowedMethods) ?>; this.originShipmentObj = <?= /* @noEscape */ $jsonHelper->jsonEncode($orShipArr) ?>; this.originShipmentObj['default'] = <?= /* @noEscape */ $jsonHelper->jsonEncode($defShipArr) ?>; diff --git a/app/code/Magento/UrlRewrite/view/adminhtml/templates/categories.phtml b/app/code/Magento/UrlRewrite/view/adminhtml/templates/categories.phtml index 632d9f6f85fd0..bd79bb1d59d98 100644 --- a/app/code/Magento/UrlRewrite/view/adminhtml/templates/categories.phtml +++ b/app/code/Magento/UrlRewrite/view/adminhtml/templates/categories.phtml @@ -4,28 +4,26 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\UrlRewrite\Block\Catalog\Category\Tree $block */ ?> <fieldset class="admin__fieldset" data-ui-id="category-selector"> <legend class="admin__legend"><span><?= $block->escapeHtml(__('Select Category')) ?></span></legend> <div class="content content-category-tree"> <input type="hidden" name="categories" id="product_categories" value=""/> - <?php if ($block->getRoot()): ?> + <?php if ($block->getRoot()) : ?> <div class="jstree-default"></div> <?php endif; ?> </div> </fieldset> -<?php if ($block->getRoot()): ?> +<?php if ($block->getRoot()) : ?> <script type="text/x-magento-init"> { ".jstree-default": { "categoryTree": { - "data": <?php /* @noEscape */ - echo $this->helper('Magento\Framework\Json\Helper\Data')->jsonEncode($block->getTreeArray()); ?>, - "url": "<?php /* @noEscape */ - echo $block->escapeUrl($block->getLoadTreeUrl()); ?>" + "data": <?= /* @noEscape */ + $this->helper(\Magento\Framework\Json\Helper\Data::class)->jsonEncode($block->getTreeArray()); ?>, + "url": "<?= /* @noEscape */ + $block->escapeUrl($block->getLoadTreeUrl()); ?>" } } } diff --git a/app/code/Magento/UrlRewrite/view/adminhtml/templates/edit.phtml b/app/code/Magento/UrlRewrite/view/adminhtml/templates/edit.phtml index 3ff25a7c84521..eb0595033ecba 100644 --- a/app/code/Magento/UrlRewrite/view/adminhtml/templates/edit.phtml +++ b/app/code/Magento/UrlRewrite/view/adminhtml/templates/edit.phtml @@ -4,12 +4,10 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\UrlRewrite\Block\Edit $block */ ?> <?= $block->getChildHtml() ?> -<?php if ($block->getChildBlock('form')): ?> +<?php if ($block->getChildBlock('form')) : ?> <script type="text/x-magento-init"> { "#edit_form": { diff --git a/app/code/Magento/UrlRewrite/view/adminhtml/templates/selector.phtml b/app/code/Magento/UrlRewrite/view/adminhtml/templates/selector.phtml index 1cc0203d8fbfe..8662001673653 100644 --- a/app/code/Magento/UrlRewrite/view/adminhtml/templates/selector.phtml +++ b/app/code/Magento/UrlRewrite/view/adminhtml/templates/selector.phtml @@ -4,8 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\UrlRewrite\Block\Selector $block */ ?> <div class="form-inline"> @@ -16,8 +14,8 @@ </label> <div class="admin__field-control control"> <select data-role="entity-type-selector" class="admin__control-select select" onchange="window.location = this.value;" id="entity-type-selector"> - <?php foreach ($block->getModes() as $mode => $label): ?> - <option <?php /* noEscape */ echo $block->isMode($mode) ? 'selected="selected" ' : '' ?>value="<?= $block->escapeUrl($block->getModeUrl($mode)) ?>"><?= $block->escapeHtml($label) ?></option> + <?php foreach ($block->getModes() as $mode => $label) : ?> + <option <?= /* noEscape */ $block->isMode($mode) ? 'selected="selected" ' : '' ?>value="<?= $block->escapeUrl($block->getModeUrl($mode)) ?>"><?= $block->escapeHtml($label) ?></option> <?php endforeach; ?> </select> </div> diff --git a/app/code/Magento/Vault/view/adminhtml/templates/form/vault.phtml b/app/code/Magento/Vault/view/adminhtml/templates/form/vault.phtml index ddaf678c57691..fb0666cde976f 100644 --- a/app/code/Magento/Vault/view/adminhtml/templates/form/vault.phtml +++ b/app/code/Magento/Vault/view/adminhtml/templates/form/vault.phtml @@ -4,8 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var Magento\Vault\Block\Form $block */ $code = $block->escapeHtml($block->getMethodCode()); ?> diff --git a/app/code/Magento/Vault/view/frontend/templates/cards_list.phtml b/app/code/Magento/Vault/view/frontend/templates/cards_list.phtml index 9fd9e304523c4..d28f7ccb65ca8 100644 --- a/app/code/Magento/Vault/view/frontend/templates/cards_list.phtml +++ b/app/code/Magento/Vault/view/frontend/templates/cards_list.phtml @@ -4,11 +4,10 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile /** @var \Magento\Vault\Block\Customer\CreditCards $block */ $tokens = $block->getPaymentTokens(); ?> -<?php if (count($tokens) !== 0): ?> +<?php if (count($tokens) !== 0) : ?> <div class="table-wrapper my-credit-cards"> <table class="data table table-credit-cards" id="my-orders-table"> <caption class="table-caption"><?= /* @noEscape */ __('Stored Payment Methods') ?></caption> @@ -30,6 +29,6 @@ $tokens = $block->getPaymentTokens(); </table> </div> -<?php elseif (!$block->isExistsCustomerTokens()): ?> +<?php elseif (!$block->isExistsCustomerTokens()) : ?> <div class="message info empty"><span><?= /* @noEscape */ __('You have no stored payment methods.') ?></span></div> <?php endif ?> diff --git a/app/code/Magento/Vault/view/frontend/templates/token_list.phtml b/app/code/Magento/Vault/view/frontend/templates/token_list.phtml index 17d648ebaf25c..84345d82867bf 100644 --- a/app/code/Magento/Vault/view/frontend/templates/token_list.phtml +++ b/app/code/Magento/Vault/view/frontend/templates/token_list.phtml @@ -4,11 +4,10 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile /** @var \Magento\Vault\Block\Customer\AccountTokens $block */ $tokens = $block->getPaymentTokens(); ?> -<?php if (count($tokens) !== 0): ?> +<?php if (count($tokens) !== 0) : ?> <div class="table-wrapper my-credit-cards"> <table class="data table table-credit-cards" id="token-list-table"> <thead> @@ -18,7 +17,7 @@ $tokens = $block->getPaymentTokens(); </tr> </thead> <tbody> - <?php foreach($tokens as $token): ?> + <?php foreach ($tokens as $token) : ?> <?= /* @noEscape */ $block->renderTokenHtml($token) ?> <?php endforeach; ?> </tbody> diff --git a/app/code/Magento/Widget/view/adminhtml/templates/catalog/category/widget/tree.phtml b/app/code/Magento/Widget/view/adminhtml/templates/catalog/category/widget/tree.phtml index b6c19f2906508..72de9550654d3 100644 --- a/app/code/Magento/Widget/view/adminhtml/templates/catalog/category/widget/tree.phtml +++ b/app/code/Magento/Widget/view/adminhtml/templates/catalog/category/widget/tree.phtml @@ -4,8 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Catalog\Block\Adminhtml\Category\Widget\Chooser $block */ ?> @@ -43,7 +41,7 @@ Ext.extend(Ext.tree.TreePanel.Enhanced, Ext.tree.TreePanel, { this.setRootNode(root); if (firstLoad) { - <?php if ($block->getNodeClickListener()): ?> + <?php if ($block->getNodeClickListener()) : ?> this.addListener('click', <?= /* @noEscape */ $block->getNodeClickListener() ?>.createDelegate(this)); <?php endif; ?> } diff --git a/app/code/Magento/Widget/view/adminhtml/templates/instance/edit/layout.phtml b/app/code/Magento/Widget/view/adminhtml/templates/instance/edit/layout.phtml index 3441cf6b5d52a..c45ef65f4f242 100644 --- a/app/code/Magento/Widget/view/adminhtml/templates/instance/edit/layout.phtml +++ b/app/code/Magento/Widget/view/adminhtml/templates/instance/edit/layout.phtml @@ -4,8 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Widget\Block\Adminhtml\Widget\Instance\Edit\Tab\Main\Layout $block */ ?> @@ -34,11 +32,11 @@ var pageGroupTemplate = '<div class="fieldset-wrapper page_group_container" id=" '<label for="widget_instance[<%- data.id %>][page_group]">Display on <span class="required">*</span></label>'+ '<?= $block->getDisplayOnSelectHtml() ?>'+ '<div class="actions">'+ - <?= /* @noEscape */ $this->helper('Magento\Framework\Json\Helper\Data')->jsonEncode($block->getRemoveLayoutButtonHtml()) ?> + + <?= /* @noEscape */ $this->helper(\Magento\Framework\Json\Helper\Data::class)->jsonEncode($block->getRemoveLayoutButtonHtml()) ?> + '</div>'+ '</div>'+ '<div class="fieldset-wrapper-content">'+ -<?php foreach ($block->getDisplayOnContainers() as $container): ?> +<?php foreach ($block->getDisplayOnContainers() as $container) : ?> '<div class="no-display <?= $block->escapeJs($container['code']) ?> group_container" id="<?= $block->escapeJs($container['name']) ?>_<%- data.id %>">'+ '<input disabled="disabled" type="hidden" class="container_name" name="__[container_name]" value="widget_instance[<%- data.id %>][<?= $block->escapeJs($container['name']) ?>]" />'+ '<input disabled="disabled" type="hidden" name="widget_instance[<%- data.id %>][<?= $block->escapeJs($container['name']) ?>][page_id]" value="<%- data.page_id %>" />'+ @@ -481,7 +479,7 @@ var WidgetInstance = { window.WidgetInstance = WidgetInstance; jQuery(function(){ - <?php foreach ($block->getPageGroups() as $pageGroup): ?> + <?php foreach ($block->getPageGroups() as $pageGroup) : ?> WidgetInstance.addPageGroup(<?= /* @noEscape */ $pageGroup ?>); <?php endforeach; ?> Event.observe(document, 'product:changed', function(event){ diff --git a/app/code/Magento/Wishlist/view/adminhtml/templates/customer/edit/tab/wishlist.phtml b/app/code/Magento/Wishlist/view/adminhtml/templates/customer/edit/tab/wishlist.phtml index a2c27193f98da..e6c0608f4b450 100644 --- a/app/code/Magento/Wishlist/view/adminhtml/templates/customer/edit/tab/wishlist.phtml +++ b/app/code/Magento/Wishlist/view/adminhtml/templates/customer/edit/tab/wishlist.phtml @@ -4,8 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Framework\View\Element\Template $block */ ?> <script> diff --git a/app/code/Magento/Wishlist/view/frontend/templates/button/share.phtml b/app/code/Magento/Wishlist/view/frontend/templates/button/share.phtml index fc54a90758780..0ec1febaf2f7f 100644 --- a/app/code/Magento/Wishlist/view/frontend/templates/button/share.phtml +++ b/app/code/Magento/Wishlist/view/frontend/templates/button/share.phtml @@ -4,11 +4,9 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Wishlist\Block\Customer\Wishlist\Button $block */ ?> -<?php if ($block->getWishlist()->getItemsCount() && $block->getWishlist()->getShared() < $block->getConfig()->getSharingEmailLimit()): ?> +<?php if ($block->getWishlist()->getItemsCount() && $block->getWishlist()->getShared() < $block->getConfig()->getSharingEmailLimit()) : ?> <button type="submit" name="save_and_share" title="<?= $block->escapeHtmlAttr(__('Share Wish List')) ?>" class="action share"> <span><?= $block->escapeHtml(__('Share Wish List')) ?></span> </button> diff --git a/app/code/Magento/Wishlist/view/frontend/templates/button/tocart.phtml b/app/code/Magento/Wishlist/view/frontend/templates/button/tocart.phtml index 6f901cac1a633..30d6c85ab64cd 100644 --- a/app/code/Magento/Wishlist/view/frontend/templates/button/tocart.phtml +++ b/app/code/Magento/Wishlist/view/frontend/templates/button/tocart.phtml @@ -4,12 +4,10 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Wishlist\Block\Customer\Wishlist\Button $block */ ?> -<?php if ($block->getWishlist()->getItemsCount() && $block->getWishlist()->isSalable()): ?> +<?php if ($block->getWishlist()->getItemsCount() && $block->getWishlist()->isSalable()) : ?> <button type="button" data-role="all-tocart" title="<?= $block->escapeHtmlAttr(__('Add All to Cart')) ?>" class="action tocart"> <span><?= $block->escapeHtml(__('Add All to Cart')) ?></span> </button> diff --git a/app/code/Magento/Wishlist/view/frontend/templates/button/update.phtml b/app/code/Magento/Wishlist/view/frontend/templates/button/update.phtml index d19a5c2968ff4..6d8e13eeca5fd 100644 --- a/app/code/Magento/Wishlist/view/frontend/templates/button/update.phtml +++ b/app/code/Magento/Wishlist/view/frontend/templates/button/update.phtml @@ -4,12 +4,10 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Wishlist\Block\Customer\Wishlist\Button $block */ ?> -<?php if ($block->getWishlist()->getItemsCount()): ?> +<?php if ($block->getWishlist()->getItemsCount()) : ?> <button type="submit" name="do" title="<?= $block->escapeHtmlAttr(__('Update Wish List')) ?>" class="action update"> <span><?= $block->escapeHtml(__('Update Wish List')) ?></span> </button> diff --git a/app/code/Magento/Wishlist/view/frontend/templates/cart/item/renderer/actions/move_to_wishlist.phtml b/app/code/Magento/Wishlist/view/frontend/templates/cart/item/renderer/actions/move_to_wishlist.phtml index 65225c4710204..99732791e108b 100644 --- a/app/code/Magento/Wishlist/view/frontend/templates/cart/item/renderer/actions/move_to_wishlist.phtml +++ b/app/code/Magento/Wishlist/view/frontend/templates/cart/item/renderer/actions/move_to_wishlist.phtml @@ -4,11 +4,9 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Wishlist\Block\Cart\Item\Renderer\Actions\MoveToWishlist $block */ ?> -<?php if ($block->isAllowInCart() && $block->isProductVisibleInSiteVisibility()): ?> +<?php if ($block->isAllowInCart() && $block->isProductVisibleInSiteVisibility()) : ?> <a href="#" data-post='<?= /* @noEscape */ $block->getMoveFromCartParams() ?>' class="use-ajax action towishlist action-towishlist"> diff --git a/app/code/Magento/Wishlist/view/frontend/templates/catalog/product/list/addto/wishlist.phtml b/app/code/Magento/Wishlist/view/frontend/templates/catalog/product/list/addto/wishlist.phtml index b09118e0483af..2427f883c2b53 100644 --- a/app/code/Magento/Wishlist/view/frontend/templates/catalog/product/list/addto/wishlist.phtml +++ b/app/code/Magento/Wishlist/view/frontend/templates/catalog/product/list/addto/wishlist.phtml @@ -4,11 +4,9 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var Magento\Wishlist\Block\Catalog\Product\ProductList\Item\AddTo\Wishlist $block */ ?> -<?php if ($block->getWishlistHelper()->isAllow()): ?> +<?php if ($block->getWishlistHelper()->isAllow()) : ?> <a href="#" class="action towishlist" title="<?= $block->escapeHtmlAttr(__('Add to Wish List')) ?>" diff --git a/app/code/Magento/Wishlist/view/frontend/templates/catalog/product/view/addto/wishlist.phtml b/app/code/Magento/Wishlist/view/frontend/templates/catalog/product/view/addto/wishlist.phtml index 1959694776ebc..a0c680ea24e32 100644 --- a/app/code/Magento/Wishlist/view/frontend/templates/catalog/product/view/addto/wishlist.phtml +++ b/app/code/Magento/Wishlist/view/frontend/templates/catalog/product/view/addto/wishlist.phtml @@ -4,8 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Wishlist\Block\Catalog\Product\View\AddTo\Wishlist $block */ ?> <?php if ($block->isWishListAllowed()) : ?> diff --git a/app/code/Magento/Wishlist/view/frontend/templates/email/items.phtml b/app/code/Magento/Wishlist/view/frontend/templates/email/items.phtml index 0bc333ad6f561..449d4c43c5aa0 100644 --- a/app/code/Magento/Wishlist/view/frontend/templates/email/items.phtml +++ b/app/code/Magento/Wishlist/view/frontend/templates/email/items.phtml @@ -4,8 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /* @var \Magento\Wishlist\Block\Share\Email\Items $block */ ?> <?php $l = $block->getWishlistItemsCount() ?> @@ -13,45 +11,45 @@ <table> <tr> <?php $i = 0; - foreach ($block->getWishlistItems() as $item): $i++ ?> - <?php /* @var $item \Magento\Wishlist\Model\Item */ ?> - <?php /* @var $_product \Magento\Catalog\Model\Product */ ?> - <?php $_product = $item->getProduct(); ?> - <td class="col product"> - <p> - <a href="<?= $block->escapeUrl($block->getProductUrl($_product)) ?>"> - <?= /* @noEscape */ $block->getImage($_product, 'product_small_image')->toHtml() ?> - </a> - </p> + foreach ($block->getWishlistItems() as $item) : $i++ ?> + <?php /* @var $item \Magento\Wishlist\Model\Item */ ?> + <?php /* @var $_product \Magento\Catalog\Model\Product */ ?> + <?php $_product = $item->getProduct(); ?> + <td class="col product"> + <p> + <a href="<?= $block->escapeUrl($block->getProductUrl($_product)) ?>"> + <?= /* @noEscape */ $block->getImage($_product, 'product_small_image')->toHtml() ?> + </a> + </p> - <p> - <a href="<?= $block->escapeUrl($block->getProductUrl($_product)) ?>"> - <strong><?= $block->escapeHtml($_product->getName()) ?></strong> - </a> - </p> - <?php if ($block->hasDescription($item)): ?> <p> - <strong><?= $block->escapeHtml(__('Comment')) ?>:</strong> - <br/><?= /* @noEscape */ $block->getEscapedDescription($item) ?> + <a href="<?= $block->escapeUrl($block->getProductUrl($_product)) ?>"> + <strong><?= $block->escapeHtml($_product->getName()) ?></strong> + </a> </p> - <?php endif; ?> - <p> - <a href="<?= $block->escapeUrl($block->getProductUrl($_product)) ?>"> - <?= $block->escapeHtml(__('View Product')) ?> - </a> - </p> - </td> - <?php if ($i % 3 != 0): ?> - <td></td> - <?php else: ?> - </tr> - <tr> - <td colspan="5"> </td> - </tr> - <?php if ($i < $l): ?> + <?php if ($block->hasDescription($item)) : ?> + <p> + <strong><?= $block->escapeHtml(__('Comment')) ?>:</strong> + <br/><?= /* @noEscape */ $block->getEscapedDescription($item) ?> + </p> + <?php endif; ?> + <p> + <a href="<?= $block->escapeUrl($block->getProductUrl($_product)) ?>"> + <?= $block->escapeHtml(__('View Product')) ?> + </a> + </p> + </td> + <?php if ($i % 3 != 0) : ?> + <td></td> + <?php else : ?> + </tr> <tr> - <?php endif ?> - <?php endif ?> + <td colspan="5"> </td> + </tr> + <?php if ($i < $l) : ?> + <tr> + <?php endif ?> + <?php endif ?> <?php endforeach ?> </table> </div> diff --git a/app/code/Magento/Wishlist/view/frontend/templates/item/column/actions.phtml b/app/code/Magento/Wishlist/view/frontend/templates/item/column/actions.phtml index 0b50df8c59fbb..ce6ac6f2b2641 100644 --- a/app/code/Magento/Wishlist/view/frontend/templates/item/column/actions.phtml +++ b/app/code/Magento/Wishlist/view/frontend/templates/item/column/actions.phtml @@ -4,14 +4,12 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Wishlist\Block\Customer\Wishlist\Item\Column\Actions $block */ ?> <?php $children = $block->getChildNames(); ?> -<?php if ($children): ?> +<?php if ($children) : ?> <div class="<?= $block->escapeHtmlAttr($block->getCssClass()) ?>"> - <?php foreach ($children as $childName):?> + <?php foreach ($children as $childName) : ?> <?= /* @noEscape */ $block->getLayout()->renderElement($childName, false) ?> <?php endforeach;?> </div> diff --git a/app/code/Magento/Wishlist/view/frontend/templates/item/column/cart.phtml b/app/code/Magento/Wishlist/view/frontend/templates/item/column/cart.phtml index f296b950f3abb..294cd7f0ab775 100644 --- a/app/code/Magento/Wishlist/view/frontend/templates/item/column/cart.phtml +++ b/app/code/Magento/Wishlist/view/frontend/templates/item/column/cart.phtml @@ -4,8 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Wishlist\Block\Customer\Wishlist\Item\Column\Cart $block */ /** @var \Magento\Wishlist\Model\Item $item */ @@ -15,12 +13,12 @@ $product = $item->getProduct(); $viewModel = $block->getData('allowedQuantityViewModel'); $allowedQty = $viewModel->setItem($item)->getMinMaxQty(); ?> -<?php foreach ($block->getChildNames() as $childName): ?> +<?php foreach ($block->getChildNames() as $childName) : ?> <?= /* @noEscape */ $block->getLayout()->renderElement($childName, false) ?> <?php endforeach;?> <div class="box-tocart"> <fieldset class="fieldset"> - <?php if ($item->canHaveQty() && $product->isVisibleInSiteVisibility()): ?> + <?php if ($item->canHaveQty() && $product->isVisibleInSiteVisibility()) : ?> <div class="field qty"> <label class="label" for="qty[<?= $block->escapeHtmlAttr($item->getId()) ?>]"><span><?= $block->escapeHtml(__('Qty')) ?></span></label> <div class="control"> @@ -29,7 +27,7 @@ $allowedQty = $viewModel->setItem($item)->getMinMaxQty(); </div> </div> <?php endif; ?> - <?php if ($product->isSaleable()): ?> + <?php if ($product->isSaleable()) : ?> <div class="product-item-actions"> <div class="actions-primary"> <button type="button" data-role="tocart" data-post='<?= /* @noEscape */ $block->getItemAddToCartParams($item) ?>' title="<?= $block->escapeHtmlAttr(__('Add to Cart')) ?>" data-item-id="<?= $block->escapeHtmlAttr($item->getId()) ?>" class="action tocart primary"> @@ -37,12 +35,12 @@ $allowedQty = $viewModel->setItem($item)->getMinMaxQty(); </button> </div> </div> - <?php else: ?> - <?php if ($product->getIsSalable()): ?> + <?php else : ?> + <?php if ($product->getIsSalable()) : ?> <p class="available stock" title="<?= $block->escapeHtmlAttr(__('Availability')) ?>"> <span><?= $block->escapeHtml(__('In stock')) ?></span> </p> - <?php else: ?> + <?php else : ?> <p class="unavailable stock" title="<?= $block->escapeHtmlAttr(__('Availability')) ?>"> <span><?= $block->escapeHtml(__('Out of stock')) ?></span> </p> diff --git a/app/code/Magento/Wishlist/view/frontend/templates/item/column/comment.phtml b/app/code/Magento/Wishlist/view/frontend/templates/item/column/comment.phtml index 5ab5bc5422e7e..0f1c696088bca 100644 --- a/app/code/Magento/Wishlist/view/frontend/templates/item/column/comment.phtml +++ b/app/code/Magento/Wishlist/view/frontend/templates/item/column/comment.phtml @@ -4,8 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /* @var \Magento\Wishlist\Block\Customer\Wishlist\Item\Column\Comment $block */ /* @var \Magento\Wishlist\Model\Item $item */ @@ -17,6 +15,6 @@ $item = $block->getItem(); <span><?= $block->escapeHtml(__('Comment')) ?></span> </label> <div class="control"> - <textarea id="product-item-comment-<?= $block->escapeHtmlAttr($item->getWishlistItemId()) ?>" placeholder="<?= /* @noEscape */ $this->helper('Magento\Wishlist\Helper\Data')->defaultCommentString() ?>" name="description[<?= $block->escapeHtmlAttr($item->getWishlistItemId()) ?>]" title="<?= $block->escapeHtmlAttr(__('Comment')) ?>" class="product-item-comment" <?= $item->getProduct()->isSaleable() ? '' : 'disabled="disabled"' ?>><?= ($block->escapeHtml($item->getDescription())) ?></textarea> + <textarea id="product-item-comment-<?= $block->escapeHtmlAttr($item->getWishlistItemId()) ?>" placeholder="<?= /* @noEscape */ $this->helper(\Magento\Wishlist\Helper\Data::class)->defaultCommentString() ?>" name="description[<?= $block->escapeHtmlAttr($item->getWishlistItemId()) ?>]" title="<?= $block->escapeHtmlAttr(__('Comment')) ?>" class="product-item-comment" <?= $item->getProduct()->isSaleable() ? '' : 'disabled="disabled"' ?>><?= ($block->escapeHtml($item->getDescription())) ?></textarea> </div> </div> diff --git a/app/code/Magento/Wishlist/view/frontend/templates/item/column/edit.phtml b/app/code/Magento/Wishlist/view/frontend/templates/item/column/edit.phtml index 1898ef6fc0d66..a6fa5d4fccdcf 100644 --- a/app/code/Magento/Wishlist/view/frontend/templates/item/column/edit.phtml +++ b/app/code/Magento/Wishlist/view/frontend/templates/item/column/edit.phtml @@ -4,8 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Wishlist\Block\Customer\Wishlist\Item\Column\Edit $block */ /** @var \Magento\Wishlist\Model\Item $item */ @@ -13,7 +11,7 @@ $item = $block->getItem(); $product = $item->getProduct(); ?> -<?php if ($product->isVisibleInSiteVisibility()): ?> +<?php if ($product->isVisibleInSiteVisibility()) : ?> <a class="action edit" href="<?= $block->escapeUrl($block->getItemConfigureUrl($item)) ?>"> <span><?= $block->escapeHtml(__('Edit')) ?></span> </a> diff --git a/app/code/Magento/Wishlist/view/frontend/templates/item/column/image.phtml b/app/code/Magento/Wishlist/view/frontend/templates/item/column/image.phtml index 2eb4664991e99..0053c1d214892 100644 --- a/app/code/Magento/Wishlist/view/frontend/templates/item/column/image.phtml +++ b/app/code/Magento/Wishlist/view/frontend/templates/item/column/image.phtml @@ -4,8 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Wishlist\Block\Customer\Wishlist\Item\Column\Image $block */ /** @var \Magento\Wishlist\Model\Item $item */ diff --git a/app/code/Magento/Wishlist/view/frontend/templates/item/column/name.phtml b/app/code/Magento/Wishlist/view/frontend/templates/item/column/name.phtml index 265f4635a6be3..2626e7745d56b 100644 --- a/app/code/Magento/Wishlist/view/frontend/templates/item/column/name.phtml +++ b/app/code/Magento/Wishlist/view/frontend/templates/item/column/name.phtml @@ -4,8 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Wishlist\Block\Customer\Wishlist\Item\Column\Info $block */ /** @var \Magento\Wishlist\Model\Item $item */ diff --git a/app/code/Magento/Wishlist/view/frontend/templates/item/column/price.phtml b/app/code/Magento/Wishlist/view/frontend/templates/item/column/price.phtml index 34770f8fe12de..c602707f102a8 100644 --- a/app/code/Magento/Wishlist/view/frontend/templates/item/column/price.phtml +++ b/app/code/Magento/Wishlist/view/frontend/templates/item/column/price.phtml @@ -4,11 +4,9 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Wishlist\Block\Customer\Wishlist\Item\Column\Cart $block */ ?> -<?php foreach ($block->getChildNames() as $childName): ?> +<?php foreach ($block->getChildNames() as $childName) : ?> <?= /* @noEscape */ $block->getLayout()->renderElement($childName, false) ?> <?php endforeach;?> diff --git a/app/code/Magento/Wishlist/view/frontend/templates/item/column/remove.phtml b/app/code/Magento/Wishlist/view/frontend/templates/item/column/remove.phtml index 57ae439d9995b..938b62931171d 100644 --- a/app/code/Magento/Wishlist/view/frontend/templates/item/column/remove.phtml +++ b/app/code/Magento/Wishlist/view/frontend/templates/item/column/remove.phtml @@ -4,8 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /* @var \Magento\Wishlist\Block\Customer\Wishlist\Item\Column\Remove $block */ ?> diff --git a/app/code/Magento/Wishlist/view/frontend/templates/item/configure/addto.phtml b/app/code/Magento/Wishlist/view/frontend/templates/item/configure/addto.phtml index a60a68e99f34e..3b2e742af8ba0 100644 --- a/app/code/Magento/Wishlist/view/frontend/templates/item/configure/addto.phtml +++ b/app/code/Magento/Wishlist/view/frontend/templates/item/configure/addto.phtml @@ -4,19 +4,17 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Wishlist\Block\Item\configure $block */ ?> <div class="product-addto-links" data-role="add-to-links"> - <?php if ($this->helper('Magento\Wishlist\Helper\Data')->isAllow()) : ?> + <?php if ($this->helper(\Magento\Wishlist\Helper\Data::class)->isAllow()) : ?> <a href="#" data-post='<?= /* @noEscape */ $block->getUpdateParams() ?>' class="action towishlist updated" data-action="add-to-wishlist"> <span><?= $block->escapeHtml(__('Update Wish List')) ?></span> </a> <?php endif; ?> <?php $_product = $block->getProduct(); ?> - <?php $_compareUrl = $this->helper('Magento\Catalog\Helper\Product\Compare')->getAddUrl($_product); ?> + <?php $_compareUrl = $this->helper(\Magento\Catalog\Helper\Product\Compare::class)->getAddUrl($_product); ?> <?php if ($_compareUrl) : ?> <a href="<?= $block->escapeUrl($_compareUrl) ?>" class="action tocompare"> <span><?= $block->escapeHtml(__('Add to Compare')) ?></span> @@ -26,7 +24,7 @@ <script type="text/x-magento-init"> { "body": { - "addToWishlist": <?= /* @noEscape */ $this->helper('Magento\Framework\Json\Helper\Data')->jsonEncode($block->getWishlistOptions()) ?> + "addToWishlist": <?= /* @noEscape */ $this->helper(\Magento\Framework\Json\Helper\Data::class)->jsonEncode($block->getWishlistOptions()) ?> } } </script> diff --git a/app/code/Magento/Wishlist/view/frontend/templates/item/configure/addto/wishlist.phtml b/app/code/Magento/Wishlist/view/frontend/templates/item/configure/addto/wishlist.phtml index 5b1d39681d948..05d4eaaa251b8 100644 --- a/app/code/Magento/Wishlist/view/frontend/templates/item/configure/addto/wishlist.phtml +++ b/app/code/Magento/Wishlist/view/frontend/templates/item/configure/addto/wishlist.phtml @@ -4,11 +4,9 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Wishlist\Block\Item\Configure $block */ ?> -<?php if ($this->helper('Magento\Wishlist\Helper\Data')->isAllow()) : ?> +<?php if ($this->helper(\Magento\Wishlist\Helper\Data::class)->isAllow()) : ?> <a href="#" data-post='<?= /* @noEscape */ $block->getUpdateParams() ?>' class="action towishlist updated" data-action="add-to-wishlist"> <span><?= $block->escapeHtml(__('Update Wish List')) ?></span> </a> @@ -16,7 +14,7 @@ <script type="text/x-magento-init"> { "body": { - "addToWishlist": <?= /* @noEscape */ $this->helper('Magento\Framework\Json\Helper\Data')->jsonEncode($block->getWishlistOptions()) ?> + "addToWishlist": <?= /* @noEscape */ $this->helper(\Magento\Framework\Json\Helper\Data::class)->jsonEncode($block->getWishlistOptions()) ?> } } </script> diff --git a/app/code/Magento/Wishlist/view/frontend/templates/item/list.phtml b/app/code/Magento/Wishlist/view/frontend/templates/item/list.phtml index ef02768c46a83..f11c9ac9a5cef 100644 --- a/app/code/Magento/Wishlist/view/frontend/templates/item/list.phtml +++ b/app/code/Magento/Wishlist/view/frontend/templates/item/list.phtml @@ -3,9 +3,6 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ - -// @codingStandardsIgnoreFile - ?> <?php /** @var \Magento\Wishlist\Block\Customer\Wishlist\Items $block */ @@ -13,25 +10,25 @@ $columns = $block->getColumns(); ?> <div class="products-grid wishlist"> - <?php if (count($block->getItems())): ?> + <?php if (count($block->getItems())) : ?> <ol class="product-items"> - <?php foreach ($block->getItems() as $item): ?> + <?php foreach ($block->getItems() as $item) : ?> <li data-row="product-item" class="product-item" id="item_<?= $block->escapeHtmlAttr($item->getId()) ?>"> <div class="product-item-info" data-container="product-grid"> - <?php foreach ($columns as $column): ?> + <?php foreach ($columns as $column) : ?> <?= $column->setItem($item)->toHtml();?> <?php endforeach; ?> </div> </li> <?php endforeach; ?> </ol> - <?php else: ?> + <?php else : ?> <div class="message info empty"> <span><?= $block->escapeHtml(__('This Wish List has no Items')) ?></span> </div> <?php endif; ?> </div> -<?php foreach ($columns as $column): ?> +<?php foreach ($columns as $column) : ?> <?= $column->getAdditionalHtml() ?> <?php endforeach; ?> diff --git a/app/code/Magento/Wishlist/view/frontend/templates/js/components.phtml b/app/code/Magento/Wishlist/view/frontend/templates/js/components.phtml index bad5acc209b5f..5902a9f25cc4b 100644 --- a/app/code/Magento/Wishlist/view/frontend/templates/js/components.phtml +++ b/app/code/Magento/Wishlist/view/frontend/templates/js/components.phtml @@ -3,8 +3,5 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ - -// @codingStandardsIgnoreFile - ?> <?= $block->getChildHtml() ?> diff --git a/app/code/Magento/Wishlist/view/frontend/templates/link.phtml b/app/code/Magento/Wishlist/view/frontend/templates/link.phtml index 7f77dd0195a3b..e3ef3cf4f009b 100644 --- a/app/code/Magento/Wishlist/view/frontend/templates/link.phtml +++ b/app/code/Magento/Wishlist/view/frontend/templates/link.phtml @@ -4,8 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /* @var \Magento\Wishlist\Block\Link $block */ ?> <li class="link wishlist" data-bind="scope: 'wishlist'"> diff --git a/app/code/Magento/Wishlist/view/frontend/templates/messages/addProductSuccessMessage.phtml b/app/code/Magento/Wishlist/view/frontend/templates/messages/addProductSuccessMessage.phtml index 342af0a474492..5abb0dd8e0144 100644 --- a/app/code/Magento/Wishlist/view/frontend/templates/messages/addProductSuccessMessage.phtml +++ b/app/code/Magento/Wishlist/view/frontend/templates/messages/addProductSuccessMessage.phtml @@ -3,7 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile + /** @var \Magento\Framework\View\Element\Template $block */ ?> diff --git a/app/code/Magento/Wishlist/view/frontend/templates/messages/removeWishlistItemSuccessMessage.phtml b/app/code/Magento/Wishlist/view/frontend/templates/messages/removeWishlistItemSuccessMessage.phtml index 1196b8fec4a21..0f222598b536d 100644 --- a/app/code/Magento/Wishlist/view/frontend/templates/messages/removeWishlistItemSuccessMessage.phtml +++ b/app/code/Magento/Wishlist/view/frontend/templates/messages/removeWishlistItemSuccessMessage.phtml @@ -3,7 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile + /** @var \Magento\Framework\View\Element\Template $block */ ?> diff --git a/app/code/Magento/Wishlist/view/frontend/templates/options_list.phtml b/app/code/Magento/Wishlist/view/frontend/templates/options_list.phtml index 9f7670e34f800..9e9cf1b64adc5 100644 --- a/app/code/Magento/Wishlist/view/frontend/templates/options_list.phtml +++ b/app/code/Magento/Wishlist/view/frontend/templates/options_list.phtml @@ -4,29 +4,27 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /* @var \Magento\Wishlist\Block\Customer\Wishlist\Item\Options $block */ ?> <?php $options = $block->getOptionList(); ?> -<?php if ($options): ?> +<?php if ($options) : ?> <div class="tooltip wrapper product-item-tooltip"> - <span class="action details tooltip toggle"><?= $block->escapeHtml(__('See Details')) ?></span> - <div class="tooltip content"> - <strong class="subtitle"><?= $block->escapeHtml(__('Options Details')) ?></strong> - <dl> - <?php foreach ($options as $option): ?> - <dt class="label"><?= $block->escapeHtml($option['label']) ?></dt> - <dd class="values"> - <?php if (is_array($option['value'])): ?> - <?= /* @noEscape */ nl2br(implode("\n", $option['value'])) ?> - <?php else: ?> - <?= /* @noEscape */ $option['value'] ?> - <?php endif; ?> - </dd> - <?php endforeach; ?> - </dl> - </div> + <span class="action details tooltip toggle"><?= $block->escapeHtml(__('See Details')) ?></span> + <div class="tooltip content"> + <strong class="subtitle"><?= $block->escapeHtml(__('Options Details')) ?></strong> + <dl> + <?php foreach ($options as $option) : ?> + <dt class="label"><?= $block->escapeHtml($option['label']) ?></dt> + <dd class="values"> + <?php if (is_array($option['value'])) : ?> + <?= /* @noEscape */ nl2br(implode("\n", $option['value'])) ?> + <?php else : ?> + <?= /* @noEscape */ $option['value'] ?> + <?php endif; ?> + </dd> + <?php endforeach; ?> + </dl> + </div> </div> <?php endif ?> diff --git a/app/code/Magento/Wishlist/view/frontend/templates/rss/email.phtml b/app/code/Magento/Wishlist/view/frontend/templates/rss/email.phtml index 7794b9027e952..4a97173fde318 100644 --- a/app/code/Magento/Wishlist/view/frontend/templates/rss/email.phtml +++ b/app/code/Magento/Wishlist/view/frontend/templates/rss/email.phtml @@ -4,13 +4,11 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /* @var \Magento\Wishlist\Block\Rss\EmailLink $block */ ?> -<?php if ($block->getLink()): ?> +<?php if ($block->getLink()) : ?> <p style="font-size:12px; line-height:16px; margin:0 0 16px;"> - <?= $block->escapeHtml(__("RSS link to %1's wishlist", $this->helper('Magento\Wishlist\Helper\Data')->getCustomerName())) ?> + <?= $block->escapeHtml(__("RSS link to %1's wishlist", $this->helper(\Magento\Wishlist\Helper\Data::class)->getCustomerName())) ?> <br /> <a href="<?= $block->escapeUrl($block->getLink()) ?>"><?= $block->escapeUrl($block->getLink()) ?></a> </p> diff --git a/app/code/Magento/Wishlist/view/frontend/templates/rss/wishlist.phtml b/app/code/Magento/Wishlist/view/frontend/templates/rss/wishlist.phtml index 04e7903b53bbf..d9cca05d667be 100644 --- a/app/code/Magento/Wishlist/view/frontend/templates/rss/wishlist.phtml +++ b/app/code/Magento/Wishlist/view/frontend/templates/rss/wishlist.phtml @@ -4,11 +4,9 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Wishlist\Block\Rss\Link $block */ ?> -<?php if ($block->isRssAllowed() && $block->getLink() && $this->helper('Magento\Wishlist\Helper\Data')->getWishlist()->getItemsCount()): ?> +<?php if ($block->isRssAllowed() && $block->getLink() && $this->helper(\Magento\Wishlist\Helper\Data::class)->getWishlist()->getItemsCount()) : ?> <a href="<?= $block->escapeUrl($block->getLink()) ?>" class="action rss wishlist"> <span><?= $block->escapeHtml(__('RSS Feed')) ?></span> </a> diff --git a/app/code/Magento/Wishlist/view/frontend/templates/shared.phtml b/app/code/Magento/Wishlist/view/frontend/templates/shared.phtml index e34c431d00475..0fcaa6c853ff0 100644 --- a/app/code/Magento/Wishlist/view/frontend/templates/shared.phtml +++ b/app/code/Magento/Wishlist/view/frontend/templates/shared.phtml @@ -4,12 +4,10 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Wishlist\Block\Share\Wishlist $block */ ?> -<?php if ($block->hasWishlistItems()): ?> +<?php if ($block->hasWishlistItems()) : ?> <form class="form shared wishlist" action="<?= $block->escapeUrl($block->getUrl('wishlist/index/update')) ?>" method="post"> <div class="wishlist table-wrapper"> <table class="table data wishlist" id="wishlist-table"> @@ -22,7 +20,7 @@ </tr> </thead> <tbody> - <?php foreach ($block->getWishlistItems() as $item): ?> + <?php foreach ($block->getWishlistItems() as $item) : ?> <?php $product = $item->getProduct(); $isVisibleProduct = $product->isVisibleInSiteVisibility(); @@ -37,8 +35,8 @@ <?= $block->escapeHtml($product->getName()) ?> </a> </strong> - <?php - echo $block->getProductPriceHtml( + <?= + $block->getProductPriceHtml( $product, 'wishlist_configured_price', \Magento\Framework\Pricing\Render::ZONE_ITEM_LIST, @@ -49,8 +47,8 @@ </td> <td data-th="<?= $block->escapeHtmlAttr(__('Comment')) ?>" class="col comment"><?= /* @noEscape */ $block->getEscapedDescription($item) ?></td> <td data-th="<?= $block->escapeHtmlAttr(__('Add to Cart')) ?>" class="col actions" data-role="add-to-links"> - <?php if ($product->isSaleable()): ?> - <?php if ($isVisibleProduct): ?> + <?php if ($product->isSaleable()) : ?> + <?php if ($isVisibleProduct) : ?> <button type="button" title="<?= $block->escapeHtmlAttr(__('Add to Cart')) ?>" data-post='<?= /* @noEscape */ $block->getSharedItemAddToCartUrl($item) ?>' @@ -70,7 +68,7 @@ </div> <div class="actions-toolbar"> - <?php if ($block->isSaleable()):?> + <?php if ($block->isSaleable()) : ?> <div class="primary"> <button type="button" title="<?= $block->escapeHtmlAttr(__('Add All to Cart')) ?>" @@ -87,6 +85,6 @@ </div> </div> </form> -<?php else: ?> +<?php else : ?> <div class="message info empty"><div><?= $block->escapeHtml(__('Wish List is empty now.')) ?></div></div> <?php endif ?> diff --git a/app/code/Magento/Wishlist/view/frontend/templates/sharing.phtml b/app/code/Magento/Wishlist/view/frontend/templates/sharing.phtml index ff01cb4532cc7..6591b480e73d4 100644 --- a/app/code/Magento/Wishlist/view/frontend/templates/sharing.phtml +++ b/app/code/Magento/Wishlist/view/frontend/templates/sharing.phtml @@ -4,8 +4,6 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Wishlist\Block\Customer\Sharing $block */ ?> <form class="form wishlist share" @@ -29,7 +27,7 @@ <textarea id="message" name="message" cols="60" rows="5"><?= /* @noEscape */ $block->getEnteredData('message') ?></textarea> </div> </div> - <?php if ($this->helper('Magento\Wishlist\Helper\Rss')->isRssAllow()): ?> + <?php if ($this->helper(\Magento\Wishlist\Helper\Rss::class)->isRssAllow()) : ?> <div class="field choice rss"> <input type="checkbox" name="rss_url" id="rss_url" value="1" title="<?= $block->escapeHtmlAttr(__('Check here to link an RSS feed to your Wish List.')) ?>" class="checkbox"> <label class="label" for="rss_url"> diff --git a/app/code/Magento/Wishlist/view/frontend/templates/sidebar.phtml b/app/code/Magento/Wishlist/view/frontend/templates/sidebar.phtml index 84b607adb6362..6e678a8916372 100644 --- a/app/code/Magento/Wishlist/view/frontend/templates/sidebar.phtml +++ b/app/code/Magento/Wishlist/view/frontend/templates/sidebar.phtml @@ -4,12 +4,10 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Wishlist\Block\Customer\Sidebar $block */ ?> <?php -$wishlistHelper = $this->helper('Magento\Wishlist\Helper\Data'); +$wishlistHelper = $this->helper(\Magento\Wishlist\Helper\Data::class); ?> <?php if ($wishlistHelper->isAllow()) : ?> <div class="block block-wishlist" data-bind="scope: 'wishlist'"> @@ -61,7 +59,7 @@ $wishlistHelper = $this->helper('Magento\Wishlist\Helper\Data'); <div class="actions-toolbar no-display" data-bind="css: {'no-display': null}"> <div class="primary"> <a class="action details" - href="<?= $block->escapeUrl($this->helper('Magento\Wishlist\Helper\Data')->getListUrl()) ?>" + href="<?= $block->escapeUrl($this->helper(\Magento\Wishlist\Helper\Data::class)->getListUrl()) ?>" title="<?= $block->escapeHtmlAttr(__('Go to Wish List')) ?>"><span><?= $block->escapeHtml(__('Go to Wish List')) ?></span></a> </div> </div> diff --git a/app/code/Magento/Wishlist/view/frontend/templates/view.phtml b/app/code/Magento/Wishlist/view/frontend/templates/view.phtml index 4f4a1d302c150..81bb5bd195091 100644 --- a/app/code/Magento/Wishlist/view/frontend/templates/view.phtml +++ b/app/code/Magento/Wishlist/view/frontend/templates/view.phtml @@ -4,12 +4,10 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - /** @var \Magento\Wishlist\Block\Customer\Wishlist $block */ ?> -<?php if ($this->helper('Magento\Wishlist\Helper\Data')->isAllow()) : ?> +<?php if ($this->helper(\Magento\Wishlist\Helper\Data::class)->isAllow()) : ?> <div class="toolbar wishlist-toolbar"><?= $block->getChildHtml('wishlist_item_pager'); ?></div> <?= ($block->getChildHtml('wishlist.rss.link')) ?> <form class="form-wishlist-items" id="wishlist-view-form" @@ -19,11 +17,11 @@ "commentString":""}, "validation": {}}' action="<?= $block->escapeUrl($block->getUrl('wishlist/index/update', ['wishlist_id' => $block->getWishlistInstance()->getId()])) ?>" method="post"> <?= $block->getChildHtml('top') ?> - <?php if ($block->hasWishlistItems()): ?> + <?php if ($block->hasWishlistItems()) : ?> <?= $block->getBlockHtml('formkey') ?> <?php $block->getChildBlock('items')->setItems($block->getWishlistItems()); ?> <?= $block->getChildHtml('items') ?> - <?php else: ?> + <?php else : ?> <div class="message info empty"><span><?= $block->escapeHtml(__('You have no items in your wish list.')) ?></span></div> <?php endif ?> <?= $block->getChildHtml('bottom') ?> From 2f792144542dff772357e9bc974b47b901fcb7b2 Mon Sep 17 00:00:00 2001 From: "rostyslav.hymon" <rostyslav.hymon@transoftgroup.com> Date: Wed, 3 Jul 2019 12:49:47 +0300 Subject: [PATCH 610/773] MC-17919: In stock products are showing as out of stock after they are enabled via a Scheduled Update --- .../Indexer/Stock/DefaultStock.php | 7 -- .../Model/Indexer/Stock/Action/FullTest.php | 71 +++++++++++++++---- 2 files changed, 59 insertions(+), 19 deletions(-) diff --git a/app/code/Magento/CatalogInventory/Model/ResourceModel/Indexer/Stock/DefaultStock.php b/app/code/Magento/CatalogInventory/Model/ResourceModel/Indexer/Stock/DefaultStock.php index f1da5c3df22bc..079704422aa89 100644 --- a/app/code/Magento/CatalogInventory/Model/ResourceModel/Indexer/Stock/DefaultStock.php +++ b/app/code/Magento/CatalogInventory/Model/ResourceModel/Indexer/Stock/DefaultStock.php @@ -230,8 +230,6 @@ protected function _getStockStatusSelect($entityIds = null, $usePrimaryTable = f { $connection = $this->getConnection(); $qtyExpr = $connection->getCheckSql('cisi.qty > 0', 'cisi.qty', 0); - $metadata = $this->getMetadataPool()->getMetadata(\Magento\Catalog\Api\Data\ProductInterface::class); - $linkField = $metadata->getLinkField(); $select = $connection->select()->from( ['e' => $this->getTable('catalog_product_entity')], @@ -245,11 +243,6 @@ protected function _getStockStatusSelect($entityIds = null, $usePrimaryTable = f ['cisi' => $this->getTable('cataloginventory_stock_item')], 'cisi.stock_id = cis.stock_id AND cisi.product_id = e.entity_id', [] - )->joinInner( - ['mcpei' => $this->getTable('catalog_product_entity_int')], - 'e.' . $linkField . ' = mcpei.' . $linkField - . ' AND mcpei.attribute_id = ' . $this->_getAttribute('status')->getId(), - [] )->columns( ['qty' => $qtyExpr] )->where( diff --git a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/Indexer/Stock/Action/FullTest.php b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/Indexer/Stock/Action/FullTest.php index 6bf1f5fbf0be2..00c13619ff2c1 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/Indexer/Stock/Action/FullTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/Indexer/Stock/Action/FullTest.php @@ -5,24 +5,42 @@ */ namespace Magento\CatalogInventory\Model\Indexer\Stock\Action; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\Framework\ObjectManagerInterface; +use Magento\CatalogInventory\Model\Indexer\Stock\Processor; +use Magento\Catalog\Model\CategoryFactory; +use Magento\Catalog\Block\Product\ListProduct; +use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory; +use Magento\Catalog\Model\Product; +use PHPUnit\Framework\TestCase; + /** * Full reindex Test */ -class FullTest extends \PHPUnit\Framework\TestCase +class FullTest extends TestCase { /** - * @var \Magento\CatalogInventory\Model\Indexer\Stock\Processor + * @var ObjectManagerInterface + */ + private $objectManager; + + /** + * @var Processor */ protected $_processor; + /** + * @inheritdoc + */ protected function setUp() { - $this->_processor = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get( - \Magento\CatalogInventory\Model\Indexer\Stock\Processor::class - ); + $this->objectManager = Bootstrap::getObjectManager(); + $this->_processor = $this->objectManager->get(Processor::class); } /** + * Reindex all + * * @magentoDbIsolation disabled * @magentoAppIsolation enabled * @magentoDataFixture Magento/Catalog/_files/product_simple.php @@ -31,13 +49,9 @@ public function testReindexAll() { $this->_processor->reindexAll(); - $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 - ); + $categoryFactory = $this->objectManager->get(CategoryFactory::class); + /** @var ListProduct $listProduct */ + $listProduct = $this->objectManager->get(ListProduct::class); $category = $categoryFactory->create()->load(2); $layer = $listProduct->getLayer(); @@ -61,4 +75,37 @@ public function testReindexAll() $this->assertEquals(100, $product->getQty()); } } + + /** + * Reindex with disabled product + * + * @return void + * @magentoDbIsolation disabled + * @magentoAppIsolation enabled + * @magentoDataFixture Magento/Catalog/_files/products_with_layered_navigation_attribute.php + */ + public function testReindexAllWithDisabledProduct(): void + { + $productCollectionFactory = $this->objectManager->get(CollectionFactory::class); + $productCollection = $productCollectionFactory + ->create() + ->addAttributeToSelect('*') + ->addAttributeToFilter('sku', ['eq' => 'simple3']) + ->addAttributeToSort('created_at', 'DESC') + ->joinField( + 'stock_status', + 'cataloginventory_stock_status', + 'stock_status', + 'product_id=entity_id', + '{{table}}.stock_id=1', + 'left' + )->load(); + + $this->assertCount(1, $productCollection); + + /** @var Product $product */ + foreach ($productCollection as $product) { + $this->assertEquals(1, $product->getData('stock_status')); + } + } } From 4f5da9bc0100f953bfb18479d92b862b898324e5 Mon Sep 17 00:00:00 2001 From: OlgaVasyltsun <olga.vasyltsun@gmail.com> Date: Wed, 3 Jul 2019 14:43:06 +0300 Subject: [PATCH 611/773] MC-17865: Finalize @codingStandardsIgnoreFile elimination in CE --- .../templates/browser/content/uploader.phtml | 15 ++++++++------- .../frontend/templates/transparent/form.phtml | 2 +- .../templates/system/config/fieldset/hint.phtml | 2 +- .../view/adminhtml/templates/categories.phtml | 3 +-- .../view/adminhtml/templates/selector.phtml | 2 +- .../view/frontend/templates/cards_list.phtml | 10 +++++----- 6 files changed, 17 insertions(+), 17 deletions(-) diff --git a/app/code/Magento/Cms/view/adminhtml/templates/browser/content/uploader.phtml b/app/code/Magento/Cms/view/adminhtml/templates/browser/content/uploader.phtml index 2f789763ded44..838a8a122fbb9 100644 --- a/app/code/Magento/Cms/view/adminhtml/templates/browser/content/uploader.phtml +++ b/app/code/Magento/Cms/view/adminhtml/templates/browser/content/uploader.phtml @@ -8,6 +8,7 @@ $filters = $block->getConfig()->getFilters() ?? []; $allowedExtensions = []; +$blockHtmlId = $block->escapeHtml($block->getHtmlId()); foreach ($filters as $media_type) { $allowedExtensions = array_merge($allowedExtensions, array_map(function ($fileExt) { @@ -24,13 +25,13 @@ $resizeConfig = $block->getImageUploadConfigData()->getIsResizeEnabled() : "{action: 'resize'}"; ?> -<div id="<?= $block->getHtmlId() ?>" class="uploader"> +<div id="<?= /* @noEscape */ $blockHtmlId ?>" class="uploader"> <span class="fileinput-button form-buttons"> <span><?= $block->escapeHtml(__('Upload Images')) ?></span> <input class="fileupload" type="file" name="<?= $block->escapeHtmlAttr($block->getConfig()->getFileField()) ?>" data-url="<?= $block->escapeUrl($block->getConfig()->getUrl()) ?>" multiple> </span> <div class="clear"></div> - <script type="text/x-magento-template" id="<?= $block->getHtmlId() ?>-template"> + <script type="text/x-magento-template" id="<?= /* @noEscape */ $blockHtmlId ?>-template"> <div id="<%- data.id %>" class="file-row"> <span class="file-info"><%- data.name %> (<%- data.size %>)</span> <div class="progressbar-container"> @@ -52,7 +53,7 @@ require([ var maxFileSize = <?= $block->escapeJs($block->getFileSizeService()->getMaxFileSize()) ?>, allowedExtensions = '<?= $block->escapeHtml(implode(' ', $allowedExtensions)) ?>'; - $('#<?= $block->getHtmlId() ?> .fileupload').fileupload({ + $('#<?= /* @noEscape */ $blockHtmlId ?> .fileupload').fileupload({ dataType: 'json', formData: { isAjax: 'true', @@ -62,9 +63,9 @@ require([ acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i, allowedExtensions: allowedExtensions, maxFileSize: maxFileSize, - dropZone: $('#<?= $block->getHtmlId() ?>').closest('[role="dialog"]'), + dropZone: $('#<?= /* @noEscape */ $blockHtmlId ?>').closest('[role="dialog"]'), add: function (e, data) { - var progressTmpl = mageTemplate('#<?= $block->getHtmlId() ?>-template'), + var progressTmpl = mageTemplate('#<?= /* @noEscape */ $blockHtmlId ?>-template'), fileSize, tmpl, validationResult; @@ -108,7 +109,7 @@ require([ } }); - $(tmpl).data('image', data).appendTo('#<?= $block->getHtmlId() ?>'); + $(tmpl).data('image', data).appendTo('#<?= /* @noEscape */ $blockHtmlId ?>'); return true; }); @@ -145,7 +146,7 @@ require([ } }); - $('#<?= $block->getHtmlId() ?> .fileupload').fileupload('option', { + $('#<?= /* @noEscape */ $blockHtmlId ?> .fileupload').fileupload('option', { process: [{ action: 'load', fileTypes: /^image\/(gif|jpeg|png)$/, diff --git a/app/code/Magento/Payment/view/frontend/templates/transparent/form.phtml b/app/code/Magento/Payment/view/frontend/templates/transparent/form.phtml index c1d1156d273cf..290c8384537fb 100644 --- a/app/code/Magento/Payment/view/frontend/templates/transparent/form.phtml +++ b/app/code/Magento/Payment/view/frontend/templates/transparent/form.phtml @@ -9,7 +9,7 @@ $code = $block->escapeHtml($block->getMethodCode()); $ccExpMonth = $block->getInfoData('cc_exp_month'); $ccExpYear = $block->getInfoData('cc_exp_year'); $ccType = $block->getInfoData('cc_type'); -$content = '<img src=\"' . $block->getViewFileUrl('Magento_Checkout::cvv.png') . '\" alt=\"' . +$content = '<img src=\"' . $block->escapeUrl($block->getViewFileUrl('Magento_Checkout::cvv.png')) . '\" alt=\"' . $block->escapeHtml(__('Card Verification Number Visual Reference')) . '\" title=\"' . $block->escapeHtml(__('Card Verification Number Visual Reference')) . '\" />'; ?> diff --git a/app/code/Magento/Paypal/view/adminhtml/templates/system/config/fieldset/hint.phtml b/app/code/Magento/Paypal/view/adminhtml/templates/system/config/fieldset/hint.phtml index 831c03a77980e..689c21943cbf1 100644 --- a/app/code/Magento/Paypal/view/adminhtml/templates/system/config/fieldset/hint.phtml +++ b/app/code/Magento/Paypal/view/adminhtml/templates/system/config/fieldset/hint.phtml @@ -13,7 +13,7 @@ $helpLink = $block->escapeUrl($block->getHelpLink()); <?php if ($helpLink) : ?> <div class="paypal-payment-notice"> <?= $block->escapeHtml(__('Not sure what PayPal payment method to use? Click ')) ?> - <a href="<?= /* @noEscape */$helpLink; ?>" target="_blank"><?= $block->escapeHtml(__('here')) ?></a> + <a href="<?= /* @noEscape */ $helpLink; ?>" target="_blank"><?= $block->escapeHtml(__('here')) ?></a> <?= $block->escapeHtml(__(' to learn more.')) ?> </div> <?php endif; ?> diff --git a/app/code/Magento/UrlRewrite/view/adminhtml/templates/categories.phtml b/app/code/Magento/UrlRewrite/view/adminhtml/templates/categories.phtml index bd79bb1d59d98..f115fdb529466 100644 --- a/app/code/Magento/UrlRewrite/view/adminhtml/templates/categories.phtml +++ b/app/code/Magento/UrlRewrite/view/adminhtml/templates/categories.phtml @@ -22,8 +22,7 @@ "categoryTree": { "data": <?= /* @noEscape */ $this->helper(\Magento\Framework\Json\Helper\Data::class)->jsonEncode($block->getTreeArray()); ?>, - "url": "<?= /* @noEscape */ - $block->escapeUrl($block->getLoadTreeUrl()); ?>" + "url": "<?= $block->escapeUrl($block->getLoadTreeUrl()); ?>" } } } diff --git a/app/code/Magento/UrlRewrite/view/adminhtml/templates/selector.phtml b/app/code/Magento/UrlRewrite/view/adminhtml/templates/selector.phtml index 8662001673653..84abf64af9757 100644 --- a/app/code/Magento/UrlRewrite/view/adminhtml/templates/selector.phtml +++ b/app/code/Magento/UrlRewrite/view/adminhtml/templates/selector.phtml @@ -15,7 +15,7 @@ <div class="admin__field-control control"> <select data-role="entity-type-selector" class="admin__control-select select" onchange="window.location = this.value;" id="entity-type-selector"> <?php foreach ($block->getModes() as $mode => $label) : ?> - <option <?= /* noEscape */ $block->isMode($mode) ? 'selected="selected" ' : '' ?>value="<?= $block->escapeUrl($block->getModeUrl($mode)) ?>"><?= $block->escapeHtml($label) ?></option> + <option <?= /* @noEscape */ $block->isMode($mode) ? 'selected="selected" ' : '' ?>value="<?= $block->escapeUrl($block->getModeUrl($mode)) ?>"><?= $block->escapeHtml($label) ?></option> <?php endforeach; ?> </select> </div> diff --git a/app/code/Magento/Vault/view/frontend/templates/cards_list.phtml b/app/code/Magento/Vault/view/frontend/templates/cards_list.phtml index d28f7ccb65ca8..275a7b447d3d7 100644 --- a/app/code/Magento/Vault/view/frontend/templates/cards_list.phtml +++ b/app/code/Magento/Vault/view/frontend/templates/cards_list.phtml @@ -10,12 +10,12 @@ $tokens = $block->getPaymentTokens(); <?php if (count($tokens) !== 0) : ?> <div class="table-wrapper my-credit-cards"> <table class="data table table-credit-cards" id="my-orders-table"> - <caption class="table-caption"><?= /* @noEscape */ __('Stored Payment Methods') ?></caption> + <caption class="table-caption"><?= $block->escapeHtml(__('Stored Payment Methods')) ?></caption> <thead> <tr> - <th scope="col" class="col card-number"><?= /* @noEscape */ __('Card Number') ?></th> - <th scope="col" class="col expire"><?= /* @noEscape */ __('Expiration Date') ?></th> - <th scope="col" class="col card-type"><?= /* @noEscape */ __('Type') ?></th> + <th scope="col" class="col card-number"><?= $block->escapeHtml(__('Card Number')) ?></th> + <th scope="col" class="col expire"><?= $block->escapeHtml(__('Expiration Date')) ?></th> + <th scope="col" class="col card-type"><?= $block->escapeHtml(__('Type')) ?></th> <th scope="col" class="col actions"> </th> </tr> </thead> @@ -30,5 +30,5 @@ $tokens = $block->getPaymentTokens(); </div> <?php elseif (!$block->isExistsCustomerTokens()) : ?> - <div class="message info empty"><span><?= /* @noEscape */ __('You have no stored payment methods.') ?></span></div> + <div class="message info empty"><span><?= $block->escapeHtml(__('You have no stored payment methods.')) ?></span></div> <?php endif ?> From dbe4f9f021d10f9b6a65c1341925f499a6fed4ee Mon Sep 17 00:00:00 2001 From: Serhiy Yelahin <serhiy.yelahin@transoftgroup.com> Date: Thu, 4 Jul 2019 11:54:41 +0300 Subject: [PATCH 612/773] MC-17925: Customer address attribute Phone validation issue --- app/code/Magento/Customer/Model/Data/Address.php | 2 +- app/code/Magento/Eav/Model/Attribute/Data/Text.php | 4 ++-- .../Magento/Eav/Test/Unit/Model/Attribute/Data/TextTest.php | 1 - 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Customer/Model/Data/Address.php b/app/code/Magento/Customer/Model/Data/Address.php index f4cf228fb557c..f6764a98d06eb 100644 --- a/app/code/Magento/Customer/Model/Data/Address.php +++ b/app/code/Magento/Customer/Model/Data/Address.php @@ -119,7 +119,7 @@ public function getCompany() */ public function getTelephone() { - return $this->_get(self::TELEPHONE); + return trim($this->_get(self::TELEPHONE)); } /** diff --git a/app/code/Magento/Eav/Model/Attribute/Data/Text.php b/app/code/Magento/Eav/Model/Attribute/Data/Text.php index 071b2b83e3963..548efb230fb0b 100644 --- a/app/code/Magento/Eav/Model/Attribute/Data/Text.php +++ b/app/code/Magento/Eav/Model/Attribute/Data/Text.php @@ -45,7 +45,7 @@ public function __construct( */ public function extractValue(RequestInterface $request) { - $value = $this->_getRequestValue($request); + $value = trim($this->_getRequestValue($request)); return $this->_applyInputFilter($value); } @@ -168,7 +168,7 @@ private function validateLength(\Magento\Eav\Model\Attribute $attribute, string */ private function validateInputRule(string $value): array { - $result = $this->_validateInputRule(trim($value)); + $result = $this->_validateInputRule($value); return \is_array($result) ? $result : []; } } diff --git a/app/code/Magento/Eav/Test/Unit/Model/Attribute/Data/TextTest.php b/app/code/Magento/Eav/Test/Unit/Model/Attribute/Data/TextTest.php index 785c386b439d8..f4c2ad43ab9e3 100644 --- a/app/code/Magento/Eav/Test/Unit/Model/Attribute/Data/TextTest.php +++ b/app/code/Magento/Eav/Test/Unit/Model/Attribute/Data/TextTest.php @@ -138,7 +138,6 @@ public function alphanumDataProvider(): array ['QazWsx12345', [ __('"%1" length must be equal or less than %2 characters.', 'Test', 10)] ], - [' 12345 ', true], ]; } From 50c051f3bee94921e2be0c2349edf0c08ba9a2b2 Mon Sep 17 00:00:00 2001 From: Yurii Sapiha <engcom-vendorworker-foxtrot@adobe.com> Date: Sun, 4 Aug 2019 01:00:34 -0700 Subject: [PATCH 613/773] magento/magento#23500 fix funk tests --- .../Catalog/Test/Mftf/Section/AdminProductFormSection.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormSection.xml index 84dd83ed4ef2a..5e2c2d365179f 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormSection.xml @@ -79,6 +79,7 @@ <element name="sectionHeader" type="button" selector="div[data-index='websites']" timeout="30"/> <element name="sectionHeaderOpened" type="button" selector="[data-index='websites']._show" timeout="30"/> <element name="website" type="checkbox" selector="//label[contains(text(), '{{var1}}')]/parent::div//input[@type='checkbox']" parameterized="true"/> + <element name="websiteChecked" type="checkbox" selector="//label[contains(text(), '{{var1}}')]/parent::div//input[@type='checkbox'][@value='1']" parameterized="true"/> </section> <section name="ProductDesignSection"> <element name="DesignTab" type="button" selector="//strong[@class='admin__collapsible-title']//span[text()='Design']"/> From 7f68d94dcf0f3a9185b692885cdd689c781112eb Mon Sep 17 00:00:00 2001 From: Nikita Fomin <nikita.fomin@transoftgroup.com> Date: Thu, 4 Jul 2019 14:20:20 +0300 Subject: [PATCH 614/773] MAGETWO-97024: Change quote expiration date with non US time format locale --- .../Test/Mftf/ActionGroup/SetAdminAccountActionGroup.xml | 8 ++++---- .../Ui/Test/Mftf/Section/AdminDataGridTableSection.xml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/Backend/Test/Mftf/ActionGroup/SetAdminAccountActionGroup.xml b/app/code/Magento/Backend/Test/Mftf/ActionGroup/SetAdminAccountActionGroup.xml index 9e5c0bb3f39bf..a1d3635093030 100644 --- a/app/code/Magento/Backend/Test/Mftf/ActionGroup/SetAdminAccountActionGroup.xml +++ b/app/code/Magento/Backend/Test/Mftf/ActionGroup/SetAdminAccountActionGroup.xml @@ -10,15 +10,15 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="SetAdminAccountActionGroup"> <arguments> - <argument name="InterfaceLocaleByValue" type="string"/> + <argument name="InterfaceLocaleByValue" defaultValue="en_US" type="string"/> </arguments> <!-- Navigate to admin System Account Page--> <amOnPage url="{{AdminSystemAccountPage.url}}" stepKey="openAdminSystemAccountPage" /> - <waitForPageLoad stepKey="loadAdminSystemAccountPage"/> <!-- Change Admin locale to Français (France) / French (France) --> <selectOption userInput="{{InterfaceLocaleByValue}}" selector="{{AdminSystemAccountSection.interfaceLocale}}" stepKey="setInterfaceLocate"/> <fillField selector="{{AdminSystemAccountSection.currentPassword}}" userInput="{{_ENV.MAGENTO_ADMIN_PASSWORD}}" stepKey="fillPassword"/> - <click selector="{{AdminCustomerMainActionsSection.saveButton}}" stepKey="clickSave"/> - <waitForElement selector="{{AdminCustomerMessagesSection.successMessage}}" stepKey="waitSuccessMessage"/> + <click selector="{{AdminMainActionsSection.save}}" stepKey="clickSave"/> + <waitForElementVisible selector="{{AdminMessagesSection.success}}" stepKey="waitSuccessMessage"/> + <see selector="{{AdminMessagesSection.success}}" userInput="You saved the account." stepKey="seeSuccessMessage"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/Ui/Test/Mftf/Section/AdminDataGridTableSection.xml b/app/code/Magento/Ui/Test/Mftf/Section/AdminDataGridTableSection.xml index 8a61bf76cc5ea..af70eae770364 100644 --- a/app/code/Magento/Ui/Test/Mftf/Section/AdminDataGridTableSection.xml +++ b/app/code/Magento/Ui/Test/Mftf/Section/AdminDataGridTableSection.xml @@ -20,6 +20,6 @@ <element name="rowViewAction" type="button" selector=".data-grid tbody > tr:nth-of-type({{row}}) .action-menu-item" parameterized="true" timeout="30"/> <element name="dataGridEmpty" type="block" selector=".data-grid-tr-no-data td"/> <element name="rowTemplateStrict" type="block" selector="//tbody/tr[td[*[text()[normalize-space()='{{text}}']]]]" parameterized="true" /> - <element name="rowTemplate" type="block" selector="//tbody/tr[td[*[contains(.,normalize-space('{{text}}'))]]]" parameterized="true" /> + <element name="rowTemplate" type="block" selector="//tbody/tr[td[*[contains(.,normalize-space('{{text}}'))]]]" parameterized="true" timeout="30" /> </section> </sections> From c556b2fe47f20155af1d9b749e3ad56bab07908f Mon Sep 17 00:00:00 2001 From: Serhiy Yelahin <serhiy.yelahin@transoftgroup.com> Date: Thu, 4 Jul 2019 15:04:14 +0300 Subject: [PATCH 615/773] MC-17925: Customer address attribute Phone validation issue --- app/code/Magento/Customer/Model/Data/Address.php | 6 +++--- .../ResourceModel/AddressRepositoryTest.php | 16 ++++++++++++++++ 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Customer/Model/Data/Address.php b/app/code/Magento/Customer/Model/Data/Address.php index f6764a98d06eb..8ed3d16f323fe 100644 --- a/app/code/Magento/Customer/Model/Data/Address.php +++ b/app/code/Magento/Customer/Model/Data/Address.php @@ -42,7 +42,7 @@ public function __construct( } /** - * {@inheritdoc} + * @inheritdoc */ protected function getCustomAttributesCodes() { @@ -452,7 +452,7 @@ public function setIsDefaultBilling($isDefaultBilling) } /** - * {@inheritdoc} + * @inheritdoc * * @return \Magento\Customer\Api\Data\AddressExtensionInterface|null */ @@ -462,7 +462,7 @@ public function getExtensionAttributes() } /** - * {@inheritdoc} + * @inheritdoc * * @param \Magento\Customer\Api\Data\AddressExtensionInterface $extensionAttributes * @return $this diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/ResourceModel/AddressRepositoryTest.php b/dev/tests/integration/testsuite/Magento/Customer/Model/ResourceModel/AddressRepositoryTest.php index 381c580f55e60..299d09d9400de 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Model/ResourceModel/AddressRepositoryTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Model/ResourceModel/AddressRepositoryTest.php @@ -571,4 +571,20 @@ private function getWebsite(string $code): WebsiteInterface $repository = $this->objectManager->get(WebsiteRepositoryInterface::class); return $repository->get($code); } + + /** + * Test for saving address with extra spaces in phone. + * + * @magentoDataFixture Magento/Customer/_files/customer.php + * @magentoDataFixture Magento/Customer/_files/customer_address.php + */ + public function testSaveNewAddressWithExtraSpacesInPhone() + { + $proposedAddress = $this->_createSecondAddress() + ->setCustomerId(1) + ->setTelephone(' 123456 '); + $returnedAddress = $this->repository->save($proposedAddress); + $savedAddress = $this->repository->getById($returnedAddress->getId()); + $this->assertEquals('123456', $savedAddress->getTelephone()); + } } From fd7ebc2398745f1f6c1af993498e6bb3b36ffdc6 Mon Sep 17 00:00:00 2001 From: Yurii Sapiha <engcom-vendorworker-foxtrot@adobe.com> Date: Sat, 3 Aug 2019 04:56:27 -0700 Subject: [PATCH 616/773] magento/magento2#23532 Fix-static-tests --- app/code/Magento/Catalog/Model/Product/Visibility.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Model/Product/Visibility.php b/app/code/Magento/Catalog/Model/Product/Visibility.php index 3a397969fdeac..c05bda7838d78 100644 --- a/app/code/Magento/Catalog/Model/Product/Visibility.php +++ b/app/code/Magento/Catalog/Model/Product/Visibility.php @@ -86,6 +86,7 @@ public function getVisibleInSiteIds() * Retrieve option array * * @return array + * phpcs:disable Magento2.Functions.StaticFunction */ public static function getOptionArray() { @@ -134,6 +135,7 @@ public static function getOptionText($optionId) $options = self::getOptionArray(); return isset($options[$optionId]) ? $options[$optionId] : null; } + //phpcs:enable Magento2.Functions.StaticFunction /** * Retrieve flat column definition @@ -251,7 +253,7 @@ public function addValueSortToCollection($collection, $dir = 'asc') } /** - * {@inheritdoc} + * @inheritdoc */ public function toOptionArray() { From 8ae68ec40075eef8f1fe0a7ef085c9e0066a67fb Mon Sep 17 00:00:00 2001 From: Dmitriy Kogut <kogut.dmitriy@gmail.com> Date: Fri, 5 Jul 2019 10:09:16 +0300 Subject: [PATCH 617/773] MC-12129: [B2B-Company Credit] Change company credit currency for different admin locale --- .../AdminSetBaseCurrencyActionGroup.xml | 19 +++++++++++++++++++ .../Mftf/Section/CurrencySetupSection.xml | 4 +++- .../VerifyDisabledCustomerGroupFieldTest.xml | 2 +- 3 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 app/code/Magento/CurrencySymbol/Test/Mftf/ActionGroup/AdminSetBaseCurrencyActionGroup.xml diff --git a/app/code/Magento/CurrencySymbol/Test/Mftf/ActionGroup/AdminSetBaseCurrencyActionGroup.xml b/app/code/Magento/CurrencySymbol/Test/Mftf/ActionGroup/AdminSetBaseCurrencyActionGroup.xml new file mode 100644 index 0000000000000..1dc9b83b45008 --- /dev/null +++ b/app/code/Magento/CurrencySymbol/Test/Mftf/ActionGroup/AdminSetBaseCurrencyActionGroup.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <!-- Set base currency --> + <actionGroup name="AdminSetBaseCurrencyActionGroup" extends="AdminSaveConfigActionGroup"> + <arguments> + <argument name="currency" type="string"/> + </arguments> + <uncheckOption selector="{{CurrencySetupSection.baseCurrencyUseDefault}}" before="clickSaveConfigBtn" stepKey="uncheckUseDefaultOption"/> + <selectOption selector="{{CurrencySetupSection.baseCurrency}}" userInput="{{currency}}" after="uncheckUseDefaultOption" stepKey="setBaseCurrencyField"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/CurrencySymbol/Test/Mftf/Section/CurrencySetupSection.xml b/app/code/Magento/CurrencySymbol/Test/Mftf/Section/CurrencySetupSection.xml index 20fcd1e89360c..5d03c83b50b9d 100644 --- a/app/code/Magento/CurrencySymbol/Test/Mftf/Section/CurrencySetupSection.xml +++ b/app/code/Magento/CurrencySymbol/Test/Mftf/Section/CurrencySetupSection.xml @@ -10,6 +10,8 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="CurrencySetupSection"> <element name="allowCurrencies" type="select" selector="#currency_options_allow"/> + <element name="baseCurrency" type="select" selector="#currency_options_base"/> + <element name="baseCurrencyUseDefault" type="checkbox" selector="#currency_options_base_inherit"/> <element name="currencyOptions" type="select" selector="#currency_options-head"/> </section> -</sections> \ No newline at end of file +</sections> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/VerifyDisabledCustomerGroupFieldTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/VerifyDisabledCustomerGroupFieldTest.xml index 648c30b1ca0bb..0f98184aafb4f 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/VerifyDisabledCustomerGroupFieldTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/VerifyDisabledCustomerGroupFieldTest.xml @@ -26,7 +26,7 @@ <!-- 2. Navigate to Customers > Customer Groups --> <amOnPage url="{{AdminCustomerGroupPage.url}}" stepKey="amOnCustomerGroupPage" /> - <waitForPageLoad stepKey="waitForCustomerGroupsPageLoad" /> + <conditionalClick selector="{{AdminDataGridHeaderSection.clearFilters}}" dependentSelector="{{AdminDataGridHeaderSection.clearFilters}}" visible="true" stepKey="clearFiltersIfTheySet"/> <!-- 3. Select system Customer Group specified in data set from grid --> <click selector="{{AdminCustomerGroupMainSection.editButtonByCustomerGroupCode(NotLoggedInCustomerGroup.code)}}" stepKey="clickOnEditCustomerGroup" /> From 0cf5ae029afb5c132fa7e79ce2a18793b5c58fe5 Mon Sep 17 00:00:00 2001 From: Nikita Shcherbatykh <nikita.shcherbatykh@transoftgroup.com> Date: Fri, 5 Jul 2019 15:26:23 +0300 Subject: [PATCH 618/773] MC-17947: Search by email is working incorrect in Sales > Orders grid --- .../View/Element/UiComponent/DataProvider/FulltextFilter.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/DataProvider/FulltextFilter.php b/lib/internal/Magento/Framework/View/Element/UiComponent/DataProvider/FulltextFilter.php index e2920cf400a49..cf0aed4d23593 100644 --- a/lib/internal/Magento/Framework/View/Element/UiComponent/DataProvider/FulltextFilter.php +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/DataProvider/FulltextFilter.php @@ -70,7 +70,8 @@ function ($column) use ($alias) { */ private function escapeAgainstValue(string $value): string { - return preg_replace('/([+\-><\(\)~*@]+)/', ' ', $value); + $value = preg_replace('/([+\-><\(\)~*]+)/', ' ', $value); + return preg_replace('/(@)/', '\_', $value); } /** From ef06b82b7d6aa21c4bcbacdb4ca7d4d94a4073ea Mon Sep 17 00:00:00 2001 From: Serhiy Yelahin <serhiy.yelahin@transoftgroup.com> Date: Fri, 5 Jul 2019 16:59:47 +0300 Subject: [PATCH 619/773] MC-17925: Customer address attribute Phone validation issue --- app/code/Magento/Customer/Model/Data/Address.php | 4 ++-- app/code/Magento/Sales/Model/Order/Address.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Customer/Model/Data/Address.php b/app/code/Magento/Customer/Model/Data/Address.php index 8ed3d16f323fe..b399a144368d3 100644 --- a/app/code/Magento/Customer/Model/Data/Address.php +++ b/app/code/Magento/Customer/Model/Data/Address.php @@ -119,7 +119,7 @@ public function getCompany() */ public function getTelephone() { - return trim($this->_get(self::TELEPHONE)); + return $this->_get(self::TELEPHONE); } /** @@ -327,7 +327,7 @@ public function setCompany($company) */ public function setTelephone($telephone) { - return $this->setData(self::TELEPHONE, $telephone); + return $this->setData(self::TELEPHONE, trim($telephone)); } /** diff --git a/app/code/Magento/Sales/Model/Order/Address.php b/app/code/Magento/Sales/Model/Order/Address.php index fd49af27a998e..9b8f4e79c23fa 100644 --- a/app/code/Magento/Sales/Model/Order/Address.php +++ b/app/code/Magento/Sales/Model/Order/Address.php @@ -601,7 +601,7 @@ public function setEmail($email) */ public function setTelephone($telephone) { - return $this->setData(OrderAddressInterface::TELEPHONE, $telephone); + return $this->setData(OrderAddressInterface::TELEPHONE, trim($telephone)); } /** From dfd664e5d2cb14348b49984d3760c779e0dabe7c Mon Sep 17 00:00:00 2001 From: Yurii Sapiha <engcom-vendorworker-foxtrot@adobe.com> Date: Fri, 5 Jul 2019 09:13:54 -0700 Subject: [PATCH 620/773] magento/magento2#23427 Fix static --- .../Ui/DataProvider/Product/AddFulltextFilterToCollection.php | 2 +- app/code/Magento/Ui/Component/Filters/Type/Search.php | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/CatalogSearch/Ui/DataProvider/Product/AddFulltextFilterToCollection.php b/app/code/Magento/CatalogSearch/Ui/DataProvider/Product/AddFulltextFilterToCollection.php index 85909fa4a280b..f312178e0bf0b 100644 --- a/app/code/Magento/CatalogSearch/Ui/DataProvider/Product/AddFulltextFilterToCollection.php +++ b/app/code/Magento/CatalogSearch/Ui/DataProvider/Product/AddFulltextFilterToCollection.php @@ -30,7 +30,7 @@ public function __construct(SearchCollection $searchCollection) } /** - * {@inheritdoc} + * @inheritdoc * * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ diff --git a/app/code/Magento/Ui/Component/Filters/Type/Search.php b/app/code/Magento/Ui/Component/Filters/Type/Search.php index 446534cb82481..afa3c775dae44 100644 --- a/app/code/Magento/Ui/Component/Filters/Type/Search.php +++ b/app/code/Magento/Ui/Component/Filters/Type/Search.php @@ -6,6 +6,8 @@ namespace Magento\Ui\Component\Filters\Type; /** + * Class Search + * * @api * @since 100.0.2 */ From 844a3bbb6076887012a8d7870b31bb6e3328f0ec Mon Sep 17 00:00:00 2001 From: mrkhoa <mrkhoa99@gmail.com> Date: Sat, 6 Jul 2019 14:06:33 +0700 Subject: [PATCH 621/773] A small fix: Improve format customer acl xml. --- app/code/Magento/Customer/etc/acl.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Customer/etc/acl.xml b/app/code/Magento/Customer/etc/acl.xml index e8e6219bef4fe..53098c2009f7b 100644 --- a/app/code/Magento/Customer/etc/acl.xml +++ b/app/code/Magento/Customer/etc/acl.xml @@ -20,7 +20,7 @@ <resource id="Magento_Customer::config_customer" title="Customers Section" translate="title" sortOrder="50" /> </resource> </resource> - </resource> + </resource> </resource> </resources> </acl> From 9aa4744ee6eafbd7ecc722b8c501493cd594b28c Mon Sep 17 00:00:00 2001 From: Yaroslav Rogoza <enarc@atwix.com> Date: Sun, 7 Jul 2019 13:52:24 +0200 Subject: [PATCH 622/773] Default filter for reports set to past month --- app/code/Magento/Reports/Block/Adminhtml/Grid.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Reports/Block/Adminhtml/Grid.php b/app/code/Magento/Reports/Block/Adminhtml/Grid.php index 1851e959e7a58..32073cf0b7a04 100644 --- a/app/code/Magento/Reports/Block/Adminhtml/Grid.php +++ b/app/code/Magento/Reports/Block/Adminhtml/Grid.php @@ -135,8 +135,8 @@ protected function _prepareCollection() $data = $this->parameters->toArray(); if (!isset($data['report_from'])) { - // getting all reports from 2001 year - $date = (new \DateTime())->setTimestamp(mktime(0, 0, 0, 1, 1, 2001)); + // Get records for the past month + $date = new \DateTime('-1 month'); $data['report_from'] = $this->_localeDate->formatDateTime( $date, \IntlDateFormatter::SHORT, @@ -145,7 +145,6 @@ protected function _prepareCollection() } if (!isset($data['report_to'])) { - // getting all reports from 2001 year $date = new \DateTime(); $data['report_to'] = $this->_localeDate->formatDateTime( $date, From ccce575fa7dd68a7c09a77f1aba5dfa4f6eccf5c Mon Sep 17 00:00:00 2001 From: Serhii Balko <serhii.balko@transoftgroup.com> Date: Mon, 8 Jul 2019 12:34:37 +0300 Subject: [PATCH 623/773] MC-17803: Request A Quote form not working in IE11 not support create-negotiable-quote.js --- lib/web/mage/msie/file-reader.js | 42 ++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 lib/web/mage/msie/file-reader.js diff --git a/lib/web/mage/msie/file-reader.js b/lib/web/mage/msie/file-reader.js new file mode 100644 index 0000000000000..6d45d3a31485a --- /dev/null +++ b/lib/web/mage/msie/file-reader.js @@ -0,0 +1,42 @@ +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +define([ + 'jquery' +], function ($) { + 'use strict'; + + /** + * Init "readAsBinaryString" function for FileReader class. + * It need for IE11 + * @param {Blob} fileData + */ + var readAsBinaryStringIEFunc = function (fileData) { + var binary = '', + self = this, + reader = new FileReader(); + + /** + * Read file as binary string + */ + reader.onload = function () { + var bytes, length, index; + + bytes = new Uint8Array(reader.result); + length = bytes.length; + + for (index = 0; index < length; index++) { + binary += String.fromCharCode(bytes[index]); + } + //self.result - readonly so assign binary + self.content = binary; + $(self).trigger('onload'); + }; + reader.readAsArrayBuffer(fileData); + }; + + if (typeof FileReader.prototype.readAsBinaryString === 'undefined') { + FileReader.prototype.readAsBinaryString = readAsBinaryStringIEFunc; + } +}); From 69a1b987ea28f54e47ec3078fe6dff8948cde056 Mon Sep 17 00:00:00 2001 From: Pieter Hoste <hoste.pieter@gmail.com> Date: Sat, 4 May 2019 21:14:09 +0200 Subject: [PATCH 624/773] Adds module:config:status command which checks if the module config in the app/etc/config.php file is correct or not. --- .../Command/ModuleConfigStatusCommand.php | 101 ++++++++++++++++++ .../src/Magento/Setup/Console/CommandList.php | 1 + setup/src/Magento/Setup/Model/Installer.php | 11 ++ .../Command/ModuleConfigStatusCommandTest.php | 87 +++++++++++++++ 4 files changed, 200 insertions(+) create mode 100644 setup/src/Magento/Setup/Console/Command/ModuleConfigStatusCommand.php create mode 100644 setup/src/Magento/Setup/Test/Unit/Console/Command/ModuleConfigStatusCommandTest.php diff --git a/setup/src/Magento/Setup/Console/Command/ModuleConfigStatusCommand.php b/setup/src/Magento/Setup/Console/Command/ModuleConfigStatusCommand.php new file mode 100644 index 0000000000000..eb1ac283cabba --- /dev/null +++ b/setup/src/Magento/Setup/Console/Command/ModuleConfigStatusCommand.php @@ -0,0 +1,101 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +declare(strict_types=1); + +namespace Magento\Setup\Console\Command; + +use Magento\Framework\App\DeploymentConfig\Reader as ConfigReader; +use Magento\Framework\Config\ConfigOptionsListConstants; +use Magento\Framework\Config\File\ConfigFilePool; +use Magento\Framework\Console\Cli; +use Magento\Framework\Setup\ConsoleLogger; +use Magento\Setup\Model\InstallerFactory; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * Command to check if the modules config in app/etc/config.php matches with how Magento interprets it + */ +class ModuleConfigStatusCommand extends Command +{ + /** + * Deployment config reader + * + * @var ConfigReader + */ + private $configReader; + + /** + * Installer service factory. + * + * @var InstallerFactory + */ + private $installerFactory; + + /** + * @param ConfigReader $configReader + * @param InstallerFactory $installerFactory + */ + public function __construct( + ConfigReader $configReader, + InstallerFactory $installerFactory + ) { + $this->configReader = $configReader; + $this->installerFactory = $installerFactory; + + parent::__construct(); + } + + /** + * @inheritdoc + */ + protected function configure() + { + $this->setName('module:config:status') + ->setDescription('Checks the modules configuration in the \'app/etc/config.php\' file and reports if they are up to date or not'); + + parent::configure(); + } + + /** + * @inheritdoc + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + try { + // the config as currently in app/etc/config.php + $currentConfig = $this->configReader->load(ConfigFilePool::APP_CONFIG); + if (!array_key_exists(ConfigOptionsListConstants::KEY_MODULES, $currentConfig)) { + throw new \Exception('Can\'t find the modules configuration in the \'app/etc/config.php\' file.'); + } + + $currentModuleConfig = $currentConfig[ConfigOptionsListConstants::KEY_MODULES]; + + $installer = $this->installerFactory->create(new ConsoleLogger($output)); + + // the module config as Magento calculated it + $correctModuleConfig = $installer->getModulesConfig(); + + if ($currentModuleConfig !== $correctModuleConfig) { + throw new \Exception( + 'The modules configuration in the \'app/etc/config.php\' file is outdated. Run \'setup:upgrade\' to fix it.' + ); + } + + $output->writeln( + '<info>The modules configuration is up to date.</info>' + ); + } catch (\Exception $e) { + $output->writeln('<error>' . $e->getMessage() . '</error>'); + + return Cli::RETURN_FAILURE; + } + + return Cli::RETURN_SUCCESS; + } +} diff --git a/setup/src/Magento/Setup/Console/CommandList.php b/setup/src/Magento/Setup/Console/CommandList.php index 08befdca2221d..101ff9edd2a0e 100644 --- a/setup/src/Magento/Setup/Console/CommandList.php +++ b/setup/src/Magento/Setup/Console/CommandList.php @@ -66,6 +66,7 @@ protected function getCommandsClasses() \Magento\Setup\Console\Command\ModuleDisableCommand::class, \Magento\Setup\Console\Command\ModuleStatusCommand::class, \Magento\Setup\Console\Command\ModuleUninstallCommand::class, + \Magento\Setup\Console\Command\ModuleConfigStatusCommand::class, \Magento\Setup\Console\Command\MaintenanceAllowIpsCommand::class, \Magento\Setup\Console\Command\MaintenanceDisableCommand::class, \Magento\Setup\Console\Command\MaintenanceEnableCommand::class, diff --git a/setup/src/Magento/Setup/Model/Installer.php b/setup/src/Magento/Setup/Model/Installer.php index d4ed261a9a945..f80a35937d5dc 100644 --- a/setup/src/Magento/Setup/Model/Installer.php +++ b/setup/src/Magento/Setup/Model/Installer.php @@ -1200,6 +1200,17 @@ public function updateModulesSequence($keepGeneratedFiles = false) $this->createModulesConfig([]); } + /** + * Get the modules config as Magento sees it + * + * @return array + * @throws \LogicException + */ + public function getModulesConfig() + { + return $this->createModulesConfig([], true); + } + /** * Uninstall Magento application * diff --git a/setup/src/Magento/Setup/Test/Unit/Console/Command/ModuleConfigStatusCommandTest.php b/setup/src/Magento/Setup/Test/Unit/Console/Command/ModuleConfigStatusCommandTest.php new file mode 100644 index 0000000000000..946e122b3c975 --- /dev/null +++ b/setup/src/Magento/Setup/Test/Unit/Console/Command/ModuleConfigStatusCommandTest.php @@ -0,0 +1,87 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +declare(strict_types=1); + +namespace Magento\Setup\Test\Unit\Console\Command; + +use Magento\Framework\Config\ConfigOptionsListConstants; +use Magento\Setup\Console\Command\ModuleConfigStatusCommand; +use PHPUnit\Framework\TestCase; +use Symfony\Component\Console\Tester\CommandTester; + +class ModuleConfigStatusCommandTest extends TestCase +{ + /** + * @param array $currentConfig + * @param array $correctConfig + * @param string $expectedOutput + * @dataProvider executeDataProvider + */ + public function testExecute(array $currentConfig, array $correctConfig, string $expectedOutput) + { + $configReader = $this->createMock(\Magento\Framework\App\DeploymentConfig\Reader::class); + $configReader->expects($this->once()) + ->method('load') + ->willReturn([ConfigOptionsListConstants::KEY_MODULES => $currentConfig]); + + $installer = $this->createMock(\Magento\Setup\Model\Installer::class); + $installer->expects($this->once()) + ->method('getModulesConfig') + ->willReturn($correctConfig); + + $installerFactory = $this->createMock(\Magento\Setup\Model\InstallerFactory::class); + $installerFactory->expects($this->once()) + ->method('create') + ->willReturn($installer); + + $command = new ModuleConfigStatusCommand($configReader, $installerFactory); + + $tester = new CommandTester($command); + $tester->execute([]); + + $this->assertEquals($expectedOutput, $tester->getDisplay()); + } + + public function executeDataProvider() + { + $successMessage = 'The modules configuration is up to date.' . PHP_EOL; + $failureMessage = 'The modules configuration in the \'app/etc/config.php\' file is outdated. Run \'setup:upgrade\' to fix it.' . PHP_EOL; + + return [ + [ + ['Magento_ModuleA' => 1, 'Magento_ModuleB' => 1], + ['Magento_ModuleA' => 1, 'Magento_ModuleB' => 1], + $successMessage, + ], + [ + ['Magento_ModuleA' => 0, 'Magento_ModuleB' => 1], + ['Magento_ModuleA' => 0, 'Magento_ModuleB' => 1], + $successMessage, + ], + [ + ['Magento_ModuleA' => 1, 'Magento_ModuleB' => 1], + ['Magento_ModuleB' => 1, 'Magento_ModuleA' => 1], + $failureMessage, + ], + [ + ['Magento_ModuleA' => 0, 'Magento_ModuleB' => 1], + ['Magento_ModuleB' => 1, 'Magento_ModuleA' => 0], + $failureMessage, + ], + [ + ['Magento_ModuleA' => 1], + ['Magento_ModuleB' => 1, 'Magento_ModuleA' => 1], + $failureMessage, + ], + [ + ['Magento_ModuleA' => 1, 'Magento_ModuleB' => 1], + ['Magento_ModuleB' => 1], + $failureMessage, + ], + ]; + } +} From c2218536d5b06ee82c9859e62259e4153e97218e Mon Sep 17 00:00:00 2001 From: Patrick McLain <pat@pmclain.com> Date: Mon, 8 Jul 2019 12:31:23 -0400 Subject: [PATCH 625/773] Remove PaymentMethodAdditionalDataInput From PaypalGraphQl --- .../Model/Plugin/Resolver/SetPaymentMethodOnCart.php | 4 ++-- app/code/Magento/PaypalGraphQl/etc/schema.graphqls | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/PaypalGraphQl/Model/Plugin/Resolver/SetPaymentMethodOnCart.php b/app/code/Magento/PaypalGraphQl/Model/Plugin/Resolver/SetPaymentMethodOnCart.php index 62ed8e0f68bcf..988ae7c8f4aa6 100644 --- a/app/code/Magento/PaypalGraphQl/Model/Plugin/Resolver/SetPaymentMethodOnCart.php +++ b/app/code/Magento/PaypalGraphQl/Model/Plugin/Resolver/SetPaymentMethodOnCart.php @@ -25,7 +25,7 @@ class SetPaymentMethodOnCart { private const PATH_CODE = 'input/payment_method/code'; - private const PATH_ADDITIONAL_DATA = 'input/payment_method/additional_data'; + private const PATH_PAYMENT_METHOD_DATA = 'input/payment_method'; private $allowedPaymentMethodCodes = []; @@ -98,7 +98,7 @@ public function afterResolve( return $resolvedValue; } - $paypalAdditionalData = $this->arrayManager->get(self::PATH_ADDITIONAL_DATA, $args) ?? []; + $paypalAdditionalData = $this->arrayManager->get(self::PATH_PAYMENT_METHOD_DATA, $args) ?? []; $payerId = $paypalAdditionalData[$paymentCode]['payer_id'] ?? null; $token = $paypalAdditionalData[$paymentCode]['token'] ?? null; $cart = $resolvedValue['cart']['model']; diff --git a/app/code/Magento/PaypalGraphQl/etc/schema.graphqls b/app/code/Magento/PaypalGraphQl/etc/schema.graphqls index 97b65fb6587f6..33cbb73668732 100644 --- a/app/code/Magento/PaypalGraphQl/etc/schema.graphqls +++ b/app/code/Magento/PaypalGraphQl/etc/schema.graphqls @@ -31,7 +31,7 @@ type PayflowLinkToken { paypal_url: String @doc(description:"PayPal URL used for requesting Payflow form") } -input PaymentMethodAdditionalDataInput { +input PaymentMethodInput { paypal_express: PaypalExpressInput @doc(description:"Required input for PayPal Express Checkout payments") payflow_express: PayflowExpressInput @doc(description:"Required input for PayPal Payflow Express Checkout payments") payflow_link: PayflowLinkAdditionalDataInput @doc(description:"Required input for PayPal Payflow Link payments") From 115948aa77faa6ac866b27343613b48d1624b6b5 Mon Sep 17 00:00:00 2001 From: Viktor Tymchynskyi <vtymchynskyi@magento.com> Date: Mon, 8 Jul 2019 11:47:48 -0500 Subject: [PATCH 626/773] MC-17966: Cannot make reorder using transparent-redirect based payment --- .../Magento/Payment/view/frontend/web/js/view/payment/iframe.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Payment/view/frontend/web/js/view/payment/iframe.js b/app/code/Magento/Payment/view/frontend/web/js/view/payment/iframe.js index 089dabac00b0f..522bd51270e87 100644 --- a/app/code/Magento/Payment/view/frontend/web/js/view/payment/iframe.js +++ b/app/code/Magento/Payment/view/frontend/web/js/view/payment/iframe.js @@ -144,7 +144,7 @@ define([ * {Function} */ setPaymentInformation: function () { - setPaymentInformationAction( + return setPaymentInformationAction( this.messageContainer, { method: this.getCode() From 9546c11b8ac6bd6fb0e33bb04b290385b956b5ec Mon Sep 17 00:00:00 2001 From: Roman Lytvynenko <lytvynen@adobe.com> Date: Mon, 8 Jul 2019 15:59:23 -0500 Subject: [PATCH 627/773] MC-17574: Magento WYSIWYG editor inserting " when inserting image image --- .../mage/adminhtml/wysiwyg/tiny_mce/tinymce4Adapter.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/web/mage/adminhtml/wysiwyg/tiny_mce/tinymce4Adapter.js b/lib/web/mage/adminhtml/wysiwyg/tiny_mce/tinymce4Adapter.js index 227ffe27bc9b3..4840fc9ae65ed 100644 --- a/lib/web/mage/adminhtml/wysiwyg/tiny_mce/tinymce4Adapter.js +++ b/lib/web/mage/adminhtml/wysiwyg/tiny_mce/tinymce4Adapter.js @@ -491,6 +491,12 @@ define([ } this.turnOff(); + var content = this.getTextArea().val(); + + if (content.match(/{{.+?}}/g)) { + this.getTextArea().val(content.replace(/"/g, '"')); + } + return false; }, @@ -701,9 +707,6 @@ define([ */ decodeContent: function (content) { if (this.config['add_directives']) { - if (content.match(/{{.+?}}/g)) { - return content.replace(/"/g, '"'); - } content = this.decodeDirectives(content); } From 7219923b140cdb51d0a69560af8c916b096d64d3 Mon Sep 17 00:00:00 2001 From: Roman Hanin <rganin@adobe.com> Date: Mon, 8 Jul 2019 16:11:58 -0500 Subject: [PATCH 628/773] MC-17854: Improper Escaping for Bundle Options in Multiple Address Checkout --- .../view/frontend/templates/checkout/item/default.phtml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Multishipping/view/frontend/templates/checkout/item/default.phtml b/app/code/Magento/Multishipping/view/frontend/templates/checkout/item/default.phtml index 51d964957c4d5..6bb5d5a1bacfc 100644 --- a/app/code/Magento/Multishipping/view/frontend/templates/checkout/item/default.phtml +++ b/app/code/Magento/Multishipping/view/frontend/templates/checkout/item/default.phtml @@ -13,11 +13,11 @@ <?php $_formatedOptionValue = $block->getFormatedOptionValue($_option) ?> <dt><?= $block->escapeHtml($_option['label']) ?></dt> <dd<?= (isset($_formatedOptionValue['full_view']) ? ' class="tooltip wrapper"' : '') ?> - <?= $block->escapeHtml($_formatedOptionValue['value']) ?> + <?= $block->escapeHtml($_formatedOptionValue['value'], ['span']) ?> <?php if (isset($_formatedOptionValue['full_view'])) : ?> <dl class="item options tooltip content"> <dt><?= $block->escapeHtml($_option['label']) ?></dt> - <dd><?= $block->escapeHtml($_formatedOptionValue['full_view']) ?></dd> + <dd><?= $block->escapeHtml($_formatedOptionValue['full_view'], ['span']) ?></dd> </dl> <?php endif; ?> </dd> From 638dab8d0efa0cc4183bdcdcc821dc691692f65b Mon Sep 17 00:00:00 2001 From: Roman Lytvynenko <lytvynen@adobe.com> Date: Mon, 8 Jul 2019 16:33:44 -0500 Subject: [PATCH 629/773] MC-17574: Magento WYSIWYG editor inserting " when inserting image image --- lib/web/mage/adminhtml/wysiwyg/tiny_mce/tinymce4Adapter.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/web/mage/adminhtml/wysiwyg/tiny_mce/tinymce4Adapter.js b/lib/web/mage/adminhtml/wysiwyg/tiny_mce/tinymce4Adapter.js index 4840fc9ae65ed..a05c0df03667e 100644 --- a/lib/web/mage/adminhtml/wysiwyg/tiny_mce/tinymce4Adapter.js +++ b/lib/web/mage/adminhtml/wysiwyg/tiny_mce/tinymce4Adapter.js @@ -484,6 +484,8 @@ define([ * @return {Boolean} */ toggle: function () { + var content = this.getTextArea().val(); + if (!tinyMCE4.get(this.getId())) { this.turnOn(); @@ -491,8 +493,6 @@ define([ } this.turnOff(); - var content = this.getTextArea().val(); - if (content.match(/{{.+?}}/g)) { this.getTextArea().val(content.replace(/"/g, '"')); } From c231bdf3af1550b577614016b64274999367923e Mon Sep 17 00:00:00 2001 From: Oleksandr Iegorov <oiegorov@magento.com> Date: Mon, 8 Jul 2019 17:19:49 -0500 Subject: [PATCH 630/773] MC-17808: Custom customer attribute code showing on guest checkout --- .../web/template/billing-address/details.html | 23 ++++++++----------- 1 file changed, 9 insertions(+), 14 deletions(-) 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 ea521b3a8afd4..b2c9974ae9b55 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 @@ -13,21 +13,16 @@ <a if="currentBillingAddress().telephone" attr="'href': 'tel:' + currentBillingAddress().telephone" text="currentBillingAddress().telephone"></a><br/> <each args="data: currentBillingAddress().customAttributes, as: 'element'"> - <each args="data: Object.keys(element), as: 'attribute'"> - <if args="typeof element[attribute] === 'object'"> - <if args="element[attribute].label"> - <text args="element[attribute].label"/> - </if> - <ifnot args="element[attribute].label"> - <if args="element[attribute].value"> - <text args="element[attribute].value"/> - </if> - </ifnot> + <if args="typeof element === 'object'"> + <if args="element.label"> + <text args="element.label"/> </if> - <if args="typeof element[attribute] === 'string'"> - <text args="element[attribute]"/> - </if><br/> - </each> + <ifnot args="element.label"> + <if args="element.value"> + <text args="element.value"/> + </if> + </ifnot> + </if> </each> <button visible="!isAddressSameAsShipping()" From 10ab218e95b60c54229abc72866c1aeaa014bbc6 Mon Sep 17 00:00:00 2001 From: Nikita Shcherbatykh <nikita.shcherbatykh@transoftgroup.com> Date: Tue, 9 Jul 2019 14:36:44 +0300 Subject: [PATCH 631/773] MC-17947: Search by email is working incorrect in Sales > Orders grid --- .../Test/SearchByEmailInCustomerGridTest.xml | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 app/code/Magento/Customer/Test/Mftf/Test/SearchByEmailInCustomerGridTest.xml diff --git a/app/code/Magento/Customer/Test/Mftf/Test/SearchByEmailInCustomerGridTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/SearchByEmailInCustomerGridTest.xml new file mode 100644 index 0000000000000..4937347c56b33 --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/Test/SearchByEmailInCustomerGridTest.xml @@ -0,0 +1,49 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="SearchByEmailInCustomerGridTest"> + <annotations> + <features value="Customer"/> + <stories value="Customer Search email searching"/> + <title value="Admin customer grid email searching"/> + <description value="Admin customer grid searching by email in keyword"/> + <severity value="MAJOR"/> + <testCaseId value="MC-17985"/> + <useCaseId value="MC-17947"/> + <group value="customer"/> + </annotations> + <before> + <createData entity="Simple_US_Customer" stepKey="createFirstCustomer"> + <field key="email">test1@example.com</field> + </createData> + <createData entity="Simple_US_Customer" stepKey="createSecondCustomer"> + <field key="email">test2@example.com</field> + </createData> + <actionGroup ref="LoginAsAdmin" stepKey="login"/> + </before> + <after> + <deleteData createDataKey="createFirstCustomer" stepKey="deleteFirstCustomer"/> + <deleteData createDataKey="createSecondCustomer" stepKey="deleteSecondCustomer"/> + <amOnPage url="{{AdminCustomerPage.url}}" stepKey="openCustomersGridPage"/> + <actionGroup ref="AdminResetFilterInCustomerAddressGrid" stepKey="clearCustomerGridFilter"/> + <actionGroup ref="logout" stepKey="logout"/> + </after> + <!--Step 1: Go to Customers > All Customers--> + <amOnPage url="{{AdminCustomerPage.url}}" stepKey="openCustomersGridPage"/> + <!--Step 2: On Customers grid page search customer by keyword--> + <actionGroup ref="searchAdminDataGridByKeyword" stepKey="searchCustomer"> + <argument name="keyword" value="$$createSecondCustomer.email$$"/> + </actionGroup> + <!--Step 3: Check if customer is placed in a first row and clear grid filter--> + <actionGroup ref="AdminAssertCustomerInCustomersGrid" stepKey="checkCustomerInGrid"> + <argument name="text" value="$$createSecondCustomer.email$$"/> + <argument name="row" value="1"/> + </actionGroup> + </test> +</tests> From cf20b918279e6a6c1c8028d2272c5aeaaa00b35c Mon Sep 17 00:00:00 2001 From: Serhii Voloshkov <serhii.voloshkov@transoftgroup.com> Date: Tue, 9 Jul 2019 15:09:19 +0300 Subject: [PATCH 632/773] MC-17864: Finalize @escapeNotVerified elimination --- .../view/frontend/templates/button.phtml | 4 +- .../view/base/templates/translate.phtml | 4 +- .../templates/layer/view.phtml | 66 ++++++++++++++----- 3 files changed, 52 insertions(+), 22 deletions(-) diff --git a/app/code/Magento/InstantPurchase/view/frontend/templates/button.phtml b/app/code/Magento/InstantPurchase/view/frontend/templates/button.phtml index d58b950f61197..8d407a3138ba4 100644 --- a/app/code/Magento/InstantPurchase/view/frontend/templates/button.phtml +++ b/app/code/Magento/InstantPurchase/view/frontend/templates/button.phtml @@ -14,8 +14,8 @@ <script type="text/x-magento-init"> { "#instant-purchase": { - "Magento_Ui/js/core/app": <?= /* @escapeNotVerified */ $block->getJsLayout();?> + "Magento_Ui/js/core/app": <?= /* @noEscape */ $block->getJsLayout();?> } } </script> -<?php endif; ?> \ No newline at end of file +<?php endif; ?> diff --git a/app/code/Magento/Translation/view/base/templates/translate.phtml b/app/code/Magento/Translation/view/base/templates/translate.phtml index ec88b1d092026..2567c02335b93 100644 --- a/app/code/Magento/Translation/view/base/templates/translate.phtml +++ b/app/code/Magento/Translation/view/base/templates/translate.phtml @@ -28,7 +28,7 @@ <?php $version = $block->getTranslationFileVersion(); ?> - if (versionObj.version !== '<?= /* @escapeNotVerified */ $block->escapeJsQuote($version) ?>') { + if (versionObj.version !== '<?= $block->escapeJsQuote($version) ?>') { dependencies.push( 'text!<?= /* @noEscape */ Magento\Translation\Model\Js\Config::DICTIONARY_FILE_NAME ?>' ); @@ -44,7 +44,7 @@ $.localStorage.set( 'mage-translation-file-version', { - version: '<?= /* @escapeNotVerified */ $block->escapeJsQuote($version) ?>' + version: '<?= $block->escapeJsQuote($version) ?>' } ); } else { diff --git a/app/design/frontend/Magento/luma/Magento_LayeredNavigation/templates/layer/view.phtml b/app/design/frontend/Magento/luma/Magento_LayeredNavigation/templates/layer/view.phtml index 1f09aa7510e06..2ec6ad43f9c40 100644 --- a/app/design/frontend/Magento/luma/Magento_LayeredNavigation/templates/layer/view.phtml +++ b/app/design/frontend/Magento/luma/Magento_LayeredNavigation/templates/layer/view.phtml @@ -3,8 +3,6 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ - -// @codingStandardsIgnoreFile ?> <?php /** @@ -14,36 +12,68 @@ */ ?> -<?php if ($block->canShowBlock()): ?> - <div class="block filter" id="layered-filter-block" data-mage-init='{"collapsible":{"openedState": "active", "collapsible": true, "active": false, "collateral": { "openedState": "filter-active", "element": "body" } }}'> +<?php if ($block->canShowBlock()) : ?> + <div class="block filter" id="layered-filter-block" data-mage-init=' + { + "collapsible": + { + "openedState": "active", + "collapsible": true, + "active": false, + "collateral": + { + "openedState": "filter-active", + "element": "body" + } + } + + }'> <?php $filtered = count($block->getLayer()->getState()->getFilters()) ?> - <div class="block-title filter-title" data-count="<?= /* @escapeNotVerified */ $filtered ?>"> - <strong data-role="title"><?= /* @escapeNotVerified */ __('Shop By') ?></strong> + <div class="block-title filter-title" data-count="<?= /* @noEscape */ $filtered ?>"> + <strong data-role="title"><?= $block->escapeHtml(__('Shop By')); ?></strong> </div> <div class="block-content filter-content"> <?= $block->getChildHtml('state') ?> - <?php if ($block->getLayer()->getState()->getFilters()): ?> + <?php if ($block->getLayer()->getState()->getFilters()) : ?> <div class="block-actions filter-actions"> - <a href="<?= /* @escapeNotVerified */ $block->getClearUrl() ?>" class="action clear filter-clear"><span><?= /* @escapeNotVerified */ __('Clear All') ?></span></a> + <a href="<?= $block->escapeUrl($block->getClearUrl()) ?>" class="action clear filter-clear"> + <span><?= $block->escapeHtml(__('Clear All')) ?></span> + </a> </div> <?php endif; ?> <?php $wrapOptions = false; ?> - <?php foreach ($block->getFilters() as $filter): ?> - <?php if ($filter->getItemsCount()): ?> - <?php if (!$wrapOptions): ?> - <strong role="heading" aria-level="2" class="block-subtitle filter-subtitle"><?= /* @escapeNotVerified */ __('Shopping Options') ?></strong> - <div class="filter-options" id="narrow-by-list" data-role="content" data-mage-init='{"accordion":{"openedState": "active", "collapsible": true, "active": false, "multipleCollapsible": false}}'> - <?php $wrapOptions = true; endif; ?> + <?php foreach ($block->getFilters() as $filter) : ?> + <?php if ($filter->getItemsCount()) : ?> + <?php if (!$wrapOptions) : ?> + <strong role="heading" aria-level="2" class="block-subtitle filter-subtitle"> + <?= $block->escapeHtml(__('Shopping Options')) ?> + </strong> + <div class="filter-options" id="narrow-by-list" data-role="content" data-mage-init=' + { + "accordion": + { + "openedState": "active", + "collapsible": true, + "active": false, + "multipleCollapsible": false + } + }'> + <?php $wrapOptions = true; + endif; ?> <div data-role="collapsible" class="filter-options-item"> - <div data-role="title" class="filter-options-title"><?= /* @escapeNotVerified */ __($filter->getName()) ?></div> - <div data-role="content" class="filter-options-content"><?= /* @escapeNotVerified */ $block->getChildBlock('renderer')->render($filter) ?></div> + <div data-role="title" class="filter-options-title"> + <?= $block->escapeHtml(__($filter->getName())) ?> + </div> + <div data-role="content" class="filter-options-content"> + <?= /* @noEscape */ $block->getChildBlock('renderer')->render($filter) ?> + </div> </div> <?php endif; ?> <?php endforeach; ?> - <?php if ($wrapOptions): ?> + <?php if ($wrapOptions) : ?> </div> - <?php else: ?> + <?php else : ?> <script> require([ 'jquery' From 2001743fa8b058586aa208020907895f995683ea Mon Sep 17 00:00:00 2001 From: Viktor Tymchynskyi <vtymchynskyi@magento.com> Date: Mon, 8 Jul 2019 20:00:14 -0500 Subject: [PATCH 633/773] MC-17236: Chinese locale code mismatch with PayPal - Added mapping Chinese locale for PayPal Express and Braintree PayPal --- .../Braintree/Model/LocaleResolver.php | 17 ++- .../Test/Unit/Model/LocaleResolverTest.php | 34 ++++-- app/code/Magento/Paypal/Model/Config.php | 1 + .../Paypal/Model/Express/LocaleResolver.php | 112 ++++++++++++++++++ .../Unit/Model/Express/LocaleResolverTest.php | 74 ++++++++++++ app/code/Magento/Paypal/etc/config.xml | 1 + app/code/Magento/Paypal/etc/frontend/di.xml | 6 + 7 files changed, 235 insertions(+), 10 deletions(-) create mode 100644 app/code/Magento/Paypal/Model/Express/LocaleResolver.php create mode 100644 app/code/Magento/Paypal/Test/Unit/Model/Express/LocaleResolverTest.php diff --git a/app/code/Magento/Braintree/Model/LocaleResolver.php b/app/code/Magento/Braintree/Model/LocaleResolver.php index cebd90dffc70e..47fc7b2acf41e 100644 --- a/app/code/Magento/Braintree/Model/LocaleResolver.php +++ b/app/code/Magento/Braintree/Model/LocaleResolver.php @@ -8,6 +8,9 @@ use Magento\Framework\Locale\ResolverInterface; use Magento\Braintree\Gateway\Config\PayPal\Config; +/** + * Resolves locale for PayPal Express. + */ class LocaleResolver implements ResolverInterface { /** @@ -20,6 +23,17 @@ class LocaleResolver implements ResolverInterface */ private $config; + /** + * Mapping Magento locales on PayPal locales. + * + * @var array + */ + private $localeMap = [ + 'zh_Hans_CN' => 'zh_CN', + 'zh_Hant_HK' => 'zh_HK', + 'zh_Hant_TW' => 'zh_TW' + ]; + /** * @param ResolverInterface $resolver * @param Config $config @@ -66,10 +80,11 @@ public function setLocale($locale = null) * Gets store's locale or the `en_US` locale if store's locale does not supported by PayPal. * * @return string + * @see https://braintree.github.io/braintree-web/current/PayPalCheckout.html#createPayment */ public function getLocale() { - $locale = $this->resolver->getLocale(); + $locale = $this->localeMap[$this->resolver->getLocale()] ?? $this->resolver->getLocale(); $allowedLocales = $this->config->getValue('supported_locales'); return strpos($allowedLocales, $locale) !== false ? $locale : 'en_US'; diff --git a/app/code/Magento/Braintree/Test/Unit/Model/LocaleResolverTest.php b/app/code/Magento/Braintree/Test/Unit/Model/LocaleResolverTest.php index b6ef534c55c29..f80b630766407 100644 --- a/app/code/Magento/Braintree/Test/Unit/Model/LocaleResolverTest.php +++ b/app/code/Magento/Braintree/Test/Unit/Model/LocaleResolverTest.php @@ -98,19 +98,35 @@ public function testSetLocale() /** * Test getLocale method * - * @return void + * @param string $locale + * @param string $expectedLocale + * @dataProvider getLocaleDataProvider */ - public function testGetLocale() + public function testGetLocale(string $locale, string $expectedLocale) { - $locale = 'en_TEST'; - $allowedLocales = 'en_US,en_GB,en_AU,da_DK,fr_FR,fr_CA,de_DE,zh_HK,it_IT,nl_NL'; - $this->resolverMock->expects($this->once())->method('getLocale')->willReturn($locale); - $this->configMock->expects($this->once())->method('getValue')->with('supported_locales') + $allowedLocales = 'en_US,en_GB,en_AU,da_DK,fr_FR,fr_CA,de_DE,zh_HK,it_IT,zh_CN,zh_TW,nl_NL'; + $this->resolverMock->method('getLocale') + ->willReturn($locale); + $this->configMock->method('getValue') + ->with('supported_locales') ->willReturn($allowedLocales); - - $expected = 'en_US'; $actual = $this->localeResolver->getLocale(); - self::assertEquals($expected, $actual); + + self::assertEquals($expectedLocale, $actual); + } + + /** + * @return array + */ + public function getLocaleDataProvider(): array + { + return [ + ['locale' => 'zh_Hans_CN', 'expectedLocale' => 'zh_CN'], + ['locale' => 'zh_Hant_HK', 'expectedLocale' => 'zh_HK'], + ['locale' => 'zh_Hant_TW', 'expectedLocale' => 'zh_TW'], + ['locale' => 'fr_FR', 'expectedLocale' => 'fr_FR'], + ['locale' => 'unknown', 'expectedLocale' => 'en_US'], + ]; } /** diff --git a/app/code/Magento/Paypal/Model/Config.php b/app/code/Magento/Paypal/Model/Config.php index 9891f68bf8741..e197218752bf5 100644 --- a/app/code/Magento/Paypal/Model/Config.php +++ b/app/code/Magento/Paypal/Model/Config.php @@ -1511,6 +1511,7 @@ protected function _mapExpressFieldset($fieldName) case 'allow_ba_signup': case 'in_context': case 'merchant_id': + case 'supported_locales': return "payment/{$this->_methodCode}/{$fieldName}"; default: return $this->_mapMethodFieldset($fieldName); diff --git a/app/code/Magento/Paypal/Model/Express/LocaleResolver.php b/app/code/Magento/Paypal/Model/Express/LocaleResolver.php new file mode 100644 index 0000000000000..c9136d03036d2 --- /dev/null +++ b/app/code/Magento/Paypal/Model/Express/LocaleResolver.php @@ -0,0 +1,112 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Paypal\Model\Express; + +use Magento\Framework\Locale\ResolverInterface; +use Magento\Paypal\Model\ConfigFactory; +use Magento\Paypal\Model\Config; + +/** + * Resolves locale for PayPal Express. + */ +class LocaleResolver implements ResolverInterface +{ + /** + * @var ResolverInterface + */ + private $resolver; + + /** + * @var Config + */ + private $config; + + /** + * Mapping Magento locales on PayPal locales. + * + * @var array + */ + private $localeMap = [ + 'zh_Hans_CN' => 'zh_CN', + 'zh_Hant_HK' => 'zh_HK', + 'zh_Hant_TW' => 'zh_TW' + ]; + + /** + * @param ResolverInterface $resolver + * @param ConfigFactory $configFactory + */ + public function __construct(ResolverInterface $resolver, ConfigFactory $configFactory) + { + $this->resolver = $resolver; + $this->config = $configFactory->create(); + $this->config->setMethod(Config::METHOD_EXPRESS); + } + + /** + * @inheritdoc + */ + public function getDefaultLocalePath() + { + return $this->resolver->getDefaultLocalePath(); + } + + /** + * @inheritdoc + */ + public function setDefaultLocale($locale) + { + return $this->resolver->setDefaultLocale($locale); + } + + /** + * @inheritdoc + */ + public function getDefaultLocale() + { + return $this->resolver->getDefaultLocale(); + } + + /** + * @inheritdoc + */ + public function setLocale($locale = null) + { + return $this->resolver->setLocale($locale); + } + + /** + * Gets store's locale or the `en_US` locale if store's locale does not supported by PayPal. + * + * @return string + * @see https://developer.paypal.com/docs/api/reference/locale-codes/#supported-locale-codes + */ + public function getLocale(): string + { + $locale = $this->localeMap[$this->resolver->getLocale()] ?? $this->resolver->getLocale(); + $allowedLocales = $this->config->getValue('supported_locales'); + + return strpos($allowedLocales, $locale) !== false ? $locale : 'en_US'; + } + + /** + * @inheritdoc + */ + public function emulate($scopeId) + { + return $this->resolver->emulate($scopeId); + } + + /** + * @inheritdoc + */ + public function revert() + { + return $this->resolver->revert(); + } +} diff --git a/app/code/Magento/Paypal/Test/Unit/Model/Express/LocaleResolverTest.php b/app/code/Magento/Paypal/Test/Unit/Model/Express/LocaleResolverTest.php new file mode 100644 index 0000000000000..b9e2c959b4f7d --- /dev/null +++ b/app/code/Magento/Paypal/Test/Unit/Model/Express/LocaleResolverTest.php @@ -0,0 +1,74 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Paypal\Test\Unit\Model\Express; + +use Magento\Framework\Locale\ResolverInterface; +use Magento\Paypal\Model\Config; +use Magento\Paypal\Model\ConfigFactory; +use Magento\Paypal\Model\Express\LocaleResolver as ExpressLocaleResolver; + +/** + * Class LocaleResolverTest + */ +class LocaleResolverTest extends \PHPUnit\Framework\TestCase +{ + /** + * @var \PHPUnit_Framework_MockObject_MockObject|ResolverInterface + */ + private $resolver; + + /** + * @var ExpressLocaleResolver + */ + private $model; + + protected function setUp() + { + $this->resolver = $this->createMock(ResolverInterface::class); + /** @var Config $config */ + $config = $this->createMock(Config::class); + $config->method('getValue') + ->with('supported_locales') + ->willReturn('zh_CN,zh_HK,zh_TW,fr_FR'); + + /** @var ConfigFactory $configFactory */ + $configFactory = $this->createPartialMock(ConfigFactory::class, ['create']); + $configFactory->method('create')->willReturn($config); + + $this->model = new ExpressLocaleResolver($this->resolver, $configFactory); + } + + /** + * Tests retrieving locales for PayPal Express. + * + * @param string $locale + * @param string $expectedLocale + * @dataProvider getLocaleDataProvider + */ + public function testGetLocale(string $locale, string $expectedLocale) + { + $this->resolver->method('getLocale') + ->willReturn($locale); + + $this->assertEquals($expectedLocale, $this->model->getLocale()); + } + + /** + * @return array + */ + public function getLocaleDataProvider(): array + { + return [ + ['locale' => 'zh_Hans_CN', 'expectedLocale' => 'zh_CN'], + ['locale' => 'zh_Hant_HK', 'expectedLocale' => 'zh_HK'], + ['locale' => 'zh_Hant_TW', 'expectedLocale' => 'zh_TW'], + ['locale' => 'fr_FR', 'expectedLocale' => 'fr_FR'], + ['locale' => 'unknown', 'expectedLocale' => 'en_US'], + ]; + } +} diff --git a/app/code/Magento/Paypal/etc/config.xml b/app/code/Magento/Paypal/etc/config.xml index 1880417af1b48..d2b6df0cf9e2e 100644 --- a/app/code/Magento/Paypal/etc/config.xml +++ b/app/code/Magento/Paypal/etc/config.xml @@ -68,6 +68,7 @@ <child_authorization_number>1</child_authorization_number> <verify_peer>1</verify_peer> <skip_order_review_step>1</skip_order_review_step> + <supported_locales>ar_EG,cs_CZ,da_DK,de_DE,el_GR,en_AU,en_GB,en_IN,en_US,es_ES,es_XC,fi_FI,fr_CA,fr_FR,fr_XC,he_IL,hu_HU,id_ID,it_IT,ja_JP,ko_KR,nl_NL,no_NO,pl_PL,pt_BR,pt_PT,ru_RU,sk_SK,sv_SE,th_TH,zh_CN,zh_HK,zh_TW,zh_XC</supported_locales> </paypal_express> <paypal_express_bml> <model>Magento\Paypal\Model\Bml</model> diff --git a/app/code/Magento/Paypal/etc/frontend/di.xml b/app/code/Magento/Paypal/etc/frontend/di.xml index 8c29ae1e2685f..858eb21d4e74a 100644 --- a/app/code/Magento/Paypal/etc/frontend/di.xml +++ b/app/code/Magento/Paypal/etc/frontend/di.xml @@ -174,6 +174,12 @@ <item name="0" xsi:type="string">CREDIT</item> </item> </argument> + <argument name="localeResolver" xsi:type="object">Magento\Paypal\Model\Express\LocaleResolver</argument> + </arguments> + </type> + <type name="Magento\Paypal\Block\Express\InContext\Component"> + <arguments> + <argument name="localeResolver" xsi:type="object">Magento\Paypal\Model\Express\LocaleResolver</argument> </arguments> </type> </config> From 14212b18de12eed264a452da8907eb953474505e Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Tue, 9 Jul 2019 16:56:59 +0300 Subject: [PATCH 634/773] magento/magento2#23345: Creditmemo getOrder() method loads order incorrectly. --- .../Magento/Sales/Model/Order/Creditmemo.php | 23 +++++++++++++++---- .../Test/Unit/Model/Order/CreditmemoTest.php | 21 ++++++++--------- 2 files changed, 27 insertions(+), 17 deletions(-) diff --git a/app/code/Magento/Sales/Model/Order/Creditmemo.php b/app/code/Magento/Sales/Model/Order/Creditmemo.php index 708aee5e59261..16a8f7e8f902a 100644 --- a/app/code/Magento/Sales/Model/Order/Creditmemo.php +++ b/app/code/Magento/Sales/Model/Order/Creditmemo.php @@ -7,13 +7,13 @@ namespace Magento\Sales\Model\Order; use Magento\Framework\Api\AttributeValueFactory; +use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\App\ObjectManager; use Magento\Framework\Pricing\PriceCurrencyInterface; use Magento\Sales\Api\Data\CreditmemoInterface; +use Magento\Sales\Api\OrderRepositoryInterface; use Magento\Sales\Model\AbstractModel; use Magento\Sales\Model\EntityInterface; -use Magento\Sales\Model\Order\InvoiceFactory; -use Magento\Framework\App\Config\ScopeConfigInterface; /** * Order creditmemo model @@ -126,6 +126,11 @@ class Creditmemo extends AbstractModel implements EntityInterface, CreditmemoInt */ private $scopeConfig; + /** + * @var OrderRepositoryInterface + */ + private $orderRepository; + /** * @param \Magento\Framework\Model\Context $context * @param \Magento\Framework\Registry $registry @@ -144,6 +149,7 @@ class Creditmemo extends AbstractModel implements EntityInterface, CreditmemoInt * @param array $data * @param InvoiceFactory $invoiceFactory * @param ScopeConfigInterface $scopeConfig + * @param OrderRepositoryInterface $orderRepository * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -163,7 +169,8 @@ public function __construct( \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [], InvoiceFactory $invoiceFactory = null, - ScopeConfigInterface $scopeConfig = null + ScopeConfigInterface $scopeConfig = null, + OrderRepositoryInterface $orderRepository = null ) { $this->_creditmemoConfig = $creditmemoConfig; $this->_orderFactory = $orderFactory; @@ -175,6 +182,7 @@ public function __construct( $this->priceCurrency = $priceCurrency; $this->invoiceFactory = $invoiceFactory ?: ObjectManager::getInstance()->get(InvoiceFactory::class); $this->scopeConfig = $scopeConfig ?: ObjectManager::getInstance()->get(ScopeConfigInterface::class); + $this->orderRepository = $orderRepository ?? ObjectManager::getInstance()->get(OrderRepositoryInterface::class); parent::__construct( $context, $registry, @@ -237,8 +245,11 @@ public function setOrder(\Magento\Sales\Model\Order $order) public function getOrder() { if (!$this->_order instanceof \Magento\Sales\Model\Order) { - $this->_order = $this->_orderFactory->create()->load($this->getOrderId()); + $this->_order = $this->getOrderId() ? + $this->orderRepository->get($this->getOrderId()) : + $this->_orderFactory->create(); } + return $this->_order->setHistoryEntityName($this->entityType); } @@ -449,6 +460,7 @@ public function canVoid() * Retrieve Creditmemo states array * * @return array + * phpcs:disable Magento2.Functions.StaticFunction */ public static function getStates() { @@ -461,11 +473,12 @@ public static function getStates() } return static::$_states; } + // phpcs:enable /** * Retrieve Creditmemo state name by state identifier * - * @param int $stateId + * @param int $stateId * @return \Magento\Framework\Phrase */ public function getStateName($stateId = null) diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/CreditmemoTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/CreditmemoTest.php index 4d8dd00ac65b3..07300968ae06b 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/CreditmemoTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/CreditmemoTest.php @@ -6,6 +6,7 @@ namespace Magento\Sales\Test\Unit\Model\Order; +use Magento\Sales\Api\OrderRepositoryInterface; use Magento\Sales\Model\ResourceModel\OrderFactory; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; use Magento\Sales\Model\ResourceModel\Order\Creditmemo\Item\CollectionFactory; @@ -20,9 +21,9 @@ class CreditmemoTest extends \PHPUnit\Framework\TestCase { /** - * @var OrderFactory |\PHPUnit_Framework_MockObject_MockObject + * @var OrderRepositoryInterface |\PHPUnit_Framework_MockObject_MockObject */ - protected $orderFactory; + protected $orderRepository; /** * @var \Magento\Sales\Model\Order\Creditmemo @@ -41,7 +42,7 @@ class CreditmemoTest extends \PHPUnit\Framework\TestCase protected function setUp() { - $this->orderFactory = $this->createPartialMock(\Magento\Sales\Model\OrderFactory::class, ['create']); + $this->orderRepository = $this->createMock(OrderRepositoryInterface::class); $this->scopeConfigMock = $this->createMock(ScopeConfigInterface::class); $objectManagerHelper = new ObjectManagerHelper($this); @@ -61,7 +62,6 @@ protected function setUp() 'creditmemoConfig' => $this->createMock( \Magento\Sales\Model\Order\Creditmemo\Config::class ), - 'orderFactory' => $this->orderFactory, 'cmItemCollectionFactory' => $this->cmItemCollectionFactoryMock, 'calculatorFactory' => $this->createMock(\Magento\Framework\Math\CalculatorFactory::class), 'storeManager' => $this->createMock(\Magento\Store\Model\StoreManagerInterface::class), @@ -69,7 +69,8 @@ protected function setUp() 'commentCollectionFactory' => $this->createMock( \Magento\Sales\Model\ResourceModel\Order\Creditmemo\Comment\CollectionFactory::class ), - 'scopeConfig' => $this->scopeConfigMock + 'scopeConfig' => $this->scopeConfigMock, + 'orderRepository' => $this->orderRepository, ]; $this->creditmemo = $objectManagerHelper->getObject( \Magento\Sales\Model\Order\Creditmemo::class, @@ -91,14 +92,10 @@ public function testGetOrder() ->method('setHistoryEntityName') ->with($entityName) ->will($this->returnSelf()); - $order->expects($this->atLeastOnce()) - ->method('load') + $this->orderRepository->expects($this->atLeastOnce()) + ->method('get') ->with($orderId) - ->will($this->returnValue($order)); - - $this->orderFactory->expects($this->atLeastOnce()) - ->method('create') - ->will($this->returnValue($order)); + ->willReturn($order); $this->assertEquals($order, $this->creditmemo->getOrder()); } From 7f19de5e80002afe37bf756499453a0c55c39ce5 Mon Sep 17 00:00:00 2001 From: Deepty Thampy <dthampy@adobe.com> Date: Tue, 9 Jul 2019 09:46:56 -0500 Subject: [PATCH 635/773] MC-17875: Refactor GraphQl Integration tests - refactor payment tests --- .../PlaceOrderWithAuthorizeNetTest.php | 36 +++++------------- ...SetAuthorizeNetPaymentMethodOnCartTest.php | 37 +++++++------------ .../Guest/PlaceOrderWithAuthorizeNetTest.php | 37 ++++++------------- ...SetAuthorizeNetPaymentMethodOnCartTest.php | 32 ++++------------ .../PaypalExpressSetPaymentMethodTest.php | 28 ++++++-------- .../Customer/PaypalExpressTokenTest.php | 37 ++++++++----------- .../PlaceOrderWithPayflowLinkTest.php | 1 - .../Customer/PlaceOrderWithPayflowProTest.php | 32 +++++----------- .../Guest/GetPayflowLinkTokenTest.php | 1 - .../PaypalExpressSetPaymentMethodTest.php | 21 +++-------- .../Resolver/Guest/PaypalExpressTokenTest.php | 37 ++++--------------- .../PaypalPayflowProSetPaymentMethodTest.php | 23 +++--------- .../PaypalPayflowProTokenExceptionTest.php | 21 +++-------- .../Guest/PaypalPayflowProTokenTest.php | 29 +++------------ 14 files changed, 106 insertions(+), 266 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/AuthorizenetGraphQl/Model/Resolver/Customer/PlaceOrderWithAuthorizeNetTest.php b/dev/tests/integration/testsuite/Magento/AuthorizenetGraphQl/Model/Resolver/Customer/PlaceOrderWithAuthorizeNetTest.php index 1f9d5574ad3c3..021e4d9db7766 100644 --- a/dev/tests/integration/testsuite/Magento/AuthorizenetGraphQl/Model/Resolver/Customer/PlaceOrderWithAuthorizeNetTest.php +++ b/dev/tests/integration/testsuite/Magento/AuthorizenetGraphQl/Model/Resolver/Customer/PlaceOrderWithAuthorizeNetTest.php @@ -7,12 +7,10 @@ namespace Magento\AuthorizenetGraphQl\Model\Resolver\Customer; -use Magento\Framework\App\Request\Http; use Magento\Framework\Serialize\SerializerInterface; -use Magento\GraphQl\Controller\GraphQl; use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; +use Magento\GraphQl\Service\GraphQlRequest; use Magento\Integration\Api\CustomerTokenServiceInterface; -use Magento\Framework\Webapi\Request; use Magento\TestFramework\Helper\Bootstrap; use Magento\Framework\HTTP\ZendClient; use Magento\Framework\HTTP\ZendClientFactory; @@ -33,8 +31,6 @@ */ class PlaceOrderWithAuthorizeNetTest extends TestCase { - const CONTENT_TYPE = 'application/json'; - /** @var ObjectManager */ private $objectManager; @@ -44,8 +40,8 @@ class PlaceOrderWithAuthorizeNetTest extends TestCase /** @var SerializerInterface */ private $jsonSerializer; - /** @var Http */ - private $request; + /** @var GraphQlRequest */ + private $graphQlRequest; /** @var ZendClient|MockObject|InvocationMocker */ private $clientMock; @@ -63,7 +59,7 @@ protected function setUp() : void { $this->objectManager = Bootstrap::getObjectManager(); $this->jsonSerializer = $this->objectManager->get(SerializerInterface::class); - $this->request = $this->objectManager->get(Http::class); + $this->graphQlRequest = $this->objectManager->create(GraphQlRequest::class); $this->getMaskedQuoteIdByReservedOrderId = $this->objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); $this->customerTokenService = $this->objectManager->get(CustomerTokenServiceInterface::class); $this->clientMock = $this->createMock(ZendClient::class); @@ -126,23 +122,12 @@ public function testDispatchToPlaceOrderWithRegisteredCustomer(): void } } QUERY; - $postData = [ - 'query' => $query, - 'variables' => null, - 'operationName' => null - ]; - $this->request->setPathInfo('/graphql'); - $this->request->setMethod('POST'); - $this->request->setContent($this->jsonSerializer->serialize($postData)); - $customerToken = $this->customerTokenService->createCustomerAccessToken('customer@example.com', 'password'); - $bearerCustomerToken = 'Bearer ' . $customerToken; - $webApiRequest = $this->objectManager->get(Request::class); - $webApiRequest->getHeaders()->addHeaderLine('Content-Type', 'application/json') - ->addHeaderLine('Accept', 'application/json') - ->addHeaderLine('Authorization', $bearerCustomerToken); - $this->request->setHeaders($webApiRequest->getHeaders()); - $graphql = $this->objectManager->get(\Magento\GraphQl\Controller\GraphQl::class); + $customerToken = $this->customerTokenService->createCustomerAccessToken('customer@example.com', 'password'); + $requestHeaders = [ + 'Accept' => 'application/json', + 'Authorization' => 'Bearer ' . $customerToken + ]; // phpcs:ignore Magento2.Security.IncludeFile $expectedRequest = include __DIR__ . '/../../../_files/request_authorize_customer.php'; // phpcs:ignore Magento2.Security.IncludeFile @@ -153,7 +138,7 @@ public function testDispatchToPlaceOrderWithRegisteredCustomer(): void $this->responseMock->method('getBody')->willReturn(json_encode($authorizeResponse)); - $response = $graphql->dispatch($this->request); + $response = $this->graphQlRequest->send($query, [], '', $requestHeaders); $responseData = $this->jsonSerializer->unserialize($response->getContent()); $this->assertArrayNotHasKey('errors', $responseData, 'Response has errors'); @@ -178,6 +163,5 @@ public function testDispatchToPlaceOrderWithRegisteredCustomer(): void protected function tearDown() { $this->objectManager->removeSharedInstance(ZendClientFactory::class); - parent::tearDown(); } } diff --git a/dev/tests/integration/testsuite/Magento/AuthorizenetGraphQl/Model/Resolver/Customer/SetAuthorizeNetPaymentMethodOnCartTest.php b/dev/tests/integration/testsuite/Magento/AuthorizenetGraphQl/Model/Resolver/Customer/SetAuthorizeNetPaymentMethodOnCartTest.php index 4c84bbf0b58aa..27c6eb0455efc 100644 --- a/dev/tests/integration/testsuite/Magento/AuthorizenetGraphQl/Model/Resolver/Customer/SetAuthorizeNetPaymentMethodOnCartTest.php +++ b/dev/tests/integration/testsuite/Magento/AuthorizenetGraphQl/Model/Resolver/Customer/SetAuthorizeNetPaymentMethodOnCartTest.php @@ -7,10 +7,9 @@ namespace Magento\AuthorizenetGraphQl\Model\Resolver\Customer; -use Magento\Framework\App\Request\Http; use Magento\Framework\Serialize\SerializerInterface; -use Magento\Framework\Webapi\Request; use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; +use Magento\GraphQl\Service\GraphQlRequest; use Magento\Integration\Api\CustomerTokenServiceInterface; use Magento\TestFramework\Helper\Bootstrap; use PHPUnit\Framework\TestCase; @@ -24,8 +23,6 @@ */ class SetAuthorizeNetPaymentMethodOnCartTest extends TestCase { - const CONTENT_TYPE = 'application/json'; - /** @var \Magento\Framework\ObjectManagerInterface */ private $objectManager; @@ -38,14 +35,14 @@ class SetAuthorizeNetPaymentMethodOnCartTest extends TestCase /** @var CustomerTokenServiceInterface */ private $customerTokenService; - /** @var Http */ - private $request; + /** @var GraphQlRequest */ + private $graphQlRequest; protected function setUp() : void { $this->objectManager = Bootstrap::getObjectManager(); $this->jsonSerializer = $this->objectManager->get(SerializerInterface::class); - $this->request = $this->objectManager->get(Http::class); + $this->graphQlRequest = $this->objectManager->create(GraphQlRequest::class); $this->getMaskedQuoteIdByReservedOrderId = $this->objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); $this->customerTokenService = $this->objectManager->get(CustomerTokenServiceInterface::class); } @@ -88,24 +85,16 @@ public function testDispatchToSetPaymentMethodWithAuthorizenet(): void } } QUERY; - $postData = [ - 'query' => $query, - 'variables' => null, - 'operationName' => null - ]; - $this->request->setPathInfo('/graphql'); - $this->request->setMethod('POST'); - $this->request->setContent($this->jsonSerializer->serialize($postData)); + $customerToken = $this->customerTokenService->createCustomerAccessToken('customer@example.com', 'password'); - $bearerCustomerToken = 'Bearer ' . $customerToken; - $contentType ='application/json'; - $webApiRequest = $this->objectManager->get(Request::class); - $webApiRequest->getHeaders()->addHeaderLine('Content-Type', $contentType) - ->addHeaderLine('Accept', $contentType) - ->addHeaderLine('Authorization', $bearerCustomerToken); - $this->request->setHeaders($webApiRequest->getHeaders()); - $graphql = $this->objectManager->get(\Magento\GraphQl\Controller\GraphQl::class); - $response = $graphql->dispatch($this->request); + + $requestHeaders = [ + 'Accept' => 'application/json', + 'Authorization' => 'Bearer ' . $customerToken + ]; + + $response = $this->graphQlRequest->send($query, [], '', $requestHeaders); + $output = $this->jsonSerializer->unserialize($response->getContent()); $this->assertArrayNotHasKey('errors', $output, 'Response has errors'); $this->assertArrayHasKey('setPaymentMethodOnCart', $output['data']); diff --git a/dev/tests/integration/testsuite/Magento/AuthorizenetGraphQl/Model/Resolver/Guest/PlaceOrderWithAuthorizeNetTest.php b/dev/tests/integration/testsuite/Magento/AuthorizenetGraphQl/Model/Resolver/Guest/PlaceOrderWithAuthorizeNetTest.php index 1be7069b90cda..0b5f3ca32ad29 100644 --- a/dev/tests/integration/testsuite/Magento/AuthorizenetGraphQl/Model/Resolver/Guest/PlaceOrderWithAuthorizeNetTest.php +++ b/dev/tests/integration/testsuite/Magento/AuthorizenetGraphQl/Model/Resolver/Guest/PlaceOrderWithAuthorizeNetTest.php @@ -9,8 +9,8 @@ use Magento\Framework\App\Request\Http; use Magento\Framework\Serialize\SerializerInterface; -use Magento\GraphQl\Controller\GraphQl; use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; +use Magento\GraphQl\Service\GraphQlRequest; use Magento\TestFramework\Helper\Bootstrap; use Magento\Framework\HTTP\ZendClient; use Magento\Framework\HTTP\ZendClientFactory; @@ -31,22 +31,17 @@ */ class PlaceOrderWithAuthorizeNetTest extends TestCase { - const CONTENT_TYPE = 'application/json'; - /** @var ObjectManager */ private $objectManager; /** @var GetMaskedQuoteIdByReservedOrderId */ private $getMaskedQuoteIdByReservedOrderId; - /** @var GraphQl */ - private $graphql; - /** @var SerializerInterface */ private $jsonSerializer; - /** @var Http */ - private $request; + /** @var GraphQlRequest */ + private $graphQlRequest; /** @var ZendClient|MockObject|InvocationMocker */ private $clientMock; @@ -64,6 +59,7 @@ protected function setUp() : void $this->jsonSerializer = $this->objectManager->get(SerializerInterface::class); $this->request = $this->objectManager->get(Http::class); $this->getMaskedQuoteIdByReservedOrderId = $this->objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); + $this->graphQlRequest = $this->objectManager->create(GraphQlRequest::class); $this->clientMock = $this->createMock(ZendClient::class); $this->responseMock = $this->createMock(Zend_Http_Response::class); $this->clientMock->method('request') @@ -78,6 +74,11 @@ protected function setUp() : void $this->objectManager->addSharedInstance($clientFactoryMock, ZendClientFactory::class); } + protected function tearDown() + { + $this->objectManager->removeSharedInstance(ZendClientFactory::class); + } + /** * @magentoConfigFixture default_store payment/authorizenet_acceptjs/active 1 * @magentoConfigFixture default_store payment/authorizenet_acceptjs/environment sandbox @@ -124,17 +125,7 @@ public function testDispatchToPlaceAnOrderWithAuthorizenet(): void } } QUERY; - $postData = [ - 'query' => $query, - 'variables' => null, - 'operationName' => null - ]; - $this->request->setPathInfo('/graphql'); - $this->request->setMethod('POST'); - $this->request->setContent(json_encode($postData)); - $headers = $this->objectManager->create(\Zend\Http\Headers::class) - ->addHeaders(['Content-Type' => 'application/json']); - $this->request->setHeaders($headers); + // phpcs:ignore Magento2.Security.IncludeFile $expectedRequest = include __DIR__ . '/../../../_files/request_authorize.php'; // phpcs:ignore Magento2.Security.IncludeFile @@ -145,7 +136,7 @@ public function testDispatchToPlaceAnOrderWithAuthorizenet(): void $this->responseMock->method('getBody')->willReturn(json_encode($authorizeResponse)); - $response = $this->graphql->dispatch($this->request); + $response = $this->graphQlRequest->send($query); $responseData = $this->jsonSerializer->unserialize($response->getContent()); $this->assertArrayNotHasKey('errors', $responseData, 'Response has errors'); @@ -166,10 +157,4 @@ public function testDispatchToPlaceAnOrderWithAuthorizenet(): void $responseData['data']['placeOrder']['order']['order_id'] ); } - - protected function tearDown() - { - $this->objectManager->removeSharedInstance(ZendClientFactory::class); - parent::tearDown(); - } } diff --git a/dev/tests/integration/testsuite/Magento/AuthorizenetGraphQl/Model/Resolver/Guest/SetAuthorizeNetPaymentMethodOnCartTest.php b/dev/tests/integration/testsuite/Magento/AuthorizenetGraphQl/Model/Resolver/Guest/SetAuthorizeNetPaymentMethodOnCartTest.php index ba63861086b1d..1386e3b1980ac 100644 --- a/dev/tests/integration/testsuite/Magento/AuthorizenetGraphQl/Model/Resolver/Guest/SetAuthorizeNetPaymentMethodOnCartTest.php +++ b/dev/tests/integration/testsuite/Magento/AuthorizenetGraphQl/Model/Resolver/Guest/SetAuthorizeNetPaymentMethodOnCartTest.php @@ -7,11 +7,11 @@ namespace Magento\AuthorizenetGraphQl\Model\Resolver\Guest; -use Magento\Framework\App\Request\Http; use Magento\Framework\Serialize\SerializerInterface; -use Magento\GraphQl\Controller\GraphQl; use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; +use Magento\GraphQl\Service\GraphQlRequest; use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\ObjectManager; use PHPUnit\Framework\TestCase; /** @@ -23,30 +23,24 @@ */ class SetAuthorizeNetPaymentMethodOnCartTest extends TestCase { - const CONTENT_TYPE = 'application/json'; - - /** @var \Magento\Framework\ObjectManagerInterface */ + /** @var ObjectManager */ private $objectManager; /** @var GetMaskedQuoteIdByReservedOrderId */ private $getMaskedQuoteIdByReservedOrderId; - /** @var GraphQl */ - private $graphql; - /** @var SerializerInterface */ private $jsonSerializer; - /** @var Http */ - private $request; + /** @var GraphQlRequest */ + private $graphQlRequest; protected function setUp() : void { $this->objectManager = Bootstrap::getObjectManager(); - $this->graphql = $this->objectManager->get(\Magento\GraphQl\Controller\GraphQl::class); $this->jsonSerializer = $this->objectManager->get(SerializerInterface::class); - $this->request = $this->objectManager->get(Http::class); $this->getMaskedQuoteIdByReservedOrderId = $this->objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); + $this->graphQlRequest = $this->objectManager->create(GraphQlRequest::class); } /** @@ -86,18 +80,8 @@ public function testDispatchToSetPaymentMethodWithAuthorizenet(): void } } QUERY; - $postData = [ - 'query' => $query, - 'variables' => null, - 'operationName' => null - ]; - $this->request->setPathInfo('/graphql'); - $this->request->setMethod('POST'); - $this->request->setContent(json_encode($postData)); - $headers = $this->objectManager->create(\Zend\Http\Headers::class) - ->addHeaders(['Content-Type' => 'application/json']); - $this->request->setHeaders($headers); - $response = $this->graphql->dispatch($this->request); + + $response = $this->graphQlRequest->send($query); $output = $this->jsonSerializer->unserialize($response->getContent()); $this->assertArrayNotHasKey('errors', $output, 'Response has errors'); $this->assertArrayHasKey('setPaymentMethodOnCart', $output['data']); diff --git a/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Customer/PaypalExpressSetPaymentMethodTest.php b/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Customer/PaypalExpressSetPaymentMethodTest.php index f135a35d1f41b..4c956dfb06149 100644 --- a/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Customer/PaypalExpressSetPaymentMethodTest.php +++ b/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Customer/PaypalExpressSetPaymentMethodTest.php @@ -7,8 +7,7 @@ namespace Magento\PaypalGraphQl\Model\Resolver\Customer; -use Magento\Framework\App\Request\Http; -use Magento\Framework\Webapi\Request; +use Magento\GraphQl\Service\GraphQlRequest; use Magento\Paypal\Model\Api\Nvp; use Magento\PaypalGraphQl\PaypalExpressAbstractTest; use Magento\Framework\Serialize\SerializerInterface; @@ -23,9 +22,9 @@ class PaypalExpressSetPaymentMethodTest extends PaypalExpressAbstractTest { /** - * @var Http + * @var GraphQlRequest */ - private $request; + private $graphQlRequest; /** * @var SerializerInterface @@ -41,9 +40,9 @@ protected function setUp() { parent::setUp(); - $this->request = $this->objectManager->create(Http::class); $this->json = $this->objectManager->get(SerializerInterface::class); $this->quoteIdToMaskedId = $this->objectManager->get(QuoteIdToMaskedQuoteId::class); + $this->graphQlRequest = $this->objectManager->create(GraphQlRequest::class); } /** @@ -53,6 +52,7 @@ protected function setUp() * @return void * @dataProvider getPaypalCodesProvider * @magentoConfigFixture default_store paypal/wpp/sandbox_flag 1 + * @magentoDataFixture Magento/Sales/_files/default_rollback.php * @magentoDataFixture Magento/Customer/_files/customer.php * @magentoDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php @@ -132,21 +132,15 @@ public function testResolve(string $paymentMethod): void } QUERY; - $postData = $this->json->serialize(['query' => $query]); - $this->request->setPathInfo('/graphql'); - $this->request->setMethod('POST'); - $this->request->setContent($postData); - /** @var \Magento\Integration\Model\Oauth\Token $tokenModel */ $tokenModel = $this->objectManager->create(\Magento\Integration\Model\Oauth\Token::class); $customerToken = $tokenModel->createCustomerToken(1)->getToken(); - $webApiRequest = $this->objectManager->get(Request::class); - $webApiRequest->getHeaders() - ->addHeaderLine('Content-Type', 'application/json') - ->addHeaderLine('Accept', 'application/json') - ->addHeaderLine('Authorization', 'Bearer ' . $customerToken); - $this->request->setHeaders($webApiRequest->getHeaders()); + $requestHeaders = [ + 'Content-Type' => 'application/json', + 'Accept' => 'application/json', + 'Authorization' => 'Bearer ' . $customerToken + ]; $paypalRequest = include __DIR__ . '/../../../_files/customer_paypal_create_token_request.php'; $paypalResponse = [ @@ -204,7 +198,7 @@ public function testResolve(string $paymentMethod): void ] ); - $response = $this->graphqlController->dispatch($this->request); + $response = $this->graphQlRequest->send($query, [], '', $requestHeaders); $responseData = $this->json->unserialize($response->getContent()); $this->assertArrayHasKey('data', $responseData); diff --git a/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Customer/PaypalExpressTokenTest.php b/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Customer/PaypalExpressTokenTest.php index a952bcaf1cf61..3298d2524bc09 100644 --- a/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Customer/PaypalExpressTokenTest.php +++ b/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Customer/PaypalExpressTokenTest.php @@ -7,8 +7,7 @@ namespace Magento\PaypalGraphQl\Model\Resolver\Customer; -use Magento\Framework\App\Request\Http; -use Magento\Framework\Webapi\Request; +use Magento\GraphQl\Service\GraphQlRequest; use Magento\Paypal\Model\Api\Nvp; use Magento\PaypalGraphQl\PaypalExpressAbstractTest; use Magento\Framework\Serialize\SerializerInterface; @@ -22,9 +21,9 @@ class PaypalExpressTokenTest extends PaypalExpressAbstractTest { /** - * @var Http + * @var GraphQlRequest */ - private $request; + private $graphQlRequest; /** * @var SerializerInterface @@ -40,9 +39,9 @@ protected function setUp() { parent::setUp(); - $this->request = $this->objectManager->create(Http::class); $this->json = $this->objectManager->get(SerializerInterface::class); $this->quoteIdToMaskedId = $this->objectManager->get(QuoteIdToMaskedQuoteId::class); + $this->graphQlRequest = $this->objectManager->create(GraphQlRequest::class); } /** @@ -51,6 +50,7 @@ protected function setUp() * @param string $paymentMethod * @dataProvider getPaypalCodesProvider * @magentoConfigFixture default_store paypal/wpp/sandbox_flag 1 + * @magentoDataFixture Magento/Sales/_files/default_rollback.php * @magentoDataFixture Magento/Customer/_files/customer.php * @magentoDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php @@ -73,22 +73,6 @@ public function testResolve($paymentMethod): void $query = $this->getCreateTokenMutation($maskedCartId, $paymentMethod); - $postData = $this->json->serialize(['query' => $query]); - $this->request->setPathInfo('/graphql'); - $this->request->setMethod('POST'); - $this->request->setContent($postData); - - /** @var \Magento\Integration\Model\Oauth\Token $tokenModel */ - $tokenModel = $this->objectManager->create(\Magento\Integration\Model\Oauth\Token::class); - $customerToken = $tokenModel->createCustomerToken(1)->getToken(); - - $webApiRequest = $this->objectManager->get(Request::class); - $webApiRequest->getHeaders() - ->addHeaderLine('Content-Type', 'application/json') - ->addHeaderLine('Accept', 'application/json') - ->addHeaderLine('Authorization', 'Bearer ' . $customerToken); - $this->request->setHeaders($webApiRequest->getHeaders()); - $paypalRequest = include __DIR__ . '/../../../_files/customer_paypal_create_token_request.php'; if ($paymentMethod == 'payflow_express') { $paypalRequest['SOLUTIONTYPE'] = null; @@ -106,7 +90,16 @@ public function testResolve($paymentMethod): void ->with(Nvp::SET_EXPRESS_CHECKOUT, $paypalRequest) ->willReturn($paypalResponse); - $response = $this->graphqlController->dispatch($this->request); + /** @var \Magento\Integration\Model\Oauth\Token $tokenModel */ + $tokenModel = $this->objectManager->create(\Magento\Integration\Model\Oauth\Token::class); + $customerToken = $tokenModel->createCustomerToken(1)->getToken(); + + $requestHeaders = [ + 'Accept' => 'application/json', + 'Authorization' => 'Bearer ' . $customerToken + ]; + + $response = $this->graphQlRequest->send($query, [], '', $requestHeaders); $responseData = $this->json->unserialize($response->getContent()); $createTokenData = $responseData['data']['createPaypalExpressToken']; $this->assertArrayNotHasKey('errors', $responseData); diff --git a/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Customer/PlaceOrderWithPayflowLinkTest.php b/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Customer/PlaceOrderWithPayflowLinkTest.php index 7eb809b13d7d3..b5d2aeb0803a5 100644 --- a/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Customer/PlaceOrderWithPayflowLinkTest.php +++ b/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Customer/PlaceOrderWithPayflowLinkTest.php @@ -185,7 +185,6 @@ public function testResolvePlaceOrderWithPayflowLinkForCustomer(): void $customerToken = $tokenModel->createCustomerToken(1)->getToken(); $requestHeaders = [ - 'Content-Type' => 'application/json', 'Accept' => 'application/json', 'Authorization' => 'Bearer ' . $customerToken ]; diff --git a/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Customer/PlaceOrderWithPayflowProTest.php b/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Customer/PlaceOrderWithPayflowProTest.php index e692aeece5033..30054dcf712b6 100644 --- a/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Customer/PlaceOrderWithPayflowProTest.php +++ b/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Customer/PlaceOrderWithPayflowProTest.php @@ -7,14 +7,12 @@ namespace Magento\PaypalGraphQl\Model\Resolver\Customer; -use Magento\Framework\App\Request\Http; +use Magento\GraphQl\Service\GraphQlRequest; use Magento\PaypalGraphQl\PaypalPayflowProAbstractTest; use Magento\Framework\Serialize\SerializerInterface; use Magento\Quote\Model\QuoteIdToMaskedQuoteId; -use Magento\TestFramework\Helper\Bootstrap; use Magento\Framework\UrlInterface; use Magento\Framework\DataObject; -use Magento\Framework\Webapi\Request; /** * End to end place order test using payflowpro via graphql endpoint for customer @@ -24,9 +22,9 @@ class PlaceOrderWithPayflowProTest extends PaypalPayflowProAbstractTest { /** - * @var Http + * @var GraphQlRequest */ - private $request; + private $graphQlRequest; /** * @var SerializerInterface @@ -42,13 +40,9 @@ protected function setUp() { parent::setUp(); - $this->request = $this->objectManager->create(Http::class); $this->json = $this->objectManager->get(SerializerInterface::class); $this->quoteIdToMaskedId = $this->objectManager->get(QuoteIdToMaskedQuoteId::class); - - $this->objectManager = Bootstrap::getObjectManager(); - $this->graphqlController = $this->objectManager->get(\Magento\GraphQl\Controller\GraphQl::class); - $this->request = $this->objectManager->create(Http::class); + $this->graphQlRequest = $this->objectManager->create(GraphQlRequest::class); } /** @@ -146,22 +140,16 @@ public function testResolveCustomer(): void } QUERY; - $postData = $this->json->serialize(['query' => $query]); - $this->request->setPathInfo('/graphql'); - $this->request->setMethod('POST'); - $this->request->setContent($postData); /** @var \Magento\Integration\Model\Oauth\Token $tokenModel */ $tokenModel = $this->objectManager->create(\Magento\Integration\Model\Oauth\Token::class); $customerToken = $tokenModel->createCustomerToken(1)->getToken(); - $webApiRequest = $this->objectManager->get(Request::class); - $webApiRequest->getHeaders() - ->addHeaderLine('Content-Type', 'application/json') - ->addHeaderLine('Accept', 'application/json') - ->addHeaderLine('Authorization', 'Bearer ' . $customerToken); - $this->request->setHeaders($webApiRequest->getHeaders()); - + $requestHeaders = [ + 'Content-Type' => 'application/json', + 'Accept' => 'application/json', + 'Authorization' => 'Bearer ' . $customerToken + ]; $paypalResponse = new DataObject( [ 'result' => '0', @@ -205,7 +193,7 @@ public function testResolveCustomer(): void ) ); - $response = $this->graphqlController->dispatch($this->request); + $response = $this->graphQlRequest->send($query, [], '', $requestHeaders); $responseData = $this->json->unserialize($response->getContent()); $this->assertArrayHasKey('data', $responseData); diff --git a/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/GetPayflowLinkTokenTest.php b/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/GetPayflowLinkTokenTest.php index 65dd9ea734562..662beab7a3659 100644 --- a/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/GetPayflowLinkTokenTest.php +++ b/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/GetPayflowLinkTokenTest.php @@ -10,7 +10,6 @@ use Magento\Framework\Serialize\SerializerInterface; use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; use Magento\GraphQl\Service\GraphQlRequest; -use Magento\Paypal\Model\Payflow\Service\Gateway; use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\ObjectManager; use PHPUnit\Framework\TestCase; diff --git a/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/PaypalExpressSetPaymentMethodTest.php b/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/PaypalExpressSetPaymentMethodTest.php index 86b2350925b28..ec5883579f6a2 100644 --- a/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/PaypalExpressSetPaymentMethodTest.php +++ b/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/PaypalExpressSetPaymentMethodTest.php @@ -8,6 +8,7 @@ namespace Magento\PaypalGraphQl\Model\Resolver\Guest; use Magento\Framework\App\Request\Http; +use Magento\GraphQl\Service\GraphQlRequest; use Magento\Paypal\Model\Api\Nvp; use Magento\PaypalGraphQl\PaypalExpressAbstractTest; use Magento\Framework\Serialize\SerializerInterface; @@ -23,9 +24,9 @@ class PaypalExpressSetPaymentMethodTest extends PaypalExpressAbstractTest { /** - * @var Http + * @var GraphQlRequest */ - private $request; + private $graphQlRequest; /** * @var SerializerInterface @@ -41,13 +42,9 @@ protected function setUp() { parent::setUp(); - $this->request = $this->objectManager->create(Http::class); $this->json = $this->objectManager->get(SerializerInterface::class); $this->quoteIdToMaskedId = $this->objectManager->get(QuoteIdToMaskedQuoteId::class); - - $this->objectManager = Bootstrap::getObjectManager(); - $this->graphqlController = $this->objectManager->get(\Magento\GraphQl\Controller\GraphQl::class); - $this->request = $this->objectManager->create(Http::class); + $this->graphQlRequest = $this->objectManager->create(GraphQlRequest::class); } /** @@ -134,14 +131,6 @@ public function testResolveGuest(string $paymentMethod): void } QUERY; - $postData = $this->json->serialize(['query' => $query]); - $this->request->setPathInfo('/graphql'); - $this->request->setMethod('POST'); - $this->request->setContent($postData); - $headers = $this->objectManager->create(\Zend\Http\Headers::class) - ->addHeaders(['Content-Type' => 'application/json']); - $this->request->setHeaders($headers); - $paypalRequest = include __DIR__ . '/../../../_files/guest_paypal_create_token_request.php'; $paypalResponse = [ 'TOKEN' => $token, @@ -196,7 +185,7 @@ public function testResolveGuest(string $paymentMethod): void ] ); - $response = $this->graphqlController->dispatch($this->request); + $response = $this->graphQlRequest->send($query); $responseData = $this->json->unserialize($response->getContent()); $this->assertArrayHasKey('data', $responseData); diff --git a/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/PaypalExpressTokenTest.php b/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/PaypalExpressTokenTest.php index 99dc25fc12032..a9c70f97d3530 100644 --- a/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/PaypalExpressTokenTest.php +++ b/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/PaypalExpressTokenTest.php @@ -7,9 +7,9 @@ namespace Magento\PaypalGraphQl\Model\Resolver\Guest; -use Magento\Framework\App\Request\Http; use Magento\Framework\Exception\LocalizedException; use Magento\Framework\GraphQl\Exception\GraphQlInputException; +use Magento\GraphQl\Service\GraphQlRequest; use Magento\Paypal\Model\Api\Nvp; use Magento\PaypalGraphQl\PaypalExpressAbstractTest; use Magento\Framework\Serialize\SerializerInterface; @@ -23,9 +23,9 @@ class PaypalExpressTokenTest extends PaypalExpressAbstractTest { /** - * @var Http + * @var GraphQlRequest */ - private $request; + private $graphQlRequest; /** * @var SerializerInterface @@ -41,9 +41,9 @@ protected function setUp() { parent::setUp(); - $this->request = $this->objectManager->create(Http::class); $this->json = $this->objectManager->get(SerializerInterface::class); $this->quoteIdToMaskedId = $this->objectManager->get(QuoteIdToMaskedQuoteId::class); + $this->graphQlRequest = $this->objectManager->create(GraphQlRequest::class); } /** @@ -72,14 +72,6 @@ public function testResolve($paymentMethod): void $cartId = $this->quoteIdToMaskedId->execute((int)$cart->getId()); $query = $this->getCreateTokenMutation($cartId, $paymentMethod); - $postData = $this->json->serialize(['query' => $query]); - $this->request->setPathInfo('/graphql'); - $this->request->setMethod('POST'); - $this->request->setContent($postData); - $headers = $this->objectManager->create(\Zend\Http\Headers::class) - ->addHeaders(['Content-Type' => 'application/json']); - $this->request->setHeaders($headers); - $paypalRequest = include __DIR__ . '/../../../_files/guest_paypal_create_token_request.php'; if ($paymentMethod == 'payflow_express') { $paypalRequest['SOLUTIONTYPE'] = null; @@ -96,7 +88,7 @@ public function testResolve($paymentMethod): void ->with(Nvp::SET_EXPRESS_CHECKOUT, $paypalRequest) ->willReturn($paypalResponse); - $response = $this->graphqlController->dispatch($this->request); + $response = $this->graphQlRequest->send($query); $responseData = $this->json->unserialize($response->getContent()); $createTokenData = $responseData['data']['createPaypalExpressToken']; @@ -131,14 +123,6 @@ public function testResolveWithPaypalError($paymentMethod): void $cartId = $this->quoteIdToMaskedId->execute((int)$cart->getId()); $query = $this->getCreateTokenMutation($cartId, $paymentMethod); - $postData = $this->json->serialize(['query' => $query]); - $this->request->setPathInfo('/graphql'); - $this->request->setMethod('POST'); - $this->request->setContent($postData); - $headers = $this->objectManager->create(\Zend\Http\Headers::class) - ->addHeaders(['Content-Type' => 'application/json']); - $this->request->setHeaders($headers); - $paypalRequest = include __DIR__ . '/../../../_files/guest_paypal_create_token_request.php'; if ($paymentMethod == 'payflow_express') { $paypalRequest['SOLUTIONTYPE'] = null; @@ -152,7 +136,7 @@ public function testResolveWithPaypalError($paymentMethod): void ->with(Nvp::SET_EXPRESS_CHECKOUT, $paypalRequest) ->willThrowException($expectedException); - $response = $this->graphqlController->dispatch($this->request); + $response = $this->graphQlRequest->send($query); $responseData = $this->json->unserialize($response->getContent()); $this->assertArrayHasKey('createPaypalExpressToken', $responseData['data']); $this->assertEmpty($responseData['data']['createPaypalExpressToken']); @@ -199,17 +183,10 @@ public function testResolveWithInvalidRedirectUrl(): void } QUERY; - $postData = $this->json->serialize(['query' => $query]); - $this->request->setPathInfo('/graphql'); - $this->request->setMethod('POST'); - $this->request->setContent($postData); - $headers = $this->objectManager->create(\Zend\Http\Headers::class) - ->addHeaders(['Content-Type' => 'application/json']); - $this->request->setHeaders($headers); $expectedExceptionMessage = "Invalid URL 'not/a/url'."; - $response = $this->graphqlController->dispatch($this->request); + $response = $this->graphQlRequest->send($query); $responseData = $this->json->unserialize($response->getContent()); $this->assertArrayHasKey('errors', $responseData); $actualError = $responseData['errors'][0]; diff --git a/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/PaypalPayflowProSetPaymentMethodTest.php b/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/PaypalPayflowProSetPaymentMethodTest.php index 1e747a7c7cea9..8e1df6e5525bf 100644 --- a/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/PaypalPayflowProSetPaymentMethodTest.php +++ b/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/PaypalPayflowProSetPaymentMethodTest.php @@ -7,11 +7,10 @@ namespace Magento\PaypalGraphQl\Model\Resolver\Guest; -use Magento\Framework\App\Request\Http; +use Magento\GraphQl\Service\GraphQlRequest; use Magento\PaypalGraphQl\PaypalPayflowProAbstractTest; use Magento\Framework\Serialize\SerializerInterface; use Magento\Quote\Model\QuoteIdToMaskedQuoteId; -use Magento\TestFramework\Helper\Bootstrap; use Magento\Framework\UrlInterface; use Magento\Framework\DataObject; @@ -23,9 +22,9 @@ class PaypalPayflowProSetPaymentMethodTest extends PaypalPayflowProAbstractTest { /** - * @var Http + * @var GraphQlRequest */ - private $request; + private $graphQlRequest; /** * @var SerializerInterface @@ -41,13 +40,9 @@ protected function setUp() { parent::setUp(); - $this->request = $this->objectManager->create(Http::class); $this->json = $this->objectManager->get(SerializerInterface::class); $this->quoteIdToMaskedId = $this->objectManager->get(QuoteIdToMaskedQuoteId::class); - - $this->objectManager = Bootstrap::getObjectManager(); - $this->graphqlController = $this->objectManager->get(\Magento\GraphQl\Controller\GraphQl::class); - $this->request = $this->objectManager->create(Http::class); + $this->graphQlRequest = $this->objectManager->create(GraphQlRequest::class); } /** @@ -146,14 +141,6 @@ public function testResolveGuest(): void } QUERY; - $postData = $this->json->serialize(['query' => $query]); - $this->request->setPathInfo('/graphql'); - $this->request->setMethod('POST'); - $this->request->setContent($postData); - $headers = $this->objectManager->create(\Zend\Http\Headers::class) - ->addHeaders(['Content-Type' => 'application/json']); - $this->request->setHeaders($headers); - $paypalResponse = new DataObject( [ 'result' => '0', @@ -197,7 +184,7 @@ public function testResolveGuest(): void ) ); - $response = $this->graphqlController->dispatch($this->request); + $response = $this->graphQlRequest->send($query); $responseData = $this->json->unserialize($response->getContent()); $this->assertArrayHasKey('data', $responseData); diff --git a/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/PaypalPayflowProTokenExceptionTest.php b/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/PaypalPayflowProTokenExceptionTest.php index 87aaadc58ddec..3b6fca8ec42bc 100644 --- a/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/PaypalPayflowProTokenExceptionTest.php +++ b/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/PaypalPayflowProTokenExceptionTest.php @@ -7,8 +7,8 @@ namespace Magento\PaypalGraphQl\Model\Resolver\Guest; -use Magento\Framework\App\Request\Http; use Magento\Framework\GraphQl\Exception\GraphQlInputException; +use Magento\GraphQl\Service\GraphQlRequest; use Magento\PaypalGraphQl\PaypalPayflowProAbstractTest; use Magento\Framework\Serialize\SerializerInterface; use Magento\Quote\Model\QuoteIdToMaskedQuoteId; @@ -21,9 +21,9 @@ class PaypalPayflowProTokenExceptionTest extends PaypalPayflowProAbstractTest { /** - * @var Http + * @var GraphQlRequest */ - private $request; + private $graphQlRequest; /** * @var SerializerInterface @@ -39,9 +39,9 @@ protected function setUp() { parent::setUp(); - $this->request = $this->objectManager->create(Http::class); $this->json = $this->objectManager->get(SerializerInterface::class); $this->quoteIdToMaskedId = $this->objectManager->get(QuoteIdToMaskedQuoteId::class); + $this->graphQlRequest = $this->objectManager->create(GraphQlRequest::class); } /** @@ -58,8 +58,6 @@ protected function setUp() */ public function testResolveWithPaypalError(): void { - $this->objectManager->removeSharedInstance(Gateway::class); - $this->enablePaymentMethod('payflowpro'); $reservedQuoteId = 'test_quote'; @@ -68,23 +66,14 @@ public function testResolveWithPaypalError(): void $cartId = $this->quoteIdToMaskedId->execute((int)$cart->getId()); $query = $this->getCreatePayflowTokenMutation($cartId); - $postData = $this->json->serialize(['query' => $query]); - $this->request->setPathInfo('/graphql'); - $this->request->setMethod('POST'); - $this->request->setContent($postData); - $headers = $this->objectManager->create(\Zend\Http\Headers::class) - ->addHeaders(['Content-Type' => 'application/json']); - $this->request->setHeaders($headers); - $expectedExceptionMessage = "Payment Gateway is unreachable at the moment. Please use another payment option."; $expectedException = new \Zend_Http_Client_Exception($expectedExceptionMessage); $this->gatewayMock - ->expects($this->any()) ->method('postRequest') ->willThrowException($expectedException); - $response = $this->graphqlController->dispatch($this->request); + $response = $this->graphQlRequest->send($query); $responseData = $this->json->unserialize($response->getContent()); $this->assertArrayHasKey('createPayflowProToken', $responseData['data']); $this->assertEmpty($responseData['data']['createPayflowProToken']); diff --git a/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/PaypalPayflowProTokenTest.php b/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/PaypalPayflowProTokenTest.php index 0ad392127e2ae..e8f9297c802c5 100644 --- a/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/PaypalPayflowProTokenTest.php +++ b/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/PaypalPayflowProTokenTest.php @@ -7,8 +7,8 @@ namespace Magento\PaypalGraphQl\Model\Resolver\Guest; -use Magento\Framework\App\Request\Http; use Magento\Framework\GraphQl\Exception\GraphQlInputException; +use Magento\GraphQl\Service\GraphQlRequest; use Magento\PaypalGraphQl\PaypalPayflowProAbstractTest; use Magento\Framework\Serialize\SerializerInterface; use Magento\Quote\Model\QuoteIdToMaskedQuoteId; @@ -22,9 +22,9 @@ class PaypalPayflowProTokenTest extends PaypalPayflowProAbstractTest { /** - * @var Http + * @var GraphQlRequest */ - private $request; + private $graphQlRequest; /** * @var SerializerInterface @@ -40,9 +40,9 @@ protected function setUp() { parent::setUp(); - $this->request = $this->objectManager->create(Http::class); $this->json = $this->objectManager->get(SerializerInterface::class); $this->quoteIdToMaskedId = $this->objectManager->get(QuoteIdToMaskedQuoteId::class); + $this->graphQlRequest = $this->objectManager->create(GraphQlRequest::class); } /** @@ -66,14 +66,6 @@ public function testResolve(): void $cartId = $this->quoteIdToMaskedId->execute((int)$cart->getId()); $query = $this->getCreatePayflowTokenMutation($cartId); - $postData = $this->json->serialize(['query' => $query]); - $this->request->setPathInfo('/graphql'); - $this->request->setMethod('POST'); - $this->request->setContent($postData); - $headers = $this->objectManager->create(\Zend\Http\Headers::class) - ->addHeaders(['Content-Type' => 'application/json']); - $this->request->setHeaders($headers); - $paypalResponse = new DataObject( [ 'result' => '0', @@ -85,11 +77,10 @@ public function testResolve(): void ); $this->gatewayMock - ->expects($this->any()) ->method('postRequest') ->willReturn($paypalResponse); - $response = $this->graphqlController->dispatch($this->request); + $response = $this->graphQlRequest->send($query); $responseData = $this->json->unserialize($response->getContent()); $this->assertArrayHasKey('data', $responseData); $this->assertArrayHasKey('createPayflowProToken', $responseData['data']); @@ -137,17 +128,9 @@ public function testResolveWithInvalidRedirectUrl(): void } QUERY; - $postData = $this->json->serialize(['query' => $query]); - $this->request->setPathInfo('/graphql'); - $this->request->setMethod('POST'); - $this->request->setContent($postData); - $headers = $this->objectManager->create(\Zend\Http\Headers::class) - ->addHeaders(['Content-Type' => 'application/json']); - $this->request->setHeaders($headers); - $expectedExceptionMessage = "Invalid URL 'not/a/url'."; - $response = $this->graphqlController->dispatch($this->request); + $response = $this->graphQlRequest->send($query); $responseData = $this->json->unserialize($response->getContent()); $this->assertArrayHasKey('errors', $responseData); $actualError = $responseData['errors'][0]; From 07ccb0bb43c8005471feededfc5cedb522ebc4f1 Mon Sep 17 00:00:00 2001 From: Roman Lytvynenko <lytvynen@adobe.com> Date: Tue, 9 Jul 2019 10:28:21 -0500 Subject: [PATCH 636/773] MC-17574: Magento WYSIWYG editor inserting " when inserting image image --- lib/web/mage/adminhtml/wysiwyg/tiny_mce/tinymce4Adapter.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/web/mage/adminhtml/wysiwyg/tiny_mce/tinymce4Adapter.js b/lib/web/mage/adminhtml/wysiwyg/tiny_mce/tinymce4Adapter.js index a05c0df03667e..78678cad2e0e8 100644 --- a/lib/web/mage/adminhtml/wysiwyg/tiny_mce/tinymce4Adapter.js +++ b/lib/web/mage/adminhtml/wysiwyg/tiny_mce/tinymce4Adapter.js @@ -491,6 +491,11 @@ define([ return true; } + + if (this.get('text') && this.get('text').getContent()) { + content = this.get('text').getContent(); + } + this.turnOff(); if (content.match(/{{.+?}}/g)) { From 49878456157f6fec520befd238821ecf58e8ae2d Mon Sep 17 00:00:00 2001 From: Roman Lytvynenko <lytvynen@adobe.com> Date: Tue, 9 Jul 2019 11:00:00 -0500 Subject: [PATCH 637/773] MC-17574: Magento WYSIWYG editor inserting " when inserting image image --- lib/web/mage/adminhtml/wysiwyg/tiny_mce/tinymce4Adapter.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/web/mage/adminhtml/wysiwyg/tiny_mce/tinymce4Adapter.js b/lib/web/mage/adminhtml/wysiwyg/tiny_mce/tinymce4Adapter.js index 78678cad2e0e8..2c00718d97ea8 100644 --- a/lib/web/mage/adminhtml/wysiwyg/tiny_mce/tinymce4Adapter.js +++ b/lib/web/mage/adminhtml/wysiwyg/tiny_mce/tinymce4Adapter.js @@ -484,7 +484,7 @@ define([ * @return {Boolean} */ toggle: function () { - var content = this.getTextArea().val(); + var content; if (!tinyMCE4.get(this.getId())) { this.turnOn(); @@ -492,9 +492,7 @@ define([ return true; } - if (this.get('text') && this.get('text').getContent()) { - content = this.get('text').getContent(); - } + content = this.get(this.getId()) ? this.get(this.getId()).getContent() : this.getTextArea().val(); this.turnOff(); From 74cbfb3bee4e57b369c894e6f8f64f3d62ea9645 Mon Sep 17 00:00:00 2001 From: Deepty Thampy <dthampy@adobe.com> Date: Tue, 9 Jul 2019 11:16:31 -0500 Subject: [PATCH 638/773] MC-17875: Refactor GraphQl Integration tests - fix static failures --- .../Model/Resolver/Customer/PlaceOrderWithPayflowProTest.php | 1 - .../Model/Resolver/Guest/PaypalExpressTokenTest.php | 1 - 2 files changed, 2 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Customer/PlaceOrderWithPayflowProTest.php b/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Customer/PlaceOrderWithPayflowProTest.php index 30054dcf712b6..00fbdbcd353c2 100644 --- a/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Customer/PlaceOrderWithPayflowProTest.php +++ b/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Customer/PlaceOrderWithPayflowProTest.php @@ -140,7 +140,6 @@ public function testResolveCustomer(): void } QUERY; - /** @var \Magento\Integration\Model\Oauth\Token $tokenModel */ $tokenModel = $this->objectManager->create(\Magento\Integration\Model\Oauth\Token::class); $customerToken = $tokenModel->createCustomerToken(1)->getToken(); diff --git a/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/PaypalExpressTokenTest.php b/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/PaypalExpressTokenTest.php index a9c70f97d3530..950eb2b9f6dc8 100644 --- a/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/PaypalExpressTokenTest.php +++ b/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/PaypalExpressTokenTest.php @@ -183,7 +183,6 @@ public function testResolveWithInvalidRedirectUrl(): void } QUERY; - $expectedExceptionMessage = "Invalid URL 'not/a/url'."; $response = $this->graphQlRequest->send($query); From 28b27f8cfd90f7fb503c6a11ac6489e03c33d55f Mon Sep 17 00:00:00 2001 From: Dmytro Yushkin <dyushkin@adobe.com> Date: Tue, 9 Jul 2019 12:30:00 -0500 Subject: [PATCH 639/773] MC-17576: Technical Question and possible documentation updates - regarding Signifyd module and the signifyd_payment_mapping.xml file when mapping to custom payment methods --- app/code/Magento/Signifyd/etc/di.xml | 3 ++ .../Signifyd/etc/signifyd_payment_mapping.xml | 32 +++++++++---------- .../Signifyd/etc/signifyd_payment_mapping.xsd | 7 ++++ 3 files changed, 26 insertions(+), 16 deletions(-) diff --git a/app/code/Magento/Signifyd/etc/di.xml b/app/code/Magento/Signifyd/etc/di.xml index fd78fff27f619..c586019ca3d12 100644 --- a/app/code/Magento/Signifyd/etc/di.xml +++ b/app/code/Magento/Signifyd/etc/di.xml @@ -68,6 +68,9 @@ <argument name="converter" xsi:type="object">Magento\Signifyd\Model\PaymentMethodMapper\XmlToArrayConfigConverter</argument> <argument name="schemaLocator" xsi:type="object">PaymentMapperSchemaLocator</argument> <argument name="fileName" xsi:type="string">signifyd_payment_mapping.xml</argument> + <argument name="idAttributes" xsi:type="array"> + <item name="/config/payment_method_list/payment_method" xsi:type="string">name</item> + </argument> </arguments> </virtualType> <virtualType name="PaymentMethodConfigData" type="Magento\Framework\Config\Data"> diff --git a/app/code/Magento/Signifyd/etc/signifyd_payment_mapping.xml b/app/code/Magento/Signifyd/etc/signifyd_payment_mapping.xml index 096a968167173..9ff952d04925d 100644 --- a/app/code/Magento/Signifyd/etc/signifyd_payment_mapping.xml +++ b/app/code/Magento/Signifyd/etc/signifyd_payment_mapping.xml @@ -6,7 +6,7 @@ */ /** * Custom payment method might adds a block in payment_method_list e.g. - * <payment_method> + * <payment_method name="custom_payment_method"> * <magento_code>custom_payment_method</magento_code> * <signifyd_code>PAYMENT_CARD</signifyd_code> * </payment_method> @@ -18,63 +18,63 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Signifyd:etc/signifyd_payment_mapping.xsd"> <payment_method_list> - <payment_method> + <payment_method name="braintree"> <magento_code>braintree</magento_code> <signifyd_code>PAYMENT_CARD</signifyd_code> </payment_method> - <payment_method> + <payment_method name="braintree_paypal"> <magento_code>braintree_paypal</magento_code> <signifyd_code>PAYPAL_ACCOUNT</signifyd_code> </payment_method> - <payment_method> + <payment_method name="paypal_express"> <magento_code>paypal_express</magento_code> <signifyd_code>PAYPAL_ACCOUNT</signifyd_code> </payment_method> - <payment_method> + <payment_method name="paypal_express_bml"> <magento_code>paypal_express_bml</magento_code> <signifyd_code>PAYPAL_ACCOUNT</signifyd_code> </payment_method> - <payment_method> + <payment_method name="payflow_express"> <magento_code>payflow_express</magento_code> <signifyd_code>PAYPAL_ACCOUNT</signifyd_code> </payment_method> - <payment_method> + <payment_method name="payflow_express_bml"> <magento_code>payflow_express_bml</magento_code> <signifyd_code>PAYPAL_ACCOUNT</signifyd_code> </payment_method> - <payment_method> + <payment_method name="payflowpro"> <magento_code>payflowpro</magento_code> <signifyd_code>PAYMENT_CARD</signifyd_code> </payment_method> - <payment_method> + <payment_method name="payflow_link"> <magento_code>payflow_link</magento_code> <signifyd_code>PAYMENT_CARD</signifyd_code> </payment_method> - <payment_method> + <payment_method name="payflow_advanced"> <magento_code>payflow_advanced</magento_code> <signifyd_code>PAYMENT_CARD</signifyd_code> </payment_method> - <payment_method> + <payment_method name="hosted_pro"> <magento_code>hosted_pro</magento_code> <signifyd_code>PAYMENT_CARD</signifyd_code> </payment_method> - <payment_method> + <payment_method name="authorizenet_directpost"> <magento_code>authorizenet_directpost</magento_code> <signifyd_code>PAYMENT_CARD</signifyd_code> </payment_method> - <payment_method> + <payment_method name="worldpay"> <magento_code>worldpay</magento_code> <signifyd_code>PAYMENT_CARD</signifyd_code> </payment_method> - <payment_method> + <payment_method name="eway"> <magento_code>eway</magento_code> <signifyd_code>PAYMENT_CARD</signifyd_code> </payment_method> - <payment_method> + <payment_method name="cybersource"> <magento_code>cybersource</magento_code> <signifyd_code>PAYMENT_CARD</signifyd_code> </payment_method> - <payment_method> + <payment_method name="free"> <magento_code>free</magento_code> <signifyd_code>FREE</signifyd_code> </payment_method> diff --git a/app/code/Magento/Signifyd/etc/signifyd_payment_mapping.xsd b/app/code/Magento/Signifyd/etc/signifyd_payment_mapping.xsd index f48805c328e09..bb3b3036d0c9c 100644 --- a/app/code/Magento/Signifyd/etc/signifyd_payment_mapping.xsd +++ b/app/code/Magento/Signifyd/etc/signifyd_payment_mapping.xsd @@ -23,5 +23,12 @@ <xs:element minOccurs="1" name="magento_code"/> <xs:element minOccurs="1" name="signifyd_code"/> </xs:sequence> + <xs:attribute name="name" type="xs:string" use="optional"> + <xs:annotation> + <xs:documentation> + Element's unique identifier. + </xs:documentation> + </xs:annotation> + </xs:attribute> </xs:complexType> </xs:schema> From a8ec25f90c6c61b591b2efd86775e09dac463dbf Mon Sep 17 00:00:00 2001 From: Oleksandr Iegorov <oiegorov@magento.com> Date: Tue, 9 Jul 2019 13:58:11 -0500 Subject: [PATCH 640/773] MC-17808: Custom customer attribute code showing on guest checkout --- .../view/frontend/web/template/billing-address/details.html | 3 +++ 1 file changed, 3 insertions(+) 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 b2c9974ae9b55..a0827d17d6622 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 @@ -23,6 +23,9 @@ </if> </ifnot> </if> + <if args="typeof element === 'string'"> + <text args="element"/> + </if><br/> </each> <button visible="!isAddressSameAsShipping()" From 342a87c859a7db367c525cf3b3a8ffd72b31c594 Mon Sep 17 00:00:00 2001 From: Roman Lytvynenko <lytvynen@adobe.com> Date: Tue, 9 Jul 2019 14:24:48 -0500 Subject: [PATCH 641/773] MC-17574: Magento WYSIWYG editor inserting " when inserting image image --- ...tConvertQuotationMarksInDirectivesTest.xml | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 app/code/Magento/Cms/Test/Mftf/Test/VerifyTinyMCEv4DoesNotConvertQuotationMarksInDirectivesTest.xml diff --git a/app/code/Magento/Cms/Test/Mftf/Test/VerifyTinyMCEv4DoesNotConvertQuotationMarksInDirectivesTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/VerifyTinyMCEv4DoesNotConvertQuotationMarksInDirectivesTest.xml new file mode 100644 index 0000000000000..168484dd267db --- /dev/null +++ b/app/code/Magento/Cms/Test/Mftf/Test/VerifyTinyMCEv4DoesNotConvertQuotationMarksInDirectivesTest.xml @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="VerifyTinyMceV4DoesNotConvertQuotationMarksInDirectivesTest"> + <annotations> + <features value="Cms"/> + <group value="Cms"/> + <title value="Magento WYSIWYG editor inserting quot; in directives when being disabled."/> + <description value="If you disable the WYSIWYG editor and enter any URL with quotations in directive, enable the editor and re-disable the editor, you will see that the quotes have been converted to quot;"/> + <severity value="MAJOR"/> + <testCaseId value="MC-17574"/> + </annotations> + <before> + <actionGroup ref="LoginActionGroup" stepKey="loginGetFromGeneralFile"/> + <actionGroup ref="EnabledWYSIWYG" stepKey="enableWYSIWYG"/> + <actionGroup ref="SwitchToVersion4ActionGroup" stepKey="switchToTinyMCE4" /> + </before> + <amOnPage url="{{CmsPagesPage.url}}" stepKey="amOnPagePagesGrid"/> + <waitForPageLoad stepKey="waitForPageLoad1"/> + <click selector="{{CmsPagesPageActionsSection.addNewPageButton}}" stepKey="clickAddNewPage"/> + <fillField selector="{{CmsNewPagePageBasicFieldsSection.pageTitle}}" userInput="{{_defaultCmsPage.title}}" stepKey="fillFieldTitle"/> + <click selector="{{CmsNewPagePageContentSection.header}}" stepKey="clickExpandContent"/> + <fillField selector="{{CmsNewPagePageContentSection.contentHeading}}" userInput="{{_defaultCmsPage.content_heading}}" stepKey="fillFieldContentHeading"/> + <waitForElementVisible selector="{{TinyMCESection.TinyMCE4}}" stepKey="waitForTinyMCE" /> + <actionGroup ref="VerifyTinyMCEActionGroup" stepKey="verifyTinyMCE4"/> + <actionGroup ref="VerifyMagentoEntityActionGroup" stepKey="verifyMagentoEntities"/> + <click selector="{{CmsWYSIWYGSection.ShowHideBtn}}" stepKey="turnWysiwygOff" /> + <wait time="1" stepKey="waitForTurnWysiwygOff" /> + <fillField selector="#cms_page_form_content" userInput="<p><img src="{{media url="wysiwyg/collection/collection-eco.jpg"}}"></p>" stepKey="fillEditorWithSampleText"/> + <grabValueFrom selector="#cms_page_form_content" stepKey="saveBeforeText"/> + <click selector="{{CmsWYSIWYGSection.ShowHideBtn}}" stepKey="toggleWysiwygOn" /> + <wait time="1" stepKey="waitForToggleOn" /> + <click selector="{{CmsWYSIWYGSection.ShowHideBtn}}" stepKey="toggleWysiwygOff" /> + <wait time="1" stepKey="waitForToggleOff" /> + <grabValueFrom selector="#cms_page_form_content" stepKey="saveAfterText"/> + <assertEquals message="Making sure text with directives will remain unchanged after toggling TinyMCE4 on and off" stepKey="assertEquals"> + <expectedResult type="variable">$saveBeforeText</expectedResult> + <actualResult type="variable">$saveAfterText</actualResult> + </assertEquals> + <after> + <actionGroup ref="DisabledWYSIWYG" stepKey="disableWYSIWYG"/> + <actionGroup ref="logout" stepKey="logout"/> + </after> + </test> +</tests> From 5a74bfe61b1e53c2fd9a21a958f0b563bf87f6e0 Mon Sep 17 00:00:00 2001 From: Maria Kovdrysh <kovdrysh@adobe.com> Date: Tue, 9 Jul 2019 15:21:31 -0500 Subject: [PATCH 642/773] MC-3241: Admin should be able to set/edit other product information when creating/editing a simple product --- ...minChangeProductSEOSettingsActionGroup.xml | 22 +++ ...minSetProductDesignSettingsActionGroup.xml | 20 +++ ...tchProductGiftMessageStatusActionGroup.xml | 21 +++ ...rontAssertGiftMessageFieldsActionGroup.xml | 19 +++ .../Test/Mftf/Data/ProductDesignData.xml | 21 +++ .../Mftf/Section/AdminProductFormSection.xml | 1 + .../AdminProductGiftOptionsSection.xml | 17 +++ .../Mftf/Section/AdminProductSEOSection.xml | 3 + .../StorefrontProductPageDesignSection.xml | 15 ++ ...CreateAndEditSimpleProductSettingsTest.xml | 136 ++++++++++++++++++ ...StorefrontProductCartGiftOptionSection.xml | 19 +++ 11 files changed, 294 insertions(+) create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminChangeProductSEOSettingsActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminSetProductDesignSettingsActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminSwitchProductGiftMessageStatusActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontAssertGiftMessageFieldsActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/Data/ProductDesignData.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/Section/AdminProductGiftOptionsSection.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductPageDesignSection.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateAndEditSimpleProductSettingsTest.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/Section/StorefrontProductCartGiftOptionSection.xml diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminChangeProductSEOSettingsActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminChangeProductSEOSettingsActionGroup.xml new file mode 100644 index 0000000000000..ec0beac86554e --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminChangeProductSEOSettingsActionGroup.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminChangeProductSEOSettingsActionGroup"> + <arguments> + <argument name="productName" defaultValue="_defaultProduct.name"/> + </arguments> + <click selector="{{AdminProductSEOSection.sectionHeader}}" stepKey="clickSearchEngineOptimizationTab"/> + <waitForPageLoad stepKey="waitForTabOpen"/> + <fillField selector="{{AdminProductSEOSection.urlKeyInput}}" userInput="{{productName}}" stepKey="setUrlKeyInput"/> + <fillField selector="{{AdminProductSEOSection.metaTitleInput}}" userInput="{{productName}}" stepKey="setMetaTitleInput"/> + <fillField selector="{{AdminProductSEOSection.metaKeywordsInput}}" userInput="{{productName}}" stepKey="setMetaKeywordsInput"/> + <fillField selector="{{AdminProductSEOSection.metaDescriptionInput}}" userInput="{{productName}}" stepKey="setMetaDescriptionInput"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminSetProductDesignSettingsActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminSetProductDesignSettingsActionGroup.xml new file mode 100644 index 0000000000000..7998cdc93732e --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminSetProductDesignSettingsActionGroup.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminSetProductDesignSettingsActionGroup"> + <arguments> + <argument name="designSettings" defaultValue="simpleBlankDesign"/> + </arguments> + <click selector="{{ProductDesignSection.DesignTab}}" stepKey="clickDesignTab"/> + <waitForPageLoad stepKey="waitForTabOpen"/> + <selectOption selector="{{ProductDesignSection.LayoutDropdown}}" userInput="{{designSettings.page_layout}}" stepKey="setLayout"/> + <selectOption selector="{{ProductDesignSection.productOptionsContainer}}" userInput="{{designSettings.options_container}}" stepKey="setDisplayProductOptions"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminSwitchProductGiftMessageStatusActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminSwitchProductGiftMessageStatusActionGroup.xml new file mode 100644 index 0000000000000..4d650a727acc9 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminSwitchProductGiftMessageStatusActionGroup.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminSwitchProductGiftMessageStatusActionGroup"> + <arguments> + <argument name="status" defaultValue="0"/> + </arguments> + <click selector="{{AdminProductGiftOptionsSection.giftOptions}}" stepKey="clickToExpandGiftOptionsTab"/> + <waitForPageLoad stepKey="waitForGiftOptionsOpen"/> + <uncheckOption selector="{{AdminProductGiftOptionsSection.useConfigSettingsMessage}}" stepKey="uncheckConfigSettingsMessage"/> + <click selector="{{AdminProductGiftOptionsSection.toggleProductGiftMessage}}" stepKey="clickToGiftMessageSwitcher"/> + <seeElement selector="{{AdminProductGiftOptionsSection.giftMessageStatus('status')}}" stepKey="assertGiftMessageStatus"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontAssertGiftMessageFieldsActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontAssertGiftMessageFieldsActionGroup.xml new file mode 100644 index 0000000000000..a5f1b92862be3 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontAssertGiftMessageFieldsActionGroup.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="StorefrontAssertGiftMessageFieldsActionGroup"> + <waitForElementVisible selector="{{StorefrontProductCartGiftOptionSection.giftOptions}}" stepKey="waitForCartGiftOptionVisible"/> + <click selector="{{StorefrontProductCartGiftOptionSection.giftOptions}}" stepKey="clickGiftOptionBtn"/> + <seeElement selector="{{StorefrontProductCartGiftOptionSection.fieldTo}}" stepKey="seeFieldTo"/> + <seeElement selector="{{StorefrontProductCartGiftOptionSection.fieldFrom}}" stepKey="seeFieldFrom"/> + <seeElement selector="{{StorefrontProductCartGiftOptionSection.message}}" stepKey="seeMessageArea"/> + <seeElement selector="{{StorefrontProductCartGiftOptionSection.update}}" stepKey="seeUpdateButton"/> + <seeElement selector="{{StorefrontProductCartGiftOptionSection.cancel}}" stepKey="seeCancelButton"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/ProductDesignData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/ProductDesignData.xml new file mode 100644 index 0000000000000..42e85ab269884 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/Data/ProductDesignData.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd"> + <entity name="simpleBlankDesign" type="product"> + <data key="custom_design">Magento Blank</data> + <data key="page_layout">2 columns with left bar</data> + <data key="options_container">Product Info Column</data> + </entity> + <entity name="simpleLumaDesign" type="product"> + <data key="custom_design">Magento Luma</data> + <data key="page_layout">Empty</data> + <data key="options_container">Block after Info Column</data> + </entity> +</entities> diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormSection.xml index 5e2c2d365179f..60b082860d524 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormSection.xml @@ -84,6 +84,7 @@ <section name="ProductDesignSection"> <element name="DesignTab" type="button" selector="//strong[@class='admin__collapsible-title']//span[text()='Design']"/> <element name="LayoutDropdown" type="select" selector="select[name='product[page_layout]']"/> + <element name="productOptionsContainer" type="select" selector="select[name='product[options_container]']"/> </section> <section name="AdminProductFormRelatedUpSellCrossSellSection"> <element name="relatedProductsHeader" type="button" selector=".admin__collapsible-block-wrapper[data-index='related']" timeout="30"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductGiftOptionsSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductGiftOptionsSection.xml new file mode 100644 index 0000000000000..63b745e522705 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductGiftOptionsSection.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="AdminProductGiftOptionsSection"> + <element name="giftOptions" type="text" selector="div[data-index='gift-options']"/> + <element name="useConfigSettingsMessage" type="checkbox" selector="[name='product[use_config_gift_message_available]']"/> + <element name="toggleProductGiftMessage" type="button" selector="input[name='product[gift_message_available]']+label"/> + <element name="giftMessageStatus" type="checkbox" selector="input[name='product[gift_message_available]'][value='{{status}}']" parameterized="true"/> + </section> +</sections> diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductSEOSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductSEOSection.xml index 53231a2a68633..8685e84a347f2 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductSEOSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductSEOSection.xml @@ -12,5 +12,8 @@ <element name="sectionHeader" type="button" selector="div[data-index='search-engine-optimization']" timeout="30"/> <element name="urlKeyInput" type="input" selector="input[name='product[url_key]']"/> <element name="useDefaultUrl" type="checkbox" selector="input[name='use_default[url_key]']"/> + <element name="metaTitleInput" type="input" selector="input[name='product[meta_title]']"/> + <element name="metaKeywordsInput" type="textarea" selector="textarea[name='product[meta_keyword]']"/> + <element name="metaDescriptionInput" type="textarea" selector="textarea[name='product[meta_description]']"/> </section> </sections> diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductPageDesignSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductPageDesignSection.xml new file mode 100644 index 0000000000000..1f41ddefd0be6 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductPageDesignSection.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="StorefrontProductPageDesignSection"> + <element name="layoutTwoColumnsLeft" type="block" selector=".page-layout-2columns-left"/> + <element name="layoutEmpty" type="block" selector=".page-layout-empty"/> + </section> +</sections> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateAndEditSimpleProductSettingsTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateAndEditSimpleProductSettingsTest.xml new file mode 100644 index 0000000000000..e3b0ae3746387 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateAndEditSimpleProductSettingsTest.xml @@ -0,0 +1,136 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AdminCreateAndEditSimpleProductSettingsTest"> + <annotations> + <features value="Catalog"/> + <stories value="Create/Edit simple product in Admin"/> + <title value="Admin should be able to set/edit other product information when creating/editing a simple product"/> + <description value="Admin should be able to set/edit product information when creating/editing a simple product"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-3241"/> + <group value="Catalog"/> + </annotations> + <before> + <!-- Login as admin --> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + + <!-- Create related products --> + <createData entity="SimpleProduct2" stepKey="createFirstRelatedProduct"/> + <createData entity="SimpleProduct2" stepKey="createSecondRelatedProduct"/> + <createData entity="SimpleProduct2" stepKey="createThirdRelatedProduct"/> + </before> + <after> + <!-- Delete related products --> + <deleteData createDataKey="createFirstRelatedProduct" stepKey="deleteFirstRelatedProduct"/> + <deleteData createDataKey="createSecondRelatedProduct" stepKey="deleteSecondRelatedProduct"/> + <deleteData createDataKey="createThirdRelatedProduct" stepKey="deleteThirdRelatedProduct"/> + + <!-- Log out --> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <!-- Create new simple product --> + <actionGroup ref="GoToSpecifiedCreateProductPage" stepKey="createSimpleProduct"/> + + <!-- Fill all main fields --> + <actionGroup ref="fillMainProductForm" stepKey="fillAllNecessaryFields"/> + + <!-- Add two related products --> + <actionGroup ref="addRelatedProductBySku" stepKey="addFirstRelatedProduct"> + <argument name="sku" value="$$createFirstRelatedProduct.sku$$"/> + </actionGroup> + <actionGroup ref="addRelatedProductBySku" stepKey="addSecondRelatedProduct"> + <argument name="sku" value="$$createSecondRelatedProduct.sku$$"/> + </actionGroup> + + <!-- Set Design settings for the product --> + <actionGroup ref="AdminSetProductDesignSettingsActionGroup" stepKey="setProductDesignSettings"/> + + <!-- Set Gift Options settings for the product --> + <actionGroup ref="AdminSwitchProductGiftMessageStatusActionGroup" stepKey="enableGiftMessageSettings"> + <argument name="status" value="1"/> + </actionGroup> + + <!-- Save product form --> + <actionGroup ref="saveProductForm" stepKey="clickSaveButton"/> + + <!-- Open product page --> + <actionGroup ref="StorefrontOpenProductPageActionGroup" stepKey="openStorefrontProductPage"> + <argument name="productUrl" value="{{_defaultProduct.name}}"/> + </actionGroup> + + <!-- Assert related products at the storefront --> + <seeElement selector="{{StorefrontProductRelatedProductsSection.relatedProductName($$createFirstRelatedProduct.name$$)}}" stepKey="seeFirstRelatedProductInStorefront"/> + <seeElement selector="{{StorefrontProductRelatedProductsSection.relatedProductName($$createSecondRelatedProduct.name$$)}}" stepKey="seeSecondRelatedProductInStorefront"/> + + <!-- Assert product design settings "left bar is present at product page with 2 columns" --> + <seeElement selector="{{StorefrontProductPageDesignSection.layoutTwoColumnsLeft}}" stepKey="seeDesignChanges"/> + + <!-- Assert Gift Option product settings is present --> + <actionGroup ref="StorefrontAddProductToCartActionGroup" stepKey="addProductToCart"> + <argument name="product" value="_defaultProduct"/> + <argument name="productCount" value="1"/> + </actionGroup> + <actionGroup ref="StorefrontOpenCartFromMinicartActionGroup" stepKey="openShoppingCart"/> + <actionGroup ref="StorefrontAssertGiftMessageFieldsActionGroup" stepKey="assertGiftMessageFieldsArePresent"/> + + <!-- Open created product --> + <actionGroup ref="SearchForProductOnBackendActionGroup" stepKey="searchForSimpleProduct"> + <argument name="product" value="_defaultProduct"/> + </actionGroup> + <actionGroup ref="OpenEditProductOnBackendActionGroup" stepKey="openEditProduct"> + <argument name="product" value="_defaultProduct"/> + </actionGroup> + + <!-- Edit product Search Engine Optimization settings --> + <actionGroup ref="AdminChangeProductSEOSettingsActionGroup" stepKey="editProductSEOSettings"> + <argument name="productName" value="SimpleProduct.name"/> + </actionGroup> + + <!-- Edit related products --> + <actionGroup ref="addRelatedProductBySku" stepKey="addThirdRelatedProduct"> + <argument name="sku" value="$$createThirdRelatedProduct.sku$$"/> + </actionGroup> + <click selector="{{AdminProductFormRelatedUpSellCrossSellSection.removeRelatedProduct($$createFirstRelatedProduct.sku$$)}}" stepKey="removeFirstRelatedProduct"/> + + <!-- Edit Design settings for the product --> + <actionGroup ref="AdminSetProductDesignSettingsActionGroup" stepKey="editProductDesignSettings"> + <argument name="designSettings" value="simpleLumaDesign"/> + </actionGroup> + + <!-- Edit Gift Option product settings --> + <actionGroup ref="AdminSwitchProductGiftMessageStatusActionGroup" stepKey="disableGiftMessageSettings"/> + + <!-- Save product form --> + <actionGroup ref="saveProductForm" stepKey="clickSaveProduct"/> + + <!-- Verify Url Key after changing --> + <actionGroup ref="StorefrontOpenProductPageActionGroup" stepKey="openProductPage"> + <argument name="productUrl" value="{{SimpleProduct.name}}"/> + </actionGroup> + + <!-- Assert related products at the storefront --> + <seeElement selector="{{StorefrontProductRelatedProductsSection.relatedProductName($$createSecondRelatedProduct.name$$)}}" stepKey="seeSecondRelatedProduct"/> + <seeElement selector="{{StorefrontProductRelatedProductsSection.relatedProductName($$createThirdRelatedProduct.name$$)}}" stepKey="seeThirdRelatedProduct"/> + + <!-- Assert product design settings "Layout empty" --> + <seeElement selector="{{StorefrontProductPageDesignSection.layoutEmpty}}" stepKey="seeNewDesignChanges"/> + + <!-- Assert Gift Option product settings --> + <actionGroup ref="StorefrontOpenCartFromMinicartActionGroup" stepKey="openCart"/> + <dontSeeElement selector="{{StorefrontProductCartGiftOptionSection.giftOptions}}" stepKey="dontSeeGiftOptionBtn"/> + + <!-- Delete created simple product --> + <actionGroup ref="deleteProductUsingProductGrid" stepKey="deleteProduct"> + <argument name="product" value="_defaultProduct"/> + </actionGroup> + </test> +</tests> diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/StorefrontProductCartGiftOptionSection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/StorefrontProductCartGiftOptionSection.xml new file mode 100644 index 0000000000000..c1bee4af4c29b --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/Section/StorefrontProductCartGiftOptionSection.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="StorefrontProductCartGiftOptionSection"> + <element name="giftOptions" type="button" selector=".action.action-gift"/> + <element name="fieldTo" type="input" selector=".gift-options-content .field-to input"/> + <element name="fieldFrom" type="input" selector=".gift-options-content .field-from input"/> + <element name="message" type="textarea" selector="#gift-message-whole-message"/> + <element name="update" type="button" selector=".action-update"/> + <element name="cancel" type="button" selector=".action-cancel"/> + </section> +</sections> From 6c9651fa649b9b5d71b1db4ce19ed002efdc7b5c Mon Sep 17 00:00:00 2001 From: Dmytro Yushkin <dyushkin@adobe.com> Date: Tue, 9 Jul 2019 15:29:09 -0500 Subject: [PATCH 643/773] MC-18004: Cannot create Shipping Label for RMA: "No authorized items or allowed shipping methods" --- app/code/Magento/Shipping/Model/Shipping.php | 3 +- .../Shipping/Test/Unit/Model/ShippingTest.php | 142 ++++++++++++------ 2 files changed, 97 insertions(+), 48 deletions(-) diff --git a/app/code/Magento/Shipping/Model/Shipping.php b/app/code/Magento/Shipping/Model/Shipping.php index eccdd720e11c0..5470f9a96775b 100644 --- a/app/code/Magento/Shipping/Model/Shipping.php +++ b/app/code/Magento/Shipping/Model/Shipping.php @@ -272,8 +272,7 @@ public function collectRates(\Magento\Quote\Model\Quote\Address\RateRequest $req */ private function prepareCarrier(string $carrierCode, RateRequest $request): AbstractCarrier { - /* @var AbstractCarrier $carrier */ - $carrier = $this->_carrierFactory->createIfActive($carrierCode, $request->getStoreId()); + $carrier = $this->_carrierFactory->create($carrierCode, $request->getStoreId()); if (!$carrier) { throw new \RuntimeException('Failed to initialize carrier'); } diff --git a/app/code/Magento/Shipping/Test/Unit/Model/ShippingTest.php b/app/code/Magento/Shipping/Test/Unit/Model/ShippingTest.php index 727675407b8a0..1d4c9e9765775 100644 --- a/app/code/Magento/Shipping/Test/Unit/Model/ShippingTest.php +++ b/app/code/Magento/Shipping/Test/Unit/Model/ShippingTest.php @@ -5,10 +5,18 @@ */ namespace Magento\Shipping\Test\Unit\Model; -use \Magento\Shipping\Model\Shipping; - +use Magento\Catalog\Model\Product; +use Magento\Catalog\Model\Product\Type as ProductType; +use Magento\CatalogInventory\Model\Stock\Item as StockItem; +use Magento\CatalogInventory\Model\StockRegistry; +use Magento\Quote\Model\Quote\Item as QuoteItem; +use Magento\Shipping\Model\Carrier\AbstractCarrierInterface; +use Magento\Shipping\Model\CarrierFactory; +use Magento\Shipping\Model\Shipping; use Magento\Quote\Model\Quote\Address\RateRequest; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +use Magento\Store\Model\Store; +use PHPUnit_Framework_MockObject_MockObject as MockObject; class ShippingTest extends \PHPUnit\Framework\TestCase { @@ -25,71 +33,69 @@ class ShippingTest extends \PHPUnit\Framework\TestCase protected $shipping; /** - * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Shipping\Model\Carrier\AbstractCarrier + * @var MockObject|StockRegistry */ - protected $carrier; + protected $stockRegistry; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var MockObject|StockItem */ - protected $stockRegistry; + protected $stockItemData; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var MockObject|AbstractCarrierInterface */ - protected $stockItemData; + private $carrier; protected function setUp() { - $this->carrier = $this->createMock(\Magento\Shipping\Model\Carrier\AbstractCarrier::class); - $this->carrier->expects($this->any())->method('getConfigData')->will($this->returnCallback(function ($key) { - $configData = [ - 'max_package_weight' => 10, - ]; - return isset($configData[$key]) ? $configData[$key] : 0; - })); - $this->stockRegistry = $this->createMock(\Magento\CatalogInventory\Model\StockRegistry::class); - $this->stockItemData = $this->createMock(\Magento\CatalogInventory\Model\Stock\Item::class); - - $objectManagerHelper = new ObjectManagerHelper($this); - $this->shipping = $objectManagerHelper->getObject( - \Magento\Shipping\Model\Shipping::class, - ['stockRegistry' => $this->stockRegistry] + $this->stockRegistry = $this->createMock(StockRegistry::class); + $this->stockItemData = $this->createMock(StockItem::class); + + $this->shipping = (new ObjectManagerHelper($this))->getObject( + Shipping::class, + [ + 'stockRegistry' => $this->stockRegistry, + 'carrierFactory' => $this->getCarrierFactory(), + ] ); } /** - * @covers \Magento\Shipping\Model\Shipping::composePackagesForCarrier + * */ public function testComposePackages() { $request = new RateRequest(); - /** \Magento\Catalog\Model\Product\Configuration\Item\ItemInterface */ - $item = $this->getMockBuilder(\Magento\Quote\Model\Quote\Item::class) + $item = $this->getMockBuilder(QuoteItem::class) ->disableOriginalConstructor() - ->setMethods([ - 'getQty', 'getIsQtyDecimal', 'getProductType', 'getProduct', 'getWeight', '__wakeup', 'getStore', - ]) - ->getMock(); - $product = $this->createMock(\Magento\Catalog\Model\Product::class); - - $item->expects($this->any())->method('getQty')->will($this->returnValue(1)); - $item->expects($this->any())->method('getWeight')->will($this->returnValue(10)); - $item->expects($this->any())->method('getIsQtyDecimal')->will($this->returnValue(true)); - $item->expects($this->any())->method('getProductType') - ->will($this->returnValue(\Magento\Catalog\Model\Product\Type::TYPE_SIMPLE)); - $item->expects($this->any())->method('getProduct')->will($this->returnValue($product)); - - $store = $this->createPartialMock(\Magento\Store\Model\Store::class, ['getWebsiteId']); - $store->expects($this->any()) - ->method('getWebsiteId') - ->will($this->returnValue(10)); - $item->expects($this->any())->method('getStore')->will($this->returnValue($store)); - - $product->expects($this->any())->method('getId')->will($this->returnValue($this->productId)); + ->setMethods( + [ + 'getQty', + 'getIsQtyDecimal', + 'getProductType', + 'getProduct', + 'getWeight', + '__wakeup', + 'getStore', + ] + )->getMock(); + $product = $this->createMock(Product::class); + + $item->method('getQty')->will($this->returnValue(1)); + $item->method('getWeight')->will($this->returnValue(10)); + $item->method('getIsQtyDecimal')->will($this->returnValue(true)); + $item->method('getProductType')->will($this->returnValue(ProductType::TYPE_SIMPLE)); + $item->method('getProduct')->will($this->returnValue($product)); + + $store = $this->createPartialMock(Store::class, ['getWebsiteId']); + $store->method('getWebsiteId')->will($this->returnValue(10)); + $item->method('getStore')->will($this->returnValue($store)); + + $product->method('getId')->will($this->returnValue($this->productId)); $request->setData('all_items', [$item]); - $this->stockItemData->expects($this->any())->method('getIsDecimalDivided')->will($this->returnValue(true)); + $this->stockItemData->method('getIsDecimalDivided')->will($this->returnValue(true)); /** Testable service calls to CatalogInventory module */ $this->stockRegistry->expects($this->atLeastOnce())->method('getStockItem') @@ -101,7 +107,51 @@ public function testComposePackages() ->will($this->returnValue(true)); $this->stockItemData->expects($this->atLeastOnce())->method('getQtyIncrements') ->will($this->returnValue(0.5)); + $this->carrier->method('getConfigData') + ->willReturnCallback(function ($key) { + $configData = [ + 'max_package_weight' => 10, + ]; + return isset($configData[$key]) ? $configData[$key] : 0; + }); $this->shipping->composePackagesForCarrier($this->carrier, $request); } + + /** + * Active flag should be set before collecting carrier rates. + */ + public function testCollectCarrierRatesSetActiveFlag() + { + $this->carrier->expects($this->atLeastOnce()) + ->method('setActiveFlag') + ->with('active'); + + $this->shipping->collectCarrierRates('carrier', new RateRequest()); + } + + /** + * @return CarrierFactory|MockObject + */ + private function getCarrierFactory() + { + $carrierFactory = $this->getMockBuilder(CarrierFactory::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->carrier = $this->getMockBuilder(AbstractCarrierInterface::class) + ->setMethods( + [ + 'setActiveFlag', + 'checkAvailableShipCountries', + 'processAdditionalValidation', + 'getConfigData', + 'collectRates', + ] + ) + ->getMockForAbstractClass(); + $carrierFactory->method('create')->willReturn($this->carrier); + + return $carrierFactory; + } } From 1c2abae168f591040e3c6db433ad38954bf8a8c1 Mon Sep 17 00:00:00 2001 From: Roman Lytvynenko <lytvynen@adobe.com> Date: Tue, 9 Jul 2019 16:34:58 -0500 Subject: [PATCH 644/773] MC-17574: Magento WYSIWYG editor inserting " when inserting image image --- ...tConvertQuotationMarksInDirectivesTest.xml | 52 ------------------- 1 file changed, 52 deletions(-) delete mode 100644 app/code/Magento/Cms/Test/Mftf/Test/VerifyTinyMCEv4DoesNotConvertQuotationMarksInDirectivesTest.xml diff --git a/app/code/Magento/Cms/Test/Mftf/Test/VerifyTinyMCEv4DoesNotConvertQuotationMarksInDirectivesTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/VerifyTinyMCEv4DoesNotConvertQuotationMarksInDirectivesTest.xml deleted file mode 100644 index 168484dd267db..0000000000000 --- a/app/code/Magento/Cms/Test/Mftf/Test/VerifyTinyMCEv4DoesNotConvertQuotationMarksInDirectivesTest.xml +++ /dev/null @@ -1,52 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> - -<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> - <test name="VerifyTinyMceV4DoesNotConvertQuotationMarksInDirectivesTest"> - <annotations> - <features value="Cms"/> - <group value="Cms"/> - <title value="Magento WYSIWYG editor inserting quot; in directives when being disabled."/> - <description value="If you disable the WYSIWYG editor and enter any URL with quotations in directive, enable the editor and re-disable the editor, you will see that the quotes have been converted to quot;"/> - <severity value="MAJOR"/> - <testCaseId value="MC-17574"/> - </annotations> - <before> - <actionGroup ref="LoginActionGroup" stepKey="loginGetFromGeneralFile"/> - <actionGroup ref="EnabledWYSIWYG" stepKey="enableWYSIWYG"/> - <actionGroup ref="SwitchToVersion4ActionGroup" stepKey="switchToTinyMCE4" /> - </before> - <amOnPage url="{{CmsPagesPage.url}}" stepKey="amOnPagePagesGrid"/> - <waitForPageLoad stepKey="waitForPageLoad1"/> - <click selector="{{CmsPagesPageActionsSection.addNewPageButton}}" stepKey="clickAddNewPage"/> - <fillField selector="{{CmsNewPagePageBasicFieldsSection.pageTitle}}" userInput="{{_defaultCmsPage.title}}" stepKey="fillFieldTitle"/> - <click selector="{{CmsNewPagePageContentSection.header}}" stepKey="clickExpandContent"/> - <fillField selector="{{CmsNewPagePageContentSection.contentHeading}}" userInput="{{_defaultCmsPage.content_heading}}" stepKey="fillFieldContentHeading"/> - <waitForElementVisible selector="{{TinyMCESection.TinyMCE4}}" stepKey="waitForTinyMCE" /> - <actionGroup ref="VerifyTinyMCEActionGroup" stepKey="verifyTinyMCE4"/> - <actionGroup ref="VerifyMagentoEntityActionGroup" stepKey="verifyMagentoEntities"/> - <click selector="{{CmsWYSIWYGSection.ShowHideBtn}}" stepKey="turnWysiwygOff" /> - <wait time="1" stepKey="waitForTurnWysiwygOff" /> - <fillField selector="#cms_page_form_content" userInput="<p><img src="{{media url="wysiwyg/collection/collection-eco.jpg"}}"></p>" stepKey="fillEditorWithSampleText"/> - <grabValueFrom selector="#cms_page_form_content" stepKey="saveBeforeText"/> - <click selector="{{CmsWYSIWYGSection.ShowHideBtn}}" stepKey="toggleWysiwygOn" /> - <wait time="1" stepKey="waitForToggleOn" /> - <click selector="{{CmsWYSIWYGSection.ShowHideBtn}}" stepKey="toggleWysiwygOff" /> - <wait time="1" stepKey="waitForToggleOff" /> - <grabValueFrom selector="#cms_page_form_content" stepKey="saveAfterText"/> - <assertEquals message="Making sure text with directives will remain unchanged after toggling TinyMCE4 on and off" stepKey="assertEquals"> - <expectedResult type="variable">$saveBeforeText</expectedResult> - <actualResult type="variable">$saveAfterText</actualResult> - </assertEquals> - <after> - <actionGroup ref="DisabledWYSIWYG" stepKey="disableWYSIWYG"/> - <actionGroup ref="logout" stepKey="logout"/> - </after> - </test> -</tests> From 734c7f879f8c8c51cf873107c1176a96abdf4213 Mon Sep 17 00:00:00 2001 From: OlgaVasyltsun <olga.vasyltsun@gmail.com> Date: Wed, 10 Jul 2019 08:47:57 +0300 Subject: [PATCH 645/773] MC-17865: Finalize @codingStandardsIgnoreFile elimination in CE --- .../Cms/view/adminhtml/templates/browser/content/uploader.phtml | 2 +- .../UrlRewrite/view/adminhtml/templates/categories.phtml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Cms/view/adminhtml/templates/browser/content/uploader.phtml b/app/code/Magento/Cms/view/adminhtml/templates/browser/content/uploader.phtml index 838a8a122fbb9..099efa0abdb88 100644 --- a/app/code/Magento/Cms/view/adminhtml/templates/browser/content/uploader.phtml +++ b/app/code/Magento/Cms/view/adminhtml/templates/browser/content/uploader.phtml @@ -8,7 +8,7 @@ $filters = $block->getConfig()->getFilters() ?? []; $allowedExtensions = []; -$blockHtmlId = $block->escapeHtml($block->getHtmlId()); +$blockHtmlId = $block->getHtmlId(); foreach ($filters as $media_type) { $allowedExtensions = array_merge($allowedExtensions, array_map(function ($fileExt) { diff --git a/app/code/Magento/UrlRewrite/view/adminhtml/templates/categories.phtml b/app/code/Magento/UrlRewrite/view/adminhtml/templates/categories.phtml index f115fdb529466..bccffcef87867 100644 --- a/app/code/Magento/UrlRewrite/view/adminhtml/templates/categories.phtml +++ b/app/code/Magento/UrlRewrite/view/adminhtml/templates/categories.phtml @@ -22,7 +22,7 @@ "categoryTree": { "data": <?= /* @noEscape */ $this->helper(\Magento\Framework\Json\Helper\Data::class)->jsonEncode($block->getTreeArray()); ?>, - "url": "<?= $block->escapeUrl($block->getLoadTreeUrl()); ?>" + "url": "<?= $block->escapeJs($block->escapeUrl($block->getLoadTreeUrl())); ?>" } } } From 32c76213e13f02a11db2abc16dd5f174346faf23 Mon Sep 17 00:00:00 2001 From: Nikita Shcherbatykh <nikita.shcherbatykh@transoftgroup.com> Date: Wed, 10 Jul 2019 10:24:33 +0300 Subject: [PATCH 646/773] MC-17947: Search by email is working incorrect in Sales > Orders grid --- .../Test/Mftf/Test/SearchByEmailInCustomerGridTest.xml | 10 +++------- .../UiComponent/DataProvider/FulltextFilter.php | 7 ++++++- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/app/code/Magento/Customer/Test/Mftf/Test/SearchByEmailInCustomerGridTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/SearchByEmailInCustomerGridTest.xml index 4937347c56b33..e16ec92e507e6 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/SearchByEmailInCustomerGridTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/SearchByEmailInCustomerGridTest.xml @@ -10,7 +10,7 @@ <test name="SearchByEmailInCustomerGridTest"> <annotations> <features value="Customer"/> - <stories value="Customer Search email searching"/> + <stories value="Customer grid search"/> <title value="Admin customer grid email searching"/> <description value="Admin customer grid searching by email in keyword"/> <severity value="MAJOR"/> @@ -19,12 +19,8 @@ <group value="customer"/> </annotations> <before> - <createData entity="Simple_US_Customer" stepKey="createFirstCustomer"> - <field key="email">test1@example.com</field> - </createData> - <createData entity="Simple_US_Customer" stepKey="createSecondCustomer"> - <field key="email">test2@example.com</field> - </createData> + <createData entity="Simple_US_Customer" stepKey="createFirstCustomer"/> + <createData entity="Simple_US_Customer" stepKey="createSecondCustomer"/> <actionGroup ref="LoginAsAdmin" stepKey="login"/> </before> <after> diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/DataProvider/FulltextFilter.php b/lib/internal/Magento/Framework/View/Element/UiComponent/DataProvider/FulltextFilter.php index cf0aed4d23593..777f645fbc7fd 100644 --- a/lib/internal/Magento/Framework/View/Element/UiComponent/DataProvider/FulltextFilter.php +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/DataProvider/FulltextFilter.php @@ -15,6 +15,11 @@ */ class FulltextFilter implements FilterApplierInterface { + /** + * Patterns using in preg_replace for emails + */ + private const EMAIL_REPLACE_PATTERNS = ['/@/', '/\./']; + /** * Returns list of columns from fulltext index (doesn't support more then one FTI per table) * @@ -71,7 +76,7 @@ function ($column) use ($alias) { private function escapeAgainstValue(string $value): string { $value = preg_replace('/([+\-><\(\)~*]+)/', ' ', $value); - return preg_replace('/(@)/', '\_', $value); + return preg_replace(self::EMAIL_REPLACE_PATTERNS, '\_', $value); } /** From b643094a624de142be9b81a3db1c8bf025f99ea1 Mon Sep 17 00:00:00 2001 From: Serhii Voloshkov <serhii.voloshkov@transoftgroup.com> Date: Tue, 9 Jul 2019 16:46:20 +0300 Subject: [PATCH 647/773] MC-17864: Finalize @escapeNotVerified elimination --- .../templates/layer/view.phtml | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/app/design/frontend/Magento/luma/Magento_LayeredNavigation/templates/layer/view.phtml b/app/design/frontend/Magento/luma/Magento_LayeredNavigation/templates/layer/view.phtml index 2ec6ad43f9c40..9bdb2d4252932 100644 --- a/app/design/frontend/Magento/luma/Magento_LayeredNavigation/templates/layer/view.phtml +++ b/app/design/frontend/Magento/luma/Magento_LayeredNavigation/templates/layer/view.phtml @@ -15,7 +15,7 @@ <?php if ($block->canShowBlock()) : ?> <div class="block filter" id="layered-filter-block" data-mage-init=' { - "collapsible": + "collapsible": { "openedState": "active", "collapsible": true, @@ -26,7 +26,6 @@ "element": "body" } } - }'> <?php $filtered = count($block->getLayer()->getState()->getFilters()) ?> <div class="block-title filter-title" data-count="<?= /* @noEscape */ $filtered ?>"> @@ -46,9 +45,7 @@ <?php foreach ($block->getFilters() as $filter) : ?> <?php if ($filter->getItemsCount()) : ?> <?php if (!$wrapOptions) : ?> - <strong role="heading" aria-level="2" class="block-subtitle filter-subtitle"> - <?= $block->escapeHtml(__('Shopping Options')) ?> - </strong> + <strong role="heading" aria-level="2" class="block-subtitle filter-subtitle"><?= $block->escapeHtml(__('Shopping Options')) ?></strong> <div class="filter-options" id="narrow-by-list" data-role="content" data-mage-init=' { "accordion": @@ -62,12 +59,8 @@ <?php $wrapOptions = true; endif; ?> <div data-role="collapsible" class="filter-options-item"> - <div data-role="title" class="filter-options-title"> - <?= $block->escapeHtml(__($filter->getName())) ?> - </div> - <div data-role="content" class="filter-options-content"> - <?= /* @noEscape */ $block->getChildBlock('renderer')->render($filter) ?> - </div> + <div data-role="title" class="filter-options-title"><?= $block->escapeHtml(__($filter->getName())) ?></div> + <div data-role="content" class="filter-options-content"><?= /* @noEscape */ $block->getChildBlock('renderer')->render($filter) ?></div> </div> <?php endif; ?> <?php endforeach; ?> From 02abb7352c616a3ef87ba89da6d0e21abfa9cf0d Mon Sep 17 00:00:00 2001 From: Yaroslav Rogoza <enarc@atwix.com> Date: Wed, 10 Jul 2019 11:04:00 +0200 Subject: [PATCH 648/773] Failing static tests fix --- app/code/Magento/CmsGraphQl/composer.json | 1 - .../Magento/CustomerGraphQl/Model/Resolver/UpdateCustomer.php | 3 ++- app/code/Magento/GraphQl/composer.json | 1 - app/code/Magento/UrlRewriteGraphQl/composer.json | 3 +-- 4 files changed, 3 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/CmsGraphQl/composer.json b/app/code/Magento/CmsGraphQl/composer.json index e0e8481d59b7b..18a6f1aa95e37 100644 --- a/app/code/Magento/CmsGraphQl/composer.json +++ b/app/code/Magento/CmsGraphQl/composer.json @@ -6,7 +6,6 @@ "php": "~7.1.3||~7.2.0", "magento/framework": "*", "magento/module-cms": "*", - "magento/module-store": "*", "magento/module-widget": "*" }, "suggest": { diff --git a/app/code/Magento/CustomerGraphQl/Model/Resolver/UpdateCustomer.php b/app/code/Magento/CustomerGraphQl/Model/Resolver/UpdateCustomer.php index 509052c3a031c..b2ef03fc40e5a 100644 --- a/app/code/Magento/CustomerGraphQl/Model/Resolver/UpdateCustomer.php +++ b/app/code/Magento/CustomerGraphQl/Model/Resolver/UpdateCustomer.php @@ -74,7 +74,8 @@ public function resolve( $customer = $this->getCustomer->execute($context); $this->updateCustomerAccount->execute( $customer, - $args['input'], $context->getExtensionAttributes()->getStore() + $args['input'], + $context->getExtensionAttributes()->getStore() ); $data = $this->extractCustomerData->execute($customer); diff --git a/app/code/Magento/GraphQl/composer.json b/app/code/Magento/GraphQl/composer.json index 9af81fe2eb04d..51e93f01a6e5c 100644 --- a/app/code/Magento/GraphQl/composer.json +++ b/app/code/Magento/GraphQl/composer.json @@ -5,7 +5,6 @@ "require": { "php": "~7.1.3||~7.2.0", "magento/module-eav": "*", - "magento/module-store": "*", "magento/framework": "*" }, "suggest": { diff --git a/app/code/Magento/UrlRewriteGraphQl/composer.json b/app/code/Magento/UrlRewriteGraphQl/composer.json index 1c99276269aa7..e063903a5170f 100644 --- a/app/code/Magento/UrlRewriteGraphQl/composer.json +++ b/app/code/Magento/UrlRewriteGraphQl/composer.json @@ -5,8 +5,7 @@ "require": { "php": "~7.1.3||~7.2.0", "magento/framework": "*", - "magento/module-url-rewrite": "*", - "magento/module-store": "*" + "magento/module-url-rewrite": "*" }, "suggest": { "magento/module-graph-ql": "*" From a1776a267caf3911ee3e75b888b0ed0c07b359b5 Mon Sep 17 00:00:00 2001 From: Nikita Shcherbatykh <nikita.shcherbatykh@transoftgroup.com> Date: Wed, 10 Jul 2019 16:36:43 +0300 Subject: [PATCH 649/773] MC-17947: Search by email is working incorrect in Sales > Orders grid --- .../UiComponent/DataProvider/FulltextFilter.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/DataProvider/FulltextFilter.php b/lib/internal/Magento/Framework/View/Element/UiComponent/DataProvider/FulltextFilter.php index 777f645fbc7fd..a7d7f76827cc8 100644 --- a/lib/internal/Magento/Framework/View/Element/UiComponent/DataProvider/FulltextFilter.php +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/DataProvider/FulltextFilter.php @@ -16,9 +16,12 @@ class FulltextFilter implements FilterApplierInterface { /** - * Patterns using in preg_replace for emails + * Patterns using in preg_replace */ - private const EMAIL_REPLACE_PATTERNS = ['/@/', '/\./']; + private $patterns = [ + '/[@\.]/' => '\_', + '/([+\-><\(\)~*]+)/' => ' ', + ]; /** * Returns list of columns from fulltext index (doesn't support more then one FTI per table) @@ -75,8 +78,7 @@ function ($column) use ($alias) { */ private function escapeAgainstValue(string $value): string { - $value = preg_replace('/([+\-><\(\)~*]+)/', ' ', $value); - return preg_replace(self::EMAIL_REPLACE_PATTERNS, '\_', $value); + return preg_replace(array_keys($this->patterns), array_values($this->patterns), $value); } /** From 64c45b769ea18a7e228392c52562da17c8ae26ad Mon Sep 17 00:00:00 2001 From: Wouter Samaey <wouter.samaey@storefront.be> Date: Wed, 10 Jul 2019 15:37:14 +0200 Subject: [PATCH 650/773] Simpify adding CSS classes to product image + Also make this template more like image_with_borders.phtml where the getClass() method is used and not here. --- .../Magento/Catalog/view/frontend/templates/product/image.phtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/view/frontend/templates/product/image.phtml b/app/code/Magento/Catalog/view/frontend/templates/product/image.phtml index 5a1b102ff6362..5a31f3d125c81 100644 --- a/app/code/Magento/Catalog/view/frontend/templates/product/image.phtml +++ b/app/code/Magento/Catalog/view/frontend/templates/product/image.phtml @@ -6,7 +6,7 @@ ?> <?php /** @var $block \Magento\Catalog\Block\Product\Image */ ?> -<img class="photo image" +<img class="photo image <?= $block->escapeHtmlAttr($block->getClass()) ?>" <?= $block->escapeHtml($block->getCustomAttributes()) ?> src="<?= $block->escapeUrl($block->getImageUrl()) ?>" width="<?= $block->escapeHtmlAttr($block->getWidth()) ?>" From 60cde2918199d28c54196ece4450eb7eedcd9769 Mon Sep 17 00:00:00 2001 From: Dmytro Yushkin <dyushkin@adobe.com> Date: Wed, 10 Jul 2019 09:26:16 -0500 Subject: [PATCH 651/773] MC-18004: Cannot create Shipping Label for RMA: "No authorized items or allowed shipping methods" - Fixed static tests --- .../Shipping/Test/Unit/Model/ShippingTest.php | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/Shipping/Test/Unit/Model/ShippingTest.php b/app/code/Magento/Shipping/Test/Unit/Model/ShippingTest.php index 1d4c9e9765775..1df41aeba076b 100644 --- a/app/code/Magento/Shipping/Test/Unit/Model/ShippingTest.php +++ b/app/code/Magento/Shipping/Test/Unit/Model/ShippingTest.php @@ -18,6 +18,9 @@ use Magento\Store\Model\Store; use PHPUnit_Framework_MockObject_MockObject as MockObject; +/** + * @see Shipping + */ class ShippingTest extends \PHPUnit\Framework\TestCase { /** @@ -108,12 +111,14 @@ public function testComposePackages() $this->stockItemData->expects($this->atLeastOnce())->method('getQtyIncrements') ->will($this->returnValue(0.5)); $this->carrier->method('getConfigData') - ->willReturnCallback(function ($key) { - $configData = [ - 'max_package_weight' => 10, - ]; - return isset($configData[$key]) ? $configData[$key] : 0; - }); + ->willReturnCallback( + function ($key) { + $configData = [ + 'max_package_weight' => 10, + ]; + return isset($configData[$key]) ? $configData[$key] : 0; + } + ); $this->shipping->composePackagesForCarrier($this->carrier, $request); } From 882379061809b806fc5580729a6c9c78d782f84d Mon Sep 17 00:00:00 2001 From: Stepan Furman <furman.stepan@gmail.com> Date: Wed, 10 Jul 2019 18:25:12 +0300 Subject: [PATCH 652/773] MC-18028: Varnish 6.2 with 2.3-develop export config for varnish 5 causes error. Fixed --- app/code/Magento/PageCache/etc/varnish6.vcl | 240 ++++++++++++++++++++ 1 file changed, 240 insertions(+) create mode 100644 app/code/Magento/PageCache/etc/varnish6.vcl diff --git a/app/code/Magento/PageCache/etc/varnish6.vcl b/app/code/Magento/PageCache/etc/varnish6.vcl new file mode 100644 index 0000000000000..b43c8a77bca74 --- /dev/null +++ b/app/code/Magento/PageCache/etc/varnish6.vcl @@ -0,0 +1,240 @@ +# VCL version 5.0 is not supported so it should be 4.0 even though actually used Varnish version is 6 +vcl 4.0; + +import std; +# The minimal Varnish version is 6.0 +# For SSL offloading, pass the following header in your proxy server or load balancer: '/* {{ ssl_offloaded_header }} */: https' + +backend default { + .host = "/* {{ host }} */"; + .port = "/* {{ port }} */"; + .first_byte_timeout = 600s; + .probe = { + .url = "/pub/health_check.php"; + .timeout = 2s; + .interval = 5s; + .window = 10; + .threshold = 5; + } +} + +acl purge { +/* {{ ips }} */ +} + +sub vcl_recv { + if (req.method == "PURGE") { + if (client.ip !~ purge) { + return (synth(405, "Method not allowed")); + } + # To use the X-Pool header for purging varnish during automated deployments, make sure the X-Pool header + # has been added to the response in your backend server config. This is used, for example, by the + # capistrano-magento2 gem for purging old content from varnish during it's deploy routine. + if (!req.http.X-Magento-Tags-Pattern && !req.http.X-Pool) { + return (synth(400, "X-Magento-Tags-Pattern or X-Pool header required")); + } + if (req.http.X-Magento-Tags-Pattern) { + ban("obj.http.X-Magento-Tags ~ " + req.http.X-Magento-Tags-Pattern); + } + if (req.http.X-Pool) { + ban("obj.http.X-Pool ~ " + req.http.X-Pool); + } + return (synth(200, "Purged")); + } + + if (req.method != "GET" && + req.method != "HEAD" && + req.method != "PUT" && + req.method != "POST" && + req.method != "TRACE" && + req.method != "OPTIONS" && + req.method != "DELETE") { + /* Non-RFC2616 or CONNECT which is weird. */ + return (pipe); + } + + # We only deal with GET and HEAD by default + if (req.method != "GET" && req.method != "HEAD") { + return (pass); + } + + # Bypass shopping cart, checkout and search requests + if (req.url ~ "/checkout" || req.url ~ "/catalogsearch") { + return (pass); + } + + # Bypass health check requests + if (req.url ~ "/pub/health_check.php") { + return (pass); + } + + # Set initial grace period usage status + set req.http.grace = "none"; + + # normalize url in case of leading HTTP scheme and domain + set req.url = regsub(req.url, "^http[s]?://", ""); + + # collect all cookies + std.collect(req.http.Cookie); + + # Compression filter. See https://www.varnish-cache.org/trac/wiki/FAQ/Compression + if (req.http.Accept-Encoding) { + if (req.url ~ "\.(jpg|jpeg|png|gif|gz|tgz|bz2|tbz|mp3|ogg|swf|flv)$") { + # No point in compressing these + unset req.http.Accept-Encoding; + } elsif (req.http.Accept-Encoding ~ "gzip") { + set req.http.Accept-Encoding = "gzip"; + } elsif (req.http.Accept-Encoding ~ "deflate" && req.http.user-agent !~ "MSIE") { + set req.http.Accept-Encoding = "deflate"; + } else { + # unknown algorithm + unset req.http.Accept-Encoding; + } + } + + # Remove all marketing get parameters to minimize the cache objects + if (req.url ~ "(\?|&)(gclid|cx|ie|cof|siteurl|zanpid|origin|fbclid|mc_[a-z]+|utm_[a-z]+|_bta_[a-z]+)=") { + set req.url = regsuball(req.url, "(gclid|cx|ie|cof|siteurl|zanpid|origin|fbclid|mc_[a-z]+|utm_[a-z]+|_bta_[a-z]+)=[-_A-z0-9+()%.]+&?", ""); + set req.url = regsub(req.url, "[?|&]+$", ""); + } + + # Static files caching + if (req.url ~ "^/(pub/)?(media|static)/") { + # Static files should not be cached by default + return (pass); + + # But if you use a few locales and don't use CDN you can enable caching static files by commenting previous line (#return (pass);) and uncommenting next 3 lines + #unset req.http.Https; + #unset req.http./* {{ ssl_offloaded_header }} */; + #unset req.http.Cookie; + } + + return (hash); +} + +sub vcl_hash { + if (req.http.cookie ~ "X-Magento-Vary=") { + hash_data(regsub(req.http.cookie, "^.*?X-Magento-Vary=([^;]+);*.*$", "\1")); + } + + # For multi site configurations to not cache each other's content + if (req.http.host) { + hash_data(req.http.host); + } else { + hash_data(server.ip); + } + + # To make sure http users don't see ssl warning + if (req.http./* {{ ssl_offloaded_header }} */) { + hash_data(req.http./* {{ ssl_offloaded_header }} */); + } + /* {{ design_exceptions_code }} */ + + if (req.url ~ "/graphql") { + call process_graphql_headers; + } +} + +sub process_graphql_headers { + if (req.http.Store) { + hash_data(req.http.Store); + } + if (req.http.Content-Currency) { + hash_data(req.http.Content-Currency); + } +} + +sub vcl_backend_response { + + set beresp.grace = 3d; + + if (beresp.http.content-type ~ "text") { + set beresp.do_esi = true; + } + + if (bereq.url ~ "\.js$" || beresp.http.content-type ~ "text") { + set beresp.do_gzip = true; + } + + if (beresp.http.X-Magento-Debug) { + set beresp.http.X-Magento-Cache-Control = beresp.http.Cache-Control; + } + + # cache only successfully responses and 404s + if (beresp.status != 200 && beresp.status != 404) { + set beresp.ttl = 0s; + set beresp.uncacheable = true; + return (deliver); + } elsif (beresp.http.Cache-Control ~ "private") { + set beresp.uncacheable = true; + set beresp.ttl = 86400s; + return (deliver); + } + + # validate if we need to cache it and prevent from setting cookie + if (beresp.ttl > 0s && (bereq.method == "GET" || bereq.method == "HEAD")) { + unset beresp.http.set-cookie; + } + + # If page is not cacheable then bypass varnish for 2 minutes as Hit-For-Pass + if (beresp.ttl <= 0s || + beresp.http.Surrogate-control ~ "no-store" || + (!beresp.http.Surrogate-Control && + beresp.http.Cache-Control ~ "no-cache|no-store") || + beresp.http.Vary == "*") { + # Mark as Hit-For-Pass for the next 2 minutes + set beresp.ttl = 120s; + set beresp.uncacheable = true; + } + + return (deliver); +} + +sub vcl_deliver { + if (resp.http.X-Magento-Debug) { + if (resp.http.x-varnish ~ " ") { + set resp.http.X-Magento-Cache-Debug = "HIT"; + set resp.http.Grace = req.http.grace; + } else { + set resp.http.X-Magento-Cache-Debug = "MISS"; + } + } else { + unset resp.http.Age; + } + + # Not letting browser to cache non-static files. + if (resp.http.Cache-Control !~ "private" && req.url !~ "^/(pub/)?(media|static)/") { + set resp.http.Pragma = "no-cache"; + set resp.http.Expires = "-1"; + set resp.http.Cache-Control = "no-store, no-cache, must-revalidate, max-age=0"; + } + + unset resp.http.X-Magento-Debug; + unset resp.http.X-Magento-Tags; + unset resp.http.X-Powered-By; + unset resp.http.Server; + unset resp.http.X-Varnish; + unset resp.http.Via; + unset resp.http.Link; +} + +sub vcl_hit { + if (obj.ttl >= 0s) { + # Hit within TTL period + return (deliver); + } + if (std.healthy(req.backend_hint)) { + if (obj.ttl + /* {{ grace_period }} */s > 0s) { + # Hit after TTL expiration, but within grace period + set req.http.grace = "normal (healthy server)"; + return (deliver); + } else { + # Hit after TTL and grace expiration + return (restart); + } + } else { + # server is not healthy, retrieve from cache + set req.http.grace = "unlimited (unhealthy server)"; + return (deliver); + } +} From 21768739df8d8d68ae5db36eaccc8e54c3401044 Mon Sep 17 00:00:00 2001 From: Stepan Furman <furman.stepan@gmail.com> Date: Wed, 10 Jul 2019 18:28:19 +0300 Subject: [PATCH 653/773] MC-18031: Create Varnish 6 template for export. Implemented --- .../Config/Form/Field/Export/Varnish6.php | 22 +++++++++++++++++++ .../PageCache/ExportVarnishConfig.php | 3 +++ app/code/Magento/PageCache/Model/Config.php | 17 ++++++++++++-- .../Model/Varnish/VclTemplateLocator.php | 11 ++++++++++ .../PageCache/etc/adminhtml/system.xml | 6 +++++ app/code/Magento/PageCache/etc/config.xml | 3 +++ 6 files changed, 60 insertions(+), 2 deletions(-) create mode 100644 app/code/Magento/PageCache/Block/System/Config/Form/Field/Export/Varnish6.php diff --git a/app/code/Magento/PageCache/Block/System/Config/Form/Field/Export/Varnish6.php b/app/code/Magento/PageCache/Block/System/Config/Form/Field/Export/Varnish6.php new file mode 100644 index 0000000000000..c5a6be9ac1b1c --- /dev/null +++ b/app/code/Magento/PageCache/Block/System/Config/Form/Field/Export/Varnish6.php @@ -0,0 +1,22 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\PageCache\Block\System\Config\Form\Field\Export; + +/** + * Class Export + */ +class Varnish6 extends \Magento\PageCache\Block\System\Config\Form\Field\Export +{ + /** + * Return Varnish version to this class + * + * @return int + */ + public function getVarnishVersion() + { + return 6; + } +} diff --git a/app/code/Magento/PageCache/Controller/Adminhtml/PageCache/ExportVarnishConfig.php b/app/code/Magento/PageCache/Controller/Adminhtml/PageCache/ExportVarnishConfig.php index b3a2e383c2531..a79fcd848a58e 100644 --- a/app/code/Magento/PageCache/Controller/Adminhtml/PageCache/ExportVarnishConfig.php +++ b/app/code/Magento/PageCache/Controller/Adminhtml/PageCache/ExportVarnishConfig.php @@ -50,6 +50,9 @@ public function execute() $fileName = 'varnish.vcl'; $varnishVersion = $this->getRequest()->getParam('varnish'); switch ($varnishVersion) { + case 6: + $content = $this->config->getVclFile(\Magento\PageCache\Model\Config::VARNISH_6_CONFIGURATION_PATH); + break; case 5: $content = $this->config->getVclFile(\Magento\PageCache\Model\Config::VARNISH_5_CONFIGURATION_PATH); break; diff --git a/app/code/Magento/PageCache/Model/Config.php b/app/code/Magento/PageCache/Model/Config.php index 83db8c0dec3b1..7d856420dd664 100644 --- a/app/code/Magento/PageCache/Model/Config.php +++ b/app/code/Magento/PageCache/Model/Config.php @@ -49,6 +49,11 @@ class Config */ protected $_scopeConfig; + /** + * XML path to Varnish 5 config template path + */ + const VARNISH_6_CONFIGURATION_PATH = 'system/full_page_cache/varnish6/path'; + /** * XML path to Varnish 5 config template path */ @@ -145,8 +150,16 @@ public function getVclFile($vclTemplatePath) self::XML_VARNISH_PAGECACHE_DESIGN_THEME_REGEX, \Magento\Store\Model\ScopeInterface::SCOPE_STORE ); - - $version = $vclTemplatePath === self::VARNISH_5_CONFIGURATION_PATH ? 5 : 4; + switch ($vclTemplatePath) { + case self::VARNISH_6_CONFIGURATION_PATH: + $version = 6; + break; + case self::VARNISH_5_CONFIGURATION_PATH: + $version = 5; + break; + default: + $version = 4; + } $sslOffloadedHeader = $this->_scopeConfig->getValue( \Magento\Framework\HTTP\PhpEnvironment\Request::XML_PATH_OFFLOADER_HEADER ); diff --git a/app/code/Magento/PageCache/Model/Varnish/VclTemplateLocator.php b/app/code/Magento/PageCache/Model/Varnish/VclTemplateLocator.php index 702f5b52434db..a12dbd8f4b5cf 100644 --- a/app/code/Magento/PageCache/Model/Varnish/VclTemplateLocator.php +++ b/app/code/Magento/PageCache/Model/Varnish/VclTemplateLocator.php @@ -15,6 +15,11 @@ class VclTemplateLocator implements VclTemplateLocatorInterface { + /** + * XML path to Varnish 5 config template path + */ + const VARNISH_6_CONFIGURATION_PATH = 'system/full_page_cache/varnish6/path'; + /** * XML path to Varnish 5 config template path */ @@ -35,12 +40,18 @@ class VclTemplateLocator implements VclTemplateLocatorInterface */ const VARNISH_SUPPORTED_VERSION_5 = '5'; + /** + * + */ + const VARNISH_SUPPORTED_VERSION_6 = '6'; + /** * @var array */ private $supportedVarnishVersions = [ self::VARNISH_SUPPORTED_VERSION_4 => self::VARNISH_4_CONFIGURATION_PATH, self::VARNISH_SUPPORTED_VERSION_5 => self::VARNISH_5_CONFIGURATION_PATH, + self::VARNISH_SUPPORTED_VERSION_6 => self::VARNISH_6_CONFIGURATION_PATH, ]; /** diff --git a/app/code/Magento/PageCache/etc/adminhtml/system.xml b/app/code/Magento/PageCache/etc/adminhtml/system.xml index 2a4439ac6a9cf..8013ad40ef5aa 100644 --- a/app/code/Magento/PageCache/etc/adminhtml/system.xml +++ b/app/code/Magento/PageCache/etc/adminhtml/system.xml @@ -62,6 +62,12 @@ <field id="caching_application">1</field> </depends> </field> + <field id="export_button_version6" type="button" sortOrder="40" showInDefault="1" showInWebsite="0" showInStore="0"> + <frontend_model>Magento\PageCache\Block\System\Config\Form\Field\Export\Varnish6</frontend_model> + <depends> + <field id="caching_application">1</field> + </depends> + </field> <depends> <field id="caching_application">2</field> </depends> diff --git a/app/code/Magento/PageCache/etc/config.xml b/app/code/Magento/PageCache/etc/config.xml index 9465b3bade48b..8a2412030c6aa 100644 --- a/app/code/Magento/PageCache/etc/config.xml +++ b/app/code/Magento/PageCache/etc/config.xml @@ -14,6 +14,9 @@ </design> <system> <full_page_cache> + <varnish6> + <path>varnish6.vcl</path> + </varnish6> <varnish5> <path>varnish5.vcl</path> </varnish5> From d51064293f640cd9d823410fee93590aa4e79a72 Mon Sep 17 00:00:00 2001 From: nmalevanec <mikola.malevanec@transoftgroup.com> Date: Fri, 10 May 2019 13:26:29 +0300 Subject: [PATCH 654/773] Fix static tests. --- .../Console/Command/ModuleConfigStatusCommand.php | 14 +++++++++++--- setup/src/Magento/Setup/Console/CommandList.php | 1 + .../Command/ModuleConfigStatusCommandTest.php | 6 +++++- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/setup/src/Magento/Setup/Console/Command/ModuleConfigStatusCommand.php b/setup/src/Magento/Setup/Console/Command/ModuleConfigStatusCommand.php index eb1ac283cabba..70dbf14728bd7 100644 --- a/setup/src/Magento/Setup/Console/Command/ModuleConfigStatusCommand.php +++ b/setup/src/Magento/Setup/Console/Command/ModuleConfigStatusCommand.php @@ -56,8 +56,12 @@ public function __construct( */ protected function configure() { - $this->setName('module:config:status') - ->setDescription('Checks the modules configuration in the \'app/etc/config.php\' file and reports if they are up to date or not'); + $this + ->setName('module:config:status') + ->setDescription( + 'Checks the modules configuration in the \'app/etc/config.php\' file ' + . 'and reports if they are up to date or not' + ); parent::configure(); } @@ -71,6 +75,7 @@ protected function execute(InputInterface $input, OutputInterface $output) // the config as currently in app/etc/config.php $currentConfig = $this->configReader->load(ConfigFilePool::APP_CONFIG); if (!array_key_exists(ConfigOptionsListConstants::KEY_MODULES, $currentConfig)) { + // phpcs:ignore Magento2.Exceptions.DirectThrow throw new \Exception('Can\'t find the modules configuration in the \'app/etc/config.php\' file.'); } @@ -82,14 +87,17 @@ protected function execute(InputInterface $input, OutputInterface $output) $correctModuleConfig = $installer->getModulesConfig(); if ($currentModuleConfig !== $correctModuleConfig) { + // phpcs:ignore Magento2.Exceptions.DirectThrow throw new \Exception( - 'The modules configuration in the \'app/etc/config.php\' file is outdated. Run \'setup:upgrade\' to fix it.' + 'The modules configuration in the \'app/etc/config.php\' file is outdated. ' + . 'Run \'setup:upgrade\' to fix it.' ); } $output->writeln( '<info>The modules configuration is up to date.</info>' ); + // phpcs:disable Magento2.Exceptions.ThrowCatch } catch (\Exception $e) { $output->writeln('<error>' . $e->getMessage() . '</error>'); diff --git a/setup/src/Magento/Setup/Console/CommandList.php b/setup/src/Magento/Setup/Console/CommandList.php index 101ff9edd2a0e..f0dad6f4a7452 100644 --- a/setup/src/Magento/Setup/Console/CommandList.php +++ b/setup/src/Magento/Setup/Console/CommandList.php @@ -92,6 +92,7 @@ public function getCommands() if (class_exists($class)) { $commands[] = $this->serviceManager->get($class); } else { + // phpcs:ignore Magento2.Exceptions.DirectThrow throw new \Exception('Class ' . $class . ' does not exist'); } } diff --git a/setup/src/Magento/Setup/Test/Unit/Console/Command/ModuleConfigStatusCommandTest.php b/setup/src/Magento/Setup/Test/Unit/Console/Command/ModuleConfigStatusCommandTest.php index 946e122b3c975..16577ed2db738 100644 --- a/setup/src/Magento/Setup/Test/Unit/Console/Command/ModuleConfigStatusCommandTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Console/Command/ModuleConfigStatusCommandTest.php @@ -13,6 +13,9 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Tester\CommandTester; +/** + * Tests for module config status command. + */ class ModuleConfigStatusCommandTest extends TestCase { /** @@ -49,7 +52,8 @@ public function testExecute(array $currentConfig, array $correctConfig, string $ public function executeDataProvider() { $successMessage = 'The modules configuration is up to date.' . PHP_EOL; - $failureMessage = 'The modules configuration in the \'app/etc/config.php\' file is outdated. Run \'setup:upgrade\' to fix it.' . PHP_EOL; + $failureMessage = 'The modules configuration in the \'app/etc/config.php\' ' + . 'file is outdated. Run \'setup:upgrade\' to fix it.' . PHP_EOL; return [ [ From d6eee26aa40c0d77418188b72f8ee333e3b04e35 Mon Sep 17 00:00:00 2001 From: Deepty Thampy <dthampy@adobe.com> Date: Wed, 10 Jul 2019 14:52:12 -0500 Subject: [PATCH 655/773] MC-17875: Refactor GraphQl Integration tests - code review comments --- .../Customer/PlaceOrderWithAuthorizeNetTest.php | 14 +++----------- .../SetAuthorizeNetPaymentMethodOnCartTest.php | 4 ++-- .../Guest/PlaceOrderWithAuthorizeNetTest.php | 15 ++------------- .../SetAuthorizeNetPaymentMethodOnCartTest.php | 2 +- .../PaypalExpressSetPaymentMethodTest.php | 7 ------- .../Resolver/Customer/PaypalExpressTokenTest.php | 7 ------- .../Customer/PlaceOrderWithPayflowProTest.php | 8 +------- .../Guest/PaypalExpressSetPaymentMethodTest.php | 10 +--------- .../Resolver/Guest/PaypalExpressTokenTest.php | 7 ------- .../PaypalPayflowProSetPaymentMethodTest.php | 7 ------- .../Guest/PaypalPayflowProTokenExceptionTest.php | 7 ------- .../Resolver/Guest/PaypalPayflowProTokenTest.php | 8 +------- .../Guest/PlaceOrderWithPayflowLinkTest.php | 1 - .../PaypalGraphQl/PaypalExpressAbstractTest.php | 11 +++++++++++ .../PaypalPayflowProAbstractTest.php | 8 ++++++++ 15 files changed, 30 insertions(+), 86 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/AuthorizenetGraphQl/Model/Resolver/Customer/PlaceOrderWithAuthorizeNetTest.php b/dev/tests/integration/testsuite/Magento/AuthorizenetGraphQl/Model/Resolver/Customer/PlaceOrderWithAuthorizeNetTest.php index 021e4d9db7766..90ec6686c5a3c 100644 --- a/dev/tests/integration/testsuite/Magento/AuthorizenetGraphQl/Model/Resolver/Customer/PlaceOrderWithAuthorizeNetTest.php +++ b/dev/tests/integration/testsuite/Magento/AuthorizenetGraphQl/Model/Resolver/Customer/PlaceOrderWithAuthorizeNetTest.php @@ -16,9 +16,7 @@ use Magento\Framework\HTTP\ZendClientFactory; use Magento\TestFramework\ObjectManager; use PHPUnit\Framework\MockObject\Builder\InvocationMocker; -use Magento\Payment\Gateway\Data\PaymentDataObjectFactory; use PHPUnit\Framework\MockObject\MockObject; -use Magento\Quote\Model\Quote\PaymentFactory; use PHPUnit\Framework\TestCase; use Zend_Http_Response; @@ -27,14 +25,13 @@ * * @magentoAppArea graphql * @magentoDbIsolation disabled - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class PlaceOrderWithAuthorizeNetTest extends TestCase { - /** @var ObjectManager */ + /** @var ObjectManager */ private $objectManager; - /** @var GetMaskedQuoteIdByReservedOrderId */ + /** @var GetMaskedQuoteIdByReservedOrderId */ private $getMaskedQuoteIdByReservedOrderId; /** @var SerializerInterface */ @@ -46,15 +43,12 @@ class PlaceOrderWithAuthorizeNetTest extends TestCase /** @var ZendClient|MockObject|InvocationMocker */ private $clientMock; - /** @var CustomerTokenServiceInterface */ + /** @var CustomerTokenServiceInterface */ private $customerTokenService; /** @var Zend_Http_Response */ protected $responseMock; - /** @var PaymentFactory */ - private $paymentFactory; - protected function setUp() : void { $this->objectManager = Bootstrap::getObjectManager(); @@ -71,8 +65,6 @@ protected function setUp() : void $clientFactoryMock = $this->createMock(ZendClientFactory::class); $clientFactoryMock->method('create') ->willReturn($this->clientMock); - /** @var PaymentDataObjectFactory $paymentFactory */ - $this->paymentFactory = $this->objectManager->get(PaymentDataObjectFactory::class); $this->objectManager->addSharedInstance($clientFactoryMock, ZendClientFactory::class); } diff --git a/dev/tests/integration/testsuite/Magento/AuthorizenetGraphQl/Model/Resolver/Customer/SetAuthorizeNetPaymentMethodOnCartTest.php b/dev/tests/integration/testsuite/Magento/AuthorizenetGraphQl/Model/Resolver/Customer/SetAuthorizeNetPaymentMethodOnCartTest.php index 27c6eb0455efc..e19042693b756 100644 --- a/dev/tests/integration/testsuite/Magento/AuthorizenetGraphQl/Model/Resolver/Customer/SetAuthorizeNetPaymentMethodOnCartTest.php +++ b/dev/tests/integration/testsuite/Magento/AuthorizenetGraphQl/Model/Resolver/Customer/SetAuthorizeNetPaymentMethodOnCartTest.php @@ -26,13 +26,13 @@ class SetAuthorizeNetPaymentMethodOnCartTest extends TestCase /** @var \Magento\Framework\ObjectManagerInterface */ private $objectManager; - /** @var GetMaskedQuoteIdByReservedOrderId */ + /** @var GetMaskedQuoteIdByReservedOrderId */ private $getMaskedQuoteIdByReservedOrderId; /** @var SerializerInterface */ private $jsonSerializer; - /** @var CustomerTokenServiceInterface */ + /** @var CustomerTokenServiceInterface */ private $customerTokenService; /** @var GraphQlRequest */ diff --git a/dev/tests/integration/testsuite/Magento/AuthorizenetGraphQl/Model/Resolver/Guest/PlaceOrderWithAuthorizeNetTest.php b/dev/tests/integration/testsuite/Magento/AuthorizenetGraphQl/Model/Resolver/Guest/PlaceOrderWithAuthorizeNetTest.php index 0b5f3ca32ad29..383abf81a111a 100644 --- a/dev/tests/integration/testsuite/Magento/AuthorizenetGraphQl/Model/Resolver/Guest/PlaceOrderWithAuthorizeNetTest.php +++ b/dev/tests/integration/testsuite/Magento/AuthorizenetGraphQl/Model/Resolver/Guest/PlaceOrderWithAuthorizeNetTest.php @@ -7,7 +7,6 @@ namespace Magento\AuthorizenetGraphQl\Model\Resolver\Guest; -use Magento\Framework\App\Request\Http; use Magento\Framework\Serialize\SerializerInterface; use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; use Magento\GraphQl\Service\GraphQlRequest; @@ -16,9 +15,7 @@ use Magento\Framework\HTTP\ZendClientFactory; use Magento\TestFramework\ObjectManager; use PHPUnit\Framework\MockObject\Builder\InvocationMocker; -use Magento\Payment\Gateway\Data\PaymentDataObjectFactory; use PHPUnit\Framework\MockObject\MockObject; -use Magento\Quote\Model\Quote\PaymentFactory; use PHPUnit\Framework\TestCase; use Zend_Http_Response; @@ -27,14 +24,13 @@ * * @magentoAppArea graphql * @magentoDbIsolation disabled - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class PlaceOrderWithAuthorizeNetTest extends TestCase { - /** @var ObjectManager */ + /** @var ObjectManager */ private $objectManager; - /** @var GetMaskedQuoteIdByReservedOrderId */ + /** @var GetMaskedQuoteIdByReservedOrderId */ private $getMaskedQuoteIdByReservedOrderId; /** @var SerializerInterface */ @@ -49,15 +45,10 @@ class PlaceOrderWithAuthorizeNetTest extends TestCase /** @var Zend_Http_Response */ protected $responseMock; - /** @var PaymentFactory */ - private $paymentFactory; - protected function setUp() : void { $this->objectManager = Bootstrap::getObjectManager(); - $this->graphql = $this->objectManager->get(\Magento\GraphQl\Controller\GraphQl::class); $this->jsonSerializer = $this->objectManager->get(SerializerInterface::class); - $this->request = $this->objectManager->get(Http::class); $this->getMaskedQuoteIdByReservedOrderId = $this->objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); $this->graphQlRequest = $this->objectManager->create(GraphQlRequest::class); $this->clientMock = $this->createMock(ZendClient::class); @@ -69,8 +60,6 @@ protected function setUp() : void $clientFactoryMock = $this->createMock(ZendClientFactory::class); $clientFactoryMock->method('create') ->willReturn($this->clientMock); - /** @var PaymentDataObjectFactory $paymentFactory */ - $this->paymentFactory = $this->objectManager->get(PaymentDataObjectFactory::class); $this->objectManager->addSharedInstance($clientFactoryMock, ZendClientFactory::class); } diff --git a/dev/tests/integration/testsuite/Magento/AuthorizenetGraphQl/Model/Resolver/Guest/SetAuthorizeNetPaymentMethodOnCartTest.php b/dev/tests/integration/testsuite/Magento/AuthorizenetGraphQl/Model/Resolver/Guest/SetAuthorizeNetPaymentMethodOnCartTest.php index 1386e3b1980ac..95dcf9829939f 100644 --- a/dev/tests/integration/testsuite/Magento/AuthorizenetGraphQl/Model/Resolver/Guest/SetAuthorizeNetPaymentMethodOnCartTest.php +++ b/dev/tests/integration/testsuite/Magento/AuthorizenetGraphQl/Model/Resolver/Guest/SetAuthorizeNetPaymentMethodOnCartTest.php @@ -26,7 +26,7 @@ class SetAuthorizeNetPaymentMethodOnCartTest extends TestCase /** @var ObjectManager */ private $objectManager; - /** @var GetMaskedQuoteIdByReservedOrderId */ + /** @var GetMaskedQuoteIdByReservedOrderId */ private $getMaskedQuoteIdByReservedOrderId; /** @var SerializerInterface */ diff --git a/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Customer/PaypalExpressSetPaymentMethodTest.php b/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Customer/PaypalExpressSetPaymentMethodTest.php index 4c956dfb06149..f367c0242fdb0 100644 --- a/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Customer/PaypalExpressSetPaymentMethodTest.php +++ b/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Customer/PaypalExpressSetPaymentMethodTest.php @@ -7,7 +7,6 @@ namespace Magento\PaypalGraphQl\Model\Resolver\Customer; -use Magento\GraphQl\Service\GraphQlRequest; use Magento\Paypal\Model\Api\Nvp; use Magento\PaypalGraphQl\PaypalExpressAbstractTest; use Magento\Framework\Serialize\SerializerInterface; @@ -21,11 +20,6 @@ */ class PaypalExpressSetPaymentMethodTest extends PaypalExpressAbstractTest { - /** - * @var GraphQlRequest - */ - private $graphQlRequest; - /** * @var SerializerInterface */ @@ -42,7 +36,6 @@ protected function setUp() $this->json = $this->objectManager->get(SerializerInterface::class); $this->quoteIdToMaskedId = $this->objectManager->get(QuoteIdToMaskedQuoteId::class); - $this->graphQlRequest = $this->objectManager->create(GraphQlRequest::class); } /** diff --git a/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Customer/PaypalExpressTokenTest.php b/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Customer/PaypalExpressTokenTest.php index 3298d2524bc09..8a48ddd0acf24 100644 --- a/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Customer/PaypalExpressTokenTest.php +++ b/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Customer/PaypalExpressTokenTest.php @@ -7,7 +7,6 @@ namespace Magento\PaypalGraphQl\Model\Resolver\Customer; -use Magento\GraphQl\Service\GraphQlRequest; use Magento\Paypal\Model\Api\Nvp; use Magento\PaypalGraphQl\PaypalExpressAbstractTest; use Magento\Framework\Serialize\SerializerInterface; @@ -20,11 +19,6 @@ */ class PaypalExpressTokenTest extends PaypalExpressAbstractTest { - /** - * @var GraphQlRequest - */ - private $graphQlRequest; - /** * @var SerializerInterface */ @@ -41,7 +35,6 @@ protected function setUp() $this->json = $this->objectManager->get(SerializerInterface::class); $this->quoteIdToMaskedId = $this->objectManager->get(QuoteIdToMaskedQuoteId::class); - $this->graphQlRequest = $this->objectManager->create(GraphQlRequest::class); } /** diff --git a/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Customer/PlaceOrderWithPayflowProTest.php b/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Customer/PlaceOrderWithPayflowProTest.php index 00fbdbcd353c2..444588195e0ae 100644 --- a/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Customer/PlaceOrderWithPayflowProTest.php +++ b/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Customer/PlaceOrderWithPayflowProTest.php @@ -7,7 +7,6 @@ namespace Magento\PaypalGraphQl\Model\Resolver\Customer; -use Magento\GraphQl\Service\GraphQlRequest; use Magento\PaypalGraphQl\PaypalPayflowProAbstractTest; use Magento\Framework\Serialize\SerializerInterface; use Magento\Quote\Model\QuoteIdToMaskedQuoteId; @@ -21,11 +20,6 @@ */ class PlaceOrderWithPayflowProTest extends PaypalPayflowProAbstractTest { - /** - * @var GraphQlRequest - */ - private $graphQlRequest; - /** * @var SerializerInterface */ @@ -42,13 +36,13 @@ protected function setUp() $this->json = $this->objectManager->get(SerializerInterface::class); $this->quoteIdToMaskedId = $this->objectManager->get(QuoteIdToMaskedQuoteId::class); - $this->graphQlRequest = $this->objectManager->create(GraphQlRequest::class); } /** * Test end to end test to process a paypal payflow pro order * * @return void + * @magentoDataFixture Magento/Sales/_files/default_rollback.php * @magentoDataFixture Magento/Customer/_files/customer.php * @magentoDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php diff --git a/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/PaypalExpressSetPaymentMethodTest.php b/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/PaypalExpressSetPaymentMethodTest.php index ec5883579f6a2..0b8b18d88e00e 100644 --- a/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/PaypalExpressSetPaymentMethodTest.php +++ b/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/PaypalExpressSetPaymentMethodTest.php @@ -7,13 +7,10 @@ namespace Magento\PaypalGraphQl\Model\Resolver\Guest; -use Magento\Framework\App\Request\Http; -use Magento\GraphQl\Service\GraphQlRequest; use Magento\Paypal\Model\Api\Nvp; use Magento\PaypalGraphQl\PaypalExpressAbstractTest; use Magento\Framework\Serialize\SerializerInterface; use Magento\Quote\Model\QuoteIdToMaskedQuoteId; -use Magento\TestFramework\Helper\Bootstrap; use Magento\Framework\UrlInterface; /** @@ -23,11 +20,6 @@ */ class PaypalExpressSetPaymentMethodTest extends PaypalExpressAbstractTest { - /** - * @var GraphQlRequest - */ - private $graphQlRequest; - /** * @var SerializerInterface */ @@ -44,7 +36,6 @@ protected function setUp() $this->json = $this->objectManager->get(SerializerInterface::class); $this->quoteIdToMaskedId = $this->objectManager->get(QuoteIdToMaskedQuoteId::class); - $this->graphQlRequest = $this->objectManager->create(GraphQlRequest::class); } /** @@ -53,6 +44,7 @@ protected function setUp() * @param string $paymentMethod * @return void * @dataProvider getPaypalCodesProvider + * @magentoDataFixture Magento/Sales/_files/default_rollback.php * @magentoDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php * @magentoDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php diff --git a/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/PaypalExpressTokenTest.php b/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/PaypalExpressTokenTest.php index 950eb2b9f6dc8..f91ffd4089d7b 100644 --- a/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/PaypalExpressTokenTest.php +++ b/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/PaypalExpressTokenTest.php @@ -9,7 +9,6 @@ use Magento\Framework\Exception\LocalizedException; use Magento\Framework\GraphQl\Exception\GraphQlInputException; -use Magento\GraphQl\Service\GraphQlRequest; use Magento\Paypal\Model\Api\Nvp; use Magento\PaypalGraphQl\PaypalExpressAbstractTest; use Magento\Framework\Serialize\SerializerInterface; @@ -22,11 +21,6 @@ */ class PaypalExpressTokenTest extends PaypalExpressAbstractTest { - /** - * @var GraphQlRequest - */ - private $graphQlRequest; - /** * @var SerializerInterface */ @@ -43,7 +37,6 @@ protected function setUp() $this->json = $this->objectManager->get(SerializerInterface::class); $this->quoteIdToMaskedId = $this->objectManager->get(QuoteIdToMaskedQuoteId::class); - $this->graphQlRequest = $this->objectManager->create(GraphQlRequest::class); } /** diff --git a/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/PaypalPayflowProSetPaymentMethodTest.php b/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/PaypalPayflowProSetPaymentMethodTest.php index 8e1df6e5525bf..8121facaf0f55 100644 --- a/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/PaypalPayflowProSetPaymentMethodTest.php +++ b/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/PaypalPayflowProSetPaymentMethodTest.php @@ -7,7 +7,6 @@ namespace Magento\PaypalGraphQl\Model\Resolver\Guest; -use Magento\GraphQl\Service\GraphQlRequest; use Magento\PaypalGraphQl\PaypalPayflowProAbstractTest; use Magento\Framework\Serialize\SerializerInterface; use Magento\Quote\Model\QuoteIdToMaskedQuoteId; @@ -21,11 +20,6 @@ */ class PaypalPayflowProSetPaymentMethodTest extends PaypalPayflowProAbstractTest { - /** - * @var GraphQlRequest - */ - private $graphQlRequest; - /** * @var SerializerInterface */ @@ -42,7 +36,6 @@ protected function setUp() $this->json = $this->objectManager->get(SerializerInterface::class); $this->quoteIdToMaskedId = $this->objectManager->get(QuoteIdToMaskedQuoteId::class); - $this->graphQlRequest = $this->objectManager->create(GraphQlRequest::class); } /** diff --git a/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/PaypalPayflowProTokenExceptionTest.php b/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/PaypalPayflowProTokenExceptionTest.php index 3b6fca8ec42bc..b5de225b7abbc 100644 --- a/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/PaypalPayflowProTokenExceptionTest.php +++ b/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/PaypalPayflowProTokenExceptionTest.php @@ -8,7 +8,6 @@ namespace Magento\PaypalGraphQl\Model\Resolver\Guest; use Magento\Framework\GraphQl\Exception\GraphQlInputException; -use Magento\GraphQl\Service\GraphQlRequest; use Magento\PaypalGraphQl\PaypalPayflowProAbstractTest; use Magento\Framework\Serialize\SerializerInterface; use Magento\Quote\Model\QuoteIdToMaskedQuoteId; @@ -20,11 +19,6 @@ */ class PaypalPayflowProTokenExceptionTest extends PaypalPayflowProAbstractTest { - /** - * @var GraphQlRequest - */ - private $graphQlRequest; - /** * @var SerializerInterface */ @@ -41,7 +35,6 @@ protected function setUp() $this->json = $this->objectManager->get(SerializerInterface::class); $this->quoteIdToMaskedId = $this->objectManager->get(QuoteIdToMaskedQuoteId::class); - $this->graphQlRequest = $this->objectManager->create(GraphQlRequest::class); } /** diff --git a/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/PaypalPayflowProTokenTest.php b/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/PaypalPayflowProTokenTest.php index e8f9297c802c5..8bbb0dff2d69a 100644 --- a/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/PaypalPayflowProTokenTest.php +++ b/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/PaypalPayflowProTokenTest.php @@ -8,7 +8,6 @@ namespace Magento\PaypalGraphQl\Model\Resolver\Guest; use Magento\Framework\GraphQl\Exception\GraphQlInputException; -use Magento\GraphQl\Service\GraphQlRequest; use Magento\PaypalGraphQl\PaypalPayflowProAbstractTest; use Magento\Framework\Serialize\SerializerInterface; use Magento\Quote\Model\QuoteIdToMaskedQuoteId; @@ -21,11 +20,6 @@ */ class PaypalPayflowProTokenTest extends PaypalPayflowProAbstractTest { - /** - * @var GraphQlRequest - */ - private $graphQlRequest; - /** * @var SerializerInterface */ @@ -42,13 +36,13 @@ protected function setUp() $this->json = $this->objectManager->get(SerializerInterface::class); $this->quoteIdToMaskedId = $this->objectManager->get(QuoteIdToMaskedQuoteId::class); - $this->graphQlRequest = $this->objectManager->create(GraphQlRequest::class); } /** * Test create paypal token for guest * * @return void + * @magentoDataFixture Magento/Sales/_files/default_rollback.php * @magentoDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php * @magentoDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php diff --git a/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/PlaceOrderWithPayflowLinkTest.php b/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/PlaceOrderWithPayflowLinkTest.php index eab686c93fee3..789d4b34c8ced 100644 --- a/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/PlaceOrderWithPayflowLinkTest.php +++ b/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/PlaceOrderWithPayflowLinkTest.php @@ -52,7 +52,6 @@ protected function setUp() { $this->objectManager = Bootstrap::getObjectManager(); $this->graphQlRequest = $this->objectManager->create(GraphQlRequest::class); - $this->json = $this->objectManager->get(SerializerInterface::class); $this->getMaskedQuoteIdByReservedOrderId = $this->objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); $this->gateway = $this->getMockBuilder(Gateway::class) diff --git a/dev/tests/integration/testsuite/Magento/PaypalGraphQl/PaypalExpressAbstractTest.php b/dev/tests/integration/testsuite/Magento/PaypalGraphQl/PaypalExpressAbstractTest.php index 080ebd02e423e..9d4d3717b8beb 100644 --- a/dev/tests/integration/testsuite/Magento/PaypalGraphQl/PaypalExpressAbstractTest.php +++ b/dev/tests/integration/testsuite/Magento/PaypalGraphQl/PaypalExpressAbstractTest.php @@ -14,6 +14,7 @@ use Magento\Framework\HTTP\Adapter\CurlFactory; use Magento\Framework\Locale\ResolverInterface; use Magento\GraphQl\Controller\GraphQl; +use Magento\GraphQl\Service\GraphQlRequest; use Magento\Payment\Model\Method\Logger; use Magento\Paypal\Model\Api\Nvp; use Magento\Paypal\Model\Api\PayflowNvp; @@ -53,6 +54,12 @@ abstract class PaypalExpressAbstractTest extends TestCase */ protected $graphqlController; + /** + * @var GraphQlRequest + */ + protected $graphQlRequest; + + protected function setUp() { $this->objectManager = Bootstrap::getObjectManager(); @@ -72,6 +79,10 @@ protected function setUp() $this->objectManager->addSharedInstance($apiFactoryMock, ApiFactory::class); $this->graphqlController = $this->objectManager->get(GraphQl::class); + + $this->graphQlRequest = $this->objectManager->create(GraphQlRequest::class); + + } protected function tearDown() diff --git a/dev/tests/integration/testsuite/Magento/PaypalGraphQl/PaypalPayflowProAbstractTest.php b/dev/tests/integration/testsuite/Magento/PaypalGraphQl/PaypalPayflowProAbstractTest.php index 332e08be5b434..e5a94c1f1039b 100644 --- a/dev/tests/integration/testsuite/Magento/PaypalGraphQl/PaypalPayflowProAbstractTest.php +++ b/dev/tests/integration/testsuite/Magento/PaypalGraphQl/PaypalPayflowProAbstractTest.php @@ -8,6 +8,7 @@ namespace Magento\PaypalGraphQl; use Magento\GraphQl\Controller\GraphQl; +use Magento\GraphQl\Service\GraphQlRequest; use Magento\Paypal\Model\Payflow\Service\Gateway; use Magento\Quote\Model\Quote; use Magento\Quote\Model\QuoteFactory; @@ -43,6 +44,11 @@ abstract class PaypalPayflowProAbstractTest extends TestCase */ protected $graphqlController; + /** + * @var GraphQlRequest + */ + protected $graphQlRequest; + protected function setUp() { $this->objectManager = Bootstrap::getObjectManager(); @@ -50,6 +56,8 @@ protected function setUp() $this->objectManager->addSharedInstance($this->getGatewayMock(), Gateway::class); $this->graphqlController = $this->objectManager->get(GraphQl::class); + + $this->graphQlRequest = $this->objectManager->create(GraphQlRequest::class); } protected function tearDown() From 8d0e0ccaad2f0203d687ecbb3831da534db619fd Mon Sep 17 00:00:00 2001 From: Deepty Thampy <dthampy@adobe.com> Date: Wed, 10 Jul 2019 16:27:19 -0500 Subject: [PATCH 656/773] MC-17875: Refactor GraphQl Integration tests - fix static failures --- .../Magento/PaypalGraphQl/PaypalExpressAbstractTest.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/PaypalGraphQl/PaypalExpressAbstractTest.php b/dev/tests/integration/testsuite/Magento/PaypalGraphQl/PaypalExpressAbstractTest.php index 9d4d3717b8beb..936bbcf6503d5 100644 --- a/dev/tests/integration/testsuite/Magento/PaypalGraphQl/PaypalExpressAbstractTest.php +++ b/dev/tests/integration/testsuite/Magento/PaypalGraphQl/PaypalExpressAbstractTest.php @@ -59,7 +59,6 @@ abstract class PaypalExpressAbstractTest extends TestCase */ protected $graphQlRequest; - protected function setUp() { $this->objectManager = Bootstrap::getObjectManager(); @@ -81,8 +80,6 @@ protected function setUp() $this->graphqlController = $this->objectManager->get(GraphQl::class); $this->graphQlRequest = $this->objectManager->create(GraphQlRequest::class); - - } protected function tearDown() From 571a72c3d22f601a6958958dae16408c49d1659b Mon Sep 17 00:00:00 2001 From: Ryan Simmons <rsimmons@crimsonagility.com> Date: Wed, 10 Jul 2019 17:33:05 -0700 Subject: [PATCH 657/773] Fixes issue 22112 (https://github.com/magento/magento2/issues/22112) by removing shipping address validation from the new billing address form in checkout. It appears this was added initially simply to validate the postcode in the form, but running the billing address through the actual shipping rate functionality in shipping-rates-validator's validateFields function was causing the issues leading to the address disappearing from the Ship To section & being deselected in the Shipping step. Instead, this validation is replaced in the billing address form by a simpler validator which only checks the postcode. --- .../billing-address-postcode-validator.js | 83 +++++++++++++++++++ .../frontend/web/js/view/billing-address.js | 6 +- 2 files changed, 86 insertions(+), 3 deletions(-) create mode 100644 app/code/Magento/Checkout/view/frontend/web/js/model/billing-address-postcode-validator.js diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/billing-address-postcode-validator.js b/app/code/Magento/Checkout/view/frontend/web/js/model/billing-address-postcode-validator.js new file mode 100644 index 0000000000000..863954add73b7 --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/js/model/billing-address-postcode-validator.js @@ -0,0 +1,83 @@ +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +define([ + 'jquery', + 'Magento_Checkout/js/model/postcode-validator', + 'mage/translate', + 'uiRegistry', + ], function ( + $, + postcodeValidator, + $t, + uiRegistry, +) { + 'use strict'; + + var postcodeElementName = 'postcode'; + + + return { + validateZipCodeTimeout: 0, + validateDelay: 2000, + + + /** + * Perform postponed binding for fieldset elements + * + * @param {String} formPath + */ + initFields: function (formPath) { + var self = this; + uiRegistry.async(formPath + '.' + postcodeElementName)(self.bindHandler.bind(self)); + }, + + /** + * @param {Object} element + * @param {Number} delay + */ + bindHandler: function (element, delay) { + var self = this; + + delay = typeof delay === 'undefined' ? self.validateDelay : delay; + + element.on('value', function () { + clearTimeout(self.validateZipCodeTimeout); + self.validateZipCodeTimeout = setTimeout(function () { + self.postcodeValidation(element); + }, delay); + }); + }, + + /** + * @param {Object} postcodeElement + * @return {*} + */ + postcodeValidation: function (postcodeElement) { + var countryId = $('select[name="country_id"]:visible').val(), + validationResult, + warnMessage; + + if (postcodeElement == null || postcodeElement.value() == null) { + return true; + } + + postcodeElement.warn(null); + validationResult = postcodeValidator.validate(postcodeElement.value(), countryId); + + if (!validationResult) { + warnMessage = $t('Provided Zip/Postal Code seems to be invalid.'); + + if (postcodeValidator.validatedPostCodeExample.length) { + warnMessage += $t(' Example: ') + postcodeValidator.validatedPostCodeExample.join('; ') + '. '; + } + warnMessage += $t('If you believe it is the right one you can ignore this notice.'); + postcodeElement.warn(warnMessage); + } + + return validationResult; + } + }; +}); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/billing-address.js b/app/code/Magento/Checkout/view/frontend/web/js/view/billing-address.js index a552aa01da061..59d1daa757138 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/view/billing-address.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/view/billing-address.js @@ -18,7 +18,7 @@ define([ 'Magento_Checkout/js/action/set-billing-address', 'Magento_Ui/js/model/messageList', 'mage/translate', - 'Magento_Checkout/js/model/shipping-rates-validator' + 'Magento_Checkout/js/model/billing-address-postcode-validator' ], function ( ko, @@ -35,7 +35,7 @@ function ( setBillingAddressAction, globalMessageList, $t, - shippingRatesValidator + billingAddressPostcodeValidator ) { 'use strict'; @@ -66,7 +66,7 @@ function ( quote.paymentMethod.subscribe(function () { checkoutDataResolver.resolveBillingAddress(); }, this); - shippingRatesValidator.initFields(this.get('name') + '.form-fields'); + billingAddressPostcodeValidator.initFields(this.get('name') + '.form-fields'); }, /** From e9e9eeefe0f78a46a974667ce152249ff05c0490 Mon Sep 17 00:00:00 2001 From: Viktor Tymchynskyi <vtymchynskyi@magento.com> Date: Wed, 10 Jul 2019 21:44:33 -0500 Subject: [PATCH 658/773] MAGETWO-99867: Braintree - 3D Secure 2.0 Support for 2.3 --- .../Braintree/Test/Block/Form/Secure3d.php | 31 ++++++++++++++++--- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/Block/Form/Secure3d.php b/dev/tests/functional/tests/app/Magento/Braintree/Test/Block/Form/Secure3d.php index 927d24f58f89c..02f016cbe79c9 100644 --- a/dev/tests/functional/tests/app/Magento/Braintree/Test/Block/Form/Secure3d.php +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/Block/Form/Secure3d.php @@ -19,9 +19,23 @@ class Secure3d extends Form /** * 3D Secure iFrame locator. * - * @var array + * @var string + */ + protected $braintree3dSecure = "//iframe[contains(@id, 'braintreethreedsecurelanding')]"; + + /** + * AuthWindow locator. + * + * @var string */ - protected $braintree3dSecure = "//iframe[contains(@src, 'braintreegateway.com/3ds')]"; + private $authWindow3dSecure = "//iframe[contains(@id, 'authWindow')]"; + + /** + * Password field locator. + * + * @var string + */ + private $passwordField = "//*[@name='external.field.password']"; /** * Submit button button css selector. @@ -33,12 +47,12 @@ class Secure3d extends Form /** * Switch to 3D Secure iFrame. * - * @param array $locator + * @param string $locator */ public function switchToFrame($locator) { - $this->browser->switchToFrame(new Locator($locator, Locator::SELECTOR_XPATH)); - $this->browser->switchToFrame(new Locator($locator, Locator::SELECTOR_XPATH)); + $this->browser->switchToFrame(new Locator($locator, Locator::SELECTOR_XPATH)); + $this->browser->switchToFrame(new Locator($this->authWindow3dSecure, Locator::SELECTOR_XPATH)); } /** @@ -56,6 +70,7 @@ public function submit() * * @param FixtureInterface $fixture * @param SimpleElement|null $element + * * @return $this|void */ public function fill(FixtureInterface $fixture, SimpleElement $element = null) @@ -63,6 +78,12 @@ public function fill(FixtureInterface $fixture, SimpleElement $element = null) $mapping = $this->dataMapping($fixture->getData()); $this->switchToFrame($this->braintree3dSecure); $element = $this->browser->find('body'); + $this->browser->waitUntil( + function () use ($element) { + $fieldElement = $element->find($this->passwordField, Locator::SELECTOR_XPATH); + return $fieldElement->isVisible() ? true : null; + } + ); $this->_fill([$mapping['secure3d_password']], $element); $this->submit(); $this->browser->switchToFrame(); From ebfcbcfad2b94aec552808d84559cdfda5a66fb2 Mon Sep 17 00:00:00 2001 From: Serhii Voloshkov <serhii.voloshkov@transoftgroup.com> Date: Thu, 11 Jul 2019 10:28:29 +0300 Subject: [PATCH 659/773] MC-17864: Finalize @escapeNotVerified elimination --- .../Magento/Translation/view/base/templates/translate.phtml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Translation/view/base/templates/translate.phtml b/app/code/Magento/Translation/view/base/templates/translate.phtml index 2567c02335b93..247d3d04f7f48 100644 --- a/app/code/Magento/Translation/view/base/templates/translate.phtml +++ b/app/code/Magento/Translation/view/base/templates/translate.phtml @@ -28,7 +28,7 @@ <?php $version = $block->getTranslationFileVersion(); ?> - if (versionObj.version !== '<?= $block->escapeJsQuote($version) ?>') { + if (versionObj.version !== '<?= $block->escapeJs($version) ?>') { dependencies.push( 'text!<?= /* @noEscape */ Magento\Translation\Model\Js\Config::DICTIONARY_FILE_NAME ?>' ); @@ -44,7 +44,7 @@ $.localStorage.set( 'mage-translation-file-version', { - version: '<?= $block->escapeJsQuote($version) ?>' + version: '<?= $block->escapeJs($version) ?>' } ); } else { From b55f474174077e7f650b5f56caac285d234f4522 Mon Sep 17 00:00:00 2001 From: Nikita Shcherbatykh <nikita.shcherbatykh@transoftgroup.com> Date: Thu, 11 Jul 2019 10:29:18 +0300 Subject: [PATCH 660/773] MC-17947: Search by email is working incorrect in Sales > Orders grid --- .../Element/UiComponent/DataProvider/FulltextFilter.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/DataProvider/FulltextFilter.php b/lib/internal/Magento/Framework/View/Element/UiComponent/DataProvider/FulltextFilter.php index a7d7f76827cc8..d6ea0a267a9dc 100644 --- a/lib/internal/Magento/Framework/View/Element/UiComponent/DataProvider/FulltextFilter.php +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/DataProvider/FulltextFilter.php @@ -16,9 +16,9 @@ class FulltextFilter implements FilterApplierInterface { /** - * Patterns using in preg_replace + * Patterns using for escaping special characters in escapeAgainstValue method */ - private $patterns = [ + private $escapePatterns = [ '/[@\.]/' => '\_', '/([+\-><\(\)~*]+)/' => ' ', ]; @@ -78,7 +78,7 @@ function ($column) use ($alias) { */ private function escapeAgainstValue(string $value): string { - return preg_replace(array_keys($this->patterns), array_values($this->patterns), $value); + return preg_replace(array_keys($this->escapePatterns), array_values($this->escapePatterns), $value); } /** From 226009e90bba3af2c1d2b0ddb3ad9fc5c2b8f362 Mon Sep 17 00:00:00 2001 From: Graham Wharton <graham@gwharton.me.uk> Date: Thu, 11 Jul 2019 08:38:01 +0100 Subject: [PATCH 661/773] Change Encoding of MIME Emails to QUOTED-PRINTABLE Added Content-Disposition: inline to all MIME emails Implementation now matches previous ZF1 implementation --- .../testsuite/Magento/Customer/Controller/AccountTest.php | 2 +- .../testsuite/Magento/Newsletter/Model/SubscriberTest.php | 5 ++++- .../Sales/Controller/Adminhtml/Order/Create/SaveTest.php | 2 +- .../Adminhtml/Order/Creditmemo/AddCommentTest.php | 2 +- .../Controller/Adminhtml/Order/Creditmemo/SaveTest.php | 2 +- .../Magento/Sales/Controller/Adminhtml/Order/EmailTest.php | 2 +- .../Controller/Adminhtml/Order/Invoice/AddCommentTest.php | 2 +- .../Sales/Controller/Adminhtml/Order/Invoice/EmailTest.php | 2 +- .../Sales/Controller/Adminhtml/Order/Invoice/SaveTest.php | 2 +- .../testsuite/Magento/Sales/Model/Order/CreateTest.php | 2 +- .../Controller/Adminhtml/Order/Shipment/AddCommentTest.php | 2 +- .../Controller/Adminhtml/Order/Shipment/SaveTest.php | 2 +- lib/internal/Magento/Framework/Mail/Message.php | 2 ++ .../Magento/Framework/Mail/Test/Unit/MessageTest.php | 6 ++++-- 14 files changed, 21 insertions(+), 14 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php b/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php index 898d3ff400b38..b80f00b16f0bd 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php @@ -771,7 +771,7 @@ public function testConfirmationEmailWithSpecialCharacters(): void $this->assertContains('To: ' . $email, $rawMessage); - $content = $message->getBody()->getPartContent(0); + $content = $message->getBody()->getParts()[0]->getRawContent(); $confirmationUrl = $this->getConfirmationUrlFromMessageContent($content); $this->setRequestInfo($confirmationUrl, 'confirm'); $this->clearCookieMessagesList(); diff --git a/dev/tests/integration/testsuite/Magento/Newsletter/Model/SubscriberTest.php b/dev/tests/integration/testsuite/Magento/Newsletter/Model/SubscriberTest.php index bcd4233655489..e971ca88c4e57 100644 --- a/dev/tests/integration/testsuite/Magento/Newsletter/Model/SubscriberTest.php +++ b/dev/tests/integration/testsuite/Magento/Newsletter/Model/SubscriberTest.php @@ -7,6 +7,9 @@ use Magento\TestFramework\Mail\Template\TransportBuilderMock; +/** + * \Magento\Newsletter\Model\Subscriber tests + */ class SubscriberTest extends \PHPUnit\Framework\TestCase { /** @@ -35,7 +38,7 @@ public function testEmailConfirmation() $this->assertContains( '/newsletter/subscriber/confirm/id/' . $this->model->getSubscriberId() . '/code/ysayquyajua23iq29gxwu2eax2qb6gvy', - $transportBuilder->getSentMessage()->getRawMessage() + $transportBuilder->getSentMessage()->getBody()->getParts()[0]->getRawContent() ); $this->assertEquals(Subscriber::STATUS_NOT_ACTIVE, $this->model->getSubscriberStatus()); } diff --git a/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/Create/SaveTest.php b/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/Create/SaveTest.php index f863edd049258..6dba48092c400 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/Create/SaveTest.php +++ b/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/Create/SaveTest.php @@ -142,7 +142,7 @@ public function testSendEmailOnOrderSave(): void ); $this->assertEquals($message->getSubject(), $subject); - $this->assertThat($message->getRawMessage(), $assert); + $this->assertThat($message->getBody()->getParts()[0]->getRawContent(), $assert); } /** diff --git a/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/AddCommentTest.php b/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/AddCommentTest.php index 2f23da8b3db87..13bcc756c2364 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/AddCommentTest.php +++ b/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/AddCommentTest.php @@ -54,7 +54,7 @@ public function testSendEmailOnAddCreditmemoComment(): void ); $this->assertEquals($message->getSubject(), $subject); - $this->assertThat($message->getRawMessage(), $messageConstraint); + $this->assertThat($message->getBody()->getParts()[0]->getRawContent(), $messageConstraint); } /** diff --git a/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/SaveTest.php b/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/SaveTest.php index f589a0f5a1c74..13d1fe89f149a 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/SaveTest.php +++ b/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/SaveTest.php @@ -56,7 +56,7 @@ public function testSendEmailOnCreditmemoSave(): void ); $this->assertEquals($message->getSubject(), $subject); - $this->assertThat($message->getRawMessage(), $messageConstraint); + $this->assertThat($message->getBody()->getParts()[0]->getRawContent(), $messageConstraint); } /** diff --git a/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/EmailTest.php b/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/EmailTest.php index 4d19106ad8e51..2addc4d40ecda 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/EmailTest.php +++ b/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/EmailTest.php @@ -82,7 +82,7 @@ public function testSendOrderEmail(): void ); $this->assertEquals($message->getSubject(), $subject); - $this->assertThat($message->getRawMessage(), $assert); + $this->assertThat($message->getBody()->getParts()[0]->getRawContent(), $assert); } /** diff --git a/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/Invoice/AddCommentTest.php b/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/Invoice/AddCommentTest.php index 81e1dd7afc496..1db008690a154 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/Invoice/AddCommentTest.php +++ b/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/Invoice/AddCommentTest.php @@ -55,7 +55,7 @@ public function testSendEmailOnAddInvoiceComment(): void ); $this->assertEquals($message->getSubject(), $subject); - $this->assertThat($message->getRawMessage(), $messageConstraint); + $this->assertThat($message->getBody()->getParts()[0]->getRawContent(), $messageConstraint); } /** diff --git a/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/Invoice/EmailTest.php b/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/Invoice/EmailTest.php index 85223528ec82a..b2f4b8a6954d5 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/Invoice/EmailTest.php +++ b/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/Invoice/EmailTest.php @@ -59,7 +59,7 @@ public function testSendInvoiceEmail(): void ); $this->assertEquals($message->getSubject(), $subject); - $this->assertThat($message->getRawMessage(), $messageConstraint); + $this->assertThat($message->getBody()->getParts()[0]->getRawContent(), $messageConstraint); } /** diff --git a/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/Invoice/SaveTest.php b/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/Invoice/SaveTest.php index 68074e38d9a39..40540f3126899 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/Invoice/SaveTest.php +++ b/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/Invoice/SaveTest.php @@ -51,7 +51,7 @@ public function testSendEmailOnInvoiceSave(): void ); $this->assertEquals($message->getSubject(), $subject); - $this->assertThat($message->getRawMessage(), $messageConstraint); + $this->assertThat($message->getBody()->getParts()[0]->getRawContent(), $messageConstraint); } /** diff --git a/dev/tests/integration/testsuite/Magento/Sales/Model/Order/CreateTest.php b/dev/tests/integration/testsuite/Magento/Sales/Model/Order/CreateTest.php index 1035ce1592314..3fe3fca260e8b 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/Model/Order/CreateTest.php +++ b/dev/tests/integration/testsuite/Magento/Sales/Model/Order/CreateTest.php @@ -95,6 +95,6 @@ public function testSendEmailOnOrderPlace(): void ); $this->assertEquals($message->getSubject(), $subject); - $this->assertThat($message->getRawMessage(), $assert); + $this->assertThat($message->getBody()->getParts()[0]->getRawContent(), $assert); } } diff --git a/dev/tests/integration/testsuite/Magento/Shipping/Controller/Adminhtml/Order/Shipment/AddCommentTest.php b/dev/tests/integration/testsuite/Magento/Shipping/Controller/Adminhtml/Order/Shipment/AddCommentTest.php index 25a44bab62994..a2ac5883a13d9 100644 --- a/dev/tests/integration/testsuite/Magento/Shipping/Controller/Adminhtml/Order/Shipment/AddCommentTest.php +++ b/dev/tests/integration/testsuite/Magento/Shipping/Controller/Adminhtml/Order/Shipment/AddCommentTest.php @@ -54,7 +54,7 @@ public function testSendEmailOnShipmentCommentAdd(): void ); $this->assertEquals($message->getSubject(), $subject); - $this->assertThat($message->getRawMessage(), $messageConstraint); + $this->assertThat($message->getBody()->getParts()[0]->getRawContent(), $messageConstraint); } /** diff --git a/dev/tests/integration/testsuite/Magento/Shipping/Controller/Adminhtml/Order/Shipment/SaveTest.php b/dev/tests/integration/testsuite/Magento/Shipping/Controller/Adminhtml/Order/Shipment/SaveTest.php index 27b5bb02d4b22..e95e99224a6d9 100644 --- a/dev/tests/integration/testsuite/Magento/Shipping/Controller/Adminhtml/Order/Shipment/SaveTest.php +++ b/dev/tests/integration/testsuite/Magento/Shipping/Controller/Adminhtml/Order/Shipment/SaveTest.php @@ -51,7 +51,7 @@ public function testSendEmailOnShipmentSave(): void ); $this->assertEquals($message->getSubject(), $subject); - $this->assertThat($message->getRawMessage(), $messageConstraint); + $this->assertThat($message->getBody()->getParts()[0]->getRawContent(), $messageConstraint); } /** diff --git a/lib/internal/Magento/Framework/Mail/Message.php b/lib/internal/Magento/Framework/Mail/Message.php index a9996c0a4f12a..b15b75ca9ac63 100644 --- a/lib/internal/Magento/Framework/Mail/Message.php +++ b/lib/internal/Magento/Framework/Mail/Message.php @@ -167,6 +167,8 @@ private function createMimeFromString($body, $messageType) { $part = new Part($body); $part->setCharset($this->zendMessage->getEncoding()); + $part->setEncoding(Mime::ENCODING_QUOTEDPRINTABLE); + $part->setDisposition(Mime::DISPOSITION_INLINE); $part->setType($messageType); $mimeMessage = new \Zend\Mime\Message(); $mimeMessage->addPart($part); diff --git a/lib/internal/Magento/Framework/Mail/Test/Unit/MessageTest.php b/lib/internal/Magento/Framework/Mail/Test/Unit/MessageTest.php index bea2a9ea91d38..c29ca4d261cc4 100644 --- a/lib/internal/Magento/Framework/Mail/Test/Unit/MessageTest.php +++ b/lib/internal/Magento/Framework/Mail/Test/Unit/MessageTest.php @@ -26,9 +26,10 @@ public function testSetBodyHtml() $part = $this->message->getBody()->getParts()[0]; $this->assertEquals('text/html', $part->getType()); - $this->assertEquals('8bit', $part->getEncoding()); + $this->assertEquals('quoted-printable', $part->getEncoding()); $this->assertEquals('utf-8', $part->getCharset()); $this->assertEquals('body', $part->getContent()); + $this->assertEquals('inline', $part->getDisposition()); } public function testSetBodyText() @@ -37,8 +38,9 @@ public function testSetBodyText() $part = $this->message->getBody()->getParts()[0]; $this->assertEquals('text/plain', $part->getType()); - $this->assertEquals('8bit', $part->getEncoding()); + $this->assertEquals('quoted-printable', $part->getEncoding()); $this->assertEquals('utf-8', $part->getCharset()); $this->assertEquals('body', $part->getContent()); + $this->assertEquals('inline', $part->getDisposition()); } } From 10d4911289ef5fe19483b2677122c54cf8da6964 Mon Sep 17 00:00:00 2001 From: Alex Taranovsky <firster@atwix.com> Date: Thu, 11 Jul 2019 13:28:46 +0300 Subject: [PATCH 662/773] magento/magento2#: Fix storeId param type in the EmailNotification::newAccount, EmailNotificationInterface::newAccount methods - Magento\Customer\Model\EmailNotificationInterface - Magento\Customer\Model\EmailNotification --- app/code/Magento/Customer/Model/EmailNotification.php | 2 +- app/code/Magento/Customer/Model/EmailNotificationInterface.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Customer/Model/EmailNotification.php b/app/code/Magento/Customer/Model/EmailNotification.php index 144c24f8e8355..573f86247e0c3 100644 --- a/app/code/Magento/Customer/Model/EmailNotification.php +++ b/app/code/Magento/Customer/Model/EmailNotification.php @@ -362,7 +362,7 @@ public function passwordResetConfirmation(CustomerInterface $customer) * @param CustomerInterface $customer * @param string $type * @param string $backUrl - * @param string $storeId + * @param int $storeId * @param string $sendemailStoreId * @return void * @throws LocalizedException diff --git a/app/code/Magento/Customer/Model/EmailNotificationInterface.php b/app/code/Magento/Customer/Model/EmailNotificationInterface.php index 0821abff04750..028322acdd9d7 100644 --- a/app/code/Magento/Customer/Model/EmailNotificationInterface.php +++ b/app/code/Magento/Customer/Model/EmailNotificationInterface.php @@ -73,7 +73,7 @@ public function passwordResetConfirmation(CustomerInterface $customer); * @param CustomerInterface $customer * @param string $type * @param string $backUrl - * @param string $storeId + * @param int $storeId * @param string $sendemailStoreId * @return void * @throws LocalizedException From 6aa03829fcbdba312e33fdfad06c0d2b7ce3e1bb Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <engcom-vendorworker-foxtrot@adobe.com> Date: Thu, 11 Jul 2019 14:07:18 +0300 Subject: [PATCH 663/773] magento/magenot2#23351: Static tests fix. --- lib/internal/Magento/Framework/App/Utility/Files.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/internal/Magento/Framework/App/Utility/Files.php b/lib/internal/Magento/Framework/App/Utility/Files.php index 58168df4e3cd7..8bb59bb42ff49 100644 --- a/lib/internal/Magento/Framework/App/Utility/Files.php +++ b/lib/internal/Magento/Framework/App/Utility/Files.php @@ -615,6 +615,7 @@ protected function getLayoutXmlFiles($location, $incomingParams = [], $asDataSet $params[$key] = $incomingParams[$key]; } } + //phpcs:ignore Magento2.Security.InsecureFunction $cacheKey = md5($location . '|' . implode('|', $params)); if (!isset(self::$_cache[__METHOD__][$cacheKey])) { @@ -768,6 +769,7 @@ public function getPageTypeFiles($incomingParams = [], $asDataSet = true) $params[$key] = $incomingParams[$key]; } } + //phpcs:ignore Magento2.Security.InsecureFunction $cacheKey = md5(implode('|', $params)); if (!isset(self::$_cache[__METHOD__][$cacheKey])) { From e1601c255798ac971bad65b4d62ec77daa3402eb Mon Sep 17 00:00:00 2001 From: Nikita Shcherbatykh <nikita.shcherbatykh@transoftgroup.com> Date: Thu, 11 Jul 2019 14:38:53 +0300 Subject: [PATCH 664/773] MC-17947: Search by email is working incorrect in Sales > Orders grid --- .../View/Element/UiComponent/DataProvider/FulltextFilter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/DataProvider/FulltextFilter.php b/lib/internal/Magento/Framework/View/Element/UiComponent/DataProvider/FulltextFilter.php index d6ea0a267a9dc..f7586379a37fc 100644 --- a/lib/internal/Magento/Framework/View/Element/UiComponent/DataProvider/FulltextFilter.php +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/DataProvider/FulltextFilter.php @@ -16,7 +16,7 @@ class FulltextFilter implements FilterApplierInterface { /** - * Patterns using for escaping special characters in escapeAgainstValue method + * Patterns using for escaping special characters */ private $escapePatterns = [ '/[@\.]/' => '\_', From 2f6238232a43c9fb8808f41683d7ab6584ade4b3 Mon Sep 17 00:00:00 2001 From: Graham Wharton <graham@gwharton.me.uk> Date: Thu, 11 Jul 2019 13:58:20 +0100 Subject: [PATCH 665/773] php bin/magento catalog:images:resize extracts source file from database if in media storage mode and also stores resized images back into database after resize. --- .../MediaStorage/Service/ImageResize.php | 40 ++- .../Test/Unit/Service/ImageResizeTest.php | 300 ++++++++++++++++++ 2 files changed, 333 insertions(+), 7 deletions(-) create mode 100644 app/code/Magento/MediaStorage/Test/Unit/Service/ImageResizeTest.php diff --git a/app/code/Magento/MediaStorage/Service/ImageResize.php b/app/code/Magento/MediaStorage/Service/ImageResize.php index d3f4fc01e387b..1184fb5cc4600 100644 --- a/app/code/Magento/MediaStorage/Service/ImageResize.php +++ b/app/code/Magento/MediaStorage/Service/ImageResize.php @@ -22,6 +22,7 @@ use Magento\Theme\Model\Config\Customization as ThemeCustomizationConfig; use Magento\Theme\Model\ResourceModel\Theme\Collection; use Magento\Framework\App\Filesystem\DirectoryList; +use Magento\MediaStorage\Helper\File\Storage\Database; /** * Image resize service. @@ -85,6 +86,11 @@ class ImageResize */ private $filesystem; + /** + * @var Database + */ + private $fileStorageDatabase; + /** * @param State $appState * @param MediaConfig $imageConfig @@ -96,6 +102,7 @@ class ImageResize * @param ThemeCustomizationConfig $themeCustomizationConfig * @param Collection $themeCollection * @param Filesystem $filesystem + * @param Database $fileStorageDatabase * @internal param ProductImage $gallery * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -109,7 +116,8 @@ public function __construct( AssertImageFactory $assertImageFactory, ThemeCustomizationConfig $themeCustomizationConfig, Collection $themeCollection, - Filesystem $filesystem + Filesystem $filesystem, + Database $fileStorageDatabase = null ) { $this->appState = $appState; $this->imageConfig = $imageConfig; @@ -122,6 +130,8 @@ public function __construct( $this->themeCollection = $themeCollection; $this->mediaDirectory = $filesystem->getDirectoryWrite(DirectoryList::MEDIA); $this->filesystem = $filesystem; + $this->fileStorageDatabase = $fileStorageDatabase ?: + \Magento\Framework\App\ObjectManager::getInstance()->get(Database::class); } /** @@ -132,9 +142,15 @@ public function __construct( */ public function resizeFromImageName(string $originalImageName) { - $originalImagePath = $this->mediaDirectory->getAbsolutePath( - $this->imageConfig->getMediaPath($originalImageName) - ); + $mediastoragefilename = $this->imageConfig->getMediaPath($originalImageName); + $originalImagePath = $this->mediaDirectory->getAbsolutePath($mediastoragefilename); + + if ($this->fileStorageDatabase->checkDbUsage() && + !$this->mediaDirectory->isFile($mediastoragefilename) + ) { + $this->fileStorageDatabase->saveFileToFilesystem($mediastoragefilename); + } + if (!$this->mediaDirectory->isFile($originalImagePath)) { throw new NotFoundException(__('Cannot resize image "%1" - original image not found', $originalImagePath)); } @@ -162,10 +178,15 @@ public function resizeFromThemes(array $themes = null): \Generator foreach ($productImages as $image) { $originalImageName = $image['filepath']; - $originalImagePath = $this->mediaDirectory->getAbsolutePath( - $this->imageConfig->getMediaPath($originalImageName) - ); + $mediastoragefilename = $this->imageConfig->getMediaPath($originalImageName); + $originalImagePath = $this->mediaDirectory->getAbsolutePath($mediastoragefilename); + foreach ($viewImages as $viewImage) { + if ($this->fileStorageDatabase->checkDbUsage() && + !$this->mediaDirectory->isFile($mediastoragefilename) + ) { + $this->fileStorageDatabase->saveFileToFilesystem($mediastoragefilename); + } $this->resize($viewImage, $originalImagePath, $originalImageName); } yield $originalImageName => $count; @@ -293,6 +314,11 @@ private function resize(array $viewImage, string $originalImagePath, string $ori $image->resize($imageParams['image_width'], $imageParams['image_height']); } $image->save($imageAsset->getPath()); + + if ($this->fileStorageDatabase->checkDbUsage()) { + $mediastoragefilename = $this->mediaDirectory->getRelativePath($imageAsset->getPath()); + $this->fileStorageDatabase->saveFile($mediastoragefilename); + } } /** diff --git a/app/code/Magento/MediaStorage/Test/Unit/Service/ImageResizeTest.php b/app/code/Magento/MediaStorage/Test/Unit/Service/ImageResizeTest.php new file mode 100644 index 0000000000000..7fccfa04f86d0 --- /dev/null +++ b/app/code/Magento/MediaStorage/Test/Unit/Service/ImageResizeTest.php @@ -0,0 +1,300 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\MediaStorage\Test\Unit\Service; + +use Magento\Catalog\Model\Product\Image\ParamsBuilder; +use Magento\Catalog\Model\View\Asset\ImageFactory as AssetImageFactory; +use Magento\Catalog\Model\View\Asset\Image as AssetImage; +use Magento\Framework\DataObject; +use Magento\Framework\Filesystem; +use Magento\Framework\Image\Factory as ImageFactory; +use Magento\Framework\Image; +use Magento\Catalog\Model\Product\Media\ConfigInterface as MediaConfig; +use Magento\Framework\App\State; +use Magento\Framework\View\ConfigInterface as ViewConfig; +use Magento\Framework\Config\View; +use Magento\Catalog\Model\ResourceModel\Product\Image as ProductImage; +use Magento\Theme\Model\Config\Customization as ThemeCustomizationConfig; +use Magento\Theme\Model\ResourceModel\Theme\Collection; +use Magento\MediaStorage\Helper\File\Storage\Database; +use Magento\Framework\App\Filesystem\DirectoryList; + +/** + * Class ImageResizeTest + * + * @SuppressWarnings(PHPMD.TooManyFields) + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class ImageResizeTest extends \PHPUnit\Framework\TestCase +{ + /** + * @var \Magento\MediaStorage\Service\ImageResize + */ + protected $service; + + /** + * @var State|\PHPUnit_Framework_MockObject_MockObject + */ + protected $appStateMock; + + /** + * @var MediaConfig|\PHPUnit_Framework_MockObject_MockObject + */ + protected $imageConfigMock; + + /** + * @var ProductImage|\PHPUnit_Framework_MockObject_MockObject + */ + protected $productImageMock; + + /** + * @var ImageFactory|\PHPUnit_Framework_MockObject_MockObject + */ + protected $imageFactoryMock; + + /** + * @var Image|\PHPUnit_Framework_MockObject_MockObject + */ + protected $imageMock; + + /** + * @var ParamsBuilder|\PHPUnit_Framework_MockObject_MockObject + */ + protected $paramsBuilderMock; + + /** + * @var ViewConfig|\PHPUnit_Framework_MockObject_MockObject + */ + protected $viewConfigMock; + + /** + * @var View|\PHPUnit_Framework_MockObject_MockObject + */ + protected $viewMock; + + /** + * @var AssetImage|\PHPUnit_Framework_MockObject_MockObject + */ + protected $assetImageMock; + + /** + * @var AssetImageFactory|\PHPUnit_Framework_MockObject_MockObject + */ + protected $assetImageFactoryMock; + + /** + * @var ThemeCustomizationConfig|\PHPUnit_Framework_MockObject_MockObject + */ + protected $themeCustomizationConfigMock; + + /** + * @var Collection|\PHPUnit_Framework_MockObject_MockObject + */ + protected $themeCollectionMock; + + /** + * @var Filesystem|\PHPUnit_Framework_MockObject_MockObject + */ + protected $filesystemMock; + + /** + * @var Database|\PHPUnit_Framework_MockObject_MockObject + */ + protected $databaseMock; + + /** + * @var Filesystem|\PHPUnit_Framework_MockObject_MockObject + */ + private $mediaDirectoryMock; + + /** + * @var string + */ + private $testfilename; + + /** + * @var string + */ + private $testfilepath; + + protected function setUp() + { + $this->testfilename = "image.jpg"; + $this->testfilepath = "/image.jpg"; + + $this->appStateMock = $this->createMock(State::class); + $this->imageConfigMock = $this->createMock(MediaConfig::class); + $this->productImageMock = $this->createMock(ProductImage::class); + $this->imageMock = $this->createMock(Image::class); + $this->imageFactoryMock = $this->createMock(ImageFactory::class); + $this->paramsBuilderMock = $this->createMock(ParamsBuilder::class); + $this->viewMock = $this->createMock(View::class); + $this->viewConfigMock = $this->createMock(ViewConfig::class); + $this->assetImageMock = $this->createMock(AssetImage::class); + $this->assetImageFactoryMock = $this->createMock(AssetImageFactory::class); + $this->themeCustomizationConfigMock = $this->createMock(ThemeCustomizationConfig::class); + $this->themeCollectionMock = $this->createMock(Collection::class); + $this->filesystemMock = $this->createMock(Filesystem::class); + $this->databaseMock = $this->createMock(Database::class); + + $this->mediaDirectoryMock = $this->getMockBuilder(Filesystem::class) + ->disableOriginalConstructor() + ->setMethods(['getAbsolutePath','isFile','getRelativePath']) + ->getMock(); + + $this->filesystemMock->expects($this->any()) + ->method('getDirectoryWrite') + ->with(DirectoryList::MEDIA) + ->willReturn($this->mediaDirectoryMock); + + $this->imageFactoryMock->expects($this->any()) + ->method('create') + ->willReturn($this->imageMock); + $this->assetImageMock->expects($this->any()) + ->method('getPath') + ->will($this->returnValue($this->testfilepath)); + $this->assetImageFactoryMock->expects($this->any()) + ->method('create') + ->willReturn($this->assetImageMock); + + $this->paramsBuilderMock->expects($this->any()) + ->method('build') + ->willReturn( + [ + 'keep_aspect_ratio' => null, + 'keep_frame' => null, + 'keep_transparency' => null, + 'constrain_only' => null, + 'background' => null, + 'quality' => null, + 'image_width' => null, + 'image_height' => null + ] + ); + + $this->imageConfigMock->expects($this->any()) + ->method('getMediaPath') + ->with($this->testfilename) + ->willReturn($this->testfilepath); + $this->mediaDirectoryMock->expects($this->any()) + ->method('getAbsolutePath') + ->with($this->testfilepath) + ->willReturn($this->testfilepath); + $this->mediaDirectoryMock->expects($this->any()) + ->method('getRelativePath') + ->with($this->testfilepath) + ->willReturn($this->testfilepath); + + $this->viewMock->expects($this->any()) + ->method('getMediaEntities') + ->willReturn( + ['product_small_image' => + [ + 'type' => 'small_image', + 'width' => 75, + 'height' => 75 + ] + ] + ); + $this->viewConfigMock->expects($this->any()) + ->method('getViewConfig') + ->willReturn($this->viewMock); + + $this->service = new \Magento\MediaStorage\Service\ImageResize( + $this->appStateMock, + $this->imageConfigMock, + $this->productImageMock, + $this->imageFactoryMock, + $this->paramsBuilderMock, + $this->viewConfigMock, + $this->assetImageFactoryMock, + $this->themeCustomizationConfigMock, + $this->themeCollectionMock, + $this->filesystemMock, + $this->databaseMock + ); + } + + protected function tearDown() + { + unset($this->service); + } + + public function testResizeFromThemesMediaStorageDatabase() + { + $this->databaseMock->expects($this->any()) + ->method('checkDbUsage') + ->will($this->returnValue(true)); + + $this->productImageMock->expects($this->any()) + ->method('getCountUsedProductImages') + ->willReturn(1); + $this->productImageMock->expects($this->any()) + ->method('getUsedProductImages') + ->will( + $this->returnCallback( + function () { + $data = [[ 'filepath' => $this->testfilename ]]; + foreach ($data as $e) { + yield $e; + } + } + ) + ); + + $this->mediaDirectoryMock->expects($this->any()) + ->method('isFile') + ->with($this->testfilepath) + ->will($this->returnValue(false)); + + $this->databaseMock->expects($this->once()) + ->method('saveFileToFilesystem') + ->with($this->testfilepath); + $this->databaseMock->expects($this->once()) + ->method('saveFile') + ->with($this->testfilepath); + + $generator = $this->service->resizeFromThemes(['test-theme']); + while ($generator->valid()) { + $generator->next(); + } + } + + public function testResizeFromImageNameMediaStorageDatabase() + { + $this->databaseMock->expects($this->any()) + ->method('checkDbUsage') + ->will($this->returnValue(true)); + + $this->mediaDirectoryMock->expects($this->any()) + ->method('isFile') + ->with($this->testfilepath) + ->willReturnOnConsecutiveCalls( + $this->returnValue(false), + $this->returnValue(true) + ); + + $this->themeCollectionMock->expects($this->any()) + ->method('loadRegisteredThemes') + ->willReturn( + [ new DataObject(['id' => '0']) ] + ); + $this->themeCustomizationConfigMock->expects($this->any()) + ->method('getStoresByThemes') + ->willReturn( + ['0' => []] + ); + + $this->databaseMock->expects($this->once()) + ->method('saveFileToFilesystem') + ->with($this->testfilepath); + $this->databaseMock->expects($this->once()) + ->method('saveFile') + ->with($this->testfilepath); + + $this->service->resizeFromImageName($this->testfilename); + } +} From 6b9ad5257a322902f4810e4bffc5b4d67131aefb Mon Sep 17 00:00:00 2001 From: Dmytro Horytskyi <horytsky@adobe.com> Date: Thu, 11 Jul 2019 15:20:08 +0000 Subject: [PATCH 666/773] MC-18070: Website-level admin user edits to themes impacts grid for other admin users --- .../Magento/Store/Model/ScopeTreeProvider.php | 56 +++++++++--- .../Test/Unit/Model/ScopeTreeProviderTest.php | 87 +++++++++++-------- 2 files changed, 98 insertions(+), 45 deletions(-) diff --git a/app/code/Magento/Store/Model/ScopeTreeProvider.php b/app/code/Magento/Store/Model/ScopeTreeProvider.php index cb7d0d3b3ffee..47ed2276c1374 100644 --- a/app/code/Magento/Store/Model/ScopeTreeProvider.php +++ b/app/code/Magento/Store/Model/ScopeTreeProvider.php @@ -7,28 +7,48 @@ use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\App\ScopeTreeProviderInterface; -use Magento\Store\Model\Group; -use Magento\Store\Model\Store; -use Magento\Store\Model\Website; +use Magento\Store\Api\GroupRepositoryInterface; +use Magento\Store\Api\StoreRepositoryInterface; +use Magento\Store\Api\WebsiteRepositoryInterface; +/** + * Class for building scopes tree. + */ class ScopeTreeProvider implements ScopeTreeProviderInterface { /** - * @var StoreManagerInterface + * @var WebsiteRepositoryInterface + */ + private $websiteRepository; + + /** + * @var GroupRepositoryInterface + */ + private $groupRepository; + + /** + * @var StoreRepositoryInterface */ - protected $storeManager; + private $storeRepository; /** - * @param StoreManagerInterface $storeManager + * @param WebsiteRepositoryInterface $websiteRepository + * @param GroupRepositoryInterface $groupRepository + * @param StoreRepositoryInterface $storeRepository */ public function __construct( - StoreManagerInterface $storeManager + WebsiteRepositoryInterface $websiteRepository, + GroupRepositoryInterface $groupRepository, + StoreRepositoryInterface $storeRepository ) { - $this->storeManager = $storeManager; + $this->websiteRepository = $websiteRepository; + $this->groupRepository = $groupRepository; + $this->storeRepository = $storeRepository; } /** * @inheritdoc + * @return array */ public function get() { @@ -38,8 +58,21 @@ public function get() 'scopes' => [], ]; + $groups = []; + foreach ($this->groupRepository->getList() as $group) { + $groups[$group->getWebsiteId()][] = $group; + } + $stores = []; + foreach ($this->storeRepository->getList() as $store) { + $stores[$store->getStoreGroupId()][] = $store; + } + /** @var Website $website */ - foreach ($this->storeManager->getWebsites() as $website) { + foreach ($this->websiteRepository->getList() as $website) { + if (!$website->getId()) { + continue; + } + $websiteScope = [ 'scope' => ScopeInterface::SCOPE_WEBSITES, 'scope_id' => $website->getId(), @@ -47,7 +80,7 @@ public function get() ]; /** @var Group $group */ - foreach ($website->getGroups() as $group) { + foreach ($groups[$website->getId()] as $group) { $groupScope = [ 'scope' => ScopeInterface::SCOPE_GROUP, 'scope_id' => $group->getId(), @@ -55,7 +88,7 @@ public function get() ]; /** @var Store $store */ - foreach ($group->getStores() as $store) { + foreach ($stores[$group->getId()] as $store) { $storeScope = [ 'scope' => ScopeInterface::SCOPE_STORES, 'scope_id' => $store->getId(), @@ -67,6 +100,7 @@ public function get() } $defaultScope['scopes'][] = $websiteScope; } + return $defaultScope; } } diff --git a/app/code/Magento/Store/Test/Unit/Model/ScopeTreeProviderTest.php b/app/code/Magento/Store/Test/Unit/Model/ScopeTreeProviderTest.php index 1b4cb0b8d5f27..92b50f8fcde08 100644 --- a/app/code/Magento/Store/Test/Unit/Model/ScopeTreeProviderTest.php +++ b/app/code/Magento/Store/Test/Unit/Model/ScopeTreeProviderTest.php @@ -5,9 +5,12 @@ */ namespace Magento\Store\Test\Unit\Model; -use Magento\Store\Api\Data\WebsiteInterface; use Magento\Store\Api\Data\GroupInterface; use Magento\Store\Api\Data\StoreInterface; +use Magento\Store\Api\Data\WebsiteInterface; +use Magento\Store\Api\GroupRepositoryInterface; +use Magento\Store\Api\StoreRepositoryInterface; +use Magento\Store\Api\WebsiteRepositoryInterface; use Magento\Store\Model\Group; use Magento\Store\Model\ScopeTreeProvider; use Magento\Store\Model\Store; @@ -16,20 +19,42 @@ use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Store\Model\Website; +/** + * @covers \Magento\Store\Model\ScopeTreeProvider + */ class ScopeTreeProviderTest extends \PHPUnit\Framework\TestCase { - /** @var ScopeTreeProvider */ - protected $model; + /** + * @var ScopeTreeProvider + */ + private $model; - /** @var StoreManagerInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $storeManagerMock; + /** + * @var \PHPUnit_Framework_MockObject_MockObject|WebsiteRepositoryInterface + */ + private $websiteRepositoryMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject|GroupRepositoryInterface + */ + private $groupRepositoryMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject|StoreRepositoryInterface + */ + private $storeRepositoryMock; protected function setUp() { - $this->storeManagerMock = $this->getMockBuilder(\Magento\Store\Model\StoreManagerInterface::class) - ->getMockForAbstractClass(); + $this->websiteRepositoryMock = $this->createMock(WebsiteRepositoryInterface::class); + $this->groupRepositoryMock = $this->createMock(GroupRepositoryInterface::class); + $this->storeRepositoryMock = $this->createMock(StoreRepositoryInterface::class); - $this->model = new ScopeTreeProvider($this->storeManagerMock); + $this->model = new ScopeTreeProvider( + $this->websiteRepositoryMock, + $this->groupRepositoryMock, + $this->storeRepositoryMock + ); } public function testGet() @@ -58,40 +83,34 @@ public function testGet() 'scopes' => [$websiteData], ]; - /** @var Website|\PHPUnit_Framework_MockObject_MockObject $websiteMock */ - $websiteMock = $this->getMockBuilder(\Magento\Store\Model\Website::class) - ->disableOriginalConstructor() - ->getMock(); - $websiteMock->expects($this->any()) + $websiteMock = $this->createMock(WebsiteInterface::class); + $websiteMock->expects($this->atLeastOnce()) ->method('getId') ->willReturn($websiteId); + $this->websiteRepositoryMock->expects($this->once()) + ->method('getList') + ->willReturn([$websiteMock]); - /** @var Group|\PHPUnit_Framework_MockObject_MockObject $groupMock */ - $groupMock = $this->getMockBuilder(\Magento\Store\Model\Group::class) - ->disableOriginalConstructor() - ->getMock(); - $groupMock->expects($this->any()) + $groupMock = $this->createMock(GroupInterface::class); + $groupMock->expects($this->atLeastOnce()) ->method('getId') ->willReturn($groupId); + $groupMock->expects($this->atLeastOnce()) + ->method('getWebsiteId') + ->willReturn($websiteId); + $this->groupRepositoryMock->expects($this->once()) + ->method('getList') + ->willReturn([$groupMock, $groupMock]); - /** @var Store|\PHPUnit_Framework_MockObject_MockObject $storeMock */ - $storeMock = $this->getMockBuilder(\Magento\Store\Model\Store::class) - ->disableOriginalConstructor() - ->getMock(); - $storeMock->expects($this->any()) + $storeMock = $this->createMock(StoreInterface::class); + $storeMock->expects($this->atLeastOnce()) ->method('getId') ->willReturn($storeId); - - $this->storeManagerMock->expects($this->any()) - ->method('getWebsites') - ->willReturn([$websiteMock]); - - $websiteMock->expects($this->any()) - ->method('getGroups') - ->willReturn([$groupMock, $groupMock]); - - $groupMock->expects($this->any()) - ->method('getStores') + $storeMock->expects($this->atLeastOnce()) + ->method('getStoreGroupId') + ->willReturn($groupId); + $this->storeRepositoryMock->expects($this->once()) + ->method('getList') ->willReturn([$storeMock, $storeMock, $storeMock]); $this->assertEquals($result, $this->model->get()); From d9c1a8865f54b2da43801554936c604bd3249a2c Mon Sep 17 00:00:00 2001 From: Tom Reece <treece@adobe.com> Date: Thu, 11 Jul 2019 10:43:51 -0500 Subject: [PATCH 667/773] MQE-1611: Part two fixing skipped tests --- .../Mftf/Section/AdminProductFormBundleSection.xml | 2 +- .../Section/AdminProductCustomizableOptionsSection.xml | 6 +++--- .../AdminProductFormAdvancedInventorySection.xml | 2 +- .../Section/AdminProductFormAdvancedPricingSection.xml | 4 ++-- .../Test/Mftf/Section/AdminProductFormSection.xml | 10 +++++----- .../Mftf/Section/AdminProductGridActionSection.xml | 2 +- .../Mftf/Section/StorefrontCategoryMainSection.xml | 2 +- ...CreateVirtualProductOutOfStockWithTierPriceTest.xml | 3 --- ...oductWithCustomOptionsSuiteAndImportOptionsTest.xml | 3 --- ...eVirtualProductWithTierPriceForGeneralGroupTest.xml | 3 --- .../AdminCreateVirtualProductWithTierPriceTest.xml | 3 --- ...AdminCreateVirtualProductWithoutManageStockTest.xml | 3 --- .../Section/StorefrontQuickSearchResultsSection.xml | 4 ++-- 13 files changed, 16 insertions(+), 31 deletions(-) diff --git a/app/code/Magento/Bundle/Test/Mftf/Section/AdminProductFormBundleSection.xml b/app/code/Magento/Bundle/Test/Mftf/Section/AdminProductFormBundleSection.xml index 516f40ac2e7b7..cb6f6c1b56a78 100644 --- a/app/code/Magento/Bundle/Test/Mftf/Section/AdminProductFormBundleSection.xml +++ b/app/code/Magento/Bundle/Test/Mftf/Section/AdminProductFormBundleSection.xml @@ -92,7 +92,7 @@ <!--Category Selection--> <element name="categoryByName" type="multiselect" selector="//div[@data-index='category_ids']//span[contains(text(), '{{category}}')]" parameterized="true"/> <element name="searchForCategory" type="input" selector="div.action-menu._active > div.admin__action-multiselect-search-wrap input" timeout="30"/> - <element name="selectCategory" type="multiselect" selector="//div[@class='action-menu _active']//label[@class='admin__action-multiselect-label']"/> + <element name="selectCategory" type="multiselect" selector="//div[@class='action-menu _active']//label[@class='admin__action-multiselect-label']" timeout="30"/> <element name="categoriesLabel" type="text" selector="//div[@class='action-menu _active']//button[@data-action='close-advanced-select']"/> <element name="userDefinedQuantity" type="checkbox" selector="[name='bundle_options[bundle_options][{{option}}][bundle_selections][{{product}}][selection_can_change_qty]'][type='checkbox']" parameterized="true"/> </section> diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductCustomizableOptionsSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductCustomizableOptionsSection.xml index a7ab0c3d8e404..6d4d5d86ef798 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductCustomizableOptionsSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductCustomizableOptionsSection.xml @@ -9,7 +9,7 @@ <sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="AdminProductCustomizableOptionsSection"> - <element name="checkIfCustomizableOptionsTabOpen" type="text" selector="//span[text()='Customizable Options']/parent::strong/parent::*[@data-state-collapsible='closed']"/> + <element name="checkIfCustomizableOptionsTabOpen" type="text" selector="//span[text()='Customizable Options']/parent::strong/parent::*[@data-state-collapsible='closed']" timeout="30"/> <element name="customizableOptions" type="text" selector="//strong[contains(@class, 'admin__collapsible-title')]/span[text()='Customizable Options']"/> <element name="useDefaultOptionTitle" type="text" selector="[data-index='options'] tr.data-row [data-index='title'] [name^='options_use_default']"/> <element name="useDefaultOptionTitleByIndex" type="text" selector="[data-index='options'] [data-index='values'] tr[data-repeat-index='{{var1}}'] [name^='options_use_default']" parameterized="true"/> @@ -23,8 +23,8 @@ <element name="customOption" type="block" selector="[data-index='options'] tbody tr.data-row"/> <element name="customOptionButtonDelete" type="button" selector="[data-index='options'] [data-index='delete_button']"/> - <element name="optionTypeDropDown" type="select" selector="//table[@data-index='options']//tr[{{index}}]//div[@data-index='type']//div[contains(@class, 'action-select-wrap')]" parameterized="true" /> - <element name="optionTypeItem" type="select" selector="//table[@data-index='options']//tr[{{index}}]//div[@data-index='type']//*[contains(@class, 'action-menu-item')]//*[contains(., '{{optionValue}}')]" parameterized="true" /> + <element name="optionTypeDropDown" type="select" selector="//table[@data-index='options']//tr[{{index}}]//div[@data-index='type']//div[contains(@class, 'action-select-wrap')]" parameterized="true" timeout="30"/> + <element name="optionTypeItem" type="select" selector="//table[@data-index='options']//tr[{{index}}]//div[@data-index='type']//*[contains(@class, 'action-menu-item')]//*[contains(., '{{optionValue}}')]" parameterized="true" timeout="30"/> <element name="checkSelect" type="select" selector="//span[text()='{{var1}}']/parent::div/parent::div/parent::div//span[text()='Option Type']/parent::label/parent::div/parent::div//div[@data-role='selected-option']" parameterized="true"/> <element name="checkOptionType" type="select" selector="//span[text()='{{optionTitle}}']/parent::div/parent::div/parent::div//parent::label/parent::div/parent::div//li[@class='admin__action-multiselect-menu-inner-item']//label[text()='{{optionType}}']" parameterized="true"/> <element name="checkDropDown" type="select" selector="//span[text()='{{var1}}']/parent::div/parent::div/parent::div//parent::label/parent::div/parent::div//li[@class='admin__action-multiselect-menu-inner-item']//label[text()='Drop-down']" parameterized="true"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormAdvancedInventorySection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormAdvancedInventorySection.xml index a4517cfd46168..4196a86fe25db 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormAdvancedInventorySection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormAdvancedInventorySection.xml @@ -18,7 +18,7 @@ <element name="qtyIncrementsUseConfigSettings" type="checkbox" selector="//input[@name='product[stock_data][use_config_qty_increments]']"/> <element name="doneButton" type="button" selector="//aside[contains(@class,'product_form_product_form_advanced_inventory_modal')]//button[contains(@data-role,'action')]" timeout="5"/> <element name="useConfigSettings" type="checkbox" selector="//input[@name='product[stock_data][use_config_manage_stock]']"/> - <element name="manageStock" type="select" selector="//*[@name='product[stock_data][manage_stock]']"/> + <element name="manageStock" type="select" selector="//*[@name='product[stock_data][manage_stock]']" timeout="30"/> <element name="advancedInventoryCloseButton" type="button" selector=".product_form_product_form_advanced_inventory_modal button.action-close" timeout="30"/> <element name="miniQtyConfigSetting" type="checkbox" selector="//*[@name='product[stock_data][use_config_min_sale_qty]']"/> <element name="miniQtyAllowedInCart" type="input" selector="//*[@name='product[stock_data][min_sale_qty]']"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormAdvancedPricingSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormAdvancedPricingSection.xml index a17bd3794cffd..77b89a07fb76a 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormAdvancedPricingSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormAdvancedPricingSection.xml @@ -21,9 +21,9 @@ <element name="productTierPriceFixedPriceInput" type="input" selector="[name='product[tier_price][{{var1}}][price]']" parameterized="true"/> <element name="productTierPricePercentageValuePriceInput" type="input" selector="[name='product[tier_price][{{var1}}][percentage_value]']" parameterized="true"/> <element name="specialPrice" type="input" selector="input[name='product[special_price]']"/> - <element name="doneButton" type="button" selector=".product_form_product_form_advanced_pricing_modal button.action-primary" timeout="5"/> + <element name="doneButton" type="button" selector=".product_form_product_form_advanced_pricing_modal button.action-primary" timeout="30"/> <element name="msrp" type="input" selector="//input[@name='product[msrp]']" timeout="30"/> <element name="msrpType" type="select" selector="//select[@name='product[msrp_display_actual_price_type]']" timeout="30"/> - <element name="save" type="button" selector="#save-button"/> + <element name="save" type="button" selector="#save-button" timeout="30"/> </section> </sections> diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormSection.xml index 5e2c2d365179f..f537a68e4dc3a 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormSection.xml @@ -34,11 +34,11 @@ <element name="productTaxClassUseDefault" type="checkbox" selector="input[name='use_default[tax_class_id]']"/> <element name="advancedPricingLink" type="button" selector="button[data-index='advanced_pricing_button']" timeout="30"/> <element name="currentCategory" type="text" selector=".admin__action-multiselect-crumb > span"/> - <element name="categoriesDropdown" type="multiselect" selector="div[data-index='category_ids']"/> + <element name="categoriesDropdown" type="multiselect" selector="div[data-index='category_ids']" timeout="30"/> <element name="unselectCategories" type="button" selector="//span[@class='admin__action-multiselect-crumb']/span[contains(.,'{{category}}')]/../button[@data-action='remove-selected-item']" parameterized="true" timeout="30"/> <element name="productQuantity" type="input" selector=".admin__field[data-index=qty] input"/> <element name="advancedInventoryLink" type="button" selector="//button[contains(@data-index, 'advanced_inventory_button')]" timeout="30"/> - <element name="productStockStatus" type="select" selector="select[name='product[quantity_and_stock_status][is_in_stock]']"/> + <element name="productStockStatus" type="select" selector="select[name='product[quantity_and_stock_status][is_in_stock]']" timeout="30"/> <element name="productStockStatusDisabled" type="select" selector="select[name='product[quantity_and_stock_status][is_in_stock]'][disabled=true]"/> <element name="stockStatus" type="select" selector="[data-index='product-details'] select[name='product[quantity_and_stock_status][is_in_stock]']"/> <element name="productWeight" type="input" selector=".admin__field[data-index=weight] input"/> @@ -48,7 +48,7 @@ <element name="priceFieldError" type="text" selector="//input[@name='product[price]']/parent::div/parent::div/label[@class='admin__field-error']"/> <element name="addAttributeBtn" type="button" selector="#addAttribute"/> <element name="createNewAttributeBtn" type="button" selector="button[data-index='add_new_attribute_button']"/> - <element name="save" type="button" selector="#save-button"/> + <element name="save" type="button" selector="#save-button" timeout="30"/> <element name="saveNewAttribute" type="button" selector="//aside[contains(@class, 'create_new_attribute_modal')]//button[@id='save']"/> <element name="successMessage" type="text" selector="#messages"/> <element name="attributeTab" type="button" selector="//strong[contains(@class, 'admin__collapsible-title')]/span[text()='Attributes']"/> @@ -67,7 +67,7 @@ <element name="attributeFieldError" type="text" selector="//*[@class='admin__field _required _error']/..//label[contains(.,'This is a required field.')]"/> <element name="customSelectField" type="select" selector="//select[@name='product[{{var}}]']" parameterized="true"/> <element name="searchCategory" type="input" selector="//*[@data-index='category_ids']//input[contains(@class, 'multiselect-search')]"/> - <element name="selectCategory" type="input" selector="//*[@data-index='category_ids']//label[contains(., '{{categoryName}}')]" parameterized="true"/> + <element name="selectCategory" type="input" selector="//*[@data-index='category_ids']//label[contains(., '{{categoryName}}')]" parameterized="true" timeout="30"/> <element name="done" type="button" selector="//*[@data-index='category_ids']//button[@data-action='close-advanced-select']" timeout="30"/> <element name="selectMultipleCategories" type="input" selector="//*[@data-index='container_category_ids']//*[contains(@class, '_selected')]"/> <element name="countryOfManufacture" type="select" selector="select[name='product[country_of_manufacture]']"/> @@ -205,7 +205,7 @@ </section> <section name="AdminProductFormAdvancedPricingSection"> <element name="specialPrice" type="input" selector="input[name='product[special_price]']"/> - <element name="doneButton" type="button" selector=".product_form_product_form_advanced_pricing_modal button.action-primary"/> + <element name="doneButton" type="button" selector=".product_form_product_form_advanced_pricing_modal button.action-primary" timeout="30"/> <element name="useDefaultPrice" type="checkbox" selector="//input[@name='product[special_price]']/parent::div/following-sibling::div/input[@name='use_default[special_price]']"/> </section> <section name="AdminProductAttributeSection"> diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductGridActionSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductGridActionSection.xml index 3b74041684017..66e6f17be3430 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductGridActionSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductGridActionSection.xml @@ -10,7 +10,7 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="AdminProductGridActionSection"> <element name="addProductBtn" type="button" selector="#add_new_product-button" timeout="30"/> - <element name="addProductToggle" type="button" selector=".action-toggle.primary.add"/> + <element name="addProductToggle" type="button" selector=".action-toggle.primary.add" timeout="30"/> <element name="addSimpleProduct" type="button" selector=".item[data-ui-id='products-list-add-new-product-button-item-simple']" timeout="30"/> <element name="addGroupedProduct" type="button" selector=".item[data-ui-id='products-list-add-new-product-button-item-grouped']" timeout="30"/> <element name="addVirtualProduct" type="button" selector=".item[data-ui-id='products-list-add-new-product-button-item-virtual']" timeout="30"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryMainSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryMainSection.xml index 1cd64544d9636..ac7a15daf56aa 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryMainSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryMainSection.xml @@ -24,7 +24,7 @@ <element name="mediaDescription" type="text" selector="img[alt='{{var1}}']" parameterized="true"/> <element name="imageSource" type="text" selector="//img[contains(@src,'{{var1}}')]" parameterized="true"/> <element name="productImage" type="text" selector="img.product-image-photo"/> - <element name="productLink" type="text" selector="a.product-item-link"/> + <element name="productLink" type="text" selector="a.product-item-link" timeout="30"/> <element name="productLinkByHref" type="text" selector="a.product-item-link[href$='{{var1}}.html']" parameterized="true"/> <element name="productPrice" type="text" selector=".price-final_price"/> <element name="categoryImage" type="text" selector=".category-image"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductOutOfStockWithTierPriceTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductOutOfStockWithTierPriceTest.xml index e516a046e489e..26ad7a46a73d7 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductOutOfStockWithTierPriceTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductOutOfStockWithTierPriceTest.xml @@ -17,9 +17,6 @@ <severity value="CRITICAL"/> <group value="catalog"/> <group value="mtf_migrated"/> - <skip> - <issueId value="MC-17181"/> - </skip> </annotations> <before> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductWithCustomOptionsSuiteAndImportOptionsTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductWithCustomOptionsSuiteAndImportOptionsTest.xml index 6ee3fa6c60b82..17769c79677f7 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductWithCustomOptionsSuiteAndImportOptionsTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductWithCustomOptionsSuiteAndImportOptionsTest.xml @@ -17,9 +17,6 @@ <severity value="CRITICAL"/> <group value="catalog"/> <group value="mtf_migrated"/> - <skip> - <issueId value="MC-17181"/> - </skip> </annotations> <before> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductWithTierPriceForGeneralGroupTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductWithTierPriceForGeneralGroupTest.xml index b777babf3b3aa..78247f4943596 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductWithTierPriceForGeneralGroupTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductWithTierPriceForGeneralGroupTest.xml @@ -17,9 +17,6 @@ <severity value="CRITICAL"/> <group value="catalog"/> <group value="mtf_migrated"/> - <skip> - <issueId value="MC-17181"/> - </skip> </annotations> <before> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductWithTierPriceTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductWithTierPriceTest.xml index 28923674f4ab3..6ef2569945fa6 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductWithTierPriceTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductWithTierPriceTest.xml @@ -17,9 +17,6 @@ <severity value="CRITICAL"/> <group value="catalog"/> <group value="mtf_migrated"/> - <skip> - <issueId value="MC-17181"/> - </skip> </annotations> <before> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductWithoutManageStockTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductWithoutManageStockTest.xml index 8c5085501b799..cb41b0292d33a 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductWithoutManageStockTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductWithoutManageStockTest.xml @@ -17,9 +17,6 @@ <severity value="CRITICAL"/> <group value="catalog"/> <group value="mtf_migrated"/> - <skip> - <issueId value="MC-17181"/> - </skip> </annotations> <before> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> diff --git a/app/code/Magento/Search/Test/Mftf/Section/StorefrontQuickSearchResultsSection.xml b/app/code/Magento/Search/Test/Mftf/Section/StorefrontQuickSearchResultsSection.xml index 0bb929d889351..fcd588984c481 100644 --- a/app/code/Magento/Search/Test/Mftf/Section/StorefrontQuickSearchResultsSection.xml +++ b/app/code/Magento/Search/Test/Mftf/Section/StorefrontQuickSearchResultsSection.xml @@ -10,9 +10,9 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="StorefrontQuickSearchResultsSection"> <element name="searchTextBox" type="text" selector="#search"/> - <element name="searchTextBoxButton" type="button" selector="button[class='action search']"/> + <element name="searchTextBoxButton" type="button" selector="button[class='action search']" timeout="30"/> <element name="allResults" type="block" selector=".column.main"/> - <element name="productLink" type="select" selector="a[class='product-item-link']"/> + <element name="productLink" type="select" selector="a[class='product-item-link']" timeout="30"/> <element name="productByIndex" type="button" selector=".product-items li:nth-child({{var}}) .product-item-info" parameterized="true"/> <element name="productByName" type="button" selector="//div[contains(@class, 'product-item-info') and .//*[contains(., '{{var}}')]]" parameterized="true"/> <element name="addToCartBtn" type="button" selector="//button[contains(@class, 'tocart')]"/> From db81564f62108b05e8df8185b696cf7a2a6b0867 Mon Sep 17 00:00:00 2001 From: Dmytro Horytskyi <horytsky@adobe.com> Date: Thu, 11 Jul 2019 16:13:42 +0000 Subject: [PATCH 668/773] MC-18070: Website-level admin user edits to themes impacts grid for other admin users --- app/code/Magento/Store/Model/ScopeTreeProvider.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/code/Magento/Store/Model/ScopeTreeProvider.php b/app/code/Magento/Store/Model/ScopeTreeProvider.php index 47ed2276c1374..da772ec0410e0 100644 --- a/app/code/Magento/Store/Model/ScopeTreeProvider.php +++ b/app/code/Magento/Store/Model/ScopeTreeProvider.php @@ -48,7 +48,6 @@ public function __construct( /** * @inheritdoc - * @return array */ public function get() { From 4ad02b2059570c03d8c222f7b9ed59d1b7b1be54 Mon Sep 17 00:00:00 2001 From: Andrew Molina <amolina@adobe.com> Date: Thu, 11 Jul 2019 11:28:19 -0500 Subject: [PATCH 669/773] MC-5777: Catalog rule does not apply as expected in EE --- .../ConditionBuilder/EavAttributeCondition.php | 2 +- .../CatalogRule/Model/RuleDateFormatter.php | 4 ++-- .../Model/RuleDateFormatterInterface.php | 14 +++++++------- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Api/SearchCriteria/CollectionProcessor/ConditionProcessor/ConditionBuilder/EavAttributeCondition.php b/app/code/Magento/Catalog/Model/Api/SearchCriteria/CollectionProcessor/ConditionProcessor/ConditionBuilder/EavAttributeCondition.php index a4a03bef0f39c..e296c8d3b8978 100644 --- a/app/code/Magento/Catalog/Model/Api/SearchCriteria/CollectionProcessor/ConditionProcessor/ConditionBuilder/EavAttributeCondition.php +++ b/app/code/Magento/Catalog/Model/Api/SearchCriteria/CollectionProcessor/ConditionProcessor/ConditionBuilder/EavAttributeCondition.php @@ -64,7 +64,7 @@ public function build(Filter $filter): string ->select() ->from( [Collection::MAIN_TABLE_ALIAS => $entityResourceModel->getEntityTable()], - Collection::MAIN_TABLE_ALIAS . '.' . $entityResourceModel->getLinkField() + Collection::MAIN_TABLE_ALIAS . '.' . $entityResourceModel->getEntityIdField() )->joinLeft( [$tableAlias => $attribute->getBackendTable()], $tableAlias . '.' . $attribute->getEntityIdField() . '=' . Collection::MAIN_TABLE_ALIAS . diff --git a/app/code/Magento/CatalogRule/Model/RuleDateFormatter.php b/app/code/Magento/CatalogRule/Model/RuleDateFormatter.php index ddf2d2232cbd3..8d55c5bfa6b3f 100644 --- a/app/code/Magento/CatalogRule/Model/RuleDateFormatter.php +++ b/app/code/Magento/CatalogRule/Model/RuleDateFormatter.php @@ -28,7 +28,7 @@ public function __construct(\Magento\Framework\Stdlib\DateTime\TimezoneInterface /** * @inheritdoc */ - public function getDate($scope = null) + public function getDate($scope = null): \DateTime { return $this->localeDate->scopeDate($scope, null, true); } @@ -36,7 +36,7 @@ public function getDate($scope = null) /** * @inheritdoc */ - public function getTimeStamp($scope = null) + public function getTimeStamp($scope = null): int { return $this->localeDate->scopeTimeStamp($scope); } diff --git a/app/code/Magento/CatalogRule/Model/RuleDateFormatterInterface.php b/app/code/Magento/CatalogRule/Model/RuleDateFormatterInterface.php index 5cac66e603edb..a836f049eb5e7 100644 --- a/app/code/Magento/CatalogRule/Model/RuleDateFormatterInterface.php +++ b/app/code/Magento/CatalogRule/Model/RuleDateFormatterInterface.php @@ -15,16 +15,16 @@ interface RuleDateFormatterInterface /** * Create \DateTime object with date converted to scope timezone for catalog rule * - * @param mixed $scope Information about scope - * @return \DateTime + * @param mixed $scope Information about scope + * @return \DateTime */ - public function getDate($scope = null); + public function getDate($scope = null): \DateTime; /** - * Get scope timestamp for catalog rule + * Get scope timestamp for catalog rule * - * @param mixed $scope Information about scope - * @return int + * @param mixed $scope Information about scope + * @return int */ - public function getTimeStamp($scope = null); + public function getTimeStamp($scope = null): int; } From 2756bc970d160d30afe4315259067da7cb8c4fea Mon Sep 17 00:00:00 2001 From: Ryan Simmons <rsimmons@crimsonagility.com> Date: Thu, 11 Jul 2019 09:55:24 -0700 Subject: [PATCH 670/773] Fixes static test failure - removes unnecessary multiple line break --- .../frontend/web/js/model/billing-address-postcode-validator.js | 1 - 1 file changed, 1 deletion(-) diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/billing-address-postcode-validator.js b/app/code/Magento/Checkout/view/frontend/web/js/model/billing-address-postcode-validator.js index 863954add73b7..2c1c21eea6ecb 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/model/billing-address-postcode-validator.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/model/billing-address-postcode-validator.js @@ -23,7 +23,6 @@ define([ validateZipCodeTimeout: 0, validateDelay: 2000, - /** * Perform postponed binding for fieldset elements * From d0ff6903765f3d5be09034bc77023100bf3430c6 Mon Sep 17 00:00:00 2001 From: Deepty Thampy <dthampy@adobe.com> Date: Thu, 11 Jul 2019 11:58:39 -0500 Subject: [PATCH 671/773] MC-17875: Refactor GraphQl Integration tests - remove suppressions --- .../Resolver/Customer/SetAuthorizeNetPaymentMethodOnCartTest.php | 1 - .../Resolver/Guest/SetAuthorizeNetPaymentMethodOnCartTest.php | 1 - 2 files changed, 2 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/AuthorizenetGraphQl/Model/Resolver/Customer/SetAuthorizeNetPaymentMethodOnCartTest.php b/dev/tests/integration/testsuite/Magento/AuthorizenetGraphQl/Model/Resolver/Customer/SetAuthorizeNetPaymentMethodOnCartTest.php index e19042693b756..e304216bc4a77 100644 --- a/dev/tests/integration/testsuite/Magento/AuthorizenetGraphQl/Model/Resolver/Customer/SetAuthorizeNetPaymentMethodOnCartTest.php +++ b/dev/tests/integration/testsuite/Magento/AuthorizenetGraphQl/Model/Resolver/Customer/SetAuthorizeNetPaymentMethodOnCartTest.php @@ -19,7 +19,6 @@ * * @magentoAppArea graphql * @magentoDbIsolation disabled - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class SetAuthorizeNetPaymentMethodOnCartTest extends TestCase { diff --git a/dev/tests/integration/testsuite/Magento/AuthorizenetGraphQl/Model/Resolver/Guest/SetAuthorizeNetPaymentMethodOnCartTest.php b/dev/tests/integration/testsuite/Magento/AuthorizenetGraphQl/Model/Resolver/Guest/SetAuthorizeNetPaymentMethodOnCartTest.php index 95dcf9829939f..fef20df4ee931 100644 --- a/dev/tests/integration/testsuite/Magento/AuthorizenetGraphQl/Model/Resolver/Guest/SetAuthorizeNetPaymentMethodOnCartTest.php +++ b/dev/tests/integration/testsuite/Magento/AuthorizenetGraphQl/Model/Resolver/Guest/SetAuthorizeNetPaymentMethodOnCartTest.php @@ -19,7 +19,6 @@ * * @magentoAppArea graphql * @magentoDbIsolation disabled - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class SetAuthorizeNetPaymentMethodOnCartTest extends TestCase { From e6ab6a5b6b1900155c6e23b3b95bf19697051b29 Mon Sep 17 00:00:00 2001 From: Ryan Simmons <rsimmons@crimsonagility.com> Date: Thu, 11 Jul 2019 10:31:44 -0700 Subject: [PATCH 672/773] Removes another unnecessary multiple line break --- .../frontend/web/js/model/billing-address-postcode-validator.js | 1 - 1 file changed, 1 deletion(-) diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/billing-address-postcode-validator.js b/app/code/Magento/Checkout/view/frontend/web/js/model/billing-address-postcode-validator.js index 2c1c21eea6ecb..c2bf33ac6c570 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/model/billing-address-postcode-validator.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/model/billing-address-postcode-validator.js @@ -18,7 +18,6 @@ define([ var postcodeElementName = 'postcode'; - return { validateZipCodeTimeout: 0, validateDelay: 2000, From 94a6dc4cacbd4c845467d9f576e9141b7bc9cf59 Mon Sep 17 00:00:00 2001 From: Andrew Molina <amolina@adobe.com> Date: Thu, 11 Jul 2019 13:42:48 -0500 Subject: [PATCH 673/773] MC-5777: Catalog rule does not apply as expected in EE * Fixed broken unit test --- .../Test/Unit/Pricing/Price/CatalogRulePriceTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/CatalogRule/Test/Unit/Pricing/Price/CatalogRulePriceTest.php b/app/code/Magento/CatalogRule/Test/Unit/Pricing/Price/CatalogRulePriceTest.php index 3d19851df7335..29b040d7299d1 100644 --- a/app/code/Magento/CatalogRule/Test/Unit/Pricing/Price/CatalogRulePriceTest.php +++ b/app/code/Magento/CatalogRule/Test/Unit/Pricing/Price/CatalogRulePriceTest.php @@ -170,7 +170,7 @@ public function testGetValue() $coreWebsiteId = 1; $productId = 1; $customerGroupId = 1; - $dateTime = time(); + $dateTime = new \DateTime(); $catalogRulePrice = 55.12; $convertedPrice = 45.34; From 1c9df248b370ac67432c395e72846adf28c35eb2 Mon Sep 17 00:00:00 2001 From: Ryan Simmons <rsimmons@crimsonagility.com> Date: Thu, 11 Jul 2019 15:22:44 -0700 Subject: [PATCH 674/773] Fixes static test failure - removes trailing commas --- .../web/js/model/billing-address-postcode-validator.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/billing-address-postcode-validator.js b/app/code/Magento/Checkout/view/frontend/web/js/model/billing-address-postcode-validator.js index c2bf33ac6c570..4a4729211588d 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/model/billing-address-postcode-validator.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/model/billing-address-postcode-validator.js @@ -7,12 +7,12 @@ define([ 'jquery', 'Magento_Checkout/js/model/postcode-validator', 'mage/translate', - 'uiRegistry', + 'uiRegistry' ], function ( $, postcodeValidator, $t, - uiRegistry, + uiRegistry ) { 'use strict'; From a3c306161c5b3509970e38f4840cf983acb0c599 Mon Sep 17 00:00:00 2001 From: Ryan Simmons <rsimmons@crimsonagility.com> Date: Thu, 11 Jul 2019 16:38:34 -0700 Subject: [PATCH 675/773] Fixes static test failure - adds blank line after variable declaration --- .../frontend/web/js/model/billing-address-postcode-validator.js | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/billing-address-postcode-validator.js b/app/code/Magento/Checkout/view/frontend/web/js/model/billing-address-postcode-validator.js index 4a4729211588d..b101b67d26bae 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/model/billing-address-postcode-validator.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/model/billing-address-postcode-validator.js @@ -29,6 +29,7 @@ define([ */ initFields: function (formPath) { var self = this; + uiRegistry.async(formPath + '.' + postcodeElementName)(self.bindHandler.bind(self)); }, From 915b493ce96b29e87b1eca3b4b66698c2407f7fb Mon Sep 17 00:00:00 2001 From: "rostyslav.hymon" <rostyslav.hymon@transoftgroup.com> Date: Fri, 12 Jul 2019 11:37:24 +0300 Subject: [PATCH 676/773] MC-17984: Authorize.net cannot place order from admin panel --- .../adminhtml/templates/payment/script.phtml | 26 ++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/app/code/Magento/AuthorizenetAcceptjs/view/adminhtml/templates/payment/script.phtml b/app/code/Magento/AuthorizenetAcceptjs/view/adminhtml/templates/payment/script.phtml index 6960bddf696af..60090e2c9752a 100644 --- a/app/code/Magento/AuthorizenetAcceptjs/view/adminhtml/templates/payment/script.phtml +++ b/app/code/Magento/AuthorizenetAcceptjs/view/adminhtml/templates/payment/script.phtml @@ -6,12 +6,20 @@ /** @var Magento\AuthorizenetAcceptjs\Block\Payment $block */ ?> -<script type="text/x-magento-init"> - { - "#payment_form_<?= $block->escapeJs($block->escapeHtml($block->getMethodCode())) ?>": { - "Magento_AuthorizenetAcceptjs/js/payment-form": { - "config": <?= /* @noEscape */ $block->getPaymentConfig() ?> - } - } - } -</script> \ No newline at end of file +<script> + //<![CDATA[ + require( + [ + 'Magento_AuthorizenetAcceptjs/js/authorizenet', + 'jquery', + 'domReady!' + ], function(AuthorizenetAcceptjs, $) { + var config = <?= /* @noEscape */ $block->getPaymentConfig() ?>, + payment, + form = $('#payment_form_<?= /* @noEscape */ $block->escapeJs($block->escapeHtml($block->getMethodCode())) ?>'); + + config.active = form.length > 0 && !form.is(':hidden'); + payment = new AuthorizenetAcceptjs(config); + }); + //]]> +</script> From 616b2432be893f0d7c6e07b4768ff589c9afd7af Mon Sep 17 00:00:00 2001 From: Mastiuhin Olexandr <mastiuhin.olexandr@transoftgroup.com> Date: Fri, 12 Jul 2019 14:41:51 +0300 Subject: [PATCH 677/773] MC-17524: Child product is not addable to Cart from PLP if it does not have default source assigned --- .../Plugin/OutOfStockFilter.php | 59 ++--- .../Test/Unit/Plugin/OutOfStockFilterTest.php | 245 ++++++++---------- 2 files changed, 129 insertions(+), 175 deletions(-) diff --git a/app/code/Magento/GroupedCatalogInventory/Plugin/OutOfStockFilter.php b/app/code/Magento/GroupedCatalogInventory/Plugin/OutOfStockFilter.php index 599f40deddde0..c8c40042f5034 100644 --- a/app/code/Magento/GroupedCatalogInventory/Plugin/OutOfStockFilter.php +++ b/app/code/Magento/GroupedCatalogInventory/Plugin/OutOfStockFilter.php @@ -10,77 +10,52 @@ use Magento\Catalog\Model\Product; use Magento\CatalogInventory\Api\Data\StockStatusInterface; -use Magento\CatalogInventory\Api\StockStatusCriteriaInterfaceFactory; -use Magento\CatalogInventory\Api\StockStatusRepositoryInterface; use Magento\GroupedProduct\Model\Product\Type\Grouped; +use Magento\CatalogInventory\Api\StockRegistryInterface; +use Magento\Framework\DataObject; /** - * Removes out of stock products from cart candidates when appropriate + * Removes out of stock products from cart candidates when appropriate. */ class OutOfStockFilter { /** - * @var StockStatusRepositoryInterface + * @var StockRegistryInterface */ - private $stockStatusRepository; + private $stockRegistry; /** - * @var StockStatusCriteriaInterfaceFactory + * @param StockRegistryInterface $stockRegistry */ - private $criteriaInterfaceFactory; - - /** - * @param StockStatusRepositoryInterface $stockStatusRepository - * @param StockStatusCriteriaInterfaceFactory $criteriaInterfaceFactory - */ - public function __construct( - StockStatusRepositoryInterface $stockStatusRepository, - StockStatusCriteriaInterfaceFactory $criteriaInterfaceFactory - ) { - $this->stockStatusRepository = $stockStatusRepository; - $this->criteriaInterfaceFactory = $criteriaInterfaceFactory; + public function __construct(StockRegistryInterface $stockRegistry) + { + $this->stockRegistry = $stockRegistry; } /** - * Removes out of stock products for requests that don't specify the super group + * Removes out of stock products for requests that don't specify the super group. * * @param Grouped $subject * @param array|string $result - * @param \Magento\Framework\DataObject $buyRequest + * @param DataObject $buyRequest * @return string|array * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - public function afterPrepareForCartAdvanced( - Grouped $subject, - $result, - \Magento\Framework\DataObject $buyRequest - ) { + public function afterPrepareForCartAdvanced(Grouped $subject, $result, DataObject $buyRequest) + { if (!is_array($result) && $result instanceof Product) { $result = [$result]; } // Only remove out-of-stock products if no quantities were specified if (is_array($result) && !empty($result) && !$buyRequest->getData('super_group')) { - $productIds = []; - $productIdMap = []; - foreach ($result as $index => $cartItem) { - $productIds[] = $cartItem->getId(); - $productIdMap[$cartItem->getId()] = $index; - } - - $criteria = $this->criteriaInterfaceFactory->create(); - $criteria->setProductsFilter($productIds); - - $stockStatusCollection = $this->stockStatusRepository->getList($criteria); - foreach ($stockStatusCollection->getItems() as $status) { - /** @var $status StockStatusInterface */ - if ($status->getStockStatus() == StockStatusInterface::STATUS_OUT_OF_STOCK) { - unset($result[$productIdMap[$status->getProductId()]]); + $prodId = $cartItem->getId(); + $productStockStatus = $this->stockRegistry->getProductStockStatus($prodId); + if ($productStockStatus == StockStatusInterface::STATUS_OUT_OF_STOCK) { + unset($result[$index]); } } - - unset($productIdMap); } return $result; diff --git a/app/code/Magento/GroupedCatalogInventory/Test/Unit/Plugin/OutOfStockFilterTest.php b/app/code/Magento/GroupedCatalogInventory/Test/Unit/Plugin/OutOfStockFilterTest.php index 07877938e36ae..2ea1db594ccbd 100644 --- a/app/code/Magento/GroupedCatalogInventory/Test/Unit/Plugin/OutOfStockFilterTest.php +++ b/app/code/Magento/GroupedCatalogInventory/Test/Unit/Plugin/OutOfStockFilterTest.php @@ -8,127 +8,176 @@ namespace Magento\GroupedCatalogInventory\Test\Unit\Plugin; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; use Magento\Catalog\Model\Product; -use Magento\CatalogInventory\Api\Data\StockStatusCollectionInterface; use Magento\CatalogInventory\Api\Data\StockStatusInterface; -use Magento\CatalogInventory\Api\StockStatusCriteriaInterface; -use Magento\CatalogInventory\Api\StockStatusCriteriaInterfaceFactory; -use Magento\CatalogInventory\Api\StockStatusRepositoryInterface; use Magento\Framework\DataObject; use Magento\GroupedCatalogInventory\Plugin\OutOfStockFilter; use Magento\GroupedProduct\Model\Product\Type\Grouped; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; +use Magento\CatalogInventory\Api\StockRegistryInterface; + +/** + * Test for OutOfStockFilter plugin. + */ class OutOfStockFilterTest extends TestCase { /** - * @var MockObject + * @var OutOfStockFilter */ - private $subjectMock; - + private $unit; /** - * @var MockObject + * @var Grouped|MockObject */ - private $stockStatusRepositoryMock; + private $subjectMock; /** - * @var MockObject + * @var StockRegistryInterface|MockObject */ - private $searchCriteriaMock; + private $stockRegistryMock; /** - * @var MockObject + * @var DataObject|MockObject */ - private $searchCriteriaFactoryMock; + private $buyRequestMock; /** - * @var MockObject + * @inheritdoc */ - private $stockStatusCollectionMock; + protected function setUp() + { + $objectManager = new ObjectManager($this); + + $this->subjectMock = $this->getMockBuilder(Grouped::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->buyRequestMock = $this->getMockBuilder(DataObject::class) + ->getMock(); + + $this->stockRegistryMock = $this->getMockBuilder(StockRegistryInterface::class) + ->getMock(); + + $this->unit = $objectManager->getObject( + OutOfStockFilter::class, + [ + 'stockRegistry' => $this->stockRegistryMock, + ] + ); + } /** - * @param $nonArrayResult - * @dataProvider nonArrayResults + * Tests that the unit will process only parameters of array type. + * + * @param mixed $nonArrayResult + * @return void + * @dataProvider nonArrayResultsProvider */ - public function testFilterOnlyProcessesArray($nonArrayResult) + public function testFilterOnlyProcessesArray($nonArrayResult): void { - $this->searchCriteriaMock->expects($this->never())->method('setProductsFilter'); - $this->stockStatusRepositoryMock->expects($this->never())->method('getList'); + $this->stockRegistryMock->expects($this->never()) + ->method('getProductStockStatus'); - $plugin = $this->getPluginInstance(); - - $result = $plugin->afterPrepareForCartAdvanced( + $result = $this->unit->afterPrepareForCartAdvanced( $this->subjectMock, $nonArrayResult, - new DataObject() + $this->buyRequestMock ); $this->assertSame($nonArrayResult, $result); } - public function testFilterIgnoresResultIfSuperGroupIsPresent() + /** + * Tests that the unit will not process if special parameter "super_group" will present in "buyRequest" parameter. + * + * @return void + */ + public function testFilterIgnoresResultIfSuperGroupIsPresent(): void { - $this->searchCriteriaMock->expects($this->never())->method('setProductsFilter'); - $this->stockStatusRepositoryMock->expects($this->never())->method('getList'); - - $plugin = $this->getPluginInstance(); + $this->stockRegistryMock->method('getProductStockStatus') + ->willReturn(StockStatusInterface::STATUS_OUT_OF_STOCK); + $this->buyRequestMock->method('getData') + ->with('super_group') + ->willReturn([123 => '1']); $product = $this->createProductMock(); - $result = $plugin->afterPrepareForCartAdvanced( + $result = $this->unit->afterPrepareForCartAdvanced( $this->subjectMock, [$product], - new DataObject(['super_group' => [123 => '1']]) + $this->buyRequestMock ); - $this->assertSame([$product], $result); + $this->assertSame([$product], $result, 'All products should stay in array if super_group is setted.'); } /** - * @param $originalResult - * @param $stockStatusCollection - * @param $expectedResult - * @dataProvider outOfStockProductData + * Tests that out of stock products will be removed from resulting array. + * + * @param array $originalResult + * @param array $productStockStatusMap + * @param array $expectedResult + * @dataProvider outOfStockProductDataProvider */ - public function testFilterRemovesOutOfStockProductsWhenSuperGroupIsNotPresent( + public function testFilterRemovesOutOfStockProducts( $originalResult, - $stockStatusCollection, - $expectedResult - ) { - $this->stockStatusRepositoryMock - ->expects($this->once()) - ->method('getList') - ->with($this->searchCriteriaMock) - ->willReturn($stockStatusCollection); - - $plugin = $this->getPluginInstance(); - - $result = $plugin->afterPrepareForCartAdvanced( + array $productStockStatusMap, + array $expectedResult + ): void { + $this->stockRegistryMock->method('getProductStockStatus') + ->will($this->returnValueMap($productStockStatusMap)); + + $result = $this->unit->afterPrepareForCartAdvanced( $this->subjectMock, $originalResult, - new DataObject() + $this->buyRequestMock ); $this->assertSame($expectedResult, $result); } - public function outOfStockProductData() + /** + * Out of stock + * + * @return array + */ + public function outOfStockProductDataProvider(): array { $product1 = $this->createProductMock(); - $product1->method('getId')->willReturn(123); + $product1->method('getId') + ->willReturn(123); $product2 = $this->createProductMock(); - $product2->method('getId')->willReturn(321); + $product2->method('getId') + ->willReturn(321); return [ - [[$product1, $product2], $this->createStatusResult([123 => false, 321 => true]), [1 => $product2]], - [[$product1], $this->createStatusResult([123 => true]), [0 => $product1]], - [$product1, $this->createStatusResult([123 => true]), [0 => $product1]] + [ + 'originalResult' => [$product1, $product2], + 'productStockStatusMap' => [[123, null, false], [321, null, true]], + 'expectedResult' => [1 => $product2], + ], + [ + 'originalResult' => [$product1], + 'productStockStatusMap' => [[123, null, true]], + 'expectedResult' => [0 => $product1], + ], + [ + 'originalResult' => $product1, + 'productStockStatusMap' => [[123, null, true]], + 'expectedResult' => [0 => $product1], + ], ]; } - public function nonArrayResults() + /** + * Provider of non array type "result" parameters. + * + * @return array + */ + public function nonArrayResultsProvider(): array { return [ [123], @@ -137,85 +186,15 @@ public function nonArrayResults() ]; } - protected function setUp() - { - $this->subjectMock = $this->getMockBuilder(Grouped::class) - ->disableOriginalConstructor() - ->getMock(); - - $this->stockStatusRepositoryMock = $this->getMockBuilder(StockStatusRepositoryInterface::class) - ->getMock(); - - $this->searchCriteriaFactoryMock = $this->getMockBuilder(StockStatusCriteriaInterfaceFactory::class) - ->disableOriginalConstructor() - ->getMock(); - - $this->searchCriteriaMock = $this->getMockBuilder(StockStatusCriteriaInterface::class) - ->getMock(); - - $this->stockStatusCollectionMock = $this->getMockBuilder(StockStatusCollectionInterface::class) - ->getMock(); - - $this->searchCriteriaFactoryMock - ->expects($this->any()) - ->method('create') - ->willReturn($this->searchCriteriaMock); - } - - private function createProductMock() - { - return $this->getMockBuilder(Product::class) - ->disableOriginalConstructor() - ->getMock(); - } - /** - * @return OutOfStockFilter + * Creates new Product mock. + * + * @return MockObject|Product */ - private function getPluginInstance() - { - $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); - - /** @var OutOfStockFilter $filter */ - $filter = $objectManager->getObject(OutOfStockFilter::class, [ - 'stockStatusRepository' => $this->stockStatusRepositoryMock, - 'criteriaInterfaceFactory' => $this->searchCriteriaFactoryMock - ]); - - return $filter; - } - - private function createStatusResult(array $productStatuses) + private function createProductMock(): MockObject { - $result = []; - - foreach ($productStatuses as $productId => $status) { - $mock = $this->getMockBuilder(StockStatusInterface::class) - ->getMock(); - - $mock->expects($this->any()) - ->method('getProductId') - ->willReturn($productId); - - $mock->expects($this->any()) - ->method('getStockStatus') - ->willReturn( - $status - ? StockStatusInterface::STATUS_IN_STOCK - : StockStatusInterface::STATUS_OUT_OF_STOCK - ); - - $result[] = $mock; - } - - $stockStatusCollection = $this->getMockBuilder(StockStatusCollectionInterface::class) + return $this->getMockBuilder(Product::class) + ->disableOriginalConstructor() ->getMock(); - - $stockStatusCollection - ->expects($this->once()) - ->method('getItems') - ->willReturn($result); - - return $stockStatusCollection; } } From 089e24a10d2ee8d527e5e65308d384a095127461 Mon Sep 17 00:00:00 2001 From: Andrea Parmeggiani <andrea.parmeggiani@santacleo.com> Date: Fri, 12 Jul 2019 17:02:06 +0200 Subject: [PATCH 678/773] Moved Zero Subtotal Checkout Payment Settings --- .../OfflinePayments/etc/adminhtml/system.xml | 35 ------------------- .../Magento/Payment/etc/adminhtml/system.xml | 35 +++++++++++++++++++ 2 files changed, 35 insertions(+), 35 deletions(-) diff --git a/app/code/Magento/OfflinePayments/etc/adminhtml/system.xml b/app/code/Magento/OfflinePayments/etc/adminhtml/system.xml index 89cc4d0986a00..01f041bcb68c2 100644 --- a/app/code/Magento/OfflinePayments/etc/adminhtml/system.xml +++ b/app/code/Magento/OfflinePayments/etc/adminhtml/system.xml @@ -152,41 +152,6 @@ <label>Sort Order</label> </field> </group> - <group id="free" translate="label" type="text" sortOrder="30" showInDefault="1" showInWebsite="1" showInStore="1"> - <label>Zero Subtotal Checkout</label> - <field id="active" translate="label" type="select" sortOrder="1" showInDefault="1" showInWebsite="1" showInStore="0" canRestore="1"> - <label>Enabled</label> - <source_model>Magento\Config\Model\Config\Source\Yesno</source_model> - </field> - <field id="order_status" translate="label" type="select" sortOrder="2" showInDefault="1" showInWebsite="1" showInStore="0" canRestore="1"> - <label>New Order Status</label> - <source_model>Magento\Sales\Model\Config\Source\Order\Status\Newprocessing</source_model> - </field> - <field id="payment_action" translate="label" type="select" sortOrder="3" showInDefault="1" showInWebsite="1" showInStore="0" canRestore="1"> - <label>Automatically Invoice All Items</label> - <source_model>Magento\Payment\Model\Source\Invoice</source_model> - <depends> - <field id="order_status" separator=",">processing</field> - </depends> - </field> - <field id="sort_order" translate="label" type="text" sortOrder="100" showInDefault="1" showInWebsite="1" showInStore="0" canRestore="1"> - <label>Sort Order</label> - <frontend_class>validate-number</frontend_class> - </field> - <field id="title" translate="label" type="text" sortOrder="1" showInDefault="1" showInWebsite="1" showInStore="1" canRestore="1"> - <label>Title</label> - </field> - <field id="allowspecific" translate="label" type="allowspecific" sortOrder="50" showInDefault="1" showInWebsite="1" showInStore="0" canRestore="1"> - <label>Payment from Applicable Countries</label> - <source_model>Magento\Payment\Model\Config\Source\Allspecificcountries</source_model> - </field> - <field id="specificcountry" translate="label" type="multiselect" sortOrder="51" showInDefault="1" showInWebsite="1" showInStore="0"> - <label>Payment from Specific Countries</label> - <source_model>Magento\Directory\Model\Config\Source\Country</source_model> - <can_be_empty>1</can_be_empty> - </field> - <field id="model"></field> - </group> </section> </system> </config> diff --git a/app/code/Magento/Payment/etc/adminhtml/system.xml b/app/code/Magento/Payment/etc/adminhtml/system.xml index 3aa4ee53b30f1..d168dc13a397b 100644 --- a/app/code/Magento/Payment/etc/adminhtml/system.xml +++ b/app/code/Magento/Payment/etc/adminhtml/system.xml @@ -11,6 +11,41 @@ <label>Payment Methods</label> <tab>sales</tab> <resource>Magento_Payment::payment</resource> + <group id="free" translate="label" type="text" sortOrder="30" showInDefault="1" showInWebsite="1" showInStore="1"> + <label>Zero Subtotal Checkout</label> + <field id="active" translate="label" type="select" sortOrder="1" showInDefault="1" showInWebsite="1" showInStore="0" canRestore="1"> + <label>Enabled</label> + <source_model>Magento\Config\Model\Config\Source\Yesno</source_model> + </field> + <field id="order_status" translate="label" type="select" sortOrder="2" showInDefault="1" showInWebsite="1" showInStore="0" canRestore="1"> + <label>New Order Status</label> + <source_model>Magento\Sales\Model\Config\Source\Order\Status\Newprocessing</source_model> + </field> + <field id="payment_action" translate="label" type="select" sortOrder="3" showInDefault="1" showInWebsite="1" showInStore="0" canRestore="1"> + <label>Automatically Invoice All Items</label> + <source_model>Magento\Payment\Model\Source\Invoice</source_model> + <depends> + <field id="order_status" separator=",">processing</field> + </depends> + </field> + <field id="sort_order" translate="label" type="text" sortOrder="100" showInDefault="1" showInWebsite="1" showInStore="0" canRestore="1"> + <label>Sort Order</label> + <frontend_class>validate-number</frontend_class> + </field> + <field id="title" translate="label" type="text" sortOrder="1" showInDefault="1" showInWebsite="1" showInStore="1" canRestore="1"> + <label>Title</label> + </field> + <field id="allowspecific" translate="label" type="allowspecific" sortOrder="50" showInDefault="1" showInWebsite="1" showInStore="0" canRestore="1"> + <label>Payment from Applicable Countries</label> + <source_model>Magento\Payment\Model\Config\Source\Allspecificcountries</source_model> + </field> + <field id="specificcountry" translate="label" type="multiselect" sortOrder="51" showInDefault="1" showInWebsite="1" showInStore="0"> + <label>Payment from Specific Countries</label> + <source_model>Magento\Directory\Model\Config\Source\Country</source_model> + <can_be_empty>1</can_be_empty> + </field> + <field id="model"></field> + </group> </section> </system> </config> From 0773987e3074c9b4a121b8a3eddd9bac721922b5 Mon Sep 17 00:00:00 2001 From: Eden <quocviet312@gmail.com> Date: Fri, 12 Jul 2019 22:29:32 +0700 Subject: [PATCH 679/773] Resolve Frontend Label For Custom Order Status not Editable in Magento Admin in Single Store Mode #23654 --- .../Adminhtml/Order/Status/NewStatus/Form.php | 33 +++++++++++++++---- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/app/code/Magento/Sales/Block/Adminhtml/Order/Status/NewStatus/Form.php b/app/code/Magento/Sales/Block/Adminhtml/Order/Status/NewStatus/Form.php index 363c8cb22f25a..c4d8907c9762b 100644 --- a/app/code/Magento/Sales/Block/Adminhtml/Order/Status/NewStatus/Form.php +++ b/app/code/Magento/Sales/Block/Adminhtml/Order/Status/NewStatus/Form.php @@ -56,9 +56,7 @@ protected function _prepareForm() ['name' => 'label', 'label' => __('Status Label'), 'class' => 'required-entry', 'required' => true] ); - if (!$this->_storeManager->isSingleStoreMode()) { - $this->_addStoresFieldset($model, $form); - } + $this->_addStoresFieldset($model, $form); if ($model) { $form->addValues($model->getData()); @@ -80,10 +78,31 @@ protected function _prepareForm() protected function _addStoresFieldset($model, $form) { $labels = $model ? $model->getStoreLabels() : []; - $fieldset = $form->addFieldset( - 'store_labels_fieldset', - ['legend' => __('Store View Specific Labels'), 'class' => 'store-scope'] - ); + if (!$this->_storeManager->isSingleStoreMode()) { + $fieldset = $form->addFieldset( + 'store_labels_fieldset', + ['legend' => __('Store View Specific Labels'), 'class' => 'store-scope'] + ); + } else { + $fieldset = $form->addFieldset( + 'store_labels_fieldset', + ['legend' => __('Frontend Label')] + ); + $store = $this->_storeManager->getDefaultStoreView(); + $fieldset->addField( + "store_label_{$store->getId()}", + 'text', + [ + 'name' => 'store_labels[' . $store->getId() . ']', + 'required' => false, + 'label' => $store->getName(), + 'value' => isset($labels[$store->getId()]) ? $labels[$store->getId()] : '', + 'fieldset_html_class' => 'store' + ] + ); + return ; + } + $renderer = $this->getLayout()->createBlock( \Magento\Backend\Block\Store\Switcher\Form\Renderer\Fieldset::class ); From ca0fe6ef8671a003d57dd8753a539f74faeb0542 Mon Sep 17 00:00:00 2001 From: Mastiuhin Olexandr <mastiuhin.olexandr@transoftgroup.com> Date: Fri, 12 Jul 2019 21:42:32 +0300 Subject: [PATCH 680/773] MC-17524: Child product is not addable to Cart from PLP if it does not have default source assigned --- .../GroupedCatalogInventory/Plugin/OutOfStockFilter.php | 5 ++--- .../Test/Unit/Plugin/OutOfStockFilterTest.php | 1 - 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/GroupedCatalogInventory/Plugin/OutOfStockFilter.php b/app/code/Magento/GroupedCatalogInventory/Plugin/OutOfStockFilter.php index c8c40042f5034..c39a332ee3022 100644 --- a/app/code/Magento/GroupedCatalogInventory/Plugin/OutOfStockFilter.php +++ b/app/code/Magento/GroupedCatalogInventory/Plugin/OutOfStockFilter.php @@ -50,9 +50,8 @@ public function afterPrepareForCartAdvanced(Grouped $subject, $result, DataObjec // Only remove out-of-stock products if no quantities were specified if (is_array($result) && !empty($result) && !$buyRequest->getData('super_group')) { foreach ($result as $index => $cartItem) { - $prodId = $cartItem->getId(); - $productStockStatus = $this->stockRegistry->getProductStockStatus($prodId); - if ($productStockStatus == StockStatusInterface::STATUS_OUT_OF_STOCK) { + $productStockStatus = $this->stockRegistry->getProductStockStatus($cartItem->getId()); + if ($productStockStatus === StockStatusInterface::STATUS_OUT_OF_STOCK) { unset($result[$index]); } } diff --git a/app/code/Magento/GroupedCatalogInventory/Test/Unit/Plugin/OutOfStockFilterTest.php b/app/code/Magento/GroupedCatalogInventory/Test/Unit/Plugin/OutOfStockFilterTest.php index 2ea1db594ccbd..1d685defb3e40 100644 --- a/app/code/Magento/GroupedCatalogInventory/Test/Unit/Plugin/OutOfStockFilterTest.php +++ b/app/code/Magento/GroupedCatalogInventory/Test/Unit/Plugin/OutOfStockFilterTest.php @@ -16,7 +16,6 @@ use Magento\GroupedProduct\Model\Product\Type\Grouped; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; - use Magento\CatalogInventory\Api\StockRegistryInterface; /** From 8194cf9a60431cf515b7d8d3ad179f0907ab3672 Mon Sep 17 00:00:00 2001 From: Denis Kopylov <dkopylov@magenius.team> Date: Fri, 12 Jul 2019 21:49:11 +0300 Subject: [PATCH 681/773] [Unit] Fix broken unit tests --- .../Unit/Model/Payflow/TransparentTest.php | 4 +- .../ResourceModel/Product/Collection.php | 13 ++-- .../ResourceModel/Product/CollectionTest.php | 71 ++++++++++++------- .../Test/Unit/Model/Method/VaultTest.php | 57 ++++++++++----- .../Dependency/Route/RouteMapper.php | 15 ++-- .../Magento/Framework/App/Utility/Files.php | 36 ++++++---- 6 files changed, 126 insertions(+), 70 deletions(-) diff --git a/app/code/Magento/Paypal/Test/Unit/Model/Payflow/TransparentTest.php b/app/code/Magento/Paypal/Test/Unit/Model/Payflow/TransparentTest.php index f6df35ae272b7..9587600203561 100644 --- a/app/code/Magento/Paypal/Test/Unit/Model/Payflow/TransparentTest.php +++ b/app/code/Magento/Paypal/Test/Unit/Model/Payflow/TransparentTest.php @@ -29,6 +29,8 @@ use PHPUnit_Framework_MockObject_MockObject as MockObject; /** + * Paypal transparent test class + * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class TransparentTest extends \PHPUnit\Framework\TestCase @@ -194,7 +196,7 @@ private function getPaymentExtensionInterfaceFactory() ->disableOriginalConstructor() ->getMock(); $orderPaymentExtension = $this->getMockBuilder(OrderPaymentExtensionInterface::class) - ->setMethods(['setVaultPaymentToken']) + ->setMethods(['setVaultPaymentToken', 'getVaultPaymentToken']) ->disableOriginalConstructor() ->getMock(); diff --git a/app/code/Magento/Reports/Model/ResourceModel/Product/Collection.php b/app/code/Magento/Reports/Model/ResourceModel/Product/Collection.php index d81f6c6f362dc..aa41759baac68 100644 --- a/app/code/Magento/Reports/Model/ResourceModel/Product/Collection.php +++ b/app/code/Magento/Reports/Model/ResourceModel/Product/Collection.php @@ -3,12 +3,12 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); -/** - * @author Magento Core Team <core@magentocommerce.com> - */ namespace Magento\Reports\Model\ResourceModel\Product; +use Magento\Catalog\Model\ResourceModel\Product\Collection\ProductLimitationFactory; + /** * Products Report collection. * @@ -90,6 +90,7 @@ class Collection extends \Magento\Catalog\Model\ResourceModel\Product\Collection * @param \Magento\Catalog\Model\Product\Type $productType * @param \Magento\Quote\Model\ResourceModel\Quote\Collection $quoteResource * @param \Magento\Framework\DB\Adapter\AdapterInterface|null $connection + * @param ProductLimitationFactory|null $productLimitationFactory * * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -117,7 +118,8 @@ public function __construct( \Magento\Reports\Model\Event\TypeFactory $eventTypeFactory, \Magento\Catalog\Model\Product\Type $productType, \Magento\Quote\Model\ResourceModel\Quote\Collection $quoteResource, - \Magento\Framework\DB\Adapter\AdapterInterface $connection = null + \Magento\Framework\DB\Adapter\AdapterInterface $connection = null, + ProductLimitationFactory $productLimitationFactory = null ) { $this->setProductEntityId($product->getEntityIdField()); $this->setProductEntityTableName($product->getEntityTable()); @@ -142,7 +144,8 @@ public function __construct( $customerSession, $dateTime, $groupManagement, - $connection + $connection, + $productLimitationFactory ); $this->_eventTypeFactory = $eventTypeFactory; $this->_productType = $productType; diff --git a/app/code/Magento/Reports/Test/Unit/Model/ResourceModel/Product/CollectionTest.php b/app/code/Magento/Reports/Test/Unit/Model/ResourceModel/Product/CollectionTest.php index c8a16c2476824..3f1857b352dbc 100644 --- a/app/code/Magento/Reports/Test/Unit/Model/ResourceModel/Product/CollectionTest.php +++ b/app/code/Magento/Reports/Test/Unit/Model/ResourceModel/Product/CollectionTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); namespace Magento\Reports\Test\Unit\Model\ResourceModel\Product; @@ -12,6 +13,8 @@ use Magento\Catalog\Model\Product\Type as ProductType; use Magento\Catalog\Model\ResourceModel\Helper; use Magento\Catalog\Model\ResourceModel\Product as ResourceProduct; +use Magento\Catalog\Model\ResourceModel\Product\Collection\ProductLimitation; +use Magento\Catalog\Model\ResourceModel\Product\Collection\ProductLimitationFactory; use Magento\Catalog\Model\ResourceModel\Url; use Magento\Customer\Api\GroupManagementInterface; use Magento\Customer\Model\Session; @@ -75,6 +78,11 @@ class CollectionTest extends \PHPUnit\Framework\TestCase */ private $selectMock; + /** + * SetUp method + * + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + */ protected function setUp() { $this->objectManager = new ObjectManager($this); @@ -138,31 +146,44 @@ protected function setUp() $this->resourceMock->expects($this->atLeastOnce())->method('getConnection')->willReturn($this->connectionMock); $this->connectionMock->expects($this->atLeastOnce())->method('select')->willReturn($this->selectMock); - $this->collection = new ProductCollection( - $entityFactoryMock, - $loggerMock, - $fetchStrategyMock, - $eventManagerMock, - $eavConfigMock, - $this->resourceMock, - $eavEntityFactoryMock, - $resourceHelperMock, - $universalFactoryMock, - $storeManagerMock, - $moduleManagerMock, - $productFlatStateMock, - $scopeConfigMock, - $optionFactoryMock, - $catalogUrlMock, - $localeDateMock, - $customerSessionMock, - $dateTimeMock, - $groupManagementMock, - $productMock, - $this->eventTypeFactoryMock, - $productTypeMock, - $quoteResourceMock, - $this->connectionMock + $productLimitationFactoryMock = $this->createPartialMock( + ProductLimitationFactory::class, + ['create'] + ); + $productLimitation = $this->createMock(ProductLimitation::class); + $productLimitationFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($productLimitation); + + $this->collection = $this->objectManager->getObject( + ProductCollection::class, + [ + 'entityFactory' => $entityFactoryMock, + 'logger' => $loggerMock, + 'fetchStrategy' => $fetchStrategyMock, + 'eventManager' => $eventManagerMock, + 'eavConfig' => $eavConfigMock, + 'resource' => $this->resourceMock, + 'eavEntityFactory' => $eavEntityFactoryMock, + 'resourceHelper' => $resourceHelperMock, + 'universalFactory' => $universalFactoryMock, + 'storeManager' => $storeManagerMock, + 'moduleManager' => $moduleManagerMock, + 'catalogProductFlatState' => $productFlatStateMock, + 'scopeConfig' => $scopeConfigMock, + 'productOptionFactory' => $optionFactoryMock, + 'catalogUrl' => $catalogUrlMock, + 'localeDate' => $localeDateMock, + 'customerSession' => $customerSessionMock, + 'dateTime' => $dateTimeMock, + 'groupManagement' => $groupManagementMock, + 'product' => $productMock, + 'eventTypeFactory' => $this->eventTypeFactoryMock, + 'productType' => $productTypeMock, + 'quoteResource' => $quoteResourceMock, + 'connection' => $this->connectionMock, + 'productLimitationFactory' => $productLimitationFactoryMock + ] ); } diff --git a/app/code/Magento/Vault/Test/Unit/Model/Method/VaultTest.php b/app/code/Magento/Vault/Test/Unit/Model/Method/VaultTest.php index 00ec485b15692..7e3f9b67a58ec 100644 --- a/app/code/Magento/Vault/Test/Unit/Model/Method/VaultTest.php +++ b/app/code/Magento/Vault/Test/Unit/Model/Method/VaultTest.php @@ -3,6 +3,8 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Vault\Test\Unit\Model\Method; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; @@ -25,6 +27,7 @@ /** * Class VaultTest + * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class VaultTest extends \PHPUnit\Framework\TestCase @@ -140,7 +143,7 @@ public function testAuthorize() ->disableOriginalConstructor() ->getMock(); $extensionAttributes = $this->getMockBuilder(OrderPaymentExtensionInterface::class) - ->setMethods(['setVaultPaymentToken']) + ->setMethods(['setVaultPaymentToken', 'getVaultPaymentToken']) ->getMockForAbstractClass(); $commandManagerPool = $this->createMock(CommandManagerPoolInterface::class); @@ -235,7 +238,7 @@ public function testCapture() } /** - * @covers \Magento\Vault\Model\Method\Vault::isAvailable + * @covers \Magento\Vault\Model\Method\Vault::isAvailable * @dataProvider isAvailableDataProvider */ public function testIsAvailable($isAvailableProvider, $isActive, $expected) @@ -251,7 +254,10 @@ public function testIsAvailable($isAvailableProvider, $isActive, $expected) $config->expects(static::any()) ->method('getValue') - ->with('active', $storeId) + ->with( + 'active', + $storeId + ) ->willReturn($isActive); $quote->expects(static::any()) @@ -259,10 +265,13 @@ public function testIsAvailable($isAvailableProvider, $isActive, $expected) ->willReturn($storeId); /** @var Vault $model */ - $model = $this->objectManager->getObject(Vault::class, [ - 'config' => $config, - 'vaultProvider' => $this->vaultProvider - ]); + $model = $this->objectManager->getObject( + Vault::class, + [ + 'config' => $config, + 'vaultProvider' => $this->vaultProvider + ] + ); $actual = $model->isAvailable($quote); static::assertEquals($expected, $actual); } @@ -296,19 +305,25 @@ public function testIsAvailableWithoutQuote() $config->expects(static::once()) ->method('getValue') - ->with('active', $quote) + ->with( + 'active', + $quote + ) ->willReturn(false); /** @var Vault $model */ - $model = $this->objectManager->getObject(Vault::class, [ - 'config' => $config, - 'vaultProvider' => $this->vaultProvider - ]); + $model = $this->objectManager->getObject( + Vault::class, + [ + 'config' => $config, + 'vaultProvider' => $this->vaultProvider + ] + ); static::assertFalse($model->isAvailable($quote)); } /** - * @covers \Magento\Vault\Model\Method\Vault::canUseInternal + * @covers \Magento\Vault\Model\Method\Vault::canUseInternal * @param bool|null $configValue * @param bool|null $paymentValue * @param bool $expected @@ -326,7 +341,10 @@ public function testCanUseInternal($configValue, $paymentValue, $expected) $handler->expects(static::once()) ->method('handle') - ->with(['field' => 'can_use_internal'], null) + ->with( + ['field' => 'can_use_internal'], + null + ) ->willReturn($configValue); $this->vaultProvider->expects(static::any()) @@ -334,10 +352,13 @@ public function testCanUseInternal($configValue, $paymentValue, $expected) ->willReturn($paymentValue); /** @var Vault $model */ - $model = $this->objectManager->getObject(Vault::class, [ - 'vaultProvider' => $this->vaultProvider, - 'valueHandlerPool' => $handlerPool, - ]); + $model = $this->objectManager->getObject( + Vault::class, + [ + 'vaultProvider' => $this->vaultProvider, + 'valueHandlerPool' => $handlerPool, + ] + ); static::assertEquals($expected, $model->canUseInternal()); } diff --git a/dev/tests/static/framework/Magento/TestFramework/Dependency/Route/RouteMapper.php b/dev/tests/static/framework/Magento/TestFramework/Dependency/Route/RouteMapper.php index a3e5b6927e72a..87cc0985a053b 100644 --- a/dev/tests/static/framework/Magento/TestFramework/Dependency/Route/RouteMapper.php +++ b/dev/tests/static/framework/Magento/TestFramework/Dependency/Route/RouteMapper.php @@ -9,6 +9,7 @@ use Magento\Framework\App\Area; use Magento\Framework\App\Utility\Files; +use Magento\Framework\Component\ComponentFile; use Magento\TestFramework\Exception\NoSuchActionException; /** @@ -231,7 +232,7 @@ private function processConfigFile(string $module, string $configFile) // Read module's routes.xml file $config = simplexml_load_file($configFile); - $routers = $config->xpath("/config/router"); + $routers = $config->xpath("/config/router"); foreach ($routers as $router) { $routerId = (string)$router['id']; foreach ($router->xpath('route') as $route) { @@ -254,13 +255,11 @@ private function processConfigFile(string $module, string $configFile) private function getListRoutesXml() { if (empty($this->routeConfigFiles)) { - $files = Files::init()->getConfigFiles('*/routes.xml', [], false); - $pattern = '/(?<namespace>[A-Z][a-z]+)[_\/\\\\](?<module>[A-Z][a-zA-Z]+)/'; - foreach ($files as $file) { - if (preg_match($pattern, $file, $matches)) { - $module = $matches['namespace'] . '\\' . $matches['module']; - $this->routeConfigFiles[$module][] = $file; - } + $files = Files::init()->getConfigFiles('*/routes.xml', [], false, true); + /** @var ComponentFile $componentFile */ + foreach ($files as $componentFile) { + $module = str_replace('_', '\\', $componentFile->getComponentName()); + $this->routeConfigFiles[$module][] = $componentFile->getFullPath(); } } return $this->routeConfigFiles; diff --git a/lib/internal/Magento/Framework/App/Utility/Files.php b/lib/internal/Magento/Framework/App/Utility/Files.php index 8bb59bb42ff49..3460faf854bac 100644 --- a/lib/internal/Magento/Framework/App/Utility/Files.php +++ b/lib/internal/Magento/Framework/App/Utility/Files.php @@ -3,15 +3,18 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\App\Utility; use Magento\Framework\App\ObjectManager; +use Magento\Framework\Component\ComponentFile; use Magento\Framework\Component\ComponentRegistrar; use Magento\Framework\Component\DirSearch; +use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\Filesystem\Glob; use Magento\Framework\Serialize\Serializer\Json; use Magento\Framework\View\Design\Theme\ThemePackage; use Magento\Framework\View\Design\Theme\ThemePackageList; -use Magento\Framework\Filesystem\Glob; /** * A helper to gather specific kind of files in Magento application. @@ -143,13 +146,13 @@ public static function setInstance(Files $instance = null) * Getter for an instance of self * * @return \Magento\Framework\App\Utility\Files - * @throws \Exception when there is no instance set + * @throws LocalizedException when there is no instance set */ public static function init() { if (!self::$_instance) { // phpcs:ignore Magento2.Exceptions.DirectThrow.FoundDirectThrow - throw new \Exception('Instance is not set yet.'); + throw new LocalizedException(__('Instance is not set yet.')); } return self::$_instance; } @@ -410,21 +413,25 @@ public function getMainConfigFiles($asDataSet = true) * @param string $fileNamePattern * @param array $excludedFileNames * @param bool $asDataSet + * @param bool $collectWithContext * @return array * @codingStandardsIgnoreStart */ public function getConfigFiles( $fileNamePattern = '*.xml', $excludedFileNames = ['wsdl.xml', 'wsdl2.xml', 'wsi.xml'], - $asDataSet = true + $asDataSet = true, + $collectWithContext = false ) { $cacheKey = __METHOD__ . '|' . $this->serializer->serialize([$fileNamePattern, $excludedFileNames, $asDataSet]); if (!isset(self::$_cache[$cacheKey])) { - $files = $this->dirSearch->collectFiles(ComponentRegistrar::MODULE, "/etc/{$fileNamePattern}"); + $method = $collectWithContext ? 'collectFilesWithContext' : 'collectFiles'; + $files = $this->dirSearch->{$method}(ComponentRegistrar::MODULE, "/etc/{$fileNamePattern}"); $files = array_filter( $files, - function ($file) use ($excludedFileNames) { - return !in_array(basename($file), $excludedFileNames); + function ($file) use ($excludedFileNames, $collectWithContext) { + /** @var ComponentFile $file */ + return !in_array(basename($collectWithContext ? $file->getFullPath() : $file), $excludedFileNames); } ); self::$_cache[$cacheKey] = $files; @@ -615,8 +622,7 @@ protected function getLayoutXmlFiles($location, $incomingParams = [], $asDataSet $params[$key] = $incomingParams[$key]; } } - //phpcs:ignore Magento2.Security.InsecureFunction - $cacheKey = md5($location . '|' . implode('|', $params)); + $cacheKey = hash('sha256', $location . '|' . implode('|', $params)); if (!isset(self::$_cache[__METHOD__][$cacheKey])) { $files = []; @@ -769,8 +775,7 @@ public function getPageTypeFiles($incomingParams = [], $asDataSet = true) $params[$key] = $incomingParams[$key]; } } - //phpcs:ignore Magento2.Security.InsecureFunction - $cacheKey = md5(implode('|', $params)); + $cacheKey = hash('sha256', implode('|', $params)); if (!isset(self::$_cache[__METHOD__][$cacheKey])) { self::$_cache[__METHOD__][$cacheKey] = self::getFiles( @@ -1506,7 +1511,7 @@ public function getNamespaces() public function getModuleFile($namespace, $module, $file) { return $this->componentRegistrar->getPath(ComponentRegistrar::MODULE, $namespace . '_' . $module) . - '/' . $file; + '/' . $file; } /** @@ -1607,7 +1612,12 @@ public function readLists($globPattern) $result = array_merge($result, $files); } if (!empty($incorrectPatterns)) { - throw new \Exception("The following patterns didn't return any result:\n" . join("\n", $incorrectPatterns)); + throw new LocalizedException( + __( + "The following patterns didn't return any result:\n%1", + join("\n", $incorrectPatterns) + ) + ); } return $result; } From f23fc69644519d5c0fc1d370f0abca5baf1586bd Mon Sep 17 00:00:00 2001 From: Volodymyr Zaets <vzaets@magento.com> Date: Fri, 12 Jul 2019 14:42:34 -0500 Subject: [PATCH 682/773] Add suppress warning couplingBetweenObjects --- .../CustomerGraphQl/Model/Customer/UpdateCustomerAccount.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/code/Magento/CustomerGraphQl/Model/Customer/UpdateCustomerAccount.php b/app/code/Magento/CustomerGraphQl/Model/Customer/UpdateCustomerAccount.php index 161471c86a561..51d47eaf0d048 100644 --- a/app/code/Magento/CustomerGraphQl/Model/Customer/UpdateCustomerAccount.php +++ b/app/code/Magento/CustomerGraphQl/Model/Customer/UpdateCustomerAccount.php @@ -16,6 +16,8 @@ /** * Update customer account data + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) - https://jira.corp.magento.com/browse/MC-18152 */ class UpdateCustomerAccount { From 9772075c23c5bf463e4fdc7c47f28b67535ac0a8 Mon Sep 17 00:00:00 2001 From: Eden <quocviet312@gmail.com> Date: Sat, 13 Jul 2019 16:56:43 +0700 Subject: [PATCH 683/773] Resolve "Automatically Invoice All Items" is "Yes" but no invoice is created (Zero Subtotal Checkout) --- app/code/Magento/OfflinePayments/etc/config.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/OfflinePayments/etc/config.xml b/app/code/Magento/OfflinePayments/etc/config.xml index 9e126bafbb459..94a0a45f00ef7 100644 --- a/app/code/Magento/OfflinePayments/etc/config.xml +++ b/app/code/Magento/OfflinePayments/etc/config.xml @@ -42,6 +42,7 @@ </cashondelivery> <free> <group>offline</group> + <payment_action>authorize_capture</payment_action> </free> </payment> </default> From 91c7bfa25bbc38e4838f0f398181bccfa434863c Mon Sep 17 00:00:00 2001 From: "rostyslav.hymon" <rostyslav.hymon@transoftgroup.com> Date: Mon, 15 Jul 2019 09:26:45 +0300 Subject: [PATCH 684/773] MC-17984: Authorize.net cannot place order from admin panel --- .../view/adminhtml/templates/payment/script.phtml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/code/Magento/AuthorizenetAcceptjs/view/adminhtml/templates/payment/script.phtml b/app/code/Magento/AuthorizenetAcceptjs/view/adminhtml/templates/payment/script.phtml index 60090e2c9752a..6be6008dba507 100644 --- a/app/code/Magento/AuthorizenetAcceptjs/view/adminhtml/templates/payment/script.phtml +++ b/app/code/Magento/AuthorizenetAcceptjs/view/adminhtml/templates/payment/script.phtml @@ -15,11 +15,10 @@ 'domReady!' ], function(AuthorizenetAcceptjs, $) { var config = <?= /* @noEscape */ $block->getPaymentConfig() ?>, - payment, form = $('#payment_form_<?= /* @noEscape */ $block->escapeJs($block->escapeHtml($block->getMethodCode())) ?>'); config.active = form.length > 0 && !form.is(':hidden'); - payment = new AuthorizenetAcceptjs(config); + new AuthorizenetAcceptjs(config); }); //]]> </script> From aa3cef4041ed90cf032390e855e2388197bb3d0d Mon Sep 17 00:00:00 2001 From: Soumya Unnikrishnan <sunnikri@adobe.com> Date: Mon, 15 Jul 2019 16:11:41 +0530 Subject: [PATCH 685/773] MC-4555: Convert UpdateCustomerCustomAttributesEntityTest to MFTF Fixed locators --- .../Mftf/Section/CheckoutPaymentSection.xml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutPaymentSection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutPaymentSection.xml index aac20e7ec4af1..903c21d7ec0ca 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutPaymentSection.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutPaymentSection.xml @@ -16,15 +16,15 @@ <element name="billingAddressNotSameCheckbox" type="checkbox" selector="#billing-address-same-as-shipping-checkmo"/> <element name="editAddress" type="button" selector="button.action.action-edit-address"/> <element name="placeOrderDisabled" type="button" selector="#checkout-payment-method-load button.disabled"/> - <element name="update" type="button" selector=".payment-method-billing-address .action.action-update"/> - <element name="guestFirstName" type="input" selector=".billing-address-form input[name*='firstname']"/> - <element name="guestLastName" type="input" selector=".billing-address-form input[name*='lastname']"/> - <element name="guestStreet" type="input" selector=".billing-address-form input[name*='street[0]']"/> - <element name="guestCity" type="input" selector=".billing-address-form input[name*='city']"/> - <element name="guestCountry" type="select" selector=".billing-address-form select[name*='country_id']"/> - <element name="guestRegion" type="select" selector=".billing-address-form select[name*='region_id']"/> - <element name="guestPostcode" type="input" selector=".billing-address-form input[name*='postcode']"/> - <element name="guestTelephone" type="input" selector=".billing-address-form input[name*='telephone']"/> + <element name="update" type="button" selector=".payment-method._active .payment-method-billing-address .action.action-update"/> + <element name="guestFirstName" type="input" selector=".payment-method._active .billing-address-form input[name='firstname']"/> + <element name="guestLastName" type="input" selector=".payment-method._active .billing-address-form input[name*='lastname']"/> + <element name="guestStreet" type="input" selector=".payment-method._active .billing-address-form input[name*='street[0]']"/> + <element name="guestCity" type="input" selector=".payment-method._active .billing-address-form input[name*='city']"/> + <element name="guestCountry" type="select" selector=".payment-method._active .billing-address-form select[name*='country_id']"/> + <element name="guestRegion" type="select" selector=".payment-method._active .billing-address-form select[name*='region_id']"/> + <element name="guestPostcode" type="input" selector=".payment-method._active .billing-address-form input[name*='postcode']"/> + <element name="guestTelephone" type="input" selector=".payment-method._active .billing-address-form input[name*='telephone']"/> <element name="billingAddress" type="text" selector=".payment-method._active div.billing-address-details"/> <element name="cartItems" type="text" selector="ol.minicart-items"/> <element name="cartItemsArea" type="button" selector="div.block.items-in-cart"/> From d91a3c9807b5773b8957cb566d5f92aeebe80be8 Mon Sep 17 00:00:00 2001 From: Quentin Farizon <quentin.farizon@afrimarketgroup.com> Date: Tue, 4 Jun 2019 17:29:49 +0200 Subject: [PATCH 686/773] Catch throwables in mview updating --- lib/internal/Magento/Framework/Mview/View.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/Mview/View.php b/lib/internal/Magento/Framework/Mview/View.php index fa1bfa0d38c6f..f00d59b764929 100644 --- a/lib/internal/Magento/Framework/Mview/View.php +++ b/lib/internal/Magento/Framework/Mview/View.php @@ -277,12 +277,19 @@ public function update() ? View\StateInterface::STATUS_SUSPENDED : View\StateInterface::STATUS_IDLE; $this->getState()->setVersionId($currentVersionId)->setStatus($statusToRestore)->save(); - } catch (Exception $exception) { + } catch (\Throwable $exception) { $this->getState()->loadByView($this->getId()); $statusToRestore = $this->getState()->getStatus() === View\StateInterface::STATUS_SUSPENDED ? View\StateInterface::STATUS_SUSPENDED : View\StateInterface::STATUS_IDLE; $this->getState()->setStatus($statusToRestore)->save(); + if (!$exception instanceof \Exception) { + $exception = new \RuntimeException( + 'Error when updating an mview', + 0, + $exception + ); + } throw $exception; } } From ba4dff7dcb8caee9aa0e07ba0575940201d24715 Mon Sep 17 00:00:00 2001 From: Quentin Farizon <quentin.farizon@afrimarketgroup.com> Date: Tue, 4 Jun 2019 18:27:27 +0200 Subject: [PATCH 687/773] Refactor View::update --- lib/internal/Magento/Framework/Mview/View.php | 50 ++++++++++++------- 1 file changed, 33 insertions(+), 17 deletions(-) diff --git a/lib/internal/Magento/Framework/Mview/View.php b/lib/internal/Magento/Framework/Mview/View.php index f00d59b764929..e6f2d9fe03996 100644 --- a/lib/internal/Magento/Framework/Mview/View.php +++ b/lib/internal/Magento/Framework/Mview/View.php @@ -4,6 +4,8 @@ * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Framework\Mview; use InvalidArgumentException; @@ -254,23 +256,7 @@ public function update() try { $this->getState()->setStatus(View\StateInterface::STATUS_WORKING)->save(); - $versionBatchSize = self::$maxVersionQueryBatch; - $batchSize = isset($this->changelogBatchSize[$this->getChangelog()->getViewId()]) - ? $this->changelogBatchSize[$this->getChangelog()->getViewId()] - : self::DEFAULT_BATCH_SIZE; - - for ($vsFrom = $lastVersionId; $vsFrom < $currentVersionId; $vsFrom += $versionBatchSize) { - // Don't go past the current version for atomicy. - $versionTo = min($currentVersionId, $vsFrom + $versionBatchSize); - $ids = $this->getChangelog()->getList($vsFrom, $versionTo); - - // We run the actual indexer in batches. - // Chunked AFTER loading to avoid duplicates in separate chunks. - $chunks = array_chunk($ids, $batchSize); - foreach ($chunks as $ids) { - $action->execute($ids); - } - } + $this->executeAction($action, $lastVersionId, $currentVersionId); $this->getState()->loadByView($this->getId()); $statusToRestore = $this->getState()->getStatus() === View\StateInterface::STATUS_SUSPENDED @@ -294,6 +280,36 @@ public function update() } } + /** + * Execute action from last version to current version, by batches + * + * @param ActionInterface $action + * @param int $lastVersionId + * @param int $currentVersionId + * @return void + * @throws \Exception + */ + private function executeAction(ActionInterface $action, int $lastVersionId, int $currentVersionId) + { + $versionBatchSize = self::$maxVersionQueryBatch; + $batchSize = isset($this->changelogBatchSize[$this->getChangelog()->getViewId()]) + ? $this->changelogBatchSize[$this->getChangelog()->getViewId()] + : self::DEFAULT_BATCH_SIZE; + + for ($vsFrom = $lastVersionId; $vsFrom < $currentVersionId; $vsFrom += $versionBatchSize) { + // Don't go past the current version for atomicity. + $versionTo = min($currentVersionId, $vsFrom + $versionBatchSize); + $ids = $this->getChangelog()->getList($vsFrom, $versionTo); + + // We run the actual indexer in batches. + // Chunked AFTER loading to avoid duplicates in separate chunks. + $chunks = array_chunk($ids, $batchSize); + foreach ($chunks as $ids) { + $action->execute($ids); + } + } + } + /** * Suspend view updates and set version ID to changelog's end * From f69830c525fdc842ae0521b15ad972715f6aa8a9 Mon Sep 17 00:00:00 2001 From: Krissy Hiserote <khiserote@magento.com> Date: Mon, 15 Jul 2019 11:08:30 -0500 Subject: [PATCH 688/773] MC-15776: Merge release branch into 2.3-develop - fix integration tests --- .../testsuite/Magento/Customer/Model/CustomerMetadataTest.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/CustomerMetadataTest.php b/dev/tests/integration/testsuite/Magento/Customer/Model/CustomerMetadataTest.php index a5c69bcd3239e..a02f6f76e64d8 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Model/CustomerMetadataTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Model/CustomerMetadataTest.php @@ -70,6 +70,9 @@ public function testGetCustomAttributesMetadata() ); } + /** + * @magentoAppIsolation enabled + */ public function testGetNestedOptionsCustomerAttributesMetadata() { $nestedOptionsAttribute = 'store_id'; From 85e5375ad2e45eebeb5667b3f5e9a91e16989213 Mon Sep 17 00:00:00 2001 From: Graham Wharton <graham@gwharton.me.uk> Date: Mon, 15 Jul 2019 18:44:23 +0100 Subject: [PATCH 689/773] Removed Default value options for Media Storage Location. Added additional comment reminding of need to save settings following synchronization of storage. --- app/code/Magento/MediaStorage/etc/adminhtml/system.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/MediaStorage/etc/adminhtml/system.xml b/app/code/Magento/MediaStorage/etc/adminhtml/system.xml index d7244a5d4fd01..d29ed43002f08 100644 --- a/app/code/Magento/MediaStorage/etc/adminhtml/system.xml +++ b/app/code/Magento/MediaStorage/etc/adminhtml/system.xml @@ -10,11 +10,11 @@ <section id="system" type="text" sortOrder="900" showInDefault="1" showInWebsite="1" showInStore="1"> <group id="media_storage_configuration" translate="label" type="text" sortOrder="900" showInDefault="1" showInWebsite="1" showInStore="1"> <label>Storage Configuration for Media</label> - <field id="media_storage" translate="label" type="select" sortOrder="100" showInDefault="1" showInWebsite="0" showInStore="0" canRestore="1"> + <field id="media_storage" translate="label" type="select" sortOrder="100" showInDefault="1" showInWebsite="0" showInStore="0"> <label>Media Storage</label> <source_model>Magento\MediaStorage\Model\Config\Source\Storage\Media\Storage</source_model> </field> - <field id="media_database" translate="label" type="select" sortOrder="200" showInDefault="1" showInWebsite="0" showInStore="0" canRestore="1"> + <field id="media_database" translate="label" type="select" sortOrder="200" showInDefault="1" showInWebsite="0" showInStore="0"> <label>Select Media Database</label> <source_model>Magento\MediaStorage\Model\Config\Source\Storage\Media\Database</source_model> <backend_model>Magento\MediaStorage\Model\Config\Backend\Storage\Media\Database</backend_model> @@ -24,7 +24,7 @@ </field> <field id="synchronize" translate="label comment" type="button" sortOrder="300" showInDefault="1" showInWebsite="0" showInStore="0"> <frontend_model>Magento\MediaStorage\Block\System\Config\System\Storage\Media\Synchronize</frontend_model> - <comment>After selecting a new media storage location, press the Synchronize button to transfer all media to that location. Media will not be available in the new location until the synchronization process is complete.</comment> + <comment>After selecting a new media storage location, press the Synchronize button to transfer all media to that location. Media will not be available in the new location until the synchronization process is complete. Remember to "Save Config" following change of mode and synchronization.</comment> </field> <field id="configuration_update_time" translate="label" type="text" sortOrder="400" showInDefault="1" showInWebsite="0" showInStore="0" canRestore="1"> <label>Environment Update Time</label> From a97426185620893353474b0586f499322a07ae29 Mon Sep 17 00:00:00 2001 From: gwharton <30697781+gwharton@users.noreply.github.com> Date: Mon, 15 Jul 2019 18:58:57 +0100 Subject: [PATCH 690/773] Updated comment on Synchronization button --- app/code/Magento/MediaStorage/etc/adminhtml/system.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/MediaStorage/etc/adminhtml/system.xml b/app/code/Magento/MediaStorage/etc/adminhtml/system.xml index d29ed43002f08..0f6e7f93aea11 100644 --- a/app/code/Magento/MediaStorage/etc/adminhtml/system.xml +++ b/app/code/Magento/MediaStorage/etc/adminhtml/system.xml @@ -24,7 +24,7 @@ </field> <field id="synchronize" translate="label comment" type="button" sortOrder="300" showInDefault="1" showInWebsite="0" showInStore="0"> <frontend_model>Magento\MediaStorage\Block\System\Config\System\Storage\Media\Synchronize</frontend_model> - <comment>After selecting a new media storage location, press the Synchronize button to transfer all media to that location. Media will not be available in the new location until the synchronization process is complete. Remember to "Save Config" following change of mode and synchronization.</comment> + <comment>After selecting a new media storage location, press the Synchronize button to transfer all media to that location and then "Save Config". Media will not be available in the new location until the synchronization process is complete.</comment> </field> <field id="configuration_update_time" translate="label" type="text" sortOrder="400" showInDefault="1" showInWebsite="0" showInStore="0" canRestore="1"> <label>Environment Update Time</label> From eb5183519769cabf702a3d6dcd9e1aa7138d379f Mon Sep 17 00:00:00 2001 From: Viktor Tymchynskyi <vtymchynskyi@magento.com> Date: Mon, 15 Jul 2019 13:52:32 -0500 Subject: [PATCH 691/773] MAGETWO-99867: Braintree - 3D Secure 2.0 Support for 2.3 --- .../Braintree/view/frontend/web/js/view/payment/3d-secure.js | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Braintree/view/frontend/web/js/view/payment/3d-secure.js b/app/code/Magento/Braintree/view/frontend/web/js/view/payment/3d-secure.js index 354c697e2967b..43aec27508ce9 100644 --- a/app/code/Magento/Braintree/view/frontend/web/js/view/payment/3d-secure.js +++ b/app/code/Magento/Braintree/view/frontend/web/js/view/payment/3d-secure.js @@ -134,6 +134,7 @@ define([ } if (!this.isAmountAvailable(totalAmount) || !this.isCountryAvailable(billingAddress.countryId)) { + self.state = $.Deferred(); self.state.resolve(); return self.state.promise(); From 55f0cd98607efcc30aa7773642e1aaa7d3b39afb Mon Sep 17 00:00:00 2001 From: Roman Lytvynenko <lytvynen@adobe.com> Date: Mon, 15 Jul 2019 14:20:24 -0500 Subject: [PATCH 692/773] MC-17808: Custom customer attribute code showing on guest checkout --- .../address-renderer/default.html | 26 +++++++++---------- 1 file changed, 12 insertions(+), 14 deletions(-) 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 541413955cb47..75e061426d816 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 @@ -13,20 +13,18 @@ <a if="address().telephone" attr="'href': 'tel:' + address().telephone" text="address().telephone"></a><br/> <each args="data: address().customAttributes, as: 'element'"> - <each args="data: Object.keys(element), as: 'attribute'"> - <if args="typeof element[attribute] === 'object'"> - <if args="element[attribute].label"> - <text args="element[attribute].label"/> - </if> - <ifnot args="element[attribute].label"> - <if args="element[attribute].value"> - <text args="element[attribute].value"/> - </if> - </ifnot> + <if args="typeof element === 'object'"> + <if args="element.label"> + <text args="element.label"/> </if> - <if args="typeof element[attribute] === 'string'"> - <text args="element[attribute]"/> - </if><br/> - </each> + <ifnot args="element.label"> + <if args="element.value"> + <text args="element.value"/> + </if> + </ifnot> + </if> + <if args="typeof element === 'string'"> + <text args="element"/> + </if><br/> </each> </if> From 250e936fc783458b6b9ef54cfad55cdd4652fb8a Mon Sep 17 00:00:00 2001 From: Eden <quocviet312@gmail.com> Date: Tue, 16 Jul 2019 14:06:21 +0700 Subject: [PATCH 693/773] [Authorize.net accept.js] Resolve "Place Order" button not being disabled when edit billing address issue23624 --- .../frontend/web/template/payment/authorizenet-acceptjs.html | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/AuthorizenetAcceptjs/view/frontend/web/template/payment/authorizenet-acceptjs.html b/app/code/Magento/AuthorizenetAcceptjs/view/frontend/web/template/payment/authorizenet-acceptjs.html index 6db52a2b1025e..1e41c2b49adba 100644 --- a/app/code/Magento/AuthorizenetAcceptjs/view/frontend/web/template/payment/authorizenet-acceptjs.html +++ b/app/code/Magento/AuthorizenetAcceptjs/view/frontend/web/template/payment/authorizenet-acceptjs.html @@ -35,6 +35,7 @@ <button class="action primary checkout" type="submit" click="beforePlaceOrder" + css="disabled: !isPlaceOrderActionAllowed()" attr="title: $t('Place Order')" > <span translate="'Place Order'"></span> From 8c6875b47003df960179918b09fe90d40baf1ae4 Mon Sep 17 00:00:00 2001 From: Dmitriy Kogut <kogut.dmitriy@gmail.com> Date: Tue, 16 Jul 2019 12:12:14 +0300 Subject: [PATCH 694/773] MC-3483: Admin should be able to associate simple product to websites --- .../ActionGroup/AdminProductActionGroup.xml | 15 ++++ ...undErrorOnProductDetailPageActionGroup.xml | 19 +++++ ...ductPageUsingStoreCodeInUrlActionGroup.xml | 18 ++++ ...ToAssociateSimpleProductToWebsitesTest.xml | 83 +++++++++++++++++++ 4 files changed, 135 insertions(+) create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontAssertPageNotFoundErrorOnProductDetailPageActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontOpenProductPageUsingStoreCodeInUrlActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/Test/AdminShouldBeAbleToAssociateSimpleProductToWebsitesTest.xml diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductActionGroup.xml index c1cb69373b00e..83bb7841614d1 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductActionGroup.xml @@ -388,6 +388,14 @@ <waitForPageLoad stepKey="waitForSave"/> </actionGroup> + <!-- Action group assign to one website and unassign from another --> + <actionGroup name="AdminProcessProductWebsitesActionGroup" extends="CreatedProductConnectToWebsite"> + <arguments> + <argument name="websiteToUnassign"/> + </arguments> + <uncheckOption selector="{{ProductInWebsitesSection.website(websiteToUnassign.name)}}" after="SelectWebsite" stepKey="uncheckWebsite"/> + </actionGroup> + <!--Check tier price with a discount percentage on product--> <actionGroup name="AssertDiscountsPercentageOfProducts"> <arguments> @@ -538,4 +546,11 @@ <remove keyForRemoval="seeCheckboxForWebsite"/> <seeCheckboxIsChecked selector="{{ProductInWebsitesSection.website(website)}}" after="expandProductWebsitesSection" stepKey="seeCustomWebsiteIsChecked"/> </actionGroup> + + <!-- You are on product Edit Page --> + <!-- Assert checkbox is not checked for website in Product In Websites --> + <actionGroup name="AssertProductIsNotAssignedToWebsite" extends="AssertWebsiteIsAvailableInProductWebsites"> + <remove keyForRemoval="seeCheckboxForWebsite"/> + <dontSeeCheckboxIsChecked selector="{{ProductInWebsitesSection.website(website)}}" after="expandProductWebsitesSection" stepKey="seeCustomWebsiteIsNotChecked"/> + </actionGroup> </actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontAssertPageNotFoundErrorOnProductDetailPageActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontAssertPageNotFoundErrorOnProductDetailPageActionGroup.xml new file mode 100644 index 0000000000000..1de5933c6969a --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontAssertPageNotFoundErrorOnProductDetailPageActionGroup.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <!-- Assert 404 Page Not Found on product detail page --> + <actionGroup name="StorefrontAssertPageNotFoundErrorOnProductDetailPageActionGroup"> + <arguments> + <argument name="product"/> + </arguments> + <see selector="{{StorefrontProductInfoMainSection.productName}}" userInput="Whoops, our bad..." stepKey="assert404Page"/> + <dontSee selector="{{StorefrontProductInfoMainSection.productName}}" userInput="{{product.name}}" stepKey="dontSeeProductName"/> + <seeInCurrentUrl url="/{{product.custom_attributes[url_key]}}.html" stepKey="checkProductUrl"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontOpenProductPageUsingStoreCodeInUrlActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontOpenProductPageUsingStoreCodeInUrlActionGroup.xml new file mode 100644 index 0000000000000..7c79a624d4d11 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontOpenProductPageUsingStoreCodeInUrlActionGroup.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <!-- Action group opens product detail page from second website using Store code in URL option --> + <actionGroup name="StorefrontOpenProductPageUsingStoreCodeInUrlActionGroup"> + <arguments> + <argument name="product"/> + <argument name="storeView"/> + </arguments> + <amOnPage url="/{{storeView.code}}/{{product.custom_attributes[url_key]}}.html" stepKey="openProductPageUsingStoreCodeInUrl"/> + <see selector="{{StorefrontProductInfoMainSection.productName}}" userInput="{{product.name}}" stepKey="assertProductName"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminShouldBeAbleToAssociateSimpleProductToWebsitesTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminShouldBeAbleToAssociateSimpleProductToWebsitesTest.xml new file mode 100644 index 0000000000000..061c30b224828 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminShouldBeAbleToAssociateSimpleProductToWebsitesTest.xml @@ -0,0 +1,83 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AdminShouldBeAbleToAssociateSimpleProductToWebsitesTest"> + <annotations> + <features value="Catalog"/> + <stories value="Edit products"/> + <title value="Admin should be able to associate simple product to websites"/> + <description value="Admin should be able to associate simple product to websites"/> + <testCaseId value="MC-3483"/> + <group value="catalog"/> + <severity value="AVERAGE"/> + </annotations> + + <before> + <magentoCLI command="config:set {{StorefrontEnableAddStoreCodeToUrls.path}} {{StorefrontEnableAddStoreCodeToUrls.value}}" stepKey="setAddStoreCodeToUrlsToYes"/> + <createData entity="secondCustomWebsite" stepKey="createCustomWebsite"/> + <createData entity="SimpleProduct2" stepKey="createSimpleProduct"/> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + <actionGroup ref="AdminStoreGroupCreateActionGroup" stepKey="createNewStore"> + <argument name="Website" value="secondCustomWebsite"/> + <argument name="storeGroup" value="customStoreGroup"/> + </actionGroup> + <actionGroup ref="AdminCreateStoreViewActionGroup" stepKey="createCustomStoreView"> + <argument name="StoreGroup" value="customStoreGroup"/> + <argument name="customStore" value="customStoreEN"/> + </actionGroup> + </before> + + <after> + <magentoCLI command="config:set {{StorefrontDisableAddStoreCodeToUrls.path}} {{StorefrontDisableAddStoreCodeToUrls.value}}" stepKey="setAddStoreCodeToUrlsToNo"/> + <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProduct"/> + <!-- Delete second website --> + <actionGroup ref="DeleteCustomWebsiteActionGroup" stepKey="deleteCustomWeWebsite"> + <argument name="websiteName" value="$createCustomWebsite.website[name]$"/> + </actionGroup> + <actionGroup ref="AdminGridFilterResetActionGroup" stepKey="resetFiltersOnStoresIndexPage"/> + <actionGroup ref="AdminOpenProductIndexPageActionGroup" stepKey="openProductIndexPageToResetFilters"/> + <actionGroup ref="clearFiltersAdminDataGrid" stepKey="clearFiltersOnProductIndexPage"/> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <!-- 1. Go to product page in admin panel to edit --> + <actionGroup ref="AdminOpenProductIndexPageActionGroup" stepKey="openProductIndexPageToAssociateToSecondWebsite"/> + <actionGroup ref="filterProductGridByName2" stepKey="filterProductInGrid"> + <argument name="name" value="$$createSimpleProduct.name$$"/> + </actionGroup> + + <!-- 2. Go to Product in Websites tab, unassign product from Main website and assign it to Second website --> + <actionGroup ref="AdminProcessProductWebsitesActionGroup" stepKey="processProductWebsites"> + <argument name="website" value="secondCustomWebsite"/> + <argument name="websiteToUnassign" value="_defaultWebsite"/> + <argument name="product" value="$$createSimpleProduct$$"/> + </actionGroup> + <actionGroup ref="AssertProductIsAssignedToWebsite" stepKey="seeCustomWebsiteIsChecked"> + <argument name="website" value="$createCustomWebsite.website[name]$"/> + </actionGroup> + <actionGroup ref="AssertProductIsNotAssignedToWebsite" stepKey="seeMainWebsiteIsNotChecked"> + <argument name="website" value="{{_defaultWebsite.name}}"/> + </actionGroup> + + <!-- 3. Go to frontend and open Simple product on Main website and assert 404 page--> + <actionGroup ref="StorefrontOpenProductPageActionGroup" stepKey="openProductPage"> + <argument name="productUrl" value="$createSimpleProduct.custom_attributes[url_key]$"/> + </actionGroup> + <actionGroup ref="StorefrontAssertPageNotFoundErrorOnProductDetailPageActionGroup" stepKey="assertPageNotFoundErrorOnProductDetailPage"> + <argument name="product" value="$$createSimpleProduct$$"/> + </actionGroup> + + <!-- 4. Open Simple product on Second website and assert its name --> + <actionGroup ref="StorefrontOpenProductPageUsingStoreCodeInUrlActionGroup" stepKey="openProductPageUsingStoreCodeInUrl"> + <argument name="product" value="$$createSimpleProduct$$"/> + <argument name="storeView" value="customStoreEN"/> + </actionGroup> + </test> +</tests> From 50f1f4e631bf4e63f125b946cfdaf7d5eb0eac6a Mon Sep 17 00:00:00 2001 From: mahesh <mahesh721@webkul.com> Date: Fri, 7 Jun 2019 20:42:23 +0530 Subject: [PATCH 695/773] Fixed issue #23135 Insert Variable popup missing template variables for new email templates --- .../Block/Adminhtml/Template/Edit/Form.php | 5 +- app/code/Magento/Email/Model/Template.php | 2 +- .../Adminhtml/Template/Edit/FormTest.php | 2 +- .../Email/Test/Unit/Model/TemplateTest.php | 141 +++++++++--------- 4 files changed, 77 insertions(+), 73 deletions(-) diff --git a/app/code/Magento/Email/Block/Adminhtml/Template/Edit/Form.php b/app/code/Magento/Email/Block/Adminhtml/Template/Edit/Form.php index e8096fa2c25f8..3a39fc223ce05 100644 --- a/app/code/Magento/Email/Block/Adminhtml/Template/Edit/Form.php +++ b/app/code/Magento/Email/Block/Adminhtml/Template/Edit/Form.php @@ -9,6 +9,9 @@ */ namespace Magento\Email\Block\Adminhtml\Template\Edit; +/** + * Adminhtml email template edit form block + */ class Form extends \Magento\Backend\Block\Widget\Form\Generic { /** @@ -191,7 +194,7 @@ public function getVariables() } $template = $this->getEmailTemplate(); if ($template->getId() && ($templateVariables = $template->getVariablesOptionArray(true))) { - $variables = array_merge_recursive($variables, $templateVariables); + $variables = array_merge_recursive($variables, [$templateVariables]); } return $variables; } diff --git a/app/code/Magento/Email/Model/Template.php b/app/code/Magento/Email/Model/Template.php index ef2c4341dafa4..7306db1222872 100644 --- a/app/code/Magento/Email/Model/Template.php +++ b/app/code/Magento/Email/Model/Template.php @@ -326,7 +326,7 @@ public function getVariablesOptionArray($withGroup = false) $optionArray[] = ['value' => '{{' . $value . '}}', 'label' => __('%1', $label)]; } if ($withGroup) { - $optionArray = [['label' => __('Template Variables'), 'value' => $optionArray]]; + $optionArray = ['label' => __('Template Variables'), 'value' => $optionArray]; } } return $optionArray; diff --git a/app/code/Magento/Email/Test/Unit/Block/Adminhtml/Template/Edit/FormTest.php b/app/code/Magento/Email/Test/Unit/Block/Adminhtml/Template/Edit/FormTest.php index 3e6f41877940e..a822d5a5d5764 100644 --- a/app/code/Magento/Email/Test/Unit/Block/Adminhtml/Template/Edit/FormTest.php +++ b/app/code/Magento/Email/Test/Unit/Block/Adminhtml/Template/Edit/FormTest.php @@ -75,7 +75,7 @@ public function testGetVariables() ->method('getVariablesOptionArray') ->willReturn(['template var 1', 'template var 2']); $this->assertEquals( - ['var1', 'var2', 'var3', 'custom var 1', 'custom var 2', 'template var 1', 'template var 2'], + ['var1', 'var2', 'var3', 'custom var 1', 'custom var 2', ['template var 1', 'template var 2']], $this->form->getVariables() ); } diff --git a/app/code/Magento/Email/Test/Unit/Model/TemplateTest.php b/app/code/Magento/Email/Test/Unit/Model/TemplateTest.php index 9599cd1fef448..12b970f623e2d 100644 --- a/app/code/Magento/Email/Test/Unit/Model/TemplateTest.php +++ b/app/code/Magento/Email/Test/Unit/Model/TemplateTest.php @@ -173,23 +173,25 @@ protected function getModelMock(array $mockedMethods = []) { return $this->getMockBuilder(Template::class) ->setMethods(array_merge($mockedMethods, ['__wakeup', '__sleep', '_init'])) - ->setConstructorArgs([ - $this->context, - $this->design, - $this->registry, - $this->appEmulation, - $this->storeManager, - $this->assetRepo, - $this->filesystem, - $this->scopeConfig, - $this->emailConfig, - $this->templateFactory, - $this->filterManager, - $this->urlModel, - $this->filterFactory, - [], - $this->serializerMock - ]) + ->setConstructorArgs( + [ + $this->context, + $this->design, + $this->registry, + $this->appEmulation, + $this->storeManager, + $this->assetRepo, + $this->filesystem, + $this->scopeConfig, + $this->emailConfig, + $this->templateFactory, + $this->filterManager, + $this->urlModel, + $this->filterFactory, + [], + $this->serializerMock + ] + ) ->getMock(); } @@ -257,9 +259,7 @@ public function testLoadDefault( $expectedOrigTemplateVariables, $expectedTemplateStyles ) { - $model = $this->getModelMock([ - 'getDesignParams' - ]); + $model = $this->getModelMock(['getDesignParams']); $designParams = [ 'area' => Area::AREA_FRONTEND, @@ -382,13 +382,15 @@ public function loadDefaultDataProvider() public function testLoadByConfigPath($loadFromDatabase) { $configPath = 'design/email/header_template'; - $model = $this->getModelMock([ - 'getDesignConfig', - 'loadDefault', - 'load', - 'getTemplateText', - 'setTemplateText', - ]); + $model = $this->getModelMock( + [ + 'getDesignConfig', + 'loadDefault', + 'load', + 'getTemplateText', + 'setTemplateText', + ] + ); $designConfig = $this->getMockBuilder(\Magento\Framework\DataObject::class) ->setMethods(['getStore']) @@ -611,21 +613,19 @@ public function getVariablesOptionArrayDataProvider() 'templateVariables' => '{"store url=\"\"":"Store Url","var logo_url":"Email Logo Image Url",' . '"var customer.name":"Customer Name"}', 'expectedResult' => [ - [ - 'label' => __('Template Variables'), - 'value' => [ - [ - 'value' => '{{store url=""}}', - 'label' => __('%1', 'Store Url'), - ], - [ - 'value' => '{{var logo_url}}', - 'label' => __('%1', 'Email Logo Image Url'), - ], - [ - 'value' => '{{var customer.name}}', - 'label' => __('%1', 'Customer Name'), - ], + 'label' => __('Template Variables'), + 'value' => [ + [ + 'value' => '{{store url=""}}', + 'label' => __('%1', 'Store Url'), + ], + [ + 'value' => '{{var logo_url}}', + 'label' => __('%1', 'Email Logo Image Url'), + ], + [ + 'value' => '{{var customer.name}}', + 'label' => __('%1', 'Customer Name'), ], ], ], @@ -640,13 +640,15 @@ public function getVariablesOptionArrayDataProvider() */ public function testProcessTemplate($templateId, $expectedResult) { - $model = $this->getModelMock([ - 'load', - 'loadDefault', - 'getProcessedTemplate', - 'applyDesignConfig', - 'cancelDesignConfig', - ]); + $model = $this->getModelMock( + [ + 'load', + 'loadDefault', + 'getProcessedTemplate', + 'applyDesignConfig', + 'cancelDesignConfig', + ] + ); $model->setId($templateId); if (is_numeric($templateId)) { $model->expects($this->once()) @@ -698,10 +700,7 @@ public function processTemplateVariable() */ public function testProcessTemplateThrowsExceptionNonExistentTemplate() { - $model = $this->getModelMock([ - 'loadDefault', - 'applyDesignConfig', - ]); + $model = $this->getModelMock(['loadDefault', 'applyDesignConfig',]); $model->expects($this->once()) ->method('loadDefault') ->willReturn(true); @@ -753,23 +752,25 @@ public function testGetType($templateType, $expectedResult) /** @var Template $model */ $model = $this->getMockBuilder(Template::class) ->setMethods(['_init']) - ->setConstructorArgs([ - $this->createMock(Context::class), - $this->createMock(Design::class), - $this->createMock(Registry::class), - $this->createMock(Emulation::class), - $this->createMock(StoreManager::class), - $this->createMock(Repository::class), - $this->createMock(Filesystem::class), - $this->createMock(ScopeConfigInterface::class), - $emailConfig, - $this->createMock(TemplateFactory::class), - $this->createMock(FilterManager::class), - $this->createMock(Url::class), - $this->createMock(FilterFactory::class), - [], - $this->createMock(Json::class) - ]) + ->setConstructorArgs( + [ + $this->createMock(Context::class), + $this->createMock(Design::class), + $this->createMock(Registry::class), + $this->createMock(Emulation::class), + $this->createMock(StoreManager::class), + $this->createMock(Repository::class), + $this->createMock(Filesystem::class), + $this->createMock(ScopeConfigInterface::class), + $emailConfig, + $this->createMock(TemplateFactory::class), + $this->createMock(FilterManager::class), + $this->createMock(Url::class), + $this->createMock(FilterFactory::class), + [], + $this->createMock(Json::class) + ] + ) ->getMock(); $model->setTemplateId(10); From c1ed5283bcc73035f14cab500865f7898b9104ad Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <engcom-vendorworker-foxtrot@adobe.com> Date: Tue, 16 Jul 2019 12:21:50 +0300 Subject: [PATCH 696/773] magento/magento2#23173: Static and integration tests fix. --- .../Block/Adminhtml/Template/Edit/Form.php | 3 +- .../Magento/Email/Model/TemplateTest.php | 96 +++++++++++-------- 2 files changed, 56 insertions(+), 43 deletions(-) diff --git a/app/code/Magento/Email/Block/Adminhtml/Template/Edit/Form.php b/app/code/Magento/Email/Block/Adminhtml/Template/Edit/Form.php index 3a39fc223ce05..2cd3ea42649c1 100644 --- a/app/code/Magento/Email/Block/Adminhtml/Template/Edit/Form.php +++ b/app/code/Magento/Email/Block/Adminhtml/Template/Edit/Form.php @@ -57,7 +57,8 @@ public function __construct( /** * Prepare layout. - * Add files to use dialog windows + * + * Add files to use dialog windows. * * @return $this */ diff --git a/dev/tests/integration/testsuite/Magento/Email/Model/TemplateTest.php b/dev/tests/integration/testsuite/Magento/Email/Model/TemplateTest.php index 2d12eefc286c6..f791cdbeffe59 100644 --- a/dev/tests/integration/testsuite/Magento/Email/Model/TemplateTest.php +++ b/dev/tests/integration/testsuite/Magento/Email/Model/TemplateTest.php @@ -52,21 +52,23 @@ protected function mockModel($filesystem = null) $this->model = $this->getMockBuilder(\Magento\Email\Model\Template::class) ->setMethods(['_getMail']) - ->setConstructorArgs([ - $this->objectManager->get(\Magento\Framework\Model\Context::class), - $this->objectManager->get(\Magento\Framework\View\DesignInterface::class), - $this->objectManager->get(\Magento\Framework\Registry::class), - $this->objectManager->get(\Magento\Store\Model\App\Emulation::class), - $this->objectManager->get(\Magento\Store\Model\StoreManager::class), - $this->objectManager->create(\Magento\Framework\View\Asset\Repository::class), - $filesystem, - $this->objectManager->create(\Magento\Framework\App\Config\ScopeConfigInterface::class), - $this->objectManager->get(\Magento\Email\Model\Template\Config::class), - $this->objectManager->get(\Magento\Email\Model\TemplateFactory::class), - $this->objectManager->get(\Magento\Framework\Filter\FilterManager::class), - $this->objectManager->get(\Magento\Framework\UrlInterface::class), - $this->objectManager->get(\Magento\Email\Model\Template\FilterFactory::class), - ]) + ->setConstructorArgs( + [ + $this->objectManager->get(\Magento\Framework\Model\Context::class), + $this->objectManager->get(\Magento\Framework\View\DesignInterface::class), + $this->objectManager->get(\Magento\Framework\Registry::class), + $this->objectManager->get(\Magento\Store\Model\App\Emulation::class), + $this->objectManager->get(\Magento\Store\Model\StoreManager::class), + $this->objectManager->create(\Magento\Framework\View\Asset\Repository::class), + $filesystem, + $this->objectManager->create(\Magento\Framework\App\Config\ScopeConfigInterface::class), + $this->objectManager->get(\Magento\Email\Model\Template\Config::class), + $this->objectManager->get(\Magento\Email\Model\TemplateFactory::class), + $this->objectManager->get(\Magento\Framework\Filter\FilterManager::class), + $this->objectManager->get(\Magento\Framework\UrlInterface::class), + $this->objectManager->get(\Magento\Email\Model\Template\FilterFactory::class), + ] + ) ->getMock(); $this->objectManager->get(\Magento\Framework\App\State::class)->setAreaCode('frontend'); @@ -122,12 +124,14 @@ public function testGetProcessedTemplate() ->load(); $expectedViewUrl = '/frontend/Magento/blank/en_US/Magento_Theme/favicon.ico'; - $this->model->setDesignConfig([ - 'area' => 'frontend', - 'store' => $this->objectManager->get(\Magento\Store\Model\StoreManagerInterface::class) - ->getStore('fixturestore') - ->getId(), - ]); + $this->model->setDesignConfig( + [ + 'area' => 'frontend', + 'store' => $this->objectManager->get(\Magento\Store\Model\StoreManagerInterface::class) + ->getStore('fixturestore') + ->getId(), + ] + ); $this->model->setTemplateText('{{view url="Magento_Theme::favicon.ico"}}'); $this->setNotDefaultThemeForFixtureStore(); @@ -373,9 +377,11 @@ public function testTemplateStylesVariable($area, $expectedOutput, $unexpectedOu // @styles comments by default, it is necessary to mock an object to return testable contents $themeDirectory = $this->getMockBuilder(\Magento\Framework\Filesystem\Directory\ReadInterface::class) ->disableOriginalConstructor() - ->setMethods([ - 'readFile', - ]) + ->setMethods( + [ + 'readFile', + ] + ) ->getMockForAbstractClass(); $themeDirectory->expects($this->once()) @@ -478,10 +484,12 @@ protected function setUpAdminThemeFallback() $adminStore = $this->objectManager->create(\Magento\Store\Model\Store::class) ->load(Store::ADMIN_CODE); - $this->model->setDesignConfig([ - 'area' => 'adminhtml', - 'store' => $adminStore->getId(), - ]); + $this->model->setDesignConfig( + [ + 'area' => 'adminhtml', + 'store' => $adminStore->getId(), + ] + ); } /** @@ -516,12 +524,14 @@ protected function setUpThemeFallback($area) 'fixturestore' ); - $this->model->setDesignConfig([ - 'area' => 'frontend', - 'store' => $this->objectManager->get(\Magento\Store\Model\StoreManagerInterface::class) - ->getStore('fixturestore') - ->getId(), - ]); + $this->model->setDesignConfig( + [ + 'area' => 'frontend', + 'store' => $this->objectManager->get(\Magento\Store\Model\StoreManagerInterface::class) + ->getStore('fixturestore') + ->getId(), + ] + ); } /** @@ -578,12 +588,14 @@ public function testGetProcessedTemplateSubject() ->load(); $this->model->setTemplateSubject('{{view url="Magento_Theme::favicon.ico"}}'); - $this->model->setDesignConfig([ - 'area' => 'frontend', - 'store' => $this->objectManager->get(\Magento\Store\Model\StoreManagerInterface::class) - ->getStore('fixturestore') - ->getId(), - ]); + $this->model->setDesignConfig( + [ + 'area' => 'frontend', + 'store' => $this->objectManager->get(\Magento\Store\Model\StoreManagerInterface::class) + ->getStore('fixturestore') + ->getId(), + ] + ); $this->setNotDefaultThemeForFixtureStore(); $this->assertStringMatchesFormat( @@ -703,8 +715,8 @@ public function testGetVariablesOptionArrayInGroup() $testTemplateVariables = '{"var data.name":"Sender Name","var data.email":"Sender Email"}'; $this->model->setOrigTemplateVariables($testTemplateVariables); $variablesOptionArray = $this->model->getVariablesOptionArray(true); - $this->assertEquals('Template Variables', $variablesOptionArray[0]['label']->getText()); - $this->assertEquals($this->model->getVariablesOptionArray(), $variablesOptionArray[0]['value']); + $this->assertEquals('Template Variables', $variablesOptionArray['label']->getText()); + $this->assertEquals($this->model->getVariablesOptionArray(), $variablesOptionArray['value']); } /** From d8fc77673812b635d7a6b93f12c2579324c86dd1 Mon Sep 17 00:00:00 2001 From: Nikita Fomin <nikita.fomin@transoftgroup.com> Date: Tue, 16 Jul 2019 12:41:23 +0300 Subject: [PATCH 697/773] MC-18053: [MTF] OnePageCheckoutJsValidationTestVariation1_0 randomly fails on jenkins --- .../Checkout/Test/TestCase/OnePageCheckoutJsValidationTest.php | 2 +- .../Checkout/Test/TestCase/OnePageCheckoutJsValidationTest.xml | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) 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 ff0038715bcb0..2763982657072 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 @@ -17,7 +17,7 @@ * 5. Perform assertions. * * @group One_Page_Checkout - * @ZephyrId MAGETWO-59697 + * @ZephyrId MC-18203 */ class OnePageCheckoutJsValidationTest extends Scenario { 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 75603d12cbe32..c01f25a6066d6 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 @@ -6,9 +6,8 @@ */ --> <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"> + <testCase name="Magento\Checkout\Test\TestCase\OnePageCheckoutJsValidationTest" summary="JS validation verification for Checkout flow" ticketId="MC-18203"> <variation name="OnePageCheckoutJsValidationTestVariation1" summary="JS validation is not applied for empty required checkout fields if customer did not fill them"> - <data name="issue" xsi:type="string">MAGETWO-97990: [MTF] OnePageCheckoutJsValidationTestVariation1_0 randomly fails on jenkins</data> <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> From 9a44da1e9b910d8c1c06f4af9e02b8db91e9ea7a Mon Sep 17 00:00:00 2001 From: Aliaksei Yakimovich2 <aliaksei_yakimovich2@epam.com> Date: Tue, 16 Jul 2019 13:01:45 +0300 Subject: [PATCH 698/773] MC-17218: php bin/magento catalog:image:resize error if image is missing - Fixed unit test; --- .../Magento/MediaStorage/Test/Unit/Service/ImageResizeTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/MediaStorage/Test/Unit/Service/ImageResizeTest.php b/app/code/Magento/MediaStorage/Test/Unit/Service/ImageResizeTest.php index 7fccfa04f86d0..d612fb9e3b67b 100644 --- a/app/code/Magento/MediaStorage/Test/Unit/Service/ImageResizeTest.php +++ b/app/code/Magento/MediaStorage/Test/Unit/Service/ImageResizeTest.php @@ -248,7 +248,7 @@ function () { $this->mediaDirectoryMock->expects($this->any()) ->method('isFile') ->with($this->testfilepath) - ->will($this->returnValue(false)); + ->will($this->returnValue(true)); $this->databaseMock->expects($this->once()) ->method('saveFileToFilesystem') From 058e09bcaeee0b2ee2cfa478bfb3c874c8a73e8c Mon Sep 17 00:00:00 2001 From: "rostyslav.hymon" <rostyslav.hymon@transoftgroup.com> Date: Tue, 16 Jul 2019 14:08:41 +0300 Subject: [PATCH 699/773] MC-18193: All Sales emails are being copied to the same customer when sales_emails cron has an error --- .../Magento/Framework/Mail/Template/TransportBuilder.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php b/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php index b9271c0209fd3..85c941f5dfedb 100644 --- a/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php +++ b/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php @@ -261,8 +261,13 @@ public function setTemplateOptions($templateOptions) */ public function getTransport() { - $this->prepareMessage(); - $mailTransport = $this->mailTransportFactory->create(['message' => clone $this->message]); + try { + $this->prepareMessage(); + $mailTransport = $this->mailTransportFactory->create(['message' => clone $this->message]); + } catch (LocalizedException $e) { + $this->reset(); + throw $e; + } $this->reset(); return $mailTransport; From 4a8c042ff91be2582d7f62509fa0b884a0801109 Mon Sep 17 00:00:00 2001 From: Dmytro Yushkin <dyushkin@adobe.com> Date: Tue, 16 Jul 2019 15:13:03 -0500 Subject: [PATCH 700/773] MC-18200: Cybersource in iframe does not work --- .../templates/transparent/iframe.phtml | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/app/code/Magento/Payment/view/frontend/templates/transparent/iframe.phtml b/app/code/Magento/Payment/view/frontend/templates/transparent/iframe.phtml index ea06c60c30e20..538f89e8bec06 100644 --- a/app/code/Magento/Payment/view/frontend/templates/transparent/iframe.phtml +++ b/app/code/Magento/Payment/view/frontend/templates/transparent/iframe.phtml @@ -15,19 +15,19 @@ $params = $block->getParams(); <?php if (isset($params['redirect'])): ?> window.location="<?= $block->escapeUrl($params['redirect']) ?>"; <?php elseif (isset($params['redirect_parent'])): ?> - var require = window.top.require; + var require = window.parent.require; require( [ 'jquery' ], function($) { - var parent = window.top; + var parent = window.parent; $(parent).trigger('clearTimeout'); parent.location="<?= $block->escapeUrl($params['redirect_parent']) ?>"; } ); <?php elseif (isset($params['error_msg'])): ?> - var require = window.top.require; + var require = window.parent.require; require( [ 'jquery', @@ -36,7 +36,7 @@ $params = $block->getParams(); 'Magento_Checkout/js/model/full-screen-loader' ], function($, globalMessageList, $t, fullScreenLoader) { - var parent = window.top; + var parent = window.parent; $(parent).trigger('clearTimeout'); fullScreenLoader.stopLoader(); globalMessageList.addErrorMessage({ @@ -45,21 +45,21 @@ $params = $block->getParams(); } ); <?php elseif (isset($params['multishipping'])): ?> - var require = window.top.require; + var require = window.parent.require; require( [ 'jquery' ], function($) { - var parent = window.top; + var parent = window.parent; $(parent).trigger('clearTimeout'); $(parent.document).find('#multishipping-billing-form').submit(); } ); <?php elseif (isset($params['order_success'])): ?> - window.top.location = "<?= $block->escapeUrl($params['order_success']) ?>"; + window.parent.location = "<?= $block->escapeUrl($params['order_success']) ?>"; <?php else: ?> - var require = window.top.require; + var require = window.parent.require; require( [ 'jquery', @@ -69,7 +69,7 @@ $params = $block->getParams(); 'Magento_Checkout/js/model/full-screen-loader' ], function($, quote, placeOrderAction, redirectOnSuccessAction, fullScreenLoader) { - var parent = window.top; + var parent = window.parent; $(parent).trigger('clearTimeout'); $.when( @@ -80,7 +80,7 @@ $params = $block->getParams(); } ).fail( function () { - var parent = window.top; + var parent = window.parent; $(parent).trigger('clearTimeout'); fullScreenLoader.stopLoader(); } From 142d2aadf58ff2bbbc9a4d4c264520b050a5b133 Mon Sep 17 00:00:00 2001 From: Arnolds Kozlovskis <arnoldskozlovskis@gmail.com> Date: Tue, 16 Jul 2019 21:19:40 +0100 Subject: [PATCH 701/773] Fixed typo in deploy module README.md from `bin/magento setup:mode:set` to `bin/magento deploy:mode:set` --- app/code/Magento/Deploy/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Deploy/README.md b/app/code/Magento/Deploy/README.md index 344080063a801..0e4bdb11e0bb8 100644 --- a/app/code/Magento/Deploy/README.md +++ b/app/code/Magento/Deploy/README.md @@ -5,7 +5,7 @@ Deploy is a module that holds collection of services and command line tools to h To execute this command, please, run "bin/magento setup:static-content:deploy" from the Magento root directory. Deploy module contains 2 additional commands that allows switching between application modes (for instance from development to -production) and show current application mode. To change the mode run "bin/magento setup:mode:set [mode]". +production) and show current application mode. To change the mode run "bin/magento deploy:mode:set [mode]". Where mode can be one of the following: - development - production From a45275ba6de0e098df1bd7c19f6d1aec8dd378ed Mon Sep 17 00:00:00 2001 From: Tom Reece <treece@adobe.com> Date: Tue, 16 Jul 2019 15:25:11 -0500 Subject: [PATCH 702/773] MQE-1632: Part three fixing skipped tests - Add various waits and timeouts --- .../Catalog/Test/Mftf/Section/AdminProductFormSection.xml | 2 +- ...oductWithRegularPriceInStockVisibleInCategoryOnlyTest.xml | 5 ++--- ...rPriceInStockWithCustomOptionsVisibleInSearchOnlyTest.xml | 5 ++--- ...ctWithRegularPriceOutOfStockVisibleInCategoryOnlyTest.xml | 5 ++--- ...WithSpecialPriceInStockVisibleInCategoryAndSearchTest.xml | 5 ++--- ...hSpecialPriceOutOfStockVisibleInCategoryAndSearchTest.xml | 5 ++--- ...uctWithTierPriceInStockVisibleInCategoryAndSearchTest.xml | 5 ++--- ...lProductWithTierPriceInStockVisibleInCategoryOnlyTest.xml | 5 ++--- ...WithTierPriceOutOfStockVisibleInCategoryAndSearchTest.xml | 5 ++--- 9 files changed, 17 insertions(+), 25 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormSection.xml index 90e954b8e136f..0dd9e6d948c18 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormSection.xml @@ -66,7 +66,7 @@ <element name="attributeRequiredInput" type="input" selector="//input[contains(@name, 'product[{{attributeCode}}]')]" parameterized="true"/> <element name="attributeFieldError" type="text" selector="//*[@class='admin__field _required _error']/..//label[contains(.,'This is a required field.')]"/> <element name="customSelectField" type="select" selector="//select[@name='product[{{var}}]']" parameterized="true"/> - <element name="searchCategory" type="input" selector="//*[@data-index='category_ids']//input[contains(@class, 'multiselect-search')]"/> + <element name="searchCategory" type="input" selector="//*[@data-index='category_ids']//input[contains(@class, 'multiselect-search')]" timeout="30"/> <element name="selectCategory" type="input" selector="//*[@data-index='category_ids']//label[contains(., '{{categoryName}}')]" parameterized="true" timeout="30"/> <element name="done" type="button" selector="//*[@data-index='category_ids']//button[@data-action='close-advanced-select']" timeout="30"/> <element name="selectMultipleCategories" type="input" selector="//*[@data-index='container_category_ids']//*[contains(@class, '_selected')]"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceInStockVisibleInCategoryOnlyTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceInStockVisibleInCategoryOnlyTest.xml index d7ceefb03d3b1..8ac56d09e5b42 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceInStockVisibleInCategoryOnlyTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceInStockVisibleInCategoryOnlyTest.xml @@ -17,9 +17,6 @@ <severity value="CRITICAL"/> <group value="catalog"/> <group value="mtf_migrated"/> - <skip> - <issueId value="MC-17181"/> - </skip> </annotations> <before> @@ -65,8 +62,10 @@ <selectOption selector="{{AdminProductFormSection.stockStatus}}" userInput="{{updateVirtualProductRegularPrice.status}}" stepKey="selectStockStatusInStock"/> <click selector="{{AdminProductFormSection.categoriesDropdown}}" stepKey="clickCategoriesDropDown"/> <fillField selector="{{AdminProductFormSection.searchCategory}}" userInput="$$initialCategoryEntity.name$$" stepKey="fillSearchForInitialCategory" /> + <waitForPageLoad stepKey="waitForCategory1"/> <click selector="{{AdminProductFormSection.selectCategory($$initialCategoryEntity.name$$)}}" stepKey="unselectInitialCategory"/> <fillField selector="{{AdminProductFormSection.searchCategory}}" userInput="$$categoryEntity.name$$" stepKey="fillSearchCategory" /> + <waitForPageLoad stepKey="waitForCategory2"/> <click selector="{{AdminProductFormSection.selectCategory($$categoryEntity.name$$)}}" stepKey="clickOnCategory"/> <click selector="{{AdminProductFormSection.done}}" stepKey="clickOnDoneAdvancedCategorySelect"/> <selectOption selector="{{AdminProductFormSection.visibility}}" userInput="{{updateVirtualProductRegularPrice.visibility}}" stepKey="selectVisibility"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceInStockWithCustomOptionsVisibleInSearchOnlyTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceInStockWithCustomOptionsVisibleInSearchOnlyTest.xml index ef02b73ea16d4..f621813f4f8c0 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceInStockWithCustomOptionsVisibleInSearchOnlyTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceInStockWithCustomOptionsVisibleInSearchOnlyTest.xml @@ -17,9 +17,6 @@ <severity value="CRITICAL"/> <group value="catalog"/> <group value="mtf_migrated"/> - <skip> - <issueId value="MC-17181"/> - </skip> </annotations> <before> @@ -55,8 +52,10 @@ <selectOption selector="{{AdminProductFormSection.stockStatus}}" userInput="{{updateVirtualProductRegularPriceInStock.status}}" stepKey="selectStockStatusInStock"/> <click selector="{{AdminProductFormSection.categoriesDropdown}}" stepKey="clickCategoriesDropDown"/> <fillField selector="{{AdminProductFormSection.searchCategory}}" userInput="$$initialCategoryEntity.name$$" stepKey="fillSearchForInitialCategory" /> + <waitForPageLoad stepKey="waitForCategory1"/> <click selector="{{AdminProductFormSection.selectCategory($$initialCategoryEntity.name$$)}}" stepKey="unselectInitialCategory"/> <fillField selector="{{AdminProductFormSection.searchCategory}}" userInput="$$categoryEntity.name$$" stepKey="fillSearchCategory" /> + <waitForPageLoad stepKey="waitForCategory2"/> <click selector="{{AdminProductFormSection.selectCategory($$categoryEntity.name$$)}}" stepKey="clickOnCategory"/> <click selector="{{AdminProductFormSection.done}}" stepKey="clickOnDoneAdvancedCategorySelect"/> <selectOption selector="{{AdminProductFormSection.visibility}}" userInput="{{updateVirtualProductRegularPriceInStock.visibility}}" stepKey="selectVisibility"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceOutOfStockVisibleInCategoryOnlyTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceOutOfStockVisibleInCategoryOnlyTest.xml index b5ee6d8112b50..ffbad0752b73c 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceOutOfStockVisibleInCategoryOnlyTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceOutOfStockVisibleInCategoryOnlyTest.xml @@ -17,9 +17,6 @@ <severity value="CRITICAL"/> <group value="catalog"/> <group value="mtf_migrated"/> - <skip> - <issueId value="MC-17181"/> - </skip> </annotations> <before> @@ -54,8 +51,10 @@ <selectOption selector="{{AdminProductFormSection.stockStatus}}" userInput="{{updateVirtualProductRegularPrice5OutOfStock.status}}" stepKey="selectStockStatusInStock"/> <click selector="{{AdminProductFormSection.categoriesDropdown}}" stepKey="clickCategoriesDropDown"/> <fillField selector="{{AdminProductFormSection.searchCategory}}" userInput="$$initialCategoryEntity.name$$" stepKey="fillSearchForInitialCategory" /> + <waitForPageLoad stepKey="waitForCategory1"/> <click selector="{{AdminProductFormSection.selectCategory($$initialCategoryEntity.name$$)}}" stepKey="unselectInitialCategory"/> <fillField selector="{{AdminProductFormSection.searchCategory}}" userInput="$$categoryEntity.name$$" stepKey="fillSearchCategory" /> + <waitForPageLoad stepKey="waitForCategory2"/> <click selector="{{AdminProductFormSection.selectCategory($$categoryEntity.name$$)}}" stepKey="clickOnCategory"/> <click selector="{{AdminProductFormSection.done}}" stepKey="clickOnDoneAdvancedCategorySelect"/> <selectOption selector="{{AdminProductFormSection.visibility}}" userInput="{{updateVirtualProductRegularPrice5OutOfStock.visibility}}" stepKey="selectVisibility"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithSpecialPriceInStockVisibleInCategoryAndSearchTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithSpecialPriceInStockVisibleInCategoryAndSearchTest.xml index 64342d18198c5..3101c1e460322 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithSpecialPriceInStockVisibleInCategoryAndSearchTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithSpecialPriceInStockVisibleInCategoryAndSearchTest.xml @@ -17,9 +17,6 @@ <severity value="CRITICAL"/> <group value="catalog"/> <group value="mtf_migrated"/> - <skip> - <issueId value="MC-17181"/> - </skip> </annotations> <before> @@ -60,8 +57,10 @@ <selectOption selector="{{AdminProductFormSection.stockStatus}}" userInput="{{updateVirtualProductSpecialPrice.status}}" stepKey="selectStockStatusInStock"/> <click selector="{{AdminProductFormSection.categoriesDropdown}}" stepKey="clickCategoriesDropDown"/> <fillField selector="{{AdminProductFormSection.searchCategory}}" userInput="$$initialCategoryEntity.name$$" stepKey="fillSearchForInitialCategory" /> + <waitForPageLoad stepKey="waitForCategory1"/> <click selector="{{AdminProductFormSection.selectCategory($$initialCategoryEntity.name$$)}}" stepKey="unselectInitialCategory"/> <fillField selector="{{AdminProductFormSection.searchCategory}}" userInput="$$categoryEntity.name$$" stepKey="fillSearchCategory" /> + <waitForPageLoad stepKey="waitForCategory2"/> <click selector="{{AdminProductFormSection.selectCategory($$categoryEntity.name$$)}}" stepKey="clickOnCategory"/> <click selector="{{AdminProductFormSection.done}}" stepKey="clickOnDoneAdvancedCategorySelect"/> <selectOption selector="{{AdminProductFormSection.visibility}}" userInput="{{updateVirtualProductSpecialPrice.visibility}}" stepKey="selectVisibility"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithSpecialPriceOutOfStockVisibleInCategoryAndSearchTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithSpecialPriceOutOfStockVisibleInCategoryAndSearchTest.xml index 7378a7f111c30..58978c31b5b40 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithSpecialPriceOutOfStockVisibleInCategoryAndSearchTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithSpecialPriceOutOfStockVisibleInCategoryAndSearchTest.xml @@ -17,9 +17,6 @@ <severity value="CRITICAL"/> <group value="catalog"/> <group value="mtf_migrated"/> - <skip> - <issueId value="MC-17181"/> - </skip> </annotations> <before> @@ -59,8 +56,10 @@ <selectOption selector="{{AdminProductFormSection.stockStatus}}" userInput="{{updateVirtualProductSpecialPriceOutOfStock.status}}" stepKey="selectStockStatusInStock"/> <click selector="{{AdminProductFormSection.categoriesDropdown}}" stepKey="clickCategoriesDropDown"/> <fillField selector="{{AdminProductFormSection.searchCategory}}" userInput="$$initialCategoryEntity.name$$" stepKey="fillSearchForInitialCategory" /> + <waitForPageLoad stepKey="waitForCategory1"/> <click selector="{{AdminProductFormSection.selectCategory($$initialCategoryEntity.name$$)}}" stepKey="unselectInitialCategory"/> <fillField selector="{{AdminProductFormSection.searchCategory}}" userInput="$$categoryEntity.name$$" stepKey="fillSearchCategory" /> + <waitForPageLoad stepKey="waitForCategory2"/> <click selector="{{AdminProductFormSection.selectCategory($$categoryEntity.name$$)}}" stepKey="clickOnCategory"/> <click selector="{{AdminProductFormSection.done}}" stepKey="clickOnDoneAdvancedCategorySelect"/> <selectOption selector="{{AdminProductFormSection.visibility}}" userInput="{{updateVirtualProductSpecialPriceOutOfStock.visibility}}" stepKey="selectVisibility"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithTierPriceInStockVisibleInCategoryAndSearchTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithTierPriceInStockVisibleInCategoryAndSearchTest.xml index ddb4002a5dba3..d28e9ddbb1271 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithTierPriceInStockVisibleInCategoryAndSearchTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithTierPriceInStockVisibleInCategoryAndSearchTest.xml @@ -17,9 +17,6 @@ <severity value="CRITICAL"/> <group value="catalog"/> <group value="mtf_migrated"/> - <skip> - <issueId value="MC-17181"/> - </skip> </annotations> <before> @@ -65,8 +62,10 @@ <selectOption selector="{{AdminProductFormSection.stockStatus}}" userInput="{{updateVirtualProductTierPriceInStock.status}}" stepKey="selectStockStatusInStock"/> <click selector="{{AdminProductFormSection.categoriesDropdown}}" stepKey="clickCategoriesDropDown"/> <fillField selector="{{AdminProductFormSection.searchCategory}}" userInput="$$initialCategoryEntity.name$$" stepKey="fillSearchForInitialCategory" /> + <waitForPageLoad stepKey="waitForCategory1"/> <click selector="{{AdminProductFormSection.selectCategory($$initialCategoryEntity.name$$)}}" stepKey="unselectInitialCategory"/> <fillField selector="{{AdminProductFormSection.searchCategory}}" userInput="$$categoryEntity.name$$" stepKey="fillSearchCategory" /> + <waitForPageLoad stepKey="waitForCategory2"/> <click selector="{{AdminProductFormSection.selectCategory($$categoryEntity.name$$)}}" stepKey="clickOnCategory"/> <click selector="{{AdminProductFormSection.done}}" stepKey="clickOnDoneAdvancedCategorySelect"/> <selectOption selector="{{AdminProductFormSection.visibility}}" userInput="{{updateVirtualProductTierPriceInStock.visibility}}" stepKey="selectVisibility"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithTierPriceInStockVisibleInCategoryOnlyTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithTierPriceInStockVisibleInCategoryOnlyTest.xml index 9aff504f58f81..22dd2b0054db4 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithTierPriceInStockVisibleInCategoryOnlyTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithTierPriceInStockVisibleInCategoryOnlyTest.xml @@ -17,9 +17,6 @@ <severity value="CRITICAL"/> <group value="catalog"/> <group value="mtf_migrated"/> - <skip> - <issueId value="MC-17181"/> - </skip> </annotations> <before> @@ -65,8 +62,10 @@ <selectOption selector="{{AdminProductFormSection.stockStatus}}" userInput="{{updateVirtualProductWithTierPriceInStock.status}}" stepKey="selectStockStatusInStock"/> <click selector="{{AdminProductFormSection.categoriesDropdown}}" stepKey="clickCategoriesDropDown"/> <fillField selector="{{AdminProductFormSection.searchCategory}}" userInput="$$initialCategoryEntity.name$$" stepKey="fillSearchForInitialCategory" /> + <waitForPageLoad stepKey="waitForCategory1"/> <click selector="{{AdminProductFormSection.selectCategory($$initialCategoryEntity.name$$)}}" stepKey="unselectInitialCategory"/> <fillField selector="{{AdminProductFormSection.searchCategory}}" userInput="$$categoryEntity.name$$" stepKey="fillSearchCategory" /> + <waitForPageLoad stepKey="waitForCategory2"/> <click selector="{{AdminProductFormSection.selectCategory($$categoryEntity.name$$)}}" stepKey="clickOnCategory"/> <click selector="{{AdminProductFormSection.done}}" stepKey="clickOnDoneAdvancedCategorySelect"/> <selectOption selector="{{AdminProductFormSection.visibility}}" userInput="{{updateVirtualProductWithTierPriceInStock.visibility}}" stepKey="selectVisibility"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithTierPriceOutOfStockVisibleInCategoryAndSearchTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithTierPriceOutOfStockVisibleInCategoryAndSearchTest.xml index 41796bcc2c3a9..29c7536d21621 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithTierPriceOutOfStockVisibleInCategoryAndSearchTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithTierPriceOutOfStockVisibleInCategoryAndSearchTest.xml @@ -17,9 +17,6 @@ <severity value="CRITICAL"/> <group value="catalog"/> <group value="mtf_migrated"/> - <skip> - <issueId value="MC-17181"/> - </skip> </annotations> <before> @@ -65,8 +62,10 @@ <selectOption selector="{{AdminProductFormSection.stockStatus}}" userInput="{{updateVirtualTierPriceOutOfStock.status}}" stepKey="selectStockStatusInStock"/> <click selector="{{AdminProductFormSection.categoriesDropdown}}" stepKey="clickCategoriesDropDown"/> <fillField selector="{{AdminProductFormSection.searchCategory}}" userInput="$$initialCategoryEntity.name$$" stepKey="fillSearchForInitialCategory" /> + <waitForPageLoad stepKey="waitForCategory1"/> <click selector="{{AdminProductFormSection.selectCategory($$initialCategoryEntity.name$$)}}" stepKey="unselectInitialCategory"/> <fillField selector="{{AdminProductFormSection.searchCategory}}" userInput="$$categoryEntity.name$$" stepKey="fillSearchCategory" /> + <waitForPageLoad stepKey="waitForCategory2"/> <click selector="{{AdminProductFormSection.selectCategory($$categoryEntity.name$$)}}" stepKey="clickOnCategory"/> <click selector="{{AdminProductFormSection.done}}" stepKey="clickOnDoneAdvancedCategorySelect"/> <selectOption selector="{{AdminProductFormSection.visibility}}" userInput="{{updateVirtualTierPriceOutOfStock.visibility}}" stepKey="selectVisibility"/> From 1664ee65bf39b74744a98b0fa0fdf47d6614b0f2 Mon Sep 17 00:00:00 2001 From: Dave Macaulay <macaulay@adobe.com> Date: Tue, 16 Jul 2019 16:50:26 -0500 Subject: [PATCH 703/773] MC-15981: Page Builder Render --- app/code/Magento/Ui/view/base/web/js/lib/core/storage/local.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Ui/view/base/web/js/lib/core/storage/local.js b/app/code/Magento/Ui/view/base/web/js/lib/core/storage/local.js index adeb510ab3e40..a7407362cff9e 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/core/storage/local.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/core/storage/local.js @@ -11,7 +11,7 @@ define([ 'use strict'; var root = 'appData', - localStorage = window.localStorage, + localStorage, hasSupport, storage; @@ -22,6 +22,7 @@ define([ var key = '_storageSupported'; try { + localStorage = window.localStorage; localStorage.setItem(key, 'true'); if (localStorage.getItem(key) === 'true') { From 86e0175fbd4342dfe08ae55b7c8b504fff0727eb Mon Sep 17 00:00:00 2001 From: Buba Suma <soumah@adobe.com> Date: Mon, 8 Jul 2019 14:34:10 -0500 Subject: [PATCH 704/773] MC-17860: Shopping cart items added to the order created in the admin - Fix changes to sidebar data should be applied only if it is intentionally submitted by the user by clicking on "Update Changes" button --- .../Controller/Adminhtml/Order/Create.php | 9 +- .../ActionGroup/AdminOrderActionGroup.xml | 8 ++ .../AdminOrderFormShoppingCartSection.xml | 15 +++ ...OrderWithSelectedShoppingCartItemsTest.xml | 103 ++++++++++++++++++ 4 files changed, 133 insertions(+), 2 deletions(-) create mode 100644 app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormShoppingCartSection.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderWithSelectedShoppingCartItemsTest.xml diff --git a/app/code/Magento/Sales/Controller/Adminhtml/Order/Create.php b/app/code/Magento/Sales/Controller/Adminhtml/Order/Create.php index b8567cee866f6..6058523ac584c 100644 --- a/app/code/Magento/Sales/Controller/Adminhtml/Order/Create.php +++ b/app/code/Magento/Sales/Controller/Adminhtml/Order/Create.php @@ -20,6 +20,10 @@ */ abstract class Create extends \Magento\Backend\App\Action { + /** + * Indicates how to process post data + */ + private const ACTION_SAVE = 'save'; /** * @var \Magento\Framework\Escaper */ @@ -209,7 +213,7 @@ protected function _processActionData($action = null) /** * Apply mass changes from sidebar */ - if ($data = $this->getRequest()->getPost('sidebar')) { + if (($data = $this->getRequest()->getPost('sidebar')) && $action !== self::ACTION_SAVE) { $this->_getOrderCreateModel()->applySidebarData($data); } @@ -225,7 +229,8 @@ protected function _processActionData($action = null) /** * Adding products to quote from special grid */ - if ($this->getRequest()->has('item') && !$this->getRequest()->getPost('update_items') && !($action == 'save') + if ($this->getRequest()->has('item') && !$this->getRequest()->getPost('update_items') + && $action !== self::ACTION_SAVE ) { $items = $this->getRequest()->getPost('item'); $items = $this->_processFiles($items); diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOrderActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOrderActionGroup.xml index bf04d88fcb818..58e35745ead53 100644 --- a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOrderActionGroup.xml +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOrderActionGroup.xml @@ -377,6 +377,14 @@ <see selector="{{AdminOrderDetailsInformationSection.orderStatus}}" userInput="{{orderStatus}}" stepKey="seeOrderStatusCanceled"/> </actionGroup> + <!--Assert that the product is not in the order items list--> + <actionGroup name="dontSeeProductInItemsOrdered"> + <arguments> + <argument name="product"/> + </arguments> + <dontSee selector="{{AdminOrderItemsOrderedSection.productSkuColumn}}" userInput="{{product.sku}}" stepKey="dontseeSkuInItemsOrdered"/> + </actionGroup> + <!--Select Check Money payment method--> <actionGroup name="SelectCheckMoneyPaymentMethod"> <waitForElementVisible selector="{{AdminOrderFormPaymentSection.paymentBlock}}" stepKey="waitForPaymentOptions"/> diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormShoppingCartSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormShoppingCartSection.xml new file mode 100644 index 0000000000000..020d41e78c8ef --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormShoppingCartSection.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="AdminOrderFormShoppingCartSection"> + <element name="addProduct" type="button" selector="//div[@id='sidebar_data_cart']//tr[td[contains(.,'{{name}}')]]//input[contains(@name,'[add_cart_item]')]" timeout="30" parameterized="true"/> + <element name="removeProduct" type="button" selector="//div[@id='sidebar_data_cart']//tr[td[contains(.,'{{name}}')]]//input[contains(@name,'[remove]')]" timeout="30" parameterized="true"/> + </section> +</sections> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderWithSelectedShoppingCartItemsTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderWithSelectedShoppingCartItemsTest.xml new file mode 100644 index 0000000000000..513fcd7fd2699 --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderWithSelectedShoppingCartItemsTest.xml @@ -0,0 +1,103 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AdminCreateOrderWithSelectedShoppingCartItemsTest"> + <annotations> + <title value="Shopping cart items must not be added to the order unless they were moved manually"/> + <stories value="MC-17838: Shopping cart items added to the order created in the admin"/> + <description value="Shopping cart items must not be added to the order unless they were moved manually"/> + <features value="Sales"/> + <severity value="AVERAGE"/> + <group value="Sales"/> + </annotations> + <before> + <!--Set default flat rate shipping method settings--> + <magentoCLI command="config:set {{EnableFlatRateConfigData.path}} {{EnableFlatRateConfigData.value}}" stepKey="enableFlatRate"/> + + <!--Create customer--> + <createData entity="Simple_US_CA_Customer" stepKey="simpleCustomer"/> + + <!--Create category--> + <createData entity="_defaultCategory" stepKey="category1"/> + + <!--Create product1--> + <createData entity="_defaultProduct" stepKey="product1"> + <requiredEntity createDataKey="category1"/> + </createData> + + <!--Create product2--> + <createData entity="_defaultProduct" stepKey="product2"> + <requiredEntity createDataKey="category1"/> + </createData> + + <!--Login as admin--> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + </before> + + <!-- Step 1: Go to Storefront as Customer --> + <actionGroup ref="LoginToStorefrontActionGroup" stepKey="customerLogin"> + <argument name="Customer" value="$$simpleCustomer$$" /> + </actionGroup> + + <!-- Step 2: Add product to cart --> + <amOnPage url="{{StorefrontProductPage.url($$product1.custom_attributes[url_key]$)}}" stepKey="amOnPage"/> + <actionGroup ref="StorefrontAddProductToCartActionGroup" stepKey="addProductToCart"> + <argument name="product" value="$$product1$$"/> + <argument name="productCount" value="1"/> + </actionGroup> + + <!--Step 3: Create new customer order--> + <actionGroup ref="navigateToNewOrderPageExistingCustomer" stepKey="navigateToNewOrderWithExistingCustomer"> + <argument name="customer" value="$$simpleCustomer$$"/> + </actionGroup> + + <!--Step 4: Add product2 to the order--> + <actionGroup ref="addSimpleProductToOrder" stepKey="addSimpleProductToOrder"> + <argument name="product" value="$$product2$$"/> + </actionGroup> + + <!--Step 5: Select product1 in the shopping cart--> + <click selector="{{AdminOrderFormShoppingCartSection.addProduct($$product1.name$$)}}" stepKey="selectProduct1InTheShoppingCart"/> + + <!--Step 6: Select FlatRate shipping method--> + <actionGroup ref="orderSelectFlatRateShipping" stepKey="orderSelectFlatRateShippingMethod"/> + + <!--Step 7: Submit order--> + <actionGroup ref="AdminSubmitOrderActionGroup" stepKey="submitOrder"/> + + <!--Step 8: Verify order information--> + <actionGroup ref="verifyCreatedOrderInformation" stepKey="verifyCreatedOrderInformation"/> + + <!--Step 9: Check that product 2 is in the order items list --> + <actionGroup ref="seeProductInItemsOrdered" stepKey="seeProduct2InItemsOrdered"> + <argument name="product" value="$$product2$$"/> + </actionGroup> + + <!--Step 10: Check that product 1 is not in the order items list --> + <actionGroup ref="dontSeeProductInItemsOrdered" stepKey="dontSeeProduct1InItemsOrdered"> + <argument name="product" value="$$product1$$"/> + </actionGroup> + <after> + <!--Delete product1--> + <deleteData createDataKey="product1" stepKey="deleteProduct1"/> + + <!--Delete product2--> + <deleteData createDataKey="product2" stepKey="deleteProduct2"/> + + <!--Delete category--> + <deleteData createDataKey="category1" stepKey="deleteCategory1"/> + + <!--Delete customer--> + <deleteData createDataKey="simpleCustomer" stepKey="deleteSimpleCustomer"/> + + <!--Logout--> + <actionGroup ref="logout" stepKey="logout"/> + </after> + </test> +</tests> From 863ec2ebe29bc1c707383f05c37ebcfeb8437f94 Mon Sep 17 00:00:00 2001 From: "rostyslav.hymon" <rostyslav.hymon@transoftgroup.com> Date: Wed, 17 Jul 2019 10:42:48 +0300 Subject: [PATCH 705/773] MC-18193: All Sales emails are being copied to the same customer when sales_emails cron has an error --- .../Mail/Template/TransportBuilder.php | 4 +-- .../Unit/Template/TransportBuilderTest.php | 28 +++++++++++++++++++ 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php b/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php index 85c941f5dfedb..7bef92af57da9 100644 --- a/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php +++ b/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php @@ -264,11 +264,9 @@ public function getTransport() try { $this->prepareMessage(); $mailTransport = $this->mailTransportFactory->create(['message' => clone $this->message]); - } catch (LocalizedException $e) { + } finally { $this->reset(); - throw $e; } - $this->reset(); return $mailTransport; } diff --git a/lib/internal/Magento/Framework/Mail/Test/Unit/Template/TransportBuilderTest.php b/lib/internal/Magento/Framework/Mail/Test/Unit/Template/TransportBuilderTest.php index 5e3309af6497b..c9781281d353d 100644 --- a/lib/internal/Magento/Framework/Mail/Test/Unit/Template/TransportBuilderTest.php +++ b/lib/internal/Magento/Framework/Mail/Test/Unit/Template/TransportBuilderTest.php @@ -143,6 +143,34 @@ public function testGetTransport($templateType, $messageType, $bodyText, $templa $this->assertInstanceOf(\Magento\Framework\Mail\TransportInterface::class, $this->builder->getTransport()); } + /** + * Test get transport with exception + * + * @expectedException \Magento\Framework\Exception\LocalizedException + * @expectedExceptionMessage Unknown template type + */ + public function testGetTransportWithException() + { + $this->builder->setTemplateModel('Test\Namespace\Template'); + + $vars = ['reason' => 'Reason', 'customer' => 'Customer']; + $options = ['area' => 'frontend', 'store' => 1]; + + $template = $this->createMock(\Magento\Framework\Mail\TemplateInterface::class); + $template->expects($this->once())->method('setVars')->with($this->equalTo($vars))->willReturnSelf(); + $template->expects($this->once())->method('setOptions')->with($this->equalTo($options))->willReturnSelf(); + $template->expects($this->once())->method('getType')->willReturn('Unknown'); + $this->messageFactoryMock->expects($this->once())->method('create'); + $this->templateFactoryMock->expects($this->once()) + ->method('get') + ->with($this->equalTo('identifier'), $this->equalTo('Test\Namespace\Template')) + ->willReturn($template); + + $this->builder->setTemplateIdentifier('identifier')->setTemplateVars($vars)->setTemplateOptions($options); + + $this->assertInstanceOf(\Magento\Framework\Mail\TransportInterface::class, $this->builder->getTransport()); + } + /** * @return array */ From e0075aa1623b299f63719a1429e346c95cd9af5c Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <engcom-vendorworker-foxtrot@adobe.com> Date: Tue, 16 Jul 2019 11:51:14 +0300 Subject: [PATCH 706/773] magento/magento2#22891: Static tests fix. --- .../Reader/Source/Deployed/SettingChecker.php | 18 +++++++++--------- .../Source/Deployed/SettingCheckerTest.php | 17 ++++++++++++----- 2 files changed, 21 insertions(+), 14 deletions(-) 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 index 5560884c2d722..0d56aca14fb0a 100644 --- a/app/code/Magento/Config/Model/Config/Reader/Source/Deployed/SettingChecker.php +++ b/app/code/Magento/Config/Model/Config/Reader/Source/Deployed/SettingChecker.php @@ -5,12 +5,11 @@ */ 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\Config\Model\Placeholder\PlaceholderInterface; use Magento\Framework\App\Config\ScopeCodeResolver; +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Framework\App\DeploymentConfig; /** * Class for checking settings that defined in config file @@ -65,13 +64,13 @@ public function isReadOnly($path, $scope, $scopeCode = null) ); if (null === $config) { - $config = $this->config->get( - $this->resolvePath(ScopeConfigInterface::SCOPE_TYPE_DEFAULT, null) . "/" . $path - ); + $config = $this->config->get($this->resolvePath($scope, $scopeCode) . "/" . $path); } if (null === $config) { - $config = $this->config->get($this->resolvePath($scope, $scopeCode) . "/" . $path); + $config = $this->config->get( + $this->resolvePath(ScopeConfigInterface::SCOPE_TYPE_DEFAULT, null) . "/" . $path + ); } return $config !== null; @@ -84,7 +83,6 @@ public function isReadOnly($path, $scope, $scopeCode = null) * * @param string $path * @param string $scope - * @param string $scopeCode * @param string|null $scopeCode * @return string|null * @since 100.1.2 @@ -103,9 +101,11 @@ public function getPlaceholderValue($path, $scope, $scopeCode = null) */ public function getEnvValue($placeholder) { + // phpcs:disable Magento2.Security.Superglobal if ($this->placeholder->isApplicable($placeholder) && isset($_ENV[$placeholder])) { return $_ENV[$placeholder]; } + // phpcs:enable return null; } 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 index ce2131e061727..d7323b1eef0cd 100644 --- 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 @@ -3,14 +3,14 @@ * Copyright © Magento, Inc. 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\Config\Model\Placeholder\PlaceholderFactory; +use Magento\Config\Model\Placeholder\PlaceholderInterface; 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 @@ -75,8 +75,15 @@ public function setUp() * @param bool $expectedResult * @dataProvider isReadonlyDataProvider */ - public function testIsReadonly($path, $scope, $scopeCode, $confValue, array $variables, array $configMap, $expectedResult) - { + public function testIsReadonly( + $path, + $scope, + $scopeCode, + $confValue, + array $variables, + array $configMap, + $expectedResult + ) { $this->placeholderMock->expects($this->any()) ->method('isApplicable') ->willReturn(true); From 8bd4141b97ab001b0099b89c8692655f4fcae9ea Mon Sep 17 00:00:00 2001 From: Dmytro Horytskyi <horytsky@adobe.com> Date: Wed, 17 Jul 2019 10:44:21 -0500 Subject: [PATCH 707/773] MAGETWO-99439: Exteremly slow removing from memory tables in GaleraDb --- .../Patch/Schema/ChangeTmpTablesEngine.php | 62 +++++++++++++++++ .../Patch/Schema/ChangeTmpTablesEngine.php | 68 +++++++++++++++++++ .../Patch/Schema/ChangeTmpTablesEngine.php | 55 +++++++++++++++ .../Patch/Schema/ChangeTmpTablesEngine.php | 55 +++++++++++++++ 4 files changed, 240 insertions(+) create mode 100644 app/code/Magento/Bundle/Setup/Patch/Schema/ChangeTmpTablesEngine.php create mode 100644 app/code/Magento/Catalog/Setup/Patch/Schema/ChangeTmpTablesEngine.php create mode 100644 app/code/Magento/CatalogInventory/Setup/Patch/Schema/ChangeTmpTablesEngine.php create mode 100644 app/code/Magento/Downloadable/Setup/Patch/Schema/ChangeTmpTablesEngine.php diff --git a/app/code/Magento/Bundle/Setup/Patch/Schema/ChangeTmpTablesEngine.php b/app/code/Magento/Bundle/Setup/Patch/Schema/ChangeTmpTablesEngine.php new file mode 100644 index 0000000000000..87ff3d8966f82 --- /dev/null +++ b/app/code/Magento/Bundle/Setup/Patch/Schema/ChangeTmpTablesEngine.php @@ -0,0 +1,62 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Bundle\Setup\Patch\Schema; + +use Magento\Framework\Setup\Patch\SchemaPatchInterface; +use Magento\Framework\Setup\SchemaSetupInterface; + +class ChangeTmpTablesEngine implements SchemaPatchInterface +{ + /** + * @var SchemaSetupInterface + */ + private $schemaSetup; + + /** + * @param SchemaSetupInterface $schemaSetup + */ + public function __construct(SchemaSetupInterface $schemaSetup) + { + $this->schemaSetup = $schemaSetup; + } + + /** + * @inheritdoc + */ + public function apply() + { + $this->schemaSetup->startSetup(); + + $tables = [ + 'catalog_product_index_price_bundle_tmp', + 'catalog_product_index_price_bundle_sel_tmp', + 'catalog_product_index_price_bundle_opt_tmp', + ]; + foreach ($tables as $table) { + $this->schemaSetup->getConnection()->changeTableEngine($table, 'InnoDB'); + } + + $this->schemaSetup->endSetup(); + } + + /** + * @inheritdoc + */ + public static function getDependencies() + { + return []; + } + + /** + * @inheritdoc + */ + public function getAliases() + { + return []; + } +} diff --git a/app/code/Magento/Catalog/Setup/Patch/Schema/ChangeTmpTablesEngine.php b/app/code/Magento/Catalog/Setup/Patch/Schema/ChangeTmpTablesEngine.php new file mode 100644 index 0000000000000..a9ec22ab664a9 --- /dev/null +++ b/app/code/Magento/Catalog/Setup/Patch/Schema/ChangeTmpTablesEngine.php @@ -0,0 +1,68 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Catalog\Setup\Patch\Schema; + +use Magento\Framework\Setup\Patch\SchemaPatchInterface; +use Magento\Framework\Setup\SchemaSetupInterface; + +class ChangeTmpTablesEngine implements SchemaPatchInterface +{ + /** + * @var SchemaSetupInterface + */ + private $schemaSetup; + + /** + * @param SchemaSetupInterface $schemaSetup + */ + public function __construct(SchemaSetupInterface $schemaSetup) + { + $this->schemaSetup = $schemaSetup; + } + + /** + * @inheritdoc + */ + public function apply() + { + $this->schemaSetup->startSetup(); + + $tables = [ + 'catalog_product_index_price_cfg_opt_agr_tmp', + 'catalog_product_index_price_cfg_opt_tmp', + 'catalog_product_index_price_final_tmp', + 'catalog_product_index_price_opt_tmp', + 'catalog_product_index_price_opt_agr_tmp', + 'catalog_product_index_eav_tmp', + 'catalog_product_index_eav_decimal_tmp', + 'catalog_product_index_price_tmp', + 'catalog_category_product_index_tmp', + ]; + foreach ($tables as $table) { + $this->schemaSetup->getConnection()->changeTableEngine($table, 'InnoDB'); + } + + $this->schemaSetup->endSetup(); + } + + /** + * @inheritdoc + */ + public static function getDependencies() + { + return []; + } + + /** + * @inheritdoc + */ + public function getAliases() + { + return []; + } +} diff --git a/app/code/Magento/CatalogInventory/Setup/Patch/Schema/ChangeTmpTablesEngine.php b/app/code/Magento/CatalogInventory/Setup/Patch/Schema/ChangeTmpTablesEngine.php new file mode 100644 index 0000000000000..fbeba9f483b1a --- /dev/null +++ b/app/code/Magento/CatalogInventory/Setup/Patch/Schema/ChangeTmpTablesEngine.php @@ -0,0 +1,55 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\CatalogInventory\Setup\Patch\Schema; + +use Magento\Framework\Setup\Patch\SchemaPatchInterface; +use Magento\Framework\Setup\SchemaSetupInterface; + +class ChangeTmpTablesEngine implements SchemaPatchInterface +{ + /** + * @var SchemaSetupInterface + */ + private $schemaSetup; + + /** + * @param SchemaSetupInterface $schemaSetup + */ + public function __construct(SchemaSetupInterface $schemaSetup) + { + $this->schemaSetup = $schemaSetup; + } + + /** + * @inheritdoc + */ + public function apply() + { + $this->schemaSetup->startSetup(); + + $this->schemaSetup->getConnection()->changeTableEngine('cataloginventory_stock_status_tmp', 'InnoDB'); + + $this->schemaSetup->endSetup(); + } + + /** + * @inheritdoc + */ + public static function getDependencies() + { + return []; + } + + /** + * @inheritdoc + */ + public function getAliases() + { + return []; + } +} diff --git a/app/code/Magento/Downloadable/Setup/Patch/Schema/ChangeTmpTablesEngine.php b/app/code/Magento/Downloadable/Setup/Patch/Schema/ChangeTmpTablesEngine.php new file mode 100644 index 0000000000000..90e1ddf87f8a3 --- /dev/null +++ b/app/code/Magento/Downloadable/Setup/Patch/Schema/ChangeTmpTablesEngine.php @@ -0,0 +1,55 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Downloadable\Setup\Patch\Schema; + +use Magento\Framework\Setup\Patch\SchemaPatchInterface; +use Magento\Framework\Setup\SchemaSetupInterface; + +class ChangeTmpTablesEngine implements SchemaPatchInterface +{ + /** + * @var SchemaSetupInterface + */ + private $schemaSetup; + + /** + * @param SchemaSetupInterface $schemaSetup + */ + public function __construct(SchemaSetupInterface $schemaSetup) + { + $this->schemaSetup = $schemaSetup; + } + + /** + * @inheritdoc + */ + public function apply() + { + $this->schemaSetup->startSetup(); + + $this->schemaSetup->getConnection()->changeTableEngine('catalog_product_index_price_downlod_tmp', 'InnoDB'); + + $this->schemaSetup->endSetup(); + } + + /** + * @inheritdoc + */ + public static function getDependencies() + { + return []; + } + + /** + * @inheritdoc + */ + public function getAliases() + { + return []; + } +} From ad61ec2b044a9f84c77650b4aa96577072c3578f Mon Sep 17 00:00:00 2001 From: Dmytro Horytskyi <horytsky@adobe.com> Date: Wed, 17 Jul 2019 11:26:00 -0500 Subject: [PATCH 708/773] MAGETWO-99439: Exteremly slow removing from memory tables in GaleraDb --- .../Bundle/Setup/Patch/Schema/ChangeTmpTablesEngine.php | 3 +++ .../Catalog/Setup/Patch/Schema/ChangeTmpTablesEngine.php | 3 +++ .../Setup/Patch/Schema/ChangeTmpTablesEngine.php | 3 +++ .../Downloadable/Setup/Patch/Schema/ChangeTmpTablesEngine.php | 3 +++ 4 files changed, 12 insertions(+) diff --git a/app/code/Magento/Bundle/Setup/Patch/Schema/ChangeTmpTablesEngine.php b/app/code/Magento/Bundle/Setup/Patch/Schema/ChangeTmpTablesEngine.php index 87ff3d8966f82..adb178796f88d 100644 --- a/app/code/Magento/Bundle/Setup/Patch/Schema/ChangeTmpTablesEngine.php +++ b/app/code/Magento/Bundle/Setup/Patch/Schema/ChangeTmpTablesEngine.php @@ -10,6 +10,9 @@ use Magento\Framework\Setup\Patch\SchemaPatchInterface; use Magento\Framework\Setup\SchemaSetupInterface; +/** + * Change engine for temporary tables to InnoDB. + */ class ChangeTmpTablesEngine implements SchemaPatchInterface { /** diff --git a/app/code/Magento/Catalog/Setup/Patch/Schema/ChangeTmpTablesEngine.php b/app/code/Magento/Catalog/Setup/Patch/Schema/ChangeTmpTablesEngine.php index a9ec22ab664a9..39e2e0cb0963c 100644 --- a/app/code/Magento/Catalog/Setup/Patch/Schema/ChangeTmpTablesEngine.php +++ b/app/code/Magento/Catalog/Setup/Patch/Schema/ChangeTmpTablesEngine.php @@ -10,6 +10,9 @@ use Magento\Framework\Setup\Patch\SchemaPatchInterface; use Magento\Framework\Setup\SchemaSetupInterface; +/** + * Change engine for temporary tables to InnoDB. + */ class ChangeTmpTablesEngine implements SchemaPatchInterface { /** diff --git a/app/code/Magento/CatalogInventory/Setup/Patch/Schema/ChangeTmpTablesEngine.php b/app/code/Magento/CatalogInventory/Setup/Patch/Schema/ChangeTmpTablesEngine.php index fbeba9f483b1a..27a70d0c908fe 100644 --- a/app/code/Magento/CatalogInventory/Setup/Patch/Schema/ChangeTmpTablesEngine.php +++ b/app/code/Magento/CatalogInventory/Setup/Patch/Schema/ChangeTmpTablesEngine.php @@ -10,6 +10,9 @@ use Magento\Framework\Setup\Patch\SchemaPatchInterface; use Magento\Framework\Setup\SchemaSetupInterface; +/** + * Change engine for temporary tables to InnoDB. + */ class ChangeTmpTablesEngine implements SchemaPatchInterface { /** diff --git a/app/code/Magento/Downloadable/Setup/Patch/Schema/ChangeTmpTablesEngine.php b/app/code/Magento/Downloadable/Setup/Patch/Schema/ChangeTmpTablesEngine.php index 90e1ddf87f8a3..37c6a96542e2e 100644 --- a/app/code/Magento/Downloadable/Setup/Patch/Schema/ChangeTmpTablesEngine.php +++ b/app/code/Magento/Downloadable/Setup/Patch/Schema/ChangeTmpTablesEngine.php @@ -10,6 +10,9 @@ use Magento\Framework\Setup\Patch\SchemaPatchInterface; use Magento\Framework\Setup\SchemaSetupInterface; +/** + * Change engine for temporary tables to InnoDB. + */ class ChangeTmpTablesEngine implements SchemaPatchInterface { /** From 7c5ad0be8ccfa580c4234db2e39e9bfbc0f6cde9 Mon Sep 17 00:00:00 2001 From: Krissy Hiserote <khiserote@magento.com> Date: Wed, 17 Jul 2019 15:13:09 -0500 Subject: [PATCH 709/773] MC-15776: Merge release branch into 2.3-develop - fix composer lock file --- composer.lock | 112 +++++++++++++++++++++++++------------------------- 1 file changed, 56 insertions(+), 56 deletions(-) diff --git a/composer.lock b/composer.lock index 158aa76a36fff..6b1eaee8f25e6 100644 --- a/composer.lock +++ b/composer.lock @@ -1567,16 +1567,16 @@ }, { "name": "phpseclib/phpseclib", - "version": "2.0.20", + "version": "2.0.18", "source": { "type": "git", "url": "https://github.com/phpseclib/phpseclib.git", - "reference": "d6819a55b05e123db1e881d8b230d57f912126be" + "reference": "60519001db8d791215a822efd366d24cafee9e63" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/d6819a55b05e123db1e881d8b230d57f912126be", - "reference": "d6819a55b05e123db1e881d8b230d57f912126be", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/60519001db8d791215a822efd366d24cafee9e63", + "reference": "60519001db8d791215a822efd366d24cafee9e63", "shasum": "" }, "require": { @@ -1655,7 +1655,7 @@ "x.509", "x509" ], - "time": "2019-06-23T16:33:11+00:00" + "time": "2019-06-13T06:15:54+00:00" }, { "name": "psr/container", @@ -2137,7 +2137,7 @@ }, { "name": "symfony/css-selector", - "version": "v4.3.2", + "version": "v4.3.1", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", @@ -2253,16 +2253,16 @@ }, { "name": "symfony/filesystem", - "version": "v4.3.2", + "version": "v4.3.1", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "b9896d034463ad6fd2bf17e2bf9418caecd6313d" + "reference": "bf2af40d738dec5e433faea7b00daa4431d0a4cf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/b9896d034463ad6fd2bf17e2bf9418caecd6313d", - "reference": "b9896d034463ad6fd2bf17e2bf9418caecd6313d", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/bf2af40d738dec5e433faea7b00daa4431d0a4cf", + "reference": "bf2af40d738dec5e433faea7b00daa4431d0a4cf", "shasum": "" }, "require": { @@ -2299,20 +2299,20 @@ ], "description": "Symfony Filesystem Component", "homepage": "https://symfony.com", - "time": "2019-06-23T08:51:25+00:00" + "time": "2019-06-03T20:27:40+00:00" }, { "name": "symfony/finder", - "version": "v4.3.2", + "version": "v4.3.1", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "33c21f7d5d3dc8a140c282854a7e13aeb5d0f91a" + "reference": "b3d4f4c0e4eadfdd8b296af9ca637cfbf51d8176" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/33c21f7d5d3dc8a140c282854a7e13aeb5d0f91a", - "reference": "33c21f7d5d3dc8a140c282854a7e13aeb5d0f91a", + "url": "https://api.github.com/repos/symfony/finder/zipball/b3d4f4c0e4eadfdd8b296af9ca637cfbf51d8176", + "reference": "b3d4f4c0e4eadfdd8b296af9ca637cfbf51d8176", "shasum": "" }, "require": { @@ -2348,7 +2348,7 @@ ], "description": "Symfony Finder Component", "homepage": "https://symfony.com", - "time": "2019-06-13T11:03:18+00:00" + "time": "2019-05-26T20:47:49+00:00" }, { "name": "symfony/polyfill-ctype", @@ -8674,16 +8674,16 @@ }, { "name": "symfony/browser-kit", - "version": "v4.3.2", + "version": "v4.3.1", "source": { "type": "git", "url": "https://github.com/symfony/browser-kit.git", - "reference": "a29dd02a1f3f81b9a15c7730cc3226718ddb55ca" + "reference": "e07d50e84b8cf489590f22244f4f609579b4a2c4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/browser-kit/zipball/a29dd02a1f3f81b9a15c7730cc3226718ddb55ca", - "reference": "a29dd02a1f3f81b9a15c7730cc3226718ddb55ca", + "url": "https://api.github.com/repos/symfony/browser-kit/zipball/e07d50e84b8cf489590f22244f4f609579b4a2c4", + "reference": "e07d50e84b8cf489590f22244f4f609579b4a2c4", "shasum": "" }, "require": { @@ -8729,20 +8729,20 @@ ], "description": "Symfony BrowserKit Component", "homepage": "https://symfony.com", - "time": "2019-06-11T15:41:59+00:00" + "time": "2019-05-30T16:10:05+00:00" }, { "name": "symfony/config", - "version": "v4.3.2", + "version": "v4.3.1", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "9198eea354be75794a7b1064de00d9ae9ae5090f" + "reference": "6379ee07398643e09e6ed1e87d9c62dfcad7f4eb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/9198eea354be75794a7b1064de00d9ae9ae5090f", - "reference": "9198eea354be75794a7b1064de00d9ae9ae5090f", + "url": "https://api.github.com/repos/symfony/config/zipball/6379ee07398643e09e6ed1e87d9c62dfcad7f4eb", + "reference": "6379ee07398643e09e6ed1e87d9c62dfcad7f4eb", "shasum": "" }, "require": { @@ -8793,20 +8793,20 @@ ], "description": "Symfony Config Component", "homepage": "https://symfony.com", - "time": "2019-06-08T06:33:08+00:00" + "time": "2019-05-30T16:10:05+00:00" }, { "name": "symfony/dependency-injection", - "version": "v4.3.2", + "version": "v4.3.1", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "b851928be349c065197fdc0832f78d85139e3903" + "reference": "fea7f73e278ee0337349a5a68b867fc656bb33f3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/b851928be349c065197fdc0832f78d85139e3903", - "reference": "b851928be349c065197fdc0832f78d85139e3903", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/fea7f73e278ee0337349a5a68b867fc656bb33f3", + "reference": "fea7f73e278ee0337349a5a68b867fc656bb33f3", "shasum": "" }, "require": { @@ -8866,20 +8866,20 @@ ], "description": "Symfony DependencyInjection Component", "homepage": "https://symfony.com", - "time": "2019-06-15T04:08:07+00:00" + "time": "2019-05-30T16:10:05+00:00" }, { "name": "symfony/dom-crawler", - "version": "v4.3.2", + "version": "v4.3.1", "source": { "type": "git", "url": "https://github.com/symfony/dom-crawler.git", - "reference": "291397232a2eefb3347eaab9170409981eaad0e2" + "reference": "06ee58fbc9a8130f1d35b5280e15235a0515d457" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/291397232a2eefb3347eaab9170409981eaad0e2", - "reference": "291397232a2eefb3347eaab9170409981eaad0e2", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/06ee58fbc9a8130f1d35b5280e15235a0515d457", + "reference": "06ee58fbc9a8130f1d35b5280e15235a0515d457", "shasum": "" }, "require": { @@ -8927,20 +8927,20 @@ ], "description": "Symfony DomCrawler Component", "homepage": "https://symfony.com", - "time": "2019-06-13T11:03:18+00:00" + "time": "2019-05-31T18:55:30+00:00" }, { "name": "symfony/http-foundation", - "version": "v4.3.2", + "version": "v4.3.1", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "e1b507fcfa4e87d192281774b5ecd4265370180d" + "reference": "b7e4945dd9b277cd24e93566e4da0a87956392a9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/e1b507fcfa4e87d192281774b5ecd4265370180d", - "reference": "e1b507fcfa4e87d192281774b5ecd4265370180d", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/b7e4945dd9b277cd24e93566e4da0a87956392a9", + "reference": "b7e4945dd9b277cd24e93566e4da0a87956392a9", "shasum": "" }, "require": { @@ -8982,11 +8982,11 @@ ], "description": "Symfony HttpFoundation Component", "homepage": "https://symfony.com", - "time": "2019-06-26T09:25:00+00:00" + "time": "2019-06-06T10:05:02+00:00" }, { "name": "symfony/mime", - "version": "v4.3.2", + "version": "v4.3.1", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", @@ -9045,16 +9045,16 @@ }, { "name": "symfony/options-resolver", - "version": "v4.3.2", + "version": "v4.3.1", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "40762ead607c8f792ee4516881369ffa553fee6f" + "reference": "914e0edcb7cd0c9f494bc023b1d47534f4542332" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/40762ead607c8f792ee4516881369ffa553fee6f", - "reference": "40762ead607c8f792ee4516881369ffa553fee6f", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/914e0edcb7cd0c9f494bc023b1d47534f4542332", + "reference": "914e0edcb7cd0c9f494bc023b1d47534f4542332", "shasum": "" }, "require": { @@ -9095,7 +9095,7 @@ "configuration", "options" ], - "time": "2019-06-13T11:01:17+00:00" + "time": "2019-05-10T05:38:46+00:00" }, { "name": "symfony/polyfill-intl-idn", @@ -9275,23 +9275,23 @@ }, { "name": "symfony/service-contracts", - "version": "v1.1.5", + "version": "v1.1.2", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "f391a00de78ec7ec8cf5cdcdae59ec7b883edb8d" + "reference": "191afdcb5804db960d26d8566b7e9a2843cab3a0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f391a00de78ec7ec8cf5cdcdae59ec7b883edb8d", - "reference": "f391a00de78ec7ec8cf5cdcdae59ec7b883edb8d", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/191afdcb5804db960d26d8566b7e9a2843cab3a0", + "reference": "191afdcb5804db960d26d8566b7e9a2843cab3a0", "shasum": "" }, "require": { - "php": "^7.1.3", - "psr/container": "^1.0" + "php": "^7.1.3" }, "suggest": { + "psr/container": "", "symfony/service-implementation": "" }, "type": "library", @@ -9329,11 +9329,11 @@ "interoperability", "standards" ], - "time": "2019-06-13T11:15:36+00:00" + "time": "2019-05-28T07:50:59+00:00" }, { "name": "symfony/stopwatch", - "version": "v4.3.2", + "version": "v4.3.1", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", @@ -9383,7 +9383,7 @@ }, { "name": "symfony/yaml", - "version": "v3.4.29", + "version": "v3.4.28", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", From a303ce89133fddcc9a2cc2b5d50eac5c76f800af Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun <ogorkun@magento.com> Date: Wed, 17 Jul 2019 15:26:07 -0500 Subject: [PATCH 710/773] MC-17489: Require specific suffix for HTML binding --- .../Magento/Sniffs/Html/HtmlBindingSniff.php | 21 ++++++++++++++++--- .../Html/_files/test-html-binding-errors.txt | 14 +++++++++---- .../Sniffs/Html/_files/test-html-binding.html | 16 ++++++++++++-- 3 files changed, 42 insertions(+), 9 deletions(-) diff --git a/dev/tests/static/framework/Magento/Sniffs/Html/HtmlBindingSniff.php b/dev/tests/static/framework/Magento/Sniffs/Html/HtmlBindingSniff.php index 02ade2ccb870e..ff79bddd4202f 100644 --- a/dev/tests/static/framework/Magento/Sniffs/Html/HtmlBindingSniff.php +++ b/dev/tests/static/framework/Magento/Sniffs/Html/HtmlBindingSniff.php @@ -41,15 +41,30 @@ public function process(File $phpcsFile, $stackPtr) $loaded = false; } if ($loaded) { + /** @var string[] $htmlBindings */ + $htmlBindings = []; $domXpath = new \DOMXPath($dom); $dataBindAttributes = $domXpath->query('//@*[name() = "data-bind"]'); foreach ($dataBindAttributes as $dataBindAttribute) { $knockoutBinding = $dataBindAttribute->nodeValue; - preg_match('/^(.+\s*?)?html\s*?\:\s*?([a-z0-9\.\(\)\_]+)/ims', $knockoutBinding, $htmlBinding); - if ($htmlBinding && !preg_match('/UnsanitizedHtml[\(\)]*?$/', $htmlBinding[2])) { + preg_match('/^(.+\s*?)?html\s*?\:(.+)/ims', $knockoutBinding, $htmlBindingStart); + if ($htmlBindingStart) { + $htmlBinding = trim(preg_replace('/\,[a-z0-9\_\s]+\:.+/ims', '', $htmlBindingStart[2])); + $htmlBindings[] = $htmlBinding; + } + } + $htmlAttributes = $domXpath->query('//@*[name() = "html"]'); + foreach ($htmlAttributes as $htmlAttribute) { + $magentoBinding = $htmlAttribute->nodeValue; + $htmlBindings[] = trim($magentoBinding); + } + foreach ($htmlBindings as $htmlBinding) { + if (!preg_match('/^[0-9\\\'\"]/ims', $htmlBinding) + && !preg_match('/UnsanitizedHtml(\(.*?\))*?$/', $htmlBinding) + ) { $phpcsFile->addError( 'Variables/functions used for HTML binding must have UnsanitizedHtml suffix' - .' - "' .$htmlBinding[2] .'" doesn\'t,' .PHP_EOL + .' - "' .$htmlBinding .'" doesn\'t,' .PHP_EOL .'consider using text binding if the value is supposed to be text', null, 'UIComponentTemplate.KnockoutBinding.HtmlSuffix' diff --git a/dev/tests/static/framework/tests/unit/testsuite/Magento/Sniffs/Html/_files/test-html-binding-errors.txt b/dev/tests/static/framework/tests/unit/testsuite/Magento/Sniffs/Html/_files/test-html-binding-errors.txt index 6524ebed4dfb2..ee9d812788683 100644 --- a/dev/tests/static/framework/tests/unit/testsuite/Magento/Sniffs/Html/_files/test-html-binding-errors.txt +++ b/dev/tests/static/framework/tests/unit/testsuite/Magento/Sniffs/Html/_files/test-html-binding-errors.txt @@ -1,12 +1,18 @@ -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -FOUND 3 ERRORS AFFECTING 1 LINE -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +FOUND 6 ERRORS AFFECTING 1 LINE +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 1 | ERROR | Variables/functions used for HTML binding must have UnsanitizedHtml suffix - "testError()" doesn't, | | consider using text binding if the value is supposed to be text 1 | ERROR | Variables/functions used for HTML binding must have UnsanitizedHtml suffix - "test.getSomething().value.error()" doesn't, | | consider using text binding if the value is supposed to be text + 1 | ERROR | Variables/functions used for HTML binding must have UnsanitizedHtml suffix - "bind_stuff(1, 2)" doesn't, + | | consider using text binding if the value is supposed to be text + 1 | ERROR | Variables/functions used for HTML binding must have UnsanitizedHtml suffix - "testError()" doesn't, + | | consider using text binding if the value is supposed to be text + 1 | ERROR | Variables/functions used for HTML binding must have UnsanitizedHtml suffix - "test.getSomething().value.error(1)" doesn't, + | | consider using text binding if the value is supposed to be text 1 | ERROR | Variables/functions used for HTML binding must have UnsanitizedHtml suffix - "bind_stuff()" doesn't, | | consider using text binding if the value is supposed to be text -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- diff --git a/dev/tests/static/framework/tests/unit/testsuite/Magento/Sniffs/Html/_files/test-html-binding.html b/dev/tests/static/framework/tests/unit/testsuite/Magento/Sniffs/Html/_files/test-html-binding.html index d0c420ee19793..37e71322472d3 100644 --- a/dev/tests/static/framework/tests/unit/testsuite/Magento/Sniffs/Html/_files/test-html-binding.html +++ b/dev/tests/static/framework/tests/unit/testsuite/Magento/Sniffs/Html/_files/test-html-binding.html @@ -12,7 +12,19 @@ attr : tst, html: test.getSomething().value.error() "></div> -<p data-bind="html: '<b>Some html</b>'"></p> +<p data-bind="html: '<b>Some html</b>', attr: test"></p> <div data-bind="html: valueUnsanitizedHtml"></div> <div data-bind="attr: testhtml, html: valueUnsanitizedHtml()"></div> -<p data-bind="other_html: bind, html: bind_stuff()"></p> +<p data-bind="other_html: bind, html: bind_stuff(1, 2)"></p> + +<div style="tst()"></div> +<span html="testError()"></span> +<div html=" + test.getSomething().value.error(1) +"></div> +<p html="'<b>Some html</b>'"></p> +<div html="valueUnsanitizedHtml"></div> +<div html=" +valueUnsanitizedHtml('test') +"></div> +<p html="bind_stuff()"></p> From b6bf08baa835400d4191242a1656d32fef84b59d Mon Sep 17 00:00:00 2001 From: Eden <quocviet312@gmail.com> Date: Thu, 18 Jul 2019 09:14:07 +0700 Subject: [PATCH 711/773] Add Magento\ConfigurableProduct\Pricing\Price\PriceResolverInterface to di.xml in issue23717 --- app/code/Magento/ConfigurableProduct/etc/di.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/ConfigurableProduct/etc/di.xml b/app/code/Magento/ConfigurableProduct/etc/di.xml index 8cec84abc4fea..498591fc31569 100644 --- a/app/code/Magento/ConfigurableProduct/etc/di.xml +++ b/app/code/Magento/ConfigurableProduct/etc/di.xml @@ -12,6 +12,7 @@ <preference for="Magento\ConfigurableProduct\Api\Data\OptionInterface" type="Magento\ConfigurableProduct\Model\Product\Type\Configurable\Attribute" /> <preference for="Magento\ConfigurableProduct\Api\Data\OptionValueInterface" type="Magento\ConfigurableProduct\Model\Product\Type\Configurable\OptionValue" /> <preference for="Magento\ConfigurableProduct\Api\Data\ConfigurableItemOptionValueInterface" type="Magento\ConfigurableProduct\Model\Quote\Item\ConfigurableItemOptionValue" /> + <preference for="Magento\ConfigurableProduct\Pricing\Price\PriceResolverInterface" type="Magento\ConfigurableProduct\Pricing\Price\ConfigurablePriceResolver" /> <preference for="Magento\ConfigurableProduct\Pricing\Price\ConfigurableOptionsProviderInterface" type="Magento\ConfigurableProduct\Pricing\Price\ConfigurableOptionsProvider" /> <preference for="Magento\ConfigurableProduct\Pricing\Price\LowestPriceOptionsProviderInterface" type="Magento\ConfigurableProduct\Pricing\Price\LowestPriceOptionsProvider" /> <preference for="Magento\ConfigurableProduct\Model\AttributeOptionProviderInterface" type="Magento\ConfigurableProduct\Model\AttributeOptionProvider" /> From 5223ed0226c2f176e6ffe81f039e94ef54910390 Mon Sep 17 00:00:00 2001 From: Serhii Balko <serhii.balko@transoftgroup.com> Date: Thu, 18 Jul 2019 09:38:49 +0300 Subject: [PATCH 712/773] MC-17201: Delegated account creation fails with custom attributes present in customer address --- .../Customer/Model/Delegation/Storage.php | 16 +++++++++++++++- .../Api/OrderCustomerDelegateInterfaceTest.php | 2 ++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Customer/Model/Delegation/Storage.php b/app/code/Magento/Customer/Model/Delegation/Storage.php index 71a61d59057cb..ba1c62de1ac85 100644 --- a/app/code/Magento/Customer/Model/Delegation/Storage.php +++ b/app/code/Magento/Customer/Model/Delegation/Storage.php @@ -19,6 +19,7 @@ use Magento\Customer\Model\Delegation\Data\NewOperationFactory; use Magento\Customer\Api\Data\CustomerInterfaceFactory; use Magento\Customer\Api\Data\AddressInterfaceFactory; +use Magento\Framework\Api\CustomAttributesDataInterface; use Psr\Log\LoggerInterface; /** @@ -134,9 +135,22 @@ public function consumeNewOperation() ); $addressData['region'] = $region; } - $addresses[] = $this->addressFactory->create( + + $customAttributes = []; + if (!empty($addressData[CustomAttributesDataInterface::CUSTOM_ATTRIBUTES])) { + $customAttributes = $addressData[CustomAttributesDataInterface::CUSTOM_ATTRIBUTES]; + unset($addressData[CustomAttributesDataInterface::CUSTOM_ATTRIBUTES]); + } + + $address = $this->addressFactory->create( ['data' => $addressData] ); + + foreach ($customAttributes as $attributeCode => $attributeValue) { + $address->setCustomAttribute($attributeCode, $attributeValue); + } + + $addresses[] = $address; } $customerData = $serialized['customer']; $customerData['addresses'] = $addresses; diff --git a/dev/tests/integration/testsuite/Magento/Sales/Api/OrderCustomerDelegateInterfaceTest.php b/dev/tests/integration/testsuite/Magento/Sales/Api/OrderCustomerDelegateInterfaceTest.php index cb6f4aaac07d3..d955874309afd 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/Api/OrderCustomerDelegateInterfaceTest.php +++ b/dev/tests/integration/testsuite/Magento/Sales/Api/OrderCustomerDelegateInterfaceTest.php @@ -11,6 +11,7 @@ use Magento\Customer\Api\Data\AddressInterface; use Magento\Customer\Api\Data\CustomerInterface; use Magento\Customer\Api\Data\CustomerInterfaceFactory; +use Magento\Framework\Api\AttributeInterface; use Magento\Sales\Api\Data\OrderAddressInterface; use Magento\Sales\Model\Order; use Magento\Sales\Model\OrderFactory; @@ -126,6 +127,7 @@ private function compareAddresses( /** * @magentoDbIsolation enabled * @magentoAppIsolation enabled + * @magentoDataFixture Magento/Customer/_files/attribute_user_defined_address.php * @magentoDataFixture Magento/Sales/_files/order.php * @return void */ From 52d678676ad85c09584e913cb90362b10707905f Mon Sep 17 00:00:00 2001 From: Serhii Balko <serhii.balko@transoftgroup.com> Date: Thu, 18 Jul 2019 10:54:48 +0300 Subject: [PATCH 713/773] MC-17201: Delegated account creation fails with custom attributes present in customer address --- .../Customer/Model/Delegation/Storage.php | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/app/code/Magento/Customer/Model/Delegation/Storage.php b/app/code/Magento/Customer/Model/Delegation/Storage.php index ba1c62de1ac85..d1eae3f56001c 100644 --- a/app/code/Magento/Customer/Model/Delegation/Storage.php +++ b/app/code/Magento/Customer/Model/Delegation/Storage.php @@ -101,11 +101,13 @@ public function storeNewOperation(CustomerInterface $customer, array $delegatedD } } $this->session->setCustomerFormData($customerData); - $this->session->setDelegatedNewCustomerData([ - 'customer' => $customerData, - 'addresses' => $addressesData, - 'delegated_data' => $delegatedData, - ]); + $this->session->setDelegatedNewCustomerData( + [ + 'customer' => $customerData, + 'addresses' => $addressesData, + 'delegated_data' => $delegatedData, + ] + ); } /** @@ -155,11 +157,11 @@ public function consumeNewOperation() $customerData = $serialized['customer']; $customerData['addresses'] = $addresses; - return $this->newFactory->create([ - 'customer' => $this->customerFactory->create( - ['data' => $customerData] - ), - 'additionalData' => $serialized['delegated_data'], - ]); + return $this->newFactory->create( + [ + 'customer' => $this->customerFactory->create(['data' => $customerData]), + 'additionalData' => $serialized['delegated_data'], + ] + ); } } From 377960b9679110d40d1246bbedcd17e8c33c54c5 Mon Sep 17 00:00:00 2001 From: Serhii Balko <serhii.balko@transoftgroup.com> Date: Thu, 18 Jul 2019 12:50:00 +0300 Subject: [PATCH 714/773] MC-17803: Request A Quote form not working in IE11 not support create-negotiable-quote.js --- lib/web/mage/msie/file-reader.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/web/mage/msie/file-reader.js b/lib/web/mage/msie/file-reader.js index 6d45d3a31485a..7cd519321e86c 100644 --- a/lib/web/mage/msie/file-reader.js +++ b/lib/web/mage/msie/file-reader.js @@ -23,7 +23,9 @@ define([ reader.onload = function () { var bytes, length, index; + /* eslint-disable no-undef */ bytes = new Uint8Array(reader.result); + /* eslint-enable */ length = bytes.length; for (index = 0; index < length; index++) { From c4986d0f45ce28554c1fde9f41f86f6a80f54381 Mon Sep 17 00:00:00 2001 From: Mastiuhin Olexandr <mastiuhin.olexandr@transoftgroup.com> Date: Thu, 18 Jul 2019 12:54:02 +0300 Subject: [PATCH 715/773] MC-17524: Child product is not addable to Cart from PLP if it does not have default source assigned --- .../Magento/GroupedCatalogInventory/Plugin/OutOfStockFilter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/GroupedCatalogInventory/Plugin/OutOfStockFilter.php b/app/code/Magento/GroupedCatalogInventory/Plugin/OutOfStockFilter.php index c39a332ee3022..e207bf22dbde0 100644 --- a/app/code/Magento/GroupedCatalogInventory/Plugin/OutOfStockFilter.php +++ b/app/code/Magento/GroupedCatalogInventory/Plugin/OutOfStockFilter.php @@ -51,7 +51,7 @@ public function afterPrepareForCartAdvanced(Grouped $subject, $result, DataObjec if (is_array($result) && !empty($result) && !$buyRequest->getData('super_group')) { foreach ($result as $index => $cartItem) { $productStockStatus = $this->stockRegistry->getProductStockStatus($cartItem->getId()); - if ($productStockStatus === StockStatusInterface::STATUS_OUT_OF_STOCK) { + if ($productStockStatus == StockStatusInterface::STATUS_OUT_OF_STOCK) { unset($result[$index]); } } From 33090a82524c52846ab586494dd4565e7a6dc76a Mon Sep 17 00:00:00 2001 From: Mastiuhin Olexandr <mastiuhin.olexandr@transoftgroup.com> Date: Thu, 18 Jul 2019 13:53:20 +0300 Subject: [PATCH 716/773] MC-17524: Child product is not addable to Cart from PLP if it does not have default source assigned --- .../Test/Unit/Plugin/OutOfStockFilterTest.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/GroupedCatalogInventory/Test/Unit/Plugin/OutOfStockFilterTest.php b/app/code/Magento/GroupedCatalogInventory/Test/Unit/Plugin/OutOfStockFilterTest.php index 1d685defb3e40..c7ba29d08592c 100644 --- a/app/code/Magento/GroupedCatalogInventory/Test/Unit/Plugin/OutOfStockFilterTest.php +++ b/app/code/Magento/GroupedCatalogInventory/Test/Unit/Plugin/OutOfStockFilterTest.php @@ -155,17 +155,20 @@ public function outOfStockProductDataProvider(): array return [ [ 'originalResult' => [$product1, $product2], - 'productStockStatusMap' => [[123, null, false], [321, null, true]], + 'productStockStatusMap' => [ + [123, null, StockStatusInterface::STATUS_OUT_OF_STOCK], + [321, null, StockStatusInterface::STATUS_IN_STOCK], + ], 'expectedResult' => [1 => $product2], ], [ 'originalResult' => [$product1], - 'productStockStatusMap' => [[123, null, true]], + 'productStockStatusMap' => [[123, null, StockStatusInterface::STATUS_IN_STOCK]], 'expectedResult' => [0 => $product1], ], [ 'originalResult' => $product1, - 'productStockStatusMap' => [[123, null, true]], + 'productStockStatusMap' => [[123, null, StockStatusInterface::STATUS_IN_STOCK]], 'expectedResult' => [0 => $product1], ], ]; From cea6e3727e2329760757b46fdfe96a0225f754d6 Mon Sep 17 00:00:00 2001 From: Stepan Furman <furman.stepan@gmail.com> Date: Thu, 18 Jul 2019 16:02:47 +0300 Subject: [PATCH 717/773] MC-18031: Fix static tests --- .../PageCache/ExportVarnishConfig.php | 7 +++-- app/code/Magento/PageCache/Model/Config.php | 29 ++++++++++--------- .../Model/Varnish/VclTemplateLocator.php | 5 +++- 3 files changed, 24 insertions(+), 17 deletions(-) diff --git a/app/code/Magento/PageCache/Controller/Adminhtml/PageCache/ExportVarnishConfig.php b/app/code/Magento/PageCache/Controller/Adminhtml/PageCache/ExportVarnishConfig.php index a79fcd848a58e..6d22f5be6dad3 100644 --- a/app/code/Magento/PageCache/Controller/Adminhtml/PageCache/ExportVarnishConfig.php +++ b/app/code/Magento/PageCache/Controller/Adminhtml/PageCache/ExportVarnishConfig.php @@ -1,14 +1,17 @@ <?php /** - * * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\PageCache\Controller\Adminhtml\PageCache; +use Magento\Framework\App\Action\HttpGetActionInterface; use Magento\Framework\App\Filesystem\DirectoryList; -class ExportVarnishConfig extends \Magento\Backend\App\Action +/** + * Class ExportVarnishConfig action which exports vcl config file + */ +class ExportVarnishConfig extends \Magento\Backend\App\Action implements HttpGetActionInterface { /** * Authorization level of a basic admin session diff --git a/app/code/Magento/PageCache/Model/Config.php b/app/code/Magento/PageCache/Model/Config.php index 7d856420dd664..1d77cb453e6af 100644 --- a/app/code/Magento/PageCache/Model/Config.php +++ b/app/code/Magento/PageCache/Model/Config.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\PageCache\Model; use Magento\Framework\App\ObjectManager; @@ -12,8 +13,7 @@ use Magento\PageCache\Model\Varnish\VclGeneratorFactory; /** - * Model is responsible for replacing default vcl template - * file configuration with user-defined from configuration + * Model is responsible for replacing default vcl template file configuration with user-defined from configuration * * @api * @since 100.0.2 @@ -163,14 +163,16 @@ public function getVclFile($vclTemplatePath) $sslOffloadedHeader = $this->_scopeConfig->getValue( \Magento\Framework\HTTP\PhpEnvironment\Request::XML_PATH_OFFLOADER_HEADER ); - $vclGenerator = $this->vclGeneratorFactory->create([ - 'backendHost' => $this->_scopeConfig->getValue(self::XML_VARNISH_PAGECACHE_BACKEND_HOST), - 'backendPort' => $this->_scopeConfig->getValue(self::XML_VARNISH_PAGECACHE_BACKEND_PORT), - 'accessList' => $accessList ? explode(',', $accessList) : [], - 'designExceptions' => $designExceptions ? $this->serializer->unserialize($designExceptions) : [], - 'sslOffloadedHeader' => $sslOffloadedHeader, - 'gracePeriod' => $this->_scopeConfig->getValue(self::XML_VARNISH_PAGECACHE_GRACE_PERIOD) - ]); + $vclGenerator = $this->vclGeneratorFactory->create( + [ + 'backendHost' => $this->_scopeConfig->getValue(self::XML_VARNISH_PAGECACHE_BACKEND_HOST), + 'backendPort' => $this->_scopeConfig->getValue(self::XML_VARNISH_PAGECACHE_BACKEND_PORT), + 'accessList' => $accessList ? explode(',', $accessList) : [], + 'designExceptions' => $designExceptions ? $this->serializer->unserialize($designExceptions) : [], + 'sslOffloadedHeader' => $sslOffloadedHeader, + 'gracePeriod' => $this->_scopeConfig->getValue(self::XML_VARNISH_PAGECACHE_GRACE_PERIOD) + ] + ); return $vclGenerator->generateVcl($version); } @@ -200,13 +202,12 @@ protected function _getReplacements() } /** - * Get IPs access list that can purge Varnish configuration for config file generation - * and transform it to appropriate view + * Get IPs access list allowed purge Varnish config for config file generation and transform it to appropriate view * - * acl purge{ + * Example acl_purge{ * "127.0.0.1"; * "127.0.0.2"; - * + * } * @return mixed|null|string * @deprecated 100.2.0 see \Magento\PageCache\Model\VclGeneratorInterface::generateVcl */ diff --git a/app/code/Magento/PageCache/Model/Varnish/VclTemplateLocator.php b/app/code/Magento/PageCache/Model/Varnish/VclTemplateLocator.php index a12dbd8f4b5cf..1550a00af0212 100644 --- a/app/code/Magento/PageCache/Model/Varnish/VclTemplateLocator.php +++ b/app/code/Magento/PageCache/Model/Varnish/VclTemplateLocator.php @@ -13,6 +13,9 @@ use Magento\PageCache\Model\VclTemplateLocatorInterface; use Magento\PageCache\Exception\UnsupportedVarnishVersion; +/** + * Class VclTemplateLocator provides vcl template path + */ class VclTemplateLocator implements VclTemplateLocatorInterface { /** @@ -84,7 +87,7 @@ public function __construct(Reader $reader, ReadFactory $readFactory, ScopeConfi } /** - * {@inheritdoc} + * @inheritdoc */ public function getTemplate($version) { From 41045c7f84b3950ffbbabea8b936686427a29cd5 Mon Sep 17 00:00:00 2001 From: Stepan Furman <furman.stepan@gmail.com> Date: Thu, 18 Jul 2019 17:36:44 +0300 Subject: [PATCH 718/773] MC-18031: Fix static tests. Add one blank line before tag --- app/code/Magento/PageCache/Model/Config.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/PageCache/Model/Config.php b/app/code/Magento/PageCache/Model/Config.php index 1d77cb453e6af..22d09e2f5dd9e 100644 --- a/app/code/Magento/PageCache/Model/Config.php +++ b/app/code/Magento/PageCache/Model/Config.php @@ -208,6 +208,7 @@ protected function _getReplacements() * "127.0.0.1"; * "127.0.0.2"; * } + * * @return mixed|null|string * @deprecated 100.2.0 see \Magento\PageCache\Model\VclGeneratorInterface::generateVcl */ From 643aa1f00382bac58a8c1a06b81ba9e72e6ce444 Mon Sep 17 00:00:00 2001 From: David Haecker <dhaecker@magento.com> Date: Thu, 18 Jul 2019 11:13:12 -0500 Subject: [PATCH 719/773] MC-4306: Delete skipped test MC-3494 & Skip Flaky Tests - Skipping unstable MFTF tests - Deleting MC-3494 MFTF test --- .../Mftf/Test/AdminMassOrdersCancelCompleteAndClosedTest.xml | 3 +++ .../Mftf/Test/AdminMassOrdersCancelProcessingAndClosedTest.xml | 3 +++ 2 files changed, 6 insertions(+) diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminMassOrdersCancelCompleteAndClosedTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminMassOrdersCancelCompleteAndClosedTest.xml index ec624a80f1613..0fb7d36379e85 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminMassOrdersCancelCompleteAndClosedTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminMassOrdersCancelCompleteAndClosedTest.xml @@ -17,6 +17,9 @@ <testCaseId value="MC-16183"/> <group value="sales"/> <group value="mtf_migrated"/> + <skip> + <issueId value="MC-18275"/> + </skip> </annotations> <before> <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminMassOrdersCancelProcessingAndClosedTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminMassOrdersCancelProcessingAndClosedTest.xml index 5e524bcf6e05c..22dcdc1fbbca7 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminMassOrdersCancelProcessingAndClosedTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminMassOrdersCancelProcessingAndClosedTest.xml @@ -17,6 +17,9 @@ <testCaseId value="MC-16184"/> <group value="sales"/> <group value="mtf_migrated"/> + <skip> + <issueId value="MC-18275"/> + </skip> </annotations> <before> <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> From 59cae726b9628d0d27e1f7f3f30e92be95e1823c Mon Sep 17 00:00:00 2001 From: David Haecker <dhaecker@magento.com> Date: Thu, 18 Jul 2019 11:38:40 -0500 Subject: [PATCH 720/773] MC-4306: Delete skipped test MC-3494 & Skip Flaky Tests - Fixing deprecation warnings --- .../Test/Mftf/Test/AdminCloneProductWithDuplicateUrlTest.xml | 1 + .../Test/AdminRestrictedUserAddCategoryFromProductPageTest.xml | 1 + .../CheckCurrentCategoryIsHighlightedAndProductsDisplayed.xml | 1 + ...AdminCheckConfigurableProductAttributeValueUniquenessTest.xml | 1 + .../Test/NoOptionAvailableToConfigureDisabledProductTest.xml | 1 + .../Mftf/Test/StorefrontVisibilityOfDuplicateProductTest.xml | 1 + 6 files changed, 6 insertions(+) diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCloneProductWithDuplicateUrlTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCloneProductWithDuplicateUrlTest.xml index 295351b00bf60..99adaeb522786 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCloneProductWithDuplicateUrlTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCloneProductWithDuplicateUrlTest.xml @@ -11,6 +11,7 @@ <test name="AdminCloneProductWithDuplicateUrlTest"> <annotations> <features value="Catalog"/> + <stories value="Product"/> <title value="Cloning a product with duplicate URL key"/> <description value="Check product cloning with duplicate URL key"/> <severity value="AVERAGE"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminRestrictedUserAddCategoryFromProductPageTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminRestrictedUserAddCategoryFromProductPageTest.xml index cd401b7a4651a..7b5455951fb27 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminRestrictedUserAddCategoryFromProductPageTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminRestrictedUserAddCategoryFromProductPageTest.xml @@ -11,6 +11,7 @@ <test name="AdminRestrictedUserAddCategoryFromProductPageTest"> <annotations> <features value="Catalog"/> + <stories value="Category"/> <title value="Adding new category from product page by restricted user"/> <description value="Adding new category from product page by restricted user"/> <severity value="MAJOR"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/CheckCurrentCategoryIsHighlightedAndProductsDisplayed.xml b/app/code/Magento/Catalog/Test/Mftf/Test/CheckCurrentCategoryIsHighlightedAndProductsDisplayed.xml index d2fe983cb82e9..7d09cb419f312 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/CheckCurrentCategoryIsHighlightedAndProductsDisplayed.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/CheckCurrentCategoryIsHighlightedAndProductsDisplayed.xml @@ -11,6 +11,7 @@ <test name="CheckCurrentCategoryIsHighlightedAndProductsDisplayed"> <annotations> <features value="Catalog"/> + <stories value="Category"/> <title value="Сheck that current category is highlighted and all products displayed for it"/> <description value="Сheck that current category is highlighted and all products displayed for it"/> <severity value="MAJOR"/> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCheckConfigurableProductAttributeValueUniquenessTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCheckConfigurableProductAttributeValueUniquenessTest.xml index df934446fc89b..df6afdcfd2243 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCheckConfigurableProductAttributeValueUniquenessTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCheckConfigurableProductAttributeValueUniquenessTest.xml @@ -11,6 +11,7 @@ <test name="AdminCheckConfigurableProductAttributeValueUniquenessTest"> <annotations> <features value="ConfigurableProduct"/> + <stories value="Configurable Product"/> <title value="Attribute value validation (check for uniqueness) in configurable products"/> <description value="Attribute value validation (check for uniqueness) in configurable products"/> <severity value="MAJOR"/> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/NoOptionAvailableToConfigureDisabledProductTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/NoOptionAvailableToConfigureDisabledProductTest.xml index cb0ea1c5de623..f52bdb1851b5e 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/NoOptionAvailableToConfigureDisabledProductTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/NoOptionAvailableToConfigureDisabledProductTest.xml @@ -10,6 +10,7 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="NoOptionAvailableToConfigureDisabledProductTest"> <annotations> + <stories value="Disabled Product"/> <title value="Disabled variation of configurable product can't be added to shopping cart via admin"/> <description value="Disabled variation of configurable product can't be added to shopping cart via admin"/> <severity value="AVERAGE"/> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontVisibilityOfDuplicateProductTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontVisibilityOfDuplicateProductTest.xml index 36c8301b23d49..ccbc587110d16 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontVisibilityOfDuplicateProductTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontVisibilityOfDuplicateProductTest.xml @@ -9,6 +9,7 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="StorefrontVisibilityOfDuplicateProductTest"> <annotations> + <stories value="Duplicate Product"/> <features value="ConfigurableProduct"/> <title value="Visibility of duplicate product on the Storefront"/> <description value="Check visibility of duplicate product on the Storefront"/> From ef2f79d8700bc2e828b8c92b7c3ef347adea03dc Mon Sep 17 00:00:00 2001 From: Krissy Hiserote <khiserote@magento.com> Date: Thu, 18 Jul 2019 13:00:12 -0500 Subject: [PATCH 721/773] MC-15776: Merge release branch into 2.3-develop - fix static failures --- .../adminhtml/templates/system/shipping/carrier_config.phtml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/code/Magento/Ups/view/adminhtml/templates/system/shipping/carrier_config.phtml b/app/code/Magento/Ups/view/adminhtml/templates/system/shipping/carrier_config.phtml index 61da69f5b8e6b..c4298cd8dc046 100644 --- a/app/code/Magento/Ups/view/adminhtml/templates/system/shipping/carrier_config.phtml +++ b/app/code/Magento/Ups/view/adminhtml/templates/system/shipping/carrier_config.phtml @@ -4,6 +4,8 @@ * See COPYING.txt for license details. */ +// phpcs:disable Magento2.Templates.ThisInTemplate.FoundThis + /** @var $upsModel \Magento\Ups\Helper\Config */ /** @var $block \Magento\Ups\Block\Backend\System\CarrierConfig */ $upsCarrierConfig = $block->getCarrierConfig(); From 71574fb94ab6730d4def1b7fd22a774d5054c729 Mon Sep 17 00:00:00 2001 From: Viktor Tymchynskyi <vtymchynskyi@magento.com> Date: Thu, 18 Jul 2019 13:49:32 -0500 Subject: [PATCH 722/773] MC-18199: Improving extensibility usability of CardinalCommerce module - Introduced JwtParserInterface - Introduced CAVV response code validator for Authorize.net - Added CardinalCommerce description in admin panel --- .../AuthorizenetAcceptjs/etc/adminhtml/di.xml | 5 ++ .../Magento/AuthorizenetAcceptjs/etc/di.xml | 2 + .../Request/Authorize3DSecureBuilder.php | 8 +- .../Validator/CavvResponseValidator.php | 83 +++++++++++++++++++ .../Magento/AuthorizenetCardinal/etc/di.xml | 16 ++++ .../web/js/authorizenet-accept-mixin.js | 2 + .../Model/Response/JwtParser.php | 4 +- .../Model/Response/JwtParserInterface.php | 21 +++++ .../CardinalCommerce/etc/adminhtml/system.xml | 5 +- app/code/Magento/CardinalCommerce/etc/di.xml | 1 + .../Fixture/response/authorize.php | 2 +- .../Gateway/Command/AuthorizeCommandTest.php | 5 +- 12 files changed, 142 insertions(+), 12 deletions(-) create mode 100644 app/code/Magento/AuthorizenetCardinal/Gateway/Validator/CavvResponseValidator.php create mode 100644 app/code/Magento/CardinalCommerce/Model/Response/JwtParserInterface.php diff --git a/app/code/Magento/AuthorizenetAcceptjs/etc/adminhtml/di.xml b/app/code/Magento/AuthorizenetAcceptjs/etc/adminhtml/di.xml index 730094b8d5524..f4059aebbe3e3 100644 --- a/app/code/Magento/AuthorizenetAcceptjs/etc/adminhtml/di.xml +++ b/app/code/Magento/AuthorizenetAcceptjs/etc/adminhtml/di.xml @@ -31,4 +31,9 @@ </argument> </arguments> </virtualType> + <virtualType name="AuthorizenetAcceptjsAuthorizeCommand" type="Magento\Payment\Gateway\Command\GatewayCommand"> + <arguments> + <argument name="validator" xsi:type="object">AuthorizenetAcceptjsTransactionValidator</argument> + </arguments> + </virtualType> </config> diff --git a/app/code/Magento/AuthorizenetAcceptjs/etc/di.xml b/app/code/Magento/AuthorizenetAcceptjs/etc/di.xml index 02dffe215fcc5..6e1d270f0152a 100644 --- a/app/code/Magento/AuthorizenetAcceptjs/etc/di.xml +++ b/app/code/Magento/AuthorizenetAcceptjs/etc/di.xml @@ -134,6 +134,7 @@ <arguments> <argument name="requestBuilder" xsi:type="object">AuthorizenetAcceptjsRefundRequest</argument> <argument name="handler" xsi:type="object">AuthorizenetAcceptjsRefundSettledHandler</argument> + <argument name="validator" xsi:type="object">AuthorizenetAcceptjsTransactionValidator</argument> </arguments> </virtualType> <virtualType name="AuthorizenetAcceptjsCaptureCommand" type="Magento\AuthorizenetAcceptjs\Gateway\Command\CaptureStrategyCommand"> @@ -145,6 +146,7 @@ <arguments> <argument name="requestBuilder" xsi:type="object">AuthorizenetAcceptjsCaptureRequest</argument> <argument name="handler" xsi:type="object">AuthorizenetAcceptjsCaptureTransactionHandler</argument> + <argument name="validator" xsi:type="object">AuthorizenetAcceptjsTransactionValidator</argument> </arguments> </virtualType> <virtualType name="AuthorizenetAcceptjsVoidCommand" type="Magento\Payment\Gateway\Command\GatewayCommand"> diff --git a/app/code/Magento/AuthorizenetCardinal/Gateway/Request/Authorize3DSecureBuilder.php b/app/code/Magento/AuthorizenetCardinal/Gateway/Request/Authorize3DSecureBuilder.php index 7e3d63d6f186e..00def8ce2b0cf 100644 --- a/app/code/Magento/AuthorizenetCardinal/Gateway/Request/Authorize3DSecureBuilder.php +++ b/app/code/Magento/AuthorizenetCardinal/Gateway/Request/Authorize3DSecureBuilder.php @@ -10,7 +10,7 @@ use Magento\AuthorizenetAcceptjs\Gateway\SubjectReader; use Magento\AuthorizenetCardinal\Model\Config; -use Magento\CardinalCommerce\Model\Response\JwtParser; +use Magento\CardinalCommerce\Model\Response\JwtParserInterface; use Magento\Payment\Gateway\Request\BuilderInterface; use Magento\Sales\Model\Order\Payment; @@ -30,19 +30,19 @@ class Authorize3DSecureBuilder implements BuilderInterface private $config; /** - * @var JwtParser + * @var JwtParserInterface */ private $jwtParser; /** * @param SubjectReader $subjectReader * @param Config $config - * @param JwtParser $jwtParser + * @param JwtParserInterface $jwtParser */ public function __construct( SubjectReader $subjectReader, Config $config, - JwtParser $jwtParser + JwtParserInterface $jwtParser ) { $this->subjectReader = $subjectReader; $this->config = $config; diff --git a/app/code/Magento/AuthorizenetCardinal/Gateway/Validator/CavvResponseValidator.php b/app/code/Magento/AuthorizenetCardinal/Gateway/Validator/CavvResponseValidator.php new file mode 100644 index 0000000000000..036c1fa332ebf --- /dev/null +++ b/app/code/Magento/AuthorizenetCardinal/Gateway/Validator/CavvResponseValidator.php @@ -0,0 +1,83 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +declare(strict_types=1); + +namespace Magento\AuthorizenetCardinal\Gateway\Validator; + +use Magento\AuthorizenetAcceptjs\Gateway\SubjectReader; +use Magento\AuthorizenetCardinal\Model\Config; +use Magento\Payment\Gateway\Validator\AbstractValidator; +use Magento\Payment\Gateway\Validator\ResultInterface; +use Magento\Payment\Gateway\Validator\ResultInterfaceFactory; + +/** + * Validates cardholder authentication verification response code. + */ +class CavvResponseValidator extends AbstractValidator +{ + /** + * The result code that authorize.net returns if CAVV passed validation. + */ + private const RESULT_CODE_SUCCESS = '2'; + + /** + * @var SubjectReader + */ + private $subjectReader; + + /** + * @var ResultInterfaceFactory + */ + private $resultFactory; + + /** + * @var Config + */ + private $config; + + /** + * @param ResultInterfaceFactory $resultFactory + * @param SubjectReader $subjectReader + * @param Config $config + */ + public function __construct( + ResultInterfaceFactory $resultFactory, + SubjectReader $subjectReader, + Config $config + ) { + parent::__construct($resultFactory); + + $this->resultFactory = $resultFactory; + $this->subjectReader = $subjectReader; + $this->config = $config; + } + + /** + * @inheritdoc + */ + public function validate(array $validationSubject): ResultInterface + { + if ($this->config->isActive() === false) { + return $this->createResult(true); + } + + $response = $this->subjectReader->readResponse($validationSubject); + $transactionResponse = $response['transactionResponse']; + + $cavvResultCode = $transactionResponse['cavvResultCode'] ?? ''; + $isValid = $cavvResultCode === self::RESULT_CODE_SUCCESS; + $errorCodes = []; + $errorMessages = []; + + if (!$isValid) { + $errorCodes[] = $transactionResponse['cavvResultCode']; + $errorMessages[] = 'CAVV failed validation'; + } + + return $this->createResult($isValid, $errorMessages, $errorCodes); + } +} diff --git a/app/code/Magento/AuthorizenetCardinal/etc/di.xml b/app/code/Magento/AuthorizenetCardinal/etc/di.xml index 45541a3cf499a..568cb6f4cfc4c 100644 --- a/app/code/Magento/AuthorizenetCardinal/etc/di.xml +++ b/app/code/Magento/AuthorizenetCardinal/etc/di.xml @@ -13,4 +13,20 @@ </argument> </arguments> </virtualType> + <virtualType name="Magento\AuthorizenetCardinal\Gateway\Validator\VirtualTransactionValidator" type="Magento\Payment\Gateway\Validator\ValidatorComposite"> + <arguments> + <argument name="chainBreakingValidators" xsi:type="array"> + <item name="general" xsi:type="boolean">true</item> + </argument> + <argument name="validators" xsi:type="array"> + <item name="general" xsi:type="string">AuthorizenetAcceptjsTransactionValidator</item> + <item name="cavv_response" xsi:type="string">Magento\AuthorizenetCardinal\Gateway\Validator\CavvResponseValidator</item> + </argument> + </arguments> + </virtualType> + <virtualType name="AuthorizenetAcceptjsAuthorizeCommand"> + <arguments> + <argument name="validator" xsi:type="object">Magento\AuthorizenetCardinal\Gateway\Validator\VirtualTransactionValidator</argument> + </arguments> + </virtualType> </config> diff --git a/app/code/Magento/AuthorizenetCardinal/view/frontend/web/js/authorizenet-accept-mixin.js b/app/code/Magento/AuthorizenetCardinal/view/frontend/web/js/authorizenet-accept-mixin.js index 336ceaab3ec67..20a917fc0f050 100644 --- a/app/code/Magento/AuthorizenetCardinal/view/frontend/web/js/authorizenet-accept-mixin.js +++ b/app/code/Magento/AuthorizenetCardinal/view/frontend/web/js/authorizenet-accept-mixin.js @@ -56,6 +56,8 @@ define([ }, /** + * Adds cardinal response JWT to payment additional data. + * * @returns {Object} */ getData: function () { diff --git a/app/code/Magento/CardinalCommerce/Model/Response/JwtParser.php b/app/code/Magento/CardinalCommerce/Model/Response/JwtParser.php index 1865605d50acc..6b1a67a02a18d 100644 --- a/app/code/Magento/CardinalCommerce/Model/Response/JwtParser.php +++ b/app/code/Magento/CardinalCommerce/Model/Response/JwtParser.php @@ -14,9 +14,9 @@ use Magento\Payment\Model\Method\Logger as PaymentLogger; /** - * Parse content of CardinalCommerce response JWT. + * Parses content of CardinalCommerce response JWT. */ -class JwtParser +class JwtParser implements JwtParserInterface { /** * @var JwtManagement diff --git a/app/code/Magento/CardinalCommerce/Model/Response/JwtParserInterface.php b/app/code/Magento/CardinalCommerce/Model/Response/JwtParserInterface.php new file mode 100644 index 0000000000000..c6f9a5f60d10d --- /dev/null +++ b/app/code/Magento/CardinalCommerce/Model/Response/JwtParserInterface.php @@ -0,0 +1,21 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\CardinalCommerce\Model\Response; + +/** + * Parses content of CardinalCommerce response JWT. + */ +interface JwtParserInterface +{ + /** + * Returns response JWT content. + * + * @param string $jwt + * @return array + */ + public function execute(string $jwt): array; +} diff --git a/app/code/Magento/CardinalCommerce/etc/adminhtml/system.xml b/app/code/Magento/CardinalCommerce/etc/adminhtml/system.xml index 4fa40436d4a90..532fcdd0f598f 100644 --- a/app/code/Magento/CardinalCommerce/etc/adminhtml/system.xml +++ b/app/code/Magento/CardinalCommerce/etc/adminhtml/system.xml @@ -13,9 +13,8 @@ <resource>Magento_Sales::three_d_secure</resource> <group id="cardinal" type="text" sortOrder="13" showInDefault="1" showInWebsite="1" showInStore="0"> <group id="config" translate="label comment" sortOrder="15" showInDefault="1" showInWebsite="1" showInStore="0"> - <label>Configuration</label> - <comment><![CDATA[For support contact <a href="mailto:support@cardinalcommerce.com">support@cardinalcommerce.com</a>.]]> - </comment> + <label>CardinalCommerce</label> + <comment><![CDATA[Please visit <a href="https://www.cardinalcommerce.com/" target="_blank">www.cardinalcommerce.com</a> to get the CardinalCommerce credentials and find out more details about PSD2 SCA requirements. For support contact <a href="mailto:support@cardinalcommerce.com">support@cardinalcommerce.com</a>.]]></comment> <field id="environment" translate="label" type="select" sortOrder="20" showInDefault="1" showInWebsite="1" showInStore="0"> <label>Environment</label> <source_model>Magento\CardinalCommerce\Model\Adminhtml\Source\Environment</source_model> diff --git a/app/code/Magento/CardinalCommerce/etc/di.xml b/app/code/Magento/CardinalCommerce/etc/di.xml index ffd3c50ef5043..410c16e91cb77 100644 --- a/app/code/Magento/CardinalCommerce/etc/di.xml +++ b/app/code/Magento/CardinalCommerce/etc/di.xml @@ -7,4 +7,5 @@ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> <preference for="Magento\CardinalCommerce\Model\Response\JwtPayloadValidatorInterface" type="Magento\CardinalCommerce\Model\Response\JwtPayloadValidator" /> + <preference for="Magento\CardinalCommerce\Model\Response\JwtParserInterface" type="Magento\CardinalCommerce\Model\Response\JwtParser" /> </config> diff --git a/dev/tests/integration/testsuite/Magento/AuthorizenetCardinal/Fixture/response/authorize.php b/dev/tests/integration/testsuite/Magento/AuthorizenetCardinal/Fixture/response/authorize.php index 3af04813c1ac8..c17b14721b157 100644 --- a/dev/tests/integration/testsuite/Magento/AuthorizenetCardinal/Fixture/response/authorize.php +++ b/dev/tests/integration/testsuite/Magento/AuthorizenetCardinal/Fixture/response/authorize.php @@ -12,7 +12,7 @@ 'authCode' => 'abc123', 'avsResultCode' => 'P', 'cvvResultCode' => '', - 'cavvResultCode' => '', + 'cavvResultCode' => '2', 'transId' => '123456', 'refTransID' => '', 'transHash' => 'foobar', diff --git a/dev/tests/integration/testsuite/Magento/AuthorizenetCardinal/Gateway/Command/AuthorizeCommandTest.php b/dev/tests/integration/testsuite/Magento/AuthorizenetCardinal/Gateway/Command/AuthorizeCommandTest.php index f41025e08ec22..561734b089213 100644 --- a/dev/tests/integration/testsuite/Magento/AuthorizenetCardinal/Gateway/Command/AuthorizeCommandTest.php +++ b/dev/tests/integration/testsuite/Magento/AuthorizenetCardinal/Gateway/Command/AuthorizeCommandTest.php @@ -66,7 +66,7 @@ public function testAuthorizeCommandWith3dSecure() 'authCode' => 'abc123', 'avsResultCode' => 'P', 'cvvResultCode' => '', - 'cavvResultCode' => '', + 'cavvResultCode' => '2', 'accountType' => 'Visa', ]; $this->assertSame('1111', $payment->getCcLast4()); @@ -148,6 +148,7 @@ public function testAuthorizeCommandWithDisabled3dSecure() $expectedRequest = include __DIR__ . '/../../../AuthorizenetAcceptjs/_files/expected_request/authorize.php'; $response = include __DIR__ . '/../../../AuthorizenetAcceptjs/_files/response/authorize.php'; + $response['transactionResponse']['cavvResultCode'] = '0'; $this->clientMock->method('setRawData') ->with(json_encode($expectedRequest), 'application/json'); @@ -167,7 +168,7 @@ public function testAuthorizeCommandWithDisabled3dSecure() 'authCode' => 'abc123', 'avsResultCode' => 'Y', 'cvvResultCode' => 'P', - 'cavvResultCode' => '2', + 'cavvResultCode' => '0', 'accountType' => 'Visa', ]; $this->assertSame('1111', $payment->getCcLast4()); From 9d6c358c8020e9fbf224f981aad3b81239d78d2a Mon Sep 17 00:00:00 2001 From: Dmytro Horytskyi <horytsky@adobe.com> Date: Thu, 18 Jul 2019 14:05:34 -0500 Subject: [PATCH 723/773] MC-18195: Order Products Report Interval Date incorrect --- .../Magento/Reports/Block/Adminhtml/Grid.php | 5 +- .../Model/ResourceModel/Report/Collection.php | 18 +++---- .../ResourceModel/Report/CollectionTest.php | 47 +++++++++---------- 3 files changed, 31 insertions(+), 39 deletions(-) diff --git a/app/code/Magento/Reports/Block/Adminhtml/Grid.php b/app/code/Magento/Reports/Block/Adminhtml/Grid.php index 32073cf0b7a04..8885c94c6989a 100644 --- a/app/code/Magento/Reports/Block/Adminhtml/Grid.php +++ b/app/code/Magento/Reports/Block/Adminhtml/Grid.php @@ -170,9 +170,8 @@ protected function _prepareCollection() * Validate from and to date */ try { - $from = $this->_localeDate->date($this->getFilter('report_from'), null, false, false); - $to = $this->_localeDate->date($this->getFilter('report_to'), null, false, false); - + $from = $this->_localeDate->date($this->getFilter('report_from'), null, true, false); + $to = $this->_localeDate->date($this->getFilter('report_to'), null, true, false); $collection->setInterval($from, $to); } catch (\Exception $e) { $this->_errors[] = __('Invalid date specified'); diff --git a/app/code/Magento/Reports/Model/ResourceModel/Report/Collection.php b/app/code/Magento/Reports/Model/ResourceModel/Report/Collection.php index f2a761dbd5080..b987e09194b30 100644 --- a/app/code/Magento/Reports/Model/ResourceModel/Report/Collection.php +++ b/app/code/Magento/Reports/Model/ResourceModel/Report/Collection.php @@ -22,14 +22,14 @@ class Collection extends \Magento\Framework\Data\Collection /** * From value * - * @var \DateTime + * @var \DateTimeInterface */ protected $_from; /** * To value * - * @var \DateTime + * @var \DateTimeInterface */ protected $_to; @@ -125,8 +125,8 @@ public function setPeriod($period) */ public function setInterval(\DateTimeInterface $fromDate, \DateTimeInterface $toDate) { - $this->_from = new \DateTime($fromDate->format('Y-m-d'), $fromDate->getTimezone()); - $this->_to = new \DateTime($toDate->format('Y-m-d'), $toDate->getTimezone()); + $this->_from = $fromDate; + $this->_to = $toDate; return $this; } @@ -143,8 +143,8 @@ protected function _getIntervals() if (!$this->_from && !$this->_to) { return $this->_intervals; } - $dateStart = $this->_from; - $dateEnd = $this->_to; + $dateStart = new \DateTime($this->_from->format('Y-m-d'), $this->_from->getTimezone()); + $dateEnd = new \DateTime($this->_to->format('Y-m-d'), $this->_to->getTimezone()); $firstInterval = true; while ($dateStart <= $dateEnd) { @@ -179,11 +179,7 @@ protected function _getIntervals() protected function _getDayInterval(\DateTime $dateStart) { $interval = [ - 'period' => $this->_localeDate->formatDateTime( - $dateStart, - \IntlDateFormatter::SHORT, - \IntlDateFormatter::NONE - ), + 'period' => $this->_localeDate->formatDate($dateStart, \IntlDateFormatter::SHORT), 'start' => $this->_localeDate->convertConfigTimeToUtc($dateStart->format('Y-m-d 00:00:00')), 'end' => $this->_localeDate->convertConfigTimeToUtc($dateStart->format('Y-m-d 23:59:59')), ]; diff --git a/app/code/Magento/Reports/Test/Unit/Model/ResourceModel/Report/CollectionTest.php b/app/code/Magento/Reports/Test/Unit/Model/ResourceModel/Report/CollectionTest.php index 51d890dd56df9..41b4745594571 100644 --- a/app/code/Magento/Reports/Test/Unit/Model/ResourceModel/Report/CollectionTest.php +++ b/app/code/Magento/Reports/Test/Unit/Model/ResourceModel/Report/CollectionTest.php @@ -6,49 +6,49 @@ namespace Magento\Reports\Test\Unit\Model\ResourceModel\Report; +use Magento\Framework\Data\Collection\EntityFactory; +use Magento\Framework\Stdlib\DateTime\TimezoneInterface; use Magento\Reports\Model\ResourceModel\Report\Collection; +use Magento\Reports\Model\ResourceModel\Report\Collection\Factory as ReportCollectionFactory; +/** + * Class CollectionTest + * + * @covers \Magento\Reports\Model\ResourceModel\Report\Collection + */ class CollectionTest extends \PHPUnit\Framework\TestCase { /** - * @var \Magento\Reports\Model\ResourceModel\Report\Collection + * @var Collection */ protected $collection; /** - * @var \Magento\Framework\Data\Collection\EntityFactory|\PHPUnit_Framework_MockObject_MockObject + * @var EntityFactory|\PHPUnit_Framework_MockObject_MockObject */ protected $entityFactoryMock; /** - * @var \Magento\Framework\Stdlib\DateTime\TimezoneInterface|\PHPUnit_Framework_MockObject_MockObject + * @var TimezoneInterface|\PHPUnit_Framework_MockObject_MockObject */ protected $timezoneMock; /** - * @var \Magento\Reports\Model\ResourceModel\Report\Collection\Factory|\PHPUnit_Framework_MockObject_MockObject + * @var ReportCollectionFactory|\PHPUnit_Framework_MockObject_MockObject */ protected $factoryMock; /** - * {@inheritDoc} + * @inheritDoc */ protected function setUp() { - $this->entityFactoryMock = $this->getMockBuilder(\Magento\Framework\Data\Collection\EntityFactory::class) - ->disableOriginalConstructor() - ->getMock(); - $this->timezoneMock = $this->getMockBuilder(\Magento\Framework\Stdlib\DateTime\TimezoneInterface::class) - ->getMock(); - $this->factoryMock = $this->getMockBuilder( - \Magento\Reports\Model\ResourceModel\Report\Collection\Factory::class - )->disableOriginalConstructor() - ->getMock(); - - $this->timezoneMock - ->expects($this->any()) - ->method('formatDateTime') - ->will($this->returnCallback([$this, 'formatDateTime'])); + $this->entityFactoryMock = $this->createMock(EntityFactory::class); + $this->timezoneMock = $this->createMock(TimezoneInterface::class); + $this->factoryMock = $this->createMock(ReportCollectionFactory::class); + + $this->timezoneMock->method('formatDate') + ->will($this->returnCallback([$this, 'formatDate'])); $this->collection = new Collection( $this->entityFactoryMock, @@ -131,7 +131,7 @@ public function testGetReports($period, $fromDate, $toDate, $size) public function testLoadData() { $this->assertInstanceOf( - \Magento\Reports\Model\ResourceModel\Report\Collection::class, + Collection::class, $this->collection->loadData() ); } @@ -182,14 +182,11 @@ public function intervalsDataProvider() } /** + * @param \DateTimeInterface $dateStart * @return string */ - public function formatDateTime() + public function formatDate(\DateTimeInterface $dateStart): string { - $args = func_get_args(); - - $dateStart = $args[0]; - $formatter = new \IntlDateFormatter( "en_US", \IntlDateFormatter::SHORT, From 53caf25f21cc5dcd250de669a6b6a086103b2741 Mon Sep 17 00:00:00 2001 From: Tom Reece <treece@adobe.com> Date: Thu, 18 Jul 2019 14:35:42 -0500 Subject: [PATCH 724/773] MQE-1641: Part four fixing skipped tests --- .../Mftf/Test/AdminUpdateSimpleProductTieredPriceTest.xml | 5 ++--- ...teSimpleProductWithRegularPriceInStockEnabledFlatTest.xml | 5 ++--- ...ductWithRegularPriceInStockNotVisibleIndividuallyTest.xml | 5 ++--- ...tWithRegularPriceInStockVisibleInCatalogAndSearchTest.xml | 5 ++--- ...roductWithRegularPriceInStockVisibleInCatalogOnlyTest.xml | 5 ++--- ...ProductWithRegularPriceInStockVisibleInSearchOnlyTest.xml | 5 ++--- ...leProductWithRegularPriceInStockWithCustomOptionsTest.xml | 5 ++--- ...dminUpdateSimpleProductWithRegularPriceOutOfStockTest.xml | 5 ++--- ...eateProductWithSeveralWebsitesAndCheckURLRewritesTest.xml | 5 ++--- 9 files changed, 18 insertions(+), 27 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductTieredPriceTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductTieredPriceTest.xml index d151bae3ee110..f317c66e5366a 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductTieredPriceTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductTieredPriceTest.xml @@ -17,9 +17,6 @@ <severity value="CRITICAL"/> <group value="catalog"/> <group value="mtf_migrated"/> - <skip> - <issueId value="MC-17181"/> - </skip> </annotations> <before> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> @@ -68,8 +65,10 @@ <selectOption selector="{{AdminProductFormSection.productWeightSelect}}" userInput="{{simpleProductTierPrice300InStock.weightSelect}}" stepKey="selectProductWeight"/> <click selector="{{AdminProductFormSection.categoriesDropdown}}" stepKey="clickCategoriesDropDown"/> <fillField selector="{{AdminProductFormSection.searchCategory}}" userInput="$$initialCategoryEntity.name$$" stepKey="fillSearchForInitialCategory" /> + <waitForPageLoad stepKey="waitForCategory1"/> <click selector="{{AdminProductFormSection.selectCategory($$initialCategoryEntity.name$$)}}" stepKey="unselectInitialCategory"/> <fillField selector="{{AdminProductFormSection.searchCategory}}" userInput="$$categoryEntity.name$$" stepKey="fillSearchCategory" /> + <waitForPageLoad stepKey="waitForCategory2"/> <click selector="{{AdminProductFormSection.selectCategory($$categoryEntity.name$$)}}" stepKey="clickOnCategory"/> <click selector="{{AdminProductFormSection.done}}" stepKey="clickOnDoneAdvancedCategorySelect"/> <click selector="{{AdminProductSEOSection.sectionHeader}}" stepKey="clickAdminProductSEOSection"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockEnabledFlatTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockEnabledFlatTest.xml index d30500de64a32..afb8b40a6dbd4 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockEnabledFlatTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockEnabledFlatTest.xml @@ -17,9 +17,6 @@ <severity value="CRITICAL"/> <group value="catalog"/> <group value="mtf_migrated"/> - <skip> - <issueId value="MC-17181"/> - </skip> </annotations> <before> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> @@ -65,8 +62,10 @@ <selectOption selector="{{AdminProductFormSection.productWeightSelect}}" userInput="{{simpleProductEnabledFlat.weightSelect}}" stepKey="selectProductWeight"/> <click selector="{{AdminProductFormSection.categoriesDropdown}}" stepKey="clickCategoriesDropDown"/> <fillField selector="{{AdminProductFormSection.searchCategory}}" userInput="$$initialCategoryEntity.name$$" stepKey="fillSearchForInitialCategory" /> + <waitForPageLoad stepKey="waitForCategory1"/> <click selector="{{AdminProductFormSection.selectCategory($$initialCategoryEntity.name$$)}}" stepKey="unselectInitialCategory"/> <fillField selector="{{AdminProductFormSection.searchCategory}}" userInput="$$categoryEntity.name$$" stepKey="fillSearchCategory" /> + <waitForPageLoad stepKey="waitForCategory2"/> <click selector="{{AdminProductFormSection.selectCategory($$categoryEntity.name$$)}}" stepKey="clickOnCategory"/> <click selector="{{AdminProductFormSection.done}}" stepKey="clickOnDoneAdvancedCategorySelect"/> <selectOption selector="{{AdminProductFormSection.visibility}}" userInput="{{simpleProductEnabledFlat.visibility}}" stepKey="selectVisibility"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockNotVisibleIndividuallyTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockNotVisibleIndividuallyTest.xml index cb7b3d6278aa8..2436fc0fc7f12 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockNotVisibleIndividuallyTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockNotVisibleIndividuallyTest.xml @@ -17,9 +17,6 @@ <severity value="CRITICAL"/> <group value="catalog"/> <group value="mtf_migrated"/> - <skip> - <issueId value="MC-17181"/> - </skip> </annotations> <before> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> @@ -56,8 +53,10 @@ <fillField selector="{{AdminProductFormSection.productWeight}}" userInput="{{simpleProductNotVisibleIndividually.weight}}" stepKey="fillSimpleProductWeight"/> <click selector="{{AdminProductFormSection.categoriesDropdown}}" stepKey="clickCategoriesDropDown"/> <fillField selector="{{AdminProductFormSection.searchCategory}}" userInput="$$initialCategoryEntity.name$$" stepKey="fillSearchForInitialCategory" /> + <waitForPageLoad stepKey="waitForCategory1"/> <click selector="{{AdminProductFormSection.selectCategory($$initialCategoryEntity.name$$)}}" stepKey="unselectInitialCategory"/> <fillField selector="{{AdminProductFormSection.searchCategory}}" userInput="$$categoryEntity.name$$" stepKey="fillSearchCategory"/> + <waitForPageLoad stepKey="waitForCategory2"/> <click selector="{{AdminProductFormSection.selectCategory($$categoryEntity.name$$)}}" stepKey="clickOnCategory"/> <click selector="{{AdminProductFormSection.done}}" stepKey="clickOnDoneAdvancedCategorySelect"/> <selectOption selector="{{AdminProductFormSection.visibility}}" userInput="{{simpleProductNotVisibleIndividually.visibility}}" stepKey="selectVisibility"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogAndSearchTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogAndSearchTest.xml index 75b4a9728d08b..637ae790c16c8 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogAndSearchTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogAndSearchTest.xml @@ -17,9 +17,6 @@ <severity value="CRITICAL"/> <group value="catalog"/> <group value="mtf_migrated"/> - <skip> - <issueId value="MC-17181"/> - </skip> </annotations> <before> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> @@ -56,8 +53,10 @@ <fillField selector="{{AdminProductFormSection.productWeight}}" userInput="{{simpleProductRegularPrice245InStock.weight}}" stepKey="fillSimpleProductWeight"/> <click selector="{{AdminProductFormSection.categoriesDropdown}}" stepKey="clickCategoriesDropDown"/> <fillField selector="{{AdminProductFormSection.searchCategory}}" userInput="$$initialCategoryEntity.name$$" stepKey="fillSearchForInitialCategory" /> + <waitForPageLoad stepKey="waitForCategory1"/> <click selector="{{AdminProductFormSection.selectCategory($$initialCategoryEntity.name$$)}}" stepKey="unselectInitialCategory"/> <fillField selector="{{AdminProductFormSection.searchCategory}}" userInput="$$categoryEntity.name$$" stepKey="fillSearchCategory" /> + <waitForPageLoad stepKey="waitForCategory2"/> <click selector="{{AdminProductFormSection.selectCategory($$categoryEntity.name$$)}}" stepKey="clickOnCategory"/> <click selector="{{AdminProductFormSection.done}}" stepKey="clickOnDoneAdvancedCategorySelect"/> <selectOption selector="{{AdminProductFormSection.visibility}}" userInput="{{simpleProductRegularPrice245InStock.visibility}}" stepKey="selectVisibility"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogOnlyTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogOnlyTest.xml index f8b0b17c06253..045b3f3420ff6 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogOnlyTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogOnlyTest.xml @@ -17,9 +17,6 @@ <severity value="CRITICAL"/> <group value="catalog"/> <group value="mtf_migrated"/> - <skip> - <issueId value="MC-17181"/> - </skip> </annotations> <before> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> @@ -56,8 +53,10 @@ <fillField selector="{{AdminProductFormSection.productWeight}}" userInput="{{simpleProductRegularPrice32501InStock.weight}}" stepKey="fillSimpleProductWeight"/> <click selector="{{AdminProductFormSection.categoriesDropdown}}" stepKey="clickCategoriesDropDown"/> <fillField selector="{{AdminProductFormSection.searchCategory}}" userInput="$$initialCategoryEntity.name$$" stepKey="fillSearchForInitialCategory"/> + <waitForPageLoad stepKey="waitForCategory1"/> <click selector="{{AdminProductFormSection.selectCategory($$initialCategoryEntity.name$$)}}" stepKey="unselectInitialCategory"/> <fillField selector="{{AdminProductFormSection.searchCategory}}" userInput="$$categoryEntity.name$$" stepKey="fillSearchCategory"/> + <waitForPageLoad stepKey="waitForCategory2"/> <click selector="{{AdminProductFormSection.selectCategory($$categoryEntity.name$$)}}" stepKey="clickOnCategory"/> <click selector="{{AdminProductFormSection.done}}" stepKey="clickOnDoneAdvancedCategorySelect"/> <selectOption selector="{{AdminProductFormSection.visibility}}" userInput="{{simpleProductRegularPrice32501InStock.visibility}}" stepKey="selectVisibility"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInSearchOnlyTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInSearchOnlyTest.xml index ee2a2514c9c7e..214f9b0273b6a 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInSearchOnlyTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInSearchOnlyTest.xml @@ -17,9 +17,6 @@ <severity value="CRITICAL"/> <group value="catalog"/> <group value="mtf_migrated"/> - <skip> - <issueId value="MC-17181"/> - </skip> </annotations> <before> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> @@ -56,8 +53,10 @@ <fillField selector="{{AdminProductFormSection.productWeight}}" userInput="{{simpleProductRegularPrice325InStock.weight}}" stepKey="fillSimpleProductWeight"/> <click selector="{{AdminProductFormSection.categoriesDropdown}}" stepKey="clickCategoriesDropDown"/> <fillField selector="{{AdminProductFormSection.searchCategory}}" userInput="$$initialCategoryEntity.name$$" stepKey="fillSearchForInitialCategory" /> + <waitForPageLoad stepKey="waitForCategory1"/> <click selector="{{AdminProductFormSection.selectCategory($$initialCategoryEntity.name$$)}}" stepKey="unselectInitialCategory"/> <fillField selector="{{AdminProductFormSection.searchCategory}}" userInput="$$categoryEntity.name$$" stepKey="fillSearchCategory" /> + <waitForPageLoad stepKey="waitForCategory2"/> <click selector="{{AdminProductFormSection.selectCategory($$categoryEntity.name$$)}}" stepKey="clickOnCategory"/> <click selector="{{AdminProductFormSection.done}}" stepKey="clickOnDoneAdvancedCategorySelect"/> <selectOption selector="{{AdminProductFormSection.visibility}}" userInput="{{simpleProductRegularPrice325InStock.visibility}}" stepKey="selectVisibility"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockWithCustomOptionsTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockWithCustomOptionsTest.xml index 7921ed6c3e459..b145328890a91 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockWithCustomOptionsTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockWithCustomOptionsTest.xml @@ -17,9 +17,6 @@ <severity value="CRITICAL"/> <group value="catalog"/> <group value="mtf_migrated"/> - <skip> - <issueId value="MC-17181"/> - </skip> </annotations> <before> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> @@ -56,8 +53,10 @@ <fillField selector="{{AdminProductFormSection.productWeight}}" userInput="{{simpleProductRegularPriceCustomOptions.weight}}" stepKey="fillSimpleProductWeight"/> <click selector="{{AdminProductFormSection.categoriesDropdown}}" stepKey="clickCategoriesDropDown"/> <fillField selector="{{AdminProductFormSection.searchCategory}}" userInput="$$initialCategoryEntity.name$$" stepKey="fillSearchForInitialCategory"/> + <waitForPageLoad stepKey="waitForCategory1"/> <click selector="{{AdminProductFormSection.selectCategory($$initialCategoryEntity.name$$)}}" stepKey="unselectInitialCategory"/> <fillField selector="{{AdminProductFormSection.searchCategory}}" userInput="$$categoryEntity.name$$" stepKey="fillSearchCategory"/> + <waitForPageLoad stepKey="waitForCategory2"/> <click selector="{{AdminProductFormSection.selectCategory($$categoryEntity.name$$)}}" stepKey="clickOnCategory"/> <click selector="{{AdminProductFormSection.done}}" stepKey="clickOnDoneAdvancedCategorySelect"/> <click selector="{{AdminProductSEOSection.sectionHeader}}" stepKey="clickAdminProductSEOSection"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceOutOfStockTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceOutOfStockTest.xml index 0125b4c1e713d..27c7e77a94ad1 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceOutOfStockTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceOutOfStockTest.xml @@ -17,9 +17,6 @@ <severity value="CRITICAL"/> <group value="catalog"/> <group value="mtf_migrated"/> - <skip> - <issueId value="MC-17181"/> - </skip> </annotations> <before> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> @@ -56,8 +53,10 @@ <fillField selector="{{AdminProductFormSection.productWeight}}" userInput="{{simpleProductRegularPrice32503OutOfStock.weight}}" stepKey="fillSimpleProductWeight"/> <click selector="{{AdminProductFormSection.categoriesDropdown}}" stepKey="clickCategoriesDropDown"/> <fillField selector="{{AdminProductFormSection.searchCategory}}" userInput="$$initialCategoryEntity.name$$" stepKey="fillSearchForInitialCategory"/> + <waitForPageLoad stepKey="waitForCategory1"/> <click selector="{{AdminProductFormSection.selectCategory($$initialCategoryEntity.name$$)}}" stepKey="unselectInitialCategory"/> <fillField selector="{{AdminProductFormSection.searchCategory}}" userInput="$$categoryEntity.name$$" stepKey="fillSearchCategory"/> + <waitForPageLoad stepKey="waitForCategory2"/> <click selector="{{AdminProductFormSection.selectCategory($$categoryEntity.name$$)}}" stepKey="clickOnCategory"/> <click selector="{{AdminProductFormSection.done}}" stepKey="clickOnDoneAdvancedCategorySelect"/> <click selector="{{AdminProductSEOSection.sectionHeader}}" stepKey="clickAdminProductSEOSection"/> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCreateProductWithSeveralWebsitesAndCheckURLRewritesTest.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCreateProductWithSeveralWebsitesAndCheckURLRewritesTest.xml index 8712edb69e499..4dc5c85830076 100644 --- a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCreateProductWithSeveralWebsitesAndCheckURLRewritesTest.xml +++ b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCreateProductWithSeveralWebsitesAndCheckURLRewritesTest.xml @@ -16,9 +16,6 @@ <severity value="CRITICAL"/> <group value="urlRewrite"/> <group value="mtf_migrated"/> - <skip> - <issueId value="MC-17181"/> - </skip> </annotations> <before> @@ -75,8 +72,10 @@ <waitForPageLoad stepKey="waitUntilProductIsOpened"/> <click selector="{{AdminProductFormSection.categoriesDropdown}}" stepKey="clickCategoriesDropDown"/> <fillField selector="{{AdminProductFormSection.searchCategory}}" userInput="$$rootCategory.name$$" stepKey="fillSearchForInitialCategory"/> + <waitForPageLoad stepKey="waitForCategory1"/> <click selector="{{AdminProductFormSection.selectCategory($$rootCategory.name$$)}}" stepKey="unselectInitialCategory"/> <fillField selector="{{AdminProductFormSection.searchCategory}}" userInput="$$category.name$$" stepKey="fillSearchCategory"/> + <waitForPageLoad stepKey="waitForCategory2"/> <click selector="{{AdminProductFormSection.selectCategory($$category.name$$)}}" stepKey="clickOnCategory"/> <click selector="{{AdminProductFormSection.done}}" stepKey="clickOnDoneAdvancedCategorySelect"/> <scrollToTopOfPage stepKey="scrollToTopOfAdminProductFormSection"/> From 626fab70c34e56d3d20f0a0824186735efc4e2ce Mon Sep 17 00:00:00 2001 From: Alex Kolesnyk <kolesnyk@adobe.com> Date: Thu, 18 Jul 2019 16:44:53 -0500 Subject: [PATCH 725/773] Test improvements: - added testCaseId and Severity --- .../Mftf/Test/StorefrontOnePageCheckoutJsValidationTest.xml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontOnePageCheckoutJsValidationTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontOnePageCheckoutJsValidationTest.xml index e1bff86542740..63751ad697ede 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontOnePageCheckoutJsValidationTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontOnePageCheckoutJsValidationTest.xml @@ -13,8 +13,10 @@ <features value="Checkout"/> <title value="Js validation error messages must be absent for required fields after checkout start."/> <description value="Js validation error messages must be absent for required fields after checkout start."/> - <group value="shoppingCart"/> - <group value="mtf_migrated"/> + <severity value="MAJOR" /> + <testCaseId value="MC-18312" /> + <group value="shoppingCart" /> + <group value="mtf_migrated" /> </annotations> <before> <createData entity="_defaultCategory" stepKey="createCategory"/> From c36ef28ff931e0a350f6ec4541d3d3c6dcc1c596 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun <ogorkun@magento.com> Date: Thu, 18 Jul 2019 16:54:08 -0500 Subject: [PATCH 726/773] MC-17489: Require specific suffix for HTML binding --- .../Magento/Sniffs/Html/HtmlBindingSniff.php | 90 +++++++++++-------- 1 file changed, 52 insertions(+), 38 deletions(-) diff --git a/dev/tests/static/framework/Magento/Sniffs/Html/HtmlBindingSniff.php b/dev/tests/static/framework/Magento/Sniffs/Html/HtmlBindingSniff.php index ff79bddd4202f..c0d0e67b66e06 100644 --- a/dev/tests/static/framework/Magento/Sniffs/Html/HtmlBindingSniff.php +++ b/dev/tests/static/framework/Magento/Sniffs/Html/HtmlBindingSniff.php @@ -23,54 +23,68 @@ public function register() } /** - * @inheritDoc + * Load HTML document to validate. * - * Find HTML data bindings and check variables used. + * @param int $stackPointer + * @param File $file + * @return \DOMDocument|null */ - public function process(File $phpcsFile, $stackPtr) + private function loadHtmlDocument(int $stackPointer, File $file): ?\DOMDocument { - if ($stackPtr === 0) { - $html = $phpcsFile->getTokensAsString($stackPtr, count($phpcsFile->getTokens())); + if ($stackPointer === 0) { + $html = $file->getTokensAsString($stackPointer, count($file->getTokens())); $dom = new \DOMDocument(); try { // phpcs:disable Generic.PHP.NoSilencedErrors @$dom->loadHTML($html); - $loaded = true; + return $dom; } catch (\Throwable $exception) { //Invalid HTML, skipping - $loaded = false; } - if ($loaded) { - /** @var string[] $htmlBindings */ - $htmlBindings = []; - $domXpath = new \DOMXPath($dom); - $dataBindAttributes = $domXpath->query('//@*[name() = "data-bind"]'); - foreach ($dataBindAttributes as $dataBindAttribute) { - $knockoutBinding = $dataBindAttribute->nodeValue; - preg_match('/^(.+\s*?)?html\s*?\:(.+)/ims', $knockoutBinding, $htmlBindingStart); - if ($htmlBindingStart) { - $htmlBinding = trim(preg_replace('/\,[a-z0-9\_\s]+\:.+/ims', '', $htmlBindingStart[2])); - $htmlBindings[] = $htmlBinding; - } - } - $htmlAttributes = $domXpath->query('//@*[name() = "html"]'); - foreach ($htmlAttributes as $htmlAttribute) { - $magentoBinding = $htmlAttribute->nodeValue; - $htmlBindings[] = trim($magentoBinding); - } - foreach ($htmlBindings as $htmlBinding) { - if (!preg_match('/^[0-9\\\'\"]/ims', $htmlBinding) - && !preg_match('/UnsanitizedHtml(\(.*?\))*?$/', $htmlBinding) - ) { - $phpcsFile->addError( - 'Variables/functions used for HTML binding must have UnsanitizedHtml suffix' - .' - "' .$htmlBinding .'" doesn\'t,' .PHP_EOL - .'consider using text binding if the value is supposed to be text', - null, - 'UIComponentTemplate.KnockoutBinding.HtmlSuffix' - ); - } - } + } + + return null; + } + + /** + * @inheritDoc + * + * Find HTML data bindings and check variables used. + */ + public function process(File $phpcsFile, $stackPtr) + { + if (!$dom = $this->loadHtmlDocument($stackPtr, $phpcsFile)) { + return; + } + + /** @var string[] $htmlBindings */ + $htmlBindings = []; + $domXpath = new \DOMXPath($dom); + $dataBindAttributes = $domXpath->query('//@*[name() = "data-bind"]'); + foreach ($dataBindAttributes as $dataBindAttribute) { + $knockoutBinding = $dataBindAttribute->nodeValue; + preg_match('/^(.+\s*?)?html\s*?\:(.+)/ims', $knockoutBinding, $htmlBindingStart); + if ($htmlBindingStart) { + $htmlBinding = trim(preg_replace('/\,[a-z0-9\_\s]+\:.+/ims', '', $htmlBindingStart[2])); + $htmlBindings[] = $htmlBinding; + } + } + $htmlAttributes = $domXpath->query('//@*[name() = "html"]'); + foreach ($htmlAttributes as $htmlAttribute) { + $magentoBinding = $htmlAttribute->nodeValue; + $htmlBindings[] = trim($magentoBinding); + } + foreach ($htmlBindings as $htmlBinding) { + if (!preg_match('/^[0-9\\\'\"]/ims', $htmlBinding) + && !preg_match('/UnsanitizedHtml(\(.*?\))*?$/', $htmlBinding) + ) { + $phpcsFile->addError( + 'Variables/functions used for HTML binding must have UnsanitizedHtml suffix' + . ' - "' . $htmlBinding . '" doesn\'t,' . PHP_EOL + . 'consider using text binding if the value is supposed to be text', + null, + 'UIComponentTemplate.KnockoutBinding.HtmlSuffix' + ); } } } From e8c14d20f418fa4e4b57d1fecb09a47ac7aa8d62 Mon Sep 17 00:00:00 2001 From: Graham Wharton <graham@gwharton.me.uk> Date: Fri, 19 Jul 2019 10:23:40 +0100 Subject: [PATCH 727/773] Updated AbstractPdf insertLogo function to be Database Media Storage aware. --- .../Sales/Model/Order/Pdf/AbstractPdf.php | 18 ++- .../Test/Unit/Model/Order/Pdf/InvoiceTest.php | 138 +++++++++++++++++- 2 files changed, 151 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/Sales/Model/Order/Pdf/AbstractPdf.php b/app/code/Magento/Sales/Model/Order/Pdf/AbstractPdf.php index 723940a5f67c0..ba82478c9cea1 100644 --- a/app/code/Magento/Sales/Model/Order/Pdf/AbstractPdf.php +++ b/app/code/Magento/Sales/Model/Order/Pdf/AbstractPdf.php @@ -7,6 +7,7 @@ namespace Magento\Sales\Model\Order\Pdf; use Magento\Framework\App\Filesystem\DirectoryList; +use Magento\MediaStorage\Helper\File\Storage\Database; /** * Sales Order PDF abstract model @@ -15,6 +16,7 @@ * @api * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * @SuppressWarnings(PHPMD.TooManyFields) * @since 100.0.2 */ abstract class AbstractPdf extends \Magento\Framework\DataObject @@ -122,6 +124,11 @@ abstract public function getPdf(); */ private $pageSettings; + /** + * @var Database + */ + private $fileStorageDatabase; + /** * @param \Magento\Payment\Helper\Data $paymentData * @param \Magento\Framework\Stdlib\StringUtils $string @@ -134,6 +141,7 @@ abstract public function getPdf(); * @param \Magento\Framework\Translate\Inline\StateInterface $inlineTranslation * @param \Magento\Sales\Model\Order\Address\Renderer $addressRenderer * @param array $data + * @param Database $fileStorageDatabase * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -147,7 +155,8 @@ public function __construct( \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate, \Magento\Framework\Translate\Inline\StateInterface $inlineTranslation, \Magento\Sales\Model\Order\Address\Renderer $addressRenderer, - array $data = [] + array $data = [], + Database $fileStorageDatabase = null ) { $this->addressRenderer = $addressRenderer; $this->_paymentData = $paymentData; @@ -160,6 +169,8 @@ public function __construct( $this->_pdfTotalFactory = $pdfTotalFactory; $this->_pdfItemsFactory = $pdfItemsFactory; $this->inlineTranslation = $inlineTranslation; + $this->fileStorageDatabase = $fileStorageDatabase ?: + \Magento\Framework\App\ObjectManager::getInstance()->get(Database::class); parent::__construct($data); } @@ -254,6 +265,11 @@ protected function insertLogo(&$page, $store = null) ); if ($image) { $imagePath = '/sales/store/logo/' . $image; + if ($this->fileStorageDatabase->checkDbUsage() && + !$this->_mediaDirectory->isFile($imagePath) + ) { + $this->fileStorageDatabase->saveFileToFilesystem($imagePath); + } if ($this->_mediaDirectory->isFile($imagePath)) { $image = \Zend_Pdf_Image::imageWithPath($this->_mediaDirectory->getAbsolutePath($imagePath)); $top = 830; diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/Pdf/InvoiceTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/Pdf/InvoiceTest.php index ae196c1cb5ad7..a30d0a8327d0b 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/Pdf/InvoiceTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/Pdf/InvoiceTest.php @@ -5,6 +5,18 @@ */ namespace Magento\Sales\Test\Unit\Model\Order\Pdf; +use Magento\MediaStorage\Helper\File\Storage\Database; +use Magento\Sales\Model\Order\Invoice; +use Magento\Sales\Model\Order; +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Sales\Model\Order\Address; +use Magento\Sales\Model\Order\Address\Renderer; + +/** + * Class InvoiceTest + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ class InvoiceTest extends \PHPUnit\Framework\TestCase { /** @@ -17,13 +29,38 @@ class InvoiceTest extends \PHPUnit\Framework\TestCase */ protected $_pdfConfigMock; + /** + * @var Database|\PHPUnit_Framework_MockObject_MockObject + */ + protected $databaseMock; + + /** + * @var ScopeConfigInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $scopeConfigMock; + + /** + * @var \Magento\Framework\Filesystem\Directory\Write|\PHPUnit_Framework_MockObject_MockObject + */ + protected $directoryMock; + + /** + * @var Renderer|\PHPUnit_Framework_MockObject_MockObject + */ + protected $addressRendererMock; + + /** + * @var \Magento\Payment\Helper\Data|\PHPUnit_Framework_MockObject_MockObject + */ + protected $paymentDataMock; + protected function setUp() { $this->_pdfConfigMock = $this->getMockBuilder(\Magento\Sales\Model\Order\Pdf\Config::class) ->disableOriginalConstructor() ->getMock(); - $directoryMock = $this->createMock(\Magento\Framework\Filesystem\Directory\Write::class); - $directoryMock->expects($this->any())->method('getAbsolutePath')->will( + $this->directoryMock = $this->createMock(\Magento\Framework\Filesystem\Directory\Write::class); + $this->directoryMock->expects($this->any())->method('getAbsolutePath')->will( $this->returnCallback( function ($argument) { return BP . '/' . $argument; @@ -31,8 +68,17 @@ function ($argument) { ) ); $filesystemMock = $this->createMock(\Magento\Framework\Filesystem::class); - $filesystemMock->expects($this->any())->method('getDirectoryRead')->will($this->returnValue($directoryMock)); - $filesystemMock->expects($this->any())->method('getDirectoryWrite')->will($this->returnValue($directoryMock)); + $filesystemMock->expects($this->any()) + ->method('getDirectoryRead') + ->will($this->returnValue($this->directoryMock)); + $filesystemMock->expects($this->any()) + ->method('getDirectoryWrite') + ->will($this->returnValue($this->directoryMock)); + + $this->databaseMock = $this->createMock(Database::class); + $this->scopeConfigMock = $this->createMock(ScopeConfigInterface::class); + $this->addressRendererMock = $this->createMock(Renderer::class); + $this->paymentDataMock = $this->createMock(\Magento\Payment\Helper\Data::class); $helper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); $this->_model = $helper->getObject( @@ -40,6 +86,11 @@ function ($argument) { [ 'filesystem' => $filesystemMock, 'pdfConfig' => $this->_pdfConfigMock, + 'fileStorageDatabase' => $this->databaseMock, + 'scopeConfig' => $this->scopeConfigMock, + 'addressRenderer' => $this->addressRendererMock, + 'string' => new \Magento\Framework\Stdlib\StringUtils(), + 'paymentData' => $this->paymentDataMock ] ); } @@ -72,4 +123,83 @@ public function testGetPdfInitRenderer() $renderers->getValue($this->_model) ); } + + public function testInsertLogoDatabaseMediaStorage() + { + $filename = 'image.jpg'; + $path = '/sales/store/logo/'; + + $this->_pdfConfigMock->expects($this->once()) + ->method('getRenderersPerProduct') + ->with('invoice') + ->will($this->returnValue(['product_type_one' => 'Renderer_Type_One_Product_One'])); + $this->_pdfConfigMock->expects($this->any()) + ->method('getTotals') + ->will($this->returnValue([])); + + $block = $this->getMockBuilder(\Magento\Framework\View\Element\Template::class) + ->disableOriginalConstructor() + ->setMethods(['setIsSecureMode','toPdf']) + ->getMock(); + $block->expects($this->any()) + ->method('setIsSecureMode') + ->willReturn($block); + $block->expects($this->any()) + ->method('toPdf') + ->will($this->returnValue('')); + $this->paymentDataMock->expects($this->any()) + ->method('getInfoBlock') + ->willReturn($block); + + $this->addressRendererMock->expects($this->any()) + ->method('format') + ->will($this->returnValue('')); + + $this->databaseMock->expects($this->any()) + ->method('checkDbUsage') + ->will($this->returnValue(true)); + + $invoiceMock = $this->createMock(Invoice::class); + $orderMock = $this->createMock(Order::class); + $addressMock = $this->createMock(Address::class); + $orderMock->expects($this->any()) + ->method('getBillingAddress') + ->willReturn($addressMock); + $orderMock->expects($this->any()) + ->method('getIsVirtual') + ->will($this->returnValue(true)); + $infoMock = $this->createMock(\Magento\Payment\Model\InfoInterface::class); + $orderMock->expects($this->any()) + ->method('getPayment') + ->willReturn($infoMock); + $invoiceMock->expects($this->any()) + ->method('getOrder') + ->willReturn($orderMock); + $invoiceMock->expects($this->any()) + ->method('getAllItems') + ->willReturn([]); + + $this->scopeConfigMock->expects($this->at(0)) + ->method('getValue') + ->with('sales/identity/logo', \Magento\Store\Model\ScopeInterface::SCOPE_STORE, null) + ->will($this->returnValue($filename)); + $this->scopeConfigMock->expects($this->at(1)) + ->method('getValue') + ->with('sales/identity/address', \Magento\Store\Model\ScopeInterface::SCOPE_STORE, null) + ->will($this->returnValue('')); + + $this->directoryMock->expects($this->any()) + ->method('isFile') + ->with($path . $filename) + ->willReturnOnConsecutiveCalls( + $this->returnValue(false), + $this->returnValue(false) + ); + + $this->databaseMock->expects($this->once()) + ->method('saveFileToFilesystem') + ->with($path . $filename); + + $this->_model->getPdf([$invoiceMock]); + } } From e164c89687e92e33cdc413ff19d34656b9fe311b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Niederges=C3=A4=C3=9F?= <dng-dev@users.noreply.github.com> Date: Fri, 19 Jul 2019 12:49:19 +0200 Subject: [PATCH 728/773] Fix for PHP_CodeSniffer error after app:config:dump --- .../Framework/App/DeploymentConfig/Writer/PhpFormatter.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/App/DeploymentConfig/Writer/PhpFormatter.php b/lib/internal/Magento/Framework/App/DeploymentConfig/Writer/PhpFormatter.php index d5a89c56b689f..9677cebfc6f98 100644 --- a/lib/internal/Magento/Framework/App/DeploymentConfig/Writer/PhpFormatter.php +++ b/lib/internal/Magento/Framework/App/DeploymentConfig/Writer/PhpFormatter.php @@ -80,7 +80,9 @@ private function formatData($data, $comments = [], $prefix = ' ') */ private function varExportShort($var, int $depth = 0) { - if (!is_array($var)) { + if(null === $var){ + return 'null'; + }elseif (!is_array($var)) { return var_export($var, true); } From 77fbbe2a1b8aa56282a0b7f35dab9eb1fc5abec3 Mon Sep 17 00:00:00 2001 From: Nikita Fomin <nikita.fomin@transoftgroup.com> Date: Fri, 19 Jul 2019 14:06:19 +0300 Subject: [PATCH 729/773] MC-10812: Random B2B test fail: Magento\FunctionalTestingFramework.functional.AdminSettingCustomerPhoneNumberTest --- ...hDefaultAddressWithoutPhoneActionGroup.xml | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 app/code/Magento/Customer/Test/Mftf/ActionGroup/AdminCreateCustomerWithDefaultAddressWithoutPhoneActionGroup.xml diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/AdminCreateCustomerWithDefaultAddressWithoutPhoneActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AdminCreateCustomerWithDefaultAddressWithoutPhoneActionGroup.xml new file mode 100644 index 0000000000000..ff6512ba5fc0f --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AdminCreateCustomerWithDefaultAddressWithoutPhoneActionGroup.xml @@ -0,0 +1,43 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminCreateCustomerWithDefaultAddressWithoutPhoneActionGroup"> + <arguments> + <argument name="customer" defaultValue="Simple_US_Customer"/> + <argument name="address" defaultValue="US_Address_NY"/> + </arguments> + <amOnPage url="{{AdminCustomerPage.url}}" stepKey="goToCustomersPage"/> + <click selector="{{AdminCustomerGridMainActionsSection.addNewCustomer}}" stepKey="addNewCustomer"/> + <fillField selector="{{AdminCustomerAccountInformationSection.firstName}}" userInput="{{customer.firstname}}" stepKey="fillFirstName"/> + <fillField selector="{{AdminCustomerAccountInformationSection.lastName}}" userInput="{{customer.lastname}}" stepKey="fillLastName"/> + <fillField selector="{{AdminCustomerAccountInformationSection.email}}" userInput="{{customer.email}}" stepKey="fillEmail"/> + <click selector="{{AdminMainActionsSection.saveAndContinue}}" stepKey="clickSaveAndContinue"/> + <waitForElementVisible selector="{{AdminMessagesSection.success}}" stepKey="waitForSuccessMessage"/> + <see selector="{{AdminMessagesSection.success}}" userInput="You saved the customer." stepKey="seeSuccessMessage"/> + <click selector="{{AdminCustomerAccountInformationSection.addressesButton}}" stepKey="goToAddresses"/> + <waitForPageLoad stepKey="waitForAddresses"/> + <click selector="{{AdminCustomerAddressesSection.addNewAddress}}" stepKey="clickOnAddNewAddress"/> + <waitForPageLoad stepKey="waitForAddressFieldsLoad"/> + <click selector="{{AdminCustomerAddressesSection.defaultBillingAddress}}" stepKey="defaultBillingAddressSetYes"/> + <click selector="{{AdminCustomerAddressesSection.defaultShippingAddress}}" stepKey="defaultShippingAddressSetYes"/> + <fillField selector="{{AdminCustomerAddressesSection.firstNameForAddress}}" userInput="{{address.firstname}}" stepKey="fillFirstNameForAddress"/> + <fillField selector="{{AdminCustomerAddressesSection.lastNameForAddress}}" userInput="{{address.lastname}}" stepKey="fillLastNameForAddress"/> + <fillField selector="{{AdminCustomerAddressesSection.streetAddress}}" userInput="{{address.street[0]}}" stepKey="fillStreetAddress"/> + <fillField selector="{{AdminCustomerAddressesSection.city}}" userInput="{{address.city}}" stepKey="fillCity"/> + <selectOption selector="{{AdminCustomerAddressesSection.country}}" userInput="{{address.country}}" stepKey="selectCountry"/> + <selectOption selector="{{AdminCustomerAddressesSection.state}}" userInput="{{address.state}}" stepKey="selectState"/> + <fillField selector="{{AdminCustomerAddressesSection.zip}}" userInput="{{address.postcode}}" stepKey="fillZip"/> + <click selector="{{AdminSlideOutDialogSection.saveButton}}" stepKey="saveAddress"/> + <dontSee selector="{{AdminCustomerAddressesSection.phoneNumberRequiredMessage}}" stepKey="dontSeePhoneErrorMessage"/> + <click selector="{{AdminMainActionsSection.save}}" stepKey="save"/> + <waitForElementVisible selector="{{AdminMessagesSection.success}}" stepKey="waitForSuccessfullyCreatedMessage"/> + <see selector="{{AdminMessagesSection.success}}" userInput="You saved the customer." stepKey="seeSuccessMessageAgain"/> + </actionGroup> +</actionGroups> From 180568a922cefe631b74d47d7966e6bd3cb07448 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Niederges=C3=A4=C3=9F?= <dng-dev@users.noreply.github.com> Date: Fri, 19 Jul 2019 14:03:37 +0200 Subject: [PATCH 730/773] Updated code Formatting --- .../Framework/App/DeploymentConfig/Writer/PhpFormatter.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/internal/Magento/Framework/App/DeploymentConfig/Writer/PhpFormatter.php b/lib/internal/Magento/Framework/App/DeploymentConfig/Writer/PhpFormatter.php index 9677cebfc6f98..f9a4067e8b756 100644 --- a/lib/internal/Magento/Framework/App/DeploymentConfig/Writer/PhpFormatter.php +++ b/lib/internal/Magento/Framework/App/DeploymentConfig/Writer/PhpFormatter.php @@ -80,9 +80,9 @@ private function formatData($data, $comments = [], $prefix = ' ') */ private function varExportShort($var, int $depth = 0) { - if(null === $var){ + if (null === $var) { return 'null'; - }elseif (!is_array($var)) { + } elseif (!is_array($var)) { return var_export($var, true); } From a99014e3ef132ecf8f7949b6411760c07678f9cc Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <p.bystritsky@yandex.ru> Date: Fri, 19 Jul 2019 16:09:09 +0300 Subject: [PATCH 731/773] magento/magento2#23789: CommentLevelsSniff works incorrect with @magento_import statement. --- .../Sniffs/Less/CommentLevelsSniff.php | 34 ++++++++++++++----- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/dev/tests/static/framework/Magento/Sniffs/Less/CommentLevelsSniff.php b/dev/tests/static/framework/Magento/Sniffs/Less/CommentLevelsSniff.php index 41c970d4cb496..6ce6b2a5c0f6a 100644 --- a/dev/tests/static/framework/Magento/Sniffs/Less/CommentLevelsSniff.php +++ b/dev/tests/static/framework/Magento/Sniffs/Less/CommentLevelsSniff.php @@ -5,8 +5,8 @@ */ namespace Magento\Sniffs\Less; -use PHP_CodeSniffer\Sniffs\Sniff; use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; /** * Class CommentLevelsSniff @@ -72,14 +72,7 @@ public function process(File $phpcsFile, $stackPtr) return; } - // validation of levels comments - if (!in_array($tokens[$stackPtr + 1]['content'], [ - TokenizerSymbolsInterface::DOUBLE_WHITESPACE, - TokenizerSymbolsInterface::NEW_LINE, - ]) - ) { - $phpcsFile->addError('Level\'s comment does not have 2 spaces after "//"', $stackPtr, 'SpacesMissed'); - } + $this->validateCommentLevel($phpcsFile, $stackPtr, $tokens); if (!$this->isNthLevelComment($phpcsFile, $stackPtr, $tokens)) { return; @@ -195,4 +188,27 @@ private function checkNthLevelComment(File $phpcsFile, $stackPtr, array $tokens) return $correct; } + + /** + * Validation of comment level. + * + * @param File $phpcsFile + * @param int $stackPtr + * @param array $tokens + */ + private function validateCommentLevel(File $phpcsFile, int $stackPtr, array $tokens): void + { + if ($tokens[$stackPtr + 2]['content'] !== 'magento_import' && + !in_array( + $tokens[$stackPtr + 1]['content'], + [ + TokenizerSymbolsInterface::DOUBLE_WHITESPACE, + TokenizerSymbolsInterface::NEW_LINE, + ], + true + ) + ) { + $phpcsFile->addError('Level\'s comment does not have 2 spaces after "//"', $stackPtr, 'SpacesMissed'); + } + } } From c1979da7c03d67bad717e378759a28eaad099f24 Mon Sep 17 00:00:00 2001 From: Lena Orobei <oorobei@magento.com> Date: Fri, 19 Jul 2019 10:10:59 -0500 Subject: [PATCH 732/773] magento/graphql-ce#757 Remove PaymentMethodAdditionalDataInput From Schema - fix integration tests --- .../Resolver/Customer/PlaceOrderWithAuthorizeNetTest.php | 5 ++--- .../Customer/SetAuthorizeNetPaymentMethodOnCartTest.php | 5 ++--- .../Model/Resolver/Guest/PlaceOrderWithAuthorizeNetTest.php | 5 ++--- .../Guest/SetAuthorizeNetPaymentMethodOnCartTest.php | 5 ++--- .../Resolver/Customer/PaypalExpressSetPaymentMethodTest.php | 2 -- .../Resolver/Customer/PlaceOrderWithPayflowLinkTest.php | 2 -- .../Model/Resolver/Customer/PlaceOrderWithPayflowProTest.php | 2 -- .../Resolver/Guest/PaypalExpressSetPaymentMethodTest.php | 2 -- .../Resolver/Guest/PaypalPayflowProSetPaymentMethodTest.php | 2 -- .../Model/Resolver/Guest/PlaceOrderWithPayflowLinkTest.php | 4 ---- .../Resolver/Guest/SetPaymentMethodAsPayflowLinkTest.php | 4 ---- 11 files changed, 8 insertions(+), 30 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/AuthorizenetGraphQl/Model/Resolver/Customer/PlaceOrderWithAuthorizeNetTest.php b/dev/tests/integration/testsuite/Magento/AuthorizenetGraphQl/Model/Resolver/Customer/PlaceOrderWithAuthorizeNetTest.php index 90ec6686c5a3c..794e589002e73 100644 --- a/dev/tests/integration/testsuite/Magento/AuthorizenetGraphQl/Model/Resolver/Customer/PlaceOrderWithAuthorizeNetTest.php +++ b/dev/tests/integration/testsuite/Magento/AuthorizenetGraphQl/Model/Resolver/Customer/PlaceOrderWithAuthorizeNetTest.php @@ -94,11 +94,10 @@ public function testDispatchToPlaceOrderWithRegisteredCustomer(): void cart_id: "$cartId" payment_method: { code: "$paymentMethod" - additional_data: - {authorizenet_acceptjs: + authorizenet_acceptjs: {opaque_data_descriptor: "mydescriptor", opaque_data_value: "myvalue", - cc_last_4: 1111}} + cc_last_4: 1111} } }) { cart { diff --git a/dev/tests/integration/testsuite/Magento/AuthorizenetGraphQl/Model/Resolver/Customer/SetAuthorizeNetPaymentMethodOnCartTest.php b/dev/tests/integration/testsuite/Magento/AuthorizenetGraphQl/Model/Resolver/Customer/SetAuthorizeNetPaymentMethodOnCartTest.php index e304216bc4a77..b82469c61d288 100644 --- a/dev/tests/integration/testsuite/Magento/AuthorizenetGraphQl/Model/Resolver/Customer/SetAuthorizeNetPaymentMethodOnCartTest.php +++ b/dev/tests/integration/testsuite/Magento/AuthorizenetGraphQl/Model/Resolver/Customer/SetAuthorizeNetPaymentMethodOnCartTest.php @@ -69,11 +69,10 @@ public function testDispatchToSetPaymentMethodWithAuthorizenet(): void cart_id: "$maskedQuoteId" payment_method: { code: "$methodCode" - additional_data: - {authorizenet_acceptjs: + authorizenet_acceptjs: {opaque_data_descriptor: "COMMON.ACCEPT.INAPP.PAYMENT", opaque_data_value: "abx", - cc_last_4: 1111}} + cc_last_4: 1111} } }) { cart { diff --git a/dev/tests/integration/testsuite/Magento/AuthorizenetGraphQl/Model/Resolver/Guest/PlaceOrderWithAuthorizeNetTest.php b/dev/tests/integration/testsuite/Magento/AuthorizenetGraphQl/Model/Resolver/Guest/PlaceOrderWithAuthorizeNetTest.php index 383abf81a111a..070543a0880e8 100644 --- a/dev/tests/integration/testsuite/Magento/AuthorizenetGraphQl/Model/Resolver/Guest/PlaceOrderWithAuthorizeNetTest.php +++ b/dev/tests/integration/testsuite/Magento/AuthorizenetGraphQl/Model/Resolver/Guest/PlaceOrderWithAuthorizeNetTest.php @@ -94,11 +94,10 @@ public function testDispatchToPlaceAnOrderWithAuthorizenet(): void cart_id: "$cartId" payment_method: { code: "$paymentMethod" - additional_data: - {authorizenet_acceptjs: + authorizenet_acceptjs: {opaque_data_descriptor: "mydescriptor", opaque_data_value: "myvalue", - cc_last_4: 1111}} + cc_last_4: 1111} } }) { cart { diff --git a/dev/tests/integration/testsuite/Magento/AuthorizenetGraphQl/Model/Resolver/Guest/SetAuthorizeNetPaymentMethodOnCartTest.php b/dev/tests/integration/testsuite/Magento/AuthorizenetGraphQl/Model/Resolver/Guest/SetAuthorizeNetPaymentMethodOnCartTest.php index fef20df4ee931..ff526a491b5d7 100644 --- a/dev/tests/integration/testsuite/Magento/AuthorizenetGraphQl/Model/Resolver/Guest/SetAuthorizeNetPaymentMethodOnCartTest.php +++ b/dev/tests/integration/testsuite/Magento/AuthorizenetGraphQl/Model/Resolver/Guest/SetAuthorizeNetPaymentMethodOnCartTest.php @@ -64,11 +64,10 @@ public function testDispatchToSetPaymentMethodWithAuthorizenet(): void cart_id: "$maskedQuoteId" payment_method: { code: "$methodCode" - additional_data: - {authorizenet_acceptjs: + authorizenet_acceptjs: {opaque_data_descriptor: "COMMON.ACCEPT.INAPP.PAYMENT", opaque_data_value: "abx", - cc_last_4: 1111}} + cc_last_4: 1111} } }) { cart { diff --git a/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Customer/PaypalExpressSetPaymentMethodTest.php b/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Customer/PaypalExpressSetPaymentMethodTest.php index f367c0242fdb0..b194bdbde307c 100644 --- a/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Customer/PaypalExpressSetPaymentMethodTest.php +++ b/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Customer/PaypalExpressSetPaymentMethodTest.php @@ -98,7 +98,6 @@ public function testResolve(string $paymentMethod): void setPaymentMethodOnCart(input: { payment_method: { code: "{$paymentMethod}", - additional_data: { paypal_express: { payer_id: "$payerId", token: "$token" @@ -107,7 +106,6 @@ public function testResolve(string $paymentMethod): void payer_id: "$payerId", token: "$token" } - } }, cart_id: "{$maskedCartId}"}) { diff --git a/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Customer/PlaceOrderWithPayflowLinkTest.php b/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Customer/PlaceOrderWithPayflowLinkTest.php index b5d2aeb0803a5..96d80dfc28053 100644 --- a/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Customer/PlaceOrderWithPayflowLinkTest.php +++ b/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Customer/PlaceOrderWithPayflowLinkTest.php @@ -124,13 +124,11 @@ public function testResolvePlaceOrderWithPayflowLinkForCustomer(): void cart_id: "$cartId" payment_method: { code: "$paymentMethod" - additional_data: { payflow_link: { cancel_url:"{$baseUrl}paypal/payflow/cancelPayment" return_url:"{$baseUrl}paypal/payflow/returnUrl" } - } } }) { cart { diff --git a/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Customer/PlaceOrderWithPayflowProTest.php b/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Customer/PlaceOrderWithPayflowProTest.php index 444588195e0ae..b8efe7c0319b5 100644 --- a/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Customer/PlaceOrderWithPayflowProTest.php +++ b/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Customer/PlaceOrderWithPayflowProTest.php @@ -80,7 +80,6 @@ public function testResolveCustomer(): void setPaymentMethodOnCart(input: { payment_method: { code: "{$paymentMethod}", - additional_data: { payflowpro: { cc_details: { cc_exp_month: 12, @@ -88,7 +87,6 @@ public function testResolveCustomer(): void cc_last_4: 1111, cc_type: "IV", } - } } }, cart_id: "{$cartId}"}) diff --git a/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/PaypalExpressSetPaymentMethodTest.php b/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/PaypalExpressSetPaymentMethodTest.php index 0b8b18d88e00e..e5e1955bbf81b 100644 --- a/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/PaypalExpressSetPaymentMethodTest.php +++ b/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/PaypalExpressSetPaymentMethodTest.php @@ -96,7 +96,6 @@ public function testResolveGuest(string $paymentMethod): void setPaymentMethodOnCart(input: { payment_method: { code: "{$paymentMethod}", - additional_data: { paypal_express: { payer_id: "$payerId", token: "$token" @@ -105,7 +104,6 @@ public function testResolveGuest(string $paymentMethod): void payer_id: "$payerId", token: "$token" } - } }, cart_id: "{$cartId}"}) { diff --git a/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/PaypalPayflowProSetPaymentMethodTest.php b/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/PaypalPayflowProSetPaymentMethodTest.php index 8121facaf0f55..1ef054fbdaac9 100644 --- a/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/PaypalPayflowProSetPaymentMethodTest.php +++ b/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/PaypalPayflowProSetPaymentMethodTest.php @@ -80,7 +80,6 @@ public function testResolveGuest(): void setPaymentMethodOnCart(input: { payment_method: { code: "{$paymentMethod}", - additional_data: { payflowpro: { cc_details: { cc_exp_month: 12, @@ -88,7 +87,6 @@ public function testResolveGuest(): void cc_last_4: 1111, cc_type: "IV", } - } } }, cart_id: "{$cartId}"}) diff --git a/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/PlaceOrderWithPayflowLinkTest.php b/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/PlaceOrderWithPayflowLinkTest.php index 789d4b34c8ced..7ad0659839bc7 100644 --- a/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/PlaceOrderWithPayflowLinkTest.php +++ b/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/PlaceOrderWithPayflowLinkTest.php @@ -117,14 +117,12 @@ public function testResolvePlaceOrderWithPayflowLink(): void cart_id: "$cartId" payment_method: { code: "$paymentMethod" - additional_data: { payflow_link: { cancel_url:"http://mage.test/paypal/payflow/cancel" return_url:"http://mage.test/paypal/payflow/return" error_url:"http://mage.test/paypal/payflow/error" } - } } }) { cart { @@ -221,14 +219,12 @@ public function testResolveWithPayflowLinkDeclined(): void cart_id: "$cartId" payment_method: { code: "$paymentMethod" - additional_data: { payflow_link: { cancel_url:"http://mage.test/paypal/payflow/cancelPayment" return_url:"http://mage.test/paypal/payflow/returnUrl" error_url:"http://mage.test/paypal/payflow/returnUrl" } - } } }) { cart { diff --git a/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/SetPaymentMethodAsPayflowLinkTest.php b/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/SetPaymentMethodAsPayflowLinkTest.php index 91e5b06e56e01..a4b61ed11d784 100644 --- a/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/SetPaymentMethodAsPayflowLinkTest.php +++ b/dev/tests/integration/testsuite/Magento/PaypalGraphQl/Model/Resolver/Guest/SetPaymentMethodAsPayflowLinkTest.php @@ -71,13 +71,11 @@ public function testSetPayflowLinkAsPaymentMethod(): void cart_id: "$maskedCartId" payment_method: { code: "$paymentMethod" - additional_data: { payflow_link: { return_url:"http://magento.com/paypal/payflow/link/success" cancel_url:"http://magento.com/paypal/payflow/link/cancel" error_url:"http://magento.com/paypal/payflow/link/error" } - } } }) { cart { @@ -147,13 +145,11 @@ public function testInvalidUrl(): void cart_id: "$cartId" payment_method: { code: "$paymentMethod" - additional_data: { payflow_link: { return_url:"http://magento.com/paypal/payflow/link/sucess" cancel_url:"http://magento.com/paypal/payflow/link/cancel" error_url:"/not/a/validUrl" } - } } }) { cart { From f02f393f47748f2e621b08b0a081249cb3ea61cc Mon Sep 17 00:00:00 2001 From: vital_pantsialeyeu <vital_pantsialeyeu@epam.com> Date: Fri, 19 Jul 2019 19:14:10 +0300 Subject: [PATCH 733/773] MC-17387: Fatal error appears when adding bundle product to Cart from Wish list page - Added stories for test annotations --- .../Test/AdminAddBundleProductToCartFromWishListPageTest.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminAddBundleProductToCartFromWishListPageTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminAddBundleProductToCartFromWishListPageTest.xml index 76a2c4c739e09..2a4b119a5cabc 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminAddBundleProductToCartFromWishListPageTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminAddBundleProductToCartFromWishListPageTest.xml @@ -10,6 +10,7 @@ <test name="AdminAddBundleProductToCartFromWishListPageTest"> <annotations> <features value="Catalog"/> + <stories value="Add bundle product to Cart"/> <title value="Add bundle product to Cart from Wish list page"/> <description value="Add bundle product to Cart from Wish list page"/> <severity value="MAJOR"/> From 5f5ac27de933691d42f57c694262edeabc5df396 Mon Sep 17 00:00:00 2001 From: Andrii Dimov <adimov@adobe.com> Date: Fri, 19 Jul 2019 11:21:36 -0500 Subject: [PATCH 734/773] MC-18321: Remove usage of page_cache/block/render controller in performance test --- setup/performance-toolkit/benchmark.jmx | 69 ------------------------- 1 file changed, 69 deletions(-) diff --git a/setup/performance-toolkit/benchmark.jmx b/setup/performance-toolkit/benchmark.jmx index e92c0bd738126..1fa61c21d8003 100644 --- a/setup/performance-toolkit/benchmark.jmx +++ b/setup/performance-toolkit/benchmark.jmx @@ -2478,75 +2478,6 @@ if (props.get("cms_pages") == null) { <stringProp name="HTTPSampler.embedded_url_re"/> <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/setup/warmup_add_to_cart.jmx</stringProp></HTTPSamplerProxy> <hashTree/> - - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="SetUp - Ajax Load Login Form" enabled="true"> - <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> - <collectionProp name="Arguments.arguments"> - <elementProp name="blocks" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">true</boolProp> - <stringProp name="Argument.value">["customer_form_login"]</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">blocks</stringProp> - </elementProp> - <elementProp name="handles" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">true</boolProp> - <stringProp name="Argument.value">["default","customer_account_login"]</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">handles</stringProp> - </elementProp> - <elementProp name="originalRequest" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">true</boolProp> - <stringProp name="Argument.value">{"route":"customer","controller":"account","action":"login","uri":"/customer/account/login/"}</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">originalRequest</stringProp> - </elementProp> - <elementProp name="ajax" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">true</boolProp> - <stringProp name="Argument.value">true</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">ajax</stringProp> - </elementProp> - <elementProp name="isAjax" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">true</boolProp> - <stringProp name="Argument.value">true</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">isAjax</stringProp> - </elementProp> - </collectionProp> - </elementProp> - <stringProp name="HTTPSampler.domain"/> - <stringProp name="HTTPSampler.port"/> - <stringProp name="HTTPSampler.connect_timeout">60000</stringProp> - <stringProp name="HTTPSampler.response_timeout">200000</stringProp> - <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> - <stringProp name="HTTPSampler.contentEncoding"/> - <stringProp name="HTTPSampler.path">${base_path}page_cache/block/render/</stringProp> - <stringProp name="HTTPSampler.method">GET</stringProp> - <boolProp name="HTTPSampler.follow_redirects">true</boolProp> - <boolProp name="HTTPSampler.auto_redirects">false</boolProp> - <boolProp name="HTTPSampler.use_keepalive">true</boolProp> - <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"/> - <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/setup/ajax_load_login_form.jmx</stringProp></HTTPSamplerProxy> - <hashTree> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="940598773">"customer_form_login"</stringProp> - <stringProp name="1951684663">Registered Customers</stringProp> - <stringProp name="474011748">form_key</stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">2</intProp> - </ResponseAssertion> - <hashTree/> - </hashTree> </hashTree> <ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Frontend Pool" enabled="true"> From fb7d3aeec66ef78767bd1faf48d57711f62ec593 Mon Sep 17 00:00:00 2001 From: Andrea Parmeggiani <info@textarea.it> Date: Fri, 19 Jul 2019 18:21:50 +0200 Subject: [PATCH 735/773] Moved "Zero Subtotal Checkout" translation to Payment Module --- app/code/Magento/OfflinePayments/i18n/en_US.csv | 1 - app/code/Magento/Payment/i18n/en_US.csv | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/OfflinePayments/i18n/en_US.csv b/app/code/Magento/OfflinePayments/i18n/en_US.csv index 5a180f7af4944..c5e503f4f9b6a 100644 --- a/app/code/Magento/OfflinePayments/i18n/en_US.csv +++ b/app/code/Magento/OfflinePayments/i18n/en_US.csv @@ -21,5 +21,4 @@ Title,Title "Bank Transfer Payment","Bank Transfer Payment" Instructions,Instructions "Cash On Delivery Payment","Cash On Delivery Payment" -"Zero Subtotal Checkout","Zero Subtotal Checkout" "Automatically Invoice All Items","Automatically Invoice All Items" diff --git a/app/code/Magento/Payment/i18n/en_US.csv b/app/code/Magento/Payment/i18n/en_US.csv index d5a79becec22b..939215e995d84 100644 --- a/app/code/Magento/Payment/i18n/en_US.csv +++ b/app/code/Magento/Payment/i18n/en_US.csv @@ -58,3 +58,4 @@ No,No "Payment Methods Section","Payment Methods Section" "Payment Services","Payment Services" "Payment Methods","Payment Methods" +"Zero Subtotal Checkout","Zero Subtotal Checkout" From 4e0742e9b753b9f946e3264e183485a61cfbd081 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun <ogorkun@magento.com> Date: Fri, 19 Jul 2019 11:34:13 -0500 Subject: [PATCH 736/773] MC-17489: Require specific suffix for HTML binding --- .../static/framework/Magento/Sniffs/Html/HtmlBindingSniff.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/tests/static/framework/Magento/Sniffs/Html/HtmlBindingSniff.php b/dev/tests/static/framework/Magento/Sniffs/Html/HtmlBindingSniff.php index c0d0e67b66e06..1d09b7a659af4 100644 --- a/dev/tests/static/framework/Magento/Sniffs/Html/HtmlBindingSniff.php +++ b/dev/tests/static/framework/Magento/Sniffs/Html/HtmlBindingSniff.php @@ -39,7 +39,7 @@ private function loadHtmlDocument(int $stackPointer, File $file): ?\DOMDocument @$dom->loadHTML($html); return $dom; } catch (\Throwable $exception) { - //Invalid HTML, skipping + return null; } } From 1d419dc795b4105e6a35434873ab2efce0b7072b Mon Sep 17 00:00:00 2001 From: Gabriel Fernandes <gfernandes410@gmail.com> Date: Fri, 19 Jul 2019 13:46:29 -0300 Subject: [PATCH 737/773] Remove duplicate declaration On line 33 and 37 there is a duplicate declaration of $this->formKey. --- app/code/Magento/Backend/Block/Page/RequireJs.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/code/Magento/Backend/Block/Page/RequireJs.php b/app/code/Magento/Backend/Block/Page/RequireJs.php index 0a8e9c11ec69f..7fac44068a3fb 100644 --- a/app/code/Magento/Backend/Block/Page/RequireJs.php +++ b/app/code/Magento/Backend/Block/Page/RequireJs.php @@ -29,7 +29,6 @@ public function __construct( \Magento\Framework\Data\Form\FormKey $formKey, array $data = [] ) { - $this->formKey = $formKey; parent::__construct( $context, $data From 145c7b24634c235a1489739426d1dc828e4892c7 Mon Sep 17 00:00:00 2001 From: Roman Lytvynenko <lytvynen@adobe.com> Date: Fri, 19 Jul 2019 12:18:51 -0500 Subject: [PATCH 738/773] MC-18094: Full page cache issue with non-default store view --- .../Magento/Store/App/Action/Plugin/Context.php | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/Store/App/Action/Plugin/Context.php b/app/code/Magento/Store/App/Action/Plugin/Context.php index 0d34179d3c63e..5d324c4b468f4 100644 --- a/app/code/Magento/Store/App/Action/Plugin/Context.php +++ b/app/code/Magento/Store/App/Action/Plugin/Context.php @@ -11,6 +11,7 @@ use Magento\Framework\Exception\NotFoundException; use Magento\Store\Api\Data\StoreInterface; use Magento\Store\Api\StoreCookieManagerInterface; +use Magento\Store\Model\Store; use Magento\Store\Model\StoreManagerInterface; use Magento\Framework\App\Action\AbstractAction; use Magento\Framework\App\RequestInterface; @@ -127,14 +128,19 @@ private function processInvalidStoreRequested( * * @param StoreInterface $store * @return void + * @throws \Magento\Framework\Exception\LocalizedException */ private function updateContext(StoreInterface $store) { - $this->httpContext->setValue( - StoreManagerInterface::CONTEXT_STORE, - $store->getCode(), - $this->storeManager->getDefaultStoreView()->getCode() - ); + if (!$store->getConfig(Store::XML_PATH_STORE_IN_URL) || + $store->getId() == $this->storeManager->getDefaultStoreView()->getId() + ) { + $this->httpContext->setValue( + StoreManagerInterface::CONTEXT_STORE, + $store->getCode(), + $this->storeManager->getDefaultStoreView()->getCode() + ); + } /** @var StoreInterface $defaultStore */ $defaultStore = $this->storeManager->getWebsite()->getDefaultStore(); From 9c42b8e2b1bf1fa42a9026f73afe9811985e3e0b Mon Sep 17 00:00:00 2001 From: Daniel Renaud <drenaud@magento.com> Date: Fri, 19 Jul 2019 13:45:26 -0500 Subject: [PATCH 739/773] MC-14863: Varnish Upgrade to 6.2.0 --- app/code/Magento/PageCache/Model/Config.php | 2 +- .../Magento/PageCache/Model/Varnish/VclTemplateLocator.php | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/PageCache/Model/Config.php b/app/code/Magento/PageCache/Model/Config.php index 22d09e2f5dd9e..079e371d34363 100644 --- a/app/code/Magento/PageCache/Model/Config.php +++ b/app/code/Magento/PageCache/Model/Config.php @@ -50,7 +50,7 @@ class Config protected $_scopeConfig; /** - * XML path to Varnish 5 config template path + * XML path to Varnish 6 config template path */ const VARNISH_6_CONFIGURATION_PATH = 'system/full_page_cache/varnish6/path'; diff --git a/app/code/Magento/PageCache/Model/Varnish/VclTemplateLocator.php b/app/code/Magento/PageCache/Model/Varnish/VclTemplateLocator.php index 1550a00af0212..8ad684198f409 100644 --- a/app/code/Magento/PageCache/Model/Varnish/VclTemplateLocator.php +++ b/app/code/Magento/PageCache/Model/Varnish/VclTemplateLocator.php @@ -34,17 +34,17 @@ class VclTemplateLocator implements VclTemplateLocatorInterface const VARNISH_4_CONFIGURATION_PATH = 'system/full_page_cache/varnish4/path'; /** - * + * Varnish 4 supported version */ const VARNISH_SUPPORTED_VERSION_4 = '4'; /** - * + * Varnish 5 supported version */ const VARNISH_SUPPORTED_VERSION_5 = '5'; /** - * + * Varnish 6 supported version */ const VARNISH_SUPPORTED_VERSION_6 = '6'; From 43a7392f5f449f5f62b072041b09d6fb09e2a81d Mon Sep 17 00:00:00 2001 From: Daniel Renaud <drenaud@magento.com> Date: Fri, 19 Jul 2019 14:52:10 -0500 Subject: [PATCH 740/773] MC-17015: [GraphQL] Product Categories query doesn't return all categories where product is visible --- .../Model/Resolver/Categories.php | 77 +++++++++------ .../Resolver/Product/ProductCategories.php | 97 +++++++++++++++++++ 2 files changed, 146 insertions(+), 28 deletions(-) create mode 100644 app/code/Magento/CatalogGraphQl/Model/Resolver/Product/ProductCategories.php diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Categories.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Categories.php index cb392a7b2295d..535fe3a80cd25 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Resolver/Categories.php +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Categories.php @@ -7,6 +7,7 @@ namespace Magento\CatalogGraphQl\Model\Resolver; +use Magento\CatalogGraphQl\Model\Resolver\Product\ProductCategories; use Magento\Framework\Exception\LocalizedException; use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; use Magento\Catalog\Api\Data\CategoryInterface; @@ -18,6 +19,7 @@ use Magento\Framework\GraphQl\Query\ResolverInterface; use Magento\Framework\GraphQl\Query\Resolver\ValueFactory; use Magento\CatalogGraphQl\Model\Category\Hydrator as CategoryHydrator; +use Magento\Store\Model\StoreManagerInterface; /** * Resolver for category objects the product is assigned to. @@ -56,25 +58,41 @@ class Categories implements ResolverInterface */ private $categoryHydrator; + /** + * @var ProductCategories + */ + private $productCategories; + + /** + * @var StoreManagerInterface + */ + private $storeManager; + /** * @param CollectionFactory $collectionFactory * @param AttributesJoiner $attributesJoiner * @param CustomAttributesFlattener $customAttributesFlattener * @param ValueFactory $valueFactory * @param CategoryHydrator $categoryHydrator + * @param ProductCategories $productCategories + * @param StoreManagerInterface $storeManager */ public function __construct( CollectionFactory $collectionFactory, AttributesJoiner $attributesJoiner, CustomAttributesFlattener $customAttributesFlattener, ValueFactory $valueFactory, - CategoryHydrator $categoryHydrator + CategoryHydrator $categoryHydrator, + ProductCategories $productCategories, + StoreManagerInterface $storeManager ) { $this->collection = $collectionFactory->create(); $this->attributesJoiner = $attributesJoiner; $this->customAttributesFlattener = $customAttributesFlattener; $this->valueFactory = $valueFactory; $this->categoryHydrator = $categoryHydrator; + $this->productCategories = $productCategories; + $this->storeManager = $storeManager; } /** @@ -90,39 +108,42 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value /** @var \Magento\Catalog\Model\Product $product */ $product = $value['model']; - $categoryIds = $product->getCategoryIds(); + $storeId = $this->storeManager->getStore()->getId(); + $categoryIds = $this->productCategories->getCategoryIdsByProduct((int)$product->getId(), (int)$storeId); $this->categoryIds = array_merge($this->categoryIds, $categoryIds); $that = $this; - return $this->valueFactory->create(function () use ($that, $categoryIds, $info) { - $categories = []; - if (empty($that->categoryIds)) { - return []; - } + return $this->valueFactory->create( + function () use ($that, $categoryIds, $info) { + $categories = []; + if (empty($that->categoryIds)) { + return []; + } - if (!$this->collection->isLoaded()) { - $that->attributesJoiner->join($info->fieldNodes[0], $this->collection); - $this->collection->addIdFilter($this->categoryIds); - } - /** @var CategoryInterface | \Magento\Catalog\Model\Category $item */ - foreach ($this->collection as $item) { - if (in_array($item->getId(), $categoryIds)) { - // Try to extract all requested fields from the loaded collection data - $categories[$item->getId()] = $this->categoryHydrator->hydrateCategory($item, true); - $categories[$item->getId()]['model'] = $item; - $requestedFields = $that->attributesJoiner->getQueryFields($info->fieldNodes[0]); - $extractedFields = array_keys($categories[$item->getId()]); - $foundFields = array_intersect($requestedFields, $extractedFields); - if (count($requestedFields) === count($foundFields)) { - continue; - } + if (!$this->collection->isLoaded()) { + $that->attributesJoiner->join($info->fieldNodes[0], $this->collection); + $this->collection->addIdFilter($this->categoryIds); + } + /** @var CategoryInterface | \Magento\Catalog\Model\Category $item */ + foreach ($this->collection as $item) { + if (in_array($item->getId(), $categoryIds)) { + // Try to extract all requested fields from the loaded collection data + $categories[$item->getId()] = $this->categoryHydrator->hydrateCategory($item, true); + $categories[$item->getId()]['model'] = $item; + $requestedFields = $that->attributesJoiner->getQueryFields($info->fieldNodes[0]); + $extractedFields = array_keys($categories[$item->getId()]); + $foundFields = array_intersect($requestedFields, $extractedFields); + if (count($requestedFields) === count($foundFields)) { + continue; + } - // If not all requested fields were extracted from the collection, start more complex extraction - $categories[$item->getId()] = $this->categoryHydrator->hydrateCategory($item); + // If not all requested fields were extracted from the collection, start more complex extraction + $categories[$item->getId()] = $this->categoryHydrator->hydrateCategory($item); + } } - } - return $categories; - }); + return $categories; + } + ); } } diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/ProductCategories.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/ProductCategories.php new file mode 100644 index 0000000000000..736f2a8c8e402 --- /dev/null +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/ProductCategories.php @@ -0,0 +1,97 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\CatalogGraphQl\Model\Resolver\Product; + +use Magento\Catalog\Model\Indexer\Category\Product\AbstractAction; +use Magento\Framework\App\ResourceConnection; +use Magento\Framework\Indexer\DimensionFactory; +use Magento\Framework\Indexer\ScopeResolver\IndexScopeResolver; +use Magento\Store\Model\Group; +use Magento\Store\Model\Store; + +/** + * Get all categories where product is visible + */ +class ProductCategories +{ + /** + * @var IndexScopeResolver + */ + private $tableResolver; + + /** + * @var ResourceConnection + */ + private $resourceConnection; + + /** + * @var DimensionFactory + */ + private $dimensionFactory; + + /** + * @param IndexScopeResolver $tableResolver + * @param ResourceConnection $resourceConnection + * @param DimensionFactory $dimensionFactory + */ + public function __construct( + IndexScopeResolver $tableResolver, + ResourceConnection $resourceConnection, + DimensionFactory $dimensionFactory + ) { + $this->tableResolver = $tableResolver; + $this->resourceConnection = $resourceConnection; + $this->dimensionFactory = $dimensionFactory; + } + + /** + * Get category ids for product + * + * @param int $productId + * @param int $storeId + * @return array + */ + public function getCategoryIdsByProduct(int $productId, int $storeId) + { + $connection = $this->resourceConnection->getConnection(); + $categoryProductTable = $this->getCatalogCategoryProductTableName($storeId); + $storeTable = $this->resourceConnection->getTableName(Store::ENTITY); + $storeGroupTable = $this->resourceConnection->getTableName(Group::ENTITY); + + $select = $connection->select() + ->from(['cat_index' => $categoryProductTable], ['category_id']) + ->joinInner(['store' => $storeTable], $connection->quoteInto('store.store_id = ?', $storeId), []) + ->joinInner( + ['store_group' => $storeGroupTable], + 'store.group_id = store_group.group_id AND cat_index.category_id != store_group.root_category_id', + [] + ) + ->where('product_id = ?', $productId); + + $categoryIds = $connection->fetchCol($select); + + return $categoryIds; + } + + /** + * Get catalog_product_category table name + * + * @param int $storeId + * @return string + */ + private function getCatalogCategoryProductTableName(int $storeId) + { + $dimension = $this->dimensionFactory->create(Store::ENTITY, (string)$storeId); + $tableName = $this->tableResolver->resolve( + AbstractAction::MAIN_INDEX_TABLE, + [$dimension] + ); + + return $tableName; + } +} From 0ea4bc109a168ce2c49ccb66bfa114eabd67398f Mon Sep 17 00:00:00 2001 From: Lena Orobei <oorobei@magento.com> Date: Fri, 19 Jul 2019 15:33:38 -0500 Subject: [PATCH 741/773] magento graphql-ce#493 GraphQl-299 Do not rely on global state in resolvers --- .../PaypalGraphQl/Model/Resolver/PayflowProResponse.php | 3 ++- .../Magento/PaypalGraphQl/Model/Resolver/PayflowProToken.php | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/PaypalGraphQl/Model/Resolver/PayflowProResponse.php b/app/code/Magento/PaypalGraphQl/Model/Resolver/PayflowProResponse.php index 42a5504de9a16..ce44511c60f3e 100644 --- a/app/code/Magento/PaypalGraphQl/Model/Resolver/PayflowProResponse.php +++ b/app/code/Magento/PaypalGraphQl/Model/Resolver/PayflowProResponse.php @@ -117,7 +117,8 @@ public function resolve( } $maskedCartId = $args['input']['cart_id']; - $cart = $this->getCartForUser->execute($maskedCartId, $context->getUserId()); + $storeId = (int)$context->getExtensionAttributes()->getStore()->getId(); + $cart = $this->getCartForUser->execute($maskedCartId, $context->getUserId(), $storeId); $paypalPayload = $args['input']['paypal_payload'] ?? ''; diff --git a/app/code/Magento/PaypalGraphQl/Model/Resolver/PayflowProToken.php b/app/code/Magento/PaypalGraphQl/Model/Resolver/PayflowProToken.php index 64aec1b035c0d..409145ca9a963 100644 --- a/app/code/Magento/PaypalGraphQl/Model/Resolver/PayflowProToken.php +++ b/app/code/Magento/PaypalGraphQl/Model/Resolver/PayflowProToken.php @@ -65,7 +65,8 @@ public function resolve( $urls = $args['input']['urls'] ?? null ; $customerId = $context->getUserId(); - $cart = $this->getCartForUser->execute($cartId, $customerId); + $storeId = (int)$context->getExtensionAttributes()->getStore()->getId(); + $cart = $this->getCartForUser->execute($cartId, $customerId, $storeId); if (!empty($args['input']['urls'])) { $this->validateUrls($args['input']['urls']); From 5edb053e1b8a68866102d856336f823e475b57d1 Mon Sep 17 00:00:00 2001 From: Roman Lytvynenko <lytvynen@adobe.com> Date: Fri, 19 Jul 2019 17:03:52 -0500 Subject: [PATCH 742/773] MC-18094: Full page cache issue with non-default store view --- .../Store/App/Action/Plugin/Context.php | 2 +- .../ContextNonDefaultStoreDirectLinkTest.php | 155 ++++++++++++++++++ 2 files changed, 156 insertions(+), 1 deletion(-) create mode 100644 app/code/Magento/Store/Test/Unit/App/Action/Plugin/ContextNonDefaultStoreDirectLinkTest.php diff --git a/app/code/Magento/Store/App/Action/Plugin/Context.php b/app/code/Magento/Store/App/Action/Plugin/Context.php index 5d324c4b468f4..44f6f681fbf01 100644 --- a/app/code/Magento/Store/App/Action/Plugin/Context.php +++ b/app/code/Magento/Store/App/Action/Plugin/Context.php @@ -133,7 +133,7 @@ private function processInvalidStoreRequested( private function updateContext(StoreInterface $store) { if (!$store->getConfig(Store::XML_PATH_STORE_IN_URL) || - $store->getId() == $this->storeManager->getDefaultStoreView()->getId() + $store->getCode() == $this->storeManager->getDefaultStoreView()->getCode() ) { $this->httpContext->setValue( StoreManagerInterface::CONTEXT_STORE, diff --git a/app/code/Magento/Store/Test/Unit/App/Action/Plugin/ContextNonDefaultStoreDirectLinkTest.php b/app/code/Magento/Store/Test/Unit/App/Action/Plugin/ContextNonDefaultStoreDirectLinkTest.php new file mode 100644 index 0000000000000..422aa7d2de67c --- /dev/null +++ b/app/code/Magento/Store/Test/Unit/App/Action/Plugin/ContextNonDefaultStoreDirectLinkTest.php @@ -0,0 +1,155 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Store\Test\Unit\App\Action\Plugin; + +use Magento\Framework\App\Action\AbstractAction; +use Magento\Framework\App\Http\Context; +use Magento\Framework\App\Http\Context as HttpContext; +use Magento\Framework\App\RequestInterface; +use Magento\Framework\Session\Generic; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Store\Api\StoreCookieManagerInterface; +use Magento\Store\Model\Store; +use Magento\Store\Model\StoreManagerInterface; +use Magento\Store\Model\Website; +use PHPUnit\Framework\TestCase; + +/** + * Class ContextNonDefaultStoreDirectLinkTest + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class ContextNonDefaultStoreDirectLinkTest extends TestCase +{ + const CURRENCY_SESSION = 'CNY'; + const CURRENCY_DEFAULT = 'USD'; + const CURRENCY_CURRENT_STORE = 'UAH'; + + /** + * @dataProvider cacheHitOnDirectLinkToNonDefaultStoreView + * @param $customStore + * @param $defaultStore + * @param $setValueNumberOfTimes + * @param $xmlPathStoreInUrl + * @return void + */ + public function testCacheHitOnDirectLinkToNonDefaultStoreView( + $customStore, + $defaultStore, + $setValueNumberOfTimes, + $xmlPathStoreInUrl + ) { + $sessionMock = $this->createPartialMock(Generic::class, ['getCurrencyCode']); + $httpContextMock = $this->createMock(HttpContext::class); + $storeManager = $this->createMock(StoreManagerInterface::class); + $storeCookieManager = $this->createMock(StoreCookieManagerInterface::class); + $storeMock = $this->createMock(Store::class); + $currentStoreMock = $this->createMock(Store::class); + $requestMock = $this->getMockBuilder(RequestInterface::class)->getMockForAbstractClass(); + $subjectMock = $this->getMockBuilder(AbstractAction::class) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + + $httpContextMock->expects($this->once()) + ->method('getValue') + ->with(StoreManagerInterface::CONTEXT_STORE) + ->willReturn(null); + $websiteMock = $this->createPartialMock( + Website::class, + ['getDefaultStore', '__wakeup'] + ); + + $plugin = (new ObjectManager($this))->getObject( + \Magento\Store\App\Action\Plugin\Context::class, + [ + 'session' => $sessionMock, + 'httpContext' => $httpContextMock, + 'storeManager' => $storeManager, + 'storeCookieManager' => $storeCookieManager, + ] + ); + + $storeManager->method('getDefaultStoreView') + ->willReturn($storeMock); + + $storeCookieManager->expects($this->once()) + ->method('getStoreCodeFromCookie') + ->willReturn('storeCookie'); + + $currentStoreMock->expects($this->any()) + ->method('getDefaultCurrencyCode') + ->willReturn(self::CURRENCY_CURRENT_STORE); + + $currentStoreMock->expects($this->any()) + ->method('getConfig') + ->willReturn($xmlPathStoreInUrl); + + $currentStoreMock->expects($this->any()) + ->method('getCode') + ->willReturn($customStore); + + $storeManager->expects($this->any()) + ->method('getWebsite') + ->willReturn($websiteMock); + + $websiteMock->expects($this->any()) + ->method('getDefaultStore') + ->willReturn($storeMock); + + $storeMock->expects($this->any()) + ->method('getDefaultCurrencyCode') + ->willReturn(self::CURRENCY_DEFAULT); + + $storeMock->expects($this->any()) + ->method('getCode') + ->willReturn($defaultStore); + + $requestMock->expects($this->any()) + ->method('getParam') + ->with($this->equalTo('___store')) + ->willReturn($defaultStore); + + $storeManager->method('getStore') + ->with($defaultStore) + ->willReturn($currentStoreMock); + + $sessionMock->expects($this->any()) + ->method('getCurrencyCode') + ->willReturn(self::CURRENCY_SESSION); + + $httpContextMock->expects($this->exactly($setValueNumberOfTimes)) + ->method('setValue'); + + $plugin->beforeDispatch( + $subjectMock, + $requestMock + ); + } + + public function cacheHitOnDirectLinkToNonDefaultStoreView() + { + return [ + [ + 'custom_store', + 'default', + 1, + 1 + ], + [ + 'default', + 'default', + 2, + 0 + ], + [ + 'default', + 'default', + 2, + 1 + ], + ]; + } +} From 4954bd1f9f80fe0d725569602a40ba5f250a4dae Mon Sep 17 00:00:00 2001 From: Eden <quocviet312@gmail.com> Date: Sat, 20 Jul 2019 07:59:59 +0700 Subject: [PATCH 743/773] Resolve "Discount Amount" field is validated after the page load without any action from user in Create New Catalog Rule form issue23777 --- .../view/adminhtml/ui_component/catalog_rule_form.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/CatalogRule/view/adminhtml/ui_component/catalog_rule_form.xml b/app/code/Magento/CatalogRule/view/adminhtml/ui_component/catalog_rule_form.xml index 8174434a06c49..c114f6b1d77cd 100644 --- a/app/code/Magento/CatalogRule/view/adminhtml/ui_component/catalog_rule_form.xml +++ b/app/code/Magento/CatalogRule/view/adminhtml/ui_component/catalog_rule_form.xml @@ -307,6 +307,7 @@ <settings> <validation> <rule name="required-entry" xsi:type="boolean">true</rule> + <rule name="validate-number-range" xsi:type="string">0.00-100.00</rule> </validation> <dataType>text</dataType> <label translate="true">Discount Amount</label> From d56257230757b56120ea07bfce51d0a4a94b3afb Mon Sep 17 00:00:00 2001 From: Eden <quocviet312@gmail.com> Date: Sat, 20 Jul 2019 22:23:06 +0700 Subject: [PATCH 744/773] Resolve Toggle icon not working in create configuration Product creation Page issue 22702 --- .../web/css/source/module/main/_collapsible-blocks.less | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/main/_collapsible-blocks.less b/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/main/_collapsible-blocks.less index bdc986e918c2c..51a939cae1a5f 100644 --- a/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/main/_collapsible-blocks.less +++ b/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/main/_collapsible-blocks.less @@ -122,6 +122,11 @@ &:before { content: @icon-expand-close__content; } + &.active { + &:before { + content: @icon-expand-open__content; + } + } } } From 055dcf68d6d75361dc2aba2fdc59c5f0d06b8be2 Mon Sep 17 00:00:00 2001 From: DmytroPaidych <dimonovp@gmail.com> Date: Mon, 22 Jul 2019 11:26:01 +0300 Subject: [PATCH 745/773] MC-3085: Customer can change product options using swatches --- .../StorefrontProductInfoMainSection.xml | 1 + ...ithSwatchAttributeToTheCartActionGroup.xml | 35 ++++++++++++ .../StorefrontProductInfoMainSection.xml | 1 + ...nChangeProductOptionsUsingSwatchesTest.xml | 53 +++++++++++++++++++ 4 files changed, 90 insertions(+) create mode 100644 app/code/Magento/Swatches/Test/Mftf/ActionGroup/StorefrontAddProductWithSwatchAttributeToTheCartActionGroup.xml create mode 100644 app/code/Magento/Swatches/Test/Mftf/Test/StorefrontCustomerCanChangeProductOptionsUsingSwatchesTest.xml diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/StorefrontProductInfoMainSection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/StorefrontProductInfoMainSection.xml index 95929401620b8..29a1b72947c06 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Section/StorefrontProductInfoMainSection.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Section/StorefrontProductInfoMainSection.xml @@ -10,5 +10,6 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="StorefrontProductInfoMainSection"> <element name="AddToCart" type="button" selector="#product-addtocart-button"/> + <element name="updateCart" type="button" selector="#product-updatecart-button" timeout="30"/> </section> </sections> diff --git a/app/code/Magento/Swatches/Test/Mftf/ActionGroup/StorefrontAddProductWithSwatchAttributeToTheCartActionGroup.xml b/app/code/Magento/Swatches/Test/Mftf/ActionGroup/StorefrontAddProductWithSwatchAttributeToTheCartActionGroup.xml new file mode 100644 index 0000000000000..9bd58bff69e5a --- /dev/null +++ b/app/code/Magento/Swatches/Test/Mftf/ActionGroup/StorefrontAddProductWithSwatchAttributeToTheCartActionGroup.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <!-- Add Configurable Product with Swatch attribute to the cart --> + <actionGroup name="StorefrontAddProductWithSwatchesToTheCartActionGroup" extends="StorefrontAddProductToCartWithQtyActionGroup"> + <arguments> + <argument name="product"/> + <argument name="productOption" type="string"/> + </arguments> + <remove keyForRemoval="seeSuccessSaveMessage"/> + <click selector="{{StorefrontProductInfoMainSection.visualSwatchOption(productOption)}}" after="waitForStorefrontProductPageLoad" stepKey="clickSelectOption"/> + <see selector="{{StorefrontMessagesSection.success}}" userInput="You added {{product.name}} to your shopping cart." after="waitForSuccessMessage" stepKey="seeAddToCartSuccessMessage"/> + </actionGroup> + + <!-- Update Configurable Product with Swatch attribute in the cart --> + <actionGroup name="StorefrontUpdateCartConfigurableProductWithSwatches"> + <arguments> + <argument name="product"/> + <argument name="productOption" type="string"/> + </arguments> + <click selector="{{CheckoutCartProductSection.nthEditButton('1')}}" stepKey="clickEditConfigurableProductButton"/> + <waitForPageLoad stepKey="waitForStorefrontProductPageLoad"/> + <click selector="{{StorefrontProductInfoMainSection.visualSwatchOption(productOption)}}" stepKey="changeSwatchAttributeOption"/> + <click selector="{{StorefrontProductInfoMainSection.updateCart}}" stepKey="clickUpdateCartButton"/> + <waitForElementVisible selector="{{StorefrontMessagesSection.success}}" stepKey="waitForSuccessMessage"/> + <see selector="{{StorefrontMessagesSection.success}}" userInput="{{product.name}} was updated in your shopping cart." stepKey="assertSuccessMessage"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/Swatches/Test/Mftf/Section/StorefrontProductInfoMainSection.xml b/app/code/Magento/Swatches/Test/Mftf/Section/StorefrontProductInfoMainSection.xml index 4290ddbbd8dd4..6fdf2276f39d9 100644 --- a/app/code/Magento/Swatches/Test/Mftf/Section/StorefrontProductInfoMainSection.xml +++ b/app/code/Magento/Swatches/Test/Mftf/Section/StorefrontProductInfoMainSection.xml @@ -15,5 +15,6 @@ <element name="swatchAttributeOptions" type="text" selector="div.swatch-attribute-options"/> <element name="nthSwatchOptionText" type="button" selector="div.swatch-option.text:nth-of-type({{n}})" parameterized="true"/> <element name="productSwatch" type="button" selector="//div[@class='swatch-option'][@aria-label='{{var1}}']" parameterized="true"/> + <element name="visualSwatchOption" type="button" selector=".swatch-option[option-tooltip-value='#{{visualSwatchOption}}']" parameterized="true"/> </section> </sections> diff --git a/app/code/Magento/Swatches/Test/Mftf/Test/StorefrontCustomerCanChangeProductOptionsUsingSwatchesTest.xml b/app/code/Magento/Swatches/Test/Mftf/Test/StorefrontCustomerCanChangeProductOptionsUsingSwatchesTest.xml new file mode 100644 index 0000000000000..f5bcccd4aa9b2 --- /dev/null +++ b/app/code/Magento/Swatches/Test/Mftf/Test/StorefrontCustomerCanChangeProductOptionsUsingSwatchesTest.xml @@ -0,0 +1,53 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="StorefrontCustomerCanChangeProductOptionsUsingSwatchesTest" extends="AdminCreateVisualSwatchTest"> + <annotations> + <features value="Swatches"/> + <stories value="Swatches"/> + <title value="Customer can change product options using swatches"/> + <description value="Customer can change product options using swatches"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-3085"/> + <group value="swatches"/> + </annotations> + <before> + <createData entity="Simple_US_Customer" after="createCategory" stepKey="createCustomer"/> + </before> + <after> + <deleteData createDataKey="createCustomer" before="goToProductAttributes" stepKey="deleteCustomer"/> + <actionGroup ref="StorefrontCustomerLogoutActionGroup" after="deleteCustomer" stepKey="logoutFromCustomer"/> + </after> + + <!-- Remove steps that are not used for this test --> + <remove keyForRemoval="assertSwatch4"/> + <remove keyForRemoval="assertSwatch5"/> + <remove keyForRemoval="assertSwatch6"/> + + <!-- Login to storefront from customer --> + <actionGroup ref="LoginToStorefrontActionGroup" before="amOnProductPage" stepKey="loginCustomer"> + <argument name="Customer" value="$$createCustomer$$"/> + </actionGroup> + + <!-- Add configurable product with swatch attribute to the cart --> + <actionGroup ref="StorefrontAddProductWithSwatchesToTheCartActionGroup" stepKey="addConfigurableProductToTheCart"> + <argument name="productQty" value="1"/> + <argument name="product" value="_defaultProduct"/> + <argument name="productOption" value="3498db"/> + </actionGroup> + + <!-- Go to shopping cart and update option of configurable product --> + <amOnPage url="{{CheckoutCartPage.url}}" stepKey="openShoppingCartPage"/> + <actionGroup ref="StorefrontUpdateCartConfigurableProductWithSwatches" stepKey="updateConfigurableProductInTheCart"> + <argument name="product" value="_defaultProduct"/> + <argument name="productOption" value="e74d3c"/> + </actionGroup> + </test> +</tests> From b2836aacf67d704a0eea8368cedc09aad37f353d Mon Sep 17 00:00:00 2001 From: Serhii Balko <serhii.balko@transoftgroup.com> Date: Mon, 22 Jul 2019 15:24:58 +0300 Subject: [PATCH 746/773] MC-18250: "Phone Number" field is not marked as required --- app/code/Magento/Customer/Block/Address/Edit.php | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/Customer/Block/Address/Edit.php b/app/code/Magento/Customer/Block/Address/Edit.php index afefb1138deac..ef9937a0cde8b 100644 --- a/app/code/Magento/Customer/Block/Address/Edit.php +++ b/app/code/Magento/Customer/Block/Address/Edit.php @@ -5,7 +5,8 @@ */ namespace Magento\Customer\Block\Address; -use Magento\Framework\Exception\LocalizedException; +use Magento\Customer\Api\AddressMetadataInterface; +use Magento\Framework\App\ObjectManager; use Magento\Framework\Exception\NoSuchEntityException; /** @@ -48,7 +49,7 @@ class Edit extends \Magento\Directory\Block\Data protected $dataObjectHelper; /** - * @var \Magento\Customer\Api\AddressMetadataInterface + * @var AddressMetadataInterface */ private $addressMetadata; @@ -67,7 +68,7 @@ class Edit extends \Magento\Directory\Block\Data * @param \Magento\Customer\Helper\Session\CurrentCustomer $currentCustomer * @param \Magento\Framework\Api\DataObjectHelper $dataObjectHelper * @param array $data - * @param \Magento\Customer\Api\AddressMetadataInterface|null $addressMetadata + * @param AddressMetadataInterface|null $addressMetadata * * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -84,14 +85,14 @@ public function __construct( \Magento\Customer\Helper\Session\CurrentCustomer $currentCustomer, \Magento\Framework\Api\DataObjectHelper $dataObjectHelper, array $data = [], - \Magento\Customer\Api\AddressMetadataInterface $addressMetadata = null + AddressMetadataInterface $addressMetadata = null ) { $this->_customerSession = $customerSession; $this->_addressRepository = $addressRepository; $this->addressDataFactory = $addressDataFactory; $this->currentCustomer = $currentCustomer; $this->dataObjectHelper = $dataObjectHelper; - $this->addressMetadata = $addressMetadata; + $this->addressMetadata = $addressMetadata ?: ObjectManager::getInstance()->get(AddressMetadataInterface::class); parent::__construct( $context, $directoryHelper, From d60a29b85b890fadcfd10ceed05537d66b7dcd70 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <engcom-vendorworker-foxtrot@adobe.com> Date: Mon, 22 Jul 2019 15:48:02 +0300 Subject: [PATCH 747/773] magento/magento2#23787: Static tests fix. --- .../Framework/App/DeploymentConfig/Writer/PhpFormatter.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/App/DeploymentConfig/Writer/PhpFormatter.php b/lib/internal/Magento/Framework/App/DeploymentConfig/Writer/PhpFormatter.php index f9a4067e8b756..4ae1bca2fefba 100644 --- a/lib/internal/Magento/Framework/App/DeploymentConfig/Writer/PhpFormatter.php +++ b/lib/internal/Magento/Framework/App/DeploymentConfig/Writer/PhpFormatter.php @@ -18,10 +18,11 @@ class PhpFormatter implements FormatterInterface /** * Format deployment configuration. + * * If $comments is present, each item will be added * as comment to the corresponding section * - * {@inheritdoc} + * @inheritdoc */ public function format($data, array $comments = []) { @@ -71,6 +72,8 @@ private function formatData($data, $comments = [], $prefix = ' ') } /** + * Format generated config files using the short array syntax. + * * If variable to export is an array, format with the php >= 5.4 short array syntax. Otherwise use * default var_export functionality. * From ef1690b7fa0fbda12d1d0576b94889750bb9a0ae Mon Sep 17 00:00:00 2001 From: Roman Lytvynenko <lytvynen@adobe.com> Date: Mon, 22 Jul 2019 08:17:50 -0500 Subject: [PATCH 748/773] MC-18094: Full page cache issue with non-default store view --- .../Plugin/ContextNonDefaultStoreDirectLinkTest.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Store/Test/Unit/App/Action/Plugin/ContextNonDefaultStoreDirectLinkTest.php b/app/code/Magento/Store/Test/Unit/App/Action/Plugin/ContextNonDefaultStoreDirectLinkTest.php index 422aa7d2de67c..13f5adf1687fc 100644 --- a/app/code/Magento/Store/Test/Unit/App/Action/Plugin/ContextNonDefaultStoreDirectLinkTest.php +++ b/app/code/Magento/Store/Test/Unit/App/Action/Plugin/ContextNonDefaultStoreDirectLinkTest.php @@ -3,15 +3,18 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + +declare(strict_types=1); + namespace Magento\Store\Test\Unit\App\Action\Plugin; use Magento\Framework\App\Action\AbstractAction; -use Magento\Framework\App\Http\Context; use Magento\Framework\App\Http\Context as HttpContext; use Magento\Framework\App\RequestInterface; use Magento\Framework\Session\Generic; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; use Magento\Store\Api\StoreCookieManagerInterface; +use Magento\Store\App\Action\Plugin\Context; use Magento\Store\Model\Store; use Magento\Store\Model\StoreManagerInterface; use Magento\Store\Model\Website; @@ -29,6 +32,8 @@ class ContextNonDefaultStoreDirectLinkTest extends TestCase const CURRENCY_CURRENT_STORE = 'UAH'; /** + * Test for full page cache hits from new http clients if store context was specified in the URL + * * @dataProvider cacheHitOnDirectLinkToNonDefaultStoreView * @param $customStore * @param $defaultStore @@ -57,13 +62,14 @@ public function testCacheHitOnDirectLinkToNonDefaultStoreView( ->method('getValue') ->with(StoreManagerInterface::CONTEXT_STORE) ->willReturn(null); + $websiteMock = $this->createPartialMock( Website::class, ['getDefaultStore', '__wakeup'] ); $plugin = (new ObjectManager($this))->getObject( - \Magento\Store\App\Action\Plugin\Context::class, + Context::class, [ 'session' => $sessionMock, 'httpContext' => $httpContextMock, From e6ff25a8f18e3d1b80f3fa661f27b7a70946597f Mon Sep 17 00:00:00 2001 From: Krissy Hiserote <khiserote@magento.com> Date: Mon, 22 Jul 2019 11:36:35 -0500 Subject: [PATCH 749/773] MC-15776: Merge release branch into 2.3-develop - fix merge conflict --- .../view/adminhtml/templates/payment/script.phtml | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/AuthorizenetAcceptjs/view/adminhtml/templates/payment/script.phtml b/app/code/Magento/AuthorizenetAcceptjs/view/adminhtml/templates/payment/script.phtml index 2989f99c0462d..6be6008dba507 100644 --- a/app/code/Magento/AuthorizenetAcceptjs/view/adminhtml/templates/payment/script.phtml +++ b/app/code/Magento/AuthorizenetAcceptjs/view/adminhtml/templates/payment/script.phtml @@ -9,12 +9,16 @@ <script> //<![CDATA[ require( - ['Magento_AuthorizenetAcceptjs/js/payment-form'], - function(Authorizenet) { + [ + 'Magento_AuthorizenetAcceptjs/js/authorizenet', + 'jquery', + 'domReady!' + ], function(AuthorizenetAcceptjs, $) { var config = <?= /* @noEscape */ $block->getPaymentConfig() ?>, - form = "#payment_form_<?= $block->escapeJs($block->escapeHtml($block->getMethodCode())) ?>"; + form = $('#payment_form_<?= /* @noEscape */ $block->escapeJs($block->escapeHtml($block->getMethodCode())) ?>'); - new Authorizenet(config, form); + config.active = form.length > 0 && !form.is(':hidden'); + new AuthorizenetAcceptjs(config); }); //]]> </script> From c3f2a34c20cf25abdc527895941f2688d1ce9bd3 Mon Sep 17 00:00:00 2001 From: Daniel Renaud <drenaud@magento.com> Date: Mon, 22 Jul 2019 11:59:07 -0500 Subject: [PATCH 750/773] MC-17015: [GraphQL] Product Categories query doesn't return all categories where product is visible - fix functional tests --- .../GraphQl/Catalog/ProductViewTest.php | 4 ++-- .../ConfigurableProductViewTest.php | 22 ++++++++++++------- ..._configurable_with_category_and_weight.php | 11 +++++++--- 3 files changed, 24 insertions(+), 13 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductViewTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductViewTest.php index e517b22ad09de..aad7319a37545 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductViewTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductViewTest.php @@ -282,11 +282,11 @@ public function testQueryAllFieldsSimpleProduct() $this->assertWebsites($product, $response['products']['items'][0]['websites']); self::assertEquals( 'Movable Position 2', - $responseObject->getData('products/items/0/categories/1/name') + $responseObject->getData('products/items/0/categories/0/name') ); self::assertEquals( 'Filter category', - $responseObject->getData('products/items/0/categories/2/name') + $responseObject->getData('products/items/0/categories/1/name') ); $storeManager = ObjectManager::getInstance()->get(\Magento\Store\Model\StoreManagerInterface::class); self::assertEquals( diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/ConfigurableProductViewTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/ConfigurableProductViewTest.php index da5410384627c..763a6d189b48d 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/ConfigurableProductViewTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/ConfigurableProductViewTest.php @@ -300,6 +300,7 @@ private function assertConfigurableVariants($actualResponse) isset($variantArray['product']['id']), 'variant product elements don\'t contain id key' ); + $variantProductId = $variantArray['product']['id']; $indexValue = $variantArray['product']['sku']; unset($variantArray['product']['id']); $this->assertTrue( @@ -310,14 +311,19 @@ private function assertConfigurableVariants($actualResponse) /** @var \Magento\Catalog\Model\Product $childProduct */ $childProduct = $productRepository->get($indexValue); - /** @var \Magento\Catalog\Api\Data\ProductLinkInterface[] */ - $links = $childProduct->getExtensionAttributes()->getCategoryLinks(); - $this->assertCount(1, $links, "Precondition failed, incorrect number of categories."); - $id =$links[0]->getCategoryId(); - - $actualValue - = $actualResponse['variants'][$variantKey]['product']['categories'][0]; - $this->assertEquals($actualValue, ['id' => $id]); + switch( $variantProductId ){ + case 10: + $this->assertEmpty( + $actualResponse['variants'][$variantKey]['product']['categories'], + 'No category is expected for product, that not visible individually' + ); + break; + case 20: + $this->assertEquals( + $actualResponse['variants'][$variantKey]['product']['categories'][0], + ['id' => 333] + ); + } unset($variantArray['product']['categories']); $mediaGalleryEntries = $childProduct->getMediaGalleryEntries(); diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/product_configurable_with_category_and_weight.php b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/product_configurable_with_category_and_weight.php index b8449a829a227..413fa8be5dbad 100644 --- a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/product_configurable_with_category_and_weight.php +++ b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/product_configurable_with_category_and_weight.php @@ -19,6 +19,7 @@ \Magento\TestFramework\Helper\Bootstrap::getInstance()->reinitialize(); require __DIR__ . '/configurable_attribute.php'; +require __DIR__ . '/../../Catalog/_files/category.php'; /** @var ProductRepositoryInterface $productRepository */ $productRepository = Bootstrap::getObjectManager() @@ -36,6 +37,10 @@ $associatedProductIds = []; $productIds = [10, 20]; array_shift($options); //remove the first option which is empty +$visibility = [ + 10 => Visibility::VISIBILITY_IN_CATALOG, + 20 => Visibility::VISIBILITY_NOT_VISIBLE, +]; foreach ($options as $option) { /** @var $product Product */ @@ -49,11 +54,11 @@ ->setSku('simple_' . $productId) ->setPrice($productId) ->setTestConfigurable($option->getValue()) - ->setVisibility(Visibility::VISIBILITY_NOT_VISIBLE) + ->setVisibility($visibility[$productId]) ->setStatus(Status::STATUS_ENABLED) ->setStockData(['use_config_manage_stock' => 1, 'qty' => 100, 'is_qty_decimal' => 0, 'is_in_stock' => 1]); $eavAttributeValues = [ - 'category_ids' => [2] + 'category_ids' => [333] ]; foreach ($eavAttributeValues as $eavCategoryAttributeCode => $eavCategoryAttributeValues) { $product->setCustomAttribute($eavCategoryAttributeCode, $eavCategoryAttributeValues); @@ -210,5 +215,5 @@ $categoryLinkManagement->assignProductToCategories( $product->getSku(), - [2] + [333] ); From 2a546dd09a8f89c1e857c705682f857ae155db1d Mon Sep 17 00:00:00 2001 From: Daniel Renaud <drenaud@magento.com> Date: Mon, 22 Jul 2019 13:23:08 -0500 Subject: [PATCH 751/773] MC-17015: [GraphQL] Product Categories query doesn't return all categories where product is visible - stabilize tests --- .../testsuite/Magento/GraphQl/Catalog/ProductViewTest.php | 3 +++ .../ConfigurableProduct/ConfigurableProductViewTest.php | 7 +++++-- .../product_configurable_with_category_and_weight.php | 4 ++-- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductViewTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductViewTest.php index aad7319a37545..1adca29ffb054 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductViewTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductViewTest.php @@ -15,6 +15,9 @@ use Magento\TestFramework\ObjectManager; use Magento\TestFramework\TestCase\GraphQlAbstract; +/** + * Test products query output + */ class ProductViewTest extends GraphQlAbstract { /** diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/ConfigurableProductViewTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/ConfigurableProductViewTest.php index 763a6d189b48d..4729cae92717d 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/ConfigurableProductViewTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/ConfigurableProductViewTest.php @@ -15,6 +15,9 @@ use Magento\TestFramework\ObjectManager; use Magento\TestFramework\TestCase\GraphQlAbstract; +/** + * Test products query for configurable products + */ class ConfigurableProductViewTest extends GraphQlAbstract { /** @@ -232,7 +235,6 @@ private function assertBaseFields($product, $actualResponse) $regularPriceAmount = $priceInfo->getPrice(RegularPrice::PRICE_CODE)->getAmount(); /** @var MetadataPool $metadataPool */ $metadataPool = ObjectManager::getInstance()->get(MetadataPool::class); - // ['product_object_field_name', 'expected_value'] $assertionMap = [ ['response_field' => 'attribute_set_id', 'expected_value' => $product->getAttributeSetId()], ['response_field' => 'created_at', 'expected_value' => $product->getCreatedAt()], @@ -311,7 +313,7 @@ private function assertConfigurableVariants($actualResponse) /** @var \Magento\Catalog\Model\Product $childProduct */ $childProduct = $productRepository->get($indexValue); - switch( $variantProductId ){ + switch ($variantProductId) { case 10: $this->assertEmpty( $actualResponse['variants'][$variantKey]['product']['categories'], @@ -323,6 +325,7 @@ private function assertConfigurableVariants($actualResponse) $actualResponse['variants'][$variantKey]['product']['categories'][0], ['id' => 333] ); + break; } unset($variantArray['product']['categories']); diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/product_configurable_with_category_and_weight.php b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/product_configurable_with_category_and_weight.php index 413fa8be5dbad..39d43ff925a0e 100644 --- a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/product_configurable_with_category_and_weight.php +++ b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/product_configurable_with_category_and_weight.php @@ -38,8 +38,8 @@ $productIds = [10, 20]; array_shift($options); //remove the first option which is empty $visibility = [ - 10 => Visibility::VISIBILITY_IN_CATALOG, - 20 => Visibility::VISIBILITY_NOT_VISIBLE, + 10 => Visibility::VISIBILITY_NOT_VISIBLE, + 20 => Visibility::VISIBILITY_IN_CATALOG ]; foreach ($options as $option) { From 586cea2dac456a7843b8ed46d646688c8116edc4 Mon Sep 17 00:00:00 2001 From: Buba Suma <soumah@adobe.com> Date: Fri, 19 Jul 2019 16:57:49 -0500 Subject: [PATCH 752/773] MC-18281: Checkout order summary has wrong item count - Fix summary items count on checkout page is not consistent with settings "checkout/cart_link/use_qty" --- .../Checkout/Model/DefaultConfigProvider.php | 4 + .../Checkout/Test/Mftf/Data/ConfigData.xml | 12 +++ ...pesOfCustomOptionToTheShoppingCartTest.xml | 2 +- ...rontCheckCartAndCheckoutItemsCountTest.xml | 85 +++++++++++++++++++ .../web/js/view/summary/cart-items.js | 11 +++ .../web/template/minicart/content.html | 2 +- .../web/template/summary/cart-items.html | 2 +- 7 files changed, 115 insertions(+), 3 deletions(-) create mode 100644 app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckCartAndCheckoutItemsCountTest.xml diff --git a/app/code/Magento/Checkout/Model/DefaultConfigProvider.php b/app/code/Magento/Checkout/Model/DefaultConfigProvider.php index 470d4a3aca561..70352b50d8de4 100644 --- a/app/code/Magento/Checkout/Model/DefaultConfigProvider.php +++ b/app/code/Magento/Checkout/Model/DefaultConfigProvider.php @@ -343,6 +343,10 @@ public function getConfig() ) ) ]; + $output['useQty'] = $this->scopeConfig->isSetFlag( + 'checkout/cart_link/use_qty', + \Magento\Store\Model\ScopeInterface::SCOPE_STORE + ); $output['activeCarriers'] = $this->getActiveCarriers(); $output['originCountryCode'] = $this->getOriginCountryCode(); $output['paymentMethods'] = $this->getPaymentMethods(); diff --git a/app/code/Magento/Checkout/Test/Mftf/Data/ConfigData.xml b/app/code/Magento/Checkout/Test/Mftf/Data/ConfigData.xml index cd9cd59d20b64..bb47a2fcc3070 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Data/ConfigData.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Data/ConfigData.xml @@ -88,4 +88,16 @@ <data key="label">No</data> <data key="value">0</data> </entity> + + <!-- Checkout Config: Display Cart Summary --> + <entity name="DisplayItemsQuantities"> + <data key="path">checkout/cart_link/use_qty</data> + <data key="label">Display items quantities</data> + <data key="value">1</data> + </entity> + <entity name="DisplayUniqueItems"> + <data key="path">checkout/cart_link/use_qty</data> + <data key="label">Display number of items in cart</data> + <data key="value">0</data> + </entity> </entities> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddProductWithAllTypesOfCustomOptionToTheShoppingCartTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddProductWithAllTypesOfCustomOptionToTheShoppingCartTest.xml index 611c53dba0dec..e90f69e88cec7 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddProductWithAllTypesOfCustomOptionToTheShoppingCartTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddProductWithAllTypesOfCustomOptionToTheShoppingCartTest.xml @@ -100,7 +100,7 @@ <!-- Assert Product Count in Mini Cart --> <actionGroup ref="StorefrontAssertMiniCartItemCountActionGroup" stepKey="assertProductCountAndTextInMiniCart"> <argument name="productCount" value="2"/> - <argument name="productCountText" value="1 Item in Cart"/> + <argument name="productCountText" value="2 Item in Cart"/> </actionGroup> <!--Assert Product Items in Mini cart--> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckCartAndCheckoutItemsCountTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckCartAndCheckoutItemsCountTest.xml new file mode 100644 index 0000000000000..0327deaf18968 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckCartAndCheckoutItemsCountTest.xml @@ -0,0 +1,85 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="StorefrontCartItemsCountDisplayItemsQuantities"> + <annotations> + <stories value="Checkout order summary has wrong item count"/> + <title value="Checkout order summary has wrong item count - display items quantities"/> + <description value="Items count in shopping cart and on checkout page should be consistent with settings 'checkout/cart_link/use_qty'"/> + <testCaseId value="MC-18281"/> + <severity value="CRITICAL"/> + <group value="checkout"/> + </annotations> + + <before> + <!--Set Display Cart Summary to display items quantities--> + <magentoCLI command="config:set {{DisplayItemsQuantities.path}} {{DisplayItemsQuantities.value}}" stepKey="setDisplayCartSummary"/> + <!--Create simple product--> + <createData entity="SimpleProduct2" stepKey="simpleProduct1"/> + <!--Create simple product--> + <createData entity="SimpleProduct2" stepKey="simpleProduct2"/> + </before> + <after> + <deleteData createDataKey="simpleProduct1" stepKey="deleteProduct1"/> + <deleteData createDataKey="simpleProduct2" stepKey="deleteProduct2"/> + <magentoCLI command="config:set {{DisplayItemsQuantities.path}} {{DisplayItemsQuantities.value}}" stepKey="resetDisplayCartSummary"/> + </after> + + <!-- Add simpleProduct1 to cart --> + <amOnPage url="{{StorefrontProductPage.url($$simpleProduct1.custom_attributes[url_key]$)}}" stepKey="amOnProduct1Page"/> + <actionGroup ref="AddProductWithQtyToCartFromStorefrontProductPage" stepKey="addProduct1ToCart"> + <argument name="productName" value="$$simpleProduct1.name$$"/> + <argument name="productQty" value="2"/> + </actionGroup> + <!-- Add simpleProduct2 to cart --> + <amOnPage url="{{StorefrontProductPage.url($$simpleProduct2.custom_attributes[url_key]$)}}" stepKey="amOnProduct2Page"/> + <actionGroup ref="AddProductWithQtyToCartFromStorefrontProductPage" stepKey="addProduct2ToCart"> + <argument name="productName" value="$$simpleProduct2.name$$"/> + <argument name="productQty" value="1"/> + </actionGroup> + + <!-- Open Mini Cart --> + <actionGroup ref="StorefrontOpenMiniCartActionGroup" stepKey="openMiniCart"/> + + <!-- Assert Products Count in Mini Cart --> + <actionGroup ref="StorefrontAssertMiniCartItemCountActionGroup" stepKey="assertProductCountAndTextInMiniCart"> + <argument name="productCount" value="3"/> + <argument name="productCountText" value="3 Items in Cart"/> + </actionGroup> + <!-- Assert Products Count on checkout page --> + <actionGroup ref="StorefrontCheckoutAndAssertOrderSummaryDisplayActionGroup" stepKey="assertProductCountOnCheckoutPage"> + <argument name="itemsText" value="3 Items in Cart"/> + </actionGroup> + </test> + <test name="StorefrontCartItemsCountDisplayUniqueItems" extends="StorefrontCartItemsCountDisplayItemsQuantities"> + <annotations> + <stories value="Checkout order summary has wrong item count"/> + <title value="Checkout order summary has wrong item count - display unique items"/> + <description value="Items count in shopping cart and on checkout page should be consistent with settings 'checkout/cart_link/use_qty'"/> + <testCaseId value="MC-18281"/> + <severity value="CRITICAL"/> + <group value="checkout"/> + </annotations> + + <!-- Assert Products Count in Mini Cart --> + <actionGroup ref="StorefrontAssertMiniCartItemCountActionGroup" stepKey="assertProductCountAndTextInMiniCart"> + <argument name="productCount" value="2"/> + <argument name="productCountText" value="2 Items in Cart"/> + </actionGroup> + <!-- Assert Products Count on checkout page --> + <actionGroup ref="StorefrontCheckoutAndAssertOrderSummaryDisplayActionGroup" stepKey="assertProductCountOnCheckoutPage"> + <argument name="itemsText" value="2 Items in Cart"/> + </actionGroup> + + <before> + <!--Set Display Cart Summary to display items quantities--> + <magentoCLI command="config:set {{DisplayUniqueItems.path}} {{DisplayUniqueItems.value}}" stepKey="setDisplayCartSummary"/> + </before> + </test> +</tests> diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/summary/cart-items.js b/app/code/Magento/Checkout/view/frontend/web/js/view/summary/cart-items.js index 488bcfd67594c..003fef9f15d3f 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/view/summary/cart-items.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/view/summary/cart-items.js @@ -12,6 +12,8 @@ define([ ], function (ko, totals, Component, stepNavigator, quote) { 'use strict'; + var useQty = window.checkoutConfig.useQty; + return Component.extend({ defaults: { template: 'Magento_Checkout/summary/cart-items' @@ -44,6 +46,15 @@ define([ return parseInt(totals.getItems()().length, 10); }, + /** + * Returns shopping cart items summary (includes config settings) + * + * @returns {Number} + */ + getCartSummaryItemsCount: function () { + return useQty ? this.getItemsQty() : this.getCartLineItemsCount(); + }, + /** * @inheritdoc */ diff --git a/app/code/Magento/Checkout/view/frontend/web/template/minicart/content.html b/app/code/Magento/Checkout/view/frontend/web/template/minicart/content.html index fb128a891aea2..0719a7d01ec70 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/minicart/content.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/minicart/content.html @@ -29,7 +29,7 @@ <div class="items-total"> <span class="count" if="maxItemsToDisplay < getCartLineItemsCount()" text="maxItemsToDisplay"/> <translate args="'of'" if="maxItemsToDisplay < getCartLineItemsCount()"/> - <span class="count" text="getCartLineItemsCount()"/> + <span class="count" text="getCartParam('summary_count')"/> <!-- ko if: (getCartLineItemsCount() === 1) --> <span translate="'Item in Cart'"/> <!--/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 fc74a4691a2e7..4e49d4502d8a8 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 @@ -9,7 +9,7 @@ <strong role="heading" aria-level="1"> <translate args="maxCartItemsToDisplay" if="maxCartItemsToDisplay < getCartLineItemsCount()"/> <translate args="'of'" if="maxCartItemsToDisplay < getCartLineItemsCount()"/> - <span data-bind="text: getCartLineItemsCount()"></span> + <span data-bind="text: getCartSummaryItemsCount()"></span> <translate args="'Item in Cart'" if="getCartLineItemsCount() === 1"/> <translate args="'Items in Cart'" if="getCartLineItemsCount() > 1"/> </strong> From 438b0f0a3ab24e7a563e6543070824545de8781e Mon Sep 17 00:00:00 2001 From: Roman Lytvynenko <lytvynen@adobe.com> Date: Mon, 22 Jul 2019 16:52:45 -0500 Subject: [PATCH 753/773] MC-18094: Full page cache issue with non-default store view --- .../Store/App/Action/Plugin/Context.php | 19 ++++----- .../ContextNonDefaultStoreDirectLinkTest.php | 41 ++++++++++--------- 2 files changed, 28 insertions(+), 32 deletions(-) diff --git a/app/code/Magento/Store/App/Action/Plugin/Context.php b/app/code/Magento/Store/App/Action/Plugin/Context.php index 44f6f681fbf01..b5d2e3d913f4c 100644 --- a/app/code/Magento/Store/App/Action/Plugin/Context.php +++ b/app/code/Magento/Store/App/Action/Plugin/Context.php @@ -6,15 +6,14 @@ namespace Magento\Store\App\Action\Plugin; +use Magento\Framework\App\Action\AbstractAction; use Magento\Framework\App\Http\Context as HttpContext; +use Magento\Framework\App\RequestInterface; use Magento\Framework\Exception\NoSuchEntityException; use Magento\Framework\Exception\NotFoundException; use Magento\Store\Api\Data\StoreInterface; use Magento\Store\Api\StoreCookieManagerInterface; -use Magento\Store\Model\Store; use Magento\Store\Model\StoreManagerInterface; -use Magento\Framework\App\Action\AbstractAction; -use Magento\Framework\App\RequestInterface; /** * Class ContextPlugin @@ -132,15 +131,11 @@ private function processInvalidStoreRequested( */ private function updateContext(StoreInterface $store) { - if (!$store->getConfig(Store::XML_PATH_STORE_IN_URL) || - $store->getCode() == $this->storeManager->getDefaultStoreView()->getCode() - ) { - $this->httpContext->setValue( - StoreManagerInterface::CONTEXT_STORE, - $store->getCode(), - $this->storeManager->getDefaultStoreView()->getCode() - ); - } + $this->httpContext->setValue( + StoreManagerInterface::CONTEXT_STORE, + $store->getCode(), + $store->isUseStoreInUrl() ? $store->getCode() : $this->storeManager->getDefaultStoreView()->getCode() + ); /** @var StoreInterface $defaultStore */ $defaultStore = $this->storeManager->getWebsite()->getDefaultStore(); diff --git a/app/code/Magento/Store/Test/Unit/App/Action/Plugin/ContextNonDefaultStoreDirectLinkTest.php b/app/code/Magento/Store/Test/Unit/App/Action/Plugin/ContextNonDefaultStoreDirectLinkTest.php index 13f5adf1687fc..bb2705bff9aab 100644 --- a/app/code/Magento/Store/Test/Unit/App/Action/Plugin/ContextNonDefaultStoreDirectLinkTest.php +++ b/app/code/Magento/Store/Test/Unit/App/Action/Plugin/ContextNonDefaultStoreDirectLinkTest.php @@ -35,17 +35,17 @@ class ContextNonDefaultStoreDirectLinkTest extends TestCase * Test for full page cache hits from new http clients if store context was specified in the URL * * @dataProvider cacheHitOnDirectLinkToNonDefaultStoreView - * @param $customStore - * @param $defaultStore - * @param $setValueNumberOfTimes - * @param $xmlPathStoreInUrl + * @param string $customStore + * @param string $defaultStore + * @param string $expectedDefaultStore + * @param bool $useStoreInUrl * @return void */ public function testCacheHitOnDirectLinkToNonDefaultStoreView( - $customStore, - $defaultStore, - $setValueNumberOfTimes, - $xmlPathStoreInUrl + string $customStore, + string $defaultStore, + string $expectedDefaultStore, + bool $useStoreInUrl ) { $sessionMock = $this->createPartialMock(Generic::class, ['getCurrencyCode']); $httpContextMock = $this->createMock(HttpContext::class); @@ -89,14 +89,12 @@ public function testCacheHitOnDirectLinkToNonDefaultStoreView( ->method('getDefaultCurrencyCode') ->willReturn(self::CURRENCY_CURRENT_STORE); - $currentStoreMock->expects($this->any()) - ->method('getConfig') - ->willReturn($xmlPathStoreInUrl); - $currentStoreMock->expects($this->any()) ->method('getCode') ->willReturn($customStore); + $currentStoreMock->method('isUseStoreInUrl')->willReturn($useStoreInUrl); + $storeManager->expects($this->any()) ->method('getWebsite') ->willReturn($websiteMock); @@ -126,8 +124,11 @@ public function testCacheHitOnDirectLinkToNonDefaultStoreView( ->method('getCurrencyCode') ->willReturn(self::CURRENCY_SESSION); - $httpContextMock->expects($this->exactly($setValueNumberOfTimes)) - ->method('setValue'); + $httpContextMock->expects($this->at(1))->method( + 'setValue' + )->with(StoreManagerInterface::CONTEXT_STORE, $customStore, $expectedDefaultStore); + + $httpContextMock->expects($this->at(2))->method('setValue'); $plugin->beforeDispatch( $subjectMock, @@ -141,20 +142,20 @@ public function cacheHitOnDirectLinkToNonDefaultStoreView() [ 'custom_store', 'default', - 1, - 1 + 'custom_store', + true, ], [ + 'custom_store', 'default', 'default', - 2, - 0 + false, ], [ 'default', 'default', - 2, - 1 + 'default', + true, ], ]; } From e69aba4b3d0c624cb90adedfc304a374b5b66cb6 Mon Sep 17 00:00:00 2001 From: Krissy Hiserote <khiserote@magento.com> Date: Mon, 22 Jul 2019 22:00:01 -0500 Subject: [PATCH 754/773] MC-15776: Merge release branch into 2.3-develop - fix MFTF test --- .../Email/Test/Mftf/Test/TransactionalEmailsLogoUploadTest.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/code/Magento/Email/Test/Mftf/Test/TransactionalEmailsLogoUploadTest.xml b/app/code/Magento/Email/Test/Mftf/Test/TransactionalEmailsLogoUploadTest.xml index c3870417fa5e0..4972a954c440c 100644 --- a/app/code/Magento/Email/Test/Mftf/Test/TransactionalEmailsLogoUploadTest.xml +++ b/app/code/Magento/Email/Test/Mftf/Test/TransactionalEmailsLogoUploadTest.xml @@ -21,6 +21,8 @@ <!--Login to Admin Area--> <before> <actionGroup ref="LoginAsAdmin" stepKey="loginToAdminArea"/> + <magentoCLI command="indexer:reindex" stepKey="reindex"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> </before> <!--Logout from Admin Area--> <after> From 51996a128081536489c26565581364618a496e11 Mon Sep 17 00:00:00 2001 From: Serhii Balko <serhii.balko@transoftgroup.com> Date: Tue, 23 Jul 2019 16:05:30 +0300 Subject: [PATCH 755/773] MC-18366: Shipping confirmation email does not have link for order tracking --- .../Sales/Block/Email/Shipment/Track.php | 60 +++++++++++++++++++ .../sales_email_order_shipment_track.xml | 2 +- .../templates/email/shipment/track.phtml | 8 ++- 3 files changed, 67 insertions(+), 3 deletions(-) create mode 100644 app/code/Magento/Sales/Block/Email/Shipment/Track.php diff --git a/app/code/Magento/Sales/Block/Email/Shipment/Track.php b/app/code/Magento/Sales/Block/Email/Shipment/Track.php new file mode 100644 index 0000000000000..7780657e770cf --- /dev/null +++ b/app/code/Magento/Sales/Block/Email/Shipment/Track.php @@ -0,0 +1,60 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Sales\Block\Email\Shipment; + +use Magento\Framework\View\Element\Template; +use Magento\Framework\View\Element\Template\Context; +use Magento\Sales\Model\Order\Shipment\Track as TrackModel; +use Magento\Shipping\Helper\Data as ShippingHelper; + +/** + * Shipment track info for email + */ +class Track extends Template +{ + /** + * @var ShippingHelper + */ + private $helper; + + /** + * @param Context $context + * @param ShippingHelper $helper + * @param array $data + */ + public function __construct( + Context $context, + ShippingHelper $helper, + array $data = [] + ) { + parent::__construct($context, $data); + $this->helper = $helper; + } + + /** + * Get Shipping tracking URL + * + * @param TrackModel $track + * @return string + */ + public function getTrackingUrl(TrackModel $track): string + { + return $this->helper->getTrackingPopupUrlBySalesModel($track); + } + + /** + * Get Shipping tracking URL escaped + * + * @param TrackModel $track + * @return string + */ + public function getTrackingUrlEscaped(TrackModel $track): string + { + return $this->escapeUrl($this->getTrackingUrl($track)); + } +} diff --git a/app/code/Magento/Sales/view/frontend/layout/sales_email_order_shipment_track.xml b/app/code/Magento/Sales/view/frontend/layout/sales_email_order_shipment_track.xml index 91414663951d3..e0daa49329dfb 100644 --- a/app/code/Magento/Sales/view/frontend/layout/sales_email_order_shipment_track.xml +++ b/app/code/Magento/Sales/view/frontend/layout/sales_email_order_shipment_track.xml @@ -8,6 +8,6 @@ <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"> <update handle="sales_email_order_shipment_renderers"/> <body> - <block class="Magento\Framework\View\Element\Template" name="sales.order.email.shipment.track" template="Magento_Sales::email/shipment/track.phtml"/> + <block class="Magento\Sales\Block\Email\Shipment\Track" name="sales.order.email.shipment.track" template="Magento_Sales::email/shipment/track.phtml"/> </body> </page> \ No newline at end of file diff --git a/app/code/Magento/Sales/view/frontend/templates/email/shipment/track.phtml b/app/code/Magento/Sales/view/frontend/templates/email/shipment/track.phtml index 7b3769b2971e5..2d24525733068 100644 --- a/app/code/Magento/Sales/view/frontend/templates/email/shipment/track.phtml +++ b/app/code/Magento/Sales/view/frontend/templates/email/shipment/track.phtml @@ -3,8 +3,8 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ - ?> +<?php /* @var \Magento\Sales\Block\Email\Shipment\Track $block */ ?> <?php $_shipment = $block->getShipment() ?> <?php /* @var \Magento\Sales\Model\Order $_order */ @@ -24,7 +24,11 @@ $_order = $block->getOrder() ?> <?php foreach ($trackCollection as $_item) : ?> <tr> <td><?= $block->escapeHtml($_item->getTitle()) ?>:</td> - <td><?= $block->escapeHtml($_item->getNumber()) ?></td> + <td> + <a href="<?= $block->getTrackingUrlEscaped($_item) ?>" target="_blank"> + <?= $block->escapeHtml($_item->getNumber()) ?> + </a> + </td> </tr> <?php endforeach ?> </tbody> From 1c629361c5abd210f54bf7d14b332fb681e0b39f Mon Sep 17 00:00:00 2001 From: "rostyslav.hymon" <rostyslav.hymon@transoftgroup.com> Date: Tue, 23 Jul 2019 16:25:23 +0300 Subject: [PATCH 756/773] MC-18472: Product with different custom option prices in different scope overrides to default on import --- .../Model/Import/Product/Option.php | 40 +++++++++++-------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product/Option.php b/app/code/Magento/CatalogImportExport/Model/Import/Product/Option.php index 7435c0bebfc14..8f0d247ce15c3 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product/Option.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product/Option.php @@ -1504,6 +1504,7 @@ protected function _collectOptionTypeData( $specificTypeData = $this->_getSpecificTypeData($rowData, 0, false); //For others stores if ($specificTypeData) { + $typePrices[$nextValueId][$this->_rowStoreId] = $specificTypeData['price']; $typeTitles[$nextValueId++][$this->_rowStoreId] = $specificTypeData['title']; } } @@ -1788,29 +1789,30 @@ protected function _getPriceData(array $rowData, $optionId, $type) */ protected function _getSpecificTypeData(array $rowData, $optionTypeId, $defaultStore = true) { + $data = false; + $priceData = false; + $customOptionRowPrice = $rowData[self::COLUMN_ROW_PRICE]; + if (!empty($customOptionRowPrice) || $customOptionRowPrice === '0') { + $priceData = [ + 'price' => (double)rtrim($rowData[self::COLUMN_ROW_PRICE], '%'), + 'price_type' => 'fixed', + ]; + if ('%' == substr($rowData[self::COLUMN_ROW_PRICE], -1)) { + $priceData['price_type'] = 'percent'; + } + } if (!empty($rowData[self::COLUMN_ROW_TITLE]) && $defaultStore && empty($rowData[self::COLUMN_STORE])) { $valueData = [ 'option_type_id' => $optionTypeId, 'sort_order' => empty($rowData[self::COLUMN_ROW_SORT]) ? 0 : abs($rowData[self::COLUMN_ROW_SORT]), 'sku' => !empty($rowData[self::COLUMN_ROW_SKU]) ? $rowData[self::COLUMN_ROW_SKU] : '', ]; - - $priceData = false; - $customOptionRowPrice = $rowData[self::COLUMN_ROW_PRICE]; - if (!empty($customOptionRowPrice) || $customOptionRowPrice === '0') { - $priceData = [ - 'price' => (double)rtrim($rowData[self::COLUMN_ROW_PRICE], '%'), - 'price_type' => 'fixed', - ]; - if ('%' == substr($rowData[self::COLUMN_ROW_PRICE], -1)) { - $priceData['price_type'] = 'percent'; - } - } - return ['value' => $valueData, 'title' => $rowData[self::COLUMN_ROW_TITLE], 'price' => $priceData]; + $data = ['value' => $valueData, 'title' => $rowData[self::COLUMN_ROW_TITLE], 'price' => $priceData]; } elseif (!empty($rowData[self::COLUMN_ROW_TITLE]) && !$defaultStore && !empty($rowData[self::COLUMN_STORE])) { - return ['title' => $rowData[self::COLUMN_ROW_TITLE]]; + $data = ['title' => $rowData[self::COLUMN_ROW_TITLE], 'price' => $priceData]; } - return false; + + return $data; } /** @@ -1868,7 +1870,9 @@ protected function _saveTitles(array $titles) { $titleRows = []; foreach ($titles as $optionId => $storeInfo) { - foreach ($storeInfo as $storeId => $title) { + //for use default + $uniqStoreInfo = array_unique($storeInfo); + foreach ($uniqStoreInfo as $storeId => $title) { $titleRows[] = ['option_id' => $optionId, 'store_id' => $storeId, 'title' => $title]; } } @@ -1963,7 +1967,9 @@ protected function _saveSpecificTypeTitles(array $typeTitles) { $optionTypeTitleRows = []; foreach ($typeTitles as $optionTypeId => $storesData) { - foreach ($storesData as $storeId => $title) { + //for use default + $uniqStoresData = array_unique($storesData); + foreach ($uniqStoresData as $storeId => $title) { $optionTypeTitleRows[] = [ 'option_type_id' => $optionTypeId, 'store_id' => $storeId, From a1878b420728da1cabc02ce0e83d7ae58ccc8e53 Mon Sep 17 00:00:00 2001 From: Krissy Hiserote <khiserote@magento.com> Date: Tue, 23 Jul 2019 11:37:44 -0500 Subject: [PATCH 757/773] MC-15776: Merge release branch into 2.3-develop - skip MFTF test --- .../Test/Mftf/Test/TransactionalEmailsLogoUploadTest.xml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Email/Test/Mftf/Test/TransactionalEmailsLogoUploadTest.xml b/app/code/Magento/Email/Test/Mftf/Test/TransactionalEmailsLogoUploadTest.xml index 4972a954c440c..9e1d9c5c3cdbb 100644 --- a/app/code/Magento/Email/Test/Mftf/Test/TransactionalEmailsLogoUploadTest.xml +++ b/app/code/Magento/Email/Test/Mftf/Test/TransactionalEmailsLogoUploadTest.xml @@ -17,12 +17,13 @@ <severity value="CRITICAL"/> <testCaseId value="MC-13908"/> <group value="LogoUpload"/> + <skip> + <issueId value="MC-18496"/> + </skip> </annotations> <!--Login to Admin Area--> <before> <actionGroup ref="LoginAsAdmin" stepKey="loginToAdminArea"/> - <magentoCLI command="indexer:reindex" stepKey="reindex"/> - <magentoCLI command="cache:flush" stepKey="flushCache"/> </before> <!--Logout from Admin Area--> <after> From 02aa020892f1eeefcc086043f1c2a5f798fb059b Mon Sep 17 00:00:00 2001 From: Andrii Dimov <adimov@adobe.com> Date: Thu, 11 Jul 2019 20:33:46 -0500 Subject: [PATCH 758/773] MC-17981: Pricing Index runs without ever completing --- .../Magento/Catalog/Model/Indexer/Product/Price/Action/Full.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Catalog/Model/Indexer/Product/Price/Action/Full.php b/app/code/Magento/Catalog/Model/Indexer/Product/Price/Action/Full.php index 858eba3ab217a..b30c85cfc52f0 100644 --- a/app/code/Magento/Catalog/Model/Indexer/Product/Price/Action/Full.php +++ b/app/code/Magento/Catalog/Model/Indexer/Product/Price/Action/Full.php @@ -279,6 +279,7 @@ private function getBatchesForIndexer(string $typeId): BatchIterator $select = $connection->select(); $select->distinct(true); $select->from(['e' => $entityMetadata->getEntityTable()], $entityMetadata->getIdentifierField()); + $select->where('type_id = ?', $typeId); return $this->batchQueryGenerator->generate( $this->getProductMetaData()->getIdentifierField(), From 176c6215d9e3d2a26ebe7eb0383cd18891042a5d Mon Sep 17 00:00:00 2001 From: "rostyslav.hymon" <rostyslav.hymon@transoftgroup.com> Date: Wed, 24 Jul 2019 11:47:21 +0300 Subject: [PATCH 759/773] MC-18472: Product with different custom option prices in different scope overrides to default on import --- .../Model/Import/Product/Option.php | 49 ++++++++++--------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product/Option.php b/app/code/Magento/CatalogImportExport/Model/Import/Product/Option.php index 8f0d247ce15c3..6cdafa7fc6f5a 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product/Option.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product/Option.php @@ -669,6 +669,7 @@ protected function _findNewOptionsWithTheSameTitles() * * @param array $sourceProductData * @return array + * phpcs:disable Generic.Metrics.NestingLevel */ protected function _getNewOptionsWithTheSameTitlesErrorRows(array $sourceProductData) { @@ -697,6 +698,7 @@ protected function _getNewOptionsWithTheSameTitlesErrorRows(array $sourceProduct * Find options with the same titles in DB * * @return array + * phpcs:disable Generic.Metrics.NestingLevel */ protected function _findOldOptionsWithTheSameTitles() { @@ -730,6 +732,7 @@ protected function _findOldOptionsWithTheSameTitles() * Find source file options, which have analogs in DB with the same name, but with different type * * @return array + * phpcs:disable Generic.Metrics.NestingLevel */ protected function _findNewOldOptionsTypeMismatch() { @@ -1067,7 +1070,7 @@ protected function _isSecondaryOptionRow(array $rowData) * * @param array &$options * @param array &$titles - * @param array $typeValues + * @param array $typeValues * @return bool */ protected function _isReadyForSaving(array &$options, array &$titles, array $typeValues) @@ -1414,9 +1417,9 @@ protected function _initProductsSku() /** * Collect custom option main data to import * - * @param array $rowData - * @param int &$prevOptionId - * @param int &$nextOptionId + * @param array $rowData + * @param int &$prevOptionId + * @param int &$nextOptionId * @param array &$products * @param array &$prices * @return array|null @@ -1454,9 +1457,9 @@ protected function _collectOptionMainData( /** * Collect custom option type data to import * - * @param array $rowData - * @param int &$prevOptionId - * @param int &$nextValueId + * @param array $rowData + * @param int &$prevOptionId + * @param int &$nextValueId * @param array &$typeValues * @param array &$typePrices * @param array &$typeTitles @@ -1504,7 +1507,9 @@ protected function _collectOptionTypeData( $specificTypeData = $this->_getSpecificTypeData($rowData, 0, false); //For others stores if ($specificTypeData) { - $typePrices[$nextValueId][$this->_rowStoreId] = $specificTypeData['price']; + if (isset($specificTypeData['price'])) { + $typePrices[$nextValueId][$this->_rowStoreId] = $specificTypeData['price']; + } $typeTitles[$nextValueId++][$this->_rowStoreId] = $specificTypeData['title']; } } @@ -1513,8 +1518,8 @@ protected function _collectOptionTypeData( /** * Collect custom option title to import * - * @param array $rowData - * @param int $prevOptionId + * @param array $rowData + * @param int $prevOptionId * @param array &$titles * @return void */ @@ -1789,17 +1794,12 @@ protected function _getPriceData(array $rowData, $optionId, $type) */ protected function _getSpecificTypeData(array $rowData, $optionTypeId, $defaultStore = true) { - $data = false; - $priceData = false; + $data = []; + $priceData = []; $customOptionRowPrice = $rowData[self::COLUMN_ROW_PRICE]; if (!empty($customOptionRowPrice) || $customOptionRowPrice === '0') { - $priceData = [ - 'price' => (double)rtrim($rowData[self::COLUMN_ROW_PRICE], '%'), - 'price_type' => 'fixed', - ]; - if ('%' == substr($rowData[self::COLUMN_ROW_PRICE], -1)) { - $priceData['price_type'] = 'percent'; - } + $priceData['price'] = (double)rtrim($rowData[self::COLUMN_ROW_PRICE], '%'); + $priceData['price_type'] = ('%' == substr($rowData[self::COLUMN_ROW_PRICE], -1)) ? 'percent' : 'fixed'; } if (!empty($rowData[self::COLUMN_ROW_TITLE]) && $defaultStore && empty($rowData[self::COLUMN_STORE])) { $valueData = [ @@ -1807,12 +1807,17 @@ protected function _getSpecificTypeData(array $rowData, $optionTypeId, $defaultS 'sort_order' => empty($rowData[self::COLUMN_ROW_SORT]) ? 0 : abs($rowData[self::COLUMN_ROW_SORT]), 'sku' => !empty($rowData[self::COLUMN_ROW_SKU]) ? $rowData[self::COLUMN_ROW_SKU] : '', ]; - $data = ['value' => $valueData, 'title' => $rowData[self::COLUMN_ROW_TITLE], 'price' => $priceData]; + $data['value'] = $valueData; + $data['title'] = $rowData[self::COLUMN_ROW_TITLE]; + $data['price'] = $priceData; } elseif (!empty($rowData[self::COLUMN_ROW_TITLE]) && !$defaultStore && !empty($rowData[self::COLUMN_STORE])) { - $data = ['title' => $rowData[self::COLUMN_ROW_TITLE], 'price' => $priceData]; + if ($priceData) { + $data['price'] = $priceData; + } + $data['title'] = $rowData[self::COLUMN_ROW_TITLE]; } - return $data; + return $data ?: false; } /** From b30ab6993dfa32dda8e7acfbbf9b91724834d23b Mon Sep 17 00:00:00 2001 From: Serhii Balko <serhii.balko@transoftgroup.com> Date: Wed, 24 Jul 2019 13:26:27 +0300 Subject: [PATCH 760/773] MC-18366: Shipping confirmation email does not have link for order tracking --- .../view/frontend/templates/tracking/popup.phtml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/app/code/Magento/Shipping/view/frontend/templates/tracking/popup.phtml b/app/code/Magento/Shipping/view/frontend/templates/tracking/popup.phtml index ee8a834044aa7..70e7f53f63953 100644 --- a/app/code/Magento/Shipping/view/frontend/templates/tracking/popup.phtml +++ b/app/code/Magento/Shipping/view/frontend/templates/tracking/popup.phtml @@ -60,3 +60,18 @@ $results = $block->getTrackingInfo(); </button> </div> </div> +<script> + require([ + 'jquery', + 'prototype' + ], function (jQuery) { + var hideActions = function () { + jQuery('.actions button.close').hide(); + }; + + /* hide the close button when the content doesn't open in a modal window */ + if (window.opener === null || typeof window.opener === "undefined") { + hideActions(); + } + }); +</script> \ No newline at end of file From fe84af174f325eadf17f6a3753b62aca0323c748 Mon Sep 17 00:00:00 2001 From: "rostyslav.hymon" <rostyslav.hymon@transoftgroup.com> Date: Wed, 24 Jul 2019 13:58:14 +0300 Subject: [PATCH 761/773] MC-18472: Product with different custom option prices in different scope overrides to default on import --- .../product_with_custom_options_and_multiple_store_views.csv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/product_with_custom_options_and_multiple_store_views.csv b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/product_with_custom_options_and_multiple_store_views.csv index 69d460cde472e..f068365258546 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/product_with_custom_options_and_multiple_store_views.csv +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/product_with_custom_options_and_multiple_store_views.csv @@ -1,4 +1,4 @@ sku,website_code,store_view_code,attribute_set_code,product_type,name,description,short_description,weight,product_online,visibility,product_websites,categories,price,special_price,special_price_from_date,special_price_to_date,tax_class_name,url_key,meta_title,meta_keywords,meta_description,base_image,base_image_label,small_image,small_image_label,thumbnail_image,thumbnail_image_label,additional_images,additional_image_labels,configurable_variation_labels,configurable_variations,bundle_price_type,bundle_sku_type,bundle_weight_type,bundle_values,downloadble_samples,downloadble_links,associated_skus,related_skus,crosssell_skus,upsell_skus,custom_options,additional_attributes,manage_stock,is_in_stock,qty,out_of_stock_qty,is_qty_decimal,allow_backorders,min_cart_qty,max_cart_qty,notify_on_stock_below,qty_increments,enable_qty_increments,is_decimal_divided,new_from_date,new_to_date,gift_message_available,created_at,updated_at,custom_design,custom_design_from,custom_design_to,custom_layout_update,page_layout,product_options_container,msrp_price,msrp_display_actual_price_type,map_enabled simple,base,,Default,simple,New Product,,,9,1,"Catalog, Search",base,,10,,,,Taxable Goods,new-product,,,,,,,,,,,,,,,,,,,,,,,,"name=Test Select,type=drop_down,required=1,price=3,option_title=Select Option 1,sku=3-1-select|name=Test Select,type=drop_down,required=1,price=3,option_title=Select Option 2,sku=3-2-select|name=Test Field Title,type=field,required=1,sku=1-text,price=0,price_type=fixed,max_characters=10|name=Test Date and Time Title,type=date_time,required=1,price=2,sku=2-date|name=Test Checkbox,type=checkbox,required=1,price=3,option_title=Checkbox Option 1,sku=4-1-select|name=Test Checkbox,type=checkbox,required=1,price=3,option_title=Checkbox Option 2,sku=4-2-select|name=Test Radio,type=radio,required=1,price=3,option_title=Radio Option 1,sku=5-1-radio|name=Test Radio,type=radio,required=1,price=3,option_title=Radio Option 2,sku=5-2-radio",,1,1,999,0,0,0,1,10000,1,1,0,0,,,,,,,,,,,Block after Info Column,,, simple,,default,Default,simple,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"name=Test Select_default,type=drop_down,option_title=Select Option 1_default|name=Test Select_default,type=drop_down,option_title=Select Option 2_default|name=Test Field Title_default,type=field|name=Test Date and Time Title_default,type=date_time|name=Test Checkbox_default,type=checkbox,option_title=Checkbox Option 1_default|name=Test Checkbox_default,type=checkbox,option_title=Checkbox Option 2_default|name=Test Radio_default,type=radio,option_title=Radio Option 1_default|name=Test Radio_default,type=radio,option_title=Radio Option 2_default",,,,,,,,,,,,,,,,,,,,,,,,,,, -simple,,fixture_second_store,Default,simple,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"name=Test Select_fixture_second_store,type=drop_down,option_title=Select Option 1_fixture_second_store|name=Test Select_fixture_second_store,type=drop_down,option_title=Select Option 2_fixture_second_store|name=Test Field Title_fixture_second_store,type=field|name=Test Date and Time Title_fixture_second_store,type=date_time|name=Test Checkbox_second_store,type=checkbox,option_title=Checkbox Option 1_second_store|name=Test Checkbox_second_store,type=checkbox,option_title=Checkbox Option 2_second_store|name=Test Radio_fixture_second_store,type=radio,option_title=Radio Option 1_fixture_second_store|name=Test Radio_fixture_second_store,type=radio,option_title=Radio Option 2_fixture_second_store",,,,,,,,,,,,,,,,,,,,,,,,,,, +simple,,fixture_second_store,Default,simple,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"name=Test Select_fixture_second_store,type=drop_down,price=1,option_title=Select Option 1_fixture_second_store|name=Test Select_fixture_second_store,type=drop_down,option_title=Select Option 2_fixture_second_store|name=Test Field Title_fixture_second_store,type=field|name=Test Date and Time Title_fixture_second_store,type=date_time|name=Test Checkbox_second_store,type=checkbox,option_title=Checkbox Option 1_second_store|name=Test Checkbox_second_store,type=checkbox,option_title=Checkbox Option 2_second_store|name=Test Radio_fixture_second_store,type=radio,option_title=Radio Option 1_fixture_second_store|name=Test Radio_fixture_second_store,type=radio,option_title=Radio Option 2_fixture_second_store",,,,,,,,,,,,,,,,,,,,,,,,,,, From 4e22c63169cbdb4650be2069e46b782e485b4940 Mon Sep 17 00:00:00 2001 From: Serhii Balko <serhii.balko@transoftgroup.com> Date: Wed, 24 Jul 2019 16:31:50 +0300 Subject: [PATCH 762/773] MC-18366: Shipping confirmation email does not have link for order tracking --- .../Email/Shipment/TrackingUrl.php | 42 +++++++++++++ .../Sales/Block/Email/Shipment/Track.php | 60 ------------------- .../sales_email_order_shipment_track.xml | 6 +- .../templates/email/shipment/track.phtml | 2 +- .../Adminhtml/Order/Shipment/SaveTest.php | 18 +++++- 5 files changed, 65 insertions(+), 63 deletions(-) create mode 100644 app/code/Magento/Sales/Block/DataProviders/Email/Shipment/TrackingUrl.php delete mode 100644 app/code/Magento/Sales/Block/Email/Shipment/Track.php diff --git a/app/code/Magento/Sales/Block/DataProviders/Email/Shipment/TrackingUrl.php b/app/code/Magento/Sales/Block/DataProviders/Email/Shipment/TrackingUrl.php new file mode 100644 index 0000000000000..cdc4ba2ce19d3 --- /dev/null +++ b/app/code/Magento/Sales/Block/DataProviders/Email/Shipment/TrackingUrl.php @@ -0,0 +1,42 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Sales\Block\DataProviders\Email\Shipment; + +use Magento\Framework\View\Element\Block\ArgumentInterface; +use Magento\Sales\Model\Order\Shipment\Track; +use Magento\Shipping\Helper\Data as ShippingHelper; + +/** + * Shipment track info for email + */ +class TrackingUrl implements ArgumentInterface +{ + /** + * @var ShippingHelper + */ + private $helper; + + /** + * @param ShippingHelper $helper + */ + public function __construct(ShippingHelper $helper) + { + $this->helper = $helper; + } + + /** + * Get Shipping tracking URL + * + * @param Track $track + * @return string + */ + public function getUrl(Track $track): string + { + return $this->helper->getTrackingPopupUrlBySalesModel($track); + } +} diff --git a/app/code/Magento/Sales/Block/Email/Shipment/Track.php b/app/code/Magento/Sales/Block/Email/Shipment/Track.php deleted file mode 100644 index 7780657e770cf..0000000000000 --- a/app/code/Magento/Sales/Block/Email/Shipment/Track.php +++ /dev/null @@ -1,60 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -declare(strict_types=1); - -namespace Magento\Sales\Block\Email\Shipment; - -use Magento\Framework\View\Element\Template; -use Magento\Framework\View\Element\Template\Context; -use Magento\Sales\Model\Order\Shipment\Track as TrackModel; -use Magento\Shipping\Helper\Data as ShippingHelper; - -/** - * Shipment track info for email - */ -class Track extends Template -{ - /** - * @var ShippingHelper - */ - private $helper; - - /** - * @param Context $context - * @param ShippingHelper $helper - * @param array $data - */ - public function __construct( - Context $context, - ShippingHelper $helper, - array $data = [] - ) { - parent::__construct($context, $data); - $this->helper = $helper; - } - - /** - * Get Shipping tracking URL - * - * @param TrackModel $track - * @return string - */ - public function getTrackingUrl(TrackModel $track): string - { - return $this->helper->getTrackingPopupUrlBySalesModel($track); - } - - /** - * Get Shipping tracking URL escaped - * - * @param TrackModel $track - * @return string - */ - public function getTrackingUrlEscaped(TrackModel $track): string - { - return $this->escapeUrl($this->getTrackingUrl($track)); - } -} diff --git a/app/code/Magento/Sales/view/frontend/layout/sales_email_order_shipment_track.xml b/app/code/Magento/Sales/view/frontend/layout/sales_email_order_shipment_track.xml index e0daa49329dfb..bbc7f04ce94fd 100644 --- a/app/code/Magento/Sales/view/frontend/layout/sales_email_order_shipment_track.xml +++ b/app/code/Magento/Sales/view/frontend/layout/sales_email_order_shipment_track.xml @@ -8,6 +8,10 @@ <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"> <update handle="sales_email_order_shipment_renderers"/> <body> - <block class="Magento\Sales\Block\Email\Shipment\Track" name="sales.order.email.shipment.track" template="Magento_Sales::email/shipment/track.phtml"/> + <block class="Magento\Framework\View\Element\Template" name="sales.order.email.shipment.track" template="Magento_Sales::email/shipment/track.phtml"> + <arguments> + <argument name="tracking_url" xsi:type="object">Magento\Sales\Block\DataProviders\Email\Shipment\TrackingUrl</argument> + </arguments> + </block> </body> </page> \ No newline at end of file diff --git a/app/code/Magento/Sales/view/frontend/templates/email/shipment/track.phtml b/app/code/Magento/Sales/view/frontend/templates/email/shipment/track.phtml index 2d24525733068..35e184ead5a67 100644 --- a/app/code/Magento/Sales/view/frontend/templates/email/shipment/track.phtml +++ b/app/code/Magento/Sales/view/frontend/templates/email/shipment/track.phtml @@ -25,7 +25,7 @@ $_order = $block->getOrder() ?> <tr> <td><?= $block->escapeHtml($_item->getTitle()) ?>:</td> <td> - <a href="<?= $block->getTrackingUrlEscaped($_item) ?>" target="_blank"> + <a href="<?= $block->escapeUrl($block->getTrackingUrl()->getUrl($_item)) ?>" target="_blank"> <?= $block->escapeHtml($_item->getNumber()) ?> </a> </td> diff --git a/dev/tests/integration/testsuite/Magento/Shipping/Controller/Adminhtml/Order/Shipment/SaveTest.php b/dev/tests/integration/testsuite/Magento/Shipping/Controller/Adminhtml/Order/Shipment/SaveTest.php index e95e99224a6d9..ec547ad036455 100644 --- a/dev/tests/integration/testsuite/Magento/Shipping/Controller/Adminhtml/Order/Shipment/SaveTest.php +++ b/dev/tests/integration/testsuite/Magento/Shipping/Controller/Adminhtml/Order/Shipment/SaveTest.php @@ -28,7 +28,14 @@ class SaveTest extends AbstractShipmentControllerTest */ public function testSendEmailOnShipmentSave(): void { - $order = $this->prepareRequest(['shipment' => ['send_email' => true]]); + $tracking = [ + [ + 'number' => 'some_racking_number', + 'title' => 'some_tracking_title', + 'carrier_code' => 'carrier_code' + ] + ]; + $order = $this->prepareRequest(['shipment' => ['send_email' => true], 'tracking' => $tracking]); $this->dispatch('backend/admin/order_shipment/save'); $this->assertSessionMessages( @@ -47,6 +54,15 @@ public function testSendEmailOnShipmentSave(): void ), new StringContains( "Your Shipment #{$shipment->getIncrementId()} for Order #{$order->getIncrementId()}" + ), + new StringContains( + "some_tracking_title" + ), + new StringContains( + "some_racking_number" + ), + new StringContains( + "shipping/tracking/popup?hash=" ) ); From 64d426633d7ad015850c5739bf9f077f3d6ea1fe Mon Sep 17 00:00:00 2001 From: Serhii Balko <serhii.balko@transoftgroup.com> Date: Wed, 24 Jul 2019 17:00:31 +0300 Subject: [PATCH 763/773] MC-18366: Shipping confirmation email does not have link for order tracking --- .../Sales/view/frontend/templates/email/shipment/track.phtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Sales/view/frontend/templates/email/shipment/track.phtml b/app/code/Magento/Sales/view/frontend/templates/email/shipment/track.phtml index 35e184ead5a67..5349ae5f1b1a8 100644 --- a/app/code/Magento/Sales/view/frontend/templates/email/shipment/track.phtml +++ b/app/code/Magento/Sales/view/frontend/templates/email/shipment/track.phtml @@ -4,7 +4,7 @@ * See COPYING.txt for license details. */ ?> -<?php /* @var \Magento\Sales\Block\Email\Shipment\Track $block */ ?> +<?php /* @var \Magento\Framework\View\Element\Template $block */ ?> <?php $_shipment = $block->getShipment() ?> <?php /* @var \Magento\Sales\Model\Order $_order */ From 05f0181dda1de40f0a841fc6727ad4f39481528b Mon Sep 17 00:00:00 2001 From: Serhii Balko <serhii.balko@transoftgroup.com> Date: Wed, 24 Jul 2019 17:05:30 +0300 Subject: [PATCH 764/773] MC-18366: Shipping confirmation email does not have link for order tracking --- .../Shipping/view/frontend/templates/tracking/popup.phtml | 6 +----- .../Controller/Adminhtml/Order/Shipment/SaveTest.php | 6 +++--- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/app/code/Magento/Shipping/view/frontend/templates/tracking/popup.phtml b/app/code/Magento/Shipping/view/frontend/templates/tracking/popup.phtml index 70e7f53f63953..71558465c0ba8 100644 --- a/app/code/Magento/Shipping/view/frontend/templates/tracking/popup.phtml +++ b/app/code/Magento/Shipping/view/frontend/templates/tracking/popup.phtml @@ -65,13 +65,9 @@ $results = $block->getTrackingInfo(); 'jquery', 'prototype' ], function (jQuery) { - var hideActions = function () { - jQuery('.actions button.close').hide(); - }; - /* hide the close button when the content doesn't open in a modal window */ if (window.opener === null || typeof window.opener === "undefined") { - hideActions(); + jQuery('.actions button.close').hide(); } }); </script> \ No newline at end of file diff --git a/dev/tests/integration/testsuite/Magento/Shipping/Controller/Adminhtml/Order/Shipment/SaveTest.php b/dev/tests/integration/testsuite/Magento/Shipping/Controller/Adminhtml/Order/Shipment/SaveTest.php index ec547ad036455..e3374064aa3cb 100644 --- a/dev/tests/integration/testsuite/Magento/Shipping/Controller/Adminhtml/Order/Shipment/SaveTest.php +++ b/dev/tests/integration/testsuite/Magento/Shipping/Controller/Adminhtml/Order/Shipment/SaveTest.php @@ -56,13 +56,13 @@ public function testSendEmailOnShipmentSave(): void "Your Shipment #{$shipment->getIncrementId()} for Order #{$order->getIncrementId()}" ), new StringContains( - "some_tracking_title" + 'some_tracking_title' ), new StringContains( - "some_racking_number" + 'some_racking_number' ), new StringContains( - "shipping/tracking/popup?hash=" + 'shipping/tracking/popup?hash=' ) ); From 03626cb2c9c0cdb8f7271ca49942137a6a168e91 Mon Sep 17 00:00:00 2001 From: Serhii Balko <serhii.balko@transoftgroup.com> Date: Wed, 24 Jul 2019 17:28:05 +0300 Subject: [PATCH 765/773] MC-18366: Shipping confirmation email does not have link for order tracking --- .../Shipping/view/frontend/templates/tracking/popup.phtml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/code/Magento/Shipping/view/frontend/templates/tracking/popup.phtml b/app/code/Magento/Shipping/view/frontend/templates/tracking/popup.phtml index 71558465c0ba8..1e8760b3afd6d 100644 --- a/app/code/Magento/Shipping/view/frontend/templates/tracking/popup.phtml +++ b/app/code/Magento/Shipping/view/frontend/templates/tracking/popup.phtml @@ -62,8 +62,7 @@ $results = $block->getTrackingInfo(); </div> <script> require([ - 'jquery', - 'prototype' + 'jquery' ], function (jQuery) { /* hide the close button when the content doesn't open in a modal window */ if (window.opener === null || typeof window.opener === "undefined") { From a13c4ae9c799dbc846737046d4c9ec39fed195c0 Mon Sep 17 00:00:00 2001 From: Dave Macaulay <macaulay@adobe.com> Date: Wed, 24 Jul 2019 10:56:08 -0500 Subject: [PATCH 766/773] MC-18558: Fix PHP version composer.json check for Page Builder static test failure --- .../Magento/Test/Integrity/ComposerTest.php | 27 +++++++------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/ComposerTest.php b/dev/tests/static/testsuite/Magento/Test/Integrity/ComposerTest.php index a42fe147303bb..438d9530ec5d5 100644 --- a/dev/tests/static/testsuite/Magento/Test/Integrity/ComposerTest.php +++ b/dev/tests/static/testsuite/Magento/Test/Integrity/ComposerTest.php @@ -326,24 +326,15 @@ private function assertDependsOnFramework(\StdClass $json) private function assertPhpVersionInSync($name, $phpVersion) { if (isset(self::$rootJson['require']['php'])) { - if ($this->isVendorMagento($name)) { - $this->assertEquals( - self::$rootJson['require']['php'], - $phpVersion, - "PHP version {$phpVersion} in component {$name} is inconsistent with version " - . self::$rootJson['require']['php'] . ' in root composer.json' - ); - } else { - $composerVersionsPattern = '{\s*\|\|?\s*}'; - $rootPhpVersions = preg_split($composerVersionsPattern, self::$rootJson['require']['php']); - $modulePhpVersions = preg_split($composerVersionsPattern, $phpVersion); - - $this->assertEmpty( - array_diff($rootPhpVersions, $modulePhpVersions), - "PHP version {$phpVersion} in component {$name} is inconsistent with version " - . self::$rootJson['require']['php'] . ' in root composer.json' - ); - } + $composerVersionsPattern = '{\s*\|\|?\s*}'; + $rootPhpVersions = preg_split($composerVersionsPattern, self::$rootJson['require']['php']); + $modulePhpVersions = preg_split($composerVersionsPattern, $phpVersion); + + $this->assertEmpty( + array_diff($rootPhpVersions, $modulePhpVersions), + "PHP version {$phpVersion} in component {$name} is inconsistent with version " + . self::$rootJson['require']['php'] . ' in root composer.json' + ); } } From d33f3d7f5b7bf5ac103ca067865b606f7a304c8f Mon Sep 17 00:00:00 2001 From: Soumya Unnikrishnan <sunnikri@adobe.com> Date: Wed, 24 Jul 2019 12:44:36 -0500 Subject: [PATCH 767/773] MC-4459: Convert OnePageCheckoutOfflinePaymentMethodsTest to MFTF Fixed locator --- .../Checkout/Test/Mftf/Section/CheckoutShippingSection.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingSection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingSection.xml index 50bf3dfee0c4d..5d23eb23742b7 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingSection.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingSection.xml @@ -39,7 +39,7 @@ <element name="editActiveAddress" type="button" selector="//div[@class='shipping-address-item selected-item']//span[text()='Edit']" timeout="30"/> <element name="loginButton" type="button" selector="//button[@data-action='checkout-method-login']" timeout="30"/> <element name="editActiveAddressButton" type="button" selector="//div[contains(@class,'payment-method _active')]//button[contains(@class,'action action-edit-address')]" timeout="30"/> - <element name="emailAddress" type="input" selector="#checkout-customer-email"/> + <element name="emailAddress" type="input" selector="#customer-email"/> <element name="shipHereButton" type="button" selector="//div[text()='{{street}}']/button[@class='action action-select-shipping-item']" parameterized="true" timeout="30"/> <element name="textFieldAttrRequireMessage" type="text" selector="//input[@name='custom_attributes[{{attribute}}]']/ancestor::div[contains(@class, 'control')]/div/span" parameterized="true" timeout="30"/> <element name="textFieldAttribute" type="input" selector="[name*='custom_attributes[{{attribute}}]']" parameterized="true" timeout="30"/> From cefdaaa92259a5f97640ca3fc45f8e3b3a4f1133 Mon Sep 17 00:00:00 2001 From: Deepty Thampy <dthampy@adobe.com> Date: Wed, 24 Jul 2019 14:19:23 -0500 Subject: [PATCH 768/773] MC-18552: Add api-functional test for querying for all linked categories for product - added test --- .../Resolver/Product/ProductCategories.php | 2 +- .../GraphQl/Catalog/ProductViewTest.php | 161 ++++++++++++++++++ 2 files changed, 162 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/ProductCategories.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/ProductCategories.php index 736f2a8c8e402..86984a29149ef 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/ProductCategories.php +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/ProductCategories.php @@ -79,7 +79,7 @@ public function getCategoryIdsByProduct(int $productId, int $storeId) } /** - * Get catalog_product_category table name + * Get catalog_category_product table name * * @param int $storeId * @return string diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductViewTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductViewTest.php index 1adca29ffb054..62e34fe254703 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductViewTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductViewTest.php @@ -7,9 +7,11 @@ namespace Magento\GraphQl\Catalog; +use Magento\Catalog\Api\CategoryRepositoryInterface; use Magento\Catalog\Api\Data\ProductInterface; use Magento\Catalog\Api\Data\ProductLinkInterface; use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Model\Category; use Magento\Framework\DataObject; use Magento\Framework\EntityManager\MetadataPool; use Magento\TestFramework\ObjectManager; @@ -970,4 +972,163 @@ private function eavAttributesToGraphQlSchemaFieldTranslator(string $eavAttribut } return $eavAttributeCode; } + + /** + * @magentoApiDataFixture Magento/Catalog/_files/categories.php + */ + public function testProductInAllAnchoredCategories() + { + $query = <<<QUERY +{ + products(filter: {sku: {like: "12345%"}}) + { + items + { + sku + name + categories { + id + name + is_anchor + } + } + } +} +QUERY; + $response = $this->graphQlQuery($query); + $this->assertNotEmpty($response['products']['items'][0]['categories'], "Categories must not be empty"); + /** @var ProductRepositoryInterface $productRepository */ + $productRepository = ObjectManager::getInstance()->get(ProductRepositoryInterface::class); + /** @var CategoryRepositoryInterface $categoryRepository */ + $categoryRepository = ObjectManager::getInstance()->get(CategoryRepositoryInterface::class); + $categoryIds = [3, 4, 5]; + + $productItemsInResponse = $response['products']['items']; + $this->assertEquals(1, count($productItemsInResponse)); + $this->assertCount(3, $productItemsInResponse[0]['categories']); + $categoriesInResponse = array_map(null, $categoryIds, $productItemsInResponse[0]['categories']); + foreach ($categoriesInResponse as $key => $categoryData) { + $this->assertNotEmpty($categoryData); + /** @var Category | Category $category */ + $category = $categoryRepository->get($categoriesInResponse[$key][0]); + $this->assertResponseFields( + $categoriesInResponse[$key][1], + [ + 'name' => $category->getName(), + 'id' => $category->getId(), + 'is_anchor' => $category->getIsAnchor() + ] + ); + } + } + + /** + * Set one of the categories directly assigned to the product as non -anchored. + * Verify that the non-anchored category still shows in the response + * + * @magentoApiDataFixture Magento/Catalog/_files/categories.php + */ + public function testProductWithNonAnchoredParentCategory() + { + $query = <<<QUERY +{ + products(filter: {sku: {like: "12345%"}}) + { + items + { + sku + name + categories { + id + name + is_anchor + } + } + } +} +QUERY; + /** @var CategoryRepositoryInterface $categoryRepository */ + $categoryRepository = ObjectManager::getInstance()->get(CategoryRepositoryInterface::class); + /** @var Category $nonAnchorCategory */ + $nonAnchorCategory = $categoryRepository->get(4); + $nonAnchorCategory->setIsAnchor(false); + $categoryRepository->save($nonAnchorCategory); + $categoryIds = [3, 4, 5]; + + $response = $this->graphQlQuery($query); + $this->assertNotEmpty($response['products']['items'][0]['categories'], "Categories must not be empty"); + + $productItemsInResponse = $response['products']['items']; + $this->assertEquals(1, count($productItemsInResponse)); + $this->assertCount(3, $productItemsInResponse[0]['categories']); + $categoriesInResponse = array_map(null, $categoryIds, $productItemsInResponse[0]['categories']); + foreach ($categoriesInResponse as $key => $categoryData) { + $this->assertNotEmpty($categoryData); + /** @var Category | Category $category */ + $category = $categoryRepository->get($categoriesInResponse[$key][0]); + $this->assertResponseFields( + $categoriesInResponse[$key][1], + [ + 'name' => $category->getName(), + 'id' => $category->getId(), + 'is_anchor' => $category->getIsAnchor() + ] + ); + } + } + /** + * Set as non-anchored, one of the categories not directly assigned to the product + * Verify that the category doesn't show in the response + * + * @magentoApiDataFixture Magento/Catalog/_files/categories.php + */ + public function testProductInNonAnchoredSubCategories() + { + $query = <<<QUERY +{ + products(filter: {sku: {like: "12345%"}}) + { + items + { + sku + name + categories { + id + name + is_anchor + } + } + } +} +QUERY; + /** @var CategoryRepositoryInterface $categoryRepository */ + $categoryRepository = ObjectManager::getInstance()->get(CategoryRepositoryInterface::class); + /** @var Category $nonAnchorCategory */ + $nonAnchorCategory = $categoryRepository->get(3); + //Set the parent category as non-anchored + $nonAnchorCategory->setIsAnchor(false); + $categoryRepository->save($nonAnchorCategory); + $categoryIds = [4, 5]; + + $response = $this->graphQlQuery($query); + $this->assertNotEmpty($response['products']['items'][0]['categories'], "Categories must not be empty"); + + $productItemsInResponse = $response['products']['items']; + $this->assertEquals(1, count($productItemsInResponse)); + $this->assertCount(2, $productItemsInResponse[0]['categories']); + $categoriesInResponse = array_map(null, $categoryIds, $productItemsInResponse[0]['categories']); + foreach ($categoriesInResponse as $key => $categoryData) { + $this->assertNotEmpty($categoryData); + /** @var Category | Category $category */ + $category = $categoryRepository->get($categoriesInResponse[$key][0]); + $this->assertResponseFields( + $categoriesInResponse[$key][1], + [ + 'name' => $category->getName(), + 'id' => $category->getId(), + 'is_anchor' => $category->getIsAnchor() + ] + ); + } + } } From d5fe1e5f41c4d54b0c8cf222ef0ab40990325883 Mon Sep 17 00:00:00 2001 From: Alex Kolesnyk <kolesnyk@adobe.com> Date: Wed, 24 Jul 2019 16:29:25 -0500 Subject: [PATCH 769/773] Test improvements: - test stabilization --- .../Test/Mftf/ActionGroup/AdminOpenUserEditPageActionGroup.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/User/Test/Mftf/ActionGroup/AdminOpenUserEditPageActionGroup.xml b/app/code/Magento/User/Test/Mftf/ActionGroup/AdminOpenUserEditPageActionGroup.xml index e8f8c23b7e4e5..68b5f99112d93 100644 --- a/app/code/Magento/User/Test/Mftf/ActionGroup/AdminOpenUserEditPageActionGroup.xml +++ b/app/code/Magento/User/Test/Mftf/ActionGroup/AdminOpenUserEditPageActionGroup.xml @@ -15,6 +15,7 @@ <amOnPage url="{{AdminUsersPage.url}}" stepKey="openAdminUsersPage"/> <waitForPageLoad stepKey="waitForPageToLoad"/> <click selector="{{AdminLegacyDataGridFilterSection.clear}}" stepKey="resetFilters" /> + <waitForPageLoad stepKey="waitForPageToLoadAfterFilterReset"/> <fillField selector="{{AdminLegacyDataGridFilterSection.inputFieldByNameAttr('username')}}" userInput="{{user.username}}" stepKey="fillSearchUsernameFilter"/> <click selector="{{AdminLegacyDataGridFilterSection.apply}}" stepKey="clickSearch" /> <waitForPageLoad stepKey="waitForGridToLoad"/> From d856f38e3618d36d9c2d18f3850aab7398c34e53 Mon Sep 17 00:00:00 2001 From: Cristian Partica <cpartica@magento.com> Date: Wed, 24 Jul 2019 16:40:33 -0500 Subject: [PATCH 770/773] MC-18550: Modify performance tests to include products with anchored category --- setup/performance-toolkit/benchmark.jmx | 70 ++++++++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) diff --git a/setup/performance-toolkit/benchmark.jmx b/setup/performance-toolkit/benchmark.jmx index e92c0bd738126..c2d4177b789aa 100644 --- a/setup/performance-toolkit/benchmark.jmx +++ b/setup/performance-toolkit/benchmark.jmx @@ -38661,7 +38661,7 @@ if (totalCount == null) { <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"{\n products(\n pageSize:20\n currentPage:1\n search: \"configurable\"\n filter: {name: {like: \"Configurable Product%\"} }\n ) {\n total_count\n items {\n attribute_set_id\n categories\n {\n id\n position\n }\n country_of_manufacture\n created_at\n description {\n html\n }\n gift_message_available\n id\n image\n {\n url\n label\n }\n meta_description\n meta_keyword\n meta_title\n media_gallery_entries\n {\n disabled\n file\n id\n label\n media_type\n position\n types\n content\n {\n base64_encoded_data\n type\n name\n }\n video_content\n {\n media_type\n video_description\n video_metadata\n video_provider\n video_title\n video_url\n }\n }\n name\n new_from_date\n new_to_date\n options_container\n ... on CustomizableProductInterface {\n options\n {\n title\n required\n sort_order\n }\n }\n \n price {\n minimalPrice {\n amount {\n value\n currency\n }\n adjustments {\n amount {\n value\n currency\n }\n code\n description\n }\n }\n maximalPrice {\n amount {\n value\n currency\n }\n adjustments {\n amount {\n value\n currency\n }\n code\n description\n }\n }\n regularPrice {\n amount {\n value\n currency\n }\n adjustments {\n amount {\n value\n currency\n }\n code\n description\n }\n }\n }\n product_links\n {\n link_type\n linked_product_sku\n linked_product_type\n position\n sku\n }\n short_description {\n html\n }\n sku\n small_image\n {\n url\n label\n }\n special_from_date\n special_price\n special_to_date\n swatch_image\n thumbnail\n {\n url\n label\n }\n tier_price\n tier_prices\n {\n customer_group_id\n percentage_value\n qty\n value\n website_id\n }\n type_id\n updated_at\n url_key\n url_path\n websites { id name code sort_order default_group_id is_default }\n ... on PhysicalProductInterface {\n \t\t\tweight\n \t\t\t}\n ... on ConfigurableProduct {\n configurable_options {\n id\n attribute_id\n label\n position\n use_default\n attribute_code\n values {\n value_index\n label\n store_label\n default_label\n use_default_value\n }\n product_id\n }\n variants {\n product {\n ... on PhysicalProductInterface {\n weight\n }\n sku\n color\n attribute_set_id\n categories\n {\n id\n position\n }\n country_of_manufacture\n created_at\n description {\n html\n }\n gift_message_available\n id\n image\n {\n url\n label\n }\n meta_description\n meta_keyword\n meta_title\n media_gallery_entries\n {\n disabled\n file\n id\n label\n media_type\n position\n types\n content\n {\n base64_encoded_data\n type\n name\n }\n video_content\n {\n media_type\n video_description\n video_metadata\n video_provider\n video_title\n video_url\n }\n }\n name\n new_from_date\n new_to_date\n options_container\n ... on CustomizableProductInterface {\n options\n {\n title\n required\n sort_order\n }\n }\n \n price {\n minimalPrice {\n amount {\n value\n currency\n }\n adjustments {\n amount {\n value\n currency\n }\n code\n description\n }\n }\n maximalPrice {\n amount {\n value\n currency\n }\n adjustments {\n amount {\n value\n currency\n }\n code\n description\n }\n }\n regularPrice {\n amount {\n value\n currency\n }\n adjustments {\n amount {\n value\n currency\n }\n code\n description\n }\n }\n }\n product_links\n {\n link_type\n linked_product_sku\n linked_product_type\n position\n sku\n }\n short_description {\n html\n }\n sku\n small_image\n {\n url\n label\n }\n special_from_date\n special_price\n special_to_date\n swatch_image\n thumbnail\n {\n url\n label\n }\n tier_price\n tier_prices\n {\n customer_group_id\n percentage_value\n qty\n value\n website_id\n }\n type_id\n updated_at\n url_key\n url_path\n websites { id name code sort_order default_group_id is_default }\n\n\n }\n attributes {\n label\n code\n value_index\n }\n }\n }\n }\n }\n}\n","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"{\n products(\n pageSize:20\n currentPage:1\n search: \"configurable\"\n filter: {name: {like: \"Configurable Product%\"} }\n ) {\n total_count\n page_info {\n current_page\n page_size\n total_pages\n }\n items {\n attribute_set_id\n categories\n {\n id\n position\n }\n country_of_manufacture\n created_at\n description {\n html\n }\n gift_message_available\n id\n image\n {\n url\n label\n }\n meta_description\n meta_keyword\n meta_title\n media_gallery_entries\n {\n disabled\n file\n id\n label\n media_type\n position\n types\n content\n {\n base64_encoded_data\n type\n name\n }\n video_content\n {\n media_type\n video_description\n video_metadata\n video_provider\n video_title\n video_url\n }\n }\n name\n new_from_date\n new_to_date\n options_container\n ... on CustomizableProductInterface {\n options\n {\n title\n required\n sort_order\n }\n }\n \n price {\n minimalPrice {\n amount {\n value\n currency\n }\n adjustments {\n amount {\n value\n currency\n }\n code\n description\n }\n }\n maximalPrice {\n amount {\n value\n currency\n }\n adjustments {\n amount {\n value\n currency\n }\n code\n description\n }\n }\n regularPrice {\n amount {\n value\n currency\n }\n adjustments {\n amount {\n value\n currency\n }\n code\n description\n }\n }\n }\n product_links\n {\n link_type\n linked_product_sku\n linked_product_type\n position\n sku\n }\n short_description {\n html\n }\n sku\n small_image\n {\n url\n label\n }\n special_from_date\n special_price\n special_to_date\n swatch_image\n thumbnail\n {\n url\n label\n }\n tier_price\n tier_prices\n {\n customer_group_id\n percentage_value\n qty\n value\n website_id\n }\n type_id\n updated_at\n url_key\n url_path\n websites { id name code sort_order default_group_id is_default }\n ... on PhysicalProductInterface {\n \t\t\tweight\n \t\t\t}\n ... on ConfigurableProduct {\n configurable_options {\n id\n attribute_id\n label\n position\n use_default\n attribute_code\n values {\n value_index\n label\n store_label\n default_label\n use_default_value\n }\n product_id\n }\n variants {\n product {\n ... on PhysicalProductInterface {\n weight\n }\n sku\n color\n attribute_set_id\n categories\n {\n id\n position\n }\n country_of_manufacture\n created_at\n description {\n html\n }\n gift_message_available\n id\n image\n {\n url\n label\n }\n meta_description\n meta_keyword\n meta_title\n media_gallery_entries\n {\n disabled\n file\n id\n label\n media_type\n position\n types\n content\n {\n base64_encoded_data\n type\n name\n }\n video_content\n {\n media_type\n video_description\n video_metadata\n video_provider\n video_title\n video_url\n }\n }\n name\n new_from_date\n new_to_date\n options_container\n ... on CustomizableProductInterface {\n options\n {\n title\n required\n sort_order\n }\n }\n \n price {\n minimalPrice {\n amount {\n value\n currency\n }\n adjustments {\n amount {\n value\n currency\n }\n code\n description\n }\n }\n maximalPrice {\n amount {\n value\n currency\n }\n adjustments {\n amount {\n value\n currency\n }\n code\n description\n }\n }\n regularPrice {\n amount {\n value\n currency\n }\n adjustments {\n amount {\n value\n currency\n }\n code\n description\n }\n }\n }\n product_links\n {\n link_type\n linked_product_sku\n linked_product_type\n position\n sku\n }\n short_description {\n html\n }\n sku\n small_image\n {\n url\n label\n }\n special_from_date\n special_price\n special_to_date\n swatch_image\n thumbnail\n {\n url\n label\n }\n tier_price\n tier_prices\n {\n customer_group_id\n percentage_value\n qty\n value\n website_id\n }\n type_id\n updated_at\n url_key\n url_path\n websites { id name code sort_order default_group_id is_default }\n\n\n }\n attributes {\n label\n code\n value_index\n }\n }\n }\n }\n }\n}\n","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -38682,6 +38682,74 @@ if (totalCount == null) { <stringProp name="HTTPSampler.embedded_url_re"/> <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/query_multiple_products_with_extensible_data_objects_using_full_text_and_filter.jmx</stringProp> </HTTPSamplerProxy> + <hashTree> + <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract total_count" enabled="true"> + <stringProp name="VAR">graphql_search_products_query_total_count_fulltext_filter</stringProp> + <stringProp name="JSONPATH">$.data.products.total_count</stringProp> + <stringProp name="DEFAULT"/> + <stringProp name="VARIABLE"/> + <stringProp name="SUBJECT">BODY</stringProp> + </com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> + <hashTree/> + <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract total_pages" enabled="true"> + <stringProp name="VAR">graphql_search_products_query_total_pages_fulltext_filter</stringProp> + <stringProp name="JSONPATH">$.data.products.page_info.total_pages</stringProp> + <stringProp name="DEFAULT"/> + <stringProp name="VARIABLE"/> + <stringProp name="SUBJECT">BODY</stringProp> + </com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> + <hashTree/> + <BeanShellAssertion guiclass="BeanShellAssertionGui" testclass="BeanShellAssertion" testname="Assert total count > 0" enabled="true"> + <stringProp name="BeanShellAssertion.query">String totalCount=vars.get("graphql_search_products_query_total_count_fulltext_filter"); + +if (totalCount == null) { + Failure = true; + FailureMessage = "Not Expected \"totalCount\" to be null"; +} else { + if (Integer.parseInt(totalCount) < 1) { + Failure = true; + FailureMessage = "Expected \"totalCount\" to be greater than zero, Actual: " + totalCount; + } else { + Failure = false; + } +} + + +</stringProp> + <stringProp name="BeanShellAssertion.filename"/> + <stringProp name="BeanShellAssertion.parameters"/> + <boolProp name="BeanShellAssertion.resetInterpreter">false</boolProp> + </BeanShellAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Query products with full text search and filter last page" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"query":"{\n products(\n pageSize:20\n currentPage:${graphql_search_products_query_total_pages_fulltext_filter}\n search: \"configurable\"\n filter: {name: {like: \"Configurable Product%\"} }\n ) {\n total_count\n page_info {\n current_page\n page_size\n total_pages\n }\n items {\n attribute_set_id\n categories\n {\n id\n position\n }\n country_of_manufacture\n created_at\n description {\n html\n }\n gift_message_available\n id\n image\n {\n url\n label\n }\n meta_description\n meta_keyword\n meta_title\n media_gallery_entries\n {\n disabled\n file\n id\n label\n media_type\n position\n types\n content\n {\n base64_encoded_data\n type\n name\n }\n video_content\n {\n media_type\n video_description\n video_metadata\n video_provider\n video_title\n video_url\n }\n }\n name\n new_from_date\n new_to_date\n options_container\n ... on CustomizableProductInterface {\n options\n {\n title\n required\n sort_order\n }\n }\n \n price {\n minimalPrice {\n amount {\n value\n currency\n }\n adjustments {\n amount {\n value\n currency\n }\n code\n description\n }\n }\n maximalPrice {\n amount {\n value\n currency\n }\n adjustments {\n amount {\n value\n currency\n }\n code\n description\n }\n }\n regularPrice {\n amount {\n value\n currency\n }\n adjustments {\n amount {\n value\n currency\n }\n code\n description\n }\n }\n }\n product_links\n {\n link_type\n linked_product_sku\n linked_product_type\n position\n sku\n }\n short_description {\n html\n }\n sku\n small_image\n {\n url\n label\n }\n special_from_date\n special_price\n special_to_date\n swatch_image\n thumbnail\n {\n url\n label\n }\n tier_price\n tier_prices\n {\n customer_group_id\n percentage_value\n qty\n value\n website_id\n }\n type_id\n updated_at\n url_key\n url_path\n websites { id name code sort_order default_group_id is_default }\n ... on PhysicalProductInterface {\n \t\t\tweight\n \t\t\t}\n ... on ConfigurableProduct {\n configurable_options {\n id\n attribute_id\n label\n position\n use_default\n attribute_code\n values {\n value_index\n label\n store_label\n default_label\n use_default_value\n }\n product_id\n }\n variants {\n product {\n ... on PhysicalProductInterface {\n weight\n }\n sku\n color\n attribute_set_id\n categories\n {\n id\n position\n }\n country_of_manufacture\n created_at\n description {\n html\n }\n gift_message_available\n id\n image\n {\n url\n label\n }\n meta_description\n meta_keyword\n meta_title\n media_gallery_entries\n {\n disabled\n file\n id\n label\n media_type\n position\n types\n content\n {\n base64_encoded_data\n type\n name\n }\n video_content\n {\n media_type\n video_description\n video_metadata\n video_provider\n video_title\n video_url\n }\n }\n name\n new_from_date\n new_to_date\n options_container\n ... on CustomizableProductInterface {\n options\n {\n title\n required\n sort_order\n }\n }\n \n price {\n minimalPrice {\n amount {\n value\n currency\n }\n adjustments {\n amount {\n value\n currency\n }\n code\n description\n }\n }\n maximalPrice {\n amount {\n value\n currency\n }\n adjustments {\n amount {\n value\n currency\n }\n code\n description\n }\n }\n regularPrice {\n amount {\n value\n currency\n }\n adjustments {\n amount {\n value\n currency\n }\n code\n description\n }\n }\n }\n product_links\n {\n link_type\n linked_product_sku\n linked_product_type\n position\n sku\n }\n short_description {\n html\n }\n sku\n small_image\n {\n url\n label\n }\n special_from_date\n special_price\n special_to_date\n swatch_image\n thumbnail\n {\n url\n label\n }\n tier_price\n tier_prices\n {\n customer_group_id\n percentage_value\n qty\n value\n website_id\n }\n type_id\n updated_at\n url_key\n url_path\n websites { id name code sort_order default_group_id is_default }\n\n\n }\n attributes {\n label\n code\n value_index\n }\n }\n }\n }\n }\n}\n","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol">${request_protocol}</stringProp> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}graphql</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/graphql/query_multiple_products_with_extensible_data_objects_using_full_text_and_filter_last_page.jmx</stringProp> + </HTTPSamplerProxy> <hashTree> <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract total_count" enabled="true"> <stringProp name="VAR">graphql_search_products_query_total_count_fulltext_filter</stringProp> From 70b1ff3b8d4847583a994ac5f2f8f9fad8bb1b31 Mon Sep 17 00:00:00 2001 From: Alex Kolesnyk <kolesnyk@adobe.com> Date: Wed, 24 Jul 2019 17:22:28 -0500 Subject: [PATCH 771/773] Test improvements: - test stabilization --- ...AdminClickFormActionButtonActionGroup.xml} | 10 ++-- ...l => AdminFilterLegacyGridActionGroup.xml} | 9 ++-- ...AdminResetLegacyGridFilterActionGroup.xml} | 4 +- .../AssertValueInAdminGridActionGroup.xml | 16 ------ ...AdminFillFormCustomVariableActionGroup.xml | 16 ------ .../AdminFillVariableFormActionGroup.xml | 19 +++++++ .../AdminFilterVariableGridActionGroup.xml | 22 ++++++++ ...AdminNavigateToVariablePageActionGroup.xml | 5 +- ...> AdminOpenNewVariablePageActionGroup.xml} | 2 +- ...AdminOpenVariablesGridPageActionGroup.xml} | 2 +- ...sertAdminCustomVariableFormActionGroup.xml | 19 +++++++ ...rtAdminCustomVariableInGridActionGroup.xml | 17 +++++++ .../Variable/Test/Mftf/Data/VariableData.xml | 6 +++ .../Mftf/Section/AdminVariableFormSection.xml | 20 ++++++++ ...xml => AdminVariableGridFilterSection.xml} | 6 +-- .../AdminCreateCustomVariableEntityTest.xml | 51 +++++++++++++++++++ .../Test/CreateCustomVariableEntityTest.xml | 48 ----------------- 17 files changed, 175 insertions(+), 97 deletions(-) rename app/code/Magento/Backend/Test/Mftf/ActionGroup/{AdminClickMainButtonActionGroup.xml => AdminClickFormActionButtonActionGroup.xml} (58%) rename app/code/Magento/Backend/Test/Mftf/ActionGroup/{AdminFilterGridActionGroup.xml => AdminFilterLegacyGridActionGroup.xml} (64%) rename app/code/Magento/Backend/Test/Mftf/ActionGroup/{AdminResetGridFilterActionGroup.xml => AdminResetLegacyGridFilterActionGroup.xml} (82%) delete mode 100644 app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertValueInAdminGridActionGroup.xml delete mode 100644 app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminFillFormCustomVariableActionGroup.xml create mode 100644 app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminFillVariableFormActionGroup.xml create mode 100644 app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminFilterVariableGridActionGroup.xml rename app/code/Magento/Variable/Test/Mftf/ActionGroup/{AdminNavigateToNewVariablePageActionGroup.xml => AdminOpenNewVariablePageActionGroup.xml} (87%) rename app/code/Magento/Variable/Test/Mftf/ActionGroup/{AdminNavigateToVariablesGridPageActionGroup.xml => AdminOpenVariablesGridPageActionGroup.xml} (87%) create mode 100644 app/code/Magento/Variable/Test/Mftf/ActionGroup/AssertAdminCustomVariableFormActionGroup.xml create mode 100644 app/code/Magento/Variable/Test/Mftf/ActionGroup/AssertAdminCustomVariableInGridActionGroup.xml create mode 100644 app/code/Magento/Variable/Test/Mftf/Section/AdminVariableFormSection.xml rename app/code/Magento/Variable/Test/Mftf/Section/{AdminVariablesFilterSection.xml => AdminVariableGridFilterSection.xml} (52%) create mode 100644 app/code/Magento/Variable/Test/Mftf/Test/AdminCreateCustomVariableEntityTest.xml delete mode 100644 app/code/Magento/Variable/Test/Mftf/Test/CreateCustomVariableEntityTest.xml diff --git a/app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminClickMainButtonActionGroup.xml b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminClickFormActionButtonActionGroup.xml similarity index 58% rename from app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminClickMainButtonActionGroup.xml rename to app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminClickFormActionButtonActionGroup.xml index 6eef596957458..186f11e4ea503 100644 --- a/app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminClickMainButtonActionGroup.xml +++ b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminClickFormActionButtonActionGroup.xml @@ -8,12 +8,12 @@ <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="AdminClickMainButtonActionGroup"> + <actionGroup name="AdminClickFormActionButtonActionGroup"> <arguments> - <argument name="button" type="string" /> - </arguments> - <waitForElementVisible selector="{{button}}" stepKey="waitForButton"/> - <click selector="{{button}}" stepKey="clickButton"/> + <argument name="buttonSelector" type="string" /> + </arguments> + <waitForElementVisible selector="{{buttonSelector}}" stepKey="waitForButton"/> + <click selector="{{buttonSelector}}" stepKey="clickButton"/> <waitForPageLoad stepKey="waitForPageLoad"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminFilterGridActionGroup.xml b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminFilterLegacyGridActionGroup.xml similarity index 64% rename from app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminFilterGridActionGroup.xml rename to app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminFilterLegacyGridActionGroup.xml index dea1038159fce..f4af54d2edc45 100644 --- a/app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminFilterGridActionGroup.xml +++ b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminFilterLegacyGridActionGroup.xml @@ -8,13 +8,16 @@ <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="AdminFilterGridActionGroup"> + <actionGroup name="AdminFilterLegacyGridActionGroup"> <arguments> - <argument name="field" type="string"/> + <argument name="fieldSelector" type="string"/> <argument name="value" type="string"/> - <argument name="button" type="string" defaultValue="{{AdminSecondaryGridSection.searchButton}}"/> + <argument name="button" type="string" defaultValue="{{AdminLegacyDataGridFilterSection.apply}}"/> </arguments> + <click selector="{{AdminLegacyDataGridFilterSection.clear}}" stepKey="resetFilters" /> + <waitForPageLoad stepKey="waitForFilterReset" /> <fillField selector="{{field}}" userInput="{{value}}" stepKey="fillFieldInFilter"/> <click selector="{{button}}" stepKey="clickSearchButton"/> + <waitForPageLoad stepKey="waitForFiltersApply" /> </actionGroup> </actionGroups> diff --git a/app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminResetGridFilterActionGroup.xml b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminResetLegacyGridFilterActionGroup.xml similarity index 82% rename from app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminResetGridFilterActionGroup.xml rename to app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminResetLegacyGridFilterActionGroup.xml index 7e22309493be8..8a9ac8991bac4 100644 --- a/app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminResetGridFilterActionGroup.xml +++ b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminResetLegacyGridFilterActionGroup.xml @@ -8,9 +8,9 @@ <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="AdminResetGridFilterActionGroup"> + <actionGroup name="AdminResetLegacyGridFilterActionGroup"> <arguments> - <argument name="selector" type="string" defaultValue="{{AdminSecondaryGridSection.resetFilters}}"/> + <argument name="selector" type="string" defaultValue="{{AdminLegacyDataGridFilterSection.clear}}"/> </arguments> <click selector="{{selector}}" stepKey="clickResetButton"/> </actionGroup> diff --git a/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertValueInAdminGridActionGroup.xml b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertValueInAdminGridActionGroup.xml deleted file mode 100644 index f3eec4446ae72..0000000000000 --- a/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertValueInAdminGridActionGroup.xml +++ /dev/null @@ -1,16 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="AssertValueInAdminGridActionGroup"> - <arguments> - <argument name="value" type="string" /> - </arguments> - <see selector="{{AdminGridTableSection.rowByValue(value)}}" userInput="{{value}}" stepKey="seeValueInGrid"/> - </actionGroup> -</actionGroups> diff --git a/app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminFillFormCustomVariableActionGroup.xml b/app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminFillFormCustomVariableActionGroup.xml deleted file mode 100644 index 4dabe6f0ae192..0000000000000 --- a/app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminFillFormCustomVariableActionGroup.xml +++ /dev/null @@ -1,16 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="AdminFillFormCustomVariableActionGroup"> - <fillField selector="{{CustomVariableSection.variableCode}}" userInput="{{customVariable.code}}" stepKey="fillVariableCode"/> - <fillField selector="{{CustomVariableSection.variableName}}" userInput="{{customVariable.name}}" stepKey="fillVariableName"/> - <fillField selector="{{CustomVariableSection.variableHTML}}" userInput="{{customVariable.html}}" stepKey="fillVariableHtml"/> - <fillField selector="{{CustomVariableSection.variablePlain}}" userInput="{{customVariable.plain}}" stepKey="fillVariablePlain"/> - </actionGroup> -</actionGroups> diff --git a/app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminFillVariableFormActionGroup.xml b/app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminFillVariableFormActionGroup.xml new file mode 100644 index 0000000000000..f9761ede76ada --- /dev/null +++ b/app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminFillVariableFormActionGroup.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminFillVariableFormActionGroup"> + <arguments> + <argument name="variable" /> + </arguments> + <fillField selector="{{AdminVariableFormSection.code}}" userInput="{{variable.code}}" stepKey="fillVariableCode"/> + <fillField selector="{{AdminVariableFormSection.name}}" userInput="{{variable.name}}" stepKey="fillVariableName"/> + <fillField selector="{{AdminVariableFormSection.html}}" userInput="{{variable.html}}" stepKey="fillVariableHtml"/> + <fillField selector="{{AdminVariableFormSection.plain}}" userInput="{{variable.plain}}" stepKey="fillVariablePlain"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminFilterVariableGridActionGroup.xml b/app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminFilterVariableGridActionGroup.xml new file mode 100644 index 0000000000000..a9f1f049081e0 --- /dev/null +++ b/app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminFilterVariableGridActionGroup.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminFilterVariableGridActionGroup"> + <arguments> + <argument name="variable" type="entity"/> + </arguments> + <click selector="{{AdminLegacyDataGridFilterSection.clear}}" stepKey="resetFilters" /> + <waitForPageLoad stepKey="waitForFilterReset" /> + <fillField selector="{{AdminVariableGridFilterSection.codeField}}" userInput="{{variable.code}}" stepKey="fillCodeFieldInFilter"/> + <fillField selector="{{AdminVariableGridFilterSection.nameField}}" userInput="{{variable.name}}" stepKey="fillNameFieldInFilter"/> + <click selector="{{AdminLegacyDataGridFilterSection.apply}}" stepKey="clickSearchButton"/> + <waitForPageLoad stepKey="waitForFiltersApply" /> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminNavigateToVariablePageActionGroup.xml b/app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminNavigateToVariablePageActionGroup.xml index 4904b45a47e48..4241757ada14f 100644 --- a/app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminNavigateToVariablePageActionGroup.xml +++ b/app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminNavigateToVariablePageActionGroup.xml @@ -8,10 +8,11 @@ <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="AdminNavigateToVariablePageActionGroup"> + <actionGroup name="AdminNavigateToVariablePageByCodeActionGroup"> <arguments> <argument name="code" type="string"/> </arguments> - <click selector="{{CustomVariableSection.GridCustomVariableCode(code)}}" stepKey="goToCustomVariableEditPage"/> + <click selector="{{AdminLegacyDataGridTableSection.rowTemplateStrict(code)}}" stepKey="goToCustomVariableEditPage"/> + <waitForPageLoad stepKey="waitForVariableEditPageOpen" /> </actionGroup> </actionGroups> diff --git a/app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminNavigateToNewVariablePageActionGroup.xml b/app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminOpenNewVariablePageActionGroup.xml similarity index 87% rename from app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminNavigateToNewVariablePageActionGroup.xml rename to app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminOpenNewVariablePageActionGroup.xml index 060a2a608b125..24b45926dd6a5 100644 --- a/app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminNavigateToNewVariablePageActionGroup.xml +++ b/app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminOpenNewVariablePageActionGroup.xml @@ -8,7 +8,7 @@ <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="AdminNavigateToNewVariablePageActionGroup"> + <actionGroup name="AdminOpenNewVariablePageActionGroup"> <amOnPage url="{{AdminNewVariablePage.url}}" stepKey="openNewVariablePage"/> <waitForPageLoad stepKey="waitForPageLoad"/> </actionGroup> diff --git a/app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminNavigateToVariablesGridPageActionGroup.xml b/app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminOpenVariablesGridPageActionGroup.xml similarity index 87% rename from app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminNavigateToVariablesGridPageActionGroup.xml rename to app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminOpenVariablesGridPageActionGroup.xml index cc57f6b83d49f..b2b0a155ae67d 100644 --- a/app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminNavigateToVariablesGridPageActionGroup.xml +++ b/app/code/Magento/Variable/Test/Mftf/ActionGroup/AdminOpenVariablesGridPageActionGroup.xml @@ -8,7 +8,7 @@ <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="AdminNavigateToVariablesGridPageActionGroup"> + <actionGroup name="AdminOpenVariablesGridPageActionGroup"> <amOnPage url="{{AdminVariablesPage.url}}" stepKey="openVariablesGridPage"/> <waitForPageLoad stepKey="waitForPageLoad"/> </actionGroup> diff --git a/app/code/Magento/Variable/Test/Mftf/ActionGroup/AssertAdminCustomVariableFormActionGroup.xml b/app/code/Magento/Variable/Test/Mftf/ActionGroup/AssertAdminCustomVariableFormActionGroup.xml new file mode 100644 index 0000000000000..e8372ed7593e5 --- /dev/null +++ b/app/code/Magento/Variable/Test/Mftf/ActionGroup/AssertAdminCustomVariableFormActionGroup.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AssertAdminCustomVariableFormActionGroup"> + <arguments> + <argument name="variable" /> + </arguments> + <seeInField selector="{{AdminVariableFormSection.code}}" userInput="{{variable.code}}" stepKey="seeVariableCode"/> + <seeInField selector="{{AdminVariableFormSection.name}}" userInput="{{variable.name}}" stepKey="seeVariableName"/> + <seeInField selector="{{AdminVariableFormSection.html}}" userInput="{{variable.html}}" stepKey="seeVariableHtml"/> + <seeInField selector="{{AdminVariableFormSection.plain}}" userInput="{{variable.plain}}" stepKey="seeVariablePlain"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Variable/Test/Mftf/ActionGroup/AssertAdminCustomVariableInGridActionGroup.xml b/app/code/Magento/Variable/Test/Mftf/ActionGroup/AssertAdminCustomVariableInGridActionGroup.xml new file mode 100644 index 0000000000000..d68c73f16445a --- /dev/null +++ b/app/code/Magento/Variable/Test/Mftf/ActionGroup/AssertAdminCustomVariableInGridActionGroup.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AssertAdminCustomVariableInGridActionGroup"> + <arguments> + <argument name="variable" /> + </arguments> + <see selector="{{AdminLegacyDataGridTableSection.rowTemplateStrict(variable.code)}}" userInput="{{variable.code}}" stepKey="seeVariableCode" /> + <see selector="{{AdminLegacyDataGridTableSection.rowTemplateStrict(variable.code)}}" userInput="{{variable.name}}" stepKey="seeVariableName" /> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Variable/Test/Mftf/Data/VariableData.xml b/app/code/Magento/Variable/Test/Mftf/Data/VariableData.xml index 1160b79026617..4353059eba4ed 100644 --- a/app/code/Magento/Variable/Test/Mftf/Data/VariableData.xml +++ b/app/code/Magento/Variable/Test/Mftf/Data/VariableData.xml @@ -17,4 +17,10 @@ <data key="html"> Sample Variable </data> <data key="plain">variable-plain-</data> </entity> + <entity name="SampleVariable"> + <data key="code" unique="suffix">variable-code-</data> + <data key="name">Test Sample Variable</data> + <data key="html">Test Sample Variable HTML value</data> + <data key="plain">Test Sample Variable PLAIN value</data> + </entity> </entities> diff --git a/app/code/Magento/Variable/Test/Mftf/Section/AdminVariableFormSection.xml b/app/code/Magento/Variable/Test/Mftf/Section/AdminVariableFormSection.xml new file mode 100644 index 0000000000000..59a87b434cd97 --- /dev/null +++ b/app/code/Magento/Variable/Test/Mftf/Section/AdminVariableFormSection.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="AdminVariableFormSection"> + <element name="code" type="input" selector="#edit_form input[name='variable[code]']"/> + <element name="name" type="input" selector="#edit_form input[name='variable[name]']"/> + <element name="html" type="textarea" selector="#edit_form textarea[name='variable[html_value]']"/> + <element name="plain" type="textarea" selector="#edit_form textarea[name='variable[plain_value]']"/> + <element name="save" type="button" selector=".page-actions-buttons #save"/> + <element name="delete" type="button" selector=".page-actions-buttons #delete"/> + <element name="confirmDelete" type="button" selector=".action-primary.action-accept"/> + </section> +</sections> diff --git a/app/code/Magento/Variable/Test/Mftf/Section/AdminVariablesFilterSection.xml b/app/code/Magento/Variable/Test/Mftf/Section/AdminVariableGridFilterSection.xml similarity index 52% rename from app/code/Magento/Variable/Test/Mftf/Section/AdminVariablesFilterSection.xml rename to app/code/Magento/Variable/Test/Mftf/Section/AdminVariableGridFilterSection.xml index 8c3eb683184dc..93a94e371808e 100644 --- a/app/code/Magento/Variable/Test/Mftf/Section/AdminVariablesFilterSection.xml +++ b/app/code/Magento/Variable/Test/Mftf/Section/AdminVariableGridFilterSection.xml @@ -8,8 +8,8 @@ <sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> - <section name="AdminVariablesFilterSection"> - <element name="codeFilter" type="input" selector="input.admin__control-text[name='code']"/> - <element name="nameFilter" type="input" selector="input.admin__control-text[name='name']"/> + <section name="AdminVariableGridFilterSection"> + <element name="codeField" type="input" selector="[data-role='filter-form'] input.admin__control-text[name='code']"/> + <element name="nameField" type="input" selector="[data-role='filter-form'] input.admin__control-text[name='name']"/> </section> </sections> diff --git a/app/code/Magento/Variable/Test/Mftf/Test/AdminCreateCustomVariableEntityTest.xml b/app/code/Magento/Variable/Test/Mftf/Test/AdminCreateCustomVariableEntityTest.xml new file mode 100644 index 0000000000000..3185640e3783a --- /dev/null +++ b/app/code/Magento/Variable/Test/Mftf/Test/AdminCreateCustomVariableEntityTest.xml @@ -0,0 +1,51 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AdminCreateCustomVariableEntityTest"> + <annotations> + <features value="Variable"/> + <stories value="Create Custom Variable."/> + <title value="Admin Create Custom Variable"/> + <description value="Test for creating a custom variable."/> + <testCaseId value="MC-14253"/> + <severity value="MAJOR"/> + <group value="variable"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + </before> + <after> + <actionGroup ref="logout" stepKey="logout"/> + </after> + <actionGroup ref="AdminOpenNewVariablePageActionGroup" stepKey="goToNewVariableAdminPage"/> + <actionGroup ref="AdminFillVariableFormActionGroup" stepKey="fillInCustomVariableData"> + <argument name="variable" value="SampleVariable" /> + </actionGroup> + <actionGroup ref="AdminClickFormActionButtonActionGroup" stepKey="clickSaveCustomVariable"> + <argument name="buttonSelector" value="{{AdminMainActionsSection.save}}"/> + </actionGroup> + <actionGroup ref="AssertMessageInAdminPanelActionGroup" stepKey="seeSuccessMessage"> + <argument name="message" value="You saved the custom variable."/> + </actionGroup> + <actionGroup ref="AdminFilterVariableGridActionGroup" stepKey="filterVariablesGrid"> + <argument name="variable" value="SampleVariable"/> + </actionGroup> + <actionGroup ref="AssertAdminCustomVariableInGridActionGroup" stepKey="seeNewVariableInGrid"> + <argument name="variable" value="SampleVariable"/> + </actionGroup> + <actionGroup ref="AdminNavigateToVariablePageByCodeActionGroup" stepKey="openVariableEditPage"> + <argument name="code" value="{{SampleVariable.code}}" /> + </actionGroup> + <actionGroup ref="AssertAdminCustomVariableFormActionGroup" stepKey="assertCustomVariableForm"> + <argument name="variable" value="SampleVariable"/> + </actionGroup> + </test> +</tests> diff --git a/app/code/Magento/Variable/Test/Mftf/Test/CreateCustomVariableEntityTest.xml b/app/code/Magento/Variable/Test/Mftf/Test/CreateCustomVariableEntityTest.xml deleted file mode 100644 index ff6e648c59987..0000000000000 --- a/app/code/Magento/Variable/Test/Mftf/Test/CreateCustomVariableEntityTest.xml +++ /dev/null @@ -1,48 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> - -<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> - <test name="CreateCustomVariableEntityTest"> - <annotations> - <features value="Variable"/> - <stories value="Create Custom Variable."/> - <title value="Create Custom Variable."/> - <description value="Test for creating a custom variable."/> - <severity value="MAJOR"/> - <group value="variable"/> - <group value="mtf_migrated"/> - </annotations> - <before> - <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> - </before> - <after> - <actionGroup ref="AdminResetGridFilterActionGroup" stepKey="resetVariablesGrid"/> - <actionGroup ref="logout" stepKey="logout"/> - </after> - <actionGroup ref="AdminNavigateToNewVariablePageActionGroup" stepKey="goToNewVariableAdminPage"/> - <actionGroup ref="AdminFillFormCustomVariableActionGroup" stepKey="fillInCustomVariableData"/> - <actionGroup ref="AdminClickMainButtonActionGroup" stepKey="clickSaveCustomVariable"> - <argument name="button" value="{{AdminMainActionsSection.save}}"/> - </actionGroup> - <actionGroup ref="AssertMessageInAdminPanelActionGroup" stepKey="seeSuccessMessage"> - <argument name="message" value="You saved the custom variable."/> - </actionGroup> - <actionGroup ref="AdminFilterGridActionGroup" stepKey="filterVariablesGridByNewVariableCode" > - <argument name="field" value="{{AdminVariablesFilterSection.codeFilter}}"/> - <argument name="value" value="{{customVariable.code}}"/> - </actionGroup> - <actionGroup ref="AdminFilterGridActionGroup" stepKey="filterVariablesGridByNewVariableName" > - <argument name="field" value="{{AdminVariablesFilterSection.nameFilter}}"/> - <argument name="value" value="{{customVariable.name}}"/> - </actionGroup> - <actionGroup ref="AssertValueInAdminGridActionGroup" stepKey="seeNewVariableInGrid"> - <argument name="value" value="{{customVariable.code}}"/> - </actionGroup> - </test> -</tests> From 7956633a101b2db7e49ed98cb71319209a34339a Mon Sep 17 00:00:00 2001 From: Alex Kolesnyk <kolesnyk@adobe.com> Date: Thu, 25 Jul 2019 15:24:09 -0500 Subject: [PATCH 772/773] Test improvements: - test stabilization --- ...eMainButtonWithConfirmationActionGroup.xml | 18 --------------- .../Mftf/Section/AdminGridTableSection.xml | 1 - ...dSimpleProductToShopingCartActionGroup.xml | 22 +++++++++++++++++++ .../Section/StorefrontMessagesSection.xml | 1 + 4 files changed, 23 insertions(+), 19 deletions(-) delete mode 100644 app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminClickDeleteMainButtonWithConfirmationActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAddSimpleProductToShopingCartActionGroup.xml diff --git a/app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminClickDeleteMainButtonWithConfirmationActionGroup.xml b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminClickDeleteMainButtonWithConfirmationActionGroup.xml deleted file mode 100644 index 17c9c2dea3652..0000000000000 --- a/app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminClickDeleteMainButtonWithConfirmationActionGroup.xml +++ /dev/null @@ -1,18 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> - -<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="AdminClickDeleteMainButtonWithConfirmationActionGroup"> - <waitForElementVisible selector="{{AdminMainActionsSection.delete}}" stepKey="waitForDeleteButton"/> - <click selector="{{AdminMainActionsSection.delete}}" stepKey="clickDeleteButton"/> - <waitForText userInput="Are you sure you want to do this?" stepKey="waitForText"/> - <click selector="{{AdminMainActionsSection.confirmDelete}}" stepKey="confirmDelete"/> - <waitForPageLoad stepKey="waitForPageLoad3"/> - </actionGroup> -</actionGroups> diff --git a/app/code/Magento/Backend/Test/Mftf/Section/AdminGridTableSection.xml b/app/code/Magento/Backend/Test/Mftf/Section/AdminGridTableSection.xml index cc6476547dc80..cc92e530cf3d4 100644 --- a/app/code/Magento/Backend/Test/Mftf/Section/AdminGridTableSection.xml +++ b/app/code/Magento/Backend/Test/Mftf/Section/AdminGridTableSection.xml @@ -10,6 +10,5 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="AdminGridTableSection"> <element name="row" type="text" selector="table.data-grid tbody tr[data-role=row]:nth-of-type({{row}})" parameterized="true"/> - <element name="rowByValue" type="text" selector="//table[@class='data-grid']//tbody//tr[@data-role='row'] //td[contains(., '{{var}}')]" parameterized="true" timeout="30"/> </section> </sections> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAddSimpleProductToShopingCartActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAddSimpleProductToShopingCartActionGroup.xml new file mode 100644 index 0000000000000..14b1331c7ceb1 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontAddSimpleProductToShopingCartActionGroup.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="StorefrontAddSimpleProductToShoppingCartActionGroup"> + <arguments> + <argument name="product"/> + <argument name="qty" type="string" defaultValue="1" /> + </arguments> + <amOnPage url="{{StorefrontProductPage.url(product.custom_attributes[url_key])}}" stepKey="openProductPage" /> + <waitForPageLoad stepKey="waitForProductPageOpen" /> + <fillField userInput="{{qty}}" selector="{{StorefrontProductInfoMainSection.qty}}" stepKey="fillQty" /> + <click selector="{{StorefrontProductInfoMainSection.AddToCart}}" stepKey="clickAddToCart" /> + <waitForElementVisible selector="{{StorefrontMessagesSection.messageByType('success')}}" stepKey="waitForSuccessMessage" /> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Theme/Test/Mftf/Section/StorefrontMessagesSection.xml b/app/code/Magento/Theme/Test/Mftf/Section/StorefrontMessagesSection.xml index a7bc36f1e629b..7f55065fc3186 100644 --- a/app/code/Magento/Theme/Test/Mftf/Section/StorefrontMessagesSection.xml +++ b/app/code/Magento/Theme/Test/Mftf/Section/StorefrontMessagesSection.xml @@ -13,5 +13,6 @@ selector="//main//div[contains(@class, 'messages')]//div[contains(@class, 'message')]/div[contains(text(), '{{var1}}')]" parameterized="true" /> + <element name="messageByType" type="text" selector="[data-ui-id='message-{{messageType}}']" parameterized="true" /> </section> </sections> From 5e345732c27c9e7de467ebdf8155df9931e446ca Mon Sep 17 00:00:00 2001 From: Daniel Renaud <drenaud@magento.com> Date: Fri, 26 Jul 2019 12:17:28 -0500 Subject: [PATCH 773/773] MC-18552: Add api-functional test for querying for all linked categories for product --- .../testsuite/Magento/GraphQl/Catalog/ProductViewTest.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductViewTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductViewTest.php index 62e34fe254703..e11e2e8d108c2 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductViewTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductViewTest.php @@ -997,8 +997,6 @@ public function testProductInAllAnchoredCategories() QUERY; $response = $this->graphQlQuery($query); $this->assertNotEmpty($response['products']['items'][0]['categories'], "Categories must not be empty"); - /** @var ProductRepositoryInterface $productRepository */ - $productRepository = ObjectManager::getInstance()->get(ProductRepositoryInterface::class); /** @var CategoryRepositoryInterface $categoryRepository */ $categoryRepository = ObjectManager::getInstance()->get(CategoryRepositoryInterface::class); $categoryIds = [3, 4, 5];