diff --git a/.php_cs.dist b/.php_cs.dist index 0f254c63283bd..84a5f88bf4355 100644 --- a/.php_cs.dist +++ b/.php_cs.dist @@ -5,9 +5,9 @@ */ /** - * Pre-commit hook installation: - * vendor/bin/static-review.php hook:install dev/tools/Magento/Tools/StaticReview/pre-commit .git/hooks/pre-commit + * PHP Coding Standards fixer configuration */ + $finder = PhpCsFixer\Finder::create() ->name('*.phtml') ->exclude('dev/tests/functional/generated') diff --git a/app/code/Magento/AdminNotification/etc/module.xml b/app/code/Magento/AdminNotification/etc/module.xml index 8a792ee8453ce..607ecbde10a26 100644 --- a/app/code/Magento/AdminNotification/etc/module.xml +++ b/app/code/Magento/AdminNotification/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/AdvancedPricingImportExport/etc/module.xml b/app/code/Magento/AdvancedPricingImportExport/etc/module.xml index ac4b8dafd0183..230fb17ae5544 100644 --- a/app/code/Magento/AdvancedPricingImportExport/etc/module.xml +++ b/app/code/Magento/AdvancedPricingImportExport/etc/module.xml @@ -6,6 +6,6 @@ */ --> - + diff --git a/app/code/Magento/Analytics/Model/Config/Backend/CollectionTime.php b/app/code/Magento/Analytics/Model/Config/Backend/CollectionTime.php index e26ad01fc74bf..524062eec35c6 100644 --- a/app/code/Magento/Analytics/Model/Config/Backend/CollectionTime.php +++ b/app/code/Magento/Analytics/Model/Config/Backend/CollectionTime.php @@ -66,7 +66,9 @@ public function afterSave() $result = preg_match('#(?\d{2}),(?\d{2}),(?\d{2})#', $this->getValue(), $time); if (!$result) { - throw new LocalizedException(__('Time value has an unsupported format')); + throw new LocalizedException( + __('The time value is using an unsupported format. Enter a supported format and try again.') + ); } $cronExprArray = [ diff --git a/app/code/Magento/Analytics/Model/Cryptographer.php b/app/code/Magento/Analytics/Model/Cryptographer.php index 6905eee372ae2..665d564814b14 100644 --- a/app/code/Magento/Analytics/Model/Cryptographer.php +++ b/app/code/Magento/Analytics/Model/Cryptographer.php @@ -56,13 +56,18 @@ public function encode($source) try { $source = (string)$source; } catch (\Exception $e) { - throw new LocalizedException(__('Input data must be string or convertible into string.')); + throw new LocalizedException( + __( + 'The data is invalid. ' + . 'Enter the data as a string or data that can be converted into a string and try again.' + ) + ); } } elseif (!$source) { - throw new LocalizedException(__('Input data must be non-empty string.')); + throw new LocalizedException(__('The data is invalid. Enter the data as a string and try again.')); } if (!$this->validateCipherMethod($this->cipherMethod)) { - throw new LocalizedException(__('Not valid cipher method.')); + throw new LocalizedException(__('The data is invalid. Use a valid cipher method and try again.')); } $initializationVector = $this->getInitializationVector(); @@ -90,7 +95,7 @@ private function getKey() { $token = $this->analyticsToken->getToken(); if (!$token) { - throw new LocalizedException(__('Encryption key can\'t be empty.')); + throw new LocalizedException(__('Enter the encryption key and try again.')); } return hash('sha256', $token); } diff --git a/app/code/Magento/Analytics/Model/ExportDataHandler.php b/app/code/Magento/Analytics/Model/ExportDataHandler.php index b9d3b6340184b..dc17a548763eb 100644 --- a/app/code/Magento/Analytics/Model/ExportDataHandler.php +++ b/app/code/Magento/Analytics/Model/ExportDataHandler.php @@ -195,7 +195,7 @@ private function pack($source, $destination) private function validateSource(WriteInterface $directory, $path) { if (!$directory->isExist($path)) { - throw new LocalizedException(__('Source "%1" is not exist', $directory->getAbsolutePath($path))); + throw new LocalizedException(__('The "%1" source doesn\'t exist.', $directory->getAbsolutePath($path))); } return $directory->getAbsolutePath($path); diff --git a/app/code/Magento/Analytics/Setup/InstallData.php b/app/code/Magento/Analytics/Setup/InstallData.php deleted file mode 100644 index 9832849bacc04..0000000000000 --- a/app/code/Magento/Analytics/Setup/InstallData.php +++ /dev/null @@ -1,52 +0,0 @@ -getConnection()->insertMultiple( - $setup->getTable('core_config_data'), - [ - [ - 'scope' => 'default', - 'scope_id' => 0, - 'path' => 'analytics/subscription/enabled', - 'value' => 1 - ], - [ - 'scope' => 'default', - 'scope_id' => 0, - 'path' => SubscriptionHandler::CRON_STRING_PATH, - 'value' => join(' ', SubscriptionHandler::CRON_EXPR_ARRAY) - ] - ] - ); - - $setup->getConnection()->insert( - $setup->getTable('flag'), - [ - 'flag_code' => SubscriptionHandler::ATTEMPTS_REVERSE_COUNTER_FLAG_CODE, - 'state' => 0, - 'flag_data' => 24, - ] - ); - } -} diff --git a/app/code/Magento/Analytics/Setup/Patch/Data/PrepareInitialConfig.php b/app/code/Magento/Analytics/Setup/Patch/Data/PrepareInitialConfig.php new file mode 100644 index 0000000000000..609dadc511436 --- /dev/null +++ b/app/code/Magento/Analytics/Setup/Patch/Data/PrepareInitialConfig.php @@ -0,0 +1,93 @@ +moduleDataSetup = $moduleDataSetup; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + $this->moduleDataSetup->getConnection()->insertMultiple( + $this->moduleDataSetup->getTable('core_config_data'), + [ + [ + 'scope' => 'default', + 'scope_id' => 0, + 'path' => 'analytics/subscription/enabled', + 'value' => 1 + ], + [ + 'scope' => 'default', + 'scope_id' => 0, + 'path' => SubscriptionHandler::CRON_STRING_PATH, + 'value' => join(' ', SubscriptionHandler::CRON_EXPR_ARRAY) + ] + ] + ); + + $this->moduleDataSetup->getConnection()->insert( + $this->moduleDataSetup->getTable('flag'), + [ + 'flag_code' => SubscriptionHandler::ATTEMPTS_REVERSE_COUNTER_FLAG_CODE, + 'state' => 0, + 'flag_data' => 24, + ] + ); + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return []; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.0'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } +} diff --git a/app/code/Magento/Analytics/etc/module.xml b/app/code/Magento/Analytics/etc/module.xml index 32ee5d23a4d86..24c2fbc81446e 100644 --- a/app/code/Magento/Analytics/etc/module.xml +++ b/app/code/Magento/Analytics/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/Authorization/Model/Acl/AclRetriever.php b/app/code/Magento/Authorization/Model/Acl/AclRetriever.php index f22cbaf46332b..904c8d0ea7794 100644 --- a/app/code/Magento/Authorization/Model/Acl/AclRetriever.php +++ b/app/code/Magento/Authorization/Model/Acl/AclRetriever.php @@ -84,7 +84,7 @@ public function getAllowedResourcesByUser($userType, $userId) $role = $this->_getUserRole($userType, $userId); if (!$role) { throw new AuthorizationException( - __('We can\'t find the role for the user you wanted.') + __("The role wasn't found for the user. Verify the role and try again.") ); } $allowedResources = $this->getAllowedResourcesByRole($role->getId()); diff --git a/app/code/Magento/Authorization/Setup/InstallData.php b/app/code/Magento/Authorization/Setup/Patch/Data/InitializeAuthRoles.php similarity index 59% rename from app/code/Magento/Authorization/Setup/InstallData.php rename to app/code/Magento/Authorization/Setup/Patch/Data/InitializeAuthRoles.php index b8b18706722a5..a63ab272d633b 100644 --- a/app/code/Magento/Authorization/Setup/InstallData.php +++ b/app/code/Magento/Authorization/Setup/Patch/Data/InitializeAuthRoles.php @@ -4,40 +4,48 @@ * See COPYING.txt for license details. */ -namespace Magento\Authorization\Setup; +namespace Magento\Authorization\Setup\Patch\Data; -use Magento\Framework\Setup\InstallDataInterface; -use Magento\Framework\Setup\ModuleContextInterface; +use Magento\Framework\App\ResourceConnection; use Magento\Framework\Setup\ModuleDataSetupInterface; +use Magento\Setup\Model\Patch\DataPatchInterface; +use Magento\Setup\Model\Patch\PatchVersionInterface; use Magento\Authorization\Model\Acl\Role\Group as RoleGroup; use Magento\Authorization\Model\UserContextInterface; /** - * @codeCoverageIgnore + * Class InitializeAuthRoles + * @package Magento\Authorization\Setup\Patch */ -class InstallData implements InstallDataInterface +class InitializeAuthRoles implements DataPatchInterface, PatchVersionInterface { /** - * Authorization factory - * - * @var AuthorizationFactory + * @var ModuleDataSetupInterface + */ + private $moduleDataSetup; + + /** + * @var \Magento\Authorization\Setup\AuthorizationFactory */ private $authFactory; /** - * Init - * - * @param AuthorizationFactory $authFactory + * InitializeAuthRoles constructor. + * @param ModuleDataSetupInterface $moduleDataSetup + * @param \Magento\Authorization\Setup\AuthorizationFactory $authorizationFactory */ - public function __construct(AuthorizationFactory $authFactory) - { - $this->authFactory = $authFactory; + public function __construct( + ModuleDataSetupInterface $moduleDataSetup, + \Magento\Authorization\Setup\AuthorizationFactory $authorizationFactory + ) { + $this->moduleDataSetup = $moduleDataSetup; + $this->authFactory = $authorizationFactory; } /** * {@inheritdoc} */ - public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context) + public function apply() { $roleCollection = $this->authFactory->createRoleCollection() ->addFieldToFilter('parent_id', 0) @@ -60,6 +68,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ] )->save(); } else { + /** @var \Magento\Authorization\Model\ResourceModel\Role $item */ foreach ($roleCollection as $item) { $admGroupRole = $item; break; @@ -89,13 +98,36 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface /** * Delete rows by condition from authorization_rule */ - $setup->startSetup(); - - $tableName = $setup->getTable('authorization_rule'); + $tableName = $this->moduleDataSetup->getTable('authorization_rule'); if ($tableName) { - $setup->getConnection()->delete($tableName, ['resource_id = ?' => 'admin/system/tools/compiler']); + $this->moduleDataSetup->getConnection()->delete( + $tableName, + ['resource_id = ?' => 'admin/system/tools/compiler'] + ); } + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return []; + } - $setup->endSetup(); + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.0'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; } } diff --git a/app/code/Magento/Authorization/Test/Unit/Model/Acl/AclRetrieverTest.php b/app/code/Magento/Authorization/Test/Unit/Model/Acl/AclRetrieverTest.php index bd1a3616a746e..c214cfc832597 100644 --- a/app/code/Magento/Authorization/Test/Unit/Model/Acl/AclRetrieverTest.php +++ b/app/code/Magento/Authorization/Test/Unit/Model/Acl/AclRetrieverTest.php @@ -60,7 +60,7 @@ public function testGetAllowedResourcesByUserTypeCustomer() /** * @expectedException \Magento\Framework\Exception\AuthorizationException - * @expectedExceptionMessage We can't find the role for the user you wanted. + * @expectedExceptionMessage The role wasn't found for the user. Verify the role and try again. */ public function testGetAllowedResourcesByUserRoleNotFound() { diff --git a/app/code/Magento/Authorization/etc/module.xml b/app/code/Magento/Authorization/etc/module.xml index 357e36d937e50..145b1ba10d0f8 100644 --- a/app/code/Magento/Authorization/etc/module.xml +++ b/app/code/Magento/Authorization/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/Authorizenet/Controller/Directpost/Payment/Place.php b/app/code/Magento/Authorizenet/Controller/Directpost/Payment/Place.php index ea73b4b734569..92957481b9290 100644 --- a/app/code/Magento/Authorizenet/Controller/Directpost/Payment/Place.php +++ b/app/code/Magento/Authorizenet/Controller/Directpost/Payment/Place.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Authorizenet\Controller\Directpost\Payment; use Magento\Authorizenet\Controller\Directpost\Payment; @@ -147,7 +148,7 @@ protected function placeCheckoutOrder() $result->setData('error', true); $result->setData( 'error_messages', - __('An error occurred on the server. Please try to place the order again.') + __('A server error stopped your order from being placed. Please try to place your order again.') ); } if ($response instanceof Http) { diff --git a/app/code/Magento/Authorizenet/Model/TransactionService.php b/app/code/Magento/Authorizenet/Model/TransactionService.php index fef22d6c913c0..693a5b890faba 100644 --- a/app/code/Magento/Authorizenet/Model/TransactionService.php +++ b/app/code/Magento/Authorizenet/Model/TransactionService.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Authorizenet\Model; use Magento\Framework\Exception\LocalizedException; @@ -124,7 +125,7 @@ protected function loadTransactionDetails(Authorizenet $context, $transactionId) $responseXmlDocument = new Element($responseBody); libxml_use_internal_errors(false); } catch (\Exception $e) { - throw new LocalizedException(__('Unable to get transaction details. Try again later.')); + throw new LocalizedException(__('The transaction details are unavailable. Please try again later.')); } finally { $context->debugData($debugData); } @@ -132,7 +133,7 @@ protected function loadTransactionDetails(Authorizenet $context, $transactionId) if (!isset($responseXmlDocument->messages->resultCode) || $responseXmlDocument->messages->resultCode != static::PAYMENT_UPDATE_STATUS_CODE_SUCCESS ) { - throw new LocalizedException(__('Unable to get transaction details. Try again later.')); + throw new LocalizedException(__('The transaction details are unavailable. Please try again later.')); } $this->transactionDetails[$transactionId] = $responseXmlDocument; diff --git a/app/code/Magento/Authorizenet/Test/Unit/Controller/Directpost/Payment/PlaceTest.php b/app/code/Magento/Authorizenet/Test/Unit/Controller/Directpost/Payment/PlaceTest.php index 95ceed1ee11e7..c0a50e66759ba 100644 --- a/app/code/Magento/Authorizenet/Test/Unit/Controller/Directpost/Payment/PlaceTest.php +++ b/app/code/Magento/Authorizenet/Test/Unit/Controller/Directpost/Payment/PlaceTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Authorizenet\Test\Unit\Controller\Directpost\Payment; use Magento\Authorizenet\Controller\Directpost\Payment\Place; @@ -297,7 +298,9 @@ public function textExecuteFailedPlaceOrderDataProvider() $objectFailed1 = new \Magento\Framework\DataObject( [ 'error' => true, - 'error_messages' => __('An error occurred on the server. Please try to place the order again.') + 'error_messages' => __( + 'A server error stopped your order from being placed. Please try to place your order again.' + ) ] ); $generalException = new \Exception('Exception logging will save the world!'); diff --git a/app/code/Magento/Authorizenet/etc/module.xml b/app/code/Magento/Authorizenet/etc/module.xml index 6d05f14d21318..a30fd34927746 100644 --- a/app/code/Magento/Authorizenet/etc/module.xml +++ b/app/code/Magento/Authorizenet/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/Backend/Block/Widget/Grid/Massaction/AbstractMassaction.php b/app/code/Magento/Backend/Block/Widget/Grid/Massaction/AbstractMassaction.php index 8252ed1a1e2f8..dfddef6a11f81 100644 --- a/app/code/Magento/Backend/Block/Widget/Grid/Massaction/AbstractMassaction.php +++ b/app/code/Magento/Backend/Block/Widget/Grid/Massaction/AbstractMassaction.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Backend\Block\Widget\Grid\Massaction; use Magento\Backend\Block\Widget\Grid\Massaction\VisibilityCheckerInterface as VisibilityChecker; @@ -57,7 +58,7 @@ protected function _construct() { parent::_construct(); - $this->setErrorText($this->escapeHtml(__('Please select items.'))); + $this->setErrorText($this->escapeHtml(__('An item needs to be selected. Select and try again.'))); if (null !== $this->getOptions()) { foreach ($this->getOptions() as $optionId => $option) { diff --git a/app/code/Magento/Backend/Block/Widget/Grid/Massaction/Extended.php b/app/code/Magento/Backend/Block/Widget/Grid/Massaction/Extended.php index 42f5e61bf5fa8..e90d49847ee36 100644 --- a/app/code/Magento/Backend/Block/Widget/Grid/Massaction/Extended.php +++ b/app/code/Magento/Backend/Block/Widget/Grid/Massaction/Extended.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Backend\Block\Widget\Grid\Massaction; /** @@ -69,7 +70,7 @@ public function __construct( public function _construct() { parent::_construct(); - $this->setErrorText($this->escapeHtml(__('Please select items.'))); + $this->setErrorText($this->escapeHtml(__('An item needs to be selected. Select and try again.'))); } /** diff --git a/app/code/Magento/Backend/Controller/Adminhtml/Cache.php b/app/code/Magento/Backend/Controller/Adminhtml/Cache.php index daaa2a9aaeced..4fcd5993fb504 100644 --- a/app/code/Magento/Backend/Controller/Adminhtml/Cache.php +++ b/app/code/Magento/Backend/Controller/Adminhtml/Cache.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Backend\Controller\Adminhtml; use Magento\Backend\App\Action; @@ -73,7 +74,7 @@ protected function _validateTypes(array $types) $allTypes = array_keys($this->_cacheTypeList->getTypes()); $invalidTypes = array_diff($types, $allTypes); if (count($invalidTypes) > 0) { - throw new LocalizedException(__('Specified cache type(s) don\'t exist: %1', join(', ', $invalidTypes))); + throw new LocalizedException(__('These cache type(s) don\'t exist: %1', join(', ', $invalidTypes))); } } } diff --git a/app/code/Magento/Backend/Model/Auth.php b/app/code/Magento/Backend/Model/Auth.php index 08921d1615f87..02bf64fef07ed 100644 --- a/app/code/Magento/Backend/Model/Auth.php +++ b/app/code/Magento/Backend/Model/Auth.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Backend\Model; use Magento\Framework\Exception\AuthenticationException; @@ -148,7 +149,12 @@ public function getCredentialStorage() public function login($username, $password) { if (empty($username) || empty($password)) { - self::throwException(__('You did not sign in correctly or your account is temporarily disabled.')); + self::throwException( + __( + 'The account sign-in was incorrect or your account is disabled temporarily. ' + . 'Please wait and try again later.' + ) + ); } try { @@ -165,7 +171,12 @@ public function login($username, $password) } if (!$this->getAuthStorage()->getUser()) { - self::throwException(__('You did not sign in correctly or your account is temporarily disabled.')); + self::throwException( + __( + 'The account sign-in was incorrect or your account is disabled temporarily. ' + . 'Please wait and try again later.' + ) + ); } } catch (PluginAuthenticationException $e) { $this->_eventManager->dispatch( @@ -179,7 +190,10 @@ public function login($username, $password) ['user_name' => $username, 'exception' => $e] ); self::throwException( - __($e->getMessage()? : 'You did not sign in correctly or your account is temporarily disabled.') + __( + $e->getMessage()? : 'The account sign-in was incorrect or your account is disabled temporarily. ' + . 'Please wait and try again later.' + ) ); } } @@ -215,7 +229,7 @@ public function isLoggedIn() public static function throwException(Phrase $msg = null) { if ($msg === null) { - $msg = __('Authentication error occurred.'); + $msg = __('An authentication error occurred. Verify and try again.'); } throw new AuthenticationException($msg); } diff --git a/app/code/Magento/Backend/Model/Auth/StorageInterface.php b/app/code/Magento/Backend/Model/Auth/StorageInterface.php index 52b2b089c71e1..e643165a93317 100644 --- a/app/code/Magento/Backend/Model/Auth/StorageInterface.php +++ b/app/code/Magento/Backend/Model/Auth/StorageInterface.php @@ -23,7 +23,7 @@ interface StorageInterface public function processLogin(); /** - * Perform login specific actions + * Perform logout specific actions * * @return $this * @abstract diff --git a/app/code/Magento/Backend/Model/Config/SessionLifetime/BackendModel.php b/app/code/Magento/Backend/Model/Config/SessionLifetime/BackendModel.php index 09f33abd0d44d..c106afb90a09d 100644 --- a/app/code/Magento/Backend/Model/Config/SessionLifetime/BackendModel.php +++ b/app/code/Magento/Backend/Model/Config/SessionLifetime/BackendModel.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Backend\Model\Config\SessionLifetime; use Magento\Framework\App\Config\Value; @@ -26,14 +27,17 @@ class BackendModel extends Value */ public function beforeSave() { - $value = (int) $this->getValue(); + $value = (int)$this->getValue(); if ($value > self::MAX_LIFETIME) { throw new LocalizedException( - __('Admin session lifetime must be less than or equal to 31536000 seconds (one year)') + __( + 'The Admin session lifetime is invalid. ' + . 'Set the lifetime to 31536000 seconds (one year) or shorter and try again.' + ) ); } elseif ($value < self::MIN_LIFETIME) { throw new LocalizedException( - __('Admin session lifetime must be greater than or equal to 60 seconds') + __('The Admin session lifetime is invalid. Set the lifetime to 60 seconds or longer and try again.') ); } return parent::beforeSave(); diff --git a/app/code/Magento/Backend/Test/Unit/Controller/Adminhtml/Cache/MassDisableTest.php b/app/code/Magento/Backend/Test/Unit/Controller/Adminhtml/Cache/MassDisableTest.php index 556db311748bd..197b46acc61bc 100644 --- a/app/code/Magento/Backend/Test/Unit/Controller/Adminhtml/Cache/MassDisableTest.php +++ b/app/code/Magento/Backend/Test/Unit/Controller/Adminhtml/Cache/MassDisableTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Backend\Test\Unit\Controller\Adminhtml\Cache; use PHPUnit_Framework_MockObject_MockObject as MockObject; @@ -156,7 +157,7 @@ public function testExecuteInvalidTypeCache() $this->messageManagerMock->expects($this->once()) ->method('addError') - ->with('Specified cache type(s) don\'t exist: someCache') + ->with('These cache type(s) don\'t exist: someCache') ->willReturnSelf(); $this->assertSame($this->redirectMock, $this->controller->execute()); diff --git a/app/code/Magento/Backend/Test/Unit/Controller/Adminhtml/Cache/MassEnableTest.php b/app/code/Magento/Backend/Test/Unit/Controller/Adminhtml/Cache/MassEnableTest.php index ad622ca69757a..9b3640193154a 100644 --- a/app/code/Magento/Backend/Test/Unit/Controller/Adminhtml/Cache/MassEnableTest.php +++ b/app/code/Magento/Backend/Test/Unit/Controller/Adminhtml/Cache/MassEnableTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Backend\Test\Unit\Controller\Adminhtml\Cache; use PHPUnit_Framework_MockObject_MockObject as MockObject; @@ -156,7 +157,7 @@ public function testExecuteInvalidTypeCache() $this->messageManagerMock->expects($this->once()) ->method('addError') - ->with('Specified cache type(s) don\'t exist: someCache') + ->with('These cache type(s) don\'t exist: someCache') ->willReturnSelf(); $this->assertSame($this->redirectMock, $this->controller->execute()); diff --git a/app/code/Magento/Backend/Test/Unit/Model/AuthTest.php b/app/code/Magento/Backend/Test/Unit/Model/AuthTest.php index 4b79d504dad91..4af060b157ed4 100644 --- a/app/code/Magento/Backend/Test/Unit/Model/AuthTest.php +++ b/app/code/Magento/Backend/Test/Unit/Model/AuthTest.php @@ -54,7 +54,6 @@ protected function setUp() /** * @expectedException \Magento\Framework\Exception\AuthenticationException - * @expectedExceptionMessage You did not sign in correctly or your account is temporarily disabled. */ public function testLoginFailed() { @@ -64,7 +63,10 @@ public function testLoginFailed() ->with(\Magento\Backend\Model\Auth\Credential\StorageInterface::class) ->will($this->returnValue($this->_credentialStorage)); $exceptionMock = new \Magento\Framework\Exception\LocalizedException( - __('You did not sign in correctly or your account is temporarily disabled.') + __( + 'The account sign-in was incorrect or your account is disabled temporarily. ' + . 'Please wait and try again later.' + ) ); $this->_credentialStorage ->expects($this->once()) @@ -74,5 +76,10 @@ public function testLoginFailed() $this->_credentialStorage->expects($this->never())->method('getId'); $this->_eventManagerMock->expects($this->once())->method('dispatch')->with('backend_auth_user_login_failed'); $this->_model->login('username', 'password'); + + $this->expectExceptionMessage( + 'The account sign-in was incorrect or your account is disabled temporarily. ' + . 'Please wait and try again later.' + ); } } diff --git a/app/code/Magento/Backend/Test/Unit/Model/Config/SessionLifetime/BackendModelTest.php b/app/code/Magento/Backend/Test/Unit/Model/Config/SessionLifetime/BackendModelTest.php index 31a13191750a3..92c549c3edfef 100755 --- a/app/code/Magento/Backend/Test/Unit/Model/Config/SessionLifetime/BackendModelTest.php +++ b/app/code/Magento/Backend/Test/Unit/Model/Config/SessionLifetime/BackendModelTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Backend\Test\Unit\Model\Config\SessionLifetime; use Magento\Backend\Model\Config\SessionLifetime\BackendModel; @@ -32,11 +33,12 @@ public function adminSessionLifetimeDataProvider() return [ [ BackendModel::MIN_LIFETIME - 1, - 'Admin session lifetime must be greater than or equal to 60 seconds' + 'The Admin session lifetime is invalid. Set the lifetime to 60 seconds or longer and try again.' ], [ BackendModel::MAX_LIFETIME + 1, - 'Admin session lifetime must be less than or equal to 31536000 seconds (one year)' + 'The Admin session lifetime is invalid. ' + . 'Set the lifetime to 31536000 seconds (one year) or shorter and try again.' ], [ 900 diff --git a/app/code/Magento/Backend/etc/module.xml b/app/code/Magento/Backend/etc/module.xml index 57e00489391f2..6d1691a0e5603 100644 --- a/app/code/Magento/Backend/etc/module.xml +++ b/app/code/Magento/Backend/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/Backup/etc/module.xml b/app/code/Magento/Backup/etc/module.xml index 667ec9d8a7461..3e9906a5ecd74 100644 --- a/app/code/Magento/Backup/etc/module.xml +++ b/app/code/Magento/Backup/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/Braintree/Controller/Paypal/AbstractAction.php b/app/code/Magento/Braintree/Controller/Paypal/AbstractAction.php index d6a81eefc6fdb..e0ed996019576 100644 --- a/app/code/Magento/Braintree/Controller/Paypal/AbstractAction.php +++ b/app/code/Magento/Braintree/Controller/Paypal/AbstractAction.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Braintree\Controller\Paypal; use Magento\Checkout\Model\Session; @@ -73,7 +74,7 @@ public function dispatch(RequestInterface $request) protected function validateQuote($quote) { if (!$quote || !$quote->getItemsCount()) { - throw new \InvalidArgumentException(__('We can\'t initialize checkout.')); + throw new \InvalidArgumentException(__('Checkout failed to initialize. Verify and try again.')); } } } diff --git a/app/code/Magento/Braintree/Controller/Paypal/Review.php b/app/code/Magento/Braintree/Controller/Paypal/Review.php index 4576e3b033df8..ca252aabe54a9 100644 --- a/app/code/Magento/Braintree/Controller/Paypal/Review.php +++ b/app/code/Magento/Braintree/Controller/Paypal/Review.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Braintree\Controller\Paypal; use Magento\Checkout\Model\Session; @@ -66,7 +67,7 @@ public function execute() $quote ); } elseif (!$quote->getPayment()->getAdditionalInformation(self::$paymentMethodNonce)) { - throw new LocalizedException(__('We can\'t initialize checkout.')); + throw new LocalizedException(__('Checkout failed to initialize. Verify and try again.')); } /** @var \Magento\Framework\View\Result\Page $resultPage */ diff --git a/app/code/Magento/Braintree/Gateway/Command/GetPaymentNonceCommand.php b/app/code/Magento/Braintree/Gateway/Command/GetPaymentNonceCommand.php index 91c9f6c14bb5d..13a1762d5cbeb 100644 --- a/app/code/Magento/Braintree/Gateway/Command/GetPaymentNonceCommand.php +++ b/app/code/Magento/Braintree/Gateway/Command/GetPaymentNonceCommand.php @@ -77,7 +77,7 @@ public function execute(array $commandSubject) $customerId = $this->subjectReader->readCustomerId($commandSubject); $paymentToken = $this->tokenManagement->getByPublicHash($publicHash, $customerId); if (!$paymentToken) { - throw new Exception('No available payment tokens'); + throw new Exception('No payment tokens are available.'); } $data = $this->adapter->createNonce($paymentToken->getGatewayToken()); diff --git a/app/code/Magento/Braintree/Model/Paypal/Helper/OrderPlace.php b/app/code/Magento/Braintree/Model/Paypal/Helper/OrderPlace.php index b833798eabf90..6c4332ef22a4c 100644 --- a/app/code/Magento/Braintree/Model/Paypal/Helper/OrderPlace.php +++ b/app/code/Magento/Braintree/Model/Paypal/Helper/OrderPlace.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Braintree\Model\Paypal\Helper; use Magento\Quote\Model\Quote; @@ -71,7 +72,9 @@ public function __construct( public function execute(Quote $quote, array $agreement) { if (!$this->agreementsValidator->isValid($agreement)) { - throw new LocalizedException(__('Please agree to all the terms and conditions before placing the order.')); + throw new LocalizedException(__( + "The order wasn't placed. First, agree to the terms and conditions, then try placing your order again." + )); } if ($this->getCheckoutMethod($quote) === Onepage::METHOD_GUEST) { diff --git a/app/code/Magento/Braintree/Setup/UpgradeData.php b/app/code/Magento/Braintree/Setup/Patch/Data/ConvertSerializedDataToJson.php similarity index 58% rename from app/code/Magento/Braintree/Setup/UpgradeData.php rename to app/code/Magento/Braintree/Setup/Patch/Data/ConvertSerializedDataToJson.php index a7b39f12273e2..da51d29bf7b6f 100644 --- a/app/code/Magento/Braintree/Setup/UpgradeData.php +++ b/app/code/Magento/Braintree/Setup/Patch/Data/ConvertSerializedDataToJson.php @@ -4,14 +4,23 @@ * See COPYING.txt for license details. */ -namespace Magento\Braintree\Setup; +namespace Magento\Braintree\Setup\Patch\Data; -use Magento\Framework\Setup\ModuleContextInterface; +use Magento\Framework\App\ResourceConnection; use Magento\Framework\Setup\ModuleDataSetupInterface; -use Magento\Framework\Setup\UpgradeDataInterface; +use Magento\Setup\Model\Patch\DataPatchInterface; +use Magento\Setup\Model\Patch\PatchVersionInterface; -class UpgradeData implements UpgradeDataInterface +/** + * Convert data fro php native serialized data to JSON. + */ +class ConvertSerializedDataToJson implements DataPatchInterface, PatchVersionInterface { + /** + * @var ModuleDataSetupInterface + */ + private $moduleDataSetup; + /** * @var \Magento\Framework\DB\FieldDataConverterFactory */ @@ -23,41 +32,36 @@ class UpgradeData implements UpgradeDataInterface private $queryModifierFactory; /** - * UpgradeData constructor. - * + * ConvertSerializedDataToJson constructor. + * @param ModuleDataSetupInterface $moduleDataSetup * @param \Magento\Framework\DB\FieldDataConverterFactory $fieldDataConverterFactory * @param \Magento\Framework\DB\Select\QueryModifierFactory $queryModifierFactory */ public function __construct( + ModuleDataSetupInterface $moduleDataSetup, \Magento\Framework\DB\FieldDataConverterFactory $fieldDataConverterFactory, \Magento\Framework\DB\Select\QueryModifierFactory $queryModifierFactory ) { + $this->moduleDataSetup = $moduleDataSetup; $this->fieldDataConverterFactory = $fieldDataConverterFactory; $this->queryModifierFactory = $queryModifierFactory; } /** - * Upgrades data for Braintree module - * - * @param ModuleDataSetupInterface $setup - * @param ModuleContextInterface $context - * @return void + * {@inheritdoc} */ - public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context) + public function apply() { - if (version_compare($context->getVersion(), '2.0.1', '<')) { - $this->convertSerializedDataToJson($setup); - } + $this->convertSerializedDataToJson(); } /** * Upgrade data to version 2.0.1, converts row data in the core_config_data table that uses the path * payment/braintree/countrycreditcard from serialized to JSON * - * @param ModuleDataSetupInterface $setup * @return void */ - private function convertSerializedDataToJson(ModuleDataSetupInterface $setup) + private function convertSerializedDataToJson() { $fieldDataConverter = $this->fieldDataConverterFactory->create( \Magento\Framework\DB\DataConverter\SerializedToJson::class @@ -73,11 +77,35 @@ private function convertSerializedDataToJson(ModuleDataSetupInterface $setup) ); $fieldDataConverter->convert( - $setup->getConnection(), - $setup->getTable('core_config_data'), + $this->moduleDataSetup->getConnection(), + $this->moduleDataSetup->getTable('core_config_data'), 'config_id', 'value', $queryModifier ); } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return []; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.1'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } } diff --git a/app/code/Magento/Braintree/Test/Unit/Controller/Paypal/PlaceOrderTest.php b/app/code/Magento/Braintree/Test/Unit/Controller/Paypal/PlaceOrderTest.php index 5a10b4abb3fbc..4bea03153b93b 100644 --- a/app/code/Magento/Braintree/Test/Unit/Controller/Paypal/PlaceOrderTest.php +++ b/app/code/Magento/Braintree/Test/Unit/Controller/Paypal/PlaceOrderTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Braintree\Test\Unit\Controller\Paypal; use Magento\Braintree\Controller\Paypal\PlaceOrder; @@ -186,7 +187,7 @@ public function testExecuteException() ->method('addExceptionMessage') ->with( self::isInstanceOf('\InvalidArgumentException'), - 'We can\'t initialize checkout.' + 'Checkout failed to initialize. Verify and try again.' ); self::assertEquals($this->placeOrder->execute(), $resultMock); diff --git a/app/code/Magento/Braintree/Test/Unit/Controller/Paypal/ReviewTest.php b/app/code/Magento/Braintree/Test/Unit/Controller/Paypal/ReviewTest.php index cb911a8396b36..609b7f21dbf87 100644 --- a/app/code/Magento/Braintree/Test/Unit/Controller/Paypal/ReviewTest.php +++ b/app/code/Magento/Braintree/Test/Unit/Controller/Paypal/ReviewTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Braintree\Test\Unit\Controller\Paypal; use Magento\Quote\Model\Quote; @@ -188,7 +189,7 @@ public function testExecuteException() ->method('addExceptionMessage') ->with( self::isInstanceOf('\InvalidArgumentException'), - 'We can\'t initialize checkout.' + 'Checkout failed to initialize. Verify and try again.' ); $this->resultFactoryMock->expects(self::once()) @@ -235,7 +236,7 @@ public function testExecuteExceptionPaymentWithoutNonce() ->method('addExceptionMessage') ->with( self::isInstanceOf(\Magento\Framework\Exception\LocalizedException::class), - 'We can\'t initialize checkout.' + 'Checkout failed to initialize. Verify and try again.' ); $this->resultFactoryMock->expects(self::once()) diff --git a/app/code/Magento/Braintree/Test/Unit/Controller/Paypal/SaveShippingMethodTest.php b/app/code/Magento/Braintree/Test/Unit/Controller/Paypal/SaveShippingMethodTest.php index 5be5df0e33c49..32ed698189fa7 100644 --- a/app/code/Magento/Braintree/Test/Unit/Controller/Paypal/SaveShippingMethodTest.php +++ b/app/code/Magento/Braintree/Test/Unit/Controller/Paypal/SaveShippingMethodTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Braintree\Test\Unit\Controller\Paypal; use Magento\Quote\Model\Quote; @@ -225,7 +226,10 @@ public function testExecuteAjaxException() $this->messageManagerMock->expects(self::once()) ->method('addExceptionMessage') - ->with(self::isInstanceOf('\InvalidArgumentException'), 'We can\'t initialize checkout.'); + ->with( + self::isInstanceOf('\InvalidArgumentException'), + 'Checkout failed to initialize. Verify and try again.' + ); $this->urlMock->expects(self::once()) ->method('getUrl') @@ -265,7 +269,10 @@ public function testExecuteException() $this->messageManagerMock->expects(self::once()) ->method('addExceptionMessage') - ->with(self::isInstanceOf('\InvalidArgumentException'), 'We can\'t initialize checkout.'); + ->with( + self::isInstanceOf('\InvalidArgumentException'), + 'Checkout failed to initialize. Verify and try again.' + ); $this->urlMock->expects(self::once()) ->method('getUrl') diff --git a/app/code/Magento/Braintree/Test/Unit/Gateway/Command/GetPaymentNonceCommandTest.php b/app/code/Magento/Braintree/Test/Unit/Gateway/Command/GetPaymentNonceCommandTest.php index 333f29eb29136..6debedf0a0e5f 100644 --- a/app/code/Magento/Braintree/Test/Unit/Gateway/Command/GetPaymentNonceCommandTest.php +++ b/app/code/Magento/Braintree/Test/Unit/Gateway/Command/GetPaymentNonceCommandTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Braintree\Test\Unit\Gateway\Command; use Magento\Braintree\Gateway\Command\GetPaymentNonceCommand; @@ -154,7 +155,7 @@ public function testExecuteWithExceptionForCustomerId() /** * @covers \Magento\Braintree\Gateway\Command\GetPaymentNonceCommand::execute * @expectedException \Exception - * @expectedExceptionMessage No available payment tokens + * @expectedExceptionMessage No payment tokens are available. */ public function testExecuteWithExceptionForTokenManagement() { @@ -169,7 +170,7 @@ public function testExecuteWithExceptionForTokenManagement() ->method('readCustomerId') ->willReturn($customerId); - $exception = new \Exception('No available payment tokens'); + $exception = new \Exception('No payment tokens are available.'); $this->tokenManagement->expects(static::once()) ->method('getByPublicHash') ->willThrowException($exception); diff --git a/app/code/Magento/Braintree/etc/module.xml b/app/code/Magento/Braintree/etc/module.xml index e3415c4935ff6..8be79268e7b58 100644 --- a/app/code/Magento/Braintree/etc/module.xml +++ b/app/code/Magento/Braintree/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/Bundle/Model/LinkManagement.php b/app/code/Magento/Bundle/Model/LinkManagement.php index 1a533f5d24990..8c85c06c7342d 100644 --- a/app/code/Magento/Bundle/Model/LinkManagement.php +++ b/app/code/Magento/Bundle/Model/LinkManagement.php @@ -4,6 +4,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Bundle\Model; use Magento\Catalog\Api\Data\ProductInterface; @@ -87,7 +88,7 @@ public function getChildren($productSku, $optionId = null) { $product = $this->productRepository->get($productSku, true); if ($product->getTypeId() != \Magento\Catalog\Model\Product\Type::TYPE_BUNDLE) { - throw new InputException(__('Only implemented for bundle product')); + throw new InputException(__('This is implemented for bundle products only.')); } $childrenList = []; @@ -125,25 +126,30 @@ public function saveChild( $product = $this->productRepository->get($sku, true); if ($product->getTypeId() != \Magento\Catalog\Model\Product\Type::TYPE_BUNDLE) { throw new InputException( - __('Product with specified sku: "%1" is not a bundle product', [$product->getSku()]) + __('The product with the "%1" SKU isn\'t a bundle product.', [$product->getSku()]) ); } /** @var \Magento\Catalog\Model\Product $linkProductModel */ $linkProductModel = $this->productRepository->get($linkedProduct->getSku()); if ($linkProductModel->isComposite()) { - throw new InputException(__('Bundle product could not contain another composite product')); + throw new InputException(__('The bundle product can\'t contain another composite product.')); } if (!$linkedProduct->getId()) { - throw new InputException(__('Id field of product link is required')); + throw new InputException(__('The product link needs an ID field entered. Enter and try again.')); } /** @var \Magento\Bundle\Model\Selection $selectionModel */ $selectionModel = $this->bundleSelection->create(); $selectionModel->load($linkedProduct->getId()); if (!$selectionModel->getId()) { - throw new InputException(__('Can not find product link with id "%1"', [$linkedProduct->getId()])); + throw new InputException( + __( + 'The product link with the "%1" ID field wasn\'t found. Verify the ID and try again.', + [$linkedProduct->getId()] + ) + ); } $linkField = $this->getMetadataPool()->getMetadata(ProductInterface::class)->getLinkField(); $selectionModel = $this->mapProductLinkToSelectionModel( @@ -218,7 +224,7 @@ public function addChild( ) { if ($product->getTypeId() != \Magento\Catalog\Model\Product\Type::TYPE_BUNDLE) { throw new InputException( - __('Product with specified sku: "%1" is not a bundle product', $product->getSku()) + __('The product with the "%1" SKU isn\'t a bundle product.', $product->getSku()) ); } @@ -246,7 +252,7 @@ public function addChild( /** @var \Magento\Catalog\Model\Product $linkProductModel */ $linkProductModel = $this->productRepository->get($linkedProduct->getSku()); if ($linkProductModel->isComposite()) { - throw new InputException(__('Bundle product could not contain another composite product')); + throw new InputException(__('The bundle product can\'t contain another composite product.')); } if ($selections) { @@ -295,7 +301,7 @@ public function removeChild($sku, $optionId, $childSku) $product = $this->productRepository->get($sku, true); if ($product->getTypeId() != \Magento\Catalog\Model\Product\Type::TYPE_BUNDLE) { - throw new InputException(__('Product with specified sku: %1 is not a bundle product', $sku)); + throw new InputException(__('The product with the "%1" SKU isn\'t a bundle product.', $sku)); } $excludeSelectionIds = []; @@ -314,7 +320,7 @@ public function removeChild($sku, $optionId, $childSku) } if (empty($removeSelectionIds)) { throw new \Magento\Framework\Exception\NoSuchEntityException( - __('Requested bundle option product doesn\'t exist') + __("The bundle product doesn't exist. Review your request and try again.") ); } $linkField = $this->getMetadataPool()->getMetadata(ProductInterface::class)->getLinkField(); diff --git a/app/code/Magento/Bundle/Model/Option/Validator.php b/app/code/Magento/Bundle/Model/Option/Validator.php index 1a82e27114924..3eb574c1751f7 100644 --- a/app/code/Magento/Bundle/Model/Option/Validator.php +++ b/app/code/Magento/Bundle/Model/Option/Validator.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Bundle\Model\Option; use Magento\Framework\Validator\NotEmpty; @@ -51,7 +52,8 @@ protected function validateRequiredFields($value) ]; foreach ($requiredFields as $requiredField => $requiredValue) { if (!$this->notEmpty->isValid(trim($requiredValue))) { - $messages[$requiredField] = __('%fieldName is a required field.', ['fieldName' => $requiredField]); + $messages[$requiredField] = + __('"%fieldName" is required. Enter and try again.', ['fieldName' => $requiredField]); } } $this->_addMessages($messages); diff --git a/app/code/Magento/Bundle/Model/OptionManagement.php b/app/code/Magento/Bundle/Model/OptionManagement.php index dd20487b7f78f..3e8efcc7bbb7b 100644 --- a/app/code/Magento/Bundle/Model/OptionManagement.php +++ b/app/code/Magento/Bundle/Model/OptionManagement.php @@ -4,6 +4,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Bundle\Model; use Magento\Framework\Exception\InputException; @@ -39,7 +40,7 @@ public function save(\Magento\Bundle\Api\Data\OptionInterface $option) { $product = $this->productRepository->get($option->getSku(), true); if ($product->getTypeId() != \Magento\Catalog\Model\Product\Type::TYPE_BUNDLE) { - throw new InputException(__('Only implemented for bundle product')); + throw new InputException(__('This is implemented for bundle products only.')); } return $this->optionRepository->save($product, $option); } diff --git a/app/code/Magento/Bundle/Model/OptionRepository.php b/app/code/Magento/Bundle/Model/OptionRepository.php index 9940344b5b61c..b4b3c84b88ef3 100644 --- a/app/code/Magento/Bundle/Model/OptionRepository.php +++ b/app/code/Magento/Bundle/Model/OptionRepository.php @@ -4,6 +4,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Bundle\Model; use Magento\Catalog\Api\Data\ProductInterface; @@ -112,7 +113,9 @@ public function get($sku, $optionId) /** @var \Magento\Bundle\Model\Option $option */ $option = $this->type->getOptionsCollection($product)->getItemById($optionId); if (!$option || !$option->getId()) { - throw new NoSuchEntityException(__('Requested option doesn\'t exist')); + throw new NoSuchEntityException( + __("The option that was requested doesn't exist. Verify the entity and try again.") + ); } $productLinks = $this->linkList->getItems($product, $optionId); @@ -159,7 +162,7 @@ public function delete(\Magento\Bundle\Api\Data\OptionInterface $option) $this->optionResource->delete($option); } catch (\Exception $exception) { throw new \Magento\Framework\Exception\StateException( - __('Cannot delete option with id %1', $option->getOptionId()), + __('The option with "%1" ID can\'t be deleted.', $option->getOptionId()), $exception ); } @@ -208,7 +211,9 @@ public function save( } } else { if (!$existingOption->getOptionId()) { - throw new NoSuchEntityException(__('Requested option doesn\'t exist')); + throw new NoSuchEntityException( + __("The option that was requested doesn't exist. Verify the entity and try again.") + ); } $option->setData(array_merge($existingOption->getData(), $option->getData())); @@ -218,7 +223,7 @@ public function save( try { $this->optionResource->save($option); } catch (\Exception $e) { - throw new CouldNotSaveException(__('Could not save option'), $e); + throw new CouldNotSaveException(__("The option couldn't be saved."), $e); } /** @var \Magento\Bundle\Api\Data\LinkInterface $linkedProduct */ @@ -282,7 +287,7 @@ private function getProduct($sku) { $product = $this->productRepository->get($sku, true); if ($product->getTypeId() != \Magento\Catalog\Model\Product\Type::TYPE_BUNDLE) { - throw new InputException(__('Only implemented for bundle product')); + throw new InputException(__('This is implemented for bundle products only.')); } return $product; } diff --git a/app/code/Magento/Bundle/Setup/InstallData.php b/app/code/Magento/Bundle/Setup/Patch/Data/ApplyAttributesUpdate.php similarity index 85% rename from app/code/Magento/Bundle/Setup/InstallData.php rename to app/code/Magento/Bundle/Setup/Patch/Data/ApplyAttributesUpdate.php index 6a3ff08c4d781..0e0d4bbc74cf3 100644 --- a/app/code/Magento/Bundle/Setup/InstallData.php +++ b/app/code/Magento/Bundle/Setup/Patch/Data/ApplyAttributesUpdate.php @@ -4,33 +4,42 @@ * See COPYING.txt for license details. */ -namespace Magento\Bundle\Setup; +namespace Magento\Bundle\Setup\Patch\Data; +use Magento\Framework\App\ResourceConnection; +use Magento\Framework\Setup\ModuleDataSetupInterface; +use Magento\Setup\Model\Patch\DataPatchInterface; +use Magento\Setup\Model\Patch\PatchVersionInterface; use Magento\Eav\Setup\EavSetup; use Magento\Eav\Setup\EavSetupFactory; -use Magento\Framework\Setup\InstallDataInterface; -use Magento\Framework\Setup\ModuleContextInterface; -use Magento\Framework\Setup\ModuleDataSetupInterface; /** - * @codeCoverageIgnore + * Class ApplyAttributesUpdate + * @package Magento\Bundle\Setup\Patch */ -class InstallData implements InstallDataInterface +class ApplyAttributesUpdate implements DataPatchInterface, PatchVersionInterface { /** - * EAV setup factory - * + * @var ModuleDataSetupInterface + */ + private $moduleDataSetup; + + /** * @var EavSetupFactory */ private $eavSetupFactory; /** - * Init + * ApplyAttributesUpdate constructor. * + * @param ModuleDataSetupInterface $moduleDataSetup * @param EavSetupFactory $eavSetupFactory */ - public function __construct(EavSetupFactory $eavSetupFactory) - { + public function __construct( + ModuleDataSetupInterface $moduleDataSetup, + \Magento\Eav\Setup\EavSetupFactory $eavSetupFactory + ) { + $this->moduleDataSetup = $moduleDataSetup; $this->eavSetupFactory = $eavSetupFactory; } @@ -38,10 +47,10 @@ public function __construct(EavSetupFactory $eavSetupFactory) * {@inheritdoc} * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ - public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context) + public function apply() { /** @var EavSetup $eavSetup */ - $eavSetup = $this->eavSetupFactory->create(['setup' => $setup]); + $eavSetup = $this->eavSetupFactory->create(['setup' => $this->moduleDataSetup]); $fieldList = [ 'price', 'special_price', @@ -205,4 +214,28 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ] ); } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return []; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.0'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } } diff --git a/app/code/Magento/Bundle/Setup/Patch/Data/UpdateBundleRelatedEntityTytpes.php b/app/code/Magento/Bundle/Setup/Patch/Data/UpdateBundleRelatedEntityTytpes.php new file mode 100644 index 0000000000000..4a66803d53d23 --- /dev/null +++ b/app/code/Magento/Bundle/Setup/Patch/Data/UpdateBundleRelatedEntityTytpes.php @@ -0,0 +1,204 @@ +moduleDataSetup = $moduleDataSetup; + $this->eavSetupFactory = $eavSetupFactory; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + /** @var \Magento\Eav\Setup\EavSetup $eavSetup */ + $eavSetup = $this->eavSetupFactory->create(['setup' => $this->moduleDataSetup]); + + $attributeSetId = $eavSetup->getDefaultAttributeSetId(ProductAttributeInterface::ENTITY_TYPE_CODE); + $eavSetup->addAttributeGroup( + ProductAttributeInterface::ENTITY_TYPE_CODE, + $attributeSetId, + 'Bundle Items', + 16 + ); + $this->upgradePriceType($eavSetup); + $this->upgradeSkuType($eavSetup); + $this->upgradeWeightType($eavSetup); + $this->upgradeShipmentType($eavSetup); + } + + /** + * Upgrade Dynamic Price attribute + * + * @param EavSetup $eavSetup + * @return void + */ + private function upgradePriceType(EavSetup $eavSetup) + { + $eavSetup->updateAttribute( + ProductAttributeInterface::ENTITY_TYPE_CODE, + 'price_type', + 'frontend_input', + 'boolean', + 31 + ); + $eavSetup->updateAttribute( + ProductAttributeInterface::ENTITY_TYPE_CODE, + 'price_type', + 'frontend_label', + 'Dynamic Price' + ); + $eavSetup->updateAttribute(ProductAttributeInterface::ENTITY_TYPE_CODE, 'price_type', 'default_value', 0); + } + + /** + * Upgrade Dynamic Sku attribute + * + * @param EavSetup $eavSetup + * @return void + */ + private function upgradeSkuType(EavSetup $eavSetup) + { + $eavSetup->updateAttribute( + ProductAttributeInterface::ENTITY_TYPE_CODE, + 'sku_type', + 'frontend_input', + 'boolean', + 21 + ); + $eavSetup->updateAttribute( + ProductAttributeInterface::ENTITY_TYPE_CODE, + 'sku_type', + 'frontend_label', + 'Dynamic SKU' + ); + $eavSetup->updateAttribute(ProductAttributeInterface::ENTITY_TYPE_CODE, 'sku_type', 'default_value', 0); + $eavSetup->updateAttribute(ProductAttributeInterface::ENTITY_TYPE_CODE, 'sku_type', 'is_visible', 1); + } + + /** + * Upgrade Dynamic Weight attribute + * + * @param EavSetup $eavSetup + * @return void + */ + private function upgradeWeightType(EavSetup $eavSetup) + { + $eavSetup->updateAttribute( + ProductAttributeInterface::ENTITY_TYPE_CODE, + 'weight_type', + 'frontend_input', + 'boolean', + 71 + ); + $eavSetup->updateAttribute( + ProductAttributeInterface::ENTITY_TYPE_CODE, + 'weight_type', + 'frontend_label', + 'Dynamic Weight' + ); + $eavSetup->updateAttribute(ProductAttributeInterface::ENTITY_TYPE_CODE, 'weight_type', 'default_value', 0); + $eavSetup->updateAttribute(ProductAttributeInterface::ENTITY_TYPE_CODE, 'weight_type', 'is_visible', 1); + } + + /** + * Upgrade Ship Bundle Items attribute + * + * @param EavSetup $eavSetup + * @return void + */ + private function upgradeShipmentType(EavSetup $eavSetup) + { + $attributeSetId = $eavSetup->getDefaultAttributeSetId(ProductAttributeInterface::ENTITY_TYPE_CODE); + $eavSetup->addAttributeToGroup( + ProductAttributeInterface::ENTITY_TYPE_CODE, + $attributeSetId, + 'Bundle Items', + 'shipment_type', + 1 + ); + $eavSetup->updateAttribute( + ProductAttributeInterface::ENTITY_TYPE_CODE, + 'shipment_type', + 'frontend_input', + 'select' + ); + $eavSetup->updateAttribute( + ProductAttributeInterface::ENTITY_TYPE_CODE, + 'shipment_type', + 'frontend_label', + 'Ship Bundle Items' + ); + $eavSetup->updateAttribute( + ProductAttributeInterface::ENTITY_TYPE_CODE, + 'shipment_type', + 'source_model', + \Magento\Bundle\Model\Product\Attribute\Source\Shipment\Type::class + ); + $eavSetup->updateAttribute(ProductAttributeInterface::ENTITY_TYPE_CODE, 'shipment_type', 'default_value', 0); + $eavSetup->updateAttribute(ProductAttributeInterface::ENTITY_TYPE_CODE, 'shipment_type', 'is_visible', 1); + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return [ + ApplyAttributesUpdate::class, + ]; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.2'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } +} diff --git a/app/code/Magento/Bundle/Setup/Patch/Schema/UpdateBundleRelatedSchema.php b/app/code/Magento/Bundle/Setup/Patch/Schema/UpdateBundleRelatedSchema.php new file mode 100644 index 0000000000000..e348b1eb15bf7 --- /dev/null +++ b/app/code/Magento/Bundle/Setup/Patch/Schema/UpdateBundleRelatedSchema.php @@ -0,0 +1,159 @@ +schemaSetup = $schemaSetup; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + $this->schemaSetup->startSetup(); + // Updating data of the 'catalog_product_bundle_option_value' table. + $tableName = $this->schemaSetup->getTable('catalog_product_bundle_option_value'); + + $select = $this->schemaSetup->getConnection()->select() + ->from( + ['values' => $tableName], + ['value_id'] + )->joinLeft( + [ + 'options' => $this->schemaSetup->getTable( + 'catalog_product_bundle_option' + ) + ], + 'values.option_id = options.option_id', + ['parent_product_id' => 'parent_id'] + ); + + $this->schemaSetup->getConnection()->query( + $this->schemaSetup->getConnection()->insertFromSelect( + $select, + $tableName, + ['value_id', 'parent_product_id'], + \Magento\Framework\DB\Adapter\AdapterInterface::INSERT_ON_DUPLICATE + ) + ); + + // Updating data of the 'catalog_product_bundle_selection_price' table. + $tableName = $this->schemaSetup->getTable( + 'catalog_product_bundle_selection_price' + ); + $tmpTableName = $this->schemaSetup->getTable( + 'catalog_product_bundle_selection_price_tmp' + ); + + $existingForeignKeys = $this->schemaSetup->getConnection()->getForeignKeys($tableName); + + foreach ($existingForeignKeys as $key) { + $this->schemaSetup->getConnection()->dropForeignKey($key['TABLE_NAME'], $key['FK_NAME']); + } + + $this->schemaSetup->getConnection()->createTable( + $this->schemaSetup->getConnection()->createTableByDdl($tableName, $tmpTableName) + ); + + foreach ($existingForeignKeys as $key) { + $this->schemaSetup->getConnection()->addForeignKey( + $key['FK_NAME'], + $key['TABLE_NAME'], + $key['COLUMN_NAME'], + $key['REF_TABLE_NAME'], + $key['REF_COLUMN_NAME'], + $key['ON_DELETE'] + ); + } + + $this->schemaSetup->getConnection()->query( + $this->schemaSetup->getConnection()->insertFromSelect( + $this->schemaSetup->getConnection()->select()->from($tableName), + $tmpTableName + ) + ); + + $this->schemaSetup->getConnection()->truncateTable($tableName); + + $columnsToSelect = []; + + foreach ($this->schemaSetup->getConnection()->describeTable($tmpTableName) as $column) { + $alias = $column['COLUMN_NAME'] == 'parent_product_id' ? 'selections.' : 'prices.'; + + $columnsToSelect[] = $alias . $column['COLUMN_NAME']; + } + + $select = $this->schemaSetup->getConnection()->select() + ->from( + ['prices' => $tmpTableName], + [] + )->joinLeft( + [ + 'selections' => $this->schemaSetup->getTable( + 'catalog_product_bundle_selection' + ) + ], + 'prices.selection_id = selections.selection_id', + [] + )->columns($columnsToSelect); + + $this->schemaSetup->getConnection()->query( + $this->schemaSetup->getConnection()->insertFromSelect($select, $tableName) + ); + + $this->schemaSetup->getConnection()->dropTable($tmpTableName); + + $this->schemaSetup->endSetup(); + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return []; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.4'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } +} diff --git a/app/code/Magento/Bundle/Setup/UpgradeData.php b/app/code/Magento/Bundle/Setup/UpgradeData.php deleted file mode 100644 index 750bc79d84801..0000000000000 --- a/app/code/Magento/Bundle/Setup/UpgradeData.php +++ /dev/null @@ -1,255 +0,0 @@ -eavSetupFactory = $eavSetupFactory; - } - - /** - * {@inheritdoc} - * - * @SuppressWarnings(PHPMD.ExcessiveMethodLength) - */ - public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context) - { - $setup->startSetup(); - - if (version_compare($context->getVersion(), '2.0.2', '<')) { - /** @var \Magento\Eav\Setup\EavSetup $eavSetup */ - $eavSetup = $this->eavSetupFactory->create(['setup' => $setup]); - - $attributeSetId = $eavSetup->getDefaultAttributeSetId(ProductAttributeInterface::ENTITY_TYPE_CODE); - $eavSetup->addAttributeGroup( - ProductAttributeInterface::ENTITY_TYPE_CODE, - $attributeSetId, - 'Bundle Items', - 16 - ); - - $this->upgradePriceType($eavSetup); - $this->upgradeSkuType($eavSetup); - $this->upgradeWeightType($eavSetup); - $this->upgradeShipmentType($eavSetup); - } - - if (version_compare($context->getVersion(), '2.0.4', '<')) { - // Updating data of the 'catalog_product_bundle_option_value' table. - $tableName = $setup->getTable('catalog_product_bundle_option_value'); - - $select = $setup->getConnection()->select() - ->from( - ['values' => $tableName], - ['value_id'] - )->joinLeft( - ['options' => $setup->getTable('catalog_product_bundle_option')], - 'values.option_id = options.option_id', - ['parent_product_id' => 'parent_id'] - ); - - $setup->getConnection()->query( - $setup->getConnection()->insertFromSelect( - $select, - $tableName, - ['value_id', 'parent_product_id'], - \Magento\Framework\DB\Adapter\AdapterInterface::INSERT_ON_DUPLICATE - ) - ); - - // Updating data of the 'catalog_product_bundle_selection_price' table. - $tableName = $setup->getTable('catalog_product_bundle_selection_price'); - $tmpTableName = $setup->getTable('catalog_product_bundle_selection_price_tmp'); - - $existingForeignKeys = $setup->getConnection()->getForeignKeys($tableName); - - foreach ($existingForeignKeys as $key) { - $setup->getConnection()->dropForeignKey($key['TABLE_NAME'], $key['FK_NAME']); - } - - $setup->getConnection()->createTable( - $setup->getConnection()->createTableByDdl($tableName, $tmpTableName) - ); - - foreach ($existingForeignKeys as $key) { - $setup->getConnection()->addForeignKey( - $key['FK_NAME'], - $key['TABLE_NAME'], - $key['COLUMN_NAME'], - $key['REF_TABLE_NAME'], - $key['REF_COLUMN_NAME'], - $key['ON_DELETE'] - ); - } - - $setup->getConnection()->query( - $setup->getConnection()->insertFromSelect( - $setup->getConnection()->select()->from($tableName), - $tmpTableName - ) - ); - - $setup->getConnection()->truncateTable($tableName); - - $columnsToSelect = []; - - foreach ($setup->getConnection()->describeTable($tmpTableName) as $column) { - $alias = $column['COLUMN_NAME'] == 'parent_product_id' ? 'selections.' : 'prices.'; - - $columnsToSelect[] = $alias . $column['COLUMN_NAME']; - } - - $select = $setup->getConnection()->select() - ->from( - ['prices' => $tmpTableName], - [] - )->joinLeft( - ['selections' => $setup->getTable('catalog_product_bundle_selection')], - 'prices.selection_id = selections.selection_id', - [] - )->columns($columnsToSelect); - - $setup->getConnection()->query( - $setup->getConnection()->insertFromSelect($select, $tableName) - ); - - $setup->getConnection()->dropTable($tmpTableName); - } - - $setup->endSetup(); - } - - /** - * Upgrade Dynamic Price attribute - * - * @param EavSetup $eavSetup - * @return void - */ - private function upgradePriceType(EavSetup $eavSetup) - { - $eavSetup->updateAttribute( - ProductAttributeInterface::ENTITY_TYPE_CODE, - 'price_type', - 'frontend_input', - 'boolean', - 31 - ); - $eavSetup->updateAttribute( - ProductAttributeInterface::ENTITY_TYPE_CODE, - 'price_type', - 'frontend_label', - 'Dynamic Price' - ); - $eavSetup->updateAttribute(ProductAttributeInterface::ENTITY_TYPE_CODE, 'price_type', 'default_value', 0); - } - - /** - * Upgrade Dynamic Sku attribute - * - * @param EavSetup $eavSetup - * @return void - */ - private function upgradeSkuType(EavSetup $eavSetup) - { - $eavSetup->updateAttribute( - ProductAttributeInterface::ENTITY_TYPE_CODE, - 'sku_type', - 'frontend_input', - 'boolean', - 21 - ); - $eavSetup->updateAttribute( - ProductAttributeInterface::ENTITY_TYPE_CODE, - 'sku_type', - 'frontend_label', - 'Dynamic SKU' - ); - $eavSetup->updateAttribute(ProductAttributeInterface::ENTITY_TYPE_CODE, 'sku_type', 'default_value', 0); - $eavSetup->updateAttribute(ProductAttributeInterface::ENTITY_TYPE_CODE, 'sku_type', 'is_visible', 1); - } - - /** - * Upgrade Dynamic Weight attribute - * - * @param EavSetup $eavSetup - * @return void - */ - private function upgradeWeightType(EavSetup $eavSetup) - { - $eavSetup->updateAttribute( - ProductAttributeInterface::ENTITY_TYPE_CODE, - 'weight_type', - 'frontend_input', - 'boolean', - 71 - ); - $eavSetup->updateAttribute( - ProductAttributeInterface::ENTITY_TYPE_CODE, - 'weight_type', - 'frontend_label', - 'Dynamic Weight' - ); - $eavSetup->updateAttribute(ProductAttributeInterface::ENTITY_TYPE_CODE, 'weight_type', 'default_value', 0); - $eavSetup->updateAttribute(ProductAttributeInterface::ENTITY_TYPE_CODE, 'weight_type', 'is_visible', 1); - } - - /** - * Upgrade Ship Bundle Items attribute - * - * @param EavSetup $eavSetup - * @return void - */ - private function upgradeShipmentType(EavSetup $eavSetup) - { - $attributeSetId = $eavSetup->getDefaultAttributeSetId(ProductAttributeInterface::ENTITY_TYPE_CODE); - $eavSetup->addAttributeToGroup( - ProductAttributeInterface::ENTITY_TYPE_CODE, - $attributeSetId, - 'Bundle Items', - 'shipment_type', - 1 - ); - $eavSetup->updateAttribute( - ProductAttributeInterface::ENTITY_TYPE_CODE, - 'shipment_type', - 'frontend_input', - 'select' - ); - $eavSetup->updateAttribute( - ProductAttributeInterface::ENTITY_TYPE_CODE, - 'shipment_type', - 'frontend_label', - 'Ship Bundle Items' - ); - $eavSetup->updateAttribute( - ProductAttributeInterface::ENTITY_TYPE_CODE, - 'shipment_type', - 'source_model', - \Magento\Bundle\Model\Product\Attribute\Source\Shipment\Type::class - ); - $eavSetup->updateAttribute(ProductAttributeInterface::ENTITY_TYPE_CODE, 'shipment_type', 'default_value', 0); - $eavSetup->updateAttribute(ProductAttributeInterface::ENTITY_TYPE_CODE, 'shipment_type', 'is_visible', 1); - } -} diff --git a/app/code/Magento/Bundle/Test/Unit/Model/LinkManagementTest.php b/app/code/Magento/Bundle/Test/Unit/Model/LinkManagementTest.php index d1292146f6662..ccc8c52d5022f 100644 --- a/app/code/Magento/Bundle/Test/Unit/Model/LinkManagementTest.php +++ b/app/code/Magento/Bundle/Test/Unit/Model/LinkManagementTest.php @@ -339,7 +339,7 @@ public function testAddChildNonExistingOption() /** * @expectedException \Magento\Framework\Exception\InputException - * @expectedExceptionMessage Bundle product could not contain another composite product + * @expectedExceptionMessage The bundle product can't contain another composite product. */ public function testAddChildLinkedProductIsComposite() { @@ -797,7 +797,7 @@ public function testSaveChildWithoutId() /** * @expectedException \Magento\Framework\Exception\InputException - * @expectedExceptionMessage Can not find product link with id "12345" + * @expectedExceptionMessage The product link with the "12345" ID field wasn't found. Verify the ID and try again. */ public function testSaveChildWithInvalidId() { diff --git a/app/code/Magento/Bundle/Test/Unit/Model/Option/ValidatorTest.php b/app/code/Magento/Bundle/Test/Unit/Model/Option/ValidatorTest.php index f47c978190a2c..791126a9c1742 100644 --- a/app/code/Magento/Bundle/Test/Unit/Model/Option/ValidatorTest.php +++ b/app/code/Magento/Bundle/Test/Unit/Model/Option/ValidatorTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Bundle\Test\Unit\Model\Option; use Magento\Framework\Validator\NotEmpty; @@ -71,9 +72,17 @@ public function providerIsValid() { return [ ['title', 'select', true, []], - ['title', null, false, ['type' => 'type is a required field.']], - [null, 'select', false, ['title' => 'title is a required field.']], - [null, null, false, ['type' => 'type is a required field.', 'title' => 'title is a required field.']] + ['title', null, false, ['type' => '"type" is required. Enter and try again.']], + [null, 'select', false, ['title' => '"title" is required. Enter and try again.']], + [ + null, + null, + false, + [ + 'type' => '"type" is required. Enter and try again.', + 'title' => '"title" is required. Enter and try again.' + ] + ] ]; } } diff --git a/app/code/Magento/Bundle/Test/Unit/Model/OptionManagementTest.php b/app/code/Magento/Bundle/Test/Unit/Model/OptionManagementTest.php index f0a69bd4fb28b..8e309e48872c7 100644 --- a/app/code/Magento/Bundle/Test/Unit/Model/OptionManagementTest.php +++ b/app/code/Magento/Bundle/Test/Unit/Model/OptionManagementTest.php @@ -67,7 +67,7 @@ public function testSave() /** * @expectedException \Magento\Framework\Exception\InputException - * @expectedExceptionMessage Only implemented for bundle product + * @expectedExceptionMessage This is implemented for bundle products only. */ public function testSaveWithException() { diff --git a/app/code/Magento/Bundle/Test/Unit/Model/OptionRepositoryTest.php b/app/code/Magento/Bundle/Test/Unit/Model/OptionRepositoryTest.php index d438dc2e9b216..7549d402a57ff 100644 --- a/app/code/Magento/Bundle/Test/Unit/Model/OptionRepositoryTest.php +++ b/app/code/Magento/Bundle/Test/Unit/Model/OptionRepositoryTest.php @@ -116,7 +116,7 @@ protected function setUp() /** * @expectedException \Magento\Framework\Exception\InputException - * @expectedExceptionMessage Only implemented for bundle product + * @expectedExceptionMessage This is implemented for bundle products only. */ public function testGetThrowsExceptionIfProductIsSimple() { @@ -134,7 +134,7 @@ public function testGetThrowsExceptionIfProductIsSimple() /** * @expectedException \Magento\Framework\Exception\NoSuchEntityException - * @expectedExceptionMessage Requested option doesn't exist + * @expectedExceptionMessage The option that was requested doesn't exist. Verify the entity and try again. */ public function testGetThrowsExceptionIfOptionDoesNotExist() { @@ -226,7 +226,7 @@ public function testDelete() /** * @expectedException \Magento\Framework\Exception\StateException - * @expectedExceptionMessage Cannot delete option with id 1 + * @expectedExceptionMessage The option with "1" ID can't be deleted. */ public function testDeleteThrowsExceptionIfCannotDelete() { @@ -382,7 +382,7 @@ public function testSaveNewOption() /** * @expectedException \Magento\Framework\Exception\CouldNotSaveException - * @expectedExceptionMessage Could not save option + * @expectedExceptionMessage The option couldn't be saved. */ public function testSaveCanNotSave() { @@ -456,7 +456,7 @@ public function testGetList() /** * @expectedException \Magento\Framework\Exception\InputException - * @expectedExceptionMessage Only implemented for bundle product + * @expectedExceptionMessage This is implemented for bundle products only. */ public function testGetListException() { diff --git a/app/code/Magento/Bundle/etc/module.xml b/app/code/Magento/Bundle/etc/module.xml index 8027f3c67c927..9e4e2a166a7b8 100644 --- a/app/code/Magento/Bundle/etc/module.xml +++ b/app/code/Magento/Bundle/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/BundleGraphQl/etc/module.xml b/app/code/Magento/BundleGraphQl/etc/module.xml index 34e721bf02e8e..d6c45dd617a1a 100644 --- a/app/code/Magento/BundleGraphQl/etc/module.xml +++ b/app/code/Magento/BundleGraphQl/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/BundleImportExport/etc/module.xml b/app/code/Magento/BundleImportExport/etc/module.xml index e324145cabcca..44b09e4c5fb88 100644 --- a/app/code/Magento/BundleImportExport/etc/module.xml +++ b/app/code/Magento/BundleImportExport/etc/module.xml @@ -6,6 +6,6 @@ */ --> - + diff --git a/app/code/Magento/CacheInvalidate/etc/module.xml b/app/code/Magento/CacheInvalidate/etc/module.xml index dda90ba8b38ab..789b74480b44e 100644 --- a/app/code/Magento/CacheInvalidate/etc/module.xml +++ b/app/code/Magento/CacheInvalidate/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/Captcha/etc/module.xml b/app/code/Magento/Captcha/etc/module.xml index 03ab6dbee3991..36a44a6543066 100644 --- a/app/code/Magento/Captcha/etc/module.xml +++ b/app/code/Magento/Captcha/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/Catalog/Api/Data/CategoryInterface.php b/app/code/Magento/Catalog/Api/Data/CategoryInterface.php index b65cdafbe26f4..b9a23e9d08ec3 100644 --- a/app/code/Magento/Catalog/Api/Data/CategoryInterface.php +++ b/app/code/Magento/Catalog/Api/Data/CategoryInterface.php @@ -14,6 +14,37 @@ */ interface CategoryInterface extends \Magento\Framework\Api\CustomAttributesDataInterface { + /**#@+ + * Constants defined for keys of data array + */ + const KEY_PARENT_ID = 'parent_id'; + const KEY_NAME = 'name'; + const KEY_IS_ACTIVE = 'is_active'; + const KEY_POSITION = 'position'; + const KEY_LEVEL = 'level'; + const KEY_UPDATED_AT = 'updated_at'; + const KEY_CREATED_AT = 'created_at'; + const KEY_PATH = 'path'; + const KEY_AVAILABLE_SORT_BY = 'available_sort_by'; + const KEY_INCLUDE_IN_MENU = 'include_in_menu'; + const KEY_PRODUCT_COUNT = 'product_count'; + const KEY_CHILDREN_DATA = 'children_data'; + + const ATTRIBUTES = [ + 'id', + self::KEY_PARENT_ID, + self::KEY_NAME, + self::KEY_IS_ACTIVE, + self::KEY_POSITION, + self::KEY_LEVEL, + self::KEY_UPDATED_AT, + self::KEY_CREATED_AT, + self::KEY_AVAILABLE_SORT_BY, + self::KEY_INCLUDE_IN_MENU, + self::KEY_CHILDREN_DATA, + ]; + /**#@-*/ + /** * @return int|null */ diff --git a/app/code/Magento/Catalog/Api/Data/ProductInterface.php b/app/code/Magento/Catalog/Api/Data/ProductInterface.php index a79c76fd8e2b6..4968f49fd20dc 100644 --- a/app/code/Magento/Catalog/Api/Data/ProductInterface.php +++ b/app/code/Magento/Catalog/Api/Data/ProductInterface.php @@ -36,6 +36,24 @@ interface ProductInterface extends \Magento\Framework\Api\CustomAttributesDataIn const UPDATED_AT = 'updated_at'; + const MEDIA_GALLERY = 'media_gallery'; + + const TIER_PRICE = 'tier_price'; + + const ATTRIBUTES = [ + self::SKU, + self::NAME, + self::PRICE, + self::WEIGHT, + self::STATUS, + self::VISIBILITY, + self::ATTRIBUTE_SET_ID, + self::TYPE_ID, + self::CREATED_AT, + self::UPDATED_AT, + self::MEDIA_GALLERY, + self::TIER_PRICE, + ]; /**#@-*/ /** diff --git a/app/code/Magento/Catalog/Block/Product/ImageBuilder.php b/app/code/Magento/Catalog/Block/Product/ImageBuilder.php index 04d30270cbb62..b752000f5a19d 100644 --- a/app/code/Magento/Catalog/Block/Product/ImageBuilder.php +++ b/app/code/Magento/Catalog/Block/Product/ImageBuilder.php @@ -6,6 +6,7 @@ namespace Magento\Catalog\Block\Product; use Magento\Catalog\Helper\ImageFactory as HelperFactory; +use Magento\Catalog\Model\Product; use Magento\Catalog\Model\Product\Image\NotLoadInfoImageException; class ImageBuilder @@ -21,7 +22,7 @@ class ImageBuilder protected $helperFactory; /** - * @var \Magento\Catalog\Model\Product + * @var Product */ protected $product; @@ -50,10 +51,10 @@ public function __construct( /** * Set product * - * @param \Magento\Catalog\Model\Product $product + * @param Product $product * @return $this */ - public function setProduct(\Magento\Catalog\Model\Product $product) + public function setProduct(Product $product) { $this->product = $product; return $this; @@ -79,9 +80,7 @@ public function setImageId($imageId) */ public function setAttributes(array $attributes) { - if ($attributes) { - $this->attributes = $attributes; - } + $this->attributes = $attributes; return $this; } diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Category/Save.php b/app/code/Magento/Catalog/Controller/Adminhtml/Category/Save.php index d1ec3be1a8895..bcc7d468fd0f4 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Category/Save.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Category/Save.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Catalog\Controller\Adminhtml\Category; use Magento\Catalog\Api\Data\CategoryAttributeInterface; @@ -126,8 +127,7 @@ public function execute() return $resultRedirect->setPath('catalog/*/', ['_current' => true, 'id' => null]); } - $data['general'] = $this->getRequest()->getPostValue(); - $categoryPostData = $data['general']; + $categoryPostData = $this->getRequest()->getPostValue(); $isNewCategory = !isset($categoryPostData['entity_id']); $categoryPostData = $this->stringToBoolConverting($categoryPostData); @@ -202,7 +202,7 @@ public function execute() if ($error === true) { $attribute = $categoryResource->getAttribute($code)->getFrontend()->getLabel(); throw new \Magento\Framework\Exception\LocalizedException( - __('Attribute "%1" is required.', $attribute) + __('The "%1" attribute is required. Enter and try again.', $attribute) ); } else { throw new \Exception($error); diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/AddAttributeToTemplate.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/AddAttributeToTemplate.php index 174f06c2ea030..bbef1de28e5b6 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/AddAttributeToTemplate.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/AddAttributeToTemplate.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Catalog\Controller\Adminhtml\Product; use Magento\Catalog\Api\AttributeSetRepositoryInterface; @@ -182,7 +183,7 @@ private function getBasicAttributeSearchCriteriaBuilder() $attributeIds = (array)$this->getRequest()->getParam('attributeIds', []); if (empty($attributeIds['selected'])) { - throw new LocalizedException(__('Please, specify attributes')); + throw new LocalizedException(__('Attributes were missing and must be specified.')); } return $this->getSearchCriteriaBuilder() diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Save.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Save.php index 5335837a4d3c4..f0ba9b518fa5e 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Save.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Save.php @@ -139,7 +139,9 @@ public function execute() ->setName($name) ->getAttributeSet(); } catch (AlreadyExistsException $alreadyExists) { - $this->messageManager->addErrorMessage(__('An attribute set named \'%1\' already exists.', $name)); + $this->messageManager->addErrorMessage( + __('A "%1" attribute set name already exists. Create a new name and try again.', $name) + ); $this->_session->setAttributeData($data); return $this->returnResult('catalog/*/edit', ['_current' => true], ['error' => true]); } catch (LocalizedException $e) { diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Validate.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Validate.php index 4dd406a5d14db..8e11a57f96d71 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Validate.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Validate.php @@ -4,6 +4,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Catalog\Controller\Adminhtml\Product\Attribute; use Magento\Framework\DataObject; @@ -91,7 +92,9 @@ public function execute() $attributeSet->setEntityTypeId($this->_entityTypeId)->load($setName, 'attribute_set_name'); if ($attributeSet->getId()) { $setName = $this->_objectManager->get(\Magento\Framework\Escaper::class)->escapeHtml($setName); - $this->messageManager->addError(__('An attribute set named \'%1\' already exists.', $setName)); + $this->messageManager->addError( + __('A "%1" attribute set name already exists. Create a new name and try again.', $setName) + ); $layout = $this->layoutFactory->create(); $layout->initMessages(); diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Save.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Save.php index d34f4bedd80e4..1481687205ddb 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Save.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Save.php @@ -4,6 +4,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Catalog\Controller\Adminhtml\Product; use Magento\Backend\App\Action; @@ -103,7 +104,9 @@ public function execute() $this->productTypeManager->processProduct($product); if (isset($data['product'][$product->getIdFieldName()])) { - throw new \Magento\Framework\Exception\LocalizedException(__('Unable to save product')); + throw new \Magento\Framework\Exception\LocalizedException( + __('The product was unable to be saved. Please try again.') + ); } $originalSku = $product->getSku(); diff --git a/app/code/Magento/Catalog/Model/Category.php b/app/code/Magento/Catalog/Model/Category.php index ff840635e4c70..69340665b2ca1 100644 --- a/app/code/Magento/Catalog/Model/Category.php +++ b/app/code/Magento/Catalog/Model/Category.php @@ -6,8 +6,12 @@ namespace Magento\Catalog\Model; use Magento\Catalog\Api\CategoryRepositoryInterface; +use Magento\Catalog\Api\Data\CategoryInterface; +use Magento\Catalog\Model\Entity\GetCategoryCustomAttributeCodes; use Magento\CatalogUrlRewrite\Model\CategoryUrlRewriteGenerator; +use Magento\Eav\Model\Entity\GetCustomAttributeCodesInterface; use Magento\Framework\Api\AttributeValueFactory; +use Magento\Framework\App\ObjectManager; use Magento\Framework\Convert\ConvertArray; use Magento\Framework\Exception\NoSuchEntityException; use Magento\Framework\Profiler; @@ -69,23 +73,6 @@ class Category extends \Magento\Catalog\Model\AbstractModel implements const CACHE_TAG = 'cat_c'; - /**#@+ - * Constants - */ - const KEY_PARENT_ID = 'parent_id'; - const KEY_NAME = 'name'; - const KEY_IS_ACTIVE = 'is_active'; - const KEY_POSITION = 'position'; - const KEY_LEVEL = 'level'; - const KEY_UPDATED_AT = 'updated_at'; - const KEY_CREATED_AT = 'created_at'; - const KEY_PATH = 'path'; - const KEY_AVAILABLE_SORT_BY = 'available_sort_by'; - const KEY_INCLUDE_IN_MENU = 'include_in_menu'; - const KEY_PRODUCT_COUNT = 'product_count'; - const KEY_CHILDREN_DATA = 'children_data'; - /**#@-*/ - /**#@-*/ protected $_eventPrefix = 'catalog_category'; @@ -142,21 +129,11 @@ class Category extends \Magento\Catalog\Model\AbstractModel implements /** * Attributes are that part of interface * + * @deprecated + * @see CategoryInterface::ATTRIBUTES * @var array */ - protected $interfaceAttributes = [ - 'id', - self::KEY_PARENT_ID, - self::KEY_NAME, - self::KEY_IS_ACTIVE, - self::KEY_POSITION, - self::KEY_LEVEL, - self::KEY_UPDATED_AT, - self::KEY_CREATED_AT, - self::KEY_AVAILABLE_SORT_BY, - self::KEY_INCLUDE_IN_MENU, - self::KEY_CHILDREN_DATA, - ]; + protected $interfaceAttributes = CategoryInterface::ATTRIBUTES; /** * Category tree model @@ -230,6 +207,11 @@ class Category extends \Magento\Catalog\Model\AbstractModel implements */ protected $metadataService; + /** + * @var GetCustomAttributeCodesInterface + */ + private $getCustomAttributeCodes; + /** * @param \Magento\Framework\Model\Context $context * @param \Magento\Framework\Registry $registry @@ -252,6 +234,7 @@ 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 GetCustomAttributeCodesInterface|null $getCustomAttributeCodes * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -275,7 +258,8 @@ public function __construct( CategoryRepositoryInterface $categoryRepository, \Magento\Framework\Model\ResourceModel\AbstractResource $resource = null, \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, - array $data = [] + array $data = [], + GetCustomAttributeCodesInterface $getCustomAttributeCodes = null ) { $this->metadataService = $metadataService; $this->_treeModel = $categoryTreeResource; @@ -290,6 +274,9 @@ public function __construct( $this->urlFinder = $urlFinder; $this->indexerRegistry = $indexerRegistry; $this->categoryRepository = $categoryRepository; + $this->getCustomAttributeCodes = $getCustomAttributeCodes ?? ObjectManager::getInstance()->get( + GetCategoryCustomAttributeCodes::class + ); parent::__construct( $context, $registry, @@ -323,11 +310,7 @@ protected function _construct() */ protected function getCustomAttributesCodes() { - if ($this->customAttributesCodes === null) { - $this->customAttributesCodes = $this->getEavAttributesCodes($this->metadataService); - $this->customAttributesCodes = array_diff($this->customAttributesCodes, $this->interfaceAttributes); - } - return $this->customAttributesCodes; + return $this->getCustomAttributeCodes->execute($this->metadataService); } /** @@ -667,9 +650,22 @@ public function getImageUrl($attributeCode = 'image') $image = $this->getData($attributeCode); if ($image) { if (is_string($image)) { - $url = $this->_storeManager->getStore()->getBaseUrl( + $store = $this->_storeManager->getStore(); + + $isRelativeUrl = substr($image, 0, 1) === '/'; + + $mediaBaseUrl = $store->getBaseUrl( \Magento\Framework\UrlInterface::URL_TYPE_MEDIA - ) . 'catalog/category/' . $image; + ); + + if ($isRelativeUrl) { + $url = $image; + } else { + $url = $mediaBaseUrl + . ltrim(\Magento\Catalog\Model\Category\FileInfo::ENTITY_MEDIA_PATH, '/') + . '/' + . $image; + } } else { throw new \Magento\Framework\Exception\LocalizedException( __('Something went wrong while getting the image url.') diff --git a/app/code/Magento/Catalog/Model/Category/Attribute/Backend/Image.php b/app/code/Magento/Catalog/Model/Category/Attribute/Backend/Image.php index 19587ce56f592..a2dff83173b37 100644 --- a/app/code/Magento/Catalog/Model/Category/Attribute/Backend/Image.php +++ b/app/code/Magento/Catalog/Model/Category/Attribute/Backend/Image.php @@ -5,6 +5,8 @@ */ namespace Magento\Catalog\Model\Category\Attribute\Backend; +use Magento\Framework\App\Filesystem\DirectoryList; + /** * Catalog category image attribute backend model * @@ -95,6 +97,11 @@ public function beforeSave($object) $attributeName = $this->getAttribute()->getName(); $value = $object->getData($attributeName); + if ($this->fileResidesOutsideCategoryDir($value)) { + // use relative path for image attribute so we know it's outside of category dir when we fetch it + $value[0]['name'] = $value[0]['url']; + } + if ($imageName = $this->getUploadedImageName($value)) { $object->setData($this->additionalData . $attributeName, $value); $object->setData($attributeName, $imageName); @@ -131,6 +138,26 @@ private function isTmpFileAvailable($value) return is_array($value) && isset($value[0]['tmp_name']); } + /** + * Check for file path resides outside of category media dir. The URL will be a path including pub/media if true + * + * @param array|null $value + * @return bool + */ + private function fileResidesOutsideCategoryDir($value) + { + if (!is_array($value) || !isset($value[0]['url'])) { + return false; + } + + $fileUrl = ltrim($value[0]['url'], '/'); + $baseMediaDir = $this->_filesystem->getUri(DirectoryList::MEDIA); + + $usingPathRelativeToBase = strpos($fileUrl, $baseMediaDir) === 0; + + return $usingPathRelativeToBase; + } + /** * Save uploaded file and set its name to category * @@ -148,6 +175,7 @@ public function afterSave($object) $this->_logger->critical($e); } } + return $this; } } diff --git a/app/code/Magento/Catalog/Model/Category/Attribute/Backend/Sortby.php b/app/code/Magento/Catalog/Model/Category/Attribute/Backend/Sortby.php index b6653b73aee8d..057933c55e6de 100644 --- a/app/code/Magento/Catalog/Model/Category/Attribute/Backend/Sortby.php +++ b/app/code/Magento/Catalog/Model/Category/Attribute/Backend/Sortby.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Catalog\Model\Category\Attribute\Backend; /** @@ -58,7 +59,7 @@ public function validate($object) if (!$this->getAttribute()->getEntity()->checkAttributeUniqueValue($this->getAttribute(), $object)) { $label = $this->getAttribute()->getFrontend()->getLabel(); throw new \Magento\Framework\Exception\LocalizedException( - __('The value of attribute "%1" must be unique.', $label) + __('The value of the "%1" attribute isn\'t unique. Set a unique value and try again.', $label) ); } } diff --git a/app/code/Magento/Catalog/Model/Category/DataProvider.php b/app/code/Magento/Catalog/Model/Category/DataProvider.php index 803c89a2504fb..a4127c9a97ffd 100644 --- a/app/code/Magento/Catalog/Model/Category/DataProvider.php +++ b/app/code/Magento/Catalog/Model/Category/DataProvider.php @@ -492,12 +492,20 @@ private function convertValues($category, $categoryData) unset($categoryData[$attributeCode]); $fileName = $category->getData($attributeCode); - if ($this->getFileInfo()->isExist($fileName)) { - $stat = $this->getFileInfo()->getStat($fileName); - $mime = $this->getFileInfo()->getMimeType($fileName); + $fileInfo = $this->getFileInfo(); + + if ($fileInfo->isExist($fileName)) { + $stat = $fileInfo->getStat($fileName); + $mime = $fileInfo->getMimeType($fileName); + + $categoryData[$attributeCode][0]['name'] = basename($fileName); + + if ($fileInfo->isBeginsWithMediaDirectoryPath($fileName)) { + $categoryData[$attributeCode][0]['url'] = $fileName; + } else { + $categoryData[$attributeCode][0]['url'] = $category->getImageUrl($attributeCode); + } - $categoryData[$attributeCode][0]['name'] = $fileName; - $categoryData[$attributeCode][0]['url'] = $category->getImageUrl($attributeCode); $categoryData[$attributeCode][0]['size'] = isset($stat) ? $stat['size'] : 0; $categoryData[$attributeCode][0]['type'] = $mime; } diff --git a/app/code/Magento/Catalog/Model/Category/FileInfo.php b/app/code/Magento/Catalog/Model/Category/FileInfo.php index b26036ff9832c..9715bb2b1616e 100644 --- a/app/code/Magento/Catalog/Model/Category/FileInfo.php +++ b/app/code/Magento/Catalog/Model/Category/FileInfo.php @@ -9,6 +9,7 @@ use Magento\Framework\File\Mime; use Magento\Framework\Filesystem; use Magento\Framework\Filesystem\Directory\WriteInterface; +use Magento\Framework\Filesystem\Directory\ReadInterface; /** * Class FileInfo @@ -37,6 +38,11 @@ class FileInfo */ private $mediaDirectory; + /** + * @var ReadInterface + */ + private $baseDirectory; + /** * @param Filesystem $filesystem * @param Mime $mime @@ -62,6 +68,20 @@ private function getMediaDirectory() return $this->mediaDirectory; } + /** + * Get Base Directory read instance + * + * @return ReadInterface + */ + private function getBaseDirectory() + { + if (!isset($this->baseDirectory)) { + $this->baseDirectory = $this->filesystem->getDirectoryRead(DirectoryList::ROOT); + } + + return $this->baseDirectory; + } + /** * Retrieve MIME type of requested file * @@ -70,7 +90,7 @@ private function getMediaDirectory() */ public function getMimeType($fileName) { - $filePath = self::ENTITY_MEDIA_PATH . '/' . ltrim($fileName, '/'); + $filePath = $this->getFilePath($fileName); $absoluteFilePath = $this->getMediaDirectory()->getAbsolutePath($filePath); $result = $this->mime->getMimeType($absoluteFilePath); @@ -85,7 +105,7 @@ public function getMimeType($fileName) */ public function getStat($fileName) { - $filePath = self::ENTITY_MEDIA_PATH . '/' . ltrim($fileName, '/'); + $filePath = $this->getFilePath($fileName); $result = $this->getMediaDirectory()->stat($filePath); return $result; @@ -99,9 +119,65 @@ public function getStat($fileName) */ public function isExist($fileName) { - $filePath = self::ENTITY_MEDIA_PATH . '/' . ltrim($fileName, '/'); + $filePath = $this->getFilePath($fileName); $result = $this->getMediaDirectory()->isExist($filePath); return $result; } + + /** + * Construct and return file subpath based on filename relative to media directory + * + * @param string $fileName + * @return string + */ + private function getFilePath($fileName) + { + $filePath = ltrim($fileName, '/'); + + $mediaDirectoryRelativeSubpath = $this->getMediaDirectoryPathRelativeToBaseDirectoryPath(); + $isFileNameBeginsWithMediaDirectoryPath = $this->isBeginsWithMediaDirectoryPath($fileName); + + // if the file is not using a relative path, it resides in the catalog/category media directory + $fileIsInCategoryMediaDir = !$isFileNameBeginsWithMediaDirectoryPath; + + if ($fileIsInCategoryMediaDir) { + $filePath = self::ENTITY_MEDIA_PATH . '/' . $filePath; + } else { + $filePath = substr($filePath, strlen($mediaDirectoryRelativeSubpath)); + } + + return $filePath; + } + + /** + * Checks for whether $fileName string begins with media directory path + * + * @param string $fileName + * @return bool + */ + public function isBeginsWithMediaDirectoryPath($fileName) + { + $filePath = ltrim($fileName, '/'); + + $mediaDirectoryRelativeSubpath = $this->getMediaDirectoryPathRelativeToBaseDirectoryPath(); + $isFileNameBeginsWithMediaDirectoryPath = strpos($filePath, $mediaDirectoryRelativeSubpath) === 0; + + return $isFileNameBeginsWithMediaDirectoryPath; + } + + /** + * Get media directory subpath relative to base directory path + * + * @return string + */ + private function getMediaDirectoryPathRelativeToBaseDirectoryPath() + { + $baseDirectoryPath = $this->getBaseDirectory()->getAbsolutePath(); + $mediaDirectoryPath = $this->getMediaDirectory()->getAbsolutePath(); + + $mediaDirectoryRelativeSubpath = substr($mediaDirectoryPath, strlen($baseDirectoryPath)); + + return $mediaDirectoryRelativeSubpath; + } } diff --git a/app/code/Magento/Catalog/Model/CategoryLinkRepository.php b/app/code/Magento/Catalog/Model/CategoryLinkRepository.php index 6c3d84d5f5eb4..fb0ea680569a8 100644 --- a/app/code/Magento/Catalog/Model/CategoryLinkRepository.php +++ b/app/code/Magento/Catalog/Model/CategoryLinkRepository.php @@ -78,7 +78,7 @@ public function deleteByIds($categoryId, $sku) $productID = $product->getId(); if (!isset($productPositions[$productID])) { - throw new InputException(__('Category does not contain specified product')); + throw new InputException(__("The category doesn't contain the specified product.")); } $backupPosition = $productPositions[$productID]; unset($productPositions[$productID]); diff --git a/app/code/Magento/Catalog/Model/CategoryRepository.php b/app/code/Magento/Catalog/Model/CategoryRepository.php index 505c729ac1001..8cb11c4306d52 100644 --- a/app/code/Magento/Catalog/Model/CategoryRepository.php +++ b/app/code/Magento/Catalog/Model/CategoryRepository.php @@ -197,7 +197,7 @@ protected function validateCategory(Category $category) if ($error === true) { $attribute = $this->categoryResource->getAttribute($code)->getFrontend()->getLabel(); throw new \Magento\Framework\Exception\LocalizedException( - __('Attribute "%1" is required.', $attribute) + __('The "%1" attribute is required. Enter and try again.', $attribute) ); } else { throw new \Magento\Framework\Exception\LocalizedException(__($error)); diff --git a/app/code/Magento/Catalog/Model/Entity/GetCategoryCustomAttributeCodes.php b/app/code/Magento/Catalog/Model/Entity/GetCategoryCustomAttributeCodes.php new file mode 100644 index 0000000000000..b2b9199cc56b4 --- /dev/null +++ b/app/code/Magento/Catalog/Model/Entity/GetCategoryCustomAttributeCodes.php @@ -0,0 +1,37 @@ +baseCustomAttributeCodes = $baseCustomAttributeCodes; + } + + /** + * @inheritdoc + */ + public function execute(MetadataServiceInterface $metadataService): array + { + $customAttributesCodes = $this->baseCustomAttributeCodes->execute($metadataService); + return array_diff($customAttributesCodes, CategoryInterface::ATTRIBUTES); + } +} diff --git a/app/code/Magento/Catalog/Model/Entity/GetProductCustomAttributeCodes.php b/app/code/Magento/Catalog/Model/Entity/GetProductCustomAttributeCodes.php new file mode 100644 index 0000000000000..23678ffcf48b7 --- /dev/null +++ b/app/code/Magento/Catalog/Model/Entity/GetProductCustomAttributeCodes.php @@ -0,0 +1,37 @@ +baseCustomAttributeCodes = $baseCustomAttributeCodes; + } + + /** + * @inheritdoc + */ + public function execute(MetadataServiceInterface $metadataService): array + { + $customAttributesCodes = $this->baseCustomAttributeCodes->execute($metadataService); + return array_diff($customAttributesCodes, ProductInterface::ATTRIBUTES); + } +} diff --git a/app/code/Magento/Catalog/Model/Layer/Filter/Dynamic/AlgorithmFactory.php b/app/code/Magento/Catalog/Model/Layer/Filter/Dynamic/AlgorithmFactory.php index 6a9c37e06a7e2..b0467c98907da 100644 --- a/app/code/Magento/Catalog/Model/Layer/Filter/Dynamic/AlgorithmFactory.php +++ b/app/code/Magento/Catalog/Model/Layer/Filter/Dynamic/AlgorithmFactory.php @@ -71,7 +71,7 @@ public function create(array $data = []) ); if (!isset($this->algorithms[$calculationType])) { - throw new LocalizedException(__('%1 was not found in algorithms', $calculationType)); + throw new LocalizedException(__("The %1 value wasn't found in the algorithms.", $calculationType)); } $className = $this->algorithms[$calculationType]; diff --git a/app/code/Magento/Catalog/Model/Layer/State.php b/app/code/Magento/Catalog/Model/Layer/State.php index 25f0caddd987b..c404e5539d209 100644 --- a/app/code/Magento/Catalog/Model/Layer/State.php +++ b/app/code/Magento/Catalog/Model/Layer/State.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Catalog\Model\Layer; use Magento\Catalog\Model\Layer\Filter\Item; @@ -42,7 +43,7 @@ public function addFilter($filter) public function setFilters($filters) { if (!is_array($filters)) { - throw new LocalizedException(__('The filters must be an array.')); + throw new LocalizedException(__('The filters are invalid. Set them in an array and try again.')); } $this->setData('filters', $filters); return $this; diff --git a/app/code/Magento/Catalog/Model/Locator/RegistryLocator.php b/app/code/Magento/Catalog/Model/Locator/RegistryLocator.php index 9770c8b39398c..700fd4b0b8997 100644 --- a/app/code/Magento/Catalog/Model/Locator/RegistryLocator.php +++ b/app/code/Magento/Catalog/Model/Locator/RegistryLocator.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Catalog\Model\Locator; use Magento\Catalog\Api\Data\ProductInterface; @@ -52,7 +53,7 @@ public function getProduct() return $this->product = $product; } - throw new NotFoundException(__('Product was not registered')); + throw new NotFoundException(__("The product wasn't registered.")); } /** @@ -69,7 +70,7 @@ public function getStore() return $this->store = $store; } - throw new NotFoundException(__('Store was not registered')); + throw new NotFoundException(__("The store wasn't registered. Verify the store and try again.")); } /** diff --git a/app/code/Magento/Catalog/Model/Product.php b/app/code/Magento/Catalog/Model/Product.php index cb5669a4bb42e..db16c34f123f2 100644 --- a/app/code/Magento/Catalog/Model/Product.php +++ b/app/code/Magento/Catalog/Model/Product.php @@ -9,9 +9,12 @@ use Magento\Catalog\Api\Data\ProductAttributeMediaGalleryEntryInterface; use Magento\Catalog\Api\Data\ProductInterface; use Magento\Catalog\Api\ProductLinkRepositoryInterface; +use Magento\Catalog\Model\Entity\GetProductCustomAttributeCodes; use Magento\Catalog\Model\Product\Attribute\Backend\Media\EntryConverterPool; +use Magento\Eav\Model\Entity\GetCustomAttributeCodesInterface; use Magento\Framework\Api\AttributeValueFactory; use Magento\Framework\App\Filesystem\DirectoryList; +use Magento\Framework\App\ObjectManager; use Magento\Framework\DataObject\IdentityInterface; use Magento\Framework\Pricing\SaleableInterface; @@ -305,22 +308,12 @@ class Product extends \Magento\Catalog\Model\AbstractModel implements /** * List of attributes in ProductInterface + * + * @deprecated + * @see ProductInterface::ATTRIBUTES * @var array */ - protected $interfaceAttributes = [ - ProductInterface::SKU, - ProductInterface::NAME, - ProductInterface::PRICE, - ProductInterface::WEIGHT, - ProductInterface::STATUS, - ProductInterface::VISIBILITY, - ProductInterface::ATTRIBUTE_SET_ID, - ProductInterface::TYPE_ID, - ProductInterface::CREATED_AT, - ProductInterface::UPDATED_AT, - 'media_gallery', - 'tier_price', - ]; + protected $interfaceAttributes = ProductInterface::ATTRIBUTES; /** * @var \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface @@ -346,6 +339,11 @@ class Product extends \Magento\Catalog\Model\AbstractModel implements */ protected $linkTypeProvider; + /** + * @var GetCustomAttributeCodesInterface + */ + private $getCustomAttributeCodes; + /** * Product constructor. * @param \Magento\Framework\Model\Context $context @@ -383,7 +381,7 @@ class Product extends \Magento\Catalog\Model\AbstractModel implements * @param \Magento\Framework\Api\DataObjectHelper $dataObjectHelper * @param \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface $joinProcessor * @param array $data - * + * @param GetCustomAttributeCodesInterface|null $getCustomAttributeCodes * @SuppressWarnings(PHPMD.ExcessiveParameterList) * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ @@ -422,7 +420,8 @@ public function __construct( EntryConverterPool $mediaGalleryEntryConverterPool, \Magento\Framework\Api\DataObjectHelper $dataObjectHelper, \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface $joinProcessor, - array $data = [] + array $data = [], + GetCustomAttributeCodesInterface $getCustomAttributeCodes = null ) { $this->metadataService = $metadataService; $this->_itemOptionFactory = $itemOptionFactory; @@ -451,6 +450,9 @@ public function __construct( $this->mediaGalleryEntryConverterPool = $mediaGalleryEntryConverterPool; $this->dataObjectHelper = $dataObjectHelper; $this->joinProcessor = $joinProcessor; + $this->getCustomAttributeCodes = $getCustomAttributeCodes ?? ObjectManager::getInstance()->get( + GetProductCustomAttributeCodes::class + ); parent::__construct( $context, $registry, @@ -478,11 +480,7 @@ protected function _construct() */ protected function getCustomAttributesCodes() { - if ($this->customAttributesCodes === null) { - $this->customAttributesCodes = $this->getEavAttributesCodes($this->metadataService); - $this->customAttributesCodes = array_diff($this->customAttributesCodes, $this->interfaceAttributes); - } - return $this->customAttributesCodes; + return $this->getCustomAttributeCodes->execute($this->metadataService); } /** diff --git a/app/code/Magento/Catalog/Model/Product/Attribute/Backend/Sku.php b/app/code/Magento/Catalog/Model/Product/Attribute/Backend/Sku.php index a312f00b26bbb..a652d0ef90213 100644 --- a/app/code/Magento/Catalog/Model/Product/Attribute/Backend/Sku.php +++ b/app/code/Magento/Catalog/Model/Product/Attribute/Backend/Sku.php @@ -51,7 +51,7 @@ public function validate($object) $value = $object->getData($attrCode); if ($this->getAttribute()->getIsRequired() && strlen($value) === 0) { throw new \Magento\Framework\Exception\LocalizedException( - __('The value of attribute "%1" must be set', $attrCode) + __('The "%1" attribute value is empty. Set the attribute and try again.', $attrCode) ); } diff --git a/app/code/Magento/Catalog/Model/Product/Attribute/Frontend/Image.php b/app/code/Magento/Catalog/Model/Product/Attribute/Frontend/Image.php index 6173a76eca421..cdd6da7019da5 100644 --- a/app/code/Magento/Catalog/Model/Product/Attribute/Frontend/Image.php +++ b/app/code/Magento/Catalog/Model/Product/Attribute/Frontend/Image.php @@ -9,23 +9,28 @@ * * @author Magento Core Team */ + namespace Magento\Catalog\Model\Product\Attribute\Frontend; -class Image extends \Magento\Eav\Model\Entity\Attribute\Frontend\AbstractFrontend +use Magento\Eav\Model\Entity\Attribute\Frontend\AbstractFrontend; +use Magento\Framework\UrlInterface; +use Magento\Store\Model\StoreManagerInterface; + +class Image extends AbstractFrontend { /** * Store manager * - * @var \Magento\Store\Model\StoreManagerInterface + * @var StoreManagerInterface */ protected $_storeManager; /** * Construct * - * @param \Magento\Store\Model\StoreManagerInterface $storeManager + * @param StoreManagerInterface $storeManager */ - public function __construct(\Magento\Store\Model\StoreManagerInterface $storeManager) + public function __construct(StoreManagerInterface $storeManager) { $this->_storeManager = $storeManager; } @@ -42,9 +47,9 @@ public function getUrl($product) $image = $product->getData($this->getAttribute()->getAttributeCode()); $url = false; if (!empty($image)) { - $url = $this->_storeManager->getStore($product->getStore()) - ->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA) - . 'catalog/product/' . $image; + $url = $this->_storeManager + ->getStore($product->getStore()) + ->getBaseUrl(UrlInterface::URL_TYPE_MEDIA) . 'catalog/product/' . ltrim($image, '/'); } return $url; } diff --git a/app/code/Magento/Catalog/Model/Product/Attribute/SetManagement.php b/app/code/Magento/Catalog/Model/Product/Attribute/SetManagement.php index fb52e83a51c58..19cb71e4231dd 100644 --- a/app/code/Magento/Catalog/Model/Product/Attribute/SetManagement.php +++ b/app/code/Magento/Catalog/Model/Product/Attribute/SetManagement.php @@ -4,6 +4,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Catalog\Model\Product\Attribute; use Magento\Framework\Exception\StateException; @@ -65,12 +66,12 @@ protected function validateSkeletonSet($skeletonId) $productEntityId = $this->eavConfig->getEntityType(\Magento\Catalog\Model\Product::ENTITY)->getId(); if ($skeletonSet->getEntityTypeId() != $productEntityId) { throw new StateException( - __('Can not create attribute set based on non product attribute set.') + __("The attribute set couldn't be created because it's based on a non-product attribute set.") ); } } catch (\Magento\Framework\Exception\NoSuchEntityException $exception) { throw new StateException( - __('Can not create attribute set based on not existing attribute set') + __("The attribute set couldn't be created because it's based on a non-existing attribute set.") ); } } diff --git a/app/code/Magento/Catalog/Model/Product/Gallery/GalleryManagement.php b/app/code/Magento/Catalog/Model/Product/Gallery/GalleryManagement.php index 1b5f96baeaf9f..4d274a071d087 100644 --- a/app/code/Magento/Catalog/Model/Product/Gallery/GalleryManagement.php +++ b/app/code/Magento/Catalog/Model/Product/Gallery/GalleryManagement.php @@ -4,6 +4,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Catalog\Model\Product\Gallery; use Magento\Catalog\Api\Data\ProductAttributeMediaGalleryEntryInterface; @@ -51,7 +52,7 @@ public function create($sku, ProductAttributeMediaGalleryEntryInterface $entry) $entryContent = $entry->getContent(); if (!$this->contentValidator->isValid($entryContent)) { - throw new InputException(__('The image content is not valid.')); + throw new InputException(__('The image content is invalid. Verify the content and try again.')); } $product = $this->productRepository->get($sku); @@ -71,7 +72,7 @@ public function create($sku, ProductAttributeMediaGalleryEntryInterface $entry) } catch (InputException $inputException) { throw $inputException; } catch (\Exception $e) { - throw new StateException(__('Cannot save product.')); + throw new StateException(__("The product can't be saved.")); } foreach ($product->getMediaGalleryEntries() as $entry) { @@ -79,7 +80,7 @@ public function create($sku, ProductAttributeMediaGalleryEntryInterface $entry) return $entry->getId(); } } - throw new StateException(__('Failed to save new media gallery entry.')); + throw new StateException(__('The new media gallery entry failed to save.')); } /** @@ -90,7 +91,9 @@ public function update($sku, ProductAttributeMediaGalleryEntryInterface $entry) $product = $this->productRepository->get($sku); $existingMediaGalleryEntries = $product->getMediaGalleryEntries(); if ($existingMediaGalleryEntries == null) { - throw new NoSuchEntityException(__('There is no image with provided ID.')); + throw new NoSuchEntityException( + __('No image with the provided ID was found. Verify the ID and try again.') + ); } $found = false; foreach ($existingMediaGalleryEntries as $key => $existingEntry) { @@ -107,14 +110,16 @@ public function update($sku, ProductAttributeMediaGalleryEntryInterface $entry) } } if (!$found) { - throw new NoSuchEntityException(__('There is no image with provided ID.')); + throw new NoSuchEntityException( + __('No image with the provided ID was found. Verify the ID and try again.') + ); } $product->setMediaGalleryEntries($existingMediaGalleryEntries); try { $this->productRepository->save($product); } catch (\Exception $exception) { - throw new StateException(__('Cannot save product.')); + throw new StateException(__("The product can't be saved.")); } return true; } @@ -127,7 +132,9 @@ public function remove($sku, $entryId) $product = $this->productRepository->get($sku); $existingMediaGalleryEntries = $product->getMediaGalleryEntries(); if ($existingMediaGalleryEntries == null) { - throw new NoSuchEntityException(__('There is no image with provided ID.')); + throw new NoSuchEntityException( + __('No image with the provided ID was found. Verify the ID and try again.') + ); } $found = false; foreach ($existingMediaGalleryEntries as $key => $entry) { @@ -138,7 +145,9 @@ public function remove($sku, $entryId) } } if (!$found) { - throw new NoSuchEntityException(__('There is no image with provided ID.')); + throw new NoSuchEntityException( + __('No image with the provided ID was found. Verify the ID and try again.') + ); } $product->setMediaGalleryEntries($existingMediaGalleryEntries); $this->productRepository->save($product); @@ -153,7 +162,7 @@ public function get($sku, $entryId) try { $product = $this->productRepository->get($sku); } catch (\Exception $exception) { - throw new NoSuchEntityException(__('Such product doesn\'t exist')); + throw new NoSuchEntityException(__("The product doesn't exist. Verify and try again.")); } $mediaGalleryEntries = $product->getMediaGalleryEntries(); @@ -163,7 +172,7 @@ public function get($sku, $entryId) } } - throw new NoSuchEntityException(__('Such image doesn\'t exist')); + throw new NoSuchEntityException(__("The image doesn't exist. Verify and try again.")); } /** diff --git a/app/code/Magento/Catalog/Model/Product/Gallery/Processor.php b/app/code/Magento/Catalog/Model/Product/Gallery/Processor.php index 73d0f1fa6795b..c6c7fbda7e9ec 100644 --- a/app/code/Magento/Catalog/Model/Product/Gallery/Processor.php +++ b/app/code/Magento/Catalog/Model/Product/Gallery/Processor.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Catalog\Model\Product\Gallery; use Magento\Framework\App\Filesystem\DirectoryList; @@ -108,7 +109,9 @@ public function validate($object) if ($this->getAttribute()->getIsUnique()) { if (!$this->getAttribute()->getEntity()->checkAttributeUniqueValue($this->getAttribute(), $object)) { $label = $this->getAttribute()->getFrontend()->getLabel(); - throw new LocalizedException(__('The value of attribute "%1" must be unique.', $label)); + throw new LocalizedException( + __('The value of the "%1" attribute isn\'t unique. Set a unique value and try again.', $label) + ); } } @@ -139,13 +142,15 @@ public function addImage( ) { $file = $this->mediaDirectory->getRelativePath($file); if (!$this->mediaDirectory->isFile($file)) { - throw new LocalizedException(__('The image does not exist.')); + throw new LocalizedException(__("The image doesn't exist.")); } $pathinfo = pathinfo($file); $imgExtensions = ['jpg', 'jpeg', 'gif', 'png']; if (!isset($pathinfo['extension']) || !in_array(strtolower($pathinfo['extension']), $imgExtensions)) { - throw new LocalizedException(__('Please correct the image file type.')); + throw new LocalizedException( + __('The image type for the file is invalid. Enter the correct image type and try again.') + ); } $fileName = \Magento\MediaStorage\Model\File\Uploader::getCorrectFileName($pathinfo['basename']); @@ -170,7 +175,7 @@ public function addImage( $storageHelper->saveFile($this->mediaConfig->getTmpMediaShortUrl($fileName)); } } catch (\Exception $e) { - throw new LocalizedException(__('We couldn\'t move this file: %1.', $e->getMessage())); + throw new LocalizedException(__('The "%1" file couldn\'t be moved.', $e->getMessage())); } $fileName = str_replace('\\', '/', $fileName); diff --git a/app/code/Magento/Catalog/Model/Product/Option/Repository.php b/app/code/Magento/Catalog/Model/Product/Option/Repository.php index c2d7781b37ad8..9dc9695daffd1 100644 --- a/app/code/Magento/Catalog/Model/Product/Option/Repository.php +++ b/app/code/Magento/Catalog/Model/Product/Option/Repository.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Catalog\Model\Product\Option; use Magento\Catalog\Api\Data\ProductInterface; @@ -147,7 +148,7 @@ public function save(\Magento\Catalog\Api\Data\ProductCustomOptionInterface $opt { $productSku = $option->getProductSku(); if (!$productSku) { - throw new CouldNotSaveException(__('ProductSku should be specified')); + throw new CouldNotSaveException(__('The ProductSku is empty. Set the ProductSku and try again.')); } /** @var \Magento\Catalog\Model\Product $product */ $product = $this->productRepository->get($productSku); @@ -200,7 +201,7 @@ public function deleteByIdentifier($sku, $optionId) $this->productRepository->save($product); } } catch (\Exception $e) { - throw new CouldNotSaveException(__('Could not remove custom option')); + throw new CouldNotSaveException(__("The custom option couldn't be removed.")); } return true; } diff --git a/app/code/Magento/Catalog/Model/Product/Option/Type/Date.php b/app/code/Magento/Catalog/Model/Product/Option/Type/Date.php index cb6e76aebaadb..7517459da650f 100644 --- a/app/code/Magento/Catalog/Model/Product/Option/Type/Date.php +++ b/app/code/Magento/Catalog/Model/Product/Option/Type/Date.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Catalog\Model\Product\Option\Type; use Magento\Catalog\Api\Data\ProductCustomOptionInterface; @@ -122,7 +123,10 @@ public function validateUserValue($values) ); } else { throw new \Magento\Framework\Exception\LocalizedException( - __('Please specify product\'s required option(s).') + __( + "The product's required option(s) weren't entered. " + . "Make sure the options are entered and try again." + ) ); } } else { diff --git a/app/code/Magento/Catalog/Model/Product/Option/Type/DefaultType.php b/app/code/Magento/Catalog/Model/Product/Option/Type/DefaultType.php index 6b1b42b305bf9..51480e849d9f3 100644 --- a/app/code/Magento/Catalog/Model/Product/Option/Type/DefaultType.php +++ b/app/code/Magento/Catalog/Model/Product/Option/Type/DefaultType.php @@ -212,7 +212,9 @@ public function validateUserValue($values) $option = $this->getOption(); if (!isset($values[$option->getId()]) && $option->getIsRequire() && !$this->getSkipCheckRequiredOption()) { - throw new LocalizedException(__('Please specify product\'s required option(s).')); + throw new LocalizedException( + __("The product's required option(s) weren't entered. Make sure the options are entered and try again.") + ); } elseif (isset($values[$option->getId()])) { $this->setUserValue($values[$option->getId()]); $this->setIsValid(true); diff --git a/app/code/Magento/Catalog/Model/Product/Option/Type/File.php b/app/code/Magento/Catalog/Model/Product/Option/Type/File.php index a7304c9b67bb2..aecb8525915d7 100644 --- a/app/code/Magento/Catalog/Model/Product/Option/Type/File.php +++ b/app/code/Magento/Catalog/Model/Product/Option/Type/File.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Catalog\Model\Product\Option\Type; use Magento\Framework\App\Filesystem\DirectoryList; @@ -255,7 +256,12 @@ public function validateUserValue($values) } catch (ProductException $e) { switch ($this->getProcessMode()) { case \Magento\Catalog\Model\Product\Type\AbstractType::PROCESS_MODE_FULL: - throw new LocalizedException(__('Please specify product\'s required option(s).')); + throw new LocalizedException( + __( + "The product's required option(s) weren't entered. " + . "Make sure the options are entered and try again." + ) + ); break; default: $this->setUserValue(null); @@ -367,7 +373,7 @@ protected function _getOptionHtml($optionValue) $sizes ); } catch (\Exception $e) { - throw new LocalizedException(__('The file options format is not valid.')); + throw new LocalizedException(__('The file options format is invalid. Use a correct format and try again.')); } } diff --git a/app/code/Magento/Catalog/Model/Product/Option/Type/File/Validator.php b/app/code/Magento/Catalog/Model/Product/Option/Type/File/Validator.php index 2c4b76d637d53..860010c3db08c 100644 --- a/app/code/Magento/Catalog/Model/Product/Option/Type/File/Validator.php +++ b/app/code/Magento/Catalog/Model/Product/Option/Type/File/Validator.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Catalog\Model\Product\Option\Type\File; use Magento\Framework\App\Filesystem\DirectoryList; @@ -102,7 +103,7 @@ protected function getValidatorErrors($errors, $fileInfo, $option) break; case \Zend_Validate_File_ImageSize::NOT_DETECTED: $result[] = __( - "The file '%1' is empty. Please choose another one", + 'The file "%1" is empty. Select another file and try again.', $fileInfo['title'] ); break; diff --git a/app/code/Magento/Catalog/Model/Product/Option/Type/File/ValidatorFile.php b/app/code/Magento/Catalog/Model/Product/Option/Type/File/ValidatorFile.php index b54c66d75a058..d6a5cb1cbc29d 100644 --- a/app/code/Magento/Catalog/Model/Product/Option/Type/File/ValidatorFile.php +++ b/app/code/Magento/Catalog/Model/Product/Option/Type/File/ValidatorFile.php @@ -115,7 +115,10 @@ public function validate($processingParams, $option) $runValidation = $option->getIsRequire() || $upload->isUploaded($file); if (!$runValidation) { throw new \Magento\Framework\Validator\Exception( - __('Validation failed. Required options were not filled or the file was not uploaded.') + __( + 'The validation failed. ' + . 'Make sure the required options are entered and the file is uploaded, then try again.' + ) ); } @@ -128,10 +131,14 @@ public function validate($processingParams, $option) if ($this->validateContentLength()) { $value = $this->fileSize->getMaxFileSizeInMb(); throw new LocalizedException( - __('The file you uploaded is larger than %1 Megabytes allowed by server', $value) + __( + "The file was too big and couldn't be uploaded. " + . "Use a file smaller than %1 MBs and try to upload again.", + $value + ) ); } else { - throw new ProductException(__('Option required.')); + throw new ProductException(__("The required option wasn't entered. Enter the option and try again.")); } } @@ -182,7 +189,7 @@ public function validate($processingParams, $option) $imageSize = getimagesize($fileInfo['tmp_name']); } } else { - throw new LocalizedException(__('The file is empty. Please choose another one')); + throw new LocalizedException(__('The file is empty. Select another file and try again.')); } if (!empty($imageSize)) { @@ -209,7 +216,9 @@ public function validate($processingParams, $option) throw new LocalizedException(__(implode("\n", $errors))); } } else { - throw new LocalizedException(__('Please specify product\'s required option(s).')); + throw new LocalizedException( + __("The product's required option(s) weren't entered. Make sure the options are entered and try again.") + ); } return $userValue; } diff --git a/app/code/Magento/Catalog/Model/Product/Option/Type/File/ValidatorInfo.php b/app/code/Magento/Catalog/Model/Product/Option/Type/File/ValidatorInfo.php index 30c3de932c3e6..37e4c7b310a81 100644 --- a/app/code/Magento/Catalog/Model/Product/Option/Type/File/ValidatorInfo.php +++ b/app/code/Magento/Catalog/Model/Product/Option/Type/File/ValidatorInfo.php @@ -102,7 +102,7 @@ public function validate($optionValue, $option) } } else { throw new \Magento\Framework\Exception\LocalizedException( - __('Please specify product\'s required option(s).') + __("The product's required option(s) weren't entered. Make sure the options are entered and try again.") ); } return $result; diff --git a/app/code/Magento/Catalog/Model/Product/Option/Type/Select.php b/app/code/Magento/Catalog/Model/Product/Option/Type/Select.php index 78cce7bd76163..08e1a3e327d2f 100644 --- a/app/code/Magento/Catalog/Model/Product/Option/Type/Select.php +++ b/app/code/Magento/Catalog/Model/Product/Option/Type/Select.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Catalog\Model\Product\Option\Type; use Magento\Framework\Exception\LocalizedException; @@ -64,13 +65,20 @@ public function validateUserValue($values) if (empty($value) && $option->getIsRequire() && !$this->getSkipCheckRequiredOption()) { $this->setIsValid(false); - throw new LocalizedException(__('Please specify product\'s required option(s).')); + throw new LocalizedException( + __("The product's required option(s) weren't entered. Make sure the options are entered and try again.") + ); } if (!$this->_isSingleSelection()) { $valuesCollection = $option->getOptionValuesByOptionId($value, $this->getProduct()->getStoreId())->load(); if ($valuesCollection->count() != count($value)) { $this->setIsValid(false); - throw new LocalizedException(__('Please specify product\'s required option(s).')); + throw new LocalizedException( + __( + "The product's required option(s) weren't entered. " + . "Make sure the options are entered and try again." + ) + ); } } return $this; diff --git a/app/code/Magento/Catalog/Model/Product/Option/Type/Text.php b/app/code/Magento/Catalog/Model/Product/Option/Type/Text.php index 79ee37c51671d..fd0eae188fea9 100644 --- a/app/code/Magento/Catalog/Model/Product/Option/Type/Text.php +++ b/app/code/Magento/Catalog/Model/Product/Option/Type/Text.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Catalog\Model\Product\Option\Type; use Magento\Framework\Exception\LocalizedException; @@ -60,14 +61,16 @@ public function validateUserValue($values) // Check requires option to have some value if (strlen($value) == 0 && $option->getIsRequire() && !$this->getSkipCheckRequiredOption()) { $this->setIsValid(false); - throw new LocalizedException(__('Please specify product\'s required option(s).')); + throw new LocalizedException( + __("The product's required option(s) weren't entered. Make sure the options are entered and try again.") + ); } // Check maximal length limit $maxCharacters = $option->getMaxCharacters(); if ($maxCharacters > 0 && $this->string->strlen($value) > $maxCharacters) { $this->setIsValid(false); - throw new LocalizedException(__('The text is too long.')); + throw new LocalizedException(__('The text is too long. Shorten the text and try again.')); } $this->setUserValue($value); diff --git a/app/code/Magento/Catalog/Model/Product/Price/SpecialPriceStorage.php b/app/code/Magento/Catalog/Model/Product/Price/SpecialPriceStorage.php index 8f1e64e1b7a3a..83a2d1340794c 100644 --- a/app/code/Magento/Catalog/Model/Product/Price/SpecialPriceStorage.php +++ b/app/code/Magento/Catalog/Model/Product/Price/SpecialPriceStorage.php @@ -143,7 +143,7 @@ private function retrieveValidPrices(array $prices) $this->validationResult->addFailedItem( $key, __( - 'Requested product doesn\'t exist. ' + 'The product that was requested doesn\'t exist. Verify the product and try again. ' . 'Row ID: SKU = %SKU, Store ID: %storeId, Price From: %priceFrom, Price To: %priceTo.', [ 'SKU' => $price->getSku(), diff --git a/app/code/Magento/Catalog/Model/Product/PriceModifier.php b/app/code/Magento/Catalog/Model/Product/PriceModifier.php index 4d81000501cff..48d53b4614527 100644 --- a/app/code/Magento/Catalog/Model/Product/PriceModifier.php +++ b/app/code/Magento/Catalog/Model/Product/PriceModifier.php @@ -40,7 +40,7 @@ public function removeTierPrice(\Magento\Catalog\Model\Product $product, $custom $prices = $product->getData('tier_price'); // verify if price exist if ($prices === null) { - throw new NoSuchEntityException(__('This product doesn\'t have tier price')); + throw new NoSuchEntityException(__('Tier price is unavailable for this product.')); } $tierPricesQty = count($prices); @@ -69,7 +69,7 @@ public function removeTierPrice(\Magento\Catalog\Model\Product $product, $custom try { $this->productRepository->save($product); } catch (\Exception $exception) { - throw new CouldNotSaveException(__('Invalid data provided for tier_price')); + throw new CouldNotSaveException(__('The tier_price data is invalid. Verify the data and try again.')); } } } diff --git a/app/code/Magento/Catalog/Model/Product/ScopedTierPriceManagement.php b/app/code/Magento/Catalog/Model/Product/ScopedTierPriceManagement.php index 9e2a79c05fee1..ca5b8038b327d 100644 --- a/app/code/Magento/Catalog/Model/Product/ScopedTierPriceManagement.php +++ b/app/code/Magento/Catalog/Model/Product/ScopedTierPriceManagement.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Catalog\Model\Product; use Magento\Catalog\Api\Data\ProductTierPriceInterface; @@ -69,7 +70,7 @@ public function add($sku, ProductTierPriceInterface $tierPrice) try { $this->productRepository->save($product); } catch (\Exception $e) { - throw new \Magento\Framework\Exception\CouldNotSaveException(__('Could not save group price')); + throw new \Magento\Framework\Exception\CouldNotSaveException(__("The group price couldn't be saved.")); } return true; } @@ -126,7 +127,9 @@ private function validate(ProductTierPriceInterface $tierPrice) $data = ['qty' => $tierPrice->getQty(), 'price' => $tierPrice->getValue()]; foreach ($data as $value) { if (!is_float($value) || $value <= 0) { - throw new \Magento\Framework\Exception\InputException(__('Please provide valid data')); + throw new \Magento\Framework\Exception\InputException( + __('The data was invalid. Verify the data and try again.') + ); } } } diff --git a/app/code/Magento/Catalog/Model/Product/TierPriceManagement.php b/app/code/Magento/Catalog/Model/Product/TierPriceManagement.php index 7cecd2f37bb84..822959bfc8519 100644 --- a/app/code/Magento/Catalog/Model/Product/TierPriceManagement.php +++ b/app/code/Magento/Catalog/Model/Product/TierPriceManagement.php @@ -89,7 +89,7 @@ public function __construct( public function add($sku, $customerGroupId, $price, $qty) { if (!\Zend_Validate::is($price, 'Float') || $price <= 0 || !\Zend_Validate::is($qty, 'Float') || $qty <= 0) { - throw new InputException(__('Please provide valid data')); + throw new InputException(__('The data was invalid. Verify the data and try again.')); } $product = $this->productRepository->get($sku, ['edit_mode' => true]); $tierPrices = $product->getData('tier_price'); @@ -132,7 +132,7 @@ public function add($sku, $customerGroupId, $price, $qty) if (is_array($errors) && count($errors)) { $errorAttributeCodes = implode(', ', array_keys($errors)); throw new InputException( - __('Values of following attributes are invalid: %1', $errorAttributeCodes) + __('Values in the %1 attributes are invalid. Verify the values and try again.', $errorAttributeCodes) ); } try { @@ -142,7 +142,7 @@ public function add($sku, $customerGroupId, $price, $qty) // temporary state exception must be already localized throw $e; } - throw new CouldNotSaveException(__('Could not save group price')); + throw new CouldNotSaveException(__("The group price couldn't be saved.")); } return true; } diff --git a/app/code/Magento/Catalog/Model/Product/Type/AbstractType.php b/app/code/Magento/Catalog/Model/Product/Type/AbstractType.php index 33ff3ecccd4dd..0ab1fbab471e6 100644 --- a/app/code/Magento/Catalog/Model/Product/Type/AbstractType.php +++ b/app/code/Magento/Catalog/Model/Product/Type/AbstractType.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Catalog\Model\Product\Type; use Magento\Catalog\Api\ProductRepositoryInterface; @@ -506,7 +507,7 @@ public function processFileQueue() $rootDir->create($rootDir->getRelativePath($path)); } catch (\Magento\Framework\Exception\FileSystemException $e) { throw new \Magento\Framework\Exception\LocalizedException( - __('We can\'t create writeable directory "%1".', $path) + __('We can\'t create the "%1" writeable directory.', $path) ); } @@ -519,7 +520,9 @@ public function processFileQueue() if (isset($queueOptions['option'])) { $queueOptions['option']->setIsValid(false); } - throw new \Magento\Framework\Exception\LocalizedException(__('The file upload failed.')); + throw new \Magento\Framework\Exception\LocalizedException( + __('The file upload failed. Try to upload again.') + ); } $this->_fileStorageDb->saveFile($dst); break; @@ -535,7 +538,7 @@ public function processFileQueue() /** * Add file to File Queue - * @param array $queueOptions Array of File Queue + * @param array $queueOptions Array of File Queue * (eg. ['operation'=>'move', * 'src_name'=>'filename', * 'dst_name'=>'filename2']) @@ -564,7 +567,7 @@ protected function _isStrictProcessMode($processMode) */ public function getSpecifyOptionMessage() { - return __('Please specify product\'s required option(s).'); + return __("The product's required option(s) weren't entered. Make sure the options are entered and try again."); } /** @@ -635,7 +638,7 @@ public function checkProductBuyState($product) if (!$customOption || strlen($customOption->getValue()) == 0) { $product->setSkipCheckRequiredOption(true); throw new \Magento\Framework\Exception\LocalizedException( - __('The product has required options.') + __('The product has required options. Enter the options and try again.') ); } } @@ -974,7 +977,7 @@ public function setConfig($config) } if (isset($config['can_use_qty_decimals'])) { - $this->_canUseQtyDecimals = (bool) $config['can_use_qty_decimals']; + $this->_canUseQtyDecimals = (bool)$config['can_use_qty_decimals']; } return $this; diff --git a/app/code/Magento/Catalog/Model/ProductAttributeGroupRepository.php b/app/code/Magento/Catalog/Model/ProductAttributeGroupRepository.php index ad1ea248916fb..f43ff45b93efa 100644 --- a/app/code/Magento/Catalog/Model/ProductAttributeGroupRepository.php +++ b/app/code/Magento/Catalog/Model/ProductAttributeGroupRepository.php @@ -4,6 +4,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Catalog\Model; use Magento\Framework\Exception\NoSuchEntityException; @@ -66,7 +67,9 @@ public function get($groupId) $group = $this->groupFactory->create(); $this->groupResource->load($group, $groupId); if (!$group->getId()) { - throw new NoSuchEntityException(__('Group with id "%1" does not exist.', $groupId)); + throw new NoSuchEntityException( + __('The group with the "%1" ID doesn\'t exist. Verify the ID and try again.', $groupId) + ); } return $group; } @@ -90,7 +93,7 @@ public function delete(\Magento\Eav\Api\Data\AttributeGroupInterface $group) /** @var \Magento\Catalog\Model\Product\Attribute\Group $group */ if ($group->hasSystemAttributes()) { throw new StateException( - __('Attribute group that contains system attributes can not be deleted') + __("The attribute group can't be deleted because it contains system attributes.") ); } return $this->groupRepository->delete($group); diff --git a/app/code/Magento/Catalog/Model/ProductLink/CollectionProvider.php b/app/code/Magento/Catalog/Model/ProductLink/CollectionProvider.php index b635d854c9e2b..bc212adae2c32 100644 --- a/app/code/Magento/Catalog/Model/ProductLink/CollectionProvider.php +++ b/app/code/Magento/Catalog/Model/ProductLink/CollectionProvider.php @@ -42,7 +42,7 @@ public function __construct(ConverterPool $converterPool, array $providers = []) public function getCollection(\Magento\Catalog\Model\Product $product, $type) { if (!isset($this->providers[$type])) { - throw new NoSuchEntityException(__('Collection provider is not registered')); + throw new NoSuchEntityException(__("The collection provider isn't registered.")); } $products = $this->providers[$type]->getLinkedProducts($product); diff --git a/app/code/Magento/Catalog/Model/ProductLink/Management.php b/app/code/Magento/Catalog/Model/ProductLink/Management.php index 18950b74eca65..066549274b07c 100644 --- a/app/code/Magento/Catalog/Model/ProductLink/Management.php +++ b/app/code/Magento/Catalog/Model/ProductLink/Management.php @@ -45,7 +45,9 @@ public function getLinkedItemsByType($sku, $type) $linkTypes = $this->linkTypeProvider->getLinkTypes(); if (!isset($linkTypes[$type])) { - throw new NoSuchEntityException(__('Unknown link type: %1', (string)$type)); + throw new NoSuchEntityException( + __('The "%1" link type is unknown. Verify the type and try again.', (string)$type) + ); } $product = $this->productRepository->get($sku); $links = $product->getProductLinks(); @@ -76,7 +78,7 @@ public function setProductLinks($sku, array $items) } if (!isset($linkTypes[$type])) { throw new NoSuchEntityException( - __('Provided link type "%1" does not exist', $type) + __('The "%1" link type wasn\'t found. Verify the type and try again.', $type) ); } } @@ -101,7 +103,7 @@ public function setProductLinks($sku, array $items) try { $this->productRepository->save($product); } catch (\Exception $exception) { - throw new CouldNotSaveException(__('Invalid data provided for linked products')); + throw new CouldNotSaveException(__('The linked products data is invalid. Verify the data and try again.')); } return true; diff --git a/app/code/Magento/Catalog/Model/ProductLink/Repository.php b/app/code/Magento/Catalog/Model/ProductLink/Repository.php index f8dee9216ddcf..5bac99dbebbb4 100644 --- a/app/code/Magento/Catalog/Model/ProductLink/Repository.php +++ b/app/code/Magento/Catalog/Model/ProductLink/Repository.php @@ -137,7 +137,7 @@ public function save(\Magento\Catalog\Api\Data\ProductLinkInterface $entity) $linkTypesToId[$entity->getLinkType()] ); } catch (\Exception $exception) { - throw new CouldNotSaveException(__('Invalid data provided for linked products')); + throw new CouldNotSaveException(__('The linked products data is invalid. Verify the data and try again.')); } return true; } @@ -212,7 +212,7 @@ public function delete(\Magento\Catalog\Api\Data\ProductLinkInterface $entity) try { $this->getLinkResource()->deleteProductLink($linkId); } catch (\Exception $exception) { - throw new CouldNotSaveException(__('Invalid data provided for linked products')); + throw new CouldNotSaveException(__('The linked products data is invalid. Verify the data and try again.')); } return true; } diff --git a/app/code/Magento/Catalog/Model/ProductRepository.php b/app/code/Magento/Catalog/Model/ProductRepository.php index e814dc03cf37f..e3329832e134a 100644 --- a/app/code/Magento/Catalog/Model/ProductRepository.php +++ b/app/code/Magento/Catalog/Model/ProductRepository.php @@ -4,6 +4,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Catalog\Model; use Magento\Catalog\Api\Data\ProductInterface; @@ -237,7 +238,9 @@ public function get($sku, $editMode = false, $storeId = null, $forceReload = fal $productId = $this->resourceModel->getIdBySku($sku); if (!$productId) { - throw new NoSuchEntityException(__('Requested product doesn\'t exist')); + throw new NoSuchEntityException( + __("The product that was requested doesn't exist. Verify the product and try again.") + ); } if ($editMode) { $product->setData('_edit_mode', true); @@ -270,7 +273,9 @@ public function getById($productId, $editMode = false, $storeId = null, $forceRe } $product->load($productId); if (!$product->getId()) { - throw new NoSuchEntityException(__('Requested product doesn\'t exist')); + throw new NoSuchEntityException( + __("The product that was requested doesn't exist. Verify the product and try again.") + ); } $this->cacheProduct($cacheKey, $product); } @@ -393,7 +398,9 @@ protected function processNewMediaGalleryEntry( $tmpFilePath = $mediaConfig->getTmpMediaShortUrl($relativeFilePath); if (!$product->hasGalleryAttribute()) { - throw new StateException(__('Requested product does not support images.')); + throw new StateException( + __("The product that was requested doesn't exist. Verify the product and try again.") + ); } $imageFileUri = $this->getMediaGalleryProcessor()->addImage( @@ -460,7 +467,7 @@ private function processLinks(\Magento\Catalog\Api\Data\ProductInterface $produc $linkedSku = $link->getLinkedProductSku(); if (!isset($linkedProductIds[$linkedSku])) { throw new NoSuchEntityException( - __('Product with SKU "%1" does not exist', $linkedSku) + __('The Product with the "%1" SKU doesn\'t exist.', $linkedSku) ); } $linkDataArray['product_id'] = $linkedProductIds[$linkedSku]; @@ -532,7 +539,7 @@ protected function processMediaGallery(ProductInterface $product, $mediaGalleryE foreach ($newEntries as $newEntry) { if (!isset($newEntry['content'])) { - throw new InputException(__('The image content is not valid.')); + throw new InputException(__('The image content is invalid. Verify the content and try again.')); } /** @var ImageContentInterface $contentDataObject */ $contentDataObject = $this->contentFactory->create() @@ -638,7 +645,10 @@ public function save(\Magento\Catalog\Api\Data\ProductInterface $product, $saveO } catch (LocalizedException $e) { throw $e; } catch (\Exception $e) { - throw new \Magento\Framework\Exception\CouldNotSaveException(__('Unable to save product'), $e); + throw new \Magento\Framework\Exception\CouldNotSaveException( + __('The product was unable to be saved. Please try again.'), + $e + ); } unset($this->instances[$product->getSku()]); unset($this->instancesById[$product->getId()]); @@ -660,7 +670,7 @@ public function delete(\Magento\Catalog\Api\Data\ProductInterface $product) throw new CouldNotSaveException(__($e->getMessage())); } catch (\Exception $e) { throw new \Magento\Framework\Exception\StateException( - __('Unable to remove product %1', $sku) + __('The "%1" product couldn\'t be removed.', $sku) ); } unset($this->instances[$sku]); diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/Link/DeleteHandler.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/Link/DeleteHandler.php index 1204c66b956f2..024c87c9fc886 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product/Link/DeleteHandler.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/Link/DeleteHandler.php @@ -93,7 +93,9 @@ public function execute($entityType, $entity) try { $this->linkResource->deleteProductLink($linkId); } catch (\Exception $exception) { - throw new CouldNotDeleteException(__('Invalid data provided for linked products')); + throw new CouldNotDeleteException( + __('The linked products data is invalid. Verify the data and try again.') + ); } } } diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/Link/SaveHandler.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/Link/SaveHandler.php index d1372feb77796..c40872ed64bed 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product/Link/SaveHandler.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/Link/SaveHandler.php @@ -105,7 +105,7 @@ public function execute($entityType, $entity) $linkTypesToId[$entity->getLinkType()] ); } catch (\Exception $exception) { - throw new CouldNotSaveException(__('Invalid data provided for linked products')); + throw new CouldNotSaveException(__('The linked products data is invalid. Verify the data and try again.')); } return $entity; } diff --git a/app/code/Magento/Catalog/Setup/CategorySetup.php b/app/code/Magento/Catalog/Setup/CategorySetup.php index f85407a9a9d7a..271387932829b 100644 --- a/app/code/Magento/Catalog/Setup/CategorySetup.php +++ b/app/code/Magento/Catalog/Setup/CategorySetup.php @@ -7,13 +7,51 @@ */ namespace Magento\Catalog\Setup; +use Magento\Catalog\Block\Adminhtml\Category\Helper\Pricestep; +use Magento\Catalog\Block\Adminhtml\Category\Helper\Sortby\Available; +use Magento\Catalog\Block\Adminhtml\Category\Helper\Sortby\DefaultSortby; +use Magento\Catalog\Block\Adminhtml\Product\Helper\Form\BaseImage; +use Magento\Catalog\Block\Adminhtml\Product\Helper\Form\Category as CategoryFormHelper; +use Magento\Catalog\Block\Adminhtml\Product\Helper\Form\Weight as WeightFormHelper; +use Magento\Catalog\Model\Attribute\Backend\Customlayoutupdate; +use Magento\Catalog\Model\Attribute\Backend\Startdate; +use Magento\Catalog\Model\Category\Attribute\Backend\Image; +use Magento\Catalog\Model\Category\Attribute\Backend\Sortby as SortbyBackendModel; +use Magento\Catalog\Model\Category\Attribute\Source\Layout; +use Magento\Catalog\Model\Category\Attribute\Source\Mode; +use Magento\Catalog\Model\Category\Attribute\Source\Page; +use Magento\Catalog\Model\Category\Attribute\Source\Sortby; use Magento\Catalog\Model\CategoryFactory; +use Magento\Catalog\Model\Entity\Product\Attribute\Design\Options\Container; +use Magento\Catalog\Model\Product\Attribute\Backend\Category as CategoryBackendAttribute; +use Magento\Catalog\Model\Product\Attribute\Backend\Price; +use Magento\Catalog\Model\Product\Attribute\Backend\Sku; +use Magento\Catalog\Model\Product\Attribute\Backend\Stock; +use Magento\Catalog\Model\Product\Attribute\Backend\Tierprice; +use Magento\Catalog\Model\Product\Attribute\Backend\Weight; +use Magento\Catalog\Model\Product\Attribute\Frontend\Image as ImageFrontendModel; +use Magento\Catalog\Model\Product\Attribute\Source\Countryofmanufacture; +use Magento\Catalog\Model\Product\Attribute\Source\Layout as LayoutModel; +use Magento\Catalog\Model\Product\Attribute\Source\Status; +use Magento\Catalog\Model\Product\Visibility; +use Magento\Catalog\Model\ResourceModel\Category; +use Magento\Catalog\Model\ResourceModel\Category\Attribute\Collection; +use Magento\Catalog\Model\ResourceModel\Eav\Attribute; +use Magento\Catalog\Model\ResourceModel\Product; +use Magento\CatalogInventory\Block\Adminhtml\Form\Field\Stock as StockField; +use Magento\CatalogInventory\Model\Source\Stock as StockSourceModel; +use Magento\CatalogInventory\Model\Stock as StockModel; +use Magento\Eav\Model\Entity\Attribute\Backend\Datetime; +use Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface; +use Magento\Eav\Model\Entity\Attribute\Source\Boolean; use Magento\Eav\Model\Entity\Setup\Context; use Magento\Eav\Model\ResourceModel\Entity\Attribute\Group\CollectionFactory; use Magento\Eav\Setup\EavSetup; use Magento\Framework\App\CacheInterface; +use Magento\Framework\App\ResourceConnection; use Magento\Framework\Setup\ModuleDataSetupInterface; use Magento\Catalog\Model\Product\Type; +use Magento\Theme\Model\Theme\Source\Theme; /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) @@ -80,28 +118,28 @@ public function getDefaultEntities() return [ 'catalog_category' => [ 'entity_type_id' => self::CATEGORY_ENTITY_TYPE_ID, - 'entity_model' => \Magento\Catalog\Model\ResourceModel\Category::class, - 'attribute_model' => \Magento\Catalog\Model\ResourceModel\Eav\Attribute::class, + 'entity_model' => Category::class, + 'attribute_model' => Attribute::class, 'table' => 'catalog_category_entity', 'additional_attribute_table' => 'catalog_eav_attribute', 'entity_attribute_collection' => - \Magento\Catalog\Model\ResourceModel\Category\Attribute\Collection::class, + Collection::class, 'attributes' => [ 'name' => [ 'type' => 'varchar', 'label' => 'Name', 'input' => 'text', 'sort_order' => 1, - 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE, + 'global' => ScopedAttributeInterface::SCOPE_STORE, 'group' => 'General Information', ], 'is_active' => [ 'type' => 'int', 'label' => 'Is Active', 'input' => 'select', - 'source' => \Magento\Eav\Model\Entity\Attribute\Source\Boolean::class, + 'source' => Boolean::class, 'sort_order' => 2, - 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE, + 'global' => ScopedAttributeInterface::SCOPE_STORE, 'group' => 'General Information', ], 'description' => [ @@ -110,7 +148,7 @@ public function getDefaultEntities() 'input' => 'textarea', 'required' => false, 'sort_order' => 4, - 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE, + 'global' => ScopedAttributeInterface::SCOPE_STORE, 'wysiwyg_enabled' => true, 'is_html_allowed_on_front' => true, 'group' => 'General Information', @@ -119,10 +157,10 @@ public function getDefaultEntities() 'type' => 'varchar', 'label' => 'Image', 'input' => 'image', - 'backend' => \Magento\Catalog\Model\Category\Attribute\Backend\Image::class, + 'backend' => Image::class, 'required' => false, 'sort_order' => 5, - 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE, + 'global' => ScopedAttributeInterface::SCOPE_STORE, 'group' => 'General Information', ], 'meta_title' => [ @@ -131,7 +169,7 @@ public function getDefaultEntities() 'input' => 'text', 'required' => false, 'sort_order' => 6, - 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE, + 'global' => ScopedAttributeInterface::SCOPE_STORE, 'group' => 'General Information', ], 'meta_keywords' => [ @@ -140,7 +178,7 @@ public function getDefaultEntities() 'input' => 'textarea', 'required' => false, 'sort_order' => 7, - 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE, + 'global' => ScopedAttributeInterface::SCOPE_STORE, 'group' => 'General Information', ], 'meta_description' => [ @@ -149,34 +187,34 @@ public function getDefaultEntities() 'input' => 'textarea', 'required' => false, 'sort_order' => 8, - 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE, + 'global' => ScopedAttributeInterface::SCOPE_STORE, 'group' => 'General Information', ], 'display_mode' => [ 'type' => 'varchar', 'label' => 'Display Mode', 'input' => 'select', - 'source' => \Magento\Catalog\Model\Category\Attribute\Source\Mode::class, + 'source' => Mode::class, 'required' => false, 'sort_order' => 10, - 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE, + 'global' => ScopedAttributeInterface::SCOPE_STORE, 'group' => 'Display Settings', ], 'landing_page' => [ 'type' => 'int', 'label' => 'CMS Block', 'input' => 'select', - 'source' => \Magento\Catalog\Model\Category\Attribute\Source\Page::class, + 'source' => Page::class, 'required' => false, 'sort_order' => 20, - 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE, + 'global' => ScopedAttributeInterface::SCOPE_STORE, 'group' => 'Display Settings', ], 'is_anchor' => [ 'type' => 'int', 'label' => 'Is Anchor', 'input' => 'select', - 'source' => \Magento\Eav\Model\Entity\Attribute\Source\Boolean::class, + 'source' => Boolean::class, 'required' => false, 'sort_order' => 30, 'group' => 'Display Settings', @@ -222,50 +260,50 @@ public function getDefaultEntities() 'type' => 'varchar', 'label' => 'Custom Design', 'input' => 'select', - 'source' => \Magento\Theme\Model\Theme\Source\Theme::class, + 'source' => Theme::class, 'required' => false, 'sort_order' => 10, - 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE, + 'global' => ScopedAttributeInterface::SCOPE_STORE, 'group' => 'Custom Design', ], 'custom_design_from' => [ 'type' => 'datetime', 'label' => 'Active From', 'input' => 'date', - 'backend' => \Magento\Catalog\Model\Attribute\Backend\Startdate::class, + 'backend' => Startdate::class, 'required' => false, 'sort_order' => 30, - 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE, + 'global' => ScopedAttributeInterface::SCOPE_STORE, 'group' => 'Custom Design', ], 'custom_design_to' => [ 'type' => 'datetime', 'label' => 'Active To', 'input' => 'date', - 'backend' => \Magento\Eav\Model\Entity\Attribute\Backend\Datetime::class, + 'backend' => Datetime::class, 'required' => false, 'sort_order' => 40, - 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE, + 'global' => ScopedAttributeInterface::SCOPE_STORE, 'group' => 'Custom Design', ], 'page_layout' => [ 'type' => 'varchar', 'label' => 'Page Layout', 'input' => 'select', - 'source' => \Magento\Catalog\Model\Category\Attribute\Source\Layout::class, + 'source' => Layout::class, 'required' => false, 'sort_order' => 50, - 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE, + 'global' => ScopedAttributeInterface::SCOPE_STORE, 'group' => 'Custom Design', ], 'custom_layout_update' => [ 'type' => 'text', 'label' => 'Custom Layout Update', 'input' => 'textarea', - 'backend' => \Magento\Catalog\Model\Attribute\Backend\Customlayoutupdate::class, + 'backend' => Customlayoutupdate::class, 'required' => false, 'sort_order' => 60, - 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE, + 'global' => ScopedAttributeInterface::SCOPE_STORE, 'group' => 'Custom Design', ], 'level' => [ @@ -288,53 +326,53 @@ public function getDefaultEntities() 'type' => 'text', 'label' => 'Available Product Listing Sort By', 'input' => 'multiselect', - 'source' => \Magento\Catalog\Model\Category\Attribute\Source\Sortby::class, - 'backend' => \Magento\Catalog\Model\Category\Attribute\Backend\Sortby::class, + 'source' => Sortby::class, + 'backend' => SortbyBackendModel::class, 'sort_order' => 40, - 'input_renderer' => \Magento\Catalog\Block\Adminhtml\Category\Helper\Sortby\Available::class, - 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE, + 'input_renderer' => Available::class, + 'global' => ScopedAttributeInterface::SCOPE_STORE, 'group' => 'Display Settings', ], 'default_sort_by' => [ 'type' => 'varchar', 'label' => 'Default Product Listing Sort By', 'input' => 'select', - 'source' => \Magento\Catalog\Model\Category\Attribute\Source\Sortby::class, - 'backend' => \Magento\Catalog\Model\Category\Attribute\Backend\Sortby::class, + 'source' => Sortby::class, + 'backend' => SortbyBackendModel::class, 'sort_order' => 50, 'input_renderer' => - \Magento\Catalog\Block\Adminhtml\Category\Helper\Sortby\DefaultSortby::class, - 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE, + DefaultSortby::class, + 'global' => ScopedAttributeInterface::SCOPE_STORE, 'group' => 'Display Settings', ], 'include_in_menu' => [ 'type' => 'int', 'label' => 'Include in Navigation Menu', 'input' => 'select', - 'source' => \Magento\Eav\Model\Entity\Attribute\Source\Boolean::class, + 'source' => Boolean::class, 'default' => '1', 'sort_order' => 10, - 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE, + 'global' => ScopedAttributeInterface::SCOPE_STORE, 'group' => 'General Information', ], 'custom_use_parent_settings' => [ 'type' => 'int', 'label' => 'Use Parent Category Settings', 'input' => 'select', - 'source' => \Magento\Eav\Model\Entity\Attribute\Source\Boolean::class, + 'source' => Boolean::class, 'required' => false, 'sort_order' => 5, - 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE, + 'global' => ScopedAttributeInterface::SCOPE_STORE, 'group' => 'Custom Design', ], 'custom_apply_to_products' => [ 'type' => 'int', 'label' => 'Apply To Products', 'input' => 'select', - 'source' => \Magento\Eav\Model\Entity\Attribute\Source\Boolean::class, + 'source' => Boolean::class, 'required' => false, 'sort_order' => 6, - 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE, + 'global' => ScopedAttributeInterface::SCOPE_STORE, 'group' => 'Custom Design', ], 'filter_price_range' => [ @@ -343,20 +381,20 @@ public function getDefaultEntities() 'input' => 'text', 'required' => false, 'sort_order' => 51, - 'input_renderer' => \Magento\Catalog\Block\Adminhtml\Category\Helper\Pricestep::class, - 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE, + 'input_renderer' => Pricestep::class, + 'global' => ScopedAttributeInterface::SCOPE_STORE, 'group' => 'Display Settings', ], ], ], 'catalog_product' => [ 'entity_type_id' => self::CATALOG_PRODUCT_ENTITY_TYPE_ID, - 'entity_model' => \Magento\Catalog\Model\ResourceModel\Product::class, - 'attribute_model' => \Magento\Catalog\Model\ResourceModel\Eav\Attribute::class, + 'entity_model' => Product::class, + 'attribute_model' => Attribute::class, 'table' => 'catalog_product_entity', 'additional_attribute_table' => 'catalog_eav_attribute', 'entity_attribute_collection' => - \Magento\Catalog\Model\ResourceModel\Product\Attribute\Collection::class, + Product\Attribute\Collection::class, 'attributes' => [ 'name' => [ 'type' => 'varchar', @@ -364,7 +402,7 @@ public function getDefaultEntities() 'input' => 'text', 'frontend_class' => 'validate-length maximum-length-255', 'sort_order' => 1, - 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE, + 'global' => ScopedAttributeInterface::SCOPE_STORE, 'searchable' => true, 'visible_in_advanced_search' => true, 'used_in_product_listing' => true, @@ -375,7 +413,7 @@ public function getDefaultEntities() 'label' => 'SKU', 'input' => 'text', 'frontend_class' => 'validate-length maximum-length-64', - 'backend' => \Magento\Catalog\Model\Product\Attribute\Backend\Sku::class, + 'backend' => Sku::class, 'unique' => true, 'sort_order' => 2, 'searchable' => true, @@ -387,7 +425,7 @@ public function getDefaultEntities() 'label' => 'Description', 'input' => 'textarea', 'sort_order' => 3, - 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE, + 'global' => ScopedAttributeInterface::SCOPE_STORE, 'searchable' => true, 'comparable' => true, 'wysiwyg_enabled' => true, @@ -399,7 +437,7 @@ public function getDefaultEntities() 'label' => 'Short Description', 'input' => 'textarea', 'sort_order' => 4, - 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE, + 'global' => ScopedAttributeInterface::SCOPE_STORE, 'searchable' => true, 'comparable' => true, 'wysiwyg_enabled' => true, @@ -414,9 +452,9 @@ public function getDefaultEntities() 'type' => 'decimal', 'label' => 'Price', 'input' => 'price', - 'backend' => \Magento\Catalog\Model\Product\Attribute\Backend\Price::class, + 'backend' => Price::class, 'sort_order' => 1, - 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_WEBSITE, + 'global' => ScopedAttributeInterface::SCOPE_WEBSITE, 'searchable' => true, 'filterable' => true, 'visible_in_advanced_search' => true, @@ -429,10 +467,10 @@ public function getDefaultEntities() 'type' => 'decimal', 'label' => 'Special Price', 'input' => 'price', - 'backend' => \Magento\Catalog\Model\Product\Attribute\Backend\Price::class, + 'backend' => Price::class, 'required' => false, 'sort_order' => 3, - 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_WEBSITE, + 'global' => ScopedAttributeInterface::SCOPE_WEBSITE, 'used_in_product_listing' => true, 'apply_to' => 'simple,virtual', 'group' => 'Prices', @@ -444,10 +482,10 @@ public function getDefaultEntities() 'type' => 'datetime', 'label' => 'Special Price From Date', 'input' => 'date', - 'backend' => \Magento\Catalog\Model\Attribute\Backend\Startdate::class, + 'backend' => Startdate::class, 'required' => false, 'sort_order' => 4, - 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_WEBSITE, + 'global' => ScopedAttributeInterface::SCOPE_WEBSITE, 'used_in_product_listing' => true, 'apply_to' => 'simple,virtual', 'group' => 'Prices', @@ -459,10 +497,10 @@ public function getDefaultEntities() 'type' => 'datetime', 'label' => 'Special Price To Date', 'input' => 'date', - 'backend' => \Magento\Eav\Model\Entity\Attribute\Backend\Datetime::class, + 'backend' => Datetime::class, 'required' => false, 'sort_order' => 5, - 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_WEBSITE, + 'global' => ScopedAttributeInterface::SCOPE_WEBSITE, 'used_in_product_listing' => true, 'apply_to' => 'simple,virtual', 'group' => 'Prices', @@ -474,11 +512,11 @@ public function getDefaultEntities() 'type' => 'decimal', 'label' => 'Cost', 'input' => 'price', - 'backend' => \Magento\Catalog\Model\Product\Attribute\Backend\Price::class, + 'backend' => Price::class, 'required' => false, 'user_defined' => true, 'sort_order' => 6, - 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_WEBSITE, + 'global' => ScopedAttributeInterface::SCOPE_WEBSITE, 'apply_to' => 'simple,virtual', 'group' => 'Prices', 'is_used_in_grid' => true, @@ -489,8 +527,8 @@ public function getDefaultEntities() 'type' => 'decimal', 'label' => 'Weight', 'input' => 'weight', - 'backend' => \Magento\Catalog\Model\Product\Attribute\Backend\Weight::class, - 'input_renderer' => \Magento\Catalog\Block\Adminhtml\Product\Helper\Form\Weight::class, + 'backend' => Weight::class, + 'input_renderer' => WeightFormHelper::class, 'sort_order' => 5, 'apply_to' => 'simple,virtual', 'is_used_in_grid' => true, @@ -518,7 +556,7 @@ public function getDefaultEntities() 'input' => 'text', 'required' => false, 'sort_order' => 20, - 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE, + 'global' => ScopedAttributeInterface::SCOPE_STORE, 'group' => 'Meta Information', 'is_used_in_grid' => true, 'is_visible_in_grid' => false, @@ -530,7 +568,7 @@ public function getDefaultEntities() 'input' => 'textarea', 'required' => false, 'sort_order' => 30, - 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE, + 'global' => ScopedAttributeInterface::SCOPE_STORE, 'group' => 'Meta Information', 'is_used_in_grid' => true, 'is_visible_in_grid' => false, @@ -544,7 +582,7 @@ public function getDefaultEntities() 'note' => 'Maximum 255 chars', 'class' => 'validate-length maximum-length-255', 'sort_order' => 40, - 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE, + 'global' => ScopedAttributeInterface::SCOPE_STORE, 'group' => 'Meta Information', 'is_used_in_grid' => true, 'is_visible_in_grid' => false, @@ -554,11 +592,11 @@ public function getDefaultEntities() 'type' => 'varchar', 'label' => 'Base Image', 'input' => 'media_image', - 'frontend' => \Magento\Catalog\Model\Product\Attribute\Frontend\Image::class, - 'input_renderer' => \Magento\Catalog\Block\Adminhtml\Product\Helper\Form\BaseImage::class, + 'frontend' => ImageFrontendModel::class, + 'input_renderer' => BaseImage::class, 'required' => false, 'sort_order' => 0, - 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE, + 'global' => ScopedAttributeInterface::SCOPE_STORE, 'used_in_product_listing' => true, 'group' => 'General', ], @@ -566,10 +604,10 @@ public function getDefaultEntities() 'type' => 'varchar', 'label' => 'Small Image', 'input' => 'media_image', - 'frontend' => \Magento\Catalog\Model\Product\Attribute\Frontend\Image::class, + 'frontend' => ImageFrontendModel::class, 'required' => false, 'sort_order' => 2, - 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE, + 'global' => ScopedAttributeInterface::SCOPE_STORE, 'used_in_product_listing' => true, 'group' => 'Images', ], @@ -577,10 +615,10 @@ public function getDefaultEntities() 'type' => 'varchar', 'label' => 'Thumbnail', 'input' => 'media_image', - 'frontend' => \Magento\Catalog\Model\Product\Attribute\Frontend\Image::class, + 'frontend' => ImageFrontendModel::class, 'required' => false, 'sort_order' => 3, - 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE, + 'global' => ScopedAttributeInterface::SCOPE_STORE, 'used_in_product_listing' => true, 'group' => 'Images', ], @@ -588,7 +626,7 @@ public function getDefaultEntities() 'type' => 'varchar', 'label' => 'Media Gallery', 'input' => 'gallery', - 'backend' => \Magento\Catalog\Model\Product\Attribute\Backend\Media::class, + 'backend' => Media::class, 'required' => false, 'sort_order' => 4, 'group' => 'Images', @@ -598,10 +636,10 @@ public function getDefaultEntities() 'type' => 'decimal', 'label' => 'Tier Price', 'input' => 'text', - 'backend' => \Magento\Catalog\Model\Product\Attribute\Backend\Tierprice::class, + 'backend' => Tierprice::class, 'required' => false, 'sort_order' => 7, - 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_WEBSITE, + 'global' => ScopedAttributeInterface::SCOPE_WEBSITE, 'apply_to' => 'simple,virtual', 'group' => 'Prices', ], @@ -624,10 +662,10 @@ public function getDefaultEntities() 'type' => 'datetime', 'label' => 'Set Product as New from Date', 'input' => 'date', - 'backend' => \Magento\Catalog\Model\Attribute\Backend\Startdate::class, + 'backend' => Startdate::class, 'required' => false, 'sort_order' => 7, - 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_WEBSITE, + 'global' => ScopedAttributeInterface::SCOPE_WEBSITE, 'used_in_product_listing' => true, 'is_used_in_grid' => true, 'is_visible_in_grid' => false, @@ -637,10 +675,10 @@ public function getDefaultEntities() 'type' => 'datetime', 'label' => 'Set Product as New to Date', 'input' => 'date', - 'backend' => \Magento\Eav\Model\Entity\Attribute\Backend\Datetime::class, + 'backend' => Datetime::class, 'required' => false, 'sort_order' => 8, - 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_WEBSITE, + 'global' => ScopedAttributeInterface::SCOPE_WEBSITE, 'used_in_product_listing' => true, 'is_used_in_grid' => true, 'is_visible_in_grid' => false, @@ -658,9 +696,9 @@ public function getDefaultEntities() 'type' => 'int', 'label' => 'Status', 'input' => 'select', - 'source' => \Magento\Catalog\Model\Product\Attribute\Source\Status::class, + 'source' => Status::class, 'sort_order' => 9, - 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_WEBSITE, + 'global' => ScopedAttributeInterface::SCOPE_WEBSITE, 'searchable' => true, 'used_in_product_listing' => true, ], @@ -670,7 +708,7 @@ public function getDefaultEntities() 'input' => 'price', 'required' => false, 'sort_order' => 8, - 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE, + 'global' => ScopedAttributeInterface::SCOPE_STORE, 'visible' => false, 'apply_to' => 'simple,virtual', 'group' => 'Prices', @@ -679,19 +717,19 @@ public function getDefaultEntities() 'type' => 'int', 'label' => 'Visibility', 'input' => 'select', - 'source' => \Magento\Catalog\Model\Product\Visibility::class, + 'source' => Visibility::class, 'default' => '4', 'sort_order' => 12, - 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE, + 'global' => ScopedAttributeInterface::SCOPE_STORE, ], 'custom_design' => [ 'type' => 'varchar', 'label' => 'Custom Design', 'input' => 'select', - 'source' => \Magento\Theme\Model\Theme\Source\Theme::class, + 'source' => Theme::class, 'required' => false, 'sort_order' => 1, - 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE, + 'global' => ScopedAttributeInterface::SCOPE_STORE, 'group' => 'Design', 'is_used_in_grid' => true, 'is_visible_in_grid' => false, @@ -701,10 +739,10 @@ public function getDefaultEntities() 'type' => 'datetime', 'label' => 'Active From', 'input' => 'date', - 'backend' => \Magento\Catalog\Model\Attribute\Backend\Startdate::class, + 'backend' => Startdate::class, 'required' => false, 'sort_order' => 2, - 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE, + 'global' => ScopedAttributeInterface::SCOPE_STORE, 'group' => 'Design', 'is_used_in_grid' => true, 'is_visible_in_grid' => false, @@ -714,10 +752,10 @@ public function getDefaultEntities() 'type' => 'datetime', 'label' => 'Active To', 'input' => 'date', - 'backend' => \Magento\Eav\Model\Entity\Attribute\Backend\Datetime::class, + 'backend' => Datetime::class, 'required' => false, 'sort_order' => 3, - 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE, + 'global' => ScopedAttributeInterface::SCOPE_STORE, 'group' => 'Design', 'is_used_in_grid' => true, 'is_visible_in_grid' => false, @@ -727,20 +765,20 @@ public function getDefaultEntities() 'type' => 'text', 'label' => 'Custom Layout Update', 'input' => 'textarea', - 'backend' => \Magento\Catalog\Model\Attribute\Backend\Customlayoutupdate::class, + 'backend' => Customlayoutupdate::class, 'required' => false, 'sort_order' => 4, - 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE, + 'global' => ScopedAttributeInterface::SCOPE_STORE, 'group' => 'Design', ], 'page_layout' => [ 'type' => 'varchar', 'label' => 'Page Layout', 'input' => 'select', - 'source' => \Magento\Catalog\Model\Product\Attribute\Source\Layout::class, + 'source' => LayoutModel::class, 'required' => false, 'sort_order' => 5, - 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE, + 'global' => ScopedAttributeInterface::SCOPE_STORE, 'group' => 'Design', 'is_used_in_grid' => true, 'is_visible_in_grid' => false, @@ -749,9 +787,9 @@ public function getDefaultEntities() 'category_ids' => [ 'type' => 'static', 'label' => 'Categories', - 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_GLOBAL, - 'backend' => \Magento\Catalog\Model\Product\Attribute\Backend\Category::class, - 'input_renderer' => \Magento\Catalog\Block\Adminhtml\Product\Helper\Form\Category::class, + 'global' => ScopedAttributeInterface::SCOPE_GLOBAL, + 'backend' => CategoryBackendAttribute::class, + 'input_renderer' => CategoryFormHelper::class, 'required' => false, 'sort_order' => 9, 'visible' => true, @@ -764,11 +802,11 @@ public function getDefaultEntities() 'type' => 'varchar', 'label' => 'Display Product Options In', 'input' => 'select', - 'source' => \Magento\Catalog\Model\Entity\Product\Attribute\Design\Options\Container::class, + 'source' => Container::class, 'required' => false, 'default' => 'container2', 'sort_order' => 6, - 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE, + 'global' => ScopedAttributeInterface::SCOPE_STORE, 'group' => 'Design', ], 'required_options' => [ @@ -792,7 +830,7 @@ public function getDefaultEntities() 'input' => 'text', 'required' => false, 'sort_order' => 16, - 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE, + 'global' => ScopedAttributeInterface::SCOPE_STORE, 'visible' => false, 'used_in_product_listing' => true, ], @@ -802,7 +840,7 @@ public function getDefaultEntities() 'input' => 'text', 'required' => false, 'sort_order' => 17, - 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE, + 'global' => ScopedAttributeInterface::SCOPE_STORE, 'visible' => false, 'used_in_product_listing' => true, ], @@ -812,7 +850,7 @@ public function getDefaultEntities() 'input' => 'text', 'required' => false, 'sort_order' => 18, - 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE, + 'global' => ScopedAttributeInterface::SCOPE_STORE, 'visible' => false, 'used_in_product_listing' => true, ], @@ -832,9 +870,9 @@ public function getDefaultEntities() 'type' => 'varchar', 'label' => 'Country of Manufacture', 'input' => 'select', - 'source' => \Magento\Catalog\Model\Product\Attribute\Source\Countryofmanufacture::class, + 'source' => Countryofmanufacture::class, 'required' => false, - 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_WEBSITE, + 'global' => ScopedAttributeInterface::SCOPE_WEBSITE, 'visible' => true, 'user_defined' => false, 'searchable' => false, @@ -851,13 +889,13 @@ public function getDefaultEntities() 'quantity_and_stock_status' => [ 'group' => 'General', 'type' => 'int', - 'backend' => \Magento\Catalog\Model\Product\Attribute\Backend\Stock::class, + 'backend' => Stock::class, 'label' => 'Quantity', 'input' => 'select', - 'input_renderer' => \Magento\CatalogInventory\Block\Adminhtml\Form\Field\Stock::class, - 'source' => \Magento\CatalogInventory\Model\Source\Stock::class, - 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_GLOBAL, - 'default' => \Magento\CatalogInventory\Model\Stock::STOCK_IN_STOCK, + 'input_renderer' => StockField::class, + 'source' => StockSourceModel::class, + 'global' => ScopedAttributeInterface::SCOPE_GLOBAL, + 'default' => StockModel::STOCK_IN_STOCK, 'user_defined' => false, 'visible' => true, 'required' => false, diff --git a/app/code/Magento/Catalog/Setup/Patch/Data/ChangePriceAttributeDefaultScope.php b/app/code/Magento/Catalog/Setup/Patch/Data/ChangePriceAttributeDefaultScope.php new file mode 100644 index 0000000000000..023ffd316c9ee --- /dev/null +++ b/app/code/Magento/Catalog/Setup/Patch/Data/ChangePriceAttributeDefaultScope.php @@ -0,0 +1,100 @@ +moduleDataSetup = $moduleDataSetup; + $this->categorySetupFactory = $categorySetupFactory; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + /** @var CategorySetup $categorySetup */ + $categorySetup = $this->categorySetupFactory->create(['setup' => $this->moduleDataSetup]); + $this->changePriceAttributeDefaultScope($categorySetup); + } + + /** + * @param CategorySetup $categorySetup + * @return void + */ + private function changePriceAttributeDefaultScope($categorySetup) + { + $entityTypeId = $categorySetup->getEntityTypeId(\Magento\Catalog\Model\Product::ENTITY); + foreach (['price', 'cost', 'special_price'] as $attributeCode) { + $attribute = $categorySetup->getAttribute($entityTypeId, $attributeCode); + if (isset($attribute['attribute_id'])) { + $categorySetup->updateAttribute( + $entityTypeId, + $attribute['attribute_id'], + 'is_global', + \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_GLOBAL + ); + } + } + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return [ + UpdateProductMetaDescription::class, + ]; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.1.3'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } +} diff --git a/app/code/Magento/Catalog/Setup/Patch/Data/DisallowUsingHtmlForProductName.php b/app/code/Magento/Catalog/Setup/Patch/Data/DisallowUsingHtmlForProductName.php new file mode 100644 index 0000000000000..6bd0c69def2da --- /dev/null +++ b/app/code/Magento/Catalog/Setup/Patch/Data/DisallowUsingHtmlForProductName.php @@ -0,0 +1,86 @@ +moduleDataSetup = $moduleDataSetup; + $this->categorySetupFactory = $categorySetupFactory; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + $categorySetup = $this->categorySetupFactory->create(['setup' => $this->moduleDataSetup]); + $entityTypeId = $categorySetup->getEntityTypeId(\Magento\Catalog\Model\Product::ENTITY); + $attribute = $categorySetup->getAttribute($entityTypeId, 'name'); + + $this->moduleDataSetup->getConnection()->update( + $this->moduleDataSetup->getTable('catalog_eav_attribute'), + ['is_html_allowed_on_front' => 0], + $this->moduleDataSetup->getConnection()->quoteInto('attribute_id = ?', $attribute['attribute_id']) + ); + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return [ + ChangePriceAttributeDefaultScope::class, + ]; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.1.5'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } +} diff --git a/app/code/Magento/Catalog/Setup/InstallData.php b/app/code/Magento/Catalog/Setup/Patch/Data/InstallDefaultCategories.php similarity index 82% rename from app/code/Magento/Catalog/Setup/InstallData.php rename to app/code/Magento/Catalog/Setup/Patch/Data/InstallDefaultCategories.php index 5b1a10b098eb5..23f5e88979337 100644 --- a/app/code/Magento/Catalog/Setup/InstallData.php +++ b/app/code/Magento/Catalog/Setup/Patch/Data/InstallDefaultCategories.php @@ -4,66 +4,68 @@ * See COPYING.txt for license details. */ -namespace Magento\Catalog\Setup; +namespace Magento\Catalog\Setup\Patch\Data; -use Magento\Framework\Setup\InstallDataInterface; -use Magento\Framework\Setup\ModuleContextInterface; -use Magento\Framework\Setup\ModuleDataSetupInterface; use Magento\Catalog\Helper\DefaultCategory; +use Magento\Catalog\Helper\DefaultCategoryFactory; +use Magento\Catalog\Setup\CategorySetupFactory; +use Magento\Framework\App\ResourceConnection; +use Magento\Framework\Setup\ModuleDataSetupInterface; +use Magento\Setup\Model\Patch\DataPatchInterface; +use Magento\Setup\Model\Patch\PatchVersionInterface; /** - * @codeCoverageIgnore + * Class InstallDefaultCategories data patch. + * + * @package Magento\Catalog\Setup\Patch * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ -class InstallData implements InstallDataInterface +class InstallDefaultCategories implements DataPatchInterface, PatchVersionInterface { /** - * Category setup factory - * - * @var CategorySetupFactory + * @var ModuleDataSetupInterface */ - private $categorySetupFactory; + private $moduleDataSetup; /** - * @var DefaultCategory + * @var CategorySetupFactory */ - private $defaultCategory; + private $categorySetupFactory; /** - * @deprecated 101.0.0 - * @return DefaultCategory + * @var DefaultCategoryFactory */ - private function getDefaultCategory() - { - if ($this->defaultCategory === null) { - $this->defaultCategory = \Magento\Framework\App\ObjectManager::getInstance() - ->get(DefaultCategory::class); - } - return $this->defaultCategory; - } + private $defaultCategoryFactory; /** - * Init - * + * PatchInitial constructor. + * @param ModuleDataSetupInterface $moduleDataSetup * @param CategorySetupFactory $categorySetupFactory + * @param DefaultCategoryFactory $defaultCategoryFactory */ - public function __construct(CategorySetupFactory $categorySetupFactory) - { + public function __construct( + ModuleDataSetupInterface $moduleDataSetup, + CategorySetupFactory $categorySetupFactory, + \Magento\Catalog\Helper\DefaultCategoryFactory $defaultCategoryFactory + ) { + $this->moduleDataSetup = $moduleDataSetup; $this->categorySetupFactory = $categorySetupFactory; + $this->defaultCategoryFactory = $defaultCategoryFactory; } /** * {@inheritdoc} - * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) */ - public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context) + public function apply() { /** @var \Magento\Catalog\Setup\CategorySetup $categorySetup */ - $categorySetup = $this->categorySetupFactory->create(['setup' => $setup]); + $categorySetup = $this->categorySetupFactory->create(['setup' => $this->moduleDataSetup]); $rootCategoryId = \Magento\Catalog\Model\Category::TREE_ROOT_ID; - $defaultCategoryId = $this->getDefaultCategory()->getId(); + $defaultCategory = $this->defaultCategoryFactory->create(); + $defaultCategoryId = $defaultCategory->getId(); $categorySetup->installEntities(); // Create Root Catalog Node @@ -99,8 +101,11 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface 'path' => \Magento\Catalog\Helper\Category::XML_PATH_CATEGORY_ROOT_ID, 'value' => $category->getId(), ]; - $setup->getConnection() - ->insertOnDuplicate($setup->getTable('core_config_data'), $data, ['value']); + $this->moduleDataSetup->getConnection()->insertOnDuplicate( + $this->moduleDataSetup->getTable('core_config_data'), + $data, + ['value'] + ); $categorySetup->addAttributeGroup(\Magento\Catalog\Model\Product::ENTITY, 'Default', 'Design', 6); @@ -156,8 +161,12 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ]; foreach ($data as $bind) { - $setup->getConnection() - ->insertForce($setup->getTable('catalog_product_link_type'), $bind); + $this->moduleDataSetup->getConnection()->insertForce( + $this->moduleDataSetup->getTable( + 'catalog_product_link_type' + ), + $bind + ); } /** @@ -181,21 +190,25 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ], ]; - $setup->getConnection() - ->insertMultiple($setup->getTable('catalog_product_link_attribute'), $data); + $this->moduleDataSetup->getConnection()->insertMultiple( + $this->moduleDataSetup->getTable('catalog_product_link_attribute'), + $data + ); /** * Remove Catalog specified attribute options (columns) from eav/attribute table * */ - $describe = $setup->getConnection() - ->describeTable($setup->getTable('catalog_eav_attribute')); + $describe = $this->moduleDataSetup->getConnection() + ->describeTable($this->moduleDataSetup->getTable('catalog_eav_attribute')); foreach ($describe as $columnData) { if ($columnData['COLUMN_NAME'] == 'attribute_id') { continue; } - $setup->getConnection() - ->dropColumn($setup->getTable('eav_attribute'), $columnData['COLUMN_NAME']); + $this->moduleDataSetup->getConnection()->dropColumn( + $this->moduleDataSetup->getTable('eav_attribute'), + $columnData['COLUMN_NAME'] + ); } $newGeneralTabName = 'Product Details'; @@ -337,4 +350,28 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface \Magento\Eav\Model\Entity\Attribute\Frontend\Datetime::class ); } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return []; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.0'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } } diff --git a/app/code/Magento/Catalog/Setup/Patch/Data/SetNewResourceModelsPaths.php b/app/code/Magento/Catalog/Setup/Patch/Data/SetNewResourceModelsPaths.php new file mode 100644 index 0000000000000..bc480443019f1 --- /dev/null +++ b/app/code/Magento/Catalog/Setup/Patch/Data/SetNewResourceModelsPaths.php @@ -0,0 +1,116 @@ +moduleDataSetup = $moduleDataSetup; + $this->categorySetupFactory = $categorySetupFactory; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + // set new resource model paths + /** @var CategorySetup $categorySetup */ + $categorySetup = $this->categorySetupFactory->create(['setup' => $this->moduleDataSetup]); + $categorySetup->updateEntityType( + \Magento\Catalog\Model\Category::ENTITY, + 'entity_model', + \Magento\Catalog\Model\ResourceModel\Category::class + ); + $categorySetup->updateEntityType( + \Magento\Catalog\Model\Category::ENTITY, + 'attribute_model', + \Magento\Catalog\Model\ResourceModel\Eav\Attribute::class + ); + $categorySetup->updateEntityType( + \Magento\Catalog\Model\Category::ENTITY, + 'entity_attribute_collection', + \Magento\Catalog\Model\ResourceModel\Category\Attribute\Collection::class + ); + $categorySetup->updateAttribute( + \Magento\Catalog\Model\Category::ENTITY, + 'custom_design_from', + 'attribute_model', + \Magento\Catalog\Model\ResourceModel\Eav\Attribute::class + ); + $categorySetup->updateEntityType( + \Magento\Catalog\Model\Product::ENTITY, + 'entity_model', + \Magento\Catalog\Model\ResourceModel\Product::class + ); + $categorySetup->updateEntityType( + \Magento\Catalog\Model\Product::ENTITY, + 'attribute_model', + \Magento\Catalog\Model\ResourceModel\Eav\Attribute::class + ); + $categorySetup->updateEntityType( + \Magento\Catalog\Model\Product::ENTITY, + 'entity_attribute_collection', + \Magento\Catalog\Model\ResourceModel\Product\Attribute\Collection::class + ); + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return [ + InstallDefaultCategories::class, + ]; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.2'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } +} diff --git a/app/code/Magento/Catalog/Setup/Patch/Data/UpdateDefaultAttributeValue.php b/app/code/Magento/Catalog/Setup/Patch/Data/UpdateDefaultAttributeValue.php new file mode 100644 index 0000000000000..293506530dc6a --- /dev/null +++ b/app/code/Magento/Catalog/Setup/Patch/Data/UpdateDefaultAttributeValue.php @@ -0,0 +1,80 @@ +moduleDataSetup = $moduleDataSetup; + $this->categorySetupFactory = $categorySetupFactory; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + /** @var CategorySetup $categorySetup */ + $categorySetup = $this->categorySetupFactory->create(['setup' => $this->moduleDataSetup]); + $categorySetup->updateAttribute(3, 54, 'default_value', 1); + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return [ + SetNewResourceModelsPaths::class, + ]; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.3'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } +} diff --git a/app/code/Magento/Catalog/Setup/Patch/Data/UpdateMediaAttributesBackendTypes.php b/app/code/Magento/Catalog/Setup/Patch/Data/UpdateMediaAttributesBackendTypes.php new file mode 100644 index 0000000000000..4dfd795273a37 --- /dev/null +++ b/app/code/Magento/Catalog/Setup/Patch/Data/UpdateMediaAttributesBackendTypes.php @@ -0,0 +1,93 @@ +moduleDataSetup = $moduleDataSetup; + $this->categorySetupFactory = $categorySetupFactory; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + $mediaBackendType = 'static'; + $mediaBackendModel = null; + /** @var CategorySetup $categorySetup */ + $categorySetup = $this->categorySetupFactory->create(['setup' => $this->moduleDataSetup]); + $categorySetup->updateAttribute( + 'catalog_product', + 'media_gallery', + 'backend_type', + $mediaBackendType + ); + $categorySetup->updateAttribute( + 'catalog_product', + 'media_gallery', + 'backend_model', + $mediaBackendModel + ); + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return [ + UpdateDefaultAttributeValue::class, + ]; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.4'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } +} diff --git a/app/code/Magento/Catalog/Setup/Patch/Data/UpdateProductAttributes.php b/app/code/Magento/Catalog/Setup/Patch/Data/UpdateProductAttributes.php new file mode 100644 index 0000000000000..e6a69ba680be1 --- /dev/null +++ b/app/code/Magento/Catalog/Setup/Patch/Data/UpdateProductAttributes.php @@ -0,0 +1,266 @@ +moduleDataSetup = $moduleDataSetup; + $this->categorySetupFactory = $categorySetupFactory; + } + + /** + * {@inheritdoc} + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + */ + public function apply() + { + /** @var CategorySetup $categorySetup */ + $categorySetup = $this->categorySetupFactory->create(['setup' => $this->moduleDataSetup]); + + //Product Details tab + $categorySetup->updateAttribute( + \Magento\Catalog\Model\Product::ENTITY, + 'status', + 'frontend_label', + 'Enable Product', + 5 + ); + $categorySetup->updateAttribute( + \Magento\Catalog\Model\Product::ENTITY, + 'name', + 'frontend_label', + 'Product Name' + ); + $attributeSetId = $categorySetup->getDefaultAttributeSetId(\Magento\Catalog\Model\Product::ENTITY); + $categorySetup->addAttributeToGroup( + \Magento\Catalog\Model\Product::ENTITY, + $attributeSetId, + 'Product Details', + 'visibility', + 80 + ); + $categorySetup->addAttributeToGroup( + \Magento\Catalog\Model\Product::ENTITY, + $attributeSetId, + 'Product Details', + 'news_from_date', + 90 + ); + $categorySetup->addAttributeToGroup( + \Magento\Catalog\Model\Product::ENTITY, + $attributeSetId, + 'Product Details', + 'news_to_date', + 100 + ); + $categorySetup->addAttributeToGroup( + \Magento\Catalog\Model\Product::ENTITY, + $attributeSetId, + 'Product Details', + 'country_of_manufacture', + 110 + ); + + //Content tab + $categorySetup->addAttributeGroup( + \Magento\Catalog\Model\Product::ENTITY, + $attributeSetId, + 'Content', + 15 + ); + $categorySetup->updateAttributeGroup( + \Magento\Catalog\Model\Product::ENTITY, + $attributeSetId, + 'Content', + 'tab_group_code', + 'basic' + ); + $categorySetup->addAttributeToGroup( + \Magento\Catalog\Model\Product::ENTITY, + $attributeSetId, + 'Content', + 'description' + ); + $categorySetup->addAttributeToGroup( + \Magento\Catalog\Model\Product::ENTITY, + $attributeSetId, + 'Content', + 'short_description', + 100 + ); + + //Images tab + $groupId = (int)$categorySetup->getAttributeGroupByCode( + \Magento\Catalog\Model\Product::ENTITY, + $attributeSetId, + 'image-management', + 'attribute_group_id' + ); + $categorySetup->addAttributeToGroup( + \Magento\Catalog\Model\Product::ENTITY, + $attributeSetId, + $groupId, + 'image', + 1 + ); + $categorySetup->updateAttributeGroup( + \Magento\Catalog\Model\Product::ENTITY, + $attributeSetId, + $groupId, + 'attribute_group_name', + 'Images' + ); + $categorySetup->updateAttribute( + \Magento\Catalog\Model\Product::ENTITY, + 'image', + 'frontend_label', + 'Base' + ); + $categorySetup->updateAttribute( + \Magento\Catalog\Model\Product::ENTITY, + 'small_image', + 'frontend_label', + 'Small' + ); + $categorySetup->updateAttribute( + \Magento\Catalog\Model\Product::ENTITY, + 'image', + 'frontend_input_renderer', + null + ); + + //Design tab + $categorySetup->updateAttribute( + \Magento\Catalog\Model\Product::ENTITY, + 'page_layout', + 'frontend_label', + 'Layout' + ); + $categorySetup->updateAttribute( + \Magento\Catalog\Model\Product::ENTITY, + 'custom_layout_update', + 'frontend_label', + 'Layout Update XML', + 10 + ); + + //Schedule Design Update tab + $categorySetup->addAttributeGroup( + \Magento\Catalog\Model\Product::ENTITY, + $attributeSetId, + 'Schedule Design Update', + 55 + ); + $categorySetup->updateAttributeGroup( + \Magento\Catalog\Model\Product::ENTITY, + $attributeSetId, + 'Schedule Design Update', + 'tab_group_code', + 'advanced' + ); + $categorySetup->addAttributeToGroup( + \Magento\Catalog\Model\Product::ENTITY, + $attributeSetId, + 'Schedule Design Update', + 'custom_design_from', + 20 + ); + $categorySetup->addAttributeToGroup( + \Magento\Catalog\Model\Product::ENTITY, + $attributeSetId, + 'Schedule Design Update', + 'custom_design_to', + 30 + ); + $categorySetup->updateAttribute( + \Magento\Catalog\Model\Product::ENTITY, + 'custom_design', + 'frontend_label', + 'New Theme', + 40 + ); + $categorySetup->addAttributeToGroup( + \Magento\Catalog\Model\Product::ENTITY, + $attributeSetId, + 'Schedule Design Update', + 'custom_design' + ); + $categorySetup->addAttribute( + \Magento\Catalog\Model\Product::ENTITY, + 'custom_layout', + [ + 'type' => 'varchar', + 'label' => 'New Layout', + 'input' => 'select', + 'source' => \Magento\Catalog\Model\Product\Attribute\Source\Layout::class, + 'required' => false, + 'sort_order' => 50, + 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE, + 'group' => 'Schedule Design Update', + 'is_used_in_grid' => true, + 'is_visible_in_grid' => false, + 'is_filterable_in_grid' => false + ] + ); + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return [ + UpdateMediaAttributesBackendTypes::class, + ]; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.5'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } +} diff --git a/app/code/Magento/Catalog/Setup/Patch/Data/UpdateProductMetaDescription.php b/app/code/Magento/Catalog/Setup/Patch/Data/UpdateProductMetaDescription.php new file mode 100644 index 0000000000000..e7936560d862c --- /dev/null +++ b/app/code/Magento/Catalog/Setup/Patch/Data/UpdateProductMetaDescription.php @@ -0,0 +1,88 @@ +moduleDataSetup = $moduleDataSetup; + $this->eavSetupFactory = $eavSetupFactory; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + /** @var EavSetup $eavSetup */ + $eavSetup = $this->eavSetupFactory->create(['setup' => $this->moduleDataSetup]); + + $eavSetup->updateAttribute( + \Magento\Catalog\Model\Product::ENTITY, + 'meta_description', + [ + 'note' => 'Maximum 255 chars. Meta Description should optimally be between 150-160 characters' + ] + ); + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return [ + UpdateProductAttributes::class, + ]; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.7'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } +} diff --git a/app/code/Magento/Catalog/Setup/UpgradeWebsiteAttributes.php b/app/code/Magento/Catalog/Setup/Patch/Data/UpgradeWebsiteAttributes.php similarity index 79% rename from app/code/Magento/Catalog/Setup/UpgradeWebsiteAttributes.php rename to app/code/Magento/Catalog/Setup/Patch/Data/UpgradeWebsiteAttributes.php index 3d300d9c849a9..85a4ec789b508 100644 --- a/app/code/Magento/Catalog/Setup/UpgradeWebsiteAttributes.php +++ b/app/code/Magento/Catalog/Setup/Patch/Data/UpgradeWebsiteAttributes.php @@ -4,7 +4,7 @@ * See COPYING.txt for license details. */ -namespace Magento\Catalog\Setup; +namespace Magento\Catalog\Setup\Patch\Data; use Magento\Catalog\Api\Data\CategoryInterface; use Magento\Catalog\Api\Data\ProductInterface; @@ -12,14 +12,16 @@ use Magento\Framework\EntityManager\MetadataPool; use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Setup\ModuleDataSetupInterface; +use Magento\Setup\Model\Patch\DataPatchInterface; +use Magento\Setup\Model\Patch\PatchVersionInterface; /** * Class UpgradeWebsiteAttributes - * @package Magento\Catalog\Setup + * @package Magento\Catalog\Setup\Patch * * IMPORTANT: This class const/methods can not be reused because it needs to be isolated */ -class UpgradeWebsiteAttributes +class UpgradeWebsiteAttributes implements DataPatchInterface, PatchVersionInterface { /** * ATTENTION: These constants must not be reused anywhere outside @@ -79,48 +81,55 @@ class UpgradeWebsiteAttributes */ private $linkFields = []; + /** + * @var ModuleDataSetupInterface + */ + private $moduleDataSetup; + /** * UpgradeWebsiteAttributes constructor. * @param Generator $batchQueryGenerator * @param MetadataPool $metadataPool + * @param ModuleDataSetupInterface $moduleDataSetup */ - public function __construct(Generator $batchQueryGenerator, MetadataPool $metadataPool) - { + public function __construct( + Generator $batchQueryGenerator, + MetadataPool $metadataPool, + ModuleDataSetupInterface $moduleDataSetup + ) { $this->batchQueryGenerator = $batchQueryGenerator; $this->metaDataPool = $metadataPool; + $this->moduleDataSetup = $moduleDataSetup; } /** - * @param ModuleDataSetupInterface $setup - * @return void + * {@inheritdoc} */ - public function upgrade(ModuleDataSetupInterface $setup) + public function apply() { foreach (array_keys($this->tableMetaDataClass) as $tableName) { - $this->upgradeTable($setup, $tableName); + $this->upgradeTable($tableName); } } /** - * @param ModuleDataSetupInterface $setup * @param string $tableName * @return void */ - private function upgradeTable(ModuleDataSetupInterface $setup, $tableName) + private function upgradeTable($tableName) { - foreach ($this->fetchAttributeValues($setup, $tableName) as $attributeValueItems) { - $this->processAttributeValues($setup, $attributeValueItems, $tableName); + foreach ($this->fetchAttributeValues($tableName) as $attributeValueItems) { + $this->processAttributeValues($attributeValueItems, $tableName); } } /** * Aligns website attribute values - * @param ModuleDataSetupInterface $setup * @param array $attributeValueItems * @param string $tableName * @return void */ - private function processAttributeValues(ModuleDataSetupInterface $setup, array $attributeValueItems, $tableName) + private function processAttributeValues(array $attributeValueItems, $tableName) { $this->resetProcessedAttributeValues(); @@ -129,9 +138,9 @@ private function processAttributeValues(ModuleDataSetupInterface $setup, array $ continue; } - $insertions = $this->generateAttributeValueInsertions($setup, $attributeValueItem, $tableName); + $insertions = $this->generateAttributeValueInsertions($attributeValueItem, $tableName); if (!empty($insertions)) { - $this->executeInsertions($setup, $insertions, $tableName); + $this->executeInsertions($insertions, $tableName); } $this->markAttributeValueProcessed($attributeValueItem, $tableName); @@ -141,32 +150,31 @@ private function processAttributeValues(ModuleDataSetupInterface $setup, array $ /** * Yields batch of AttributeValues * - * @param ModuleDataSetupInterface $setup * @param string $tableName * @yield array - * @return void + * @return \Generator */ - private function fetchAttributeValues(ModuleDataSetupInterface $setup, $tableName) + private function fetchAttributeValues($tableName) { - $connection = $setup->getConnection(); + $connection = $this->moduleDataSetup->getConnection(); $batchSelectIterator = $this->batchQueryGenerator->generate( 'value_id', $connection ->select() ->from( - ['cpei' => $setup->getTable($tableName)], + ['cpei' => $this->moduleDataSetup->getTable($tableName)], '*' ) ->join( [ - 'cea' => $setup->getTable('catalog_eav_attribute'), + 'cea' => $this->moduleDataSetup->getTable('catalog_eav_attribute'), ], 'cpei.attribute_id = cea.attribute_id', '' ) ->join( [ - 'st' => $setup->getTable('store'), + 'st' => $this->moduleDataSetup->getTable('store'), ], 'st.store_id = cpei.store_id', 'st.website_id' @@ -187,20 +195,19 @@ private function fetchAttributeValues(ModuleDataSetupInterface $setup, $tableNam } /** - * @param ModuleDataSetupInterface $setup * @return array */ - private function getGroupedStoreViews(ModuleDataSetupInterface $setup) + private function getGroupedStoreViews() { if (!empty($this->groupedStoreViews)) { return $this->groupedStoreViews; } - $connection = $setup->getConnection(); + $connection = $this->moduleDataSetup->getConnection(); $query = $connection ->select() ->from( - $setup->getTable('store'), + $this->moduleDataSetup->getTable('store'), '*' ); @@ -274,17 +281,15 @@ private function getAttributeValueKey($entityId, $attributeId, $websiteId) } /** - * @param ModuleDataSetupInterface $setup * @param array $attributeValue * @param string $tableName * @return array|null */ private function generateAttributeValueInsertions( - ModuleDataSetupInterface $setup, array $attributeValue, $tableName ) { - $groupedStoreViews = $this->getGroupedStoreViews($setup); + $groupedStoreViews = $this->getGroupedStoreViews(); if (empty($groupedStoreViews[$attributeValue['website_id']])) { return null; } @@ -305,12 +310,11 @@ private function generateAttributeValueInsertions( } /** - * @param ModuleDataSetupInterface $setup * @param array $insertions * @param string $tableName * @return void */ - private function executeInsertions(ModuleDataSetupInterface $setup, array $insertions, $tableName) + private function executeInsertions(array $insertions, $tableName) { $rawQuery = sprintf( 'INSERT INTO @@ -318,12 +322,12 @@ private function executeInsertions(ModuleDataSetupInterface $setup, array $inser VALUES %s ON duplicate KEY UPDATE `value` = VALUES(`value`)', - $setup->getTable($tableName), + $this->moduleDataSetup->getTable($tableName), $this->getTableLinkField($tableName), $this->prepareInsertValuesStatement($insertions) ); - $setup->getConnection()->query($rawQuery, $this->getPlaceholderValues($insertions)); + $this->moduleDataSetup->getConnection()->query($rawQuery, $this->getPlaceholderValues($insertions)); } /** @@ -386,4 +390,30 @@ private function getTableLinkField($tableName) return $this->linkFields[$tableName]; } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return [ + UpgradeWidgetData::class, + ]; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.2.2'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } } diff --git a/app/code/Magento/Catalog/Setup/UpgradeWidgetData.php b/app/code/Magento/Catalog/Setup/Patch/Data/UpgradeWidgetData.php similarity index 71% rename from app/code/Magento/Catalog/Setup/UpgradeWidgetData.php rename to app/code/Magento/Catalog/Setup/Patch/Data/UpgradeWidgetData.php index f9eba413f5416..46c579bde20d5 100644 --- a/app/code/Magento/Catalog/Setup/UpgradeWidgetData.php +++ b/app/code/Magento/Catalog/Setup/Patch/Data/UpgradeWidgetData.php @@ -3,19 +3,31 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\Catalog\Setup; -use Magento\Framework\DB\Select\QueryModifierFactory; -use Magento\Widget\Setup\LayoutUpdateConverter; +namespace Magento\Catalog\Setup\Patch\Data; + use Magento\Eav\Setup\EavSetup; -use Magento\Framework\DB\FieldToConvert; +use Magento\Eav\Setup\EavSetupFactory; use Magento\Framework\DB\AggregatedFieldDataConverter; +use Magento\Framework\DB\FieldToConvert; +use Magento\Framework\DB\Select\QueryModifierFactory; +use Magento\Framework\Setup\ModuleDataSetupInterface; +use Magento\Setup\Model\Patch\DataPatchInterface; +use Magento\Setup\Model\Patch\PatchVersionInterface; +use Magento\Widget\Setup\LayoutUpdateConverter; /** - * Convert serialized widget data for categories and products tables to JSON + * Class UpgradeWidgetData. + * + * @package Magento\Catalog\Setup\Patch */ -class UpgradeWidgetData +class UpgradeWidgetData implements DataPatchInterface, PatchVersionInterface { + /** + * @var ModuleDataSetupInterface + */ + private $moduleDataSetup; + /** * @var EavSetup */ @@ -27,29 +39,33 @@ class UpgradeWidgetData private $queryModifierFactory; /** - * Constructor - * - * @param EavSetup $eavSetup + * @var AggregatedFieldDataConverter + */ + private $aggregatedFieldDataConverter; + + /** + * PrepareInitialConfig constructor. + * @param ModuleDataSetupInterface $moduleDataSetup + * @param EavSetupFactory $eavSetupFactory * @param QueryModifierFactory $queryModifierFactory * @param AggregatedFieldDataConverter $aggregatedFieldDataConverter */ public function __construct( - EavSetup $eavSetup, + ModuleDataSetupInterface $moduleDataSetup, + EavSetupFactory $eavSetupFactory, QueryModifierFactory $queryModifierFactory, AggregatedFieldDataConverter $aggregatedFieldDataConverter ) { - $this->eavSetup = $eavSetup; + $this->moduleDataSetup = $moduleDataSetup; + $this->eavSetup = $eavSetupFactory->create(['setup' => $moduleDataSetup]); $this->queryModifierFactory = $queryModifierFactory; $this->aggregatedFieldDataConverter = $aggregatedFieldDataConverter; } /** - * Convert category and product layout update - * - * @return void - * @throws \InvalidArgumentException + * {@inheritdoc} */ - public function upgrade() + public function apply() { $categoryTypeId = $this->eavSetup->getEntityTypeId(\Magento\Catalog\Model\Category::ENTITY); $categoryLayoutUpdateAttribute = $this->eavSetup->getAttribute($categoryTypeId, 'custom_layout_update'); @@ -117,4 +133,30 @@ public function upgrade() $this->eavSetup->getSetup()->getConnection() ); } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return [ + DisallowUsingHtmlForProductName::class, + ]; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.2.1'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } } diff --git a/app/code/Magento/Catalog/Setup/UpgradeData.php b/app/code/Magento/Catalog/Setup/UpgradeData.php deleted file mode 100644 index a290d4870bd49..0000000000000 --- a/app/code/Magento/Catalog/Setup/UpgradeData.php +++ /dev/null @@ -1,439 +0,0 @@ -categorySetupFactory = $categorySetupFactory; - $this->eavSetupFactory = $eavSetupFactory; - $this->upgradeWidgetData = $upgradeWidgetData; - $this->upgradeWebsiteAttributes = $upgradeWebsiteAttributes; - } - - /** - * {@inheritdoc} - * @SuppressWarnings(PHPMD.ExcessiveMethodLength) - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - * @SuppressWarnings(PHPMD.NPathComplexity) - */ - public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context) - { - $setup->startSetup(); - if ($context->getVersion() - && version_compare($context->getVersion(), '2.0.1') < 0 - ) { - $select = $setup->getConnection()->select() - ->from( - $setup->getTable('catalog_product_entity_group_price'), - [ - 'entity_id', - 'all_groups', - 'customer_group_id', - new \Zend_Db_Expr('1'), - 'value', - 'website_id' - ] - ); - $select = $setup->getConnection()->insertFromSelect( - $select, - $setup->getTable('catalog_product_entity_tier_price'), - [ - 'entity_id', - 'all_groups', - 'customer_group_id', - 'qty', - 'value', - 'website_id' - ] - ); - $setup->getConnection()->query($select); - - $categorySetupManager = $this->categorySetupFactory->create(); - $categorySetupManager->removeAttribute(\Magento\Catalog\Model\Product::ENTITY, 'group_price'); - } - - if (version_compare($context->getVersion(), '2.0.2') < 0) { - // set new resource model paths - /** @var CategorySetup $categorySetup */ - $categorySetup = $this->categorySetupFactory->create(['setup' => $setup]); - $categorySetup->updateEntityType( - \Magento\Catalog\Model\Category::ENTITY, - 'entity_model', - \Magento\Catalog\Model\ResourceModel\Category::class - ); - $categorySetup->updateEntityType( - \Magento\Catalog\Model\Category::ENTITY, - 'attribute_model', - \Magento\Catalog\Model\ResourceModel\Eav\Attribute::class - ); - $categorySetup->updateEntityType( - \Magento\Catalog\Model\Category::ENTITY, - 'entity_attribute_collection', - \Magento\Catalog\Model\ResourceModel\Category\Attribute\Collection::class - ); - $categorySetup->updateAttribute( - \Magento\Catalog\Model\Category::ENTITY, - 'custom_design_from', - 'attribute_model', - \Magento\Catalog\Model\ResourceModel\Eav\Attribute::class - ); - $categorySetup->updateEntityType( - \Magento\Catalog\Model\Product::ENTITY, - 'entity_model', - \Magento\Catalog\Model\ResourceModel\Product::class - ); - $categorySetup->updateEntityType( - \Magento\Catalog\Model\Product::ENTITY, - 'attribute_model', - \Magento\Catalog\Model\ResourceModel\Eav\Attribute::class - ); - $categorySetup->updateEntityType( - \Magento\Catalog\Model\Product::ENTITY, - 'entity_attribute_collection', - \Magento\Catalog\Model\ResourceModel\Product\Attribute\Collection::class - ); - } - - if (version_compare($context->getVersion(), '2.0.3') < 0) { - /** @var CategorySetup $categorySetup */ - $categorySetup = $this->categorySetupFactory->create(['setup' => $setup]); - $categorySetup->updateAttribute(3, 54, 'default_value', 1); - } - - if (version_compare($context->getVersion(), '2.0.4') < 0) { - $mediaBackendType = 'static'; - $mediaBackendModel = null; - /** @var CategorySetup $categorySetup */ - $categorySetup = $this->categorySetupFactory->create(['setup' => $setup]); - $categorySetup->updateAttribute( - 'catalog_product', - 'media_gallery', - 'backend_type', - $mediaBackendType - ); - $categorySetup->updateAttribute( - 'catalog_product', - 'media_gallery', - 'backend_model', - $mediaBackendModel - ); - } - - if (version_compare($context->getVersion(), '2.0.5', '<')) { - /** @var CategorySetup $categorySetup */ - $categorySetup = $this->categorySetupFactory->create(['setup' => $setup]); - - //Product Details tab - $categorySetup->updateAttribute( - \Magento\Catalog\Model\Product::ENTITY, - 'status', - 'frontend_label', - 'Enable Product', - 5 - ); - $categorySetup->updateAttribute( - \Magento\Catalog\Model\Product::ENTITY, - 'name', - 'frontend_label', - 'Product Name' - ); - $attributeSetId = $categorySetup->getDefaultAttributeSetId(\Magento\Catalog\Model\Product::ENTITY); - $categorySetup->addAttributeToGroup( - \Magento\Catalog\Model\Product::ENTITY, - $attributeSetId, - 'Product Details', - 'visibility', - 80 - ); - $categorySetup->addAttributeToGroup( - \Magento\Catalog\Model\Product::ENTITY, - $attributeSetId, - 'Product Details', - 'news_from_date', - 90 - ); - $categorySetup->addAttributeToGroup( - \Magento\Catalog\Model\Product::ENTITY, - $attributeSetId, - 'Product Details', - 'news_to_date', - 100 - ); - $categorySetup->addAttributeToGroup( - \Magento\Catalog\Model\Product::ENTITY, - $attributeSetId, - 'Product Details', - 'country_of_manufacture', - 110 - ); - - //Content tab - $categorySetup->addAttributeGroup( - \Magento\Catalog\Model\Product::ENTITY, - $attributeSetId, - 'Content', - 15 - ); - $categorySetup->updateAttributeGroup( - \Magento\Catalog\Model\Product::ENTITY, - $attributeSetId, - 'Content', - 'tab_group_code', - 'basic' - ); - $categorySetup->addAttributeToGroup( - \Magento\Catalog\Model\Product::ENTITY, - $attributeSetId, - 'Content', - 'description' - ); - $categorySetup->addAttributeToGroup( - \Magento\Catalog\Model\Product::ENTITY, - $attributeSetId, - 'Content', - 'short_description', - 100 - ); - - //Images tab - $groupId = (int)$categorySetup->getAttributeGroupByCode( - \Magento\Catalog\Model\Product::ENTITY, - $attributeSetId, - 'image-management', - 'attribute_group_id' - ); - $categorySetup->addAttributeToGroup( - \Magento\Catalog\Model\Product::ENTITY, - $attributeSetId, - $groupId, - 'image', - 1 - ); - $categorySetup->updateAttributeGroup( - \Magento\Catalog\Model\Product::ENTITY, - $attributeSetId, - $groupId, - 'attribute_group_name', - 'Images' - ); - $categorySetup->updateAttribute( - \Magento\Catalog\Model\Product::ENTITY, - 'image', - 'frontend_label', - 'Base' - ); - $categorySetup->updateAttribute( - \Magento\Catalog\Model\Product::ENTITY, - 'small_image', - 'frontend_label', - 'Small' - ); - $categorySetup->updateAttribute( - \Magento\Catalog\Model\Product::ENTITY, - 'image', - 'frontend_input_renderer', - null - ); - - //Design tab - $categorySetup->updateAttribute( - \Magento\Catalog\Model\Product::ENTITY, - 'page_layout', - 'frontend_label', - 'Layout' - ); - $categorySetup->updateAttribute( - \Magento\Catalog\Model\Product::ENTITY, - 'custom_layout_update', - 'frontend_label', - 'Layout Update XML', - 10 - ); - - //Schedule Design Update tab - $categorySetup->addAttributeGroup( - \Magento\Catalog\Model\Product::ENTITY, - $attributeSetId, - 'Schedule Design Update', - 55 - ); - $categorySetup->updateAttributeGroup( - \Magento\Catalog\Model\Product::ENTITY, - $attributeSetId, - 'Schedule Design Update', - 'tab_group_code', - 'advanced' - ); - $categorySetup->addAttributeToGroup( - \Magento\Catalog\Model\Product::ENTITY, - $attributeSetId, - 'Schedule Design Update', - 'custom_design_from', - 20 - ); - $categorySetup->addAttributeToGroup( - \Magento\Catalog\Model\Product::ENTITY, - $attributeSetId, - 'Schedule Design Update', - 'custom_design_to', - 30 - ); - $categorySetup->updateAttribute( - \Magento\Catalog\Model\Product::ENTITY, - 'custom_design', - 'frontend_label', - 'New Theme', - 40 - ); - $categorySetup->addAttributeToGroup( - \Magento\Catalog\Model\Product::ENTITY, - $attributeSetId, - 'Schedule Design Update', - 'custom_design' - ); - $categorySetup->addAttribute( - \Magento\Catalog\Model\Product::ENTITY, - 'custom_layout', - [ - 'type' => 'varchar', - 'label' => 'New Layout', - 'input' => 'select', - 'source' => \Magento\Catalog\Model\Product\Attribute\Source\Layout::class, - 'required' => false, - 'sort_order' => 50, - 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE, - 'group' => 'Schedule Design Update', - 'is_used_in_grid' => true, - 'is_visible_in_grid' => false, - 'is_filterable_in_grid' => false - ] - ); - } - - if (version_compare($context->getVersion(), '2.0.7') < 0) { - /** @var EavSetup $eavSetup */ - $eavSetup = $this->eavSetupFactory->create(['setup' => $setup]); - - $eavSetup->updateAttribute( - \Magento\Catalog\Model\Product::ENTITY, - 'meta_description', - [ - 'note' => 'Maximum 255 chars. Meta Description should optimally be between 150-160 characters' - ] - ); - } - - if (version_compare($context->getVersion(), '2.1.3') < 0) { - /** @var CategorySetup $categorySetup */ - $categorySetup = $this->categorySetupFactory->create(['setup' => $setup]); - $this->changePriceAttributeDefaultScope($categorySetup); - } - - if (version_compare($context->getVersion(), '2.1.5') < 0) { - $this->disallowUsingHtmlForProductName($setup); - } - - if ($context->getVersion() && version_compare($context->getVersion(), '2.2.1') < 0) { - $this->upgradeWidgetData->upgrade(); - } - - if (version_compare($context->getVersion(), '2.2.2') < 0) { - $this->upgradeWebsiteAttributes->upgrade($setup); - } - - $setup->endSetup(); - } - - /** - * Set to 'No' 'Is Allowed Html on Store Front' option on product name attribute, because product name - * is multi entity field (used in order, quote) and cannot be conditionally escaped in all places - * - * @param ModuleDataSetupInterface $setup - * @return void - */ - private function disallowUsingHtmlForProductName(ModuleDataSetupInterface $setup) - { - /** @var CategorySetup $categorySetup */ - $categorySetup = $this->categorySetupFactory->create(['setup' => $setup]); - $entityTypeId = $categorySetup->getEntityTypeId(\Magento\Catalog\Model\Product::ENTITY); - $attribute = $categorySetup->getAttribute($entityTypeId, 'name'); - - $setup->getConnection() - ->update( - $setup->getTable('catalog_eav_attribute'), - ['is_html_allowed_on_front' => 0], - $setup->getConnection()->quoteInto('attribute_id = ?', $attribute['attribute_id']) - ); - } - - /** - * @param CategorySetup $categorySetup - * @return void - */ - private function changePriceAttributeDefaultScope($categorySetup) - { - $entityTypeId = $categorySetup->getEntityTypeId(\Magento\Catalog\Model\Product::ENTITY); - foreach (['price', 'cost', 'special_price'] as $attributeCode) { - $attribute = $categorySetup->getAttribute($entityTypeId, $attributeCode); - if (isset($attribute['attribute_id'])) { - $categorySetup->updateAttribute( - $entityTypeId, - $attribute['attribute_id'], - 'is_global', - \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_GLOBAL - ); - } - } - } -} diff --git a/app/code/Magento/Catalog/Test/Unit/Block/Product/ImageBuilderTest.php b/app/code/Magento/Catalog/Test/Unit/Block/Product/ImageBuilderTest.php index e0b5d6ef3992a..dc152aaf05867 100644 --- a/app/code/Magento/Catalog/Test/Unit/Block/Product/ImageBuilderTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Block/Product/ImageBuilderTest.php @@ -5,49 +5,43 @@ */ namespace Magento\Catalog\Test\Unit\Block\Product; +use Magento\Catalog\Block\Product\ImageBuilder; +use Magento\Catalog\Block\Product\ImageFactory; +use Magento\Catalog\Helper\Image; +use Magento\Catalog\Model\Product; + class ImageBuilderTest extends \PHPUnit\Framework\TestCase { /** - * @var \Magento\Catalog\Block\Product\ImageBuilder + * @var ImageBuilder */ - protected $model; + private $model; /** * @var \Magento\Catalog\Helper\ImageFactory|\PHPUnit_Framework_MockObject_MockObject */ - protected $helperFactory; + private $helperFactory; /** - * @var \Magento\Catalog\Block\Product\ImageFactory|\PHPUnit_Framework_MockObject_MockObject + * @var ImageFactory|\PHPUnit_Framework_MockObject_MockObject */ - protected $imageFactory; + private $imageFactory; protected function setUp() { - $this->helperFactory = $this->getMockBuilder(\Magento\Catalog\Helper\ImageFactory::class) - ->disableOriginalConstructor() - ->setMethods(['create']) - ->getMock(); - - $this->imageFactory = $this->getMockBuilder(\Magento\Catalog\Block\Product\ImageFactory::class) - ->disableOriginalConstructor() - ->setMethods(['create']) - ->getMock(); - - $this->model = new \Magento\Catalog\Block\Product\ImageBuilder( - $this->helperFactory, - $this->imageFactory - ); + $this->helperFactory = $this->createPartialMock(\Magento\Catalog\Helper\ImageFactory::class, ['create']); + + $this->imageFactory = $this->createPartialMock(ImageFactory::class, ['create']); + + $this->model = new ImageBuilder($this->helperFactory, $this->imageFactory); } public function testSetProduct() { - $productMock = $this->getMockBuilder(\Magento\Catalog\Model\Product::class) - ->disableOriginalConstructor() - ->getMock(); + $productMock = $this->createMock(Product::class); $this->assertInstanceOf( - \Magento\Catalog\Block\Product\ImageBuilder::class, + ImageBuilder::class, $this->model->setProduct($productMock) ); } @@ -57,7 +51,7 @@ public function testSetImageId() $imageId = 'test_image_id'; $this->assertInstanceOf( - \Magento\Catalog\Block\Product\ImageBuilder::class, + ImageBuilder::class, $this->model->setImageId($imageId) ); } @@ -68,7 +62,7 @@ public function testSetAttributes() 'name' => 'value', ]; $this->assertInstanceOf( - \Magento\Catalog\Block\Product\ImageBuilder::class, + ImageBuilder::class, $this->model->setAttributes($attributes) ); } @@ -81,13 +75,9 @@ public function testCreate($data, $expected) { $imageId = 'test_image_id'; - $productMock = $this->getMockBuilder(\Magento\Catalog\Model\Product::class) - ->disableOriginalConstructor() - ->getMock(); + $productMock = $this->createMock(Product::class); - $helperMock = $this->getMockBuilder(\Magento\Catalog\Helper\Image::class) - ->disableOriginalConstructor() - ->getMock(); + $helperMock = $this->createMock(Image::class); $helperMock->expects($this->once()) ->method('init') ->with($productMock, $imageId) @@ -116,9 +106,7 @@ public function testCreate($data, $expected) ->method('create') ->willReturn($helperMock); - $imageMock = $this->getMockBuilder(\Magento\Catalog\Block\Product\Image::class) - ->disableOriginalConstructor() - ->getMock(); + $imageMock = $this->createMock(\Magento\Catalog\Block\Product\Image::class); $this->imageFactory->expects($this->once()) ->method('create') @@ -131,61 +119,173 @@ public function testCreate($data, $expected) $this->assertInstanceOf(\Magento\Catalog\Block\Product\Image::class, $this->model->create()); } + /** + * Check if custom attributes will be overridden when builder used few times + * @param array $data + * @dataProvider createMultipleCallsDataProvider + */ + public function testCreateMultipleCalls($data) + { + list ($firstCall, $secondCall) = array_values($data); + + $imageId = 'test_image_id'; + + $productMock = $this->createMock(Product::class); + + $helperMock = $this->createMock(Image::class); + $helperMock->expects($this->exactly(2)) + ->method('init') + ->with($productMock, $imageId) + ->willReturnSelf(); + + $helperMock->expects($this->exactly(2)) + ->method('getFrame') + ->willReturnOnConsecutiveCalls($firstCall['data']['frame'], $secondCall['data']['frame']); + $helperMock->expects($this->exactly(2)) + ->method('getUrl') + ->willReturnOnConsecutiveCalls($firstCall['data']['url'], $secondCall['data']['url']); + $helperMock->expects($this->exactly(4)) + ->method('getWidth') + ->willReturnOnConsecutiveCalls( + $firstCall['data']['width'], + $firstCall['data']['width'], + $secondCall['data']['width'], + $secondCall['data']['width'] + ); + $helperMock->expects($this->exactly(4)) + ->method('getHeight') + ->willReturnOnConsecutiveCalls( + $firstCall['data']['height'], + $firstCall['data']['height'], + $secondCall['data']['height'], + $secondCall['data']['height'] + ); + $helperMock->expects($this->exactly(2)) + ->method('getLabel') + ->willReturnOnConsecutiveCalls($firstCall['data']['label'], $secondCall['data']['label']); + $helperMock->expects($this->exactly(2)) + ->method('getResizedImageInfo') + ->willReturnOnConsecutiveCalls($firstCall['data']['imagesize'], $secondCall['data']['imagesize']); + $this->helperFactory->expects($this->exactly(2)) + ->method('create') + ->willReturn($helperMock); + + $imageMock = $this->createMock(\Magento\Catalog\Block\Product\Image::class); + + $this->imageFactory->expects($this->at(0)) + ->method('create') + ->with($firstCall['expected']) + ->willReturn($imageMock); + + $this->imageFactory->expects($this->at(1)) + ->method('create') + ->with($secondCall['expected']) + ->willReturn($imageMock); + + $this->model->setProduct($productMock); + $this->model->setImageId($imageId); + $this->model->setAttributes($firstCall['data']['custom_attributes']); + + $this->assertInstanceOf(\Magento\Catalog\Block\Product\Image::class, $this->model->create()); + + $this->model->setProduct($productMock); + $this->model->setImageId($imageId); + $this->model->setAttributes($secondCall['data']['custom_attributes']); + $this->assertInstanceOf(\Magento\Catalog\Block\Product\Image::class, $this->model->create()); + } + + /** + * @return array + */ + public function createDataProvider(): array + { + return [ + $this->getTestDataWithoutAttributes(), + $this->getTestDataWithAttributes(), + ]; + } + /** * @return array */ - public function createDataProvider() + public function createMultipleCallsDataProvider(): array { return [ [ + [ + 'without_attributes' => $this->getTestDataWithoutAttributes(), + 'with_attributes' => $this->getTestDataWithAttributes(), + ], + ], + [ + [ + 'with_attributes' => $this->getTestDataWithAttributes(), + 'without_attributes' => $this->getTestDataWithoutAttributes(), + ], + ], + ]; + } + + /** + * @return array + */ + private function getTestDataWithoutAttributes(): array + { + return [ + 'data' => [ + 'frame' => 0, + 'url' => 'test_url_1', + 'width' => 100, + 'height' => 100, + 'label' => 'test_label', + 'custom_attributes' => [], + 'imagesize' => [100, 100], + ], + 'expected' => [ 'data' => [ - 'frame' => 0, - 'url' => 'test_url_1', + 'template' => 'Magento_Catalog::product/image_with_borders.phtml', + 'image_url' => 'test_url_1', 'width' => 100, 'height' => 100, 'label' => 'test_label', - 'custom_attributes' => [], - 'imagesize' => [100, 100], + 'ratio' => 1, + 'custom_attributes' => '', + 'resized_image_width' => 100, + 'resized_image_height' => 100, ], - 'expected' => [ - 'data' => [ - 'template' => 'Magento_Catalog::product/image_with_borders.phtml', - 'image_url' => 'test_url_1', - 'width' => 100, - 'height' => 100, - 'label' => 'test_label', - 'ratio' => 1, - 'custom_attributes' => '', - 'resized_image_width' => 100, - 'resized_image_height' => 100, - ], + ], + ]; + } + + /** + * @return array + */ + private function getTestDataWithAttributes(): array + { + return [ + 'data' => [ + 'frame' => 1, + 'url' => 'test_url_2', + 'width' => 100, + 'height' => 50, + 'label' => 'test_label_2', + 'custom_attributes' => [ + 'name_1' => 'value_1', + 'name_2' => 'value_2', ], + 'imagesize' => [120, 70], ], - [ + 'expected' => [ 'data' => [ - 'frame' => 1, - 'url' => 'test_url_2', + 'template' => 'Magento_Catalog::product/image.phtml', + 'image_url' => 'test_url_2', 'width' => 100, 'height' => 50, 'label' => 'test_label_2', - 'custom_attributes' => [ - 'name_1' => 'value_1', - 'name_2' => 'value_2', - ], - 'imagesize' => [120, 70], - ], - 'expected' => [ - 'data' => [ - 'template' => 'Magento_Catalog::product/image.phtml', - 'image_url' => 'test_url_2', - 'width' => 100, - 'height' => 50, - 'label' => 'test_label_2', - 'ratio' => 0.5, - 'custom_attributes' => 'name_1="value_1" name_2="value_2"', - 'resized_image_width' => 120, - 'resized_image_height' => 70, - ], + 'ratio' => 0.5, + 'custom_attributes' => 'name_1="value_1" name_2="value_2"', + 'resized_image_width' => 120, + 'resized_image_height' => 70, ], ], ]; diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Category/Attribute/Backend/ImageTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Category/Attribute/Backend/ImageTest.php index d4e09714d0522..aef9d761c61ba 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Category/Attribute/Backend/ImageTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Category/Attribute/Backend/ImageTest.php @@ -5,6 +5,8 @@ */ namespace Magento\Catalog\Test\Unit\Model\Category\Attribute\Backend; +use Magento\Framework\App\Filesystem\DirectoryList; + class ImageTest extends \PHPUnit\Framework\TestCase { /** @@ -27,6 +29,11 @@ class ImageTest extends \PHPUnit\Framework\TestCase */ private $logger; + /** + * @var \Magento\Framework\Filesystem|\PHPUnit_Framework_MockObject_MockObject + */ + private $filesystem; + protected function setUp() { $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); @@ -59,6 +66,9 @@ protected function setUp() \Magento\Catalog\Model\ImageUploader::class, ['moveFileFromTmp'] ); + + $this->filesystem = $this->getMockBuilder(\Magento\Framework\Filesystem::class)->disableOriginalConstructor() + ->getMock(); } /** @@ -144,6 +154,38 @@ public function testBeforeSaveAttributeFileName() $this->assertEquals('test123.jpg', $object->getTestAttribute()); } + public function testBeforeSaveAttributeFileNameOutsideOfCategoryDir() + { + $model = $this->objectManager->getObject(\Magento\Catalog\Model\Category\Attribute\Backend\Image::class, [ + 'filesystem' => $this->filesystem + ]); + + $model->setAttribute($this->attribute); + + $this->filesystem + ->expects($this->once()) + ->method('getUri') + ->with(DirectoryList::MEDIA) + ->willReturn('pub/media'); + + $object = new \Magento\Framework\DataObject([ + 'test_attribute' => [ + [ + 'name' => '/test123.jpg', + 'url' => '/pub/media/wysiwyg/test123.jpg', + ] + ] + ]); + + $model->beforeSave($object); + + $this->assertEquals('/pub/media/wysiwyg/test123.jpg', $object->getTestAttribute()); + $this->assertEquals( + [['name' => '/pub/media/wysiwyg/test123.jpg', 'url' => '/pub/media/wysiwyg/test123.jpg']], + $object->getData('_additional_data_test_attribute') + ); + } + public function testBeforeSaveTemporaryAttribute() { $model = $this->objectManager->getObject(\Magento\Catalog\Model\Category\Attribute\Backend\Image::class); diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Category/FileInfoTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Category/FileInfoTest.php index 0e8777b5c6f9e..8ca823127e66c 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Category/FileInfoTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Category/FileInfoTest.php @@ -10,6 +10,7 @@ use Magento\Framework\File\Mime; use Magento\Framework\Filesystem; use Magento\Framework\Filesystem\Directory\WriteInterface; +use Magento\Framework\Filesystem\Directory\ReadInterface; class FileInfoTest extends \PHPUnit\Framework\TestCase { @@ -28,6 +29,11 @@ class FileInfoTest extends \PHPUnit\Framework\TestCase */ private $mediaDirectory; + /** + * @var ReadInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $baseDirectory; + /** * @var FileInfo */ @@ -38,6 +44,9 @@ protected function setUp() $this->mediaDirectory = $this->getMockBuilder(WriteInterface::class) ->getMockForAbstractClass(); + $this->baseDirectory = $this->getMockBuilder(ReadInterface::class) + ->getMockForAbstractClass(); + $this->filesystem = $this->getMockBuilder(Filesystem::class) ->disableOriginalConstructor() ->getMock(); @@ -46,10 +55,20 @@ protected function setUp() ->with(DirectoryList::MEDIA) ->willReturn($this->mediaDirectory); + $this->filesystem->expects($this->any()) + ->method('getDirectoryRead') + ->with(DirectoryList::ROOT) + ->willReturn($this->baseDirectory); + $this->mime = $this->getMockBuilder(Mime::class) ->disableOriginalConstructor() ->getMock(); + $this->baseDirectory->expects($this->any()) + ->method('getAbsolutePath') + ->with(null) + ->willReturn('/a/b/c'); + $this->model = new FileInfo( $this->filesystem, $this->mime @@ -58,16 +77,24 @@ protected function setUp() public function testGetMimeType() { - $mediaPath = '/catalog/category'; - $fileName = '/filename.ext1'; - $absoluteFilePath = '/absolute_path/catalog/category/filename.ext1'; + $absoluteFilePath = '/a/b/c/pub/media/catalog/category/filename.ext1'; $expected = 'ext1'; - $this->mediaDirectory->expects($this->once()) + $this->mediaDirectory->expects($this->at(0)) + ->method('getAbsolutePath') + ->with(null) + ->willReturn('/a/b/c/pub/media'); + + $this->mediaDirectory->expects($this->at(1)) + ->method('getAbsolutePath') + ->with(null) + ->willReturn('/a/b/c/pub/media'); + + $this->mediaDirectory->expects($this->at(2)) ->method('getAbsolutePath') - ->with($mediaPath. '/' . ltrim($fileName, '/')) + ->with('/catalog/category/filename.ext1') ->willReturn($absoluteFilePath); $this->mime->expects($this->once()) @@ -86,6 +113,11 @@ public function testGetStat() $expected = ['size' => 1]; + $this->mediaDirectory->expects($this->any()) + ->method('getAbsolutePath') + ->with(null) + ->willReturn('/a/b/c/pub/media'); + $this->mediaDirectory->expects($this->once()) ->method('stat') ->with($mediaPath . $fileName) @@ -104,6 +136,11 @@ public function testIsExist() $fileName = '/filename.ext1'; + $this->mediaDirectory->expects($this->any()) + ->method('getAbsolutePath') + ->with(null) + ->willReturn('/a/b/c/pub/media'); + $this->mediaDirectory->expects($this->once()) ->method('isExist') ->with($mediaPath . $fileName) diff --git a/app/code/Magento/Catalog/Test/Unit/Model/CategoryLinkRepositoryTest.php b/app/code/Magento/Catalog/Test/Unit/Model/CategoryLinkRepositoryTest.php index 6c8951c3ca672..b42262f1f0384 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/CategoryLinkRepositoryTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/CategoryLinkRepositoryTest.php @@ -145,7 +145,7 @@ public function testDeleteByIdsWithCouldNotSaveException() /** * @expectedException \Magento\Framework\Exception\InputException - * @expectedExceptionMessage Category does not contain specified product + * @expectedExceptionMessage The category doesn't contain the specified product. */ public function testDeleteWithInputException() { diff --git a/app/code/Magento/Catalog/Test/Unit/Model/CategoryTest.php b/app/code/Magento/Catalog/Test/Unit/Model/CategoryTest.php index d96ac4bfaab0a..9f5f3313c6859 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/CategoryTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/CategoryTest.php @@ -7,7 +7,7 @@ namespace Magento\Catalog\Test\Unit\Model; use Magento\Catalog\Model\Indexer; -use Magento\Catalog\Model\Category; +use Magento\Eav\Model\Entity\GetCustomAttributeCodesInterface; /** * @SuppressWarnings(PHPMD.TooManyFields) @@ -120,6 +120,11 @@ class CategoryTest extends \PHPUnit\Framework\TestCase */ private $objectManager; + /** + * @var GetCustomAttributeCodesInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $getCustomAttributeCodes; + protected function setUp() { $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); @@ -160,6 +165,10 @@ protected function setUp() ); $this->attributeValueFactory = $this->getMockBuilder(\Magento\Framework\Api\AttributeValueFactory::class) ->disableOriginalConstructor()->getMock(); + $this->getCustomAttributeCodes = $this->getMockBuilder(GetCustomAttributeCodesInterface::class) + ->setMethods(['execute']) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); $this->category = $this->getCategoryModel(); } @@ -309,6 +318,7 @@ protected function getCategoryModel() 'indexerRegistry' => $this->indexerRegistry, 'metadataService' => $this->metadataServiceMock, 'customAttributeFactory' => $this->attributeValueFactory, + 'getCustomAttributeCodes' => $this->getCustomAttributeCodes ] ); } @@ -433,25 +443,15 @@ public function testGetCustomAttributes() { $nameAttributeCode = 'name'; $descriptionAttributeCode = 'description'; - $interfaceAttribute = $this->createMock(\Magento\Framework\Api\MetadataObjectInterface::class); - $interfaceAttribute->expects($this->once()) - ->method('getAttributeCode') - ->willReturn($nameAttributeCode); - $descriptionAttribute = $this->createMock(\Magento\Framework\Api\MetadataObjectInterface::class); - $descriptionAttribute->expects($this->once()) - ->method('getAttributeCode') - ->willReturn($descriptionAttributeCode); - $customAttributesMetadata = [$interfaceAttribute, $descriptionAttribute]; - - $this->metadataServiceMock->expects($this->once()) - ->method('getCustomAttributesMetadata') - ->willReturn($customAttributesMetadata); + $this->getCustomAttributeCodes->expects($this->exactly(3)) + ->method('execute') + ->willReturn([$descriptionAttributeCode]); $this->category->setData($nameAttributeCode, "sub"); - //The color attribute is not set, expect empty custom attribute array + //The description attribute is not set, expect empty custom attribute array $this->assertEquals([], $this->category->getCustomAttributes()); - //Set the color attribute; + //Set the description attribute; $this->category->setData($descriptionAttributeCode, "description"); $attributeValue = new \Magento\Framework\Api\AttributeValue(); $attributeValue2 = new \Magento\Framework\Api\AttributeValue(); diff --git a/app/code/Magento/Catalog/Test/Unit/Model/CollectionProviderTest.php b/app/code/Magento/Catalog/Test/Unit/Model/CollectionProviderTest.php index 9df0a6bc1eac0..d8931cbbfcf73 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/CollectionProviderTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/CollectionProviderTest.php @@ -101,7 +101,7 @@ public function testGetCollection() * Test exception when collection provider is not configured for product link type. * * @expectedException \Magento\Framework\Exception\NoSuchEntityException - * @expectedExceptionMessage Collection provider is not registered + * @expectedExceptionMessage The collection provider isn't registered. */ public function testGetCollectionWithMissingProviders() { diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Entity/GetCategoryCustomAttributeCodesTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Entity/GetCategoryCustomAttributeCodesTest.php new file mode 100644 index 0000000000000..465063dccd3d5 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Unit/Model/Entity/GetCategoryCustomAttributeCodesTest.php @@ -0,0 +1,66 @@ +baseCustomAttributeCodes = $this->getMockBuilder(GetCustomAttributeCodesInterface::class) + ->disableOriginalConstructor() + ->setMethods(['execute']) + ->getMockForAbstractClass(); + $objectManager = new ObjectManager($this); + $this->getCategoryCustomAttributeCodes = $objectManager->getObject( + GetCategoryCustomAttributeCodes::class, + ['baseCustomAttributeCodes' => $this->baseCustomAttributeCodes] + ); + } + + /** + * Test GetCategoryCustomAttributeCodes::execute() will return only custom category attribute codes. + */ + public function testExecute() + { + /** @var MetadataServiceInterface|\PHPUnit_Framework_MockObject_MockObject $metadataService */ + $metadataService = $this->getMockBuilder(MetadataServiceInterface::class) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + $this->baseCustomAttributeCodes->expects($this->once()) + ->method('execute') + ->with($this->identicalTo($metadataService)) + ->willReturn(['test_custom_attribute_code', 'name']); + $this->assertEquals( + ['test_custom_attribute_code'], + $this->getCategoryCustomAttributeCodes->execute($metadataService) + ); + } +} diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Entity/GetProductCustomAttributeCodesTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Entity/GetProductCustomAttributeCodesTest.php new file mode 100644 index 0000000000000..a37e1c6df0908 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Unit/Model/Entity/GetProductCustomAttributeCodesTest.php @@ -0,0 +1,66 @@ +baseCustomAttributeCodes = $this->getMockBuilder(GetCustomAttributeCodesInterface::class) + ->disableOriginalConstructor() + ->setMethods(['execute']) + ->getMockForAbstractClass(); + $objectManager = new ObjectManager($this); + $this->getProductCustomAttributeCodes = $objectManager->getObject( + GetProductCustomAttributeCodes::class, + ['baseCustomAttributeCodes' => $this->baseCustomAttributeCodes] + ); + } + + /** + * Test GetProductCustomAttributeCodes::execute() will return only custom product attribute codes. + */ + public function testExecute() + { + /** @var MetadataServiceInterface|\PHPUnit_Framework_MockObject_MockObject $metadataService */ + $metadataService = $this->getMockBuilder(MetadataServiceInterface::class) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + $this->baseCustomAttributeCodes->expects($this->once()) + ->method('execute') + ->with($this->identicalTo($metadataService)) + ->willReturn(['test_custom_attribute_code', 'name']); + $this->assertEquals( + ['test_custom_attribute_code'], + $this->getProductCustomAttributeCodes->execute($metadataService) + ); + } +} diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Locator/RegistryLocatorTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Locator/RegistryLocatorTest.php index fceb29295b6e1..b2810ddea2413 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Locator/RegistryLocatorTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Locator/RegistryLocatorTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Catalog\Test\Unit\Model\Locator; use Magento\Catalog\Api\Data\ProductInterface; @@ -83,7 +84,7 @@ public function testGetStore() /** * @expectedException \Magento\Framework\Exception\NotFoundException - * @expectedExceptionMessage Product was not registered + * @expectedExceptionMessage The product wasn't registered. */ public function testGetProductWithException() { @@ -92,7 +93,7 @@ public function testGetProductWithException() /** * @expectedException \Magento\Framework\Exception\NotFoundException - * @expectedExceptionMessage Store was not registered + * @expectedExceptionMessage The store wasn't registered. Verify the store and try again. */ public function testGetStoreWithException() { diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Product/Attribute/Frontend/ImageTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Product/Attribute/Frontend/ImageTest.php index 115a333a38b5b..3ceedddc2b713 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Product/Attribute/Frontend/ImageTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Product/Attribute/Frontend/ImageTest.php @@ -3,45 +3,71 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Catalog\Test\Unit\Model\Product\Attribute\Frontend; +use Magento\Catalog\Model\Product; +use Magento\Catalog\Model\Product\Attribute\Frontend\Image; +use Magento\Eav\Model\Entity\Attribute\AbstractAttribute; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Store\Model\Store; +use Magento\Store\Model\StoreManagerInterface; +use PHPUnit\Framework\TestCase; -class ImageTest extends \PHPUnit\Framework\TestCase +class ImageTest extends TestCase { /** - * @var \Magento\Catalog\Model\Product\Attribute\Frontend\Image + * @var Image */ private $model; - public function testGetUrl() + /** + * @dataProvider getUrlDataProvider + * @param string $expectedImage + * @param string $productImage + */ + public function testGetUrl(string $expectedImage, string $productImage) + { + $this->assertEquals($expectedImage, $this->model->getUrl($this->getMockedProduct($productImage))); + } + + /** + * Data provider for testGetUrl + * + * @return array + */ + public function getUrlDataProvider(): array { - $this->assertEquals('catalog/product/img.jpg', $this->model->getUrl($this->getMockedProduct())); + return [ + ['catalog/product/img.jpg', 'img.jpg'], + ['catalog/product/img.jpg', '/img.jpg'], + ]; } protected function setUp() { $helper = new ObjectManager($this); $this->model = $helper->getObject( - \Magento\Catalog\Model\Product\Attribute\Frontend\Image::class, + Image::class, ['storeManager' => $this->getMockedStoreManager()] ); $this->model->setAttribute($this->getMockedAttribute()); } /** - * @return \Magento\Catalog\Model\Product + * @param string $productImage + * @return Product */ - private function getMockedProduct() + private function getMockedProduct(string $productImage): Product { - $mockBuilder = $this->getMockBuilder(\Magento\Catalog\Model\Product::class); + $mockBuilder = $this->getMockBuilder(Product::class); $mock = $mockBuilder->setMethods(['getData', 'getStore', '__wakeup']) ->disableOriginalConstructor() ->getMock(); $mock->expects($this->any()) ->method('getData') - ->will($this->returnValue('img.jpg')); + ->will($this->returnValue($productImage)); $mock->expects($this->any()) ->method('getStore'); @@ -50,13 +76,13 @@ private function getMockedProduct() } /** - * @return \Magento\Store\Model\StoreManagerInterface + * @return StoreManagerInterface */ - private function getMockedStoreManager() + private function getMockedStoreManager(): StoreManagerInterface { $mockedStore = $this->getMockedStore(); - $mockBuilder = $this->getMockBuilder(\Magento\Store\Model\StoreManagerInterface::class); + $mockBuilder = $this->getMockBuilder(StoreManagerInterface::class); $mock = $mockBuilder->setMethods(['getStore']) ->disableOriginalConstructor() ->getMockForAbstractClass(); @@ -69,11 +95,11 @@ private function getMockedStoreManager() } /** - * @return \Magento\Store\Model\Store + * @return Store */ - private function getMockedStore() + private function getMockedStore(): Store { - $mockBuilder = $this->getMockBuilder(\Magento\Store\Model\Store::class); + $mockBuilder = $this->getMockBuilder(Store::class); $mock = $mockBuilder->setMethods(['getBaseUrl', '__wakeup']) ->disableOriginalConstructor() ->getMockForAbstractClass(); @@ -86,11 +112,11 @@ private function getMockedStore() } /** - * @return \Magento\Eav\Model\Entity\Attribute\AbstractAttribute + * @return AbstractAttribute */ - private function getMockedAttribute() + private function getMockedAttribute(): AbstractAttribute { - $mockBuilder = $this->getMockBuilder(\Magento\Eav\Model\Entity\Attribute\AbstractAttribute::class); + $mockBuilder = $this->getMockBuilder(AbstractAttribute::class); $mockBuilder->setMethods(['getAttributeCode', '__wakeup']); $mockBuilder->disableOriginalConstructor(); $mock = $mockBuilder->getMockForAbstractClass(); diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Product/Attribute/RepositoryTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Product/Attribute/RepositoryTest.php index 03bac570c36ad..3cc6f94d58c29 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Product/Attribute/RepositoryTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Product/Attribute/RepositoryTest.php @@ -207,7 +207,7 @@ public function testSaveNoSuchEntityException() /** * @expectedException \Magento\Framework\Exception\InputException - * @expectedExceptionMessage frontend_label is a required field. + * @expectedExceptionMessage "frontend_label" is required. Enter and try again. */ public function testSaveInputExceptionRequiredField() { diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Product/Attribute/SetManagementTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Product/Attribute/SetManagementTest.php index 57168f2c1270c..1f4c4dd378206 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Product/Attribute/SetManagementTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Product/Attribute/SetManagementTest.php @@ -4,6 +4,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Catalog\Test\Unit\Model\Product\Attribute; class SetManagementTest extends \PHPUnit\Framework\TestCase @@ -71,7 +72,6 @@ public function testCreate() /** * @expectedException \Magento\Framework\Exception\StateException - * @expectedExceptionMessage Can not create attribute set based on non product attribute set. */ public function testCreateNonProductAttributeSet() { @@ -91,5 +91,9 @@ public function testCreateNonProductAttributeSet() ->willReturn($typeMock); $skeletonSetMock->expects($this->once())->method('getEntityTypeId')->willReturn(3); $this->model->create($attributeSetMock, $skeletonId); + + $this->expectExceptionMessage( + "The attribute set couldn't be created because it's based on a non-product attribute set." + ); } } diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Product/Gallery/GalleryManagementTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Product/Gallery/GalleryManagementTest.php index cf49d10416d82..9fafbc9d9675b 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Product/Gallery/GalleryManagementTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Product/Gallery/GalleryManagementTest.php @@ -65,7 +65,7 @@ protected function setUp() /** * @expectedException \Magento\Framework\Exception\InputException - * @expectedExceptionMessage The image content is not valid. + * @expectedExceptionMessage The image content is invalid. Verify the content and try again. */ public function testCreateWithInvalidImageException() { @@ -82,7 +82,7 @@ public function testCreateWithInvalidImageException() /** * @expectedException \Magento\Framework\Exception\StateException - * @expectedExceptionMessage Cannot save product. + * @expectedExceptionMessage The product can't be saved. */ public function testCreateWithCannotSaveException() { @@ -136,7 +136,7 @@ public function testCreate() /** * @expectedException \Magento\Framework\Exception\NoSuchEntityException - * @expectedExceptionMessage There is no image with provided ID. + * @expectedExceptionMessage No image with the provided ID was found. Verify the ID and try again. */ public function testUpdateWithNonExistingImage() { @@ -157,7 +157,7 @@ public function testUpdateWithNonExistingImage() /** * @expectedException \Magento\Framework\Exception\StateException - * @expectedExceptionMessage Cannot save product. + * @expectedExceptionMessage The product can't be saved. */ public function testUpdateWithCannotSaveException() { @@ -216,7 +216,7 @@ public function testUpdate() /** * @expectedException \Magento\Framework\Exception\NoSuchEntityException - * @expectedExceptionMessage There is no image with provided ID. + * @expectedExceptionMessage No image with the provided ID was found. Verify the ID and try again. */ public function testRemoveWithNonExistingImage() { @@ -253,7 +253,7 @@ public function testRemove() /** * @expectedException \Magento\Framework\Exception\NoSuchEntityException - * @expectedExceptionMessage Such product doesn't exist + * @expectedExceptionMessage The product doesn't exist. Verify and try again. */ public function testGetWithNonExistingProduct() { @@ -266,7 +266,7 @@ public function testGetWithNonExistingProduct() /** * @expectedException \Magento\Framework\Exception\NoSuchEntityException - * @expectedExceptionText Such image doesn't exist + * @expectedExceptionText The image doesn't exist. Verify and try again. */ public function testGetWithNonExistingImage() { diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Product/Option/RepositoryTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Product/Option/RepositoryTest.php index ec6aa9d8db83a..fd7283903869d 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Product/Option/RepositoryTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Product/Option/RepositoryTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Catalog\Test\Unit\Model\Product\Option; use \Magento\Catalog\Model\Product\Option\Repository; @@ -199,7 +200,7 @@ public function testDeleteByIdentifierWhenCannotRemoveOption() /** * @expectedException \Magento\Framework\Exception\CouldNotSaveException - * @expectedExceptionMessage ProductSku should be specified + * @expectedExceptionMessage The ProductSku is empty. Set the ProductSku and try again. */ public function testSaveCouldNotSaveException() { diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Product/Price/SpecialPriceStorageTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Product/Price/SpecialPriceStorageTest.php index c2337d1abdb6a..e2bd4e9c10b97 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Product/Price/SpecialPriceStorageTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Product/Price/SpecialPriceStorageTest.php @@ -178,7 +178,7 @@ public function testUpdateWithInvalidSku() ->with( 1, __( - 'Requested product doesn\'t exist. ' + 'The product that was requested doesn\'t exist. Verify the product and try again. ' . 'Row ID: SKU = %SKU, Store ID: %storeId, Price From: %priceFrom, Price To: %priceTo.', [ 'SKU' => 'sku_1', diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Product/PriceModifierTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Product/PriceModifierTest.php index 1d0f89f320772..754d80302d410 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Product/PriceModifierTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Product/PriceModifierTest.php @@ -54,7 +54,7 @@ protected function setUp() /** * @expectedException \Magento\Framework\Exception\NoSuchEntityException - * @expectedMessage This product doesn't have tier price + * @expectedMessage Tier price is unavailable for this product. */ public function testRemoveWhenTierPricesNotExists() { diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Product/TierPriceManagementTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Product/TierPriceManagementTest.php index c57040f24266d..371696d08d00e 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Product/TierPriceManagementTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Product/TierPriceManagementTest.php @@ -192,7 +192,7 @@ public function testSuccessDeleteTierPrice() /** * @expectedException \Magento\Framework\Exception\NoSuchEntityException - * @message Such product doesn't exist + * @message The product doesn't exist. Verify and try again. */ public function testDeleteTierPriceFromNonExistingProduct() { @@ -328,7 +328,7 @@ public function testSetUpdatedPriceWithGlobalPriceScope() /** * @expectedException \Magento\Framework\Exception\InputException - * @expectedExceptionMessage Values of following attributes are invalid: attr1, attr2 + * @expectedExceptionMessage Values in the attr1, attr2 attributes are invalid. Verify the values and try again. */ public function testSetThrowsExceptionIfDoesntValidate() { diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ProductAttributeGroupRepositoryTest.php b/app/code/Magento/Catalog/Test/Unit/Model/ProductAttributeGroupRepositoryTest.php index 14f0cbdf9ab68..5c3e9a429317c 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/ProductAttributeGroupRepositoryTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/ProductAttributeGroupRepositoryTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Catalog\Test\Unit\Model; class ProductAttributeGroupRepositoryTest extends \PHPUnit\Framework\TestCase @@ -121,7 +122,7 @@ public function testDelete() /** * @expectedException \Magento\Framework\Exception\StateException - * @expectedExceptionMessage Attribute group that contains system attributes can not be deleted + * @expectedExceptionMessage The attribute group can't be deleted because it contains system attributes. */ public function testDeleteThrowsExceptionIfGroupHasSystemAttributes() { diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ProductLink/ManagementTest.php b/app/code/Magento/Catalog/Test/Unit/Model/ProductLink/ManagementTest.php index f9b3af4c7a3bc..ab52d87f56291 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/ProductLink/ManagementTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/ProductLink/ManagementTest.php @@ -79,7 +79,7 @@ public function testGetLinkedItemsByType() /** * @expectedException \Magento\Framework\Exception\NoSuchEntityException - * @expectedExceptionMessage Unknown link type: bad type + * @expectedExceptionMessage The "bad type" link type is unknown. Verify the type and try again. */ public function testGetLinkedItemsByTypeWithWrongType() { @@ -132,7 +132,7 @@ public function testSetProductLinks() /** * @expectedException \Magento\Framework\Exception\InputException - * @expectedExceptionMessage linkType is a required field. + * @expectedExceptionMessage "linkType" is required. Enter and try again. */ public function testSetProductLinksWithoutLinkTypeInLink() { @@ -154,7 +154,7 @@ public function testSetProductLinksWithoutLinkTypeInLink() /** * @expectedException \Magento\Framework\Exception\NoSuchEntityException - * @expectedExceptionMessage Provided link type "bad type" does not exist + * @expectedExceptionMessage The "bad type" link type wasn't found. Verify the type and try again. */ public function testSetProductLinksThrowExceptionIfProductLinkTypeDoesNotExist() { @@ -181,7 +181,7 @@ public function testSetProductLinksThrowExceptionIfProductLinkTypeDoesNotExist() /** * @expectedException \Magento\Framework\Exception\NoSuchEntityException - * @expectedExceptionMessage Requested product doesn't exist + * @expectedExceptionMessage The product that was requested doesn't exist. Verify the product and try again. */ public function testSetProductLinksNoProductException() { @@ -205,7 +205,9 @@ public function testSetProductLinksNoProductException() ->method('get') ->will( $this->throwException( - new \Magento\Framework\Exception\NoSuchEntityException(__('Requested product doesn\'t exist')) + new \Magento\Framework\Exception\NoSuchEntityException( + __("The product that was requested doesn't exist. Verify the product and try again.") + ) ) ); $this->model->setProductLinks($productSku, $links); @@ -213,7 +215,7 @@ public function testSetProductLinksNoProductException() /** * @expectedException \Magento\Framework\Exception\CouldNotSaveException - * @expectedExceptionMessage Invalid data provided for linked products + * @expectedExceptionMessage The linked products data is invalid. Verify the data and try again. */ public function testSetProductLinksInvalidDataException() { diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ProductLink/RepositoryTest.php b/app/code/Magento/Catalog/Test/Unit/Model/ProductLink/RepositoryTest.php index 56aca8d205302..88815f562b5fe 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/ProductLink/RepositoryTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/ProductLink/RepositoryTest.php @@ -137,7 +137,7 @@ public function testSave() /** * @expectedException \Magento\Framework\Exception\CouldNotSaveException - * @expectedExceptionMessage Invalid data provided for linked products + * @expectedExceptionMessage The linked products data is invalid. Verify the data and try again. */ public function testSaveWithException() { @@ -208,7 +208,7 @@ public function testDelete() /** * @expectedException \Magento\Framework\Exception\CouldNotSaveException - * @expectedExceptionMessage Invalid data provided for linked products + * @expectedExceptionMessage The linked products data is invalid. Verify the data and try again. */ public function testDeleteWithInvalidDataException() { diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ProductRepositoryTest.php b/app/code/Magento/Catalog/Test/Unit/Model/ProductRepositoryTest.php index 7470f1fc71c8e..8d65153d7ba20 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/ProductRepositoryTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/ProductRepositoryTest.php @@ -301,7 +301,7 @@ function ($value) { /** * @expectedException \Magento\Framework\Exception\NoSuchEntityException - * @expectedExceptionMessage Requested product doesn't exist + * @expectedExceptionMessage The product that was requested doesn't exist. Verify the product and try again. */ public function testGetAbsentProduct() { @@ -367,7 +367,7 @@ public function testGetWithSetStoreId() /** * @expectedException \Magento\Framework\Exception\NoSuchEntityException - * @expectedExceptionMessage Requested product doesn't exist + * @expectedExceptionMessage The product that was requested doesn't exist. Verify the product and try again. */ public function testGetByIdAbsentProduct() { @@ -592,7 +592,7 @@ public function testSaveNew() /** * @expectedException \Magento\Framework\Exception\CouldNotSaveException - * @expectedExceptionMessage Unable to save product + * @expectedExceptionMessage The product was unable to be saved. Please try again. */ public function testSaveUnableToSaveException() { @@ -707,7 +707,7 @@ public function testDelete() /** * @expectedException \Magento\Framework\Exception\StateException - * @expectedExceptionMessage Unable to remove product product-42 + * @expectedExceptionMessage The "product-42" product couldn't be removed. */ public function testDeleteException() { diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ProductTest.php b/app/code/Magento/Catalog/Test/Unit/Model/ProductTest.php index 8d7e3dfb3f2fd..74a71a2828e1d 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/ProductTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/ProductTest.php @@ -9,6 +9,7 @@ use Magento\Catalog\Api\Data\ProductExtensionFactory; use Magento\Catalog\Api\Data\ProductExtensionInterface; use Magento\Catalog\Model\Product; +use Magento\Eav\Model\Entity\GetCustomAttributeCodesInterface; use Magento\Framework\Api\Data\ImageContentInterface; use Magento\Framework\Api\ExtensibleDataInterface; use Magento\Framework\Api\ExtensionAttributesFactory; @@ -198,6 +199,11 @@ class ProductTest extends \PHPUnit\Framework\TestCase */ private $extensionAttributes; + /** + * @var GetCustomAttributeCodesInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $getCustomAttributeCodes; + /** * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ @@ -369,6 +375,10 @@ protected function setUp() ->expects($this->any()) ->method('create') ->willReturn($this->extensionAttributes); + $this->getCustomAttributeCodes = $this->getMockBuilder(GetCustomAttributeCodesInterface::class) + ->disableOriginalConstructor() + ->setMethods(['execute']) + ->getMockForAbstractClass(); $this->objectManagerHelper = new ObjectManagerHelper($this); $this->model = $this->objectManagerHelper->getObject( @@ -398,7 +408,8 @@ protected function setUp() 'catalogProductMediaConfig' => $this->mediaConfig, '_filesystem' => $this->filesystemMock, '_collectionFactory' => $this->collectionFactoryMock, - 'data' => ['id' => 1] + 'data' => ['id' => 1], + 'getCustomAttributeCodes' => $this->getCustomAttributeCodes ] ); } @@ -1269,19 +1280,9 @@ public function testGetCustomAttributes() { $priceCode = 'price'; $colorAttributeCode = 'color'; - $interfaceAttribute = $this->createMock(\Magento\Framework\Api\MetadataObjectInterface::class); - $interfaceAttribute->expects($this->once()) - ->method('getAttributeCode') - ->willReturn($priceCode); - $colorAttribute = $this->createMock(\Magento\Framework\Api\MetadataObjectInterface::class); - $colorAttribute->expects($this->once()) - ->method('getAttributeCode') - ->willReturn($colorAttributeCode); - $customAttributesMetadata = [$interfaceAttribute, $colorAttribute]; - - $this->metadataServiceMock->expects($this->once()) - ->method('getCustomAttributesMetadata') - ->willReturn($customAttributesMetadata); + $this->getCustomAttributeCodes->expects($this->exactly(3)) + ->method('execute') + ->willReturn([$colorAttributeCode]); $this->model->setData($priceCode, 10); //The color attribute is not set, expect empty custom attribute array diff --git a/app/code/Magento/Catalog/etc/di.xml b/app/code/Magento/Catalog/etc/di.xml index 29b1cdfc7d15a..a7502d12e1f7b 100644 --- a/app/code/Magento/Catalog/etc/di.xml +++ b/app/code/Magento/Catalog/etc/di.xml @@ -143,6 +143,12 @@ Magento\Catalog\Model\Product\Attribute\Source\Status\Proxy Magento\Catalog\Model\Product\Link\Proxy + Magento\Catalog\Model\Entity\GetProductCustomAttributeCodes + + + + + Magento\Catalog\Model\Entity\GetCategoryCustomAttributeCodes diff --git a/app/code/Magento/Catalog/etc/module.xml b/app/code/Magento/Catalog/etc/module.xml index 26ed173420adb..96deaa08bbfae 100644 --- a/app/code/Magento/Catalog/etc/module.xml +++ b/app/code/Magento/Catalog/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + 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 57474f835125e..130e7b169ccfe 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 @@ -151,32 +151,35 @@ true - + category - ui/form/element/uploader/uploader + ui/form/element/uploader/image string true false - + false Magento_Catalog/image-preview + Media Gallery + jpg jpeg gif png + 4194304 - + - + diff --git a/app/code/Magento/Catalog/view/adminhtml/ui_component/design_config_form.xml b/app/code/Magento/Catalog/view/adminhtml/ui_component/design_config_form.xml index 96055b73d363b..1e60823929770 100644 --- a/app/code/Magento/Catalog/view/adminhtml/ui_component/design_config_form.xml +++ b/app/code/Magento/Catalog/view/adminhtml/ui_component/design_config_form.xml @@ -22,10 +22,10 @@ Allowed file types: jpeg, gif, png. - fileUploader + imageUploader - + jpg jpeg gif png 2097152 @@ -33,7 +33,7 @@ theme/design_config_fileUploader/save - + @@ -80,12 +80,11 @@ - Allowed file types: jpeg, gif, png. - fileUploader + imageUploader - + jpg jpeg gif png 2097152 @@ -93,7 +92,7 @@ theme/design_config_fileUploader/save - + @@ -140,12 +139,11 @@ - Allowed file types: jpeg, gif, png. - fileUploader + imageUploader - + jpg jpeg gif png 2097152 @@ -153,7 +151,7 @@ theme/design_config_fileUploader/save - + diff --git a/app/code/Magento/Catalog/view/adminhtml/web/js/custom-options.js b/app/code/Magento/Catalog/view/adminhtml/web/js/custom-options.js index 5aa0a163c0d41..4d0448f8f2a1e 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/js/custom-options.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/js/custom-options.js @@ -166,7 +166,7 @@ define([ if (request.length === 0) { if (!massActionTrigger) { alert({ - content: $.mage.__('Please select items.') + content: $.mage.__('An item needs to be selected. Select and try again.') }); } diff --git a/app/code/Magento/Catalog/view/adminhtml/web/template/field-wysiwyg.html b/app/code/Magento/Catalog/view/adminhtml/web/template/field-wysiwyg.html new file mode 100644 index 0000000000000..c9340eab2f2e6 --- /dev/null +++ b/app/code/Magento/Catalog/view/adminhtml/web/template/field-wysiwyg.html @@ -0,0 +1,46 @@ + +
+ +
+ + +
+ + + + +
+ + + + + +
+
+ + diff --git a/app/code/Magento/Catalog/view/adminhtml/web/template/image-preview.html b/app/code/Magento/Catalog/view/adminhtml/web/template/image-preview.html index a6a1b3e5b05e8..04b4990f9cace 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/template/image-preview.html +++ b/app/code/Magento/Catalog/view/adminhtml/web/template/image-preview.html @@ -5,8 +5,9 @@ */ -->
-
- +
+ +
@@ -30,7 +32,7 @@
- x + x,
diff --git a/app/code/Magento/CatalogAnalytics/etc/module.xml b/app/code/Magento/CatalogAnalytics/etc/module.xml index 7974598e17a59..613af18d1832c 100644 --- a/app/code/Magento/CatalogAnalytics/etc/module.xml +++ b/app/code/Magento/CatalogAnalytics/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/CatalogGraphQl/etc/module.xml b/app/code/Magento/CatalogGraphQl/etc/module.xml index e183010353532..1f7aca7667425 100644 --- a/app/code/Magento/CatalogGraphQl/etc/module.xml +++ b/app/code/Magento/CatalogGraphQl/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/CatalogImportExport/etc/module.xml b/app/code/Magento/CatalogImportExport/etc/module.xml index 517ffc0fa393d..9e2c801d27b46 100644 --- a/app/code/Magento/CatalogImportExport/etc/module.xml +++ b/app/code/Magento/CatalogImportExport/etc/module.xml @@ -6,6 +6,6 @@ */ --> - + diff --git a/app/code/Magento/CatalogInventory/Model/Quote/Item/QuantityValidator.php b/app/code/Magento/CatalogInventory/Model/Quote/Item/QuantityValidator.php index 3fb0790640ffc..8e0c749be2d1d 100644 --- a/app/code/Magento/CatalogInventory/Model/Quote/Item/QuantityValidator.php +++ b/app/code/Magento/CatalogInventory/Model/Quote/Item/QuantityValidator.php @@ -5,6 +5,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\CatalogInventory\Model\Quote\Item; use Magento\CatalogInventory\Api\Data\StockItemInterface; @@ -114,7 +115,7 @@ public function validate(Observer $observer) /* @var \Magento\CatalogInventory\Model\Stock\Item $stockItem */ $stockItem = $this->stockRegistry->getStockItem($product->getId(), $product->getStore()->getWebsiteId()); if (!$stockItem instanceof StockItemInterface) { - throw new LocalizedException(__('The stock item for Product is not valid.')); + throw new LocalizedException(__('The Product stock item is invalid. Verify the stock item and try again.')); } /* @var \Magento\CatalogInventory\Api\Data\StockStatusInterface $stockStatus */ diff --git a/app/code/Magento/CatalogInventory/Model/Stock/StockItemRepository.php b/app/code/Magento/CatalogInventory/Model/Stock/StockItemRepository.php index e5154a10f0a19..6928ab9947059 100644 --- a/app/code/Magento/CatalogInventory/Model/Stock/StockItemRepository.php +++ b/app/code/Magento/CatalogInventory/Model/Stock/StockItemRepository.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\CatalogInventory\Model\Stock; use Magento\Catalog\Model\ProductFactory; @@ -183,7 +184,7 @@ public function save(\Magento\CatalogInventory\Api\Data\StockItemInterface $stoc $this->resource->save($stockItem); } catch (\Exception $exception) { - throw new CouldNotSaveException(__('Unable to save Stock Item'), $exception); + throw new CouldNotSaveException(__('The stock item was unable to be saved. Please try again.'), $exception); } return $stockItem; } @@ -196,7 +197,9 @@ public function get($stockItemId) $stockItem = $this->stockItemFactory->create(); $this->resource->load($stockItem, $stockItemId); if (!$stockItem->getItemId()) { - throw new NoSuchEntityException(__('Stock Item with id "%1" does not exist.', $stockItemId)); + throw new NoSuchEntityException( + __('The stock item with the "%1" ID wasn\'t found. Verify the ID and try again.', $stockItemId) + ); } return $stockItem; } @@ -225,7 +228,10 @@ public function delete(StockItemInterface $stockItem) $this->getStockRegistryStorage()->removeStockStatus($stockItem->getProductId()); } catch (\Exception $exception) { throw new CouldNotDeleteException( - __('Unable to remove Stock Item with id "%1"', $stockItem->getItemId()), + __( + 'The stock item with the "%1" ID wasn\'t found. Verify the ID and try again.', + $stockItem->getItemId() + ), $exception ); } @@ -242,7 +248,7 @@ public function deleteById($id) $this->delete($stockItem); } catch (\Exception $exception) { throw new CouldNotDeleteException( - __('Unable to remove Stock Item with id "%1"', $id), + __('The stock item with the "%1" ID wasn\'t found. Verify the ID and try again.', $id), $exception ); } diff --git a/app/code/Magento/CatalogInventory/Model/Stock/StockRepository.php b/app/code/Magento/CatalogInventory/Model/Stock/StockRepository.php index 0e7add8a95181..d4d82dd35ee2b 100644 --- a/app/code/Magento/CatalogInventory/Model/Stock/StockRepository.php +++ b/app/code/Magento/CatalogInventory/Model/Stock/StockRepository.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\CatalogInventory\Model\Stock; use Magento\CatalogInventory\Api\Data\StockCollectionInterfaceFactory; @@ -84,7 +85,7 @@ public function save(StockInterface $stock) try { $this->resource->save($stock); } catch (\Exception $exception) { - throw new CouldNotSaveException(__('Unable to save Stock'), $exception); + throw new CouldNotSaveException(__('The stock was unable to be saved. Please try again.'), $exception); } return $stock; } @@ -99,7 +100,9 @@ public function get($stockId) $stock = $this->stockFactory->create(); $this->resource->load($stock, $stockId); if (!$stock->getId()) { - throw new NoSuchEntityException(__('Stock with id "%1" does not exist.', $stockId)); + throw new NoSuchEntityException( + __('The stock with the "%1" ID wasn\'t found. Verify the ID and try again.', $stockId) + ); } return $stock; } diff --git a/app/code/Magento/CatalogInventory/Model/Stock/StockStatusRepository.php b/app/code/Magento/CatalogInventory/Model/Stock/StockStatusRepository.php index 3dfc4c49a5d63..4db1b07ea517d 100644 --- a/app/code/Magento/CatalogInventory/Model/Stock/StockStatusRepository.php +++ b/app/code/Magento/CatalogInventory/Model/Stock/StockStatusRepository.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\CatalogInventory\Model\Stock; use Magento\CatalogInventory\Api\Data\StockStatusCollectionInterfaceFactory; @@ -82,7 +83,10 @@ public function save(StockStatusInterface $stockStatus) try { $this->resource->save($stockStatus); } catch (\Exception $exception) { - throw new CouldNotSaveException(__('Unable to save Stock Status'), $exception); + throw new CouldNotSaveException( + __('The stock status was unable to be saved. Please try again.'), + $exception + ); } return $stockStatus; } diff --git a/app/code/Magento/CatalogInventory/Model/StockItemValidator.php b/app/code/Magento/CatalogInventory/Model/StockItemValidator.php index 2cc4832159d55..5d218a4f06516 100644 --- a/app/code/Magento/CatalogInventory/Model/StockItemValidator.php +++ b/app/code/Magento/CatalogInventory/Model/StockItemValidator.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\CatalogInventory\Model; use Magento\Catalog\Api\Data\ProductInterface; @@ -53,21 +54,34 @@ public function validate(ProductInterface $product, StockItemInterface $stockIte $stockId = $stockItem->getStockId(); if ($stockId !== null && $stockId != $defaultStockId) { throw new LocalizedException( - __('Invalid stock id: %1. Only default stock with id %2 allowed', $stockId, $defaultStockId) + __( + 'The "%1" value is invalid for stock ID. Enter stock with a default value of %2 to try again.', + $stockId, + $defaultStockId + ) ); } $stockItemId = $stockItem->getItemId(); if ($stockItemId !== null && (!is_numeric($stockItemId) || $stockItemId <= 0)) { throw new LocalizedException( - __('Invalid stock item id: %1. Should be null or numeric value greater than 0', $stockItemId) + __( + 'The "%1" value is invalid for stock item ID. ' + . 'Enter either zero or a number than zero to try again.', + $stockItemId + ) ); } $defaultStockItemId = $this->stockRegistry->getStockItem($product->getId())->getItemId(); if ($defaultStockItemId && $stockItemId !== null && $defaultStockItemId != $stockItemId) { throw new LocalizedException( - __('Invalid stock item id: %1. Assigned stock item id is %2', $stockItemId, $defaultStockItemId) + __( + 'The "%1" value is invalid for stock item ID. ' + . 'Use the stock item ID\'s assigned "%2" value and try again.', + $stockItemId, + $defaultStockItemId + ) ); } } diff --git a/app/code/Magento/CatalogInventory/Model/StockRegistry.php b/app/code/Magento/CatalogInventory/Model/StockRegistry.php index d688132fdb916..f60edee330195 100644 --- a/app/code/Magento/CatalogInventory/Model/StockRegistry.php +++ b/app/code/Magento/CatalogInventory/Model/StockRegistry.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\CatalogInventory\Model; use Magento\Catalog\Model\ProductFactory; @@ -192,7 +193,7 @@ protected function resolveProductId($productSku) if (!$productId) { throw new \Magento\Framework\Exception\NoSuchEntityException( __( - 'Product with SKU "%1" does not exist', + 'The Product with the "%1" SKU doesn\'t exist.', $productSku ) ); diff --git a/app/code/Magento/CatalogInventory/Model/System/Config/Backend/Qtyincrements.php b/app/code/Magento/CatalogInventory/Model/System/Config/Backend/Qtyincrements.php index f34d765b0e5f0..3c4586c9eddd1 100644 --- a/app/code/Magento/CatalogInventory/Model/System/Config/Backend/Qtyincrements.php +++ b/app/code/Magento/CatalogInventory/Model/System/Config/Backend/Qtyincrements.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\CatalogInventory\Model\System\Config\Backend; use Magento\Framework\Exception\LocalizedException; @@ -22,7 +23,9 @@ public function beforeSave() { $value = $this->getValue(); if (floor($value) != $value) { - throw new LocalizedException(__('Decimal qty increments is not allowed.')); + throw new LocalizedException( + __("Quantity increments can't use decimals. Enter a new increment and try again.") + ); } } } diff --git a/app/code/Magento/CatalogInventory/Setup/Patch/Data/ConvertSerializedDataToJson.php b/app/code/Magento/CatalogInventory/Setup/Patch/Data/ConvertSerializedDataToJson.php new file mode 100644 index 0000000000000..07edb435743c0 --- /dev/null +++ b/app/code/Magento/CatalogInventory/Setup/Patch/Data/ConvertSerializedDataToJson.php @@ -0,0 +1,127 @@ +moduleDataSetup = $moduleDataSetup; + $this->fieldDataConverterFactory = $fieldDataConverterFactory; + $this->queryModifierFactory = $queryModifierFactory; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + $select = $this->moduleDataSetup->getConnection() + ->select() + ->from( + $this->moduleDataSetup->getTable('core_config_data'), + ['config_id', 'value'] + ) + ->where('path = ?', 'cataloginventory/item_options/min_sale_qty'); + + $rows = $this->moduleDataSetup->getConnection()->fetchAssoc($select); + $serializedRows = array_filter($rows, function ($row) { + return $this->isSerialized($row['value']); + }); + + $fieldDataConverter = $this->fieldDataConverterFactory->create(SerializedToJson::class); + $queryModifier = $this->queryModifierFactory->create( + 'in', + [ + 'values' => [ + 'config_id' => array_keys($serializedRows) + ] + ] + ); + + $fieldDataConverter->convert( + $this->moduleDataSetup->getConnection(), + $this->moduleDataSetup->getTable('core_config_data'), + 'config_id', + 'value', + $queryModifier + ); + } + + /** + * Check if value is a serialized string + * + * @param string $value + * @return boolean + */ + private function isSerialized($value) + { + return (boolean) preg_match('/^((s|i|d|b|a|O|C):|N;)/', $value); + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return [ + UpdateStockItemsWebsite::class, + ]; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.2.1'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } +} diff --git a/app/code/Magento/CatalogInventory/Setup/InstallData.php b/app/code/Magento/CatalogInventory/Setup/Patch/Data/CreateDefaultStock.php similarity index 50% rename from app/code/Magento/CatalogInventory/Setup/InstallData.php rename to app/code/Magento/CatalogInventory/Setup/Patch/Data/CreateDefaultStock.php index 6fd1745574266..179e7a88b3172 100644 --- a/app/code/Magento/CatalogInventory/Setup/InstallData.php +++ b/app/code/Magento/CatalogInventory/Setup/Patch/Data/CreateDefaultStock.php @@ -4,57 +4,88 @@ * See COPYING.txt for license details. */ -namespace Magento\CatalogInventory\Setup; +namespace Magento\CatalogInventory\Setup\Patch\Data; use Magento\Eav\Setup\EavSetup; use Magento\Eav\Setup\EavSetupFactory; -use Magento\Framework\Setup\InstallDataInterface; -use Magento\Framework\Setup\ModuleContextInterface; +use Magento\Framework\App\ResourceConnection; use Magento\Framework\Setup\ModuleDataSetupInterface; +use Magento\Setup\Model\Patch\DataPatchInterface; +use Magento\Setup\Model\Patch\PatchVersionInterface; /** - * @codeCoverageIgnore + * Class CreateDefaultStock + * @package Magento\CatalogInventory\Setup\Patch */ -class InstallData implements InstallDataInterface +class CreateDefaultStock implements DataPatchInterface, PatchVersionInterface { /** - * EAV setup factory - * + * @var ModuleDataSetupInterface + */ + private $moduleDataSetup; + + /** * @var EavSetupFactory */ private $eavSetupFactory; /** - * Init - * + * PrepareInitialConfig constructor. + * @param ModuleDataSetupInterface $resourceConnection * @param EavSetupFactory $eavSetupFactory */ - public function __construct(EavSetupFactory $eavSetupFactory) - { + public function __construct( + ModuleDataSetupInterface $resourceConnection, + EavSetupFactory $eavSetupFactory + ) { + $this->moduleDataSetup = $resourceConnection; $this->eavSetupFactory = $eavSetupFactory; } /** * {@inheritdoc} */ - public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context) + public function apply() { - $setup->getConnection() + $this->moduleDataSetup->getConnection() ->insertForce( - $setup->getTable('cataloginventory_stock'), + $this->moduleDataSetup->getTable('cataloginventory_stock'), ['stock_id' => 1, 'stock_name' => 'Default'] ); /** @var EavSetup $eavSetup */ - $eavSetup = $this->eavSetupFactory->create(['setup' => $setup]); + $eavSetup = $this->eavSetupFactory->create(['setup' => $this->moduleDataSetup]); $groupName = 'Product Details'; $entityTypeId = $eavSetup->getEntityTypeId(\Magento\Catalog\Model\Product::ENTITY); $attributeSetId = $eavSetup->getAttributeSetId($entityTypeId, 'Default'); - $attribute = $eavSetup->getAttribute($entityTypeId, 'quantity_and_stock_status'); if ($attribute) { $eavSetup->addAttributeToGroup($entityTypeId, $attributeSetId, $groupName, $attribute['attribute_id'], 60); $eavSetup->updateAttribute($entityTypeId, $attribute['attribute_id'], 'default_value', 1); } } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return []; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.0'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } } diff --git a/app/code/Magento/CatalogInventory/Setup/Patch/Data/UpdateStockItemsWebsite.php b/app/code/Magento/CatalogInventory/Setup/Patch/Data/UpdateStockItemsWebsite.php new file mode 100644 index 0000000000000..b5d1471435cb8 --- /dev/null +++ b/app/code/Magento/CatalogInventory/Setup/Patch/Data/UpdateStockItemsWebsite.php @@ -0,0 +1,98 @@ +moduleDataSetup = $moduleDataSetup; + $this->stockConfiguration = $stockConfiguration; + $this->storeManager = $storeManager; + $this->indexerProcessor = $indexerProcessor; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + $this->moduleDataSetup->getConnection()->update( + $this->moduleDataSetup->getTable('cataloginventory_stock_item'), + ['website_id' => $this->stockConfiguration->getDefaultScopeId()], + ['website_id = ?' => $this->storeManager->getWebsite()->getId()] + ); + $this->indexerProcessor->getIndexer()->invalidate(); + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return [ + CreateDefaultStock::class, + ]; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.2.0'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } +} diff --git a/app/code/Magento/CatalogInventory/Setup/UpgradeData.php b/app/code/Magento/CatalogInventory/Setup/UpgradeData.php deleted file mode 100644 index 8c99861308ba1..0000000000000 --- a/app/code/Magento/CatalogInventory/Setup/UpgradeData.php +++ /dev/null @@ -1,152 +0,0 @@ -configuration = $configuration; - $this->storeManager = $storeManager; - $this->indexerProcessor = $indexerProcessor; - $this->fieldDataConverterFactory = $fieldDataConverterFactory; - $this->queryModifierFactory = $queryModifierFactory; - } - - /** - * {@inheritdoc} - */ - public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context) - { - $setup->startSetup(); - if (version_compare($context->getVersion(), '2.2.0') < 0) { - $this->upgradeCatalogInventoryStockItem($setup); - } - - if (version_compare($context->getVersion(), '2.2.1', '<')) { - $this->convertSerializedDataToJson($setup); - } - $setup->endSetup(); - } - - /** - * @param ModuleDataSetupInterface $setup - * @return void - */ - private function upgradeCatalogInventoryStockItem($setup) - { - $setup->getConnection()->update( - $setup->getTable('cataloginventory_stock_item'), - ['website_id' => $this->configuration->getDefaultScopeId()], - ['website_id = ?' => $this->storeManager->getWebsite()->getId()] - ); - $this->indexerProcessor->getIndexer()->invalidate(); - } - - /** - * Upgrade data to version 2.2.1, converts row data in the core_config_data table that uses the - * path cataloginventory/item_options/min_sale_qty from serialized to JSON. Stored value may not be - * serialized, so validate data format before executing update. - * - * @param ModuleDataSetupInterface $setup - * @return void - */ - private function convertSerializedDataToJson(ModuleDataSetupInterface $setup) - { - $select = $setup->getConnection() - ->select() - ->from( - $setup->getTable('core_config_data'), - ['config_id', 'value'] - ) - ->where('path = ?', 'cataloginventory/item_options/min_sale_qty'); - - $rows = $setup->getConnection()->fetchAssoc($select); - $serializedRows = array_filter($rows, function ($row) { - return $this->isSerialized($row['value']); - }); - - $fieldDataConverter = $this->fieldDataConverterFactory->create(SerializedToJson::class); - $queryModifier = $this->queryModifierFactory->create( - 'in', - [ - 'values' => [ - 'config_id' => array_keys($serializedRows) - ] - ] - ); - - $fieldDataConverter->convert( - $setup->getConnection(), - $setup->getTable('core_config_data'), - 'config_id', - 'value', - $queryModifier - ); - } - - /** - * Check if value is a serialized string - * - * @param string $value - * @return boolean - */ - private function isSerialized($value) - { - return (boolean) preg_match('/^((s|i|d|b|a|O|C):|N;)/', $value); - } -} diff --git a/app/code/Magento/CatalogInventory/Test/Unit/Model/Stock/StockItemRepositoryTest.php b/app/code/Magento/CatalogInventory/Test/Unit/Model/Stock/StockItemRepositoryTest.php index 293874bb32b9f..089f6c42a1736 100644 --- a/app/code/Magento/CatalogInventory/Test/Unit/Model/Stock/StockItemRepositoryTest.php +++ b/app/code/Magento/CatalogInventory/Test/Unit/Model/Stock/StockItemRepositoryTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\CatalogInventory\Test\Unit\Model\Stock; use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory; @@ -251,7 +252,7 @@ public function testDeleteById() /** * @expectedException \Magento\Framework\Exception\CouldNotDeleteException - * @expectedExceptionMessage Unable to remove Stock Item with id "1" + * @expectedExceptionMessage The stock item with the "1" ID wasn't found. Verify the ID and try again. */ public function testDeleteByIdException() { diff --git a/app/code/Magento/CatalogInventory/etc/di.xml b/app/code/Magento/CatalogInventory/etc/di.xml index 04935b11ce02b..2a55d745e1185 100644 --- a/app/code/Magento/CatalogInventory/etc/di.xml +++ b/app/code/Magento/CatalogInventory/etc/di.xml @@ -78,11 +78,6 @@ - - - Magento\CatalogInventory\Model\Indexer\Stock\Processor - - diff --git a/app/code/Magento/CatalogInventory/etc/module.xml b/app/code/Magento/CatalogInventory/etc/module.xml index b9cddf838b9f2..d643c5015130f 100644 --- a/app/code/Magento/CatalogInventory/etc/module.xml +++ b/app/code/Magento/CatalogInventory/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/CatalogRule/Model/CatalogRuleRepository.php b/app/code/Magento/CatalogRule/Model/CatalogRuleRepository.php index a3fa9a8f67ab2..2655c0fa9646a 100644 --- a/app/code/Magento/CatalogRule/Model/CatalogRuleRepository.php +++ b/app/code/Magento/CatalogRule/Model/CatalogRuleRepository.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\CatalogRule\Model; use Magento\CatalogRule\Api\Data; @@ -55,7 +56,9 @@ public function save(Data\RuleInterface $rule) } catch (ValidatorException $e) { throw new CouldNotSaveException(__($e->getMessage())); } catch (\Exception $e) { - throw new CouldNotSaveException(__('Unable to save rule %1', $rule->getRuleId())); + throw new CouldNotSaveException( + __('The "%1" rule was unable to be saved. Please try again.', $rule->getRuleId()) + ); } return $rule; } @@ -72,7 +75,9 @@ public function get($ruleId) /* TODO: change to resource model after entity manager will be fixed */ $rule->load($ruleId); if (!$rule->getRuleId()) { - throw new NoSuchEntityException(__('Rule with specified ID "%1" not found.', $ruleId)); + throw new NoSuchEntityException( + __('The rule with the "%1" ID wasn\'t found. Verify the ID and try again.', $ruleId) + ); } $this->rules[$ruleId] = $rule; } @@ -90,7 +95,7 @@ public function delete(Data\RuleInterface $rule) } catch (ValidatorException $e) { throw new CouldNotSaveException(__($e->getMessage())); } catch (\Exception $e) { - throw new CouldNotDeleteException(__('Unable to remove rule %1', $rule->getRuleId())); + throw new CouldNotDeleteException(__('The "%1" rule couldn\'t be removed.', $rule->getRuleId())); } return true; } diff --git a/app/code/Magento/CatalogRule/Setup/InstallData.php b/app/code/Magento/CatalogRule/Setup/InstallData.php deleted file mode 100644 index 47591f838d185..0000000000000 --- a/app/code/Magento/CatalogRule/Setup/InstallData.php +++ /dev/null @@ -1,45 +0,0 @@ -createMigrationSetup(); - $setup->startSetup(); - - $installer->appendClassAliasReplace( - 'catalogrule', - 'conditions_serialized', - \Magento\Framework\Module\Setup\Migration::ENTITY_TYPE_MODEL, - \Magento\Framework\Module\Setup\Migration::FIELD_CONTENT_TYPE_SERIALIZED, - ['rule_id'] - ); - $installer->appendClassAliasReplace( - 'catalogrule', - 'actions_serialized', - \Magento\Framework\Module\Setup\Migration::ENTITY_TYPE_MODEL, - \Magento\Framework\Module\Setup\Migration::FIELD_CONTENT_TYPE_SERIALIZED, - ['rule_id'] - ); - - $installer->doUpdateClassAliases(); - - $setup->endSetup(); - } -} diff --git a/app/code/Magento/CatalogRule/Setup/Patch/Data/ConvertSerializedDataToJson.php b/app/code/Magento/CatalogRule/Setup/Patch/Data/ConvertSerializedDataToJson.php new file mode 100644 index 0000000000000..eb5ed43806aa2 --- /dev/null +++ b/app/code/Magento/CatalogRule/Setup/Patch/Data/ConvertSerializedDataToJson.php @@ -0,0 +1,101 @@ +moduleDataSetup = $moduleDataSetup; + $this->metadataPool = $metadataPool; + $this->aggregatedFieldDataConverter = $aggregatedFieldDataConverter; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + $metadata = $this->metadataPool->getMetadata(RuleInterface::class); + $this->aggregatedFieldDataConverter->convert( + [ + new FieldToConvert( + SerializedToJson::class, + $this->moduleDataSetup->getTable('catalogrule'), + $metadata->getLinkField(), + 'conditions_serialized' + ), + new FieldToConvert( + SerializedToJson::class, + $this->moduleDataSetup->getTable('catalogrule'), + $metadata->getLinkField(), + 'actions_serialized' + ), + ], + $this->moduleDataSetup->getConnection() + ); + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return [ + UpdateClassAliasesForCatalogRules::class, + ]; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.3'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } +} diff --git a/app/code/Magento/CatalogRule/Setup/Patch/Data/UpdateClassAliasesForCatalogRules.php b/app/code/Magento/CatalogRule/Setup/Patch/Data/UpdateClassAliasesForCatalogRules.php new file mode 100644 index 0000000000000..17920a997014f --- /dev/null +++ b/app/code/Magento/CatalogRule/Setup/Patch/Data/UpdateClassAliasesForCatalogRules.php @@ -0,0 +1,80 @@ +dataSetup = $dataSetup; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + $installer = $this->dataSetup->createMigrationSetup(); + $installer->appendClassAliasReplace( + 'catalogrule', + 'conditions_serialized', + \Magento\Framework\Module\Setup\Migration::ENTITY_TYPE_MODEL, + \Magento\Framework\Module\Setup\Migration::FIELD_CONTENT_TYPE_SERIALIZED, + ['rule_id'] + ); + $installer->appendClassAliasReplace( + 'catalogrule', + 'actions_serialized', + \Magento\Framework\Module\Setup\Migration::ENTITY_TYPE_MODEL, + \Magento\Framework\Module\Setup\Migration::FIELD_CONTENT_TYPE_SERIALIZED, + ['rule_id'] + ); + $installer->doUpdateClassAliases(); + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return []; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.0'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } +} diff --git a/app/code/Magento/CatalogRule/Setup/UpgradeData.php b/app/code/Magento/CatalogRule/Setup/UpgradeData.php deleted file mode 100644 index 7f75b7e41dfac..0000000000000 --- a/app/code/Magento/CatalogRule/Setup/UpgradeData.php +++ /dev/null @@ -1,86 +0,0 @@ -aggregatedFieldConverter = $aggregatedFieldConverter; - $this->metadataPool = $metadataPool; - } - - /** - * @inheritdoc - */ - public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context) - { - $setup->startSetup(); - - if (version_compare($context->getVersion(), '2.0.3', '<')) { - $this->convertSerializedDataToJson($setup); - } - - $setup->endSetup(); - } - - /** - * Convert metadata from serialized to JSON format: - * - * @param ModuleDataSetupInterface $setup - * - * @return void - */ - public function convertSerializedDataToJson($setup) - { - $metadata = $this->metadataPool->getMetadata(RuleInterface::class); - $this->aggregatedFieldConverter->convert( - [ - new FieldToConvert( - SerializedToJson::class, - $setup->getTable('catalogrule'), - $metadata->getLinkField(), - 'conditions_serialized' - ), - new FieldToConvert( - SerializedToJson::class, - $setup->getTable('catalogrule'), - $metadata->getLinkField(), - 'actions_serialized' - ), - ], - $setup->getConnection() - ); - } -} diff --git a/app/code/Magento/CatalogRule/Test/Unit/Model/CatalogRuleRepositoryTest.php b/app/code/Magento/CatalogRule/Test/Unit/Model/CatalogRuleRepositoryTest.php index 32c6896625a1f..7db805908ae72 100644 --- a/app/code/Magento/CatalogRule/Test/Unit/Model/CatalogRuleRepositoryTest.php +++ b/app/code/Magento/CatalogRule/Test/Unit/Model/CatalogRuleRepositoryTest.php @@ -65,7 +65,7 @@ public function testEditRule() /** * @expectedException \Magento\Framework\Exception\CouldNotSaveException - * @expectedExceptionMessage Unable to save rule 1 + * @expectedExceptionMessage The "1" rule was unable to be saved. Please try again. */ public function testEnableSaveRule() { @@ -106,7 +106,7 @@ public function testDeleteRuleById() /** * @expectedException \Magento\Framework\Exception\CouldNotDeleteException - * @expectedExceptionMessage Unable to remove rule 1 + * @expectedExceptionMessage The "1" rule couldn't be removed. */ public function testUnableDeleteRule() { @@ -132,7 +132,7 @@ public function testGetRule() /** * @expectedException \Magento\Framework\Exception\NoSuchEntityException - * @expectedExceptionMessage Rule with specified ID "1" not found. + * @expectedExceptionMessage The rule with the "1" ID wasn't found. Verify the ID and try again. */ public function testGetNonExistentRule() { diff --git a/app/code/Magento/CatalogRule/etc/module.xml b/app/code/Magento/CatalogRule/etc/module.xml index 1dc0f27b137bc..c2acce2ff995d 100644 --- a/app/code/Magento/CatalogRule/etc/module.xml +++ b/app/code/Magento/CatalogRule/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/CatalogRuleConfigurable/etc/module.xml b/app/code/Magento/CatalogRuleConfigurable/etc/module.xml index 3552af8ceb337..0f4d5742fb778 100644 --- a/app/code/Magento/CatalogRuleConfigurable/etc/module.xml +++ b/app/code/Magento/CatalogRuleConfigurable/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/CatalogSearch/Block/SearchTermsLog.php b/app/code/Magento/CatalogSearch/Block/SearchTermsLog.php new file mode 100644 index 0000000000000..0be43ce6ff1fb --- /dev/null +++ b/app/code/Magento/CatalogSearch/Block/SearchTermsLog.php @@ -0,0 +1,40 @@ +response = $response; + } + + /** + * Check is current page cacheable + * + * @return bool + */ + public function isPageCacheable() + { + $pragma = $this->response->getHeader('pragma')->getFieldValue(); + return ($pragma == 'cache'); + } +} diff --git a/app/code/Magento/CatalogSearch/Controller/Result/Index.php b/app/code/Magento/CatalogSearch/Controller/Result/Index.php index f3990da3a325e..22958b64d444d 100644 --- a/app/code/Magento/CatalogSearch/Controller/Result/Index.php +++ b/app/code/Magento/CatalogSearch/Controller/Result/Index.php @@ -9,9 +9,9 @@ use Magento\Catalog\Model\Layer\Resolver; use Magento\Catalog\Model\Session; use Magento\Framework\App\Action\Context; -use Magento\Framework\App\ResourceConnection; use Magento\Store\Model\StoreManagerInterface; use Magento\Search\Model\QueryFactory; +use Magento\Search\Model\PopularSearchTerms; class Index extends \Magento\Framework\App\Action\Action { @@ -64,34 +64,88 @@ public function __construct( * Display search result * * @return void + * + * @throws \Magento\Framework\Exception\LocalizedException */ public function execute() { $this->layerResolver->create(Resolver::CATALOG_LAYER_SEARCH); + /* @var $query \Magento\Search\Model\Query */ $query = $this->_queryFactory->get(); - $query->setStoreId($this->_storeManager->getStore()->getId()); + $storeId = $this->_storeManager->getStore()->getId(); + $query->setStoreId($storeId); + + $queryText = $query->getQueryText(); + + if ($queryText != '') { + $catalogSearchHelper = $this->_objectManager->get(\Magento\CatalogSearch\Helper\Data::class); - if ($query->getQueryText() != '') { - if ($this->_objectManager->get(\Magento\CatalogSearch\Helper\Data::class)->isMinQueryLength()) { - $query->setId(0)->setIsActive(1)->setIsProcessed(1); + $getAdditionalRequestParameters = $this->getRequest()->getParams(); + unset($getAdditionalRequestParameters[QueryFactory::QUERY_VAR_NAME]); + + if (empty($getAdditionalRequestParameters) && + $this->_objectManager->get(PopularSearchTerms::class)->isCacheable($queryText, $storeId) + ) { + $this->getCacheableResult($catalogSearchHelper, $query); } else { - $query->saveIncrementalPopularity(); + $this->getNotCacheableResult($catalogSearchHelper, $query); + } + } else { + $this->getResponse()->setRedirect($this->_redirect->getRedirectUrl()); + } + } - $redirect = $query->getRedirect(); - if ($redirect && $this->_url->getCurrentUrl() !== $redirect) { - $this->getResponse()->setRedirect($redirect); - return; - } + /** + * Return cacheable result + * + * @param \Magento\CatalogSearch\Helper\Data $catalogSearchHelper + * @param \Magento\Search\Model\Query $query + * @return void + */ + private function getCacheableResult($catalogSearchHelper, $query) + { + if (!$catalogSearchHelper->isMinQueryLength()) { + $redirect = $query->getRedirect(); + if ($redirect && $this->_url->getCurrentUrl() !== $redirect) { + $this->getResponse()->setRedirect($redirect); + return; } + } - $this->_objectManager->get(\Magento\CatalogSearch\Helper\Data::class)->checkNotes(); + $catalogSearchHelper->checkNotes(); + + $this->_view->loadLayout(); + $this->_view->renderLayout(); + } - $this->_view->loadLayout(); - $this->_view->renderLayout(); + /** + * Return not cacheable result + * + * @param \Magento\CatalogSearch\Helper\Data $catalogSearchHelper + * @param \Magento\Search\Model\Query $query + * @return void + * + * @throws \Magento\Framework\Exception\LocalizedException + */ + private function getNotCacheableResult($catalogSearchHelper, $query) + { + if ($catalogSearchHelper->isMinQueryLength()) { + $query->setId(0)->setIsActive(1)->setIsProcessed(1); } else { - $this->getResponse()->setRedirect($this->_redirect->getRedirectUrl()); + $query->saveIncrementalPopularity(); + $redirect = $query->getRedirect(); + if ($redirect && $this->_url->getCurrentUrl() !== $redirect) { + $this->getResponse()->setRedirect($redirect); + return; + } } + + $catalogSearchHelper->checkNotes(); + + $this->_view->loadLayout(); + $this->getResponse()->setNoCacheHeaders(); + $this->_view->renderLayout(); } } diff --git a/app/code/Magento/CatalogSearch/Controller/SearchTermsLog/Save.php b/app/code/Magento/CatalogSearch/Controller/SearchTermsLog/Save.php new file mode 100644 index 0000000000000..a4a843c636cd0 --- /dev/null +++ b/app/code/Magento/CatalogSearch/Controller/SearchTermsLog/Save.php @@ -0,0 +1,95 @@ +storeManager = $storeManager; + $this->catalogSearchHelper = $catalogSearchHelper; + $this->queryFactory = $queryFactory; + $this->resultJsonFactory = $resultJsonFactory; + } + + /** + * Save search term + * + * @return Json + */ + public function execute() + { + /* @var $query \Magento\Search\Model\Query */ + $query = $this->queryFactory->get(); + + $query->setStoreId($this->storeManager->getStore()->getId()); + + if ($query->getQueryText() != '') { + try { + if ($this->catalogSearchHelper->isMinQueryLength()) { + $query->setId(0)->setIsActive(1)->setIsProcessed(1); + } else { + $query->saveIncrementalPopularity(); + } + $responseContent = ['success' => true, 'error_message' => '']; + } catch (\Magento\Framework\Exception\LocalizedException $e) { + $responseContent = ['success' => false, 'error_message' => $e]; + } + } else { + $responseContent = ['success' => false, 'error_message' => __('Search term is empty')]; + } + + /** @var Json $resultJson */ + $resultJson = $this->resultJsonFactory->create(); + return $resultJson->setData($responseContent); + } +} diff --git a/app/code/Magento/CatalogSearch/Model/Advanced.php b/app/code/Magento/CatalogSearch/Model/Advanced.php index d158bdf40b421..28f67a7829e7e 100644 --- a/app/code/Magento/CatalogSearch/Model/Advanced.php +++ b/app/code/Magento/CatalogSearch/Model/Advanced.php @@ -226,7 +226,7 @@ public function addFilters($values) $this->_registry->register('advanced_search_conditions', $allConditions); $this->getProductCollection()->addFieldsToFilter($allConditions); } else { - throw new LocalizedException(__('Please specify at least one search term.')); + throw new LocalizedException(__('Enter a search term and try again.')); } return $this; diff --git a/app/code/Magento/CatalogSearch/Model/ResourceModel/Advanced/Collection.php b/app/code/Magento/CatalogSearch/Model/ResourceModel/Advanced/Collection.php index 02bc3e2bc2400..57896ba5a79fd 100644 --- a/app/code/Magento/CatalogSearch/Model/ResourceModel/Advanced/Collection.php +++ b/app/code/Magento/CatalogSearch/Model/ResourceModel/Advanced/Collection.php @@ -187,7 +187,7 @@ protected function _renderFiltersBefore() } catch (NonExistingRequestNameException $e) { $this->_logger->error($e->getMessage()); throw new LocalizedException( - __('Sorry, something went wrong. You can find out more in the error log.') + __('An error occurred. For details, see the error log.') ); } $temporaryStorage = $this->temporaryStorageFactory->create(); diff --git a/app/code/Magento/CatalogSearch/Model/ResourceModel/Fulltext/Collection.php b/app/code/Magento/CatalogSearch/Model/ResourceModel/Fulltext/Collection.php index 68274ee5043f5..0408957e511b9 100644 --- a/app/code/Magento/CatalogSearch/Model/ResourceModel/Fulltext/Collection.php +++ b/app/code/Magento/CatalogSearch/Model/ResourceModel/Fulltext/Collection.php @@ -347,7 +347,7 @@ protected function _renderFiltersBefore() $this->searchResult = $this->searchResultFactory->create()->setItems([]); } catch (NonExistingRequestNameException $e) { $this->_logger->error($e->getMessage()); - throw new LocalizedException(__('Sorry, something went wrong. You can find out more in the error log.')); + throw new LocalizedException(__('An error occurred. For details, see the error log.')); } $temporaryStorage = $this->temporaryStorageFactory->create(); @@ -441,7 +441,7 @@ public function getFacetedData($field) $result[$metrics['value']] = $metrics; } } else { - throw new StateException(__('Bucket does not exist')); + throw new StateException(__("The bucket doesn't exist.")); } } return $result; diff --git a/app/code/Magento/CatalogSearch/Setup/InstallData.php b/app/code/Magento/CatalogSearch/Setup/Patch/Data/SetInitialSearchWeightForAttributes.php similarity index 57% rename from app/code/Magento/CatalogSearch/Setup/InstallData.php rename to app/code/Magento/CatalogSearch/Setup/Patch/Data/SetInitialSearchWeightForAttributes.php index 8a2754f1903c5..31cc70b05083c 100644 --- a/app/code/Magento/CatalogSearch/Setup/InstallData.php +++ b/app/code/Magento/CatalogSearch/Setup/Patch/Data/SetInitialSearchWeightForAttributes.php @@ -3,15 +3,19 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\CatalogSearch\Setup; -use Magento\Framework\Setup\InstallDataInterface; -use Magento\Framework\Setup\ModuleContextInterface; -use Magento\Framework\Setup\ModuleDataSetupInterface; +namespace Magento\CatalogSearch\Setup\Patch\Data; + +use Magento\Setup\Model\Patch\DataPatchInterface; +use Magento\Setup\Model\Patch\PatchVersionInterface; use Magento\Framework\Indexer\IndexerInterfaceFactory; use Magento\Catalog\Api\ProductAttributeRepositoryInterface; -class InstallData implements InstallDataInterface +/** + * Class SetInitialSearchWeightForAttributes + * @package Magento\CatalogSearch\Setup\Patch + */ +class SetInitialSearchWeightForAttributes implements DataPatchInterface, PatchVersionInterface { /** * @var IndexerInterfaceFactory @@ -24,6 +28,7 @@ class InstallData implements InstallDataInterface private $attributeRepository; /** + * SetInitialSearchWeightForAttributes constructor. * @param IndexerInterfaceFactory $indexerFactory * @param ProductAttributeRepositoryInterface $attributeRepository */ @@ -36,33 +41,43 @@ public function __construct( } /** - * Installs data for a module - * - * @param ModuleDataSetupInterface $setup - * @param ModuleContextInterface $context - * @return void - * @SuppressWarnings(PHPMD.UnusedFormalParameter) + * {@inheritdoc} */ - public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context) + public function apply() { $this->setWeight('sku', 6); $this->setWeight('name', 5); - $this->getIndexer('catalogsearch_fulltext')->reindexAll(); } /** - * @param string $indexerId - * @return \Magento\Framework\Indexer\IndexerInterface + * {@inheritdoc} */ - private function getIndexer($indexerId) + public static function getDependencies() { - return $this->indexerFactory->create()->load($indexerId); + return []; } /** - * @param string $attributeCode - * @param int $weight - * @return void + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.0'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } + + /** + * Set attribute search weight. + * + * @param $attributeCode + * @param $weight */ private function setWeight($attributeCode, $weight) { diff --git a/app/code/Magento/CatalogSearch/Setup/RecurringData.php b/app/code/Magento/CatalogSearch/Setup/RecurringData.php new file mode 100644 index 0000000000000..0c2aee800b6f1 --- /dev/null +++ b/app/code/Magento/CatalogSearch/Setup/RecurringData.php @@ -0,0 +1,62 @@ +indexerInterfaceFactory = $indexerInterfaceFactory; + $this->state = $state; + } + + /** + * {@inheritdoc} + */ + public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context) + { + $this->state->emulateAreaCode( + \Magento\Framework\App\Area::AREA_CRONTAB, + [$this, 'reindex'] + ); + } + + /** + * Run reindex. + * + * @return void + */ + public function reindex() + { + $this->indexerInterfaceFactory->create()->load('catalogsearch_fulltext')->reindexAll(); + } +} diff --git a/app/code/Magento/CatalogSearch/etc/adminhtml/system.xml b/app/code/Magento/CatalogSearch/etc/adminhtml/system.xml index 0eeb6ab33871e..f5ebd3c6c9dc4 100644 --- a/app/code/Magento/CatalogSearch/etc/adminhtml/system.xml +++ b/app/code/Magento/CatalogSearch/etc/adminhtml/system.xml @@ -27,6 +27,11 @@ validate-digits + + + Number of popular search terms to be cached for faster response. Use “0” to cache all results after a term is searched for the second time. + validate-digits + diff --git a/app/code/Magento/CatalogSearch/etc/config.xml b/app/code/Magento/CatalogSearch/etc/config.xml index d5ff194813b9c..9fb0118701d10 100644 --- a/app/code/Magento/CatalogSearch/etc/config.xml +++ b/app/code/Magento/CatalogSearch/etc/config.xml @@ -15,6 +15,7 @@ mysql 1 128 + 100 diff --git a/app/code/Magento/CatalogSearch/etc/module.xml b/app/code/Magento/CatalogSearch/etc/module.xml index fd31faa083926..db530edbdd7ef 100644 --- a/app/code/Magento/CatalogSearch/etc/module.xml +++ b/app/code/Magento/CatalogSearch/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/CatalogSearch/view/frontend/layout/catalogsearch_result_index.xml b/app/code/Magento/CatalogSearch/view/frontend/layout/catalogsearch_result_index.xml index e54b45093589a..8dd8e3ed72828 100644 --- a/app/code/Magento/CatalogSearch/view/frontend/layout/catalogsearch_result_index.xml +++ b/app/code/Magento/CatalogSearch/view/frontend/layout/catalogsearch_result_index.xml @@ -9,16 +9,16 @@ - - + + positions:list-secondary - - + + product_list_toolbar @@ -36,6 +36,11 @@ + + + Magento\CatalogSearch\Block\SearchTermsLog + + diff --git a/app/code/Magento/CatalogSearch/view/frontend/templates/search_terms_log.phtml b/app/code/Magento/CatalogSearch/view/frontend/templates/search_terms_log.phtml new file mode 100644 index 0000000000000..61609bdf66bda --- /dev/null +++ b/app/code/Magento/CatalogSearch/view/frontend/templates/search_terms_log.phtml @@ -0,0 +1,18 @@ + +getSearchTermsLog()->isPageCacheable()): ?> + + diff --git a/app/code/Magento/CatalogSearch/view/frontend/web/js/search-terms-log.js b/app/code/Magento/CatalogSearch/view/frontend/web/js/search-terms-log.js new file mode 100644 index 0000000000000..8638a837f56b9 --- /dev/null +++ b/app/code/Magento/CatalogSearch/view/frontend/web/js/search-terms-log.js @@ -0,0 +1,21 @@ +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +define([ + 'jquery', + 'mageUtils' +], function ($, utils) { + 'use strict'; + + return function (data) { + $.ajax({ + method: 'GET', + url: data.url, + data: { + 'q': utils.getUrlParameters(window.location.href).q + } + }); + }; +}); diff --git a/app/code/Magento/CatalogUrlRewrite/Setup/InstallData.php b/app/code/Magento/CatalogUrlRewrite/Setup/Patch/Data/CreateUrlAttributes.php similarity index 70% rename from app/code/Magento/CatalogUrlRewrite/Setup/InstallData.php rename to app/code/Magento/CatalogUrlRewrite/Setup/Patch/Data/CreateUrlAttributes.php index bbc5f497843b0..dfbbb6f6f31f5 100644 --- a/app/code/Magento/CatalogUrlRewrite/Setup/InstallData.php +++ b/app/code/Magento/CatalogUrlRewrite/Setup/Patch/Data/CreateUrlAttributes.php @@ -4,43 +4,51 @@ * See COPYING.txt for license details. */ -namespace Magento\CatalogUrlRewrite\Setup; +namespace Magento\CatalogUrlRewrite\Setup\Patch\Data; use Magento\Eav\Setup\EavSetup; use Magento\Eav\Setup\EavSetupFactory; -use Magento\Framework\Setup\InstallDataInterface; -use Magento\Framework\Setup\ModuleContextInterface; +use Magento\Framework\App\ResourceConnection; use Magento\Framework\Setup\ModuleDataSetupInterface; +use Magento\Setup\Model\Patch\DataPatchInterface; +use Magento\Setup\Model\Patch\PatchVersionInterface; /** - * @codeCoverageIgnore + * Class CreateUrlAttributes + * @package Magento\CatalogUrlRewrite\Setup\Patch */ -class InstallData implements InstallDataInterface +class CreateUrlAttributes implements DataPatchInterface, PatchVersionInterface { /** - * EAV setup factory - * + * @var ModuleDataSetupInterface + */ + private $moduleDataSetup; + + /** * @var EavSetupFactory */ private $eavSetupFactory; /** - * Init - * + * CreateUrlAttributes constructor. + * @param ModuleDataSetupInterface $moduleDataSetup * @param EavSetupFactory $eavSetupFactory */ - public function __construct(EavSetupFactory $eavSetupFactory) - { + public function __construct( + ModuleDataSetupInterface $moduleDataSetup, + EavSetupFactory $eavSetupFactory + ) { + $this->moduleDataSetup = $moduleDataSetup; $this->eavSetupFactory = $eavSetupFactory; } /** * {@inheritdoc} */ - public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context) + public function apply() { /** @var EavSetup $eavSetup */ - $eavSetup = $this->eavSetupFactory->create(['setup' => $setup]); + $eavSetup = $this->eavSetupFactory->create(['setup' => $this->moduleDataSetup]); $eavSetup->addAttribute( \Magento\Catalog\Model\Category::ENTITY, 'url_key', @@ -67,7 +75,6 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface 'group' => 'General Information', ] ); - $eavSetup->addAttribute( \Magento\Catalog\Model\Product::ENTITY, 'url_key', @@ -85,7 +92,6 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface 'is_filterable_in_grid' => true, ] ); - $eavSetup->addAttribute( \Magento\Catalog\Model\Product::ENTITY, 'url_path', @@ -98,4 +104,28 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ] ); } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return []; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.0'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } } diff --git a/app/code/Magento/CatalogUrlRewrite/etc/module.xml b/app/code/Magento/CatalogUrlRewrite/etc/module.xml index 65d6e5c748d98..277c551d7b212 100644 --- a/app/code/Magento/CatalogUrlRewrite/etc/module.xml +++ b/app/code/Magento/CatalogUrlRewrite/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/CatalogUrlRewriteGraphQl/etc/module.xml b/app/code/Magento/CatalogUrlRewriteGraphQl/etc/module.xml index d17a3cdb45c76..be4bb9fcd7010 100644 --- a/app/code/Magento/CatalogUrlRewriteGraphQl/etc/module.xml +++ b/app/code/Magento/CatalogUrlRewriteGraphQl/etc/module.xml @@ -6,5 +6,5 @@ */ --> - + diff --git a/app/code/Magento/CatalogWidget/etc/module.xml b/app/code/Magento/CatalogWidget/etc/module.xml index 8954f11f954f7..b3724d4b91f79 100644 --- a/app/code/Magento/CatalogWidget/etc/module.xml +++ b/app/code/Magento/CatalogWidget/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/Checkout/Controller/Cart/Configure.php b/app/code/Magento/Checkout/Controller/Cart/Configure.php index 132fbf7d199a0..6d409144ff66d 100644 --- a/app/code/Magento/Checkout/Controller/Cart/Configure.php +++ b/app/code/Magento/Checkout/Controller/Cart/Configure.php @@ -4,6 +4,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Checkout\Controller\Cart; use Magento\Framework; @@ -63,7 +64,7 @@ public function execute() try { if (!$quoteItem || $productId != $quoteItem->getProduct()->getId()) { - $this->messageManager->addError(__("We can't find the quote item.")); + $this->messageManager->addError(__("The quote item isn't found. Verify the item and try again.")); return $this->resultFactory->create(ResultFactory::TYPE_REDIRECT)->setPath('checkout/cart'); } diff --git a/app/code/Magento/Checkout/Controller/Cart/UpdateItemOptions.php b/app/code/Magento/Checkout/Controller/Cart/UpdateItemOptions.php index 118611263220b..d7cb94f3da673 100644 --- a/app/code/Magento/Checkout/Controller/Cart/UpdateItemOptions.php +++ b/app/code/Magento/Checkout/Controller/Cart/UpdateItemOptions.php @@ -4,6 +4,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Checkout\Controller\Cart; class UpdateItemOptions extends \Magento\Checkout\Controller\Cart @@ -35,7 +36,9 @@ public function execute() $quoteItem = $this->cart->getQuote()->getItemById($id); if (!$quoteItem) { - throw new \Magento\Framework\Exception\LocalizedException(__('We can\'t find the quote item.')); + throw new \Magento\Framework\Exception\LocalizedException( + __("The quote item isn't found. Verify the item and try again.") + ); } $item = $this->cart->updateItem($id, new \Magento\Framework\DataObject($params)); diff --git a/app/code/Magento/Checkout/Controller/Onepage/SaveOrder.php b/app/code/Magento/Checkout/Controller/Onepage/SaveOrder.php index 3597962b83831..12b725a8f6df9 100644 --- a/app/code/Magento/Checkout/Controller/Onepage/SaveOrder.php +++ b/app/code/Magento/Checkout/Controller/Onepage/SaveOrder.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Checkout\Controller\Onepage; use Magento\Framework\DataObject; @@ -37,7 +38,10 @@ public function execute() $result->setData('error', true); $result->setData( 'error_messages', - __('Please agree to all the terms and conditions before placing the order.') + __( + "The order wasn't placed. " + . "First, agree to the terms and conditions, then try placing your order again." + ) ); return $this->resultJsonFactory->create()->setData($result->getData()); } diff --git a/app/code/Magento/Checkout/Model/Cart.php b/app/code/Magento/Checkout/Model/Cart.php index f7072ab97432d..d1a55aee4db93 100644 --- a/app/code/Magento/Checkout/Model/Cart.php +++ b/app/code/Magento/Checkout/Model/Cart.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Checkout\Model; use Magento\Catalog\Api\ProductRepositoryInterface; @@ -299,21 +300,30 @@ protected function _getProduct($productInfo) if ($productInfo instanceof Product) { $product = $productInfo; if (!$product->getId()) { - throw new \Magento\Framework\Exception\LocalizedException(__('We can\'t find the product.')); + throw new \Magento\Framework\Exception\LocalizedException( + __("The product wasn't found. Verify the product and try again.") + ); } } elseif (is_int($productInfo) || is_string($productInfo)) { $storeId = $this->_storeManager->getStore()->getId(); try { $product = $this->productRepository->getById($productInfo, false, $storeId); } catch (NoSuchEntityException $e) { - throw new \Magento\Framework\Exception\LocalizedException(__('We can\'t find the product.'), $e); + throw new \Magento\Framework\Exception\LocalizedException( + __("The product wasn't found. Verify the product and try again."), + $e + ); } } else { - throw new \Magento\Framework\Exception\LocalizedException(__('We can\'t find the product.')); + throw new \Magento\Framework\Exception\LocalizedException( + __("The product wasn't found. Verify the product and try again.") + ); } $currentWebsiteId = $this->_storeManager->getStore()->getWebsiteId(); if (!is_array($product->getWebsiteIds()) || !in_array($currentWebsiteId, $product->getWebsiteIds())) { - throw new \Magento\Framework\Exception\LocalizedException(__('We can\'t find the product.')); + throw new \Magento\Framework\Exception\LocalizedException( + __("The product wasn't found. Verify the product and try again.") + ); } return $product; } diff --git a/app/code/Magento/Checkout/Model/GuestPaymentInformationManagement.php b/app/code/Magento/Checkout/Model/GuestPaymentInformationManagement.php index 6779da354faf8..e18940626a338 100644 --- a/app/code/Magento/Checkout/Model/GuestPaymentInformationManagement.php +++ b/app/code/Magento/Checkout/Model/GuestPaymentInformationManagement.php @@ -95,7 +95,7 @@ public function savePaymentInformationAndPlaceOrder( } catch (\Exception $e) { $this->getLogger()->critical($e); throw new CouldNotSaveException( - __('An error occurred on the server. Please try to place the order again.'), + __('A server error stopped your order from being placed. Please try to place your order again.'), $e ); } diff --git a/app/code/Magento/Checkout/Model/PaymentInformationManagement.php b/app/code/Magento/Checkout/Model/PaymentInformationManagement.php index 3d6b0aa0cdc12..164109177d4e9 100644 --- a/app/code/Magento/Checkout/Model/PaymentInformationManagement.php +++ b/app/code/Magento/Checkout/Model/PaymentInformationManagement.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Checkout\Model; use Magento\Framework\Exception\CouldNotSaveException; @@ -89,7 +90,7 @@ public function savePaymentInformationAndPlaceOrder( } catch (\Exception $e) { $this->getLogger()->critical($e); throw new CouldNotSaveException( - __('An error occurred on the server. Please try to place the order again.'), + __('A server error stopped your order from being placed. Please try to place your order again.'), $e ); } diff --git a/app/code/Magento/Checkout/Model/ShippingInformationManagement.php b/app/code/Magento/Checkout/Model/ShippingInformationManagement.php index d8142d033f78c..381ee2b9015c9 100644 --- a/app/code/Magento/Checkout/Model/ShippingInformationManagement.php +++ b/app/code/Magento/Checkout/Model/ShippingInformationManagement.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Checkout\Model; use Magento\Framework\Exception\InputException; @@ -151,7 +152,7 @@ public function saveAddressInformation( } if (!$address->getCountryId()) { - throw new StateException(__('Shipping address is not set')); + throw new StateException(__('The shipping address is missing. Set the address and try again.')); } /** @var \Magento\Quote\Model\Quote $quote */ @@ -169,7 +170,9 @@ public function saveAddressInformation( $this->quoteRepository->save($quote); } catch (\Exception $e) { $this->logger->critical($e); - throw new InputException(__('Unable to save shipping information. Please check input data.')); + throw new InputException( + __('The shipping information was unable to be saved. Verify the input data and try again.') + ); } $shippingAddress = $quote->getShippingAddress(); @@ -198,7 +201,9 @@ public function saveAddressInformation( protected function validateQuote(\Magento\Quote\Model\Quote $quote) { if (0 == $quote->getItemsCount()) { - throw new InputException(__('Shipping method is not applicable for empty cart')); + throw new InputException( + __("The shipping method can't be set for an empty cart. Add an item to cart and try again.") + ); } } diff --git a/app/code/Magento/Checkout/Model/Sidebar.php b/app/code/Magento/Checkout/Model/Sidebar.php index 1a0e3aa818351..6f6655508f1b4 100644 --- a/app/code/Magento/Checkout/Model/Sidebar.php +++ b/app/code/Magento/Checkout/Model/Sidebar.php @@ -85,7 +85,7 @@ public function checkQuoteItem($itemId) { $item = $this->cart->getQuote()->getItemById($itemId); if (!$item instanceof CartItemInterface) { - throw new LocalizedException(__('We can\'t find the quote item.')); + throw new LocalizedException(__("The quote item isn't found. Verify the item and try again.")); } return $this; } diff --git a/app/code/Magento/Checkout/Setup/InstallData.php b/app/code/Magento/Checkout/Setup/Patch/Data/PrepareInitialCheckoutConfiguration.php similarity index 78% rename from app/code/Magento/Checkout/Setup/InstallData.php rename to app/code/Magento/Checkout/Setup/Patch/Data/PrepareInitialCheckoutConfiguration.php index 38879e06d65ac..c7a5ddca50f48 100644 --- a/app/code/Magento/Checkout/Setup/InstallData.php +++ b/app/code/Magento/Checkout/Setup/Patch/Data/PrepareInitialCheckoutConfiguration.php @@ -4,42 +4,46 @@ * See COPYING.txt for license details. */ -namespace Magento\Checkout\Setup; +namespace Magento\Checkout\Setup\Patch\Data; -use Magento\Customer\Helper\Address; use Magento\Eav\Setup\EavSetup; use Magento\Eav\Setup\EavSetupFactory; -use Magento\Framework\Setup\InstallDataInterface; -use Magento\Framework\Setup\ModuleContextInterface; +use Magento\Framework\App\ResourceConnection; use Magento\Framework\Setup\ModuleDataSetupInterface; +use Magento\Setup\Model\Patch\DataPatchInterface; +use Magento\Setup\Model\Patch\PatchVersionInterface; /** - * @codeCoverageIgnore + * Class PrepareInitialCheckoutConfiguration + * @package Magento\Checkout\Setup\Patch */ -class InstallData implements InstallDataInterface +class PrepareInitialCheckoutConfiguration implements DataPatchInterface, PatchVersionInterface { /** - * EAV setup factory - * + * @var ModuleDataSetupInterface + */ + private $moduleDataSetup; + + /** * @var EavSetupFactory */ private $eavSetupFactory; /** - * Customer address - * - * @var Address + * @var \Magento\Customer\Helper\Address */ private $customerAddress; /** - * Init - * - * @param EavSetupFactory $eavSetupFactory - * @param Address $customerAddress + * PatchInitial constructor. + * @param ModuleDataSetupInterface $moduleDataSetup */ - public function __construct(EavSetupFactory $eavSetupFactory, Address $customerAddress) - { + public function __construct( + ModuleDataSetupInterface $moduleDataSetup, + EavSetupFactory $eavSetupFactory, + \Magento\Customer\Helper\Address $customerAddress + ) { + $this->moduleDataSetup = $moduleDataSetup; $this->eavSetupFactory = $eavSetupFactory; $this->customerAddress = $customerAddress; } @@ -50,17 +54,17 @@ public function __construct(EavSetupFactory $eavSetupFactory, Address $customerA * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) */ - public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context) + public function apply() { /** @var EavSetup $eavSetup */ - $eavSetup = $this->eavSetupFactory->create(['setup' => $setup]); - - $setup->startSetup(); + $eavSetup = $this->eavSetupFactory->create(['setup' => $this->moduleDataSetup]); + + $this->moduleDataSetup->getConnection()->startSetup(); - $connection = $setup->getConnection(); + $connection = $this->moduleDataSetup->getConnection(); $select = $connection->select()->from( - $setup->getTable('core_config_data'), + $this->moduleDataSetup->getTable('core_config_data'), 'COUNT(*)' )->where( 'path=?', @@ -73,7 +77,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface || $connection->fetchOne($select) > 0; $select = $connection->select()->from( - $setup->getTable('core_config_data'), + $this->moduleDataSetup->getTable('core_config_data'), 'COUNT(*)' )->where( 'path=?', @@ -82,14 +86,11 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface 'value NOT LIKE ?', '0' ); - $showMiddlename = (bool)$this->customerAddress->getConfig( - 'middlename_show' - ) || $connection->fetchOne( - $select - ) > 0; + $showMiddlename = (bool)$this->customerAddress->getConfig('middlename_show') + || $connection->fetchOne($select) > 0; $select = $connection->select()->from( - $setup->getTable('core_config_data'), + $this->moduleDataSetup->getTable('core_config_data'), 'COUNT(*)' )->where( 'path=?', @@ -102,7 +103,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface || $connection->fetchOne($select) > 0; $select = $connection->select()->from( - $setup->getTable('core_config_data'), + $this->moduleDataSetup->getTable('core_config_data'), 'COUNT(*)' )->where( 'path=?', @@ -115,7 +116,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface || $connection->fetchOne($select) > 0; $select = $connection->select()->from( - $setup->getTable('core_config_data'), + $this->moduleDataSetup->getTable('core_config_data'), 'COUNT(*)' )->where( 'path=?', @@ -137,7 +138,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface */ $connection->insert( - $setup->getTable('eav_form_type'), + $this->moduleDataSetup->getTable('eav_form_type'), [ 'code' => 'checkout_onepage_register', 'label' => 'checkout_onepage_register', @@ -146,21 +147,21 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface 'store_id' => 0 ] ); - $formTypeId = $connection->lastInsertId($setup->getTable('eav_form_type')); + $formTypeId = $connection->lastInsertId($this->moduleDataSetup->getTable('eav_form_type')); $connection->insert( - $setup->getTable('eav_form_type_entity'), + $this->moduleDataSetup->getTable('eav_form_type_entity'), ['type_id' => $formTypeId, 'entity_type_id' => $customerEntityTypeId] ); $connection->insert( - $setup->getTable('eav_form_type_entity'), + $this->moduleDataSetup->getTable('eav_form_type_entity'), ['type_id' => $formTypeId, 'entity_type_id' => $addressEntityTypeId] ); $elementSort = 0; if ($showPrefix) { $connection->insert( - $setup->getTable('eav_form_element'), + $this->moduleDataSetup->getTable('eav_form_element'), [ 'type_id' => $formTypeId, 'fieldset_id' => null, @@ -170,7 +171,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ); } $connection->insert( - $setup->getTable('eav_form_element'), + $this->moduleDataSetup->getTable('eav_form_element'), [ 'type_id' => $formTypeId, 'fieldset_id' => null, @@ -180,7 +181,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ); if ($showMiddlename) { $connection->insert( - $setup->getTable('eav_form_element'), + $this->moduleDataSetup->getTable('eav_form_element'), [ 'type_id' => $formTypeId, 'fieldset_id' => null, @@ -190,7 +191,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ); } $connection->insert( - $setup->getTable('eav_form_element'), + $this->moduleDataSetup->getTable('eav_form_element'), [ 'type_id' => $formTypeId, 'fieldset_id' => null, @@ -200,7 +201,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ); if ($showSuffix) { $connection->insert( - $setup->getTable('eav_form_element'), + $this->moduleDataSetup->getTable('eav_form_element'), [ 'type_id' => $formTypeId, 'fieldset_id' => null, @@ -210,7 +211,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ); } $connection->insert( - $setup->getTable('eav_form_element'), + $this->moduleDataSetup->getTable('eav_form_element'), [ 'type_id' => $formTypeId, 'fieldset_id' => null, @@ -219,7 +220,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ] ); $connection->insert( - $setup->getTable('eav_form_element'), + $this->moduleDataSetup->getTable('eav_form_element'), [ 'type_id' => $formTypeId, 'fieldset_id' => null, @@ -228,7 +229,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ] ); $connection->insert( - $setup->getTable('eav_form_element'), + $this->moduleDataSetup->getTable('eav_form_element'), [ 'type_id' => $formTypeId, 'fieldset_id' => null, @@ -237,7 +238,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ] ); $connection->insert( - $setup->getTable('eav_form_element'), + $this->moduleDataSetup->getTable('eav_form_element'), [ 'type_id' => $formTypeId, 'fieldset_id' => null, @@ -246,7 +247,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ] ); $connection->insert( - $setup->getTable('eav_form_element'), + $this->moduleDataSetup->getTable('eav_form_element'), [ 'type_id' => $formTypeId, 'fieldset_id' => null, @@ -255,7 +256,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ] ); $connection->insert( - $setup->getTable('eav_form_element'), + $this->moduleDataSetup->getTable('eav_form_element'), [ 'type_id' => $formTypeId, 'fieldset_id' => null, @@ -264,7 +265,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ] ); $connection->insert( - $setup->getTable('eav_form_element'), + $this->moduleDataSetup->getTable('eav_form_element'), [ 'type_id' => $formTypeId, 'fieldset_id' => null, @@ -273,7 +274,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ] ); $connection->insert( - $setup->getTable('eav_form_element'), + $this->moduleDataSetup->getTable('eav_form_element'), [ 'type_id' => $formTypeId, 'fieldset_id' => null, @@ -282,7 +283,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ] ); $connection->insert( - $setup->getTable('eav_form_element'), + $this->moduleDataSetup->getTable('eav_form_element'), [ 'type_id' => $formTypeId, 'fieldset_id' => null, @@ -292,7 +293,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ); if ($showDob) { $connection->insert( - $setup->getTable('eav_form_element'), + $this->moduleDataSetup->getTable('eav_form_element'), [ 'type_id' => $formTypeId, 'fieldset_id' => null, @@ -303,7 +304,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface } if ($showTaxVat) { $connection->insert( - $setup->getTable('eav_form_element'), + $this->moduleDataSetup->getTable('eav_form_element'), [ 'type_id' => $formTypeId, 'fieldset_id' => null, @@ -320,7 +321,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface */ $connection->insert( - $setup->getTable('eav_form_type'), + $this->moduleDataSetup->getTable('eav_form_type'), [ 'code' => 'checkout_onepage_register_guest', 'label' => 'checkout_onepage_register_guest', @@ -329,21 +330,21 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface 'store_id' => 0 ] ); - $formTypeId = $connection->lastInsertId($setup->getTable('eav_form_type')); + $formTypeId = $connection->lastInsertId($this->moduleDataSetup->getTable('eav_form_type')); $connection->insert( - $setup->getTable('eav_form_type_entity'), + $this->moduleDataSetup->getTable('eav_form_type_entity'), ['type_id' => $formTypeId, 'entity_type_id' => $customerEntityTypeId] ); $connection->insert( - $setup->getTable('eav_form_type_entity'), + $this->moduleDataSetup->getTable('eav_form_type_entity'), ['type_id' => $formTypeId, 'entity_type_id' => $addressEntityTypeId] ); $elementSort = 0; if ($showPrefix) { $connection->insert( - $setup->getTable('eav_form_element'), + $this->moduleDataSetup->getTable('eav_form_element'), [ 'type_id' => $formTypeId, 'fieldset_id' => null, @@ -353,7 +354,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ); } $connection->insert( - $setup->getTable('eav_form_element'), + $this->moduleDataSetup->getTable('eav_form_element'), [ 'type_id' => $formTypeId, 'fieldset_id' => null, @@ -363,7 +364,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ); if ($showMiddlename) { $connection->insert( - $setup->getTable('eav_form_element'), + $this->moduleDataSetup->getTable('eav_form_element'), [ 'type_id' => $formTypeId, 'fieldset_id' => null, @@ -373,7 +374,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ); } $connection->insert( - $setup->getTable('eav_form_element'), + $this->moduleDataSetup->getTable('eav_form_element'), [ 'type_id' => $formTypeId, 'fieldset_id' => null, @@ -383,7 +384,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ); if ($showSuffix) { $connection->insert( - $setup->getTable('eav_form_element'), + $this->moduleDataSetup->getTable('eav_form_element'), [ 'type_id' => $formTypeId, 'fieldset_id' => null, @@ -393,7 +394,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ); } $connection->insert( - $setup->getTable('eav_form_element'), + $this->moduleDataSetup->getTable('eav_form_element'), [ 'type_id' => $formTypeId, 'fieldset_id' => null, @@ -402,7 +403,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ] ); $connection->insert( - $setup->getTable('eav_form_element'), + $this->moduleDataSetup->getTable('eav_form_element'), [ 'type_id' => $formTypeId, 'fieldset_id' => null, @@ -411,7 +412,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ] ); $connection->insert( - $setup->getTable('eav_form_element'), + $this->moduleDataSetup->getTable('eav_form_element'), [ 'type_id' => $formTypeId, 'fieldset_id' => null, @@ -420,7 +421,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ] ); $connection->insert( - $setup->getTable('eav_form_element'), + $this->moduleDataSetup->getTable('eav_form_element'), [ 'type_id' => $formTypeId, 'fieldset_id' => null, @@ -429,7 +430,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ] ); $connection->insert( - $setup->getTable('eav_form_element'), + $this->moduleDataSetup->getTable('eav_form_element'), [ 'type_id' => $formTypeId, 'fieldset_id' => null, @@ -438,7 +439,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ] ); $connection->insert( - $setup->getTable('eav_form_element'), + $this->moduleDataSetup->getTable('eav_form_element'), [ 'type_id' => $formTypeId, 'fieldset_id' => null, @@ -447,7 +448,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ] ); $connection->insert( - $setup->getTable('eav_form_element'), + $this->moduleDataSetup->getTable('eav_form_element'), [ 'type_id' => $formTypeId, 'fieldset_id' => null, @@ -456,7 +457,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ] ); $connection->insert( - $setup->getTable('eav_form_element'), + $this->moduleDataSetup->getTable('eav_form_element'), [ 'type_id' => $formTypeId, 'fieldset_id' => null, @@ -465,7 +466,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ] ); $connection->insert( - $setup->getTable('eav_form_element'), + $this->moduleDataSetup->getTable('eav_form_element'), [ 'type_id' => $formTypeId, 'fieldset_id' => null, @@ -475,7 +476,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ); if ($showDob) { $connection->insert( - $setup->getTable('eav_form_element'), + $this->moduleDataSetup->getTable('eav_form_element'), [ 'type_id' => $formTypeId, 'fieldset_id' => null, @@ -486,7 +487,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface } if ($showTaxVat) { $connection->insert( - $setup->getTable('eav_form_element'), + $this->moduleDataSetup->getTable('eav_form_element'), [ 'type_id' => $formTypeId, 'fieldset_id' => null, @@ -503,7 +504,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface */ $connection->insert( - $setup->getTable('eav_form_type'), + $this->moduleDataSetup->getTable('eav_form_type'), [ 'code' => 'checkout_onepage_billing_address', 'label' => 'checkout_onepage_billing_address', @@ -512,17 +513,17 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface 'store_id' => 0 ] ); - $formTypeId = $connection->lastInsertId($setup->getTable('eav_form_type')); + $formTypeId = $connection->lastInsertId($this->moduleDataSetup->getTable('eav_form_type')); $connection->insert( - $setup->getTable('eav_form_type_entity'), + $this->moduleDataSetup->getTable('eav_form_type_entity'), ['type_id' => $formTypeId, 'entity_type_id' => $addressEntityTypeId] ); $elementSort = 0; if ($showPrefix) { $connection->insert( - $setup->getTable('eav_form_element'), + $this->moduleDataSetup->getTable('eav_form_element'), [ 'type_id' => $formTypeId, 'fieldset_id' => null, @@ -532,7 +533,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ); } $connection->insert( - $setup->getTable('eav_form_element'), + $this->moduleDataSetup->getTable('eav_form_element'), [ 'type_id' => $formTypeId, 'fieldset_id' => null, @@ -542,7 +543,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ); if ($showMiddlename) { $connection->insert( - $setup->getTable('eav_form_element'), + $this->moduleDataSetup->getTable('eav_form_element'), [ 'type_id' => $formTypeId, 'fieldset_id' => null, @@ -552,7 +553,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ); } $connection->insert( - $setup->getTable('eav_form_element'), + $this->moduleDataSetup->getTable('eav_form_element'), [ 'type_id' => $formTypeId, 'fieldset_id' => null, @@ -562,7 +563,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ); if ($showSuffix) { $connection->insert( - $setup->getTable('eav_form_element'), + $this->moduleDataSetup->getTable('eav_form_element'), [ 'type_id' => $formTypeId, 'fieldset_id' => null, @@ -572,7 +573,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ); } $connection->insert( - $setup->getTable('eav_form_element'), + $this->moduleDataSetup->getTable('eav_form_element'), [ 'type_id' => $formTypeId, 'fieldset_id' => null, @@ -581,7 +582,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ] ); $connection->insert( - $setup->getTable('eav_form_element'), + $this->moduleDataSetup->getTable('eav_form_element'), [ 'type_id' => $formTypeId, 'fieldset_id' => null, @@ -590,7 +591,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ] ); $connection->insert( - $setup->getTable('eav_form_element'), + $this->moduleDataSetup->getTable('eav_form_element'), [ 'type_id' => $formTypeId, 'fieldset_id' => null, @@ -599,7 +600,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ] ); $connection->insert( - $setup->getTable('eav_form_element'), + $this->moduleDataSetup->getTable('eav_form_element'), [ 'type_id' => $formTypeId, 'fieldset_id' => null, @@ -608,7 +609,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ] ); $connection->insert( - $setup->getTable('eav_form_element'), + $this->moduleDataSetup->getTable('eav_form_element'), [ 'type_id' => $formTypeId, 'fieldset_id' => null, @@ -617,7 +618,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ] ); $connection->insert( - $setup->getTable('eav_form_element'), + $this->moduleDataSetup->getTable('eav_form_element'), [ 'type_id' => $formTypeId, 'fieldset_id' => null, @@ -626,7 +627,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ] ); $connection->insert( - $setup->getTable('eav_form_element'), + $this->moduleDataSetup->getTable('eav_form_element'), [ 'type_id' => $formTypeId, 'fieldset_id' => null, @@ -635,7 +636,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ] ); $connection->insert( - $setup->getTable('eav_form_element'), + $this->moduleDataSetup->getTable('eav_form_element'), [ 'type_id' => $formTypeId, 'fieldset_id' => null, @@ -651,7 +652,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface */ $connection->insert( - $setup->getTable('eav_form_type'), + $this->moduleDataSetup->getTable('eav_form_type'), [ 'code' => 'checkout_onepage_shipping_address', 'label' => 'checkout_onepage_shipping_address', @@ -660,17 +661,17 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface 'store_id' => 0 ] ); - $formTypeId = $connection->lastInsertId($setup->getTable('eav_form_type')); + $formTypeId = $connection->lastInsertId($this->moduleDataSetup->getTable('eav_form_type')); $connection->insert( - $setup->getTable('eav_form_type_entity'), + $this->moduleDataSetup->getTable('eav_form_type_entity'), ['type_id' => $formTypeId, 'entity_type_id' => $addressEntityTypeId] ); $elementSort = 0; if ($showPrefix) { $connection->insert( - $setup->getTable('eav_form_element'), + $this->moduleDataSetup->getTable('eav_form_element'), [ 'type_id' => $formTypeId, 'fieldset_id' => null, @@ -680,7 +681,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ); } $connection->insert( - $setup->getTable('eav_form_element'), + $this->moduleDataSetup->getTable('eav_form_element'), [ 'type_id' => $formTypeId, 'fieldset_id' => null, @@ -690,7 +691,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ); if ($showMiddlename) { $connection->insert( - $setup->getTable('eav_form_element'), + $this->moduleDataSetup->getTable('eav_form_element'), [ 'type_id' => $formTypeId, 'fieldset_id' => null, @@ -700,7 +701,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ); } $connection->insert( - $setup->getTable('eav_form_element'), + $this->moduleDataSetup->getTable('eav_form_element'), [ 'type_id' => $formTypeId, 'fieldset_id' => null, @@ -710,7 +711,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ); if ($showSuffix) { $connection->insert( - $setup->getTable('eav_form_element'), + $this->moduleDataSetup->getTable('eav_form_element'), [ 'type_id' => $formTypeId, 'fieldset_id' => null, @@ -720,7 +721,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ); } $connection->insert( - $setup->getTable('eav_form_element'), + $this->moduleDataSetup->getTable('eav_form_element'), [ 'type_id' => $formTypeId, 'fieldset_id' => null, @@ -729,7 +730,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ] ); $connection->insert( - $setup->getTable('eav_form_element'), + $this->moduleDataSetup->getTable('eav_form_element'), [ 'type_id' => $formTypeId, 'fieldset_id' => null, @@ -738,7 +739,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ] ); $connection->insert( - $setup->getTable('eav_form_element'), + $this->moduleDataSetup->getTable('eav_form_element'), [ 'type_id' => $formTypeId, 'fieldset_id' => null, @@ -747,7 +748,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ] ); $connection->insert( - $setup->getTable('eav_form_element'), + $this->moduleDataSetup->getTable('eav_form_element'), [ 'type_id' => $formTypeId, 'fieldset_id' => null, @@ -756,7 +757,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ] ); $connection->insert( - $setup->getTable('eav_form_element'), + $this->moduleDataSetup->getTable('eav_form_element'), [ 'type_id' => $formTypeId, 'fieldset_id' => null, @@ -765,7 +766,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ] ); $connection->insert( - $setup->getTable('eav_form_element'), + $this->moduleDataSetup->getTable('eav_form_element'), [ 'type_id' => $formTypeId, 'fieldset_id' => null, @@ -774,7 +775,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ] ); $connection->insert( - $setup->getTable('eav_form_element'), + $this->moduleDataSetup->getTable('eav_form_element'), [ 'type_id' => $formTypeId, 'fieldset_id' => null, @@ -783,7 +784,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ] ); $connection->insert( - $setup->getTable('eav_form_element'), + $this->moduleDataSetup->getTable('eav_form_element'), [ 'type_id' => $formTypeId, 'fieldset_id' => null, @@ -792,7 +793,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ] ); - $table = $setup->getTable('core_config_data'); + $table = $this->moduleDataSetup->getTable('core_config_data'); $select = $connection->select()->from( $table, @@ -821,6 +822,30 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface } } - $setup->endSetup(); + $connection->endSetup(); + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return []; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.0'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; } } diff --git a/app/code/Magento/Checkout/Test/Unit/Model/GuestPaymentInformationManagementTest.php b/app/code/Magento/Checkout/Test/Unit/Model/GuestPaymentInformationManagementTest.php index 5fa12521fc3e6..ba6bba6d6333d 100644 --- a/app/code/Magento/Checkout/Test/Unit/Model/GuestPaymentInformationManagementTest.php +++ b/app/code/Magento/Checkout/Test/Unit/Model/GuestPaymentInformationManagementTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Checkout\Test\Unit\Model; /** @@ -98,7 +99,6 @@ public function testSavePaymentInformationAndPlaceOrder() } /** - * @expectedExceptionMessage An error occurred on the server. Please try to place the order again. * @expectedException \Magento\Framework\Exception\CouldNotSaveException */ public function testSavePaymentInformationAndPlaceOrderException() @@ -118,6 +118,10 @@ public function testSavePaymentInformationAndPlaceOrderException() $this->cartManagementMock->expects($this->once())->method('placeOrder')->willThrowException($exception); $this->model->savePaymentInformationAndPlaceOrder($cartId, $email, $paymentMock, $billingAddressMock); + + $this->expectExceptionMessage( + 'A server error stopped your order from being placed. Please try to place your order again.' + ); } public function testSavePaymentInformation() diff --git a/app/code/Magento/Checkout/Test/Unit/Model/PaymentInformationManagementTest.php b/app/code/Magento/Checkout/Test/Unit/Model/PaymentInformationManagementTest.php index b40b2b244ac4c..77c15fccfa8ae 100644 --- a/app/code/Magento/Checkout/Test/Unit/Model/PaymentInformationManagementTest.php +++ b/app/code/Magento/Checkout/Test/Unit/Model/PaymentInformationManagementTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Checkout\Test\Unit\Model; /** @@ -83,7 +84,6 @@ public function testSavePaymentInformationAndPlaceOrder() } /** - * @expectedExceptionMessage An error occurred on the server. Please try to place the order again. * @expectedException \Magento\Framework\Exception\CouldNotSaveException */ public function testSavePaymentInformationAndPlaceOrderException() @@ -99,6 +99,10 @@ public function testSavePaymentInformationAndPlaceOrderException() $this->cartManagementMock->expects($this->once())->method('placeOrder')->willThrowException($exception); $this->model->savePaymentInformationAndPlaceOrder($cartId, $paymentMock, $billingAddressMock); + + $this->expectExceptionMessage( + 'A server error stopped your order from being placed. Please try to place your order again.' + ); } public function testSavePaymentInformationAndPlaceOrderIfBillingAddressNotExist() diff --git a/app/code/Magento/Checkout/Test/Unit/Model/ShippingInformationManagementTest.php b/app/code/Magento/Checkout/Test/Unit/Model/ShippingInformationManagementTest.php index 5c6314b2a35c8..dd88b7161acdf 100644 --- a/app/code/Magento/Checkout/Test/Unit/Model/ShippingInformationManagementTest.php +++ b/app/code/Magento/Checkout/Test/Unit/Model/ShippingInformationManagementTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Checkout\Test\Unit\Model; /** @@ -157,7 +158,7 @@ protected function setUp() /** * @expectedException \Magento\Framework\Exception\InputException - * @expectedExceptionMessage Shipping method is not applicable for empty cart + * @expectedExceptionMessage The shipping method can't be set for an empty cart. Add an item to cart and try again. */ public function testSaveAddressInformationIfCartIsEmpty() { @@ -238,7 +239,7 @@ private function setShippingAssignmentsMocks($shippingMethod) /** * @expectedException \Magento\Framework\Exception\StateException - * @expectedExceptionMessage Shipping address is not set + * @expectedExceptionMessage The shipping address is missing. Set the address and try again. */ public function testSaveAddressInformationIfShippingAddressNotSet() { @@ -263,7 +264,7 @@ public function testSaveAddressInformationIfShippingAddressNotSet() /** * @expectedException \Magento\Framework\Exception\InputException - * @expectedExceptionMessage Unable to save shipping information. Please check input data. + * @expectedExceptionMessage The shipping information was unable to be saved. Verify the input data and try again. */ public function testSaveAddressInformationIfCanNotSaveQuote() { diff --git a/app/code/Magento/Checkout/Test/Unit/Model/SidebarTest.php b/app/code/Magento/Checkout/Test/Unit/Model/SidebarTest.php index 29537e8ec0526..c07413c8611d0 100644 --- a/app/code/Magento/Checkout/Test/Unit/Model/SidebarTest.php +++ b/app/code/Magento/Checkout/Test/Unit/Model/SidebarTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Checkout\Test\Unit\Model; use Magento\Checkout\Model\Sidebar; @@ -94,7 +95,7 @@ public function testCheckQuoteItem() /** * @expectedException \Magento\Framework\Exception\LocalizedException - * @exceptedExceptionMessage We can't find the quote item. + * @exceptedExceptionMessage The quote item isn't found. Verify the item and try again. */ public function testCheckQuoteItemWithException() { diff --git a/app/code/Magento/Checkout/etc/module.xml b/app/code/Magento/Checkout/etc/module.xml index 219ca87337fc9..153de5ef2a790 100644 --- a/app/code/Magento/Checkout/etc/module.xml +++ b/app/code/Magento/Checkout/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/Checkout/view/frontend/templates/cart/item/configure/updatecart.phtml b/app/code/Magento/Checkout/view/frontend/templates/cart/item/configure/updatecart.phtml index b41d548e95b99..c1db2f7775ca8 100644 --- a/app/code/Magento/Checkout/view/frontend/templates/cart/item/configure/updatecart.phtml +++ b/app/code/Magento/Checkout/view/frontend/templates/cart/item/configure/updatecart.phtml @@ -23,7 +23,7 @@ value="" title="" class="input-text qty" - data-validate="{'required-number':true,digits:true}"/> + data-validate="escapeHtml(json_encode($block->getQuantityValidators())) ?>"/>
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/shipping.js b/app/code/Magento/Checkout/view/frontend/web/js/view/shipping.js index 619de95e467f0..a7cb7f7e7de84 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/view/shipping.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/view/shipping.js @@ -266,7 +266,9 @@ define([ field; if (!quote.shippingMethod()) { - this.errorValidationMessage($t('Please specify a shipping method.')); + this.errorValidationMessage( + $t('The shipping method is missing. Select the shipping method and try again.') + ); return false; } diff --git a/app/code/Magento/CheckoutAgreements/Model/Checkout/Plugin/GuestValidation.php b/app/code/Magento/CheckoutAgreements/Model/Checkout/Plugin/GuestValidation.php index 4176334bb4a3e..fbceca0906702 100644 --- a/app/code/Magento/CheckoutAgreements/Model/Checkout/Plugin/GuestValidation.php +++ b/app/code/Magento/CheckoutAgreements/Model/Checkout/Plugin/GuestValidation.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\CheckoutAgreements\Model\Checkout\Plugin; use Magento\CheckoutAgreements\Model\AgreementsProvider; @@ -113,7 +114,10 @@ private function validateAgreements(\Magento\Quote\Api\Data\PaymentInterface $pa if (!$this->agreementsValidator->isValid($agreements)) { throw new \Magento\Framework\Exception\CouldNotSaveException( - __('Please agree to all the terms and conditions before placing the order.') + __( + "The order wasn't placed. " + . "First, agree to the terms and conditions, then try placing your order again." + ) ); } } diff --git a/app/code/Magento/CheckoutAgreements/Model/Checkout/Plugin/Validation.php b/app/code/Magento/CheckoutAgreements/Model/Checkout/Plugin/Validation.php index b8a6afff4fced..67e2a6c9ec334 100644 --- a/app/code/Magento/CheckoutAgreements/Model/Checkout/Plugin/Validation.php +++ b/app/code/Magento/CheckoutAgreements/Model/Checkout/Plugin/Validation.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\CheckoutAgreements\Model\Checkout\Plugin; use Magento\CheckoutAgreements\Model\AgreementsProvider; @@ -105,7 +106,10 @@ protected function validateAgreements(\Magento\Quote\Api\Data\PaymentInterface $ if (!$this->agreementsValidator->isValid($agreements)) { throw new \Magento\Framework\Exception\CouldNotSaveException( - __('Please agree to all the terms and conditions before placing the order.') + __( + "The order wasn't placed. " + . "First, agree to the terms and conditions, then try placing your order again." + ) ); } } diff --git a/app/code/Magento/CheckoutAgreements/Model/CheckoutAgreementsRepository.php b/app/code/Magento/CheckoutAgreements/Model/CheckoutAgreementsRepository.php index 9379b73a1b964..60cc1f98264aa 100644 --- a/app/code/Magento/CheckoutAgreements/Model/CheckoutAgreementsRepository.php +++ b/app/code/Magento/CheckoutAgreements/Model/CheckoutAgreementsRepository.php @@ -138,7 +138,7 @@ public function save(\Magento\CheckoutAgreements\Api\Data\AgreementInterface $da $this->resourceModel->save($data); } catch (\Exception $e) { throw new \Magento\Framework\Exception\CouldNotSaveException( - __('Unable to save checkout agreement %1', $data->getAgreementId()) + __('The "%1" checkout agreement couldn\'t be saved.', $data->getAgreementId()) ); } return $data; @@ -153,7 +153,7 @@ public function delete(\Magento\CheckoutAgreements\Api\Data\AgreementInterface $ $this->resourceModel->delete($data); } catch (\Exception $e) { throw new \Magento\Framework\Exception\CouldNotDeleteException( - __('Unable to remove checkout agreement %1', $data->getAgreementId()) + __('The "%1" checkout agreement couldn\'t be removed.', $data->getAgreementId()) ); } return true; @@ -178,7 +178,9 @@ public function get($id, $storeId = null) $agreement = $this->agreementFactory->create(); $this->resourceModel->load($agreement, $id); if (!$agreement->getId()) { - throw new NoSuchEntityException(__('Checkout agreement with specified ID "%1" not found.', $id)); + throw new NoSuchEntityException( + __('A checkout agreement with the "%1" specified ID wasn\'t found. Verify the ID and try again.', $id) + ); } return $agreement; } diff --git a/app/code/Magento/CheckoutAgreements/Test/Unit/Model/Checkout/Plugin/GuestValidationTest.php b/app/code/Magento/CheckoutAgreements/Test/Unit/Model/Checkout/Plugin/GuestValidationTest.php index baaaad1bb6aff..3d7b910c7abc5 100644 --- a/app/code/Magento/CheckoutAgreements/Test/Unit/Model/Checkout/Plugin/GuestValidationTest.php +++ b/app/code/Magento/CheckoutAgreements/Test/Unit/Model/Checkout/Plugin/GuestValidationTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\CheckoutAgreements\Test\Unit\Model\Checkout\Plugin; use Magento\CheckoutAgreements\Model\AgreementsProvider; @@ -119,7 +120,6 @@ public function testBeforeSavePaymentInformationAndPlaceOrder() /** * @expectedException \Magento\Framework\Exception\CouldNotSaveException - * @expectedExceptionMessage Please agree to all the terms and conditions before placing the order. */ public function testBeforeSavePaymentInformationAndPlaceOrderIfAgreementsNotValid() { @@ -151,6 +151,10 @@ public function testBeforeSavePaymentInformationAndPlaceOrderIfAgreementsNotVali $this->paymentMock, $this->addressMock ); + + $this->expectExceptionMessage( + "The order wasn't placed. First, agree to the terms and conditions, then try placing your order again." + ); } public function testBeforeSavePaymentInformation() diff --git a/app/code/Magento/CheckoutAgreements/Test/Unit/Model/Checkout/Plugin/ValidationTest.php b/app/code/Magento/CheckoutAgreements/Test/Unit/Model/Checkout/Plugin/ValidationTest.php index b77cab203eb6b..7f11fad202401 100644 --- a/app/code/Magento/CheckoutAgreements/Test/Unit/Model/Checkout/Plugin/ValidationTest.php +++ b/app/code/Magento/CheckoutAgreements/Test/Unit/Model/Checkout/Plugin/ValidationTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\CheckoutAgreements\Test\Unit\Model\Checkout\Plugin; use Magento\CheckoutAgreements\Model\AgreementsProvider; @@ -112,7 +113,6 @@ public function testBeforeSavePaymentInformationAndPlaceOrder() /** * @expectedException \Magento\Framework\Exception\CouldNotSaveException - * @expectedExceptionMessage Please agree to all the terms and conditions before placing the order. */ public function testBeforeSavePaymentInformationAndPlaceOrderIfAgreementsNotValid() { @@ -137,6 +137,10 @@ public function testBeforeSavePaymentInformationAndPlaceOrderIfAgreementsNotVali ->method('getExtensionAttributes') ->willReturn($this->extensionAttributesMock); $this->model->beforeSavePaymentInformation($this->subjectMock, $cartId, $this->paymentMock, $this->addressMock); + + $this->expectExceptionMessage( + "The order wasn't placed. First, agree to the terms and conditions, then try placing your order again." + ); } public function testBeforeSavePaymentInformation() diff --git a/app/code/Magento/CheckoutAgreements/etc/module.xml b/app/code/Magento/CheckoutAgreements/etc/module.xml index 42a373eaad429..1ea97b556be67 100644 --- a/app/code/Magento/CheckoutAgreements/etc/module.xml +++ b/app/code/Magento/CheckoutAgreements/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/Cms/Block/Adminhtml/Wysiwyg/Images/Content.php b/app/code/Magento/Cms/Block/Adminhtml/Wysiwyg/Images/Content.php index f1e1b3797d8d3..44c2f3ca2f8c4 100644 --- a/app/code/Magento/Cms/Block/Adminhtml/Wysiwyg/Images/Content.php +++ b/app/code/Magento/Cms/Block/Adminhtml/Wysiwyg/Images/Content.php @@ -92,7 +92,10 @@ protected function _construct() */ public function getContentsUrl() { - return $this->getUrl('cms/*/contents', ['type' => $this->getRequest()->getParam('type')]); + return $this->getUrl('cms/*/contents', [ + 'type' => $this->getRequest()->getParam('type'), + 'use_storage_root' => (int) $this->getRequest()->getParam('use_storage_root'), + ]); } /** @@ -140,7 +143,9 @@ public function getNewfolderUrl() */ protected function getDeletefolderUrl() { - return $this->getUrl('cms/*/deleteFolder'); + return $this->getUrl('cms/*/deleteFolder', [ + 'use_storage_root' => (int) $this->getRequest()->getParam('use_storage_root'), + ]); } /** @@ -160,7 +165,9 @@ public function getDeleteFilesUrl() */ public function getOnInsertUrl() { - return $this->getUrl('cms/*/onInsert'); + return $this->getUrl('cms/*/onInsert', [ + 'use_storage_root' => (int) $this->getRequest()->getParam('use_storage_root'), + ]); } /** diff --git a/app/code/Magento/Cms/Block/Adminhtml/Wysiwyg/Images/Tree.php b/app/code/Magento/Cms/Block/Adminhtml/Wysiwyg/Images/Tree.php index 5471bbfb8b0f3..7bed7cee308f5 100644 --- a/app/code/Magento/Cms/Block/Adminhtml/Wysiwyg/Images/Tree.php +++ b/app/code/Magento/Cms/Block/Adminhtml/Wysiwyg/Images/Tree.php @@ -69,12 +69,21 @@ public function getTreeJson() ); $jsonArray = []; foreach ($collection as $item) { - $jsonArray[] = [ + $data = [ 'text' => $this->_cmsWysiwygImages->getShortFilename($item->getBasename(), 20), 'id' => $this->_cmsWysiwygImages->convertPathToId($item->getFilename()), 'path' => substr($item->getFilename(), strlen($storageRoot)), 'cls' => 'folder', ]; + + $hasNestedDirectories = count(glob($item->getFilename() . '/*', GLOB_ONLYDIR)) > 0; + + // if no nested directories inside dir, add 'leaf' state so that jstree hides dropdown arrow next to dir + if (!$hasNestedDirectories) { + $data['state'] = 'leaf'; + } + + $jsonArray[] = $data; } return $this->serializer->serialize($jsonArray); } @@ -86,7 +95,10 @@ public function getTreeJson() */ public function getTreeLoaderUrl() { - return $this->getUrl('cms/*/treeJson'); + return $this->getUrl( + 'cms/*/treeJson', + ['use_storage_root' => (int) $this->getRequest()->getParam('use_storage_root')] + ); } /** diff --git a/app/code/Magento/Cms/Controller/Adminhtml/Wysiwyg/Images/OnInsert.php b/app/code/Magento/Cms/Controller/Adminhtml/Wysiwyg/Images/OnInsert.php index 2daaf39d58d14..3244a7d14f0a3 100644 --- a/app/code/Magento/Cms/Controller/Adminhtml/Wysiwyg/Images/OnInsert.php +++ b/app/code/Magento/Cms/Controller/Adminhtml/Wysiwyg/Images/OnInsert.php @@ -34,17 +34,26 @@ public function __construct( */ public function execute() { - $helper = $this->_objectManager->get(\Magento\Cms\Helper\Wysiwyg\Images::class); - $storeId = $this->getRequest()->getParam('store'); + $imagesHelper = $this->_objectManager->get(\Magento\Cms\Helper\Wysiwyg\Images::class); + $request = $this->getRequest(); - $filename = $this->getRequest()->getParam('filename'); - $filename = $helper->idDecode($filename); - $asIs = $this->getRequest()->getParam('as_is'); + $storeId = $request->getParam('store'); + + $filename = $request->getParam('filename'); + $filename = $imagesHelper->idDecode($filename); + + $asIs = $request->getParam('as_is'); + + $forceStaticPath = $request->getParam('force_static_path'); $this->_objectManager->get(\Magento\Catalog\Helper\Data::class)->setStoreId($storeId); - $helper->setStoreId($storeId); + $imagesHelper->setStoreId($storeId); - $image = $helper->getImageHtmlDeclaration($filename, $asIs); + if ($forceStaticPath) { + $image = parse_url($imagesHelper->getCurrentUrl() . $filename, PHP_URL_PATH); + } else { + $image = $imagesHelper->getImageHtmlDeclaration($filename, $asIs); + } /** @var \Magento\Framework\Controller\Result\Raw $resultRaw */ $resultRaw = $this->resultRawFactory->create(); diff --git a/app/code/Magento/Cms/Helper/Wysiwyg/Images.php b/app/code/Magento/Cms/Helper/Wysiwyg/Images.php index 891b4a2d12045..3e410799906a1 100644 --- a/app/code/Magento/Cms/Helper/Wysiwyg/Images.php +++ b/app/code/Magento/Cms/Helper/Wysiwyg/Images.php @@ -9,10 +9,16 @@ /** * Wysiwyg Images Helper - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class Images extends \Magento\Framework\App\Helper\AbstractHelper { + /** + * Image directory subpath relative to media directory + * + * @var string + */ + private $imageDirectorySubpath; + /** * Current directory path * @var string @@ -80,7 +86,7 @@ public function __construct( $this->escaper = $escaper; $this->_directory = $filesystem->getDirectoryWrite(DirectoryList::MEDIA); - $this->_directory->create(\Magento\Cms\Model\Wysiwyg\Config::IMAGE_DIRECTORY); + $this->_directory->create($this->getStorageRoot()); } /** @@ -102,7 +108,19 @@ public function setStoreId($store) */ public function getStorageRoot() { - return $this->_directory->getAbsolutePath(\Magento\Cms\Model\Wysiwyg\Config::IMAGE_DIRECTORY); + return $this->_directory->getAbsolutePath($this->getStorageRootSubpath()); + } + + /** + * Get image storage root subpath. User is unable to traverse outside of this subpath in media gallery + * + * @return string + */ + public function getStorageRootSubpath() + { + return $this->_getRequest()->getParam('use_storage_root') + ? '' + : \Magento\Cms\Model\Wysiwyg\Config::IMAGE_DIRECTORY; } /** @@ -159,7 +177,7 @@ public function convertIdToPath($id) */ public function isUsingStaticUrlsAllowed() { - $checkResult = new \stdClass(); + $checkResult = (object) []; $checkResult->isAllowed = false; $this->_eventManager->dispatch( 'cms_wysiwyg_images_static_urls_allowed', @@ -211,7 +229,7 @@ public function getImageHtmlDeclaration($filename, $renderAsTag = false) public function getCurrentPath() { if (!$this->_currentPath) { - $currentPath = $this->_directory->getAbsolutePath() . \Magento\Cms\Model\Wysiwyg\Config::IMAGE_DIRECTORY; + $currentPath = $this->getStorageRoot(); $path = $this->_getRequest()->getParam($this->getTreeNodeName()); if ($path) { $path = $this->convertIdToPath($path); @@ -247,7 +265,7 @@ public function getCurrentUrl() )->getBaseUrl( \Magento\Framework\UrlInterface::URL_TYPE_MEDIA ); - $this->_currentUrl = $mediaUrl . $this->_directory->getRelativePath($path) . '/'; + $this->_currentUrl = rtrim($mediaUrl . $this->_directory->getRelativePath($path), '/') . '/'; } return $this->_currentUrl; } @@ -289,4 +307,15 @@ public function getShortFilename($filename, $maxLength = 20) } return substr($filename, 0, $maxLength) . '...'; } + + /** + * Set user-traversable image directory subpath relative to media directory and relative to nested storage root + * + * @var string $subpath + * @return void + */ + public function setImageDirectorySubpath($subpath) + { + $this->imageDirectorySubpath = $subpath; + } } diff --git a/app/code/Magento/Cms/Model/BlockRepository.php b/app/code/Magento/Cms/Model/BlockRepository.php index e724c1581e8f5..fa29cc9ff7631 100644 --- a/app/code/Magento/Cms/Model/BlockRepository.php +++ b/app/code/Magento/Cms/Model/BlockRepository.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Cms\Model; use Magento\Cms\Api\BlockRepositoryInterface; @@ -134,7 +135,7 @@ public function getById($blockId) $block = $this->blockFactory->create(); $this->resource->load($block, $blockId); if (!$block->getId()) { - throw new NoSuchEntityException(__('CMS Block with id "%1" does not exist.', $blockId)); + throw new NoSuchEntityException(__('The CMS block with the "%1" ID doesn\'t exist.', $blockId)); } return $block; } diff --git a/app/code/Magento/Cms/Model/GetBlockByIdentifier.php b/app/code/Magento/Cms/Model/GetBlockByIdentifier.php index 587785ce3d842..071e6225c82a2 100644 --- a/app/code/Magento/Cms/Model/GetBlockByIdentifier.php +++ b/app/code/Magento/Cms/Model/GetBlockByIdentifier.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Cms\Model; use Magento\Cms\Api\GetBlockByIdentifierInterface; @@ -46,7 +47,7 @@ public function execute(string $identifier, int $storeId) : BlockInterface $this->blockResource->load($block, $identifier, BlockInterface::IDENTIFIER); if (!$block->getId()) { - throw new NoSuchEntityException(__('CMS Block with identifier "%1" does not exist.', $identifier)); + throw new NoSuchEntityException(__('The CMS block with the "%1" ID doesn\'t exist.', $identifier)); } return $block; diff --git a/app/code/Magento/Cms/Model/GetPageByIdentifier.php b/app/code/Magento/Cms/Model/GetPageByIdentifier.php index d12e7749f7d7a..d3ad65fb01183 100644 --- a/app/code/Magento/Cms/Model/GetPageByIdentifier.php +++ b/app/code/Magento/Cms/Model/GetPageByIdentifier.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Cms\Model; use Magento\Cms\Api\Data\PageInterface; @@ -46,7 +47,7 @@ public function execute(string $identifier, int $storeId) : PageInterface $this->pageResource->load($page, $identifier, PageInterface::IDENTIFIER); if (!$page->getId()) { - throw new NoSuchEntityException(__('CMS Page with identifier "%1" does not exist.', $identifier)); + throw new NoSuchEntityException(__('The CMS page with the "%1" ID doesn\'t exist.', $identifier)); } return $page; diff --git a/app/code/Magento/Cms/Model/PageRepository.php b/app/code/Magento/Cms/Model/PageRepository.php index 9c9e18211aa86..65b23bce7e94c 100644 --- a/app/code/Magento/Cms/Model/PageRepository.php +++ b/app/code/Magento/Cms/Model/PageRepository.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Cms\Model; use Magento\Cms\Api\Data; @@ -137,7 +138,7 @@ public function getById($pageId) $page = $this->pageFactory->create(); $page->load($pageId); if (!$page->getId()) { - throw new NoSuchEntityException(__('CMS Page with id "%1" does not exist.', $pageId)); + throw new NoSuchEntityException(__('The CMS page with the "%1" ID doesn\'t exist.', $pageId)); } return $page; } diff --git a/app/code/Magento/Cms/Model/ResourceModel/Page.php b/app/code/Magento/Cms/Model/ResourceModel/Page.php index b836cf199632d..079d64d2882a5 100644 --- a/app/code/Magento/Cms/Model/ResourceModel/Page.php +++ b/app/code/Magento/Cms/Model/ResourceModel/Page.php @@ -117,13 +117,16 @@ protected function _beforeSave(AbstractModel $object) if (!$this->isValidPageIdentifier($object)) { throw new LocalizedException( - __('The page URL key contains capital letters or disallowed symbols.') + __( + "The page URL key can't use capital letters or disallowed symbols. " + . "Remove the letters and symbols and try again." + ) ); } if ($this->isNumericPageIdentifier($object)) { throw new LocalizedException( - __('The page URL key cannot be made of only numbers.') + __("The page URL key can't use only numbers. Add letters or words and try again.") ); } return parent::_beforeSave($object); diff --git a/app/code/Magento/Cms/Model/Wysiwyg/CompositeConfigProvider.php b/app/code/Magento/Cms/Model/Wysiwyg/CompositeConfigProvider.php index b2f32132ad3a4..a97529a7d4e45 100644 --- a/app/code/Magento/Cms/Model/Wysiwyg/CompositeConfigProvider.php +++ b/app/code/Magento/Cms/Model/Wysiwyg/CompositeConfigProvider.php @@ -130,12 +130,16 @@ public function processWysiwygConfig($config) /** * Returns active editor path * + * @param \Magento\Framework\DataObject $config * @return string */ - private function getActiveEditorPath() + private function getActiveEditorPath($config) { - if (!isset($this->activeEditorPath)) { - $this->activeEditorPath = $this->activeEditor->getWysiwygAdapterPath(); + if (!isset($this->activeEditorPath) || $this->activeEditorPath !== $config->getData('activeEditorPath')) { + $this->activeEditorPath = $config->getData('activeEditorPath') + ? $config->getData('activeEditorPath') + : $this->activeEditor->getWysiwygAdapterPath(); + $config->setData('activeEditorPath', $this->activeEditorPath); } return $this->activeEditorPath; } @@ -149,7 +153,7 @@ private function getActiveEditorPath() */ private function updateConfig($config, array $configProviders) { - $adapterType = $this->getActiveEditorPath(); + $adapterType = $this->getActiveEditorPath($config); //Extension point to update plugin settings by adapter type $providerClass = isset($configProviders[$adapterType]) ? $configProviders[$adapterType] diff --git a/app/code/Magento/Cms/Model/Wysiwyg/Config.php b/app/code/Magento/Cms/Model/Wysiwyg/Config.php index 9fdb27f0f02ef..5db3933dd1169 100644 --- a/app/code/Magento/Cms/Model/Wysiwyg/Config.php +++ b/app/code/Magento/Cms/Model/Wysiwyg/Config.php @@ -201,13 +201,13 @@ public function getConfig($data = []) $config->setData('directives_url_quoted', preg_quote($config->getData('directives_url'))); - if ($this->_authorization->isAllowed('Magento_Cms::media_gallery')) { - $this->configProvider->processGalleryConfig($config); - } - if (is_array($data)) { $config->addData($data); } + + if ($this->_authorization->isAllowed('Magento_Cms::media_gallery')) { + $this->configProvider->processGalleryConfig($config); + } if ($config->getData('add_widgets')) { $this->configProvider->processWidgetConfig($config); } diff --git a/app/code/Magento/Cms/Model/Wysiwyg/Images/Storage.php b/app/code/Magento/Cms/Model/Wysiwyg/Images/Storage.php index 0688534dc4ad9..0c8ff7d0b2b78 100644 --- a/app/code/Magento/Cms/Model/Wysiwyg/Images/Storage.php +++ b/app/code/Magento/Cms/Model/Wysiwyg/Images/Storage.php @@ -241,10 +241,12 @@ protected function getConditionsForExcludeDirs() protected function removeItemFromCollection($collection, $conditions) { $regExp = $conditions['reg_exp'] ? '~' . implode('|', array_keys($conditions['reg_exp'])) . '~i' : null; - $storageRootLength = strlen($this->_cmsWysiwygImages->getStorageRoot()); + $storageRoot = $this->_cmsWysiwygImages->getStorageRoot(); + $storageRootLength = strlen($storageRoot); foreach ($collection as $key => $value) { - $rootChildParts = explode('/', substr($value->getFilename(), $storageRootLength)); + $mediaSubPathname = substr($value->getFilename(), $storageRootLength); + $rootChildParts = explode('/', '/' . ltrim($mediaSubPathname, '/')); if (array_key_exists($rootChildParts[1], $conditions['plain']) || ($regExp && preg_match($regExp, $value->getFilename()))) { @@ -318,6 +320,8 @@ public function getFilesCollection($path, $type = null) $item->setName($item->getBasename()); $item->setShortName($this->_cmsWysiwygImages->getShortFilename($item->getBasename())); $item->setUrl($this->_cmsWysiwygImages->getCurrentUrl() . $item->getBasename()); + $item->setSize(filesize($item->getFilename())); + $item->setMimeType(\mime_content_type($item->getFilename())); if ($this->isImage($item->getBasename())) { $thumbUrl = $this->getThumbnailUrl($item->getFilename(), true); diff --git a/app/code/Magento/Cms/Setup/Patch/Data/ConvertWidgetConditionsToJson.php b/app/code/Magento/Cms/Setup/Patch/Data/ConvertWidgetConditionsToJson.php new file mode 100644 index 0000000000000..d36623fea6052 --- /dev/null +++ b/app/code/Magento/Cms/Setup/Patch/Data/ConvertWidgetConditionsToJson.php @@ -0,0 +1,158 @@ +moduleDataSetup = $moduleDataSetup; + $this->queryModifierFactory = $queryModifierFactory; + $this->metadataPool = $metadataPool; + $this->aggregatedFieldDataConverter = $aggregatedFieldDataConverter; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + $queryModifier = $this->queryModifierFactory->create( + 'like', + [ + 'values' => [ + 'content' => '%conditions_encoded%' + ] + ] + ); + $layoutUpdateXmlFieldQueryModifier = $this->queryModifierFactory->create( + 'like', + [ + 'values' => [ + 'layout_update_xml' => '%conditions_encoded%' + ] + ] + ); + $customLayoutUpdateXmlFieldQueryModifier = $this->queryModifierFactory->create( + 'like', + [ + 'values' => [ + 'custom_layout_update_xml' => '%conditions_encoded%' + ] + ] + ); + $blockMetadata = $this->metadataPool->getMetadata(BlockInterface::class); + $pageMetadata = $this->metadataPool->getMetadata(PageInterface::class); + $this->aggregatedFieldDataConverter->convert( + [ + new FieldToConvert( + ContentConverter::class, + $this->moduleDataSetup->getTable('cms_block'), + $blockMetadata->getIdentifierField(), + 'content', + $queryModifier + ), + new FieldToConvert( + ContentConverter::class, + $this->moduleDataSetup->getTable('cms_page'), + $pageMetadata->getIdentifierField(), + 'content', + $queryModifier + ), + new FieldToConvert( + LayoutUpdateConverter::class, + $this->moduleDataSetup->getTable('cms_page'), + $pageMetadata->getIdentifierField(), + 'layout_update_xml', + $layoutUpdateXmlFieldQueryModifier + ), + new FieldToConvert( + LayoutUpdateConverter::class, + $this->moduleDataSetup->getTable('cms_page'), + $pageMetadata->getIdentifierField(), + 'custom_layout_update_xml', + $customLayoutUpdateXmlFieldQueryModifier + ), + ], + $this->moduleDataSetup->getConnection() + ); + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return [ + UpdatePrivacyPolicyPage::class, + ]; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.2'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } +} diff --git a/app/code/Magento/Cms/Setup/InstallData.php b/app/code/Magento/Cms/Setup/Patch/Data/CreateDefaultPages.php similarity index 92% rename from app/code/Magento/Cms/Setup/InstallData.php rename to app/code/Magento/Cms/Setup/Patch/Data/CreateDefaultPages.php index 57e9aadd691d4..d097ed5c81741 100644 --- a/app/code/Magento/Cms/Setup/InstallData.php +++ b/app/code/Magento/Cms/Setup/Patch/Data/CreateDefaultPages.php @@ -4,42 +4,47 @@ * See COPYING.txt for license details. */ -namespace Magento\Cms\Setup; +namespace Magento\Cms\Setup\Patch\Data; -use Magento\Cms\Model\Page; -use Magento\Cms\Model\PageFactory; +use Magento\Setup\Model\Patch\DataPatchInterface; +use Magento\Setup\Model\Patch\PatchVersionInterface; use Magento\Framework\Module\Setup\Migration; -use Magento\Framework\Setup\InstallDataInterface; -use Magento\Framework\Setup\ModuleContextInterface; use Magento\Framework\Setup\ModuleDataSetupInterface; /** - * @codeCoverageIgnore + * Class CreateDefaultPages + * @package Magento\Cms\Setup\Patch */ -class InstallData implements InstallDataInterface +class CreateDefaultPages implements DataPatchInterface, PatchVersionInterface { /** - * Page factory - * - * @var PageFactory + * @var \Magento\Cms\Model\PageFactory */ private $pageFactory; /** - * Init - * - * @param PageFactory $pageFactory + * @var ModuleDataSetupInterface */ - public function __construct(PageFactory $pageFactory) - { + private $moduleDataSetup; + + /** + * CreateDefaultPages constructor. + * @param ModuleDataSetupInterface $moduleDataSetup + * @param \Magento\Cms\Model\PageFactory $pageFactory + */ + public function __construct( + \Magento\Framework\Setup\ModuleDataSetupInterface $moduleDataSetup, + \Magento\Cms\Model\PageFactory $pageFactory + ) { $this->pageFactory = $pageFactory; + $this->moduleDataSetup = $moduleDataSetup; } /** * {@inheritdoc} * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ - public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context) + public function apply() { $cmsPages = [ [ @@ -101,7 +106,6 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface foreach ($cmsPages as $data) { $this->createPage()->setData($data)->save(); } - $pageContent = <<
@@ -314,7 +318,6 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface
EOD; - $privacyPageData = [ 'title' => 'Privacy and Cookie Policy', 'content_heading' => 'Privacy and Cookie Policy', @@ -325,11 +328,8 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface 'stores' => [0], 'sort_order' => 0, ]; - $this->createPage()->setData($privacyPageData)->save(); - $footerLinksBlock = $this->createPage()->load('footer_links', 'identifier'); - if ($footerLinksBlock->getId()) { $content = $footerLinksBlock->getContent(); if (preg_match('/
    (.*?)<\\/ul>/ims', $content)) { @@ -341,10 +341,8 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $footerLinksBlock->setContent($content)->save(); } } - - $installer = $setup->createMigrationSetup(); - $setup->startSetup(); - + $installer = $this->moduleDataSetup->createMigrationSetup(); + $this->moduleDataSetup->startSetup(); $installer->appendClassAliasReplace( 'cms_block', 'content', @@ -373,18 +371,40 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface Migration::FIELD_CONTENT_TYPE_XML, ['page_id'] ); - $installer->doUpdateClassAliases(); + $this->moduleDataSetup->endSetup(); + } - $setup->endSetup(); + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return []; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.0'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; } /** - * Create page + * Create page model instance * - * @return Page + * @return \Magento\Cms\Model\Page */ - public function createPage() + private function createPage() { return $this->pageFactory->create(); } diff --git a/app/code/Magento/Cms/Setup/UpgradeData.php b/app/code/Magento/Cms/Setup/Patch/Data/UpdatePrivacyPolicyPage.php similarity index 69% rename from app/code/Magento/Cms/Setup/UpgradeData.php rename to app/code/Magento/Cms/Setup/Patch/Data/UpdatePrivacyPolicyPage.php index 91bda43d2e0e7..ced4d9d7ffc4e 100644 --- a/app/code/Magento/Cms/Setup/UpgradeData.php +++ b/app/code/Magento/Cms/Setup/Patch/Data/UpdatePrivacyPolicyPage.php @@ -3,172 +3,41 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\Cms\Setup; -use Magento\Cms\Api\Data\BlockInterface; -use Magento\Cms\Api\Data\PageInterface; -use Magento\Cms\Model\Page; +namespace Magento\Cms\Setup\Patch\Data; + use Magento\Cms\Model\PageFactory; -use Magento\Framework\DB\AggregatedFieldDataConverter; -use Magento\Framework\DB\FieldToConvert; -use Magento\Framework\EntityManager\MetadataPool; -use Magento\Framework\Setup\ModuleContextInterface; -use Magento\Framework\Setup\ModuleDataSetupInterface; -use Magento\Framework\Setup\UpgradeDataInterface; -use Magento\Widget\Setup\LayoutUpdateConverter; +use Magento\Setup\Model\Patch\DataPatchInterface; +use Magento\Setup\Model\Patch\PatchVersionInterface; -class UpgradeData implements UpgradeDataInterface +/** + * Class UpdatePrivacyPolicyPage + * @package Magento\Cms\Setup\Patch + */ +class UpdatePrivacyPolicyPage implements DataPatchInterface, PatchVersionInterface { - /** - * @deprecated - */ - const PRIVACY_COOKIE_PAGE_ID = 4; - /** * @var PageFactory */ private $pageFactory; /** - * @var \Magento\Framework\DB\Select\QueryModifierFactory - */ - private $queryModifierFactory; - - /** - * @var MetadataPool - */ - private $metadataPool; - - /** - * @var AggregatedFieldDataConverter - */ - private $aggregatedFieldConverter; - - /** - * UpgradeData constructor. - * + * UpdatePrivacyPolicyPage constructor. * @param PageFactory $pageFactory - * @param AggregatedFieldDataConverter $aggregatedFieldConverter - * @param \Magento\Framework\DB\Select\QueryModifierFactory $queryModifierFactory - * @param MetadataPool $metadataPool */ public function __construct( - PageFactory $pageFactory, - AggregatedFieldDataConverter $aggregatedFieldConverter, - \Magento\Framework\DB\Select\QueryModifierFactory $queryModifierFactory, - MetadataPool $metadataPool + PageFactory $pageFactory ) { $this->pageFactory = $pageFactory; - $this->aggregatedFieldConverter = $aggregatedFieldConverter; - $this->queryModifierFactory = $queryModifierFactory; - $this->metadataPool = $metadataPool; - } - - /** - * Upgrades data for a module - * - * @param ModuleDataSetupInterface $setup - * @param ModuleContextInterface $context - * @return void - */ - public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context) - { - if (version_compare($context->getVersion(), '2.0.1', '<')) { - $this->upgradeVersionTwoZeroOne(); - } - if (version_compare($context->getVersion(), '2.0.2', '<')) { - $this->convertWidgetConditionsToJson($setup); - } - } - - /** - * Upgrade data to version 2.0.2 - * - * @param ModuleDataSetupInterface $setup - * @return void - */ - private function convertWidgetConditionsToJson(ModuleDataSetupInterface $setup) - { - $queryModifier = $this->queryModifierFactory->create( - 'like', - [ - 'values' => [ - 'content' => '%conditions_encoded%' - ] - ] - ); - $layoutUpdateXmlFieldQueryModifier = $this->queryModifierFactory->create( - 'like', - [ - 'values' => [ - 'layout_update_xml' => '%conditions_encoded%' - ] - ] - ); - $customLayoutUpdateXmlFieldQueryModifier = $this->queryModifierFactory->create( - 'like', - [ - 'values' => [ - 'custom_layout_update_xml' => '%conditions_encoded%' - ] - ] - ); - $blockMetadata = $this->metadataPool->getMetadata(BlockInterface::class); - $pageMetadata = $this->metadataPool->getMetadata(PageInterface::class); - $this->aggregatedFieldConverter->convert( - [ - new FieldToConvert( - ContentConverter::class, - $setup->getTable('cms_block'), - $blockMetadata->getIdentifierField(), - 'content', - $queryModifier - ), - new FieldToConvert( - ContentConverter::class, - $setup->getTable('cms_page'), - $pageMetadata->getIdentifierField(), - 'content', - $queryModifier - ), - new FieldToConvert( - LayoutUpdateConverter::class, - $setup->getTable('cms_page'), - $pageMetadata->getIdentifierField(), - 'layout_update_xml', - $layoutUpdateXmlFieldQueryModifier - ), - new FieldToConvert( - LayoutUpdateConverter::class, - $setup->getTable('cms_page'), - $pageMetadata->getIdentifierField(), - 'custom_layout_update_xml', - $customLayoutUpdateXmlFieldQueryModifier - ), - ], - $setup->getConnection() - ); - } - - /** - * Create page - * - * @return Page - */ - private function createPage() - { - return $this->pageFactory->create(); } /** - * Upgrade data to version 2.0.1, - * - * @return void + * {@inheritdoc} * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ - private function upgradeVersionTwoZeroOne() + public function apply() { - $newPageContent = <<
    @@ -362,4 +231,40 @@ private function upgradeVersionTwoZeroOne() $privacyAndCookiePolicyPage->save(); } } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return [ + CreateDefaultPages::class, + ]; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.1'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } + + /** + * Create page instance. + * + * @return \Magento\Cms\Model\Page + */ + private function createPage() + { + return $this->pageFactory->create(); + } } diff --git a/app/code/Magento/Cms/Test/Unit/Helper/Wysiwyg/ImagesTest.php b/app/code/Magento/Cms/Test/Unit/Helper/Wysiwyg/ImagesTest.php index 539c9b914e291..fc5eaf998c748 100644 --- a/app/code/Magento/Cms/Test/Unit/Helper/Wysiwyg/ImagesTest.php +++ b/app/code/Magento/Cms/Test/Unit/Helper/Wysiwyg/ImagesTest.php @@ -331,9 +331,14 @@ public function providerIsUsingStaticUrlsAllowed() */ public function testGetCurrentPath($pathId, $expectedPath, $isExist) { - $this->requestMock->expects($this->once()) + $this->requestMock->expects($this->any()) ->method('getParam') - ->willReturn($pathId); + ->willReturnMap( + [ + ['node', null, $pathId], + ['use_storage_root', null, false], + ] + ); $this->directoryWriteMock->expects($this->any()) ->method('isDirectory') diff --git a/app/code/Magento/Cms/etc/di.xml b/app/code/Magento/Cms/etc/di.xml index a795cb3cb1889..5b0f5e1413461 100644 --- a/app/code/Magento/Cms/etc/di.xml +++ b/app/code/Magento/Cms/etc/di.xml @@ -55,8 +55,41 @@ - - + + + true + pub[/\\]+media[/\\]+captcha[/\\]*$ + + + true + pub[/\\]+media[/\\]+catalog[/\\]+product[/\\]*$ + + + true + pub[/\\]+media[/\\]+customer[/\\]*$ + + + true + pub[/\\]+media[/\\]+downloadable[/\\]*$ + + + true + pub[/\\]+media[/\\]+import[/\\]*$ + + + true + pub[/\\]+media[/\\]+theme[/\\]*$ + + + true + pub[/\\]+media[/\\]+theme_customization[/\\]*$ + + + true + pub[/\\]+media[/\\]+tmp[/\\]*$ + + + diff --git a/app/code/Magento/Cms/etc/module.xml b/app/code/Magento/Cms/etc/module.xml index 18bd90fddfb90..d3fc2846217d9 100644 --- a/app/code/Magento/Cms/etc/module.xml +++ b/app/code/Magento/Cms/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + 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 a4c570f9d65a1..da89991869929 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 @@ -14,7 +14,13 @@ $_height = $block->getImagesHeight(); ?> getFilesCount() > 0): ?> getFiles() as $file): ?> -
    +

    getFileThumbUrl($file)):?> <?= $block->escapeHtmlAttr($block->getFileName($file)) ?> 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 8693195449f71..097235bc9fb71 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 @@ -7,6 +7,16 @@ // @codingStandardsIgnoreFile /** @var $block \Magento\Cms\Block\Adminhtml\Wysiwyg\Images\Content\Uploader */ + +$filters = $block->getConfig()->getFilters() ?? []; +$allowedExtensions = []; + +foreach ($filters as $media_type) { + $allowedExtensions = array_merge($allowedExtensions, array_map(function ($fileExt) { + return ltrim($fileExt, '.*'); + }, $media_type['files'])); +} + ?>

    @@ -28,10 +38,15 @@ require([ 'jquery', 'mage/template', + 'Magento_Ui/js/lib/validation/validator', + 'Magento_Ui/js/modal/alert', 'jquery/file-uploader', 'domReady!', 'mage/translate' -], function ($, mageTemplate) { +], function ($, mageTemplate, validator, uiAlert) { + var maxFileSize = escapeJs($block->getFileSizeService()->getMaxFileSize()) ?>, + allowedExtensions = 'escapeHtml(implode(' ', $allowedExtensions)) ?>'; + $('#getHtmlId() ?> .fileupload').fileupload({ dataType: 'json', formData: { @@ -40,17 +55,44 @@ require([ }, sequentialUploads: true, acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i, - maxFileSize: escapeJs($block->getFileSizeService()->getMaxFileSize()) ?>, + allowedExtensions: allowedExtensions, + maxFileSize: maxFileSize, + dropZone: $('#getHtmlId() ?>').closest('[role="dialog"]'), add: function (e, data) { var progressTmpl = mageTemplate('#getHtmlId() ?>-template'), fileSize, - tmpl; + tmpl, + validationResult; - $.each(data.files, function (index, file) { + data.files = data.files.filter(function (file) { fileSize = typeof file.size == "undefined" ? $.mage.__('We could not detect a size.') : byteConvert(file.size); + if (maxFileSize) { + validationResult = validator('validate-max-size', file.size, maxFileSize); + + if (!validationResult.passed) { + uiAlert({ + content: validationResult.message + }); + + return false; + } + } + + if (allowedExtensions) { + validationResult = validator('validate-file-type', file.name, allowedExtensions); + + if (!validationResult.passed) { + uiAlert({ + content: validationResult.message + }); + + return false; + } + } + data.fileId = Math.random().toString(36).substr(2, 9); tmpl = progressTmpl({ @@ -62,11 +104,15 @@ require([ }); $(tmpl).data('image', data).appendTo('#getHtmlId() ?>'); - }); - $(this).fileupload('process', data).done(function () { - data.submit(); + return true; }); + + if (data.files.length) { + $(this).fileupload('process', data).done(function () { + data.submit(); + }); + } }, done: function (e, data) { var progressSelector = '#' + data.fileId + ' .progressbar-container .progressbar'; diff --git a/app/code/Magento/Cms/view/adminhtml/web/js/folder-tree.js b/app/code/Magento/Cms/view/adminhtml/web/js/folder-tree.js index 22540ef9d0c77..6dd0b39f692c2 100644 --- a/app/code/Magento/Cms/view/adminhtml/web/js/folder-tree.js +++ b/app/code/Magento/Cms/view/adminhtml/web/js/folder-tree.js @@ -114,7 +114,7 @@ define([ metadata: { node: codeCopy }, - state: 'closed' + state: node.state || 'closed' }; }); } diff --git a/app/code/Magento/CmsUrlRewrite/etc/module.xml b/app/code/Magento/CmsUrlRewrite/etc/module.xml index bce3dce2a40e0..1e12b5b74971d 100644 --- a/app/code/Magento/CmsUrlRewrite/etc/module.xml +++ b/app/code/Magento/CmsUrlRewrite/etc/module.xml @@ -6,6 +6,6 @@ */ --> - + diff --git a/app/code/Magento/CmsUrlRewriteGraphQl/etc/module.xml b/app/code/Magento/CmsUrlRewriteGraphQl/etc/module.xml index 9cdc305f2f913..d3c65b440aab7 100644 --- a/app/code/Magento/CmsUrlRewriteGraphQl/etc/module.xml +++ b/app/code/Magento/CmsUrlRewriteGraphQl/etc/module.xml @@ -6,5 +6,5 @@ */ --> - + diff --git a/app/code/Magento/Config/Console/Command/ConfigSet/ConfigSetProcessorFactory.php b/app/code/Magento/Config/Console/Command/ConfigSet/ConfigSetProcessorFactory.php index e005747ea5ed5..b884fc2d91f3b 100644 --- a/app/code/Magento/Config/Console/Command/ConfigSet/ConfigSetProcessorFactory.php +++ b/app/code/Magento/Config/Console/Command/ConfigSet/ConfigSetProcessorFactory.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Config\Console\Command\ConfigSet; use Magento\Config\Console\Command\ConfigSetCommand; @@ -65,7 +66,9 @@ public function __construct( public function create($processorName) { if (!isset($this->processors[$processorName])) { - throw new ConfigurationMismatchException(__('Class for type "%1" was not declared', $processorName)); + throw new ConfigurationMismatchException( + __('The class for "%1" type wasn\'t declared. Enter the class and try again.', $processorName) + ); } $object = $this->objectManager->create($this->processors[$processorName]); diff --git a/app/code/Magento/Config/Model/Config/Backend/Email/Address.php b/app/code/Magento/Config/Model/Config/Backend/Email/Address.php index 77fa787bcadc5..2d12884e7bc70 100644 --- a/app/code/Magento/Config/Model/Config/Backend/Email/Address.php +++ b/app/code/Magento/Config/Model/Config/Backend/Email/Address.php @@ -25,7 +25,9 @@ public function beforeSave() { $value = $this->getValue(); if (!\Zend_Validate::is($value, \Magento\Framework\Validator\EmailAddress::class)) { - throw new LocalizedException(__('Please correct the email address: "%1".', $value)); + throw new LocalizedException( + __('The "%1" email address is incorrect. Verify the email address and try again.', $value) + ); } return $this; } diff --git a/app/code/Magento/Config/Model/Config/Backend/Locale/Timezone.php b/app/code/Magento/Config/Model/Config/Backend/Locale/Timezone.php index 4e8be3623f399..cac4da2b52621 100644 --- a/app/code/Magento/Config/Model/Config/Backend/Locale/Timezone.php +++ b/app/code/Magento/Config/Model/Config/Backend/Locale/Timezone.php @@ -24,7 +24,7 @@ class Timezone extends \Magento\Framework\App\Config\Value public function beforeSave() { if (!in_array($this->getValue(), \DateTimeZone::listIdentifiers(\DateTimeZone::ALL))) { - throw new LocalizedException(__('Please correct the timezone.')); + throw new LocalizedException(__('The time zone is incorrect. Verify the time zone and try again.')); } return $this; } diff --git a/app/code/Magento/Config/Model/Config/Compiler/IncludeElement.php b/app/code/Magento/Config/Model/Config/Compiler/IncludeElement.php index 961931d6d28c1..5fc54fa1a8d1e 100644 --- a/app/code/Magento/Config/Model/Config/Compiler/IncludeElement.php +++ b/app/code/Magento/Config/Model/Config/Compiler/IncludeElement.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Config\Model\Config\Compiler; use Magento\Framework\DataObject; @@ -114,6 +115,6 @@ protected function getContent($includePath) return $directoryRead->readFile($path); } - throw new LocalizedException(__('The file "%1" does not exist', $path)); + throw new LocalizedException(__('The "%1" file doesn\'t exist.', $path)); } } diff --git a/app/code/Magento/Config/Model/Config/PathValidator.php b/app/code/Magento/Config/Model/Config/PathValidator.php index c7edbf51b7d36..68363bef69d91 100644 --- a/app/code/Magento/Config/Model/Config/PathValidator.php +++ b/app/code/Magento/Config/Model/Config/PathValidator.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Config\Model\Config; use Magento\Framework\Exception\ValidatorException; @@ -42,7 +43,7 @@ public function validate($path) $allPaths = $this->structure->getFieldPaths(); if (!array_key_exists($path, $allPaths)) { - throw new ValidatorException(__('The "%1" path does not exist', $path)); + throw new ValidatorException(__('The "%1" path doesn\'t exist. Verify and try again.', $path)); } return true; diff --git a/app/code/Magento/Config/Model/Config/Structure/Reader.php b/app/code/Magento/Config/Model/Config/Structure/Reader.php index 6c53991fcc372..d59f6dd7a40fd 100644 --- a/app/code/Magento/Config/Model/Config/Structure/Reader.php +++ b/app/code/Magento/Config/Model/Config/Structure/Reader.php @@ -6,6 +6,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Config\Model\Config\Structure; use Magento\Framework\DataObject; @@ -97,7 +98,10 @@ protected function _readFiles($fileList) } } catch (\Magento\Framework\Config\Dom\ValidationException $e) { throw new LocalizedException( - new \Magento\Framework\Phrase("Invalid XML in file %1:\n%2", [$key, $e->getMessage()]) + new \Magento\Framework\Phrase( + 'The XML in file "%1" is invalid:' . "\n%2\nVerify the XML and try again.", + [$key, $e->getMessage()] + ) ); } } diff --git a/app/code/Magento/Config/Setup/Patch/Data/UpdateClassAliases.php b/app/code/Magento/Config/Setup/Patch/Data/UpdateClassAliases.php new file mode 100644 index 0000000000000..22d2977467329 --- /dev/null +++ b/app/code/Magento/Config/Setup/Patch/Data/UpdateClassAliases.php @@ -0,0 +1,76 @@ +moduleDataSetup = $moduleDataSetup; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + $installer = $this->moduleDataSetup->createMigrationSetup(); + $this->moduleDataSetup->startSetup(); + + $installer->appendClassAliasReplace( + 'core_config_data', + 'value', + Migration::ENTITY_TYPE_MODEL, + Migration::FIELD_CONTENT_TYPE_PLAIN, + ['config_id'] + ); + $installer->doUpdateClassAliases(); + $this->moduleDataSetup->endSetup(); + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return []; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.0'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } +} diff --git a/app/code/Magento/Config/Test/Unit/Console/Command/ConfigSet/ConfigSetProcessorFactoryTest.php b/app/code/Magento/Config/Test/Unit/Console/Command/ConfigSet/ConfigSetProcessorFactoryTest.php index 1fa0310ca62eb..decb7d52a5e0c 100644 --- a/app/code/Magento/Config/Test/Unit/Console/Command/ConfigSet/ConfigSetProcessorFactoryTest.php +++ b/app/code/Magento/Config/Test/Unit/Console/Command/ConfigSet/ConfigSetProcessorFactoryTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Config\Test\Unit\Console\Command\ConfigSet; use Magento\Config\Console\Command\ConfigSet\ConfigSetProcessorFactory; @@ -64,7 +65,7 @@ public function testCreate() /** * @expectedException \Magento\Framework\Exception\LocalizedException - * @expectedExceptionMessage Class for type "dummyType" was not declared + * @expectedExceptionMessage The class for "dummyType" type wasn't declared. Enter the class and try again. */ public function testCreateNonExisted() { diff --git a/app/code/Magento/Config/Test/Unit/Console/Command/ConfigSetCommandTest.php b/app/code/Magento/Config/Test/Unit/Console/Command/ConfigSetCommandTest.php index 39f9c47361352..0271de0da81f4 100644 --- a/app/code/Magento/Config/Test/Unit/Console/Command/ConfigSetCommandTest.php +++ b/app/code/Magento/Config/Test/Unit/Console/Command/ConfigSetCommandTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Config\Test\Unit\Console\Command; use Magento\Config\Console\Command\ConfigSet\ProcessorFacadeFactory; @@ -170,7 +171,9 @@ public function testExecuteWithException() ->willReturn(false); $this->emulatedAreProcessorMock->expects($this->once()) ->method('process') - ->willThrowException(new ValidatorException(__('The "test/test/test" path does not exists'))); + ->willThrowException( + new ValidatorException(__('The "test/test/test" path doesn\'t exist. Verify and try again.')) + ); $tester = new CommandTester($this->command); $tester->execute([ @@ -179,7 +182,7 @@ public function testExecuteWithException() ]); $this->assertContains( - __('The "test/test/test" path does not exists')->render(), + __('The "test/test/test" path doesn\'t exist. Verify and try again.')->render(), $tester->getDisplay() ); $this->assertSame(Cli::RETURN_FAILURE, $tester->getStatusCode()); diff --git a/app/code/Magento/Config/Test/Unit/Model/Compiler/IncludeElementTest.php b/app/code/Magento/Config/Test/Unit/Model/Compiler/IncludeElementTest.php index 451c73319d5bc..3197c04b12312 100644 --- a/app/code/Magento/Config/Test/Unit/Model/Compiler/IncludeElementTest.php +++ b/app/code/Magento/Config/Test/Unit/Model/Compiler/IncludeElementTest.php @@ -82,7 +82,7 @@ public function testCompileSuccess() /** * @expectedException \Magento\Framework\Exception\LocalizedException - * @expectedExceptionMessage The file "adminhtml/path/to/file.xml" does not exist + * @expectedExceptionMessage The "adminhtml/path/to/file.xml" file doesn't exist. */ public function testCompileException() { diff --git a/app/code/Magento/Config/Test/Unit/Model/Config/PathValidatorTest.php b/app/code/Magento/Config/Test/Unit/Model/Config/PathValidatorTest.php index b1d712a29cb5f..5a8ea95eff2b9 100644 --- a/app/code/Magento/Config/Test/Unit/Model/Config/PathValidatorTest.php +++ b/app/code/Magento/Config/Test/Unit/Model/Config/PathValidatorTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Config\Test\Unit\Model\Config; use Magento\Config\Model\Config\PathValidator; @@ -55,7 +56,7 @@ public function testValidate() /** * @expectedException \Magento\Framework\Exception\ValidatorException - * @expectedExceptionMessage The "test/test/test" path does not exist + * @expectedExceptionMessage The "test/test/test" path doesn't exist. Verify and try again. */ public function testValidateWithException() { diff --git a/app/code/Magento/Config/Test/Unit/Model/Config/Structure/ReaderTest.php b/app/code/Magento/Config/Test/Unit/Model/Config/Structure/ReaderTest.php index 7329fa82b73f6..9e107a545d76f 100644 --- a/app/code/Magento/Config/Test/Unit/Model/Config/Structure/ReaderTest.php +++ b/app/code/Magento/Config/Test/Unit/Model/Config/Structure/ReaderTest.php @@ -105,7 +105,7 @@ public function testReadSuccessNotValidatedCase() * Test the execution with the Validation exception of the 'read' method * * @expectedException \Magento\Framework\Exception\LocalizedException - * @expectedExceptionMessage Invalid XML in file file: + * @expectedExceptionMessage Verify the XML and try again. */ public function testReadWithValidationException() { diff --git a/app/code/Magento/Config/etc/module.xml b/app/code/Magento/Config/etc/module.xml index b64cbe2b72623..19051a96a434c 100644 --- a/app/code/Magento/Config/etc/module.xml +++ b/app/code/Magento/Config/etc/module.xml @@ -6,5 +6,5 @@ */ --> - + diff --git a/app/code/Magento/ConfigurableImportExport/etc/module.xml b/app/code/Magento/ConfigurableImportExport/etc/module.xml index 83a4fc4e1a793..7ff81f8d63443 100644 --- a/app/code/Magento/ConfigurableImportExport/etc/module.xml +++ b/app/code/Magento/ConfigurableImportExport/etc/module.xml @@ -6,6 +6,6 @@ */ --> - + diff --git a/app/code/Magento/ConfigurableProduct/Model/LinkManagement.php b/app/code/Magento/ConfigurableProduct/Model/LinkManagement.php index 01981b5dae9db..79c2dd812acf1 100644 --- a/app/code/Magento/ConfigurableProduct/Model/LinkManagement.php +++ b/app/code/Magento/ConfigurableProduct/Model/LinkManagement.php @@ -4,6 +4,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\ConfigurableProduct\Model; use Magento\Framework\Exception\InputException; @@ -115,19 +116,24 @@ public function addChild($sku, $childSku) $childrenIds = array_values($this->configurableType->getChildrenIds($product->getId())[0]); if (in_array($child->getId(), $childrenIds)) { - throw new StateException(__('Product has been already attached')); + throw new StateException(__('The product is already attached.')); } $configurableProductOptions = $product->getExtensionAttributes()->getConfigurableProductOptions(); if (empty($configurableProductOptions)) { - throw new StateException(__('Parent product does not have configurable product options')); + throw new StateException(__("The parent product doesn't have configurable product options.")); } $attributeIds = []; foreach ($configurableProductOptions as $configurableProductOption) { $attributeCode = $configurableProductOption->getProductAttribute()->getAttributeCode(); if (!$child->getData($attributeCode)) { - throw new StateException(__('Child product does not have attribute value %1', $attributeCode)); + throw new StateException( + __( + 'The child product doesn\'t have the "%1" attribute value. Verify the value and try again.', + $attributeCode + ) + ); } $attributeIds[] = $configurableProductOption->getAttributeId(); } @@ -152,7 +158,7 @@ public function removeChild($sku, $childSku) if ($product->getTypeId() != \Magento\ConfigurableProduct\Model\Product\Type\Configurable::TYPE_CODE) { throw new InputException( - __('Product with specified sku: %1 is not a configurable product', $sku) + __('The product with the "%1" SKU isn\'t a configurable product.', $sku) ); } @@ -165,7 +171,9 @@ public function removeChild($sku, $childSku) $ids[] = $option->getId(); } if (count($options) == count($ids)) { - throw new NoSuchEntityException(__('Requested option doesn\'t exist')); + throw new NoSuchEntityException( + __("The option that was requested doesn't exist. Verify the entity and try again.") + ); } $product->getExtensionAttributes()->setConfigurableProductLinks($ids); $this->productRepository->save($product); diff --git a/app/code/Magento/ConfigurableProduct/Model/OptionRepository.php b/app/code/Magento/ConfigurableProduct/Model/OptionRepository.php index bdf4a3678524e..b4db0a4db5fcd 100644 --- a/app/code/Magento/ConfigurableProduct/Model/OptionRepository.php +++ b/app/code/Magento/ConfigurableProduct/Model/OptionRepository.php @@ -4,6 +4,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\ConfigurableProduct\Model; use Magento\Catalog\Api\Data\ProductInterface; @@ -124,7 +125,9 @@ public function get($sku, $id) } } - throw new NoSuchEntityException(__('Requested option doesn\'t exist: %1', $id)); + throw new NoSuchEntityException( + __('The "%1" entity that was requested doesn\'t exist. Verify the entity and try again.', $id) + ); } /** @@ -150,14 +153,14 @@ public function delete(OptionInterface $option) $this->configurableType->resetConfigurableAttributes($product); } catch (\Exception $exception) { throw new StateException( - __('Cannot delete variations from product: %1', $entityId) + __('The variations from the "%1" product can\'t be deleted.', $entityId) ); } try { $this->optionResource->delete($option); } catch (\Exception $exception) { throw new StateException( - __('Cannot delete option with id: %1', $option->getId()) + __('The option with "%1" ID can\'t be deleted.', $option->getId()) ); } return true; @@ -173,7 +176,9 @@ public function deleteById($sku, $id) /** @var \Magento\ConfigurableProduct\Model\Product\Type\Configurable\Attribute $option */ $option = $attributeCollection->getItemById($id); if ($option === null) { - throw new NoSuchEntityException(__('Requested option doesn\'t exist')); + throw new NoSuchEntityException( + __("The option that was requested doesn't exist. Verify the entity and try again.") + ); } return $this->delete($option); } @@ -213,11 +218,11 @@ public function save($sku, OptionInterface $option) try { $option->save(); } catch (\Exception $e) { - throw new CouldNotSaveException(__('Something went wrong while saving option.')); + throw new CouldNotSaveException(__('An error occurred while saving the option. Please try to save again.')); } if (!$option->getId()) { - throw new CouldNotSaveException(__('Something went wrong while saving option.')); + throw new CouldNotSaveException(__('An error occurred while saving the option. Please try to save again.')); } return $option->getId(); } @@ -234,7 +239,7 @@ private function getProduct($sku) $product = $this->productRepository->get($sku); if (\Magento\ConfigurableProduct\Model\Product\Type\Configurable::TYPE_CODE !== $product->getTypeId()) { throw new InputException( - __('Only implemented for configurable product: %1', $sku) + __('This is implemented for the "%1" configurable product only.', $sku) ); } return $product; @@ -252,7 +257,7 @@ private function getProductById($id) $product = $this->productRepository->getById($id); if (\Magento\ConfigurableProduct\Model\Product\Type\Configurable::TYPE_CODE !== $product->getTypeId()) { throw new InputException( - __('Only implemented for configurable product: %1', $id) + __('This is implemented for the "%1" configurable product only.', $id) ); } return $product; diff --git a/app/code/Magento/ConfigurableProduct/Model/Product/VariationHandler.php b/app/code/Magento/ConfigurableProduct/Model/Product/VariationHandler.php index a462a5ffd9edd..73e7f9053fa4a 100644 --- a/app/code/Magento/ConfigurableProduct/Model/Product/VariationHandler.php +++ b/app/code/Magento/ConfigurableProduct/Model/Product/VariationHandler.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\ConfigurableProduct\Model\Product; use Magento\Catalog\Model\Product\Type as ProductType; @@ -96,7 +97,9 @@ public function generateSimpleProducts($parentProduct, $productsData) $configurableAttribute = json_decode($simpleProductData['configurable_attribute'], true); unset($simpleProductData['configurable_attribute']); } else { - throw new LocalizedException(__('Configuration must have specified attributes')); + throw new LocalizedException( + __('Contribution must have attributes specified. Enter attributes and try again.') + ); } $this->fillSimpleProductData( diff --git a/app/code/Magento/ConfigurableProduct/Setup/InstallData.php b/app/code/Magento/ConfigurableProduct/Setup/Patch/Data/InstallInitialConfigurableAttributes.php similarity index 59% rename from app/code/Magento/ConfigurableProduct/Setup/InstallData.php rename to app/code/Magento/ConfigurableProduct/Setup/Patch/Data/InstallInitialConfigurableAttributes.php index 7bc56569dea44..d9f11c6f910f9 100644 --- a/app/code/Magento/ConfigurableProduct/Setup/InstallData.php +++ b/app/code/Magento/ConfigurableProduct/Setup/Patch/Data/InstallInitialConfigurableAttributes.php @@ -4,44 +4,51 @@ * See COPYING.txt for license details. */ -namespace Magento\ConfigurableProduct\Setup; +namespace Magento\ConfigurableProduct\Setup\Patch\Data; -use Magento\ConfigurableProduct\Model\Product\Type\Configurable; use Magento\Eav\Setup\EavSetup; use Magento\Eav\Setup\EavSetupFactory; -use Magento\Framework\Setup\InstallDataInterface; -use Magento\Framework\Setup\ModuleContextInterface; +use Magento\Framework\App\ResourceConnection; use Magento\Framework\Setup\ModuleDataSetupInterface; +use Magento\Setup\Model\Patch\DataPatchInterface; +use Magento\Setup\Model\Patch\PatchVersionInterface; +use Magento\ConfigurableProduct\Model\Product\Type\Configurable; /** - * @codeCoverageIgnore + * Class InstallInitialConfigurableAttributes + * @package Magento\ConfigurableProduct\Setup\Patch */ -class InstallData implements InstallDataInterface +class InstallInitialConfigurableAttributes implements DataPatchInterface, PatchVersionInterface { /** - * EAV setup factory - * + * @var ModuleDataSetupInterface + */ + private $moduleDataSetup; + /** * @var EavSetupFactory */ private $eavSetupFactory; /** - * Init - * + * InstallInitialConfigurableAttributes constructor. + * @param ModuleDataSetupInterface $moduleDataSetup * @param EavSetupFactory $eavSetupFactory */ - public function __construct(EavSetupFactory $eavSetupFactory) - { + public function __construct( + ModuleDataSetupInterface $moduleDataSetup, + EavSetupFactory $eavSetupFactory + ) { + $this->moduleDataSetup = $moduleDataSetup; $this->eavSetupFactory = $eavSetupFactory; } /** * {@inheritdoc} */ - public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context) + public function apply() { /** @var EavSetup $eavSetup */ - $eavSetup = $this->eavSetupFactory->create(['setup' => $setup]); + $eavSetup = $this->eavSetupFactory->create(['setup' => $this->moduleDataSetup]); $attributes = [ 'country_of_manufacture', 'minimal_price', @@ -71,4 +78,28 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface } } } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return []; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.0'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } } diff --git a/app/code/Magento/ConfigurableProduct/Setup/Patch/Data/UpdateTierPriceAttribute.php b/app/code/Magento/ConfigurableProduct/Setup/Patch/Data/UpdateTierPriceAttribute.php new file mode 100644 index 0000000000000..4d04fb4db5bbc --- /dev/null +++ b/app/code/Magento/ConfigurableProduct/Setup/Patch/Data/UpdateTierPriceAttribute.php @@ -0,0 +1,94 @@ +moduleDataSetup = $moduleDataSetup; + $this->eavSetupFactory = $eavSetupFactory; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + /** @var EavSetup $eavSetup */ + $eavSetup = $this->eavSetupFactory->create(['setup' => $this->moduleDataSetup]); + $relatedProductTypes = explode( + ',', + $eavSetup->getAttribute(\Magento\Catalog\Model\Product::ENTITY, 'tier_price', 'apply_to') + ); + $key = array_search(Configurable::TYPE_CODE, $relatedProductTypes); + if ($key !== false) { + unset($relatedProductTypes[$key]); + $eavSetup->updateAttribute( + \Magento\Catalog\Model\Product::ENTITY, + 'tier_price', + 'apply_to', + implode(',', $relatedProductTypes) + ); + } + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return [ + InstallInitialConfigurableAttributes::class, + ]; + } + + /** + * {@inheritdoc}\ + */ + public static function getVersion() + { + return '2.2.0'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } +} diff --git a/app/code/Magento/ConfigurableProduct/Setup/UpgradeData.php b/app/code/Magento/ConfigurableProduct/Setup/UpgradeData.php deleted file mode 100644 index 326af02fe39bb..0000000000000 --- a/app/code/Magento/ConfigurableProduct/Setup/UpgradeData.php +++ /dev/null @@ -1,65 +0,0 @@ -eavSetupFactory = $eavSetupFactory; - } - - /** - * {@inheritdoc} - */ - public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context) - { - $setup->startSetup(); - if (version_compare($context->getVersion(), '2.2.0') < 0) { - /** @var EavSetup $eavSetup */ - $eavSetup = $this->eavSetupFactory->create(['setup' => $setup]); - $relatedProductTypes = explode( - ',', - $eavSetup->getAttribute(\Magento\Catalog\Model\Product::ENTITY, 'tier_price', 'apply_to') - ); - $key = array_search(Configurable::TYPE_CODE, $relatedProductTypes); - if ($key !== false) { - unset($relatedProductTypes[$key]); - $eavSetup->updateAttribute( - \Magento\Catalog\Model\Product::ENTITY, - 'tier_price', - 'apply_to', - implode(',', $relatedProductTypes) - ); - } - } - - $setup->endSetup(); - } -} diff --git a/app/code/Magento/ConfigurableProduct/Test/Unit/Model/LinkManagementTest.php b/app/code/Magento/ConfigurableProduct/Test/Unit/Model/LinkManagementTest.php index acbb976318b3b..ad2fcd1e59360 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Unit/Model/LinkManagementTest.php +++ b/app/code/Magento/ConfigurableProduct/Test/Unit/Model/LinkManagementTest.php @@ -235,7 +235,7 @@ public function testAddChild() /** * @expectedException \Magento\Framework\Exception\StateException - * @expectedExceptionMessage Product has been already attached + * @expectedExceptionMessage The product is already attached. */ public function testAddChildStateException() { diff --git a/app/code/Magento/ConfigurableProduct/Test/Unit/Model/OptionRepositoryTest.php b/app/code/Magento/ConfigurableProduct/Test/Unit/Model/OptionRepositoryTest.php index 2d824e52c7244..8f3f3979b8669 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Unit/Model/OptionRepositoryTest.php +++ b/app/code/Magento/ConfigurableProduct/Test/Unit/Model/OptionRepositoryTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\ConfigurableProduct\Test\Unit\Model; use Magento\Catalog\Api\ProductRepositoryInterface; @@ -113,7 +114,7 @@ public function testGet() /** * @expectedException \Magento\Framework\Exception\InputException - * @expectedExceptionMessage Only implemented for configurable product: configurable + * @expectedExceptionMessage This is implemented for the "configurable" configurable product only. */ public function testGetNotConfigurableProduct() { @@ -141,7 +142,7 @@ public function testGetNotConfigurableProduct() /** * @expectedException \Magento\Framework\Exception\InputException - * @expectedExceptionMessage Only implemented for configurable product: 3 + * @expectedExceptionMessage This is implemented for the "3" configurable product only. */ public function testGetNotProductById() { @@ -168,7 +169,7 @@ public function testGetNotProductById() /** * @expectedException \Magento\Framework\Exception\StateException - * @expectedExceptionMessage Cannot delete variations from product: 3 + * @expectedExceptionMessage The variations from the "3" product can't be deleted. */ public function testDeleteCantSaveProducts() { @@ -200,7 +201,7 @@ public function testDeleteCantSaveProducts() /** * @expectedException \Magento\Framework\Exception\StateException - * @expectedExceptionMessage Cannot delete option with id: 33 + * @expectedExceptionMessage The option with "33" ID can't be deleted. */ public function testDeleteCantDeleteOption() { @@ -276,7 +277,7 @@ public function testDelete() /** * @expectedException \Magento\Framework\Exception\NoSuchEntityException - * @expectedExceptionMessage Requested option doesn't exist: 3 + * @expectedExceptionMessage The "3" entity that was requested doesn't exist. Verify the entity and try again. */ public function testGetEmptyExtensionAttribute() { @@ -329,7 +330,7 @@ public function testGetList() /** * @expectedException \Magento\Framework\Exception\InputException - * @expectedExceptionMessage Only implemented for configurable product: configurable + * @expectedExceptionMessage This is implemented for the "configurable" configurable product only. */ public function testGetListNotConfigurableProduct() { diff --git a/app/code/Magento/ConfigurableProduct/etc/module.xml b/app/code/Magento/ConfigurableProduct/etc/module.xml index 188337fb0ed7c..e81553191f867 100644 --- a/app/code/Magento/ConfigurableProduct/etc/module.xml +++ b/app/code/Magento/ConfigurableProduct/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/ConfigurableProductGraphQl/etc/module.xml b/app/code/Magento/ConfigurableProductGraphQl/etc/module.xml index e86b1bdf604c6..98e7957d0af8e 100644 --- a/app/code/Magento/ConfigurableProductGraphQl/etc/module.xml +++ b/app/code/Magento/ConfigurableProductGraphQl/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/ConfigurableProductSales/etc/module.xml b/app/code/Magento/ConfigurableProductSales/etc/module.xml index 4da83c9c0269b..bf5bc4472c8b2 100644 --- a/app/code/Magento/ConfigurableProductSales/etc/module.xml +++ b/app/code/Magento/ConfigurableProductSales/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/Contact/Controller/Index/Post.php b/app/code/Magento/Contact/Controller/Index/Post.php index ee2d23b74df24..b51e3c9189502 100644 --- a/app/code/Magento/Contact/Controller/Index/Post.php +++ b/app/code/Magento/Contact/Controller/Index/Post.php @@ -4,6 +4,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Contact\Controller\Index; use Magento\Contact\Model\ConfigInterface; @@ -119,13 +120,13 @@ private function validatedParams() { $request = $this->getRequest(); if (trim($request->getParam('name')) === '') { - throw new LocalizedException(__('Name is missing')); + throw new LocalizedException(__('Enter the Name and try again.')); } if (trim($request->getParam('comment')) === '') { - throw new LocalizedException(__('Comment is missing')); + throw new LocalizedException(__('Enter the comment and try again.')); } if (false === \strpos($request->getParam('email'), '@')) { - throw new LocalizedException(__('Invalid email address')); + throw new LocalizedException(__('The email address is invalid. Verify the email address and try again.')); } if (trim($request->getParam('hideit')) !== '') { throw new \Exception(); diff --git a/app/code/Magento/Contact/etc/module.xml b/app/code/Magento/Contact/etc/module.xml index ec91859ee2c8d..64ba1c1fb0f0d 100644 --- a/app/code/Magento/Contact/etc/module.xml +++ b/app/code/Magento/Contact/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/Cookie/etc/module.xml b/app/code/Magento/Cookie/etc/module.xml index 35c5a52f42ec7..df64e8b3ebfe8 100644 --- a/app/code/Magento/Cookie/etc/module.xml +++ b/app/code/Magento/Cookie/etc/module.xml @@ -6,5 +6,5 @@ */ --> - + diff --git a/app/code/Magento/Cron/Model/Schedule.php b/app/code/Magento/Cron/Model/Schedule.php index 39a58ef360cb3..b127ecae6f98d 100644 --- a/app/code/Magento/Cron/Model/Schedule.php +++ b/app/code/Magento/Cron/Model/Schedule.php @@ -87,7 +87,7 @@ public function setCronExpr($expr) { $e = preg_split('#\s+#', $expr, null, PREG_SPLIT_NO_EMPTY); if (sizeof($e) < 5 || sizeof($e) > 6) { - throw new CronException(__('Invalid cron expression: %1', $expr)); + throw new CronException(__('The "%1" cron expression is invalid. Verify and try again.', $expr)); } $this->setCronExprArr($e); @@ -184,7 +184,7 @@ public function matchCronExpression($expr, $num) } if ($from === false || $to === false) { - throw new CronException(__('Invalid cron expression: %1', $expr)); + throw new CronException(__('The "%1" cron expression is invalid. Verify and try again.', $expr)); } return $num >= $from && $num <= $to && $num % $mod === 0; diff --git a/app/code/Magento/Cron/Test/Unit/Model/ScheduleTest.php b/app/code/Magento/Cron/Test/Unit/Model/ScheduleTest.php index e9f4c61c7f551..dd1fa0e79dc67 100644 --- a/app/code/Magento/Cron/Test/Unit/Model/ScheduleTest.php +++ b/app/code/Magento/Cron/Test/Unit/Model/ScheduleTest.php @@ -311,7 +311,7 @@ public function matchCronExpressionExceptionDataProvider() return [ ['1/2/3'], //Invalid cron expression, expecting 'match/modulus': 1/2/3 ['1/'], //Invalid cron expression, expecting numeric modulus: 1/ - ['-'], //Invalid cron expression + ['-'], //The "-" cron expression is invalid. Verify and try again. ['1-2-3'], //Invalid cron expression, expecting 'from-to' structure: 1-2-3 ]; } diff --git a/app/code/Magento/Cron/etc/module.xml b/app/code/Magento/Cron/etc/module.xml index ce31b046500f7..8112b9e8c46db 100644 --- a/app/code/Magento/Cron/etc/module.xml +++ b/app/code/Magento/Cron/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/CurrencySymbol/Controller/Adminhtml/System/Currency/FetchRates.php b/app/code/Magento/CurrencySymbol/Controller/Adminhtml/System/Currency/FetchRates.php index b16330f1b3f98..38e20355b6699 100644 --- a/app/code/Magento/CurrencySymbol/Controller/Adminhtml/System/Currency/FetchRates.php +++ b/app/code/Magento/CurrencySymbol/Controller/Adminhtml/System/Currency/FetchRates.php @@ -4,6 +4,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\CurrencySymbol\Controller\Adminhtml\System\Currency; use Magento\Framework\Exception\LocalizedException; @@ -24,14 +25,16 @@ public function execute() $service = $this->getRequest()->getParam('rate_services'); $this->_getSession()->setCurrencyRateService($service); if (!$service) { - throw new LocalizedException(__('Please specify a correct Import Service.')); + throw new LocalizedException(__('The Import Service is incorrect. Verify the service and try again.')); } try { /** @var \Magento\Directory\Model\Currency\Import\ImportInterface $importModel */ $importModel = $this->_objectManager->get(\Magento\Directory\Model\Currency\Import\Factory::class) ->create($service); } catch (\Exception $e) { - throw new LocalizedException(__('We can\'t initialize the import model.')); + throw new LocalizedException( + __("The import model can't be initialized. Verify the model and try again.") + ); } $rates = $importModel->fetchRates(); $errors = $importModel->getMessages(); diff --git a/app/code/Magento/CurrencySymbol/Setup/UpgradeData.php b/app/code/Magento/CurrencySymbol/Setup/Patch/Data/ConvertSerializedCustomCurrencySymbolToJson.php similarity index 52% rename from app/code/Magento/CurrencySymbol/Setup/UpgradeData.php rename to app/code/Magento/CurrencySymbol/Setup/Patch/Data/ConvertSerializedCustomCurrencySymbolToJson.php index 474efde78ea5b..dd5e59c4d9dcd 100644 --- a/app/code/Magento/CurrencySymbol/Setup/UpgradeData.php +++ b/app/code/Magento/CurrencySymbol/Setup/Patch/Data/ConvertSerializedCustomCurrencySymbolToJson.php @@ -3,64 +3,58 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\CurrencySymbol\Setup; + +namespace Magento\CurrencySymbol\Setup\Patch\Data; use Magento\CurrencySymbol\Model\System\Currencysymbol; use Magento\Framework\DB\DataConverter\SerializedToJson; use Magento\Framework\DB\FieldDataConverterFactory; use Magento\Framework\DB\Select\QueryModifierFactory; -use Magento\Framework\Setup\UpgradeDataInterface; -use Magento\Framework\Setup\ModuleContextInterface; +use Magento\Framework\App\ResourceConnection; use Magento\Framework\Setup\ModuleDataSetupInterface; +use Magento\Setup\Model\Patch\DataPatchInterface; +use Magento\Setup\Model\Patch\PatchVersionInterface; /** - * Data upgrade script - * - * @codeCoverageIgnore + * Class ConvertSerializedCustomCurrencySymbolToJson + * @package Magento\CurrencySymbol\Setup\Patch */ -class UpgradeData implements UpgradeDataInterface +class ConvertSerializedCustomCurrencySymbolToJson implements DataPatchInterface, PatchVersionInterface { /** - * @var FieldDataConverterFactory + * @var ModuleDataSetupInterface + */ + private $moduleDataSetup; + + /** + * @param FieldDataConverterFactory $fieldDataConverterFactory */ private $fieldDataConverterFactory; /** - * @var QueryModifierFactory + * @param QueryModifierFactory $queryModifierFactory */ private $queryModifierFactory; /** - * Constructor - * * @param FieldDataConverterFactory $fieldDataConverterFactory * @param QueryModifierFactory $queryModifierFactory + * @param ModuleDataSetupInterface $moduleDataSetup */ public function __construct( FieldDataConverterFactory $fieldDataConverterFactory, - QueryModifierFactory $queryModifierFactory + QueryModifierFactory $queryModifierFactory, + ModuleDataSetupInterface $moduleDataSetup ) { $this->fieldDataConverterFactory = $fieldDataConverterFactory; $this->queryModifierFactory = $queryModifierFactory; + $this->moduleDataSetup = $moduleDataSetup; } /** * {@inheritdoc} */ - public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context) - { - if (version_compare($context->getVersion(), '2.0.1', '<')) { - $this->convertSerializedCustomCurrencySymbolToJson($setup); - } - } - - /** - * Converts custom currency symbol configuration in core_config_data table from serialized to JSON format - * - * @param ModuleDataSetupInterface $setup - * @return void - */ - private function convertSerializedCustomCurrencySymbolToJson(ModuleDataSetupInterface $setup) + public function apply() { $fieldDataConverter = $this->fieldDataConverterFactory->create(SerializedToJson::class); $queryModifier = $this->queryModifierFactory->create( @@ -72,11 +66,35 @@ private function convertSerializedCustomCurrencySymbolToJson(ModuleDataSetupInte ] ); $fieldDataConverter->convert( - $setup->getConnection(), - $setup->getTable('core_config_data'), + $this->moduleDataSetup->getConnection(), + $this->moduleDataSetup->getTable('core_config_data'), 'config_id', 'value', $queryModifier ); } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return []; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.1'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } } diff --git a/app/code/Magento/CurrencySymbol/etc/module.xml b/app/code/Magento/CurrencySymbol/etc/module.xml index f638479031f4f..2af87335518d1 100644 --- a/app/code/Magento/CurrencySymbol/etc/module.xml +++ b/app/code/Magento/CurrencySymbol/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/Customer/Controller/Account/EditPost.php b/app/code/Magento/Customer/Controller/Account/EditPost.php index 3f895ad2f17ac..a10795533a2a5 100644 --- a/app/code/Magento/Customer/Controller/Account/EditPost.php +++ b/app/code/Magento/Customer/Controller/Account/EditPost.php @@ -4,6 +4,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Customer\Controller\Account; use Magento\Customer\Model\AuthenticationInterface; @@ -168,7 +169,8 @@ public function execute() $this->messageManager->addError($e->getMessage()); } catch (UserLockedException $e) { $message = __( - 'You did not sign in correctly or your account is temporarily disabled.' + 'The account sign-in was incorrect or your account is disabled temporarily. ' + . 'Please wait and try again later.' ); $this->session->logout(); $this->session->start(); @@ -287,7 +289,9 @@ private function processChangeEmailRequest(\Magento\Customer\Api\Data\CustomerIn $this->getRequest()->getPost('current_password') ); } catch (InvalidEmailOrPasswordException $e) { - throw new InvalidEmailOrPasswordException(__('The password doesn\'t match this account.')); + throw new InvalidEmailOrPasswordException( + __("The password doesn't match this account. Verify the password and try again.") + ); } } } diff --git a/app/code/Magento/Customer/Controller/Account/ForgotPasswordPost.php b/app/code/Magento/Customer/Controller/Account/ForgotPasswordPost.php index fe92032b1b75e..f302473873087 100644 --- a/app/code/Magento/Customer/Controller/Account/ForgotPasswordPost.php +++ b/app/code/Magento/Customer/Controller/Account/ForgotPasswordPost.php @@ -66,7 +66,9 @@ public function execute() if ($email) { if (!\Zend_Validate::is($email, \Magento\Framework\Validator\EmailAddress::class)) { $this->session->setForgottenEmail($email); - $this->messageManager->addErrorMessage(__('Please correct the email address.')); + $this->messageManager->addErrorMessage( + __('The email address is incorrect. Verify the email address and try again.') + ); return $resultRedirect->setPath('*/*/forgotpassword'); } diff --git a/app/code/Magento/Customer/Controller/Account/LoginPost.php b/app/code/Magento/Customer/Controller/Account/LoginPost.php index b55863a3b486a..31e2a3aeca9e3 100644 --- a/app/code/Magento/Customer/Controller/Account/LoginPost.php +++ b/app/code/Magento/Customer/Controller/Account/LoginPost.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Customer\Controller\Account; use Magento\Customer\Model\Account\Redirect as AccountRedirect; @@ -175,12 +176,16 @@ public function execute() $this->session->setUsername($login['username']); } catch (UserLockedException $e) { $message = __( - 'You did not sign in correctly or your account is temporarily disabled.' + 'The account sign-in was incorrect or your account is disabled temporarily. ' + . 'Please wait and try again later.' ); $this->messageManager->addError($message); $this->session->setUsername($login['username']); } catch (AuthenticationException $e) { - $message = __('You did not sign in correctly or your account is temporarily disabled.'); + $message = __( + 'The account sign-in was incorrect or your account is disabled temporarily. ' + . 'Please wait and try again later.' + ); $this->messageManager->addError($message); $this->session->setUsername($login['username']); } catch (LocalizedException $e) { diff --git a/app/code/Magento/Customer/Controller/Adminhtml/Cart/Product/Composite/Cart.php b/app/code/Magento/Customer/Controller/Adminhtml/Cart/Product/Composite/Cart.php index c0ea38de809db..2603ac193e007 100644 --- a/app/code/Magento/Customer/Controller/Adminhtml/Cart/Product/Composite/Cart.php +++ b/app/code/Magento/Customer/Controller/Adminhtml/Cart/Product/Composite/Cart.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Customer\Controller\Adminhtml\Cart\Product\Composite; use Magento\Backend\App\Action; @@ -78,7 +79,7 @@ protected function _initData() { $this->_customerId = (int)$this->getRequest()->getParam('customer_id'); if (!$this->_customerId) { - throw new \Magento\Framework\Exception\LocalizedException(__('No customer ID defined.')); + throw new \Magento\Framework\Exception\LocalizedException(__("The customer ID isn't defined.")); } $quoteItemId = (int)$this->getRequest()->getParam('id'); @@ -95,7 +96,7 @@ protected function _initData() $this->_quoteItem = $this->_quote->getItemById($quoteItemId); if (!$this->_quoteItem) { - throw new LocalizedException(__('Please correct the quote items and try again.')); + throw new LocalizedException(__('The quote items are incorrect. Verify the quote items and try again.')); } return $this; diff --git a/app/code/Magento/Customer/CustomerData/SectionPool.php b/app/code/Magento/Customer/CustomerData/SectionPool.php index 26e9140c63df5..0e0d7b992e33a 100644 --- a/app/code/Magento/Customer/CustomerData/SectionPool.php +++ b/app/code/Magento/Customer/CustomerData/SectionPool.php @@ -74,7 +74,7 @@ protected function getSectionDataByNames($sectionNames) $data = []; foreach ($sectionNames as $sectionName) { if (!isset($this->sectionSourceMap[$sectionName])) { - throw new LocalizedException(__('"%1" section source is not supported', $sectionName)); + throw new LocalizedException(__('The "%1" section source isn\'t supported.', $sectionName)); } $data[$sectionName] = $this->get($this->sectionSourceMap[$sectionName])->getSectionData(); } diff --git a/app/code/Magento/Customer/Model/AccountManagement.php b/app/code/Magento/Customer/Model/AccountManagement.php index c48680f3cdb52..cd5fef7316999 100644 --- a/app/code/Magento/Customer/Model/AccountManagement.php +++ b/app/code/Magento/Customer/Model/AccountManagement.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Customer\Model; use Magento\Customer\Api\AccountManagementInterface; @@ -417,7 +418,7 @@ public function resendConfirmation($email, $websiteId = null, $redirectUrl = '') { $customer = $this->customerRepository->get($email, $websiteId); if (!$customer->getConfirmation()) { - throw new InvalidTransitionException(__('No confirmation needed.')); + throw new InvalidTransitionException(__("Confirmation isn't needed.")); } try { @@ -464,11 +465,11 @@ private function activateCustomer($customer, $confirmationKey) { // check if customer is inactive if (!$customer->getConfirmation()) { - throw new InvalidTransitionException(__('Account already active')); + throw new InvalidTransitionException(__('The account is already active.')); } if ($customer->getConfirmation() !== $confirmationKey) { - throw new InputMismatchException(__('Invalid confirmation token')); + throw new InputMismatchException(__('The confirmation token is invalid. Verify the token and try again.')); } $customer->setConfirmation(null); @@ -503,7 +504,7 @@ public function authenticate($username, $password) throw new InvalidEmailOrPasswordException(__('Invalid login or password.')); } if ($customer->getConfirmation() && $this->isConfirmationRequired($customer)) { - throw new EmailNotConfirmedException(__('This account is not confirmed.')); + throw new EmailNotConfirmedException(__("This account isn't confirmed. Verify and try again.")); } $customerModel = $this->customerFactory->create()->updateData($customer); @@ -619,13 +620,15 @@ protected function checkPasswordStrength($password) if ($length < $configMinPasswordLength) { throw new InputException( __( - 'Please enter a password with at least %1 characters.', + 'The password needs at least %1 characters. Create a new password and try again.', $configMinPasswordLength ) ); } if ($this->stringHelper->strlen(trim($password)) != $length) { - throw new InputException(__('The password can\'t begin or end with a space.')); + throw new InputException( + __("The password can't begin or end with a space. Verify the password and try again.") + ); } $requiredCharactersCheck = $this->makeRequiredCharactersCheck($password); @@ -709,7 +712,9 @@ public function createAccount(CustomerInterface $customer, $password = null, $re try { $this->credentialsValidator->checkPasswordDifferentFromEmail($customerEmail, $password); } catch (InputException $e) { - throw new LocalizedException(__('Password cannot be the same as email address.')); + throw new LocalizedException( + __("The password can't be the same as the email address. Create a new password and try again.") + ); } $hash = $this->createPasswordHash($password); } else { @@ -766,7 +771,7 @@ public function createAccountWithPasswordHash(CustomerInterface $customer, $hash $customer = $this->customerRepository->save($customer, $hash); } catch (AlreadyExistsException $e) { throw new InputMismatchException( - __('A customer with the same email already exists in an associated website.') + __('A customer with the same email address already exists in an associated website.') ); } catch (LocalizedException $e) { throw $e; @@ -880,7 +885,9 @@ private function changePasswordForCustomer($customer, $currentPassword, $newPass try { $this->getAuthentication()->authenticate($customer->getId(), $currentPassword); } catch (InvalidEmailOrPasswordException $e) { - throw new InvalidEmailOrPasswordException(__('The password doesn\'t match this account.')); + throw new InvalidEmailOrPasswordException( + __("The password doesn't match this account. Verify the password and try again.") + ); } $customerEmail = $customer->getEmail(); $this->credentialsValidator->checkPasswordDifferentFromEmail($customerEmail, $newPassword); @@ -996,7 +1003,7 @@ private function validateResetPasswordToken($customerId, $resetPasswordLinkToken } if (!is_string($resetPasswordLinkToken) || empty($resetPasswordLinkToken)) { $params = ['fieldName' => 'resetPasswordLinkToken']; - throw new InputException(__('%fieldName is a required field.', $params)); + throw new InputException(__('"%fieldName" is required. Enter and try again.', $params)); } $customerSecureData = $this->customerRegistry->retrieveSecureData($customerId); @@ -1004,9 +1011,9 @@ private function validateResetPasswordToken($customerId, $resetPasswordLinkToken $rpTokenCreatedAt = $customerSecureData->getRpTokenCreatedAt(); if (!Security::compareStrings($rpToken, $resetPasswordLinkToken)) { - throw new InputMismatchException(__('Reset password token mismatch.')); + throw new InputMismatchException(__('The password token is mismatched. Reset and try again.')); } elseif ($this->isResetPasswordLinkTokenExpired($rpToken, $rpTokenCreatedAt)) { - throw new ExpiredException(__('Reset password token expired.')); + throw new ExpiredException(__('The password token is expired. Reset and try again.')); } return true; @@ -1048,7 +1055,9 @@ protected function sendNewAccountEmail( $types = $this->getTemplateTypes(); if (!isset($types[$type])) { - throw new LocalizedException(__('Please correct the transactional account email type.')); + throw new LocalizedException( + __('The transactional account email type is incorrect. Verify and try again.') + ); } if (!$storeId) { diff --git a/app/code/Magento/Customer/Model/Address/AbstractAddress.php b/app/code/Magento/Customer/Model/Address/AbstractAddress.php index 521e233d9cfbb..aab9a811168f9 100644 --- a/app/code/Magento/Customer/Model/Address/AbstractAddress.php +++ b/app/code/Magento/Customer/Model/Address/AbstractAddress.php @@ -578,36 +578,36 @@ public function validate() $errors = []; if (!\Zend_Validate::is($this->getFirstname(), 'NotEmpty')) { - $errors[] = __('%fieldName is a required field.', ['fieldName' => 'firstname']); + $errors[] = __('"%fieldName" is required. Enter and try again.', ['fieldName' => 'firstname']); } if (!\Zend_Validate::is($this->getLastname(), 'NotEmpty')) { - $errors[] = __('%fieldName is a required field.', ['fieldName' => 'lastname']); + $errors[] = __('"%fieldName" is required. Enter and try again.', ['fieldName' => 'lastname']); } if (!\Zend_Validate::is($this->getStreetLine(1), 'NotEmpty')) { - $errors[] = __('%fieldName is a required field.', ['fieldName' => 'street']); + $errors[] = __('"%fieldName" is required. Enter and try again.', ['fieldName' => 'street']); } if (!\Zend_Validate::is($this->getCity(), 'NotEmpty')) { - $errors[] = __('%fieldName is a required field.', ['fieldName' => 'city']); + $errors[] = __('"%fieldName" is required. Enter and try again.', ['fieldName' => 'city']); } if ($this->isTelephoneRequired()) { if (!\Zend_Validate::is($this->getTelephone(), 'NotEmpty')) { - $errors[] = __('%fieldName is a required field.', ['fieldName' => 'telephone']); + $errors[] = __('"%fieldName" is required. Enter and try again.', ['fieldName' => 'telephone']); } } if ($this->isFaxRequired()) { if (!\Zend_Validate::is($this->getFax(), 'NotEmpty')) { - $errors[] = __('%fieldName is a required field.', ['fieldName' => 'fax']); + $errors[] = __('"%fieldName" is required. Enter and try again.', ['fieldName' => 'fax']); } } if ($this->isCompanyRequired()) { if (!\Zend_Validate::is($this->getCompany(), 'NotEmpty')) { - $errors[] = __('%fieldName is a required field.', ['fieldName' => 'company']); + $errors[] = __('"%fieldName" is required. Enter and try again.', ['fieldName' => 'company']); } } @@ -620,11 +620,11 @@ public function validate() 'NotEmpty' ) ) { - $errors[] = __('%fieldName is a required field.', ['fieldName' => 'postcode']); + $errors[] = __('"%fieldName" is required. Enter and try again.', ['fieldName' => 'postcode']); } if (!\Zend_Validate::is($this->getCountryId(), 'NotEmpty')) { - $errors[] = __('%fieldName is a required field.', ['fieldName' => 'countryId']); + $errors[] = __('"%fieldName" is required. Enter and try again.', ['fieldName' => 'countryId']); } if ($this->getCountryModel()->getRegionCollection()->getSize() && !\Zend_Validate::is( @@ -634,7 +634,7 @@ public function validate() $this->getCountryId() ) ) { - $errors[] = __('%fieldName is a required field.', ['fieldName' => 'regionId']); + $errors[] = __('"%fieldName" is required. Enter and try again.', ['fieldName' => 'regionId']); } if (empty($errors)) { diff --git a/app/code/Magento/Customer/Model/Customer.php b/app/code/Magento/Customer/Model/Customer.php index e0a7281776de9..6d1c1549216e8 100644 --- a/app/code/Magento/Customer/Model/Customer.php +++ b/app/code/Magento/Customer/Model/Customer.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Customer\Model; use Magento\Customer\Api\CustomerMetadataInterface; @@ -392,7 +393,7 @@ public function authenticate($login, $password) $this->loadByEmail($login); if ($this->getConfirmation() && $this->isConfirmationRequired()) { throw new EmailNotConfirmedException( - __('This account is not confirmed.') + __("This account isn't confirmed. Verify and try again.") ); } if (!$this->validatePassword($password)) { @@ -762,7 +763,7 @@ public function sendNewAccountEmail($type = 'registered', $backUrl = '', $storeI if (!isset($types[$type])) { throw new \Magento\Framework\Exception\LocalizedException( - __('Please correct the transactional account email type.') + __('The transactional account email type is incorrect. Verify and try again.') ); } @@ -1240,7 +1241,7 @@ public function changeResetPasswordLinkToken($passwordLinkToken) { if (!is_string($passwordLinkToken) || empty($passwordLinkToken)) { throw new AuthenticationException( - __('Please enter a valid password reset token.') + __('A valid password reset token is missing. Enter and try again.') ); } $this->_getResource()->changeResetPasswordLinkToken($this, $passwordLinkToken); diff --git a/app/code/Magento/Customer/Model/Customer/Attribute/Backend/Password.php b/app/code/Magento/Customer/Model/Customer/Attribute/Backend/Password.php index abdec5535e86b..a74838a1a7812 100644 --- a/app/code/Magento/Customer/Model/Customer/Attribute/Backend/Password.php +++ b/app/code/Magento/Customer/Model/Customer/Attribute/Backend/Password.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Customer\Model\Customer\Attribute\Backend; use Magento\Framework\Exception\LocalizedException; @@ -50,12 +51,17 @@ public function beforeSave($object) if ($length > 0) { if ($length < self::MIN_PASSWORD_LENGTH) { throw new LocalizedException( - __('Please enter a password with at least %1 characters.', self::MIN_PASSWORD_LENGTH) + __( + 'The password needs at least %1 characters. Create a new password and try again.', + self::MIN_PASSWORD_LENGTH + ) ); } if (trim($password) !== $password) { - throw new LocalizedException(__('The password can not begin or end with a space.')); + throw new LocalizedException( + __("The password can't begin or end with a space. Verify the password and try again.") + ); } $object->setPasswordHash($object->hashPassword($password)); diff --git a/app/code/Magento/Customer/Model/Customer/CredentialsValidator.php b/app/code/Magento/Customer/Model/Customer/CredentialsValidator.php index b8adeec2f8017..a7682bde905b6 100644 --- a/app/code/Magento/Customer/Model/Customer/CredentialsValidator.php +++ b/app/code/Magento/Customer/Model/Customer/CredentialsValidator.php @@ -25,7 +25,9 @@ class CredentialsValidator public function checkPasswordDifferentFromEmail($email, $password) { if (strcasecmp($password, $email) == 0) { - throw new InputException(__('Password cannot be the same as email address.')); + throw new InputException( + __("The password can't be the same as the email address. Create a new password and try again.") + ); } } } diff --git a/app/code/Magento/Customer/Model/EmailNotification.php b/app/code/Magento/Customer/Model/EmailNotification.php index 14ae9a885c7b1..53c16a4b37093 100644 --- a/app/code/Magento/Customer/Model/EmailNotification.php +++ b/app/code/Magento/Customer/Model/EmailNotification.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Customer\Model; use Magento\Framework\App\Config\ScopeConfigInterface; @@ -356,7 +357,9 @@ public function newAccount( $types = self::TEMPLATE_TYPES; if (!isset($types[$type])) { - throw new LocalizedException(__('Please correct the transactional account email type.')); + throw new LocalizedException( + __('The transactional account email type is incorrect. Verify and try again.') + ); } if (!$storeId) { diff --git a/app/code/Magento/Customer/Model/ResourceModel/Customer.php b/app/code/Magento/Customer/Model/ResourceModel/Customer.php index 7e5f9d51549ec..f510201559687 100644 --- a/app/code/Magento/Customer/Model/ResourceModel/Customer.php +++ b/app/code/Magento/Customer/Model/ResourceModel/Customer.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Customer\Model\ResourceModel; use Magento\Customer\Model\Customer\NotificationStorage; @@ -111,7 +112,7 @@ protected function _beforeSave(\Magento\Framework\DataObject $customer) parent::_beforeSave($customer); if (!$customer->getEmail()) { - throw new ValidatorException(__('Please enter a customer email.')); + throw new ValidatorException(__('The customer email is missing. Enter and try again.')); } $connection = $this->getConnection(); @@ -135,7 +136,7 @@ protected function _beforeSave(\Magento\Framework\DataObject $customer) $result = $connection->fetchOne($select, $bind); if ($result) { throw new AlreadyExistsException( - __('A customer with the same email already exists in an associated website.') + __('A customer with the same email address already exists in an associated website.') ); } @@ -242,7 +243,7 @@ public function loadByEmail(\Magento\Customer\Model\Customer $customer, $email) if ($customer->getSharingConfig()->isWebsiteScope()) { if (!$customer->hasData('website_id')) { throw new \Magento\Framework\Exception\LocalizedException( - __('A customer website ID must be specified when using the website scope.') + __("A customer website ID wasn't specified. The ID must be specified to use the website scope.") ); } $bind['website_id'] = (int)$customer->getWebsiteId(); diff --git a/app/code/Magento/Customer/Model/ResourceModel/GroupRepository.php b/app/code/Magento/Customer/Model/ResourceModel/GroupRepository.php index d004b99c5a3c9..cb73b7ee1cb36 100644 --- a/app/code/Magento/Customer/Model/ResourceModel/GroupRepository.php +++ b/app/code/Magento/Customer/Model/ResourceModel/GroupRepository.php @@ -305,7 +305,7 @@ private function _validate($group) { $exception = new InputException(); if (!\Zend_Validate::is($group->getCode(), 'NotEmpty')) { - $exception->addError(__('%fieldName is a required field.', ['fieldName' => 'code'])); + $exception->addError(__('"%fieldName" is required. Enter and try again.', ['fieldName' => 'code'])); } if ($exception->wasErrorAdded()) { diff --git a/app/code/Magento/Customer/Setup/CustomerSetup.php b/app/code/Magento/Customer/Setup/CustomerSetup.php index b1f07e4872fd8..c074285765e59 100644 --- a/app/code/Magento/Customer/Setup/CustomerSetup.php +++ b/app/code/Magento/Customer/Setup/CustomerSetup.php @@ -489,4 +489,23 @@ public function getEavConfig() { return $this->eavConfig; } + + /** + * Update attributes for customer. + * + * @param array $entityAttributes + * @return void + */ + public function upgradeAttributes(array $entityAttributes) + { + foreach ($entityAttributes as $entityType => $attributes) { + foreach ($attributes as $attributeCode => $attributeData) { + $attribute = $this->getEavConfig()->getAttribute($entityType, $attributeCode); + foreach ($attributeData as $key => $value) { + $attribute->setData($key, $value); + } + $attribute->save(); + } + } + } } diff --git a/app/code/Magento/Customer/Setup/Patch/Data/AddCustomerUpdatedAtAttribute.php b/app/code/Magento/Customer/Setup/Patch/Data/AddCustomerUpdatedAtAttribute.php new file mode 100644 index 0000000000000..d9103959e0227 --- /dev/null +++ b/app/code/Magento/Customer/Setup/Patch/Data/AddCustomerUpdatedAtAttribute.php @@ -0,0 +1,91 @@ +moduleDataSetup = $moduleDataSetup; + $this->customerSetupFactory = $customerSetupFactory; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + $customerSetup = $this->customerSetupFactory->create(['setup' => $this->moduleDataSetup]); + $customerSetup->addAttribute( + Customer::ENTITY, + 'updated_at', + [ + 'type' => 'static', + 'label' => 'Updated At', + 'input' => 'date', + 'required' => false, + 'sort_order' => 87, + 'visible' => false, + 'system' => false, + ] + ); + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return [ + UpdateIdentifierCustomerAttributesVisibility::class, + ]; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.4'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } +} diff --git a/app/code/Magento/Customer/Setup/Patch/Data/AddNonSpecifiedGenderAttributeOption.php b/app/code/Magento/Customer/Setup/Patch/Data/AddNonSpecifiedGenderAttributeOption.php new file mode 100644 index 0000000000000..e5c80e0854205 --- /dev/null +++ b/app/code/Magento/Customer/Setup/Patch/Data/AddNonSpecifiedGenderAttributeOption.php @@ -0,0 +1,94 @@ +moduleDataSetup = $moduleDataSetup; + $this->customerSetupFactory = $customerSetupFactory; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + $customerSetup = $this->customerSetupFactory->create(['setup' => $this->moduleDataSetup]); + $entityTypeId = $customerSetup->getEntityTypeId(Customer::ENTITY); + $attributeId = $customerSetup->getAttributeId($entityTypeId, 'gender'); + + $option = ['attribute_id' => $attributeId, 'values' => [3 => 'Not Specified']]; + $customerSetup->addAttributeOption($option); + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return [ + UpdateCustomerAttributesMetadata::class, + ]; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.2'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } +} diff --git a/app/code/Magento/Customer/Setup/Patch/Data/AddSecurityTrackingAttributes.php b/app/code/Magento/Customer/Setup/Patch/Data/AddSecurityTrackingAttributes.php new file mode 100644 index 0000000000000..afc8b570ca3d2 --- /dev/null +++ b/app/code/Magento/Customer/Setup/Patch/Data/AddSecurityTrackingAttributes.php @@ -0,0 +1,126 @@ +moduleDataSetup = $moduleDataSetup; + $this->customerSetupFactory = $customerSetupFactory; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + $customerSetup = $this->customerSetupFactory->create(['setup' => $this->moduleDataSetup]); + $customerSetup->addAttribute( + Customer::ENTITY, + 'failures_num', + [ + 'type' => 'static', + 'label' => 'Failures Number', + 'input' => 'hidden', + 'required' => false, + 'sort_order' => 100, + 'visible' => false, + 'system' => true, + ] + ); + + $customerSetup->addAttribute( + Customer::ENTITY, + 'first_failure', + [ + 'type' => 'static', + 'label' => 'First Failure Date', + 'input' => 'date', + 'required' => false, + 'sort_order' => 110, + 'visible' => false, + 'system' => true, + ] + ); + + $customerSetup->addAttribute( + Customer::ENTITY, + 'lock_expires', + [ + 'type' => 'static', + 'label' => 'Failures Number', + 'input' => 'date', + 'required' => false, + 'sort_order' => 120, + 'visible' => false, + 'system' => true, + ] + ); + $configTable = $this->moduleDataSetup->getTable('core_config_data'); + + $this->moduleDataSetup->getConnection()->update( + $configTable, + ['value' => new \Zend_Db_Expr('value*24')], + ['path = ?' => \Magento\Customer\Model\Customer::XML_PATH_CUSTOMER_RESET_PASSWORD_LINK_EXPIRATION_PERIOD] + ); + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return [ + RemoveCheckoutRegisterAndUpdateAttributes::class, + ]; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.7'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } +} diff --git a/app/code/Magento/Customer/Setup/Patch/Data/ConvertValidationRulesFromSerializedToJson.php b/app/code/Magento/Customer/Setup/Patch/Data/ConvertValidationRulesFromSerializedToJson.php new file mode 100644 index 0000000000000..a6c5087a86bdd --- /dev/null +++ b/app/code/Magento/Customer/Setup/Patch/Data/ConvertValidationRulesFromSerializedToJson.php @@ -0,0 +1,84 @@ +moduleDataSetup = $moduleDataSetup; + $this->fieldDataConverterFactory = $fieldDataConverterFactory; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + $fieldDataConverter = $this->fieldDataConverterFactory->create(SerializedToJson::class); + $fieldDataConverter->convert( + $this->moduleDataSetup->getConnection(), + $this->moduleDataSetup->getTable('customer_eav_attribute'), + 'attribute_id', + 'validate_rules' + ); + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return [ + MigrateStoresAllowedCountriesToWebsite::class, + ]; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.11'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } +} diff --git a/app/code/Magento/Customer/Setup/InstallData.php b/app/code/Magento/Customer/Setup/Patch/Data/DefaultCustomerGroupsAndAttributes.php similarity index 67% rename from app/code/Magento/Customer/Setup/InstallData.php rename to app/code/Magento/Customer/Setup/Patch/Data/DefaultCustomerGroupsAndAttributes.php index 0bc4b19db9d1c..d37acd2fd7e7e 100644 --- a/app/code/Magento/Customer/Setup/InstallData.php +++ b/app/code/Magento/Customer/Setup/Patch/Data/DefaultCustomerGroupsAndAttributes.php @@ -4,61 +4,69 @@ * See COPYING.txt for license details. */ -namespace Magento\Customer\Setup; +namespace Magento\Customer\Setup\Patch\Data; +use Magento\Customer\Setup\CustomerSetup; +use Magento\Customer\Setup\CustomerSetupFactory; use Magento\Framework\Module\Setup\Migration; -use Magento\Framework\Setup\InstallDataInterface; -use Magento\Framework\Setup\ModuleContextInterface; use Magento\Framework\Setup\ModuleDataSetupInterface; +use Magento\Framework\App\ResourceConnection; +use Magento\Setup\Model\Patch\DataPatchInterface; +use Magento\Setup\Model\Patch\PatchVersionInterface; /** - * @codeCoverageIgnore + * Class DefaultCustomerGroupsAndAttributes + * @package Magento\Customer\Setup\Patch */ -class InstallData implements InstallDataInterface +class DefaultCustomerGroupsAndAttributes implements DataPatchInterface, PatchVersionInterface { /** - * Customer setup factory - * * @var CustomerSetupFactory */ private $customerSetupFactory; /** - * Init - * + * @var ModuleDataSetupInterface + */ + private $moduleDataSetup; + + /** + * DefaultCustomerGroupsAndAttributes constructor. * @param CustomerSetupFactory $customerSetupFactory + * @param ModuleDataSetupInterface $moduleDataSetup */ - public function __construct(CustomerSetupFactory $customerSetupFactory) - { + public function __construct( + CustomerSetupFactory $customerSetupFactory, + \Magento\Framework\Setup\ModuleDataSetupInterface $moduleDataSetup + ) { $this->customerSetupFactory = $customerSetupFactory; + $this->moduleDataSetup = $moduleDataSetup; } /** * {@inheritdoc} * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ - public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context) + public function apply() { /** @var CustomerSetup $customerSetup */ - $customerSetup = $this->customerSetupFactory->create(['setup' => $setup]); - - $setup->startSetup(); + $customerSetup = $this->customerSetupFactory->create(['setup' => $this->moduleDataSetup]); // insert default customer groups - $setup->getConnection()->insertForce( - $setup->getTable('customer_group'), + $this->moduleDataSetup->getConnection()->insertForce( + $this->moduleDataSetup->getTable('customer_group'), ['customer_group_id' => 0, 'customer_group_code' => 'NOT LOGGED IN', 'tax_class_id' => 3] ); - $setup->getConnection()->insertForce( - $setup->getTable('customer_group'), + $this->moduleDataSetup->getConnection()->insertForce( + $this->moduleDataSetup->getTable('customer_group'), ['customer_group_id' => 1, 'customer_group_code' => 'General', 'tax_class_id' => 3] ); - $setup->getConnection()->insertForce( - $setup->getTable('customer_group'), + $this->moduleDataSetup->getConnection()->insertForce( + $this->moduleDataSetup->getTable('customer_group'), ['customer_group_id' => 2, 'customer_group_code' => 'Wholesale', 'tax_class_id' => 3] ); - $setup->getConnection()->insertForce( - $setup->getTable('customer_group'), + $this->moduleDataSetup->getConnection()->insertForce( + $this->moduleDataSetup->getTable('customer_group'), ['customer_group_id' => 3, 'customer_group_code' => 'Retailer', 'tax_class_id' => 3] ); @@ -128,7 +136,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface \Magento\Eav\Model\Entity\Attribute\Backend\DefaultBackend::class ); - $migrationSetup = $setup->createMigrationSetup(); + $migrationSetup = $this->moduleDataSetup->createMigrationSetup(); $migrationSetup->appendClassAliasReplace( 'customer_eav_attribute', @@ -138,7 +146,29 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ['attribute_id'] ); $migrationSetup->doUpdateClassAliases(); + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return []; + } - $setup->endSetup(); + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.0'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; } } diff --git a/app/code/Magento/Customer/Setup/Patch/Data/MigrateStoresAllowedCountriesToWebsite.php b/app/code/Magento/Customer/Setup/Patch/Data/MigrateStoresAllowedCountriesToWebsite.php new file mode 100644 index 0000000000000..e9dc08912f368 --- /dev/null +++ b/app/code/Magento/Customer/Setup/Patch/Data/MigrateStoresAllowedCountriesToWebsite.php @@ -0,0 +1,176 @@ +moduleDataSetup = $moduleDataSetup; + $this->storeManager = $storeManager; + $this->allowedCountries = $allowedCountries; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + $this->moduleDataSetup->getConnection()->beginTransaction(); + + try { + $this->migrateStoresAllowedCountriesToWebsite(); + $this->moduleDataSetup->getConnection()->commit(); + } catch (\Exception $e) { + $this->moduleDataSetup->getConnection()->rollBack(); + throw $e; + } + } + + /** + * Merge allowed countries from stores to websites + * + * @return void + */ + private function migrateStoresAllowedCountriesToWebsite() + { + $allowedCountries = []; + //Process Websites + foreach ($this->storeManager->getStores() as $store) { + $allowedCountries = $this->mergeAllowedCountries( + $allowedCountries, + $this->getAllowedCountries(ScopeInterface::SCOPE_STORE, $store->getId()), + $store->getWebsiteId() + ); + } + //Process stores + foreach ($this->storeManager->getWebsites() as $website) { + $allowedCountries = $this->mergeAllowedCountries( + $allowedCountries, + $this->getAllowedCountries(ScopeInterface::SCOPE_WEBSITE, $website->getId()), + $website->getId() + ); + } + + $connection = $this->moduleDataSetup->getConnection(); + + //Remove everything from stores scope + $connection->delete( + $this->moduleDataSetup->getTable('core_config_data'), + [ + 'path = ?' => AllowedCountries::ALLOWED_COUNTRIES_PATH, + 'scope = ?' => ScopeInterface::SCOPE_STORES + ] + ); + + //Update websites + foreach ($allowedCountries as $scopeId => $countries) { + $connection->update( + $this->moduleDataSetup->getTable('core_config_data'), + [ + 'value' => implode(',', $countries) + ], + [ + 'path = ?' => AllowedCountries::ALLOWED_COUNTRIES_PATH, + 'scope_id = ?' => $scopeId, + 'scope = ?' => ScopeInterface::SCOPE_WEBSITES + ] + ); + } + } + + /** + * Retrieve countries not depending on global scope + * + * @param string $scope + * @param int $scopeCode + * @return array + */ + private function getAllowedCountries($scope, $scopeCode) + { + return $this->allowedCountries->makeCountriesUnique( + $this->allowedCountries->getCountriesFromConfig($scope, $scopeCode) + ); + } + + /** + * Merge allowed countries between different scopes + * + * @param array $countries + * @param array $newCountries + * @param string $identifier + * @return array + */ + private function mergeAllowedCountries(array $countries, array $newCountries, $identifier) + { + if (!isset($countries[$identifier])) { + $countries[$identifier] = $newCountries; + } else { + $countries[$identifier] = array_replace($countries[$identifier], $newCountries); + } + + return $countries; + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return [ + UpdateAutocompleteOnStorefrontConfigPath::class + ]; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.9'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } +} diff --git a/app/code/Magento/Customer/Setup/Patch/Data/RemoveCheckoutRegisterAndUpdateAttributes.php b/app/code/Magento/Customer/Setup/Patch/Data/RemoveCheckoutRegisterAndUpdateAttributes.php new file mode 100644 index 0000000000000..1895f1f6c473a --- /dev/null +++ b/app/code/Magento/Customer/Setup/Patch/Data/RemoveCheckoutRegisterAndUpdateAttributes.php @@ -0,0 +1,136 @@ +moduleDataSetup = $moduleDataSetup; + $this->customerSetupFactory = $customerSetupFactory; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + $this->moduleDataSetup->getConnection()->delete( + $this->moduleDataSetup->getTable('customer_form_attribute'), + ['form_code = ?' => 'checkout_register'] + ); + $customerSetup = $this->customerSetupFactory->create(['setup' => $this->moduleDataSetup]); + $customerSetup->updateEntityType( + \Magento\Customer\Model\Customer::ENTITY, + 'entity_model', + \Magento\Customer\Model\ResourceModel\Customer::class + ); + $customerSetup->updateEntityType( + \Magento\Customer\Model\Customer::ENTITY, + 'increment_model', + \Magento\Eav\Model\Entity\Increment\NumericValue::class + ); + $customerSetup->updateEntityType( + \Magento\Customer\Model\Customer::ENTITY, + 'entity_attribute_collection', + \Magento\Customer\Model\ResourceModel\Attribute\Collection::class + ); + $customerSetup->updateEntityType( + 'customer_address', + 'entity_model', + \Magento\Customer\Model\ResourceModel\Address::class + ); + $customerSetup->updateEntityType( + 'customer_address', + 'entity_attribute_collection', + \Magento\Customer\Model\ResourceModel\Address\Attribute\Collection::class + ); + $customerSetup->updateAttribute( + 'customer_address', + 'country_id', + 'source_model', + \Magento\Customer\Model\ResourceModel\Address\Attribute\Source\Country::class + ); + $customerSetup->updateAttribute( + 'customer_address', + 'region', + 'backend_model', + \Magento\Customer\Model\ResourceModel\Address\Attribute\Backend\Region::class + ); + $customerSetup->updateAttribute( + 'customer_address', + 'region_id', + 'source_model', + \Magento\Customer\Model\ResourceModel\Address\Attribute\Source\Region::class + ); + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return [ + UpgradePasswordHashAndAddress::class, + ]; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.6'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } +} diff --git a/app/code/Magento/Customer/Setup/Patch/Data/UpdateAutocompleteOnStorefrontConfigPath.php b/app/code/Magento/Customer/Setup/Patch/Data/UpdateAutocompleteOnStorefrontConfigPath.php new file mode 100644 index 0000000000000..bbd0d2b66e68b --- /dev/null +++ b/app/code/Magento/Customer/Setup/Patch/Data/UpdateAutocompleteOnStorefrontConfigPath.php @@ -0,0 +1,72 @@ +moduleDataSetup = $moduleDataSetup; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + $this->moduleDataSetup->getConnection()->update( + $this->moduleDataSetup->getTable('core_config_data'), + ['path' => \Magento\Customer\Model\Form::XML_PATH_ENABLE_AUTOCOMPLETE], + ['path = ?' => 'general/restriction/autocomplete_on_storefront'] + ); + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return [ + AddSecurityTrackingAttributes::class, + ]; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.8'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } +} diff --git a/app/code/Magento/Customer/Setup/Patch/Data/UpdateCustomerAttributeInputFilters.php b/app/code/Magento/Customer/Setup/Patch/Data/UpdateCustomerAttributeInputFilters.php new file mode 100644 index 0000000000000..9df78ff182ecd --- /dev/null +++ b/app/code/Magento/Customer/Setup/Patch/Data/UpdateCustomerAttributeInputFilters.php @@ -0,0 +1,102 @@ +moduleDataSetup = $moduleDataSetup; + $this->customerSetupFactory = $customerSetupFactory; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + $customerSetup = $this->customerSetupFactory->create(['setup' => $this->moduleDataSetup]); + $entityAttributes = [ + 'customer_address' => [ + 'firstname' => [ + 'input_filter' => 'trim' + ], + 'lastname' => [ + 'input_filter' => 'trim' + ], + 'middlename' => [ + 'input_filter' => 'trim' + ], + ], + 'customer' => [ + 'firstname' => [ + 'input_filter' => 'trim' + ], + 'lastname' => [ + 'input_filter' => 'trim' + ], + 'middlename' => [ + 'input_filter' => 'trim' + ], + ], + ]; + $customerSetup->upgradeAttributes($entityAttributes); + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return [ + UpdateVATNumber::class, + ]; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.13'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } +} diff --git a/app/code/Magento/Customer/Setup/Patch/Data/UpdateCustomerAttributesMetadata.php b/app/code/Magento/Customer/Setup/Patch/Data/UpdateCustomerAttributesMetadata.php new file mode 100644 index 0000000000000..5863803f79ff8 --- /dev/null +++ b/app/code/Magento/Customer/Setup/Patch/Data/UpdateCustomerAttributesMetadata.php @@ -0,0 +1,203 @@ +moduleDataSetup = $moduleDataSetup; + $this->customerSetupFactory = $customerSetupFactory; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + /** @var CustomerSetup $customerSetup */ + $customerSetup = $this->customerSetupFactory->create(['setup' => $this->moduleDataSetup]); + $this->updateCustomerAttributesMetadata($customerSetup); + } + + /** + * @param CustomerSetup $customerSetup + * @return void + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + */ + private function updateCustomerAttributesMetadata($customerSetup) + { + $entityAttributes = [ + 'customer' => [ + 'website_id' => [ + 'is_used_in_grid' => true, + 'is_visible_in_grid' => true, + 'is_filterable_in_grid' => true, + 'is_searchable_in_grid' => false, + ], + 'created_in' => [ + 'is_used_in_grid' => true, + 'is_visible_in_grid' => true, + 'is_filterable_in_grid' => false, + 'is_searchable_in_grid' => true, + ], + 'email' => [ + 'is_used_in_grid' => true, + 'is_visible_in_grid' => true, + 'is_filterable_in_grid' => true, + 'is_searchable_in_grid' => true, + ], + 'group_id' => [ + 'is_used_in_grid' => true, + 'is_visible_in_grid' => true, + 'is_filterable_in_grid' => true, + 'is_searchable_in_grid' => false, + ], + 'dob' => [ + 'is_used_in_grid' => true, + 'is_visible_in_grid' => true, + 'is_filterable_in_grid' => true, + 'is_searchable_in_grid' => false, + ], + 'taxvat' => [ + 'is_used_in_grid' => true, + 'is_visible_in_grid' => true, + 'is_filterable_in_grid' => false, + 'is_searchable_in_grid' => true, + ], + 'confirmation' => [ + 'is_used_in_grid' => true, + 'is_visible_in_grid' => true, + 'is_filterable_in_grid' => true, + 'is_searchable_in_grid' => false, + ], + 'created_at' => [ + 'is_used_in_grid' => true, + 'is_visible_in_grid' => true, + 'is_filterable_in_grid' => true, + 'is_searchable_in_grid' => false, + ], + 'gender' => [ + 'is_used_in_grid' => true, + 'is_visible_in_grid' => true, + 'is_filterable_in_grid' => true, + 'is_searchable_in_grid' => false, + ], + ], + 'customer_address' => [ + 'company' => [ + 'is_used_in_grid' => true, + 'is_visible_in_grid' => false, + 'is_filterable_in_grid' => false, + 'is_searchable_in_grid' => true, + ], + 'street' => [ + 'is_used_in_grid' => true, + 'is_visible_in_grid' => false, + 'is_filterable_in_grid' => false, + 'is_searchable_in_grid' => true, + ], + 'city' => [ + 'is_used_in_grid' => true, + 'is_visible_in_grid' => false, + 'is_filterable_in_grid' => false, + 'is_searchable_in_grid' => true, + ], + 'country_id' => [ + 'is_used_in_grid' => true, + 'is_visible_in_grid' => true, + 'is_filterable_in_grid' => true, + 'is_searchable_in_grid' => false, + ], + 'region' => [ + 'is_used_in_grid' => true, + 'is_visible_in_grid' => true, + 'is_filterable_in_grid' => false, + 'is_searchable_in_grid' => true, + ], + 'region_id' => [ + 'is_used_in_grid' => true, + 'is_visible_in_grid' => false, + 'is_filterable_in_grid' => true, + 'is_searchable_in_grid' => false, + ], + 'postcode' => [ + 'is_used_in_grid' => true, + 'is_visible_in_grid' => true, + 'is_filterable_in_grid' => true, + 'is_searchable_in_grid' => true, + ], + 'telephone' => [ + 'is_used_in_grid' => true, + 'is_visible_in_grid' => true, + 'is_filterable_in_grid' => true, + 'is_searchable_in_grid' => true, + ], + 'fax' => [ + 'is_used_in_grid' => true, + 'is_visible_in_grid' => false, + 'is_filterable_in_grid' => false, + 'is_searchable_in_grid' => true, + ], + ], + ]; + $customerSetup->upgradeAttributes($entityAttributes); + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return [ + DefaultCustomerGroupsAndAttributes::class, + ]; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.1'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } +} diff --git a/app/code/Magento/Customer/Setup/Patch/Data/UpdateIdentifierCustomerAttributesVisibility.php b/app/code/Magento/Customer/Setup/Patch/Data/UpdateIdentifierCustomerAttributesVisibility.php new file mode 100644 index 0000000000000..e0b92b342716c --- /dev/null +++ b/app/code/Magento/Customer/Setup/Patch/Data/UpdateIdentifierCustomerAttributesVisibility.php @@ -0,0 +1,100 @@ +moduleDataSetup = $moduleDataSetup; + $this->customerSetupFactory = $customerSetupFactory; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + $customerSetup = $this->customerSetupFactory->create(['setup' => $this->moduleDataSetup]); + $entityAttributes = [ + 'customer_address' => [ + 'region_id' => [ + 'is_used_in_grid' => false, + 'is_visible_in_grid' => false, + 'is_filterable_in_grid' => false, + 'is_searchable_in_grid' => false, + ], + 'firstname' => [ + 'is_used_in_grid' => true, + 'is_visible_in_grid' => false, + 'is_filterable_in_grid' => false, + 'is_searchable_in_grid' => true, + ], + 'lastname' => [ + 'is_used_in_grid' => true, + 'is_visible_in_grid' => false, + 'is_filterable_in_grid' => false, + 'is_searchable_in_grid' => true, + ], + ], + ]; + $customerSetup->upgradeAttributes($entityAttributes); + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return [ + AddNonSpecifiedGenderAttributeOption::class, + ]; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.3'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } +} diff --git a/app/code/Magento/Customer/Setup/Patch/Data/UpdateVATNumber.php b/app/code/Magento/Customer/Setup/Patch/Data/UpdateVATNumber.php new file mode 100644 index 0000000000000..e61d204bcac0c --- /dev/null +++ b/app/code/Magento/Customer/Setup/Patch/Data/UpdateVATNumber.php @@ -0,0 +1,86 @@ +moduleDataSetup = $moduleDataSetup; + $this->customerSetupFactory = $customerSetupFactory; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + $customerSetup = $this->customerSetupFactory->create(['resourceConnection' => $this->moduleDataSetup]); + $customerSetup->updateAttribute('customer_address', 'vat_id', 'frontend_label', 'VAT Number'); + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return [ + ConvertValidationRulesFromSerializedToJson::class, + ]; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.12'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } +} diff --git a/app/code/Magento/Customer/Setup/Patch/Data/UpgradePasswordHashAndAddress.php b/app/code/Magento/Customer/Setup/Patch/Data/UpgradePasswordHashAndAddress.php new file mode 100644 index 0000000000000..16c74405e786b --- /dev/null +++ b/app/code/Magento/Customer/Setup/Patch/Data/UpgradePasswordHashAndAddress.php @@ -0,0 +1,120 @@ +moduleDataSetup = $moduleDataSetup; + $this->customerSetupFactory = $customerSetupFactory; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + $this->upgradeHash(); + $entityAttributes = [ + 'customer_address' => [ + 'fax' => [ + 'is_visible' => false, + 'is_system' => false, + ], + ], + ]; + $customerSetup = $this->customerSetupFactory->create(['setup' => $this->moduleDataSetup]); + $customerSetup->upgradeAttributes($entityAttributes); + } + + /** + * @return void + */ + private function upgradeHash() + { + $customerEntityTable = $this->moduleDataSetup->getTable('customer_entity'); + + $select = $this->moduleDataSetup->getConnection()->select()->from( + $customerEntityTable, + ['entity_id', 'password_hash'] + ); + + $customers = $this->moduleDataSetup->getConnection()->fetchAll($select); + foreach ($customers as $customer) { + if ($customer['password_hash'] === null) { + continue; + } + list($hash, $salt) = explode(Encryptor::DELIMITER, $customer['password_hash']); + + $newHash = $customer['password_hash']; + if (strlen($hash) === 32) { + $newHash = implode(Encryptor::DELIMITER, [$hash, $salt, Encryptor::HASH_VERSION_MD5]); + } elseif (strlen($hash) === 64) { + $newHash = implode(Encryptor::DELIMITER, [$hash, $salt, Encryptor::HASH_VERSION_SHA256]); + } + + $bind = ['password_hash' => $newHash]; + $where = ['entity_id = ?' => (int)$customer['entity_id']]; + $this->moduleDataSetup->getConnection()->update($customerEntityTable, $bind, $where); + } + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return [ + AddCustomerUpdatedAtAttribute::class, + ]; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.5'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } +} diff --git a/app/code/Magento/Customer/Setup/UpgradeData.php b/app/code/Magento/Customer/Setup/UpgradeData.php deleted file mode 100644 index 5e08759958853..0000000000000 --- a/app/code/Magento/Customer/Setup/UpgradeData.php +++ /dev/null @@ -1,700 +0,0 @@ -customerSetupFactory = $customerSetupFactory; - $this->indexerRegistry = $indexerRegistry; - $this->eavConfig = $eavConfig; - - $this->fieldDataConverterFactory = $fieldDataConverterFactory ?: ObjectManager::getInstance()->get( - FieldDataConverterFactory::class - ); - } - - /** - * {@inheritdoc} - * @SuppressWarnings(PHPMD.NPathComplexity) - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - */ - public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context) - { - $setup->startSetup(); - /** @var CustomerSetup $customerSetup */ - $customerSetup = $this->customerSetupFactory->create(['setup' => $setup]); - - if (version_compare($context->getVersion(), '2.0.6', '<')) { - $this->upgradeVersionTwoZeroSix($customerSetup); - } - - if (version_compare($context->getVersion(), '2.0.1', '<')) { - $this->upgradeVersionTwoZeroOne($customerSetup); - } - - if (version_compare($context->getVersion(), '2.0.2') < 0) { - $this->upgradeVersionTwoZeroTwo($customerSetup); - } - - if (version_compare($context->getVersion(), '2.0.3', '<')) { - $this->upgradeVersionTwoZeroThree($customerSetup); - } - - if (version_compare($context->getVersion(), '2.0.4', '<')) { - $this->upgradeVersionTwoZeroFour($customerSetup); - } - - if (version_compare($context->getVersion(), '2.0.5', '<')) { - $this->upgradeVersionTwoZeroFive($customerSetup, $setup); - } - - if (version_compare($context->getVersion(), '2.0.6', '<')) { - $setup->getConnection()->delete( - $setup->getTable('customer_form_attribute'), - ['form_code = ?' => 'checkout_register'] - ); - } - - if (version_compare($context->getVersion(), '2.0.8', '<')) { - $setup->getConnection()->update( - $setup->getTable('core_config_data'), - ['path' => \Magento\Customer\Model\Form::XML_PATH_ENABLE_AUTOCOMPLETE], - ['path = ?' => 'general/restriction/autocomplete_on_storefront'] - ); - } - - if (version_compare($context->getVersion(), '2.0.7', '<')) { - $this->upgradeVersionTwoZeroSeven($customerSetup); - $this->upgradeCustomerPasswordResetlinkExpirationPeriodConfig($setup); - } - - if (version_compare($context->getVersion(), '2.0.9', '<')) { - $setup->getConnection()->beginTransaction(); - - try { - $this->migrateStoresAllowedCountriesToWebsite($setup); - $setup->getConnection()->commit(); - } catch (\Exception $e) { - $setup->getConnection()->rollBack(); - throw $e; - } - } - if (version_compare($context->getVersion(), '2.0.11', '<')) { - $fieldDataConverter = $this->fieldDataConverterFactory->create(SerializedToJson::class); - $fieldDataConverter->convert( - $setup->getConnection(), - $setup->getTable('customer_eav_attribute'), - 'attribute_id', - 'validate_rules' - ); - } - - if (version_compare($context->getVersion(), '2.0.12', '<')) { - $this->upgradeVersionTwoZeroTwelve($customerSetup); - } - - if (version_compare($context->getVersion(), '2.0.13', '<')) { - $this->upgradeVersionTwoZeroThirteen($customerSetup); - } - - $this->eavConfig->clear(); - $setup->endSetup(); - } - - /** - * Retrieve Store Manager - * - * @deprecated 100.1.3 - * @return StoreManagerInterface - */ - private function getStoreManager() - { - if (!$this->storeManager) { - $this->storeManager = ObjectManager::getInstance()->get(StoreManagerInterface::class); - } - - return $this->storeManager; - } - - /** - * Retrieve Allowed Countries Reader - * - * @deprecated 100.1.3 - * @return AllowedCountries - */ - private function getAllowedCountriesReader() - { - if (!$this->allowedCountriesReader) { - $this->allowedCountriesReader = ObjectManager::getInstance()->get(AllowedCountries::class); - } - - return $this->allowedCountriesReader; - } - - /** - * Merge allowed countries between different scopes - * - * @param array $countries - * @param array $newCountries - * @param string $identifier - * @return array - */ - private function mergeAllowedCountries(array $countries, array $newCountries, $identifier) - { - if (!isset($countries[$identifier])) { - $countries[$identifier] = $newCountries; - } else { - $countries[$identifier] = - array_replace($countries[$identifier], $newCountries); - } - - return $countries; - } - - /** - * Retrieve countries not depending on global scope - * - * @param string $scope - * @param int $scopeCode - * @return array - */ - private function getAllowedCountries($scope, $scopeCode) - { - $reader = $this->getAllowedCountriesReader(); - return $reader->makeCountriesUnique($reader->getCountriesFromConfig($scope, $scopeCode)); - } - - /** - * Merge allowed countries from stores to websites - * - * @param SetupInterface $setup - * @return void - */ - private function migrateStoresAllowedCountriesToWebsite(SetupInterface $setup) - { - $allowedCountries = []; - //Process Websites - foreach ($this->getStoreManager()->getStores() as $store) { - $allowedCountries = $this->mergeAllowedCountries( - $allowedCountries, - $this->getAllowedCountries(ScopeInterface::SCOPE_STORE, $store->getId()), - $store->getWebsiteId() - ); - } - //Process stores - foreach ($this->getStoreManager()->getWebsites() as $website) { - $allowedCountries = $this->mergeAllowedCountries( - $allowedCountries, - $this->getAllowedCountries(ScopeInterface::SCOPE_WEBSITE, $website->getId()), - $website->getId() - ); - } - - $connection = $setup->getConnection(); - - //Remove everything from stores scope - $connection->delete( - $setup->getTable('core_config_data'), - [ - 'path = ?' => AllowedCountries::ALLOWED_COUNTRIES_PATH, - 'scope = ?' => ScopeInterface::SCOPE_STORES - ] - ); - - //Update websites - foreach ($allowedCountries as $scopeId => $countries) { - $connection->update( - $setup->getTable('core_config_data'), - [ - 'value' => implode(',', $countries) - ], - [ - 'path = ?' => AllowedCountries::ALLOWED_COUNTRIES_PATH, - 'scope_id = ?' => $scopeId, - 'scope = ?' => ScopeInterface::SCOPE_WEBSITES - ] - ); - } - } - - /** - * @param array $entityAttributes - * @param CustomerSetup $customerSetup - * @return void - */ - protected function upgradeAttributes(array $entityAttributes, CustomerSetup $customerSetup) - { - foreach ($entityAttributes as $entityType => $attributes) { - foreach ($attributes as $attributeCode => $attributeData) { - $attribute = $customerSetup->getEavConfig()->getAttribute($entityType, $attributeCode); - foreach ($attributeData as $key => $value) { - $attribute->setData($key, $value); - } - $attribute->save(); - } - } - } - - /** - * @param ModuleDataSetupInterface $setup - * @return void - */ - private function upgradeHash($setup) - { - $customerEntityTable = $setup->getTable('customer_entity'); - - $select = $setup->getConnection()->select()->from( - $customerEntityTable, - ['entity_id', 'password_hash'] - ); - - $customers = $setup->getConnection()->fetchAll($select); - foreach ($customers as $customer) { - if ($customer['password_hash'] === null) { - continue; - } - list($hash, $salt) = explode(Encryptor::DELIMITER, $customer['password_hash']); - - $newHash = $customer['password_hash']; - if (strlen($hash) === 32) { - $newHash = implode(Encryptor::DELIMITER, [$hash, $salt, Encryptor::HASH_VERSION_MD5]); - } elseif (strlen($hash) === 64) { - $newHash = implode(Encryptor::DELIMITER, [$hash, $salt, Encryptor::HASH_VERSION_SHA256]); - } - - $bind = ['password_hash' => $newHash]; - $where = ['entity_id = ?' => (int)$customer['entity_id']]; - $setup->getConnection()->update($customerEntityTable, $bind, $where); - } - } - - /** - * @param CustomerSetup $customerSetup - * @return void - * @SuppressWarnings(PHPMD.ExcessiveMethodLength) - */ - private function upgradeVersionTwoZeroOne($customerSetup) - { - $entityAttributes = [ - 'customer' => [ - 'website_id' => [ - 'is_used_in_grid' => true, - 'is_visible_in_grid' => true, - 'is_filterable_in_grid' => true, - 'is_searchable_in_grid' => false, - ], - 'created_in' => [ - 'is_used_in_grid' => true, - 'is_visible_in_grid' => true, - 'is_filterable_in_grid' => false, - 'is_searchable_in_grid' => true, - ], - 'email' => [ - 'is_used_in_grid' => true, - 'is_visible_in_grid' => true, - 'is_filterable_in_grid' => true, - 'is_searchable_in_grid' => true, - ], - 'group_id' => [ - 'is_used_in_grid' => true, - 'is_visible_in_grid' => true, - 'is_filterable_in_grid' => true, - 'is_searchable_in_grid' => false, - ], - 'dob' => [ - 'is_used_in_grid' => true, - 'is_visible_in_grid' => true, - 'is_filterable_in_grid' => true, - 'is_searchable_in_grid' => false, - ], - 'taxvat' => [ - 'is_used_in_grid' => true, - 'is_visible_in_grid' => true, - 'is_filterable_in_grid' => false, - 'is_searchable_in_grid' => true, - ], - 'confirmation' => [ - 'is_used_in_grid' => true, - 'is_visible_in_grid' => true, - 'is_filterable_in_grid' => true, - 'is_searchable_in_grid' => false, - ], - 'created_at' => [ - 'is_used_in_grid' => true, - 'is_visible_in_grid' => true, - 'is_filterable_in_grid' => true, - 'is_searchable_in_grid' => false, - ], - 'gender' => [ - 'is_used_in_grid' => true, - 'is_visible_in_grid' => true, - 'is_filterable_in_grid' => true, - 'is_searchable_in_grid' => false, - ], - ], - 'customer_address' => [ - 'company' => [ - 'is_used_in_grid' => true, - 'is_visible_in_grid' => false, - 'is_filterable_in_grid' => false, - 'is_searchable_in_grid' => true, - ], - 'street' => [ - 'is_used_in_grid' => true, - 'is_visible_in_grid' => false, - 'is_filterable_in_grid' => false, - 'is_searchable_in_grid' => true, - ], - 'city' => [ - 'is_used_in_grid' => true, - 'is_visible_in_grid' => false, - 'is_filterable_in_grid' => false, - 'is_searchable_in_grid' => true, - ], - 'country_id' => [ - 'is_used_in_grid' => true, - 'is_visible_in_grid' => true, - 'is_filterable_in_grid' => true, - 'is_searchable_in_grid' => false, - ], - 'region' => [ - 'is_used_in_grid' => true, - 'is_visible_in_grid' => true, - 'is_filterable_in_grid' => false, - 'is_searchable_in_grid' => true, - ], - 'region_id' => [ - 'is_used_in_grid' => true, - 'is_visible_in_grid' => false, - 'is_filterable_in_grid' => true, - 'is_searchable_in_grid' => false, - ], - 'postcode' => [ - 'is_used_in_grid' => true, - 'is_visible_in_grid' => true, - 'is_filterable_in_grid' => true, - 'is_searchable_in_grid' => true, - ], - 'telephone' => [ - 'is_used_in_grid' => true, - 'is_visible_in_grid' => true, - 'is_filterable_in_grid' => true, - 'is_searchable_in_grid' => true, - ], - 'fax' => [ - 'is_used_in_grid' => true, - 'is_visible_in_grid' => false, - 'is_filterable_in_grid' => false, - 'is_searchable_in_grid' => true, - ], - ], - ]; - $this->upgradeAttributes($entityAttributes, $customerSetup); - } - - /** - * @param CustomerSetup $customerSetup - * @return void - */ - private function upgradeVersionTwoZeroTwo($customerSetup) - { - $entityTypeId = $customerSetup->getEntityTypeId(Customer::ENTITY); - $attributeId = $customerSetup->getAttributeId($entityTypeId, 'gender'); - - $option = ['attribute_id' => $attributeId, 'values' => [3 => 'Not Specified']]; - $customerSetup->addAttributeOption($option); - } - - /** - * @param CustomerSetup $customerSetup - * @return void - */ - private function upgradeVersionTwoZeroThree($customerSetup) - { - $entityAttributes = [ - 'customer_address' => [ - 'region_id' => [ - 'is_used_in_grid' => false, - 'is_visible_in_grid' => false, - 'is_filterable_in_grid' => false, - 'is_searchable_in_grid' => false, - ], - 'firstname' => [ - 'is_used_in_grid' => true, - 'is_visible_in_grid' => false, - 'is_filterable_in_grid' => false, - 'is_searchable_in_grid' => true, - ], - 'lastname' => [ - 'is_used_in_grid' => true, - 'is_visible_in_grid' => false, - 'is_filterable_in_grid' => false, - 'is_searchable_in_grid' => true, - ], - ], - ]; - $this->upgradeAttributes($entityAttributes, $customerSetup); - } - - /** - * @param CustomerSetup $customerSetup - * @return void - */ - private function upgradeVersionTwoZeroFour($customerSetup) - { - $customerSetup->addAttribute( - Customer::ENTITY, - 'updated_at', - [ - 'type' => 'static', - 'label' => 'Updated At', - 'input' => 'date', - 'required' => false, - 'sort_order' => 87, - 'visible' => false, - 'system' => false, - ] - ); - } - - /** - * @param CustomerSetup $customerSetup - * @param ModuleDataSetupInterface $setup - * @return void - */ - private function upgradeVersionTwoZeroFive($customerSetup, $setup) - { - $this->upgradeHash($setup); - $entityAttributes = [ - 'customer_address' => [ - 'fax' => [ - 'is_visible' => false, - 'is_system' => false, - ], - ], - ]; - $this->upgradeAttributes($entityAttributes, $customerSetup); - } - - /** - * @param CustomerSetup $customerSetup - * @return void - */ - private function upgradeVersionTwoZeroSix($customerSetup) - { - $customerSetup->updateEntityType( - \Magento\Customer\Model\Customer::ENTITY, - 'entity_model', - \Magento\Customer\Model\ResourceModel\Customer::class - ); - $customerSetup->updateEntityType( - \Magento\Customer\Model\Customer::ENTITY, - 'increment_model', - \Magento\Eav\Model\Entity\Increment\NumericValue::class - ); - $customerSetup->updateEntityType( - \Magento\Customer\Model\Customer::ENTITY, - 'entity_attribute_collection', - \Magento\Customer\Model\ResourceModel\Attribute\Collection::class - ); - $customerSetup->updateEntityType( - 'customer_address', - 'entity_model', - \Magento\Customer\Model\ResourceModel\Address::class - ); - $customerSetup->updateEntityType( - 'customer_address', - 'entity_attribute_collection', - \Magento\Customer\Model\ResourceModel\Address\Attribute\Collection::class - ); - $customerSetup->updateAttribute( - 'customer_address', - 'country_id', - 'source_model', - \Magento\Customer\Model\ResourceModel\Address\Attribute\Source\Country::class - ); - $customerSetup->updateAttribute( - 'customer_address', - 'region', - 'backend_model', - \Magento\Customer\Model\ResourceModel\Address\Attribute\Backend\Region::class - ); - $customerSetup->updateAttribute( - 'customer_address', - 'region_id', - 'source_model', - \Magento\Customer\Model\ResourceModel\Address\Attribute\Source\Region::class - ); - } - - /** - * @param CustomerSetup $customerSetup - * @return void - */ - private function upgradeVersionTwoZeroSeven($customerSetup) - { - $customerSetup->addAttribute( - Customer::ENTITY, - 'failures_num', - [ - 'type' => 'static', - 'label' => 'Failures Number', - 'input' => 'hidden', - 'required' => false, - 'sort_order' => 100, - 'visible' => false, - 'system' => true, - ] - ); - - $customerSetup->addAttribute( - Customer::ENTITY, - 'first_failure', - [ - 'type' => 'static', - 'label' => 'First Failure Date', - 'input' => 'date', - 'required' => false, - 'sort_order' => 110, - 'visible' => false, - 'system' => true, - ] - ); - - $customerSetup->addAttribute( - Customer::ENTITY, - 'lock_expires', - [ - 'type' => 'static', - 'label' => 'Failures Number', - 'input' => 'date', - 'required' => false, - 'sort_order' => 120, - 'visible' => false, - 'system' => true, - ] - ); - } - - /** - * @param CustomerSetup $customerSetup - * @return void - */ - private function upgradeVersionTwoZeroTwelve(CustomerSetup $customerSetup) - { - $customerSetup->updateAttribute('customer_address', 'vat_id', 'frontend_label', 'VAT Number'); - } - - /** - * @param ModuleDataSetupInterface $setup - * @return void - */ - private function upgradeCustomerPasswordResetlinkExpirationPeriodConfig($setup) - { - $configTable = $setup->getTable('core_config_data'); - - $setup->getConnection()->update( - $configTable, - ['value' => new \Zend_Db_Expr('value*24')], - ['path = ?' => \Magento\Customer\Model\Customer::XML_PATH_CUSTOMER_RESET_PASSWORD_LINK_EXPIRATION_PERIOD] - ); - } - - /** - * @param CustomerSetup $customerSetup - */ - private function upgradeVersionTwoZeroThirteen(CustomerSetup $customerSetup) - { - $entityAttributes = [ - 'customer_address' => [ - 'firstname' => [ - 'input_filter' => 'trim' - ], - 'lastname' => [ - 'input_filter' => 'trim' - ], - 'middlename' => [ - 'input_filter' => 'trim' - ], - ], - 'customer' => [ - 'firstname' => [ - 'input_filter' => 'trim' - ], - 'lastname' => [ - 'input_filter' => 'trim' - ], - 'middlename' => [ - 'input_filter' => 'trim' - ], - ], - ]; - $this->upgradeAttributes($entityAttributes, $customerSetup); - } -} diff --git a/app/code/Magento/Customer/Test/Unit/Controller/Account/EditPostTest.php b/app/code/Magento/Customer/Test/Unit/Controller/Account/EditPostTest.php index f2860725dbbae..aaa1c17027928 100644 --- a/app/code/Magento/Customer/Test/Unit/Controller/Account/EditPostTest.php +++ b/app/code/Magento/Customer/Test/Unit/Controller/Account/EditPostTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Customer\Test\Unit\Controller\Account; use Magento\Customer\Api\CustomerRepositoryInterface; @@ -394,12 +395,13 @@ public function changeEmailExceptionDataProvider() [ 'testNumber' => 1, 'exceptionClass' => \Magento\Framework\Exception\InvalidEmailOrPasswordException::class, - 'errorMessage' => __('The password doesn\'t match this account.') + 'errorMessage' => __("The password doesn't match this account. Verify the password and try again.") ], [ 'testNumber' => 2, 'exceptionClass' => \Magento\Framework\Exception\State\UserLockedException::class, - 'errorMessage' => __('You did not sign in correctly or your account is temporarily disabled.') + 'errorMessage' => __('The account sign-in was incorrect or your account is disabled temporarily. ' + . 'Please wait and try again later.') ] ]; } diff --git a/app/code/Magento/Customer/Test/Unit/Controller/Account/LoginPostTest.php b/app/code/Magento/Customer/Test/Unit/Controller/Account/LoginPostTest.php index 8e07f41cff5a7..762c76b695dee 100644 --- a/app/code/Magento/Customer/Test/Unit/Controller/Account/LoginPostTest.php +++ b/app/code/Magento/Customer/Test/Unit/Controller/Account/LoginPostTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Customer\Test\Unit\Controller\Account; use Magento\Customer\Api\AccountManagementInterface; @@ -563,7 +564,12 @@ protected function mockExceptions($exception, $username) case \Magento\Framework\Exception\AuthenticationException::class: $this->messageManager->expects($this->once()) ->method('addError') - ->with(__('You did not sign in correctly or your account is temporarily disabled.')) + ->with( + __( + 'The account sign-in was incorrect or your account is disabled temporarily. ' + . 'Please wait and try again later.' + ) + ) ->willReturnSelf(); $this->session->expects($this->once()) @@ -581,7 +587,8 @@ protected function mockExceptions($exception, $username) case \Magento\Framework\Exception\State\UserLockedException::class: $message = __( - 'You did not sign in correctly or your account is temporarily disabled.' + 'The account sign-in was incorrect or your account is disabled temporarily. ' + . 'Please wait and try again later.' ); $this->messageManager->expects($this->once()) ->method('addError') diff --git a/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php b/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php index fed2005ade8e2..0ca79833e8a13 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Customer\Test\Unit\Model; use Magento\Customer\Model\AccountManagement; @@ -723,7 +724,8 @@ public function testCreateAccountWithPasswordInputException( if ($testNumber == 1) { $this->expectException( \Magento\Framework\Exception\InputException::class, - 'Please enter a password with at least ' . $minPasswordLength . ' characters.' + 'The password needs at least ' . $minPasswordLength . ' characters. ' + . 'Create a new password and try again.' ); } @@ -1214,7 +1216,7 @@ public function testValidateResetPasswordTokenBadCustomerId() /** * @expectedException \Magento\Framework\Exception\InputException - * @expectedExceptionMessage resetPasswordLinkToken is a required field + * @expectedExceptionMessage "resetPasswordLinkToken" is required. Enter and try again. */ public function testValidateResetPasswordTokenBadResetPasswordLinkToken() { @@ -1223,7 +1225,7 @@ public function testValidateResetPasswordTokenBadResetPasswordLinkToken() /** * @expectedException \Magento\Framework\Exception\State\InputMismatchException - * @expectedExceptionMessage Reset password token mismatch + * @expectedExceptionMessage The password token is mismatched. Reset and try again. */ public function testValidateResetPasswordTokenTokenMismatch() { @@ -1236,7 +1238,7 @@ public function testValidateResetPasswordTokenTokenMismatch() /** * @expectedException \Magento\Framework\Exception\State\ExpiredException - * @expectedExceptionMessage Reset password token expired + * @expectedExceptionMessage The password token is expired. Reset and try again. */ public function testValidateResetPasswordTokenTokenExpired() { diff --git a/app/code/Magento/Customer/Test/Unit/Model/Address/AbstractAddressTest.php b/app/code/Magento/Customer/Test/Unit/Model/Address/AbstractAddressTest.php index 2eef9a44cab74..a94b7e39bc0eb 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/Address/AbstractAddressTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/Address/AbstractAddressTest.php @@ -327,31 +327,31 @@ public function validateDataProvider() return [ 'firstname' => [ array_merge(array_diff_key($data, ['firstname' => '']), ['country_id' => $countryId++]), - ['firstname is a required field.'], + ['"firstname" is required. Enter and try again.'], ], 'lastname' => [ array_merge(array_diff_key($data, ['lastname' => '']), ['country_id' => $countryId++]), - ['lastname is a required field.'], + ['"lastname" is required. Enter and try again.'], ], 'street' => [ array_merge(array_diff_key($data, ['street' => '']), ['country_id' => $countryId++]), - ['street is a required field.'], + ['"street" is required. Enter and try again.'], ], 'city' => [ array_merge(array_diff_key($data, ['city' => '']), ['country_id' => $countryId++]), - ['city is a required field.'], + ['"city" is required. Enter and try again.'], ], 'telephone' => [ array_merge(array_diff_key($data, ['telephone' => '']), ['country_id' => $countryId++]), - ['telephone is a required field.'], + ['"telephone" is required. Enter and try again.'], ], 'postcode' => [ array_merge(array_diff_key($data, ['postcode' => '']), ['country_id' => $countryId++]), - ['postcode is a required field.'], + ['"postcode" is required. Enter and try again.'], ], 'country_id' => [ array_diff_key($data, ['country_id' => '']), - ['countryId is a required field.'], + ['"countryId" is required. Enter and try again.'], ], 'validated' => [array_merge($data, ['country_id' => $countryId++]), true], ]; diff --git a/app/code/Magento/Customer/Test/Unit/Model/Customer/CredentialsValidatorTest.php b/app/code/Magento/Customer/Test/Unit/Model/Customer/CredentialsValidatorTest.php index 07aef85e92d08..36667e0ccf6c3 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/Customer/CredentialsValidatorTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/Customer/CredentialsValidatorTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Customer\Test\Unit\Model\Customer; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; @@ -29,7 +30,6 @@ protected function setUp() /** * @expectedException \Magento\Framework\Exception\InputException - * @expectedExceptionMessage Password cannot be the same as email address. */ public function testCheckPasswordDifferentFromEmail() { @@ -37,5 +37,9 @@ public function testCheckPasswordDifferentFromEmail() $password = strtoupper($email); // for case-insensitive check $this->object->checkPasswordDifferentFromEmail($email, $password); + + $this->expectExceptionMessage( + "The password can't be the same as the email address. Create a new password and try again." + ); } } diff --git a/app/code/Magento/Customer/Test/Unit/Model/CustomerTest.php b/app/code/Magento/Customer/Test/Unit/Model/CustomerTest.php index f5b7f08d2906d..9848a09540cb0 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/CustomerTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/CustomerTest.php @@ -134,7 +134,7 @@ public function testHashPassword() /** * @expectedException \Magento\Framework\Exception\LocalizedException - * @expectedExceptionMessage Please correct the transactional account email type. + * @expectedExceptionMessage The transactional account email type is incorrect. Verify and try again. */ public function testSendNewAccountEmailException() { diff --git a/app/code/Magento/Customer/Test/Unit/Model/ResourceModel/AddressRepositoryTest.php b/app/code/Magento/Customer/Test/Unit/Model/ResourceModel/AddressRepositoryTest.php index f2ccc50dc68d0..070e5e59e3f99 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/ResourceModel/AddressRepositoryTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/ResourceModel/AddressRepositoryTest.php @@ -275,13 +275,13 @@ public function testSaveWithInvalidRegion() /** * @expectedException \Magento\Framework\Exception\InputException - * @expectedExceptionMessage regionId is a required field. + * @expectedExceptionMessage "regionId" is required. Enter and try again. */ public function testSaveWithInvalidRegionId() { $customerId = 34; $addressId = 53; - $errors[] = __('regionId is a required field.'); + $errors[] = __('"regionId" is required. Enter and try again.'); $customerAddress = $this->getMockForAbstractClass( \Magento\Customer\Api\Data\AddressInterface::class, [], diff --git a/app/code/Magento/Customer/Test/Unit/Model/ResourceModel/Group/Grid/ServiceCollectionTest.php b/app/code/Magento/Customer/Test/Unit/Model/ResourceModel/Group/Grid/ServiceCollectionTest.php index 61081e1aaf224..524ae9065f67e 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/ResourceModel/Group/Grid/ServiceCollectionTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/ResourceModel/Group/Grid/ServiceCollectionTest.php @@ -219,7 +219,7 @@ public function testGetSearchCriteriaAnd() * @param array $conditions * * @expectedException \Magento\Framework\Exception\LocalizedException - * @expectedExceptionMessage When passing in a field array there must be a matching condition array + * @expectedExceptionMessage The field array failed to pass. The array must have a matching condition array. * @dataProvider addFieldToFilterInconsistentArraysDataProvider */ public function testAddFieldToFilterInconsistentArrays($fields, $conditions) @@ -243,7 +243,7 @@ public function addFieldToFilterInconsistentArraysDataProvider() /** * @expectedException \Magento\Framework\Exception\LocalizedException - * @expectedExceptionMessage When passing an array of fields there must be at least one field in the array. + * @expectedExceptionMessage The array of fields failed to pass. The array must include at one field. * @dataProvider addFieldToFilterInconsistentArraysDataProvider */ public function testAddFieldToFilterEmptyArrays() diff --git a/app/code/Magento/Customer/etc/events.xml b/app/code/Magento/Customer/etc/events.xml index 66c9a3813892c..d841d8faa9c38 100644 --- a/app/code/Magento/Customer/etc/events.xml +++ b/app/code/Magento/Customer/etc/events.xml @@ -10,7 +10,7 @@ - + diff --git a/app/code/Magento/Customer/etc/module.xml b/app/code/Magento/Customer/etc/module.xml index 2dfe561d0da8f..853157fed1f5d 100644 --- a/app/code/Magento/Customer/etc/module.xml +++ b/app/code/Magento/Customer/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/Customer/view/frontend/web/js/password-strength-indicator.js b/app/code/Magento/Customer/view/frontend/web/js/password-strength-indicator.js index 71ca63f6750bb..be2e0aedfe4bb 100644 --- a/app/code/Magento/Customer/view/frontend/web/js/password-strength-indicator.js +++ b/app/code/Magento/Customer/view/frontend/web/js/password-strength-indicator.js @@ -31,6 +31,8 @@ define([ this.options.cache.label = $(this.options.passwordStrengthMeterLabelSelector, this.element); // We need to look outside the module for backward compatibility, since someone can already use the module. + // @todo Narrow this selector in 2.3 so it doesn't accidentally finds the the email field from the + // newsletter email field or any other "email" field. this.options.cache.email = $(this.options.formSelector).find(this.options.emailSelector); this._bind(); }, @@ -74,7 +76,9 @@ define([ 'password-not-equal-to-user-name': this.options.cache.email.val() }); - if (password.toLowerCase() === this.options.cache.email.val().toLowerCase()) { + // We should only perform this check in case there is an email field on screen + if (this.options.cache.email.length && + password.toLowerCase() === this.options.cache.email.val().toLowerCase()) { displayScore = 1; } else { isValid = $.validator.validateSingleElement(this.options.cache.input); diff --git a/app/code/Magento/CustomerAnalytics/etc/module.xml b/app/code/Magento/CustomerAnalytics/etc/module.xml index adc4f8dd849c2..a6a3380b3462e 100644 --- a/app/code/Magento/CustomerAnalytics/etc/module.xml +++ b/app/code/Magento/CustomerAnalytics/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/CustomerGraphQl/etc/module.xml b/app/code/Magento/CustomerGraphQl/etc/module.xml index 88f08623c717d..c3149965b0fe0 100644 --- a/app/code/Magento/CustomerGraphQl/etc/module.xml +++ b/app/code/Magento/CustomerGraphQl/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/CustomerImportExport/Model/Import/AbstractCustomer.php b/app/code/Magento/CustomerImportExport/Model/Import/AbstractCustomer.php index 1d78c4e5bc20e..cc6eebed57b1d 100644 --- a/app/code/Magento/CustomerImportExport/Model/Import/AbstractCustomer.php +++ b/app/code/Magento/CustomerImportExport/Model/Import/AbstractCustomer.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\CustomerImportExport\Model\Import; use Magento\ImportExport\Model\Import; @@ -122,7 +123,10 @@ public function __construct( ); $this->addMessageTemplate(self::ERROR_WEBSITE_IS_EMPTY, __('Please specify a website.')); - $this->addMessageTemplate(self::ERROR_EMAIL_IS_EMPTY, __('Please specify an email.')); + $this->addMessageTemplate( + self::ERROR_EMAIL_IS_EMPTY, + __("An email wasn't specified. Enter the email and try again.") + ); $this->addMessageTemplate(self::ERROR_INVALID_WEBSITE, __('We found an invalid value in a website column.')); $this->addMessageTemplate(self::ERROR_INVALID_EMAIL, __('Please enter a valid email.')); $this->addMessageTemplate(self::ERROR_VALUE_IS_REQUIRED, __('Please make sure attribute "%s" is not empty.')); diff --git a/app/code/Magento/CustomerImportExport/etc/module.xml b/app/code/Magento/CustomerImportExport/etc/module.xml index 865b2e991418d..2b351d06a5ffd 100644 --- a/app/code/Magento/CustomerImportExport/etc/module.xml +++ b/app/code/Magento/CustomerImportExport/etc/module.xml @@ -6,6 +6,6 @@ */ --> - + diff --git a/app/code/Magento/Deploy/Console/Command/App/SensitiveConfigSet/CollectorFactory.php b/app/code/Magento/Deploy/Console/Command/App/SensitiveConfigSet/CollectorFactory.php index f7c38f7c6f680..c66388ed47092 100644 --- a/app/code/Magento/Deploy/Console/Command/App/SensitiveConfigSet/CollectorFactory.php +++ b/app/code/Magento/Deploy/Console/Command/App/SensitiveConfigSet/CollectorFactory.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Deploy\Console\Command\App\SensitiveConfigSet; use Magento\Framework\Exception\LocalizedException; @@ -64,7 +65,9 @@ public function __construct( public function create($type) { if (!isset($this->types[$type])) { - throw new LocalizedException(__('Class for type "%1" was not declared', $type)); + throw new LocalizedException( + __('The class for "%1" type wasn\'t declared. Enter the class and try again.', $type) + ); } $object = $this->objectManager->create($this->types[$type]); diff --git a/app/code/Magento/Deploy/Console/Command/App/SensitiveConfigSet/SimpleCollector.php b/app/code/Magento/Deploy/Console/Command/App/SensitiveConfigSet/SimpleCollector.php index 0dd5930794168..53cd616604049 100644 --- a/app/code/Magento/Deploy/Console/Command/App/SensitiveConfigSet/SimpleCollector.php +++ b/app/code/Magento/Deploy/Console/Command/App/SensitiveConfigSet/SimpleCollector.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Deploy\Console\Command\App\SensitiveConfigSet; use Magento\Deploy\Console\Command\App\SensitiveConfigSetCommand; @@ -103,7 +104,7 @@ private function getConfigValueQuestion() ]); $configValueQuestion->setValidator(function ($interviewer) { if (empty($interviewer)) { - throw new LocalizedException(new Phrase('Value can\'t be empty')); + throw new LocalizedException(new Phrase("The value can't be empty. Enter the value and try again.")); } return $interviewer; }); diff --git a/app/code/Magento/Deploy/Console/Command/SetModeCommand.php b/app/code/Magento/Deploy/Console/Command/SetModeCommand.php index 55b4a4f4f9b6a..2e223f5a0dc65 100644 --- a/app/code/Magento/Deploy/Console/Command/SetModeCommand.php +++ b/app/code/Magento/Deploy/Console/Command/SetModeCommand.php @@ -105,7 +105,7 @@ protected function execute(InputInterface $input, OutputInterface $output) $modeController->enableDefaultMode(); break; default: - throw new LocalizedException(__('Cannot switch into given mode "%1"', $toMode)); + throw new LocalizedException(__('The mode can\'t be switched to "%1".', $toMode)); } $output->writeln('Enabled ' . $toMode . ' mode.'); diff --git a/app/code/Magento/Deploy/Model/DeploymentConfig/Hash.php b/app/code/Magento/Deploy/Model/DeploymentConfig/Hash.php index 780d36ddb27e0..17f418d9457d8 100644 --- a/app/code/Magento/Deploy/Model/DeploymentConfig/Hash.php +++ b/app/code/Magento/Deploy/Model/DeploymentConfig/Hash.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Deploy\Model\DeploymentConfig; use Magento\Framework\Exception\LocalizedException; @@ -97,7 +98,7 @@ public function regenerate($sectionName = null) $flag->setFlagData($hashes); $this->flagResource->save($flag); } catch (\Exception $exception) { - throw new LocalizedException(__('Hash has not been saved.'), $exception); + throw new LocalizedException(__("The hash isn't saved."), $exception); } } diff --git a/app/code/Magento/Deploy/Model/DeploymentConfig/ImporterPool.php b/app/code/Magento/Deploy/Model/DeploymentConfig/ImporterPool.php index 9a987c704dea0..a4a9ef00c4a83 100644 --- a/app/code/Magento/Deploy/Model/DeploymentConfig/ImporterPool.php +++ b/app/code/Magento/Deploy/Model/DeploymentConfig/ImporterPool.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Deploy\Model\DeploymentConfig; use Magento\Framework\App\DeploymentConfig\ValidatorInterface; @@ -148,7 +149,9 @@ public function getImporters() foreach ($this->sort($this->importers) as $section => $importer) { if (empty($importer['importer_class'])) { - throw new ConfigurationMismatchException(__('Parameter "importer_class" must be present.')); + throw new ConfigurationMismatchException( + __('The parameter "importer_class" is missing. Set the "importer_class" and try again.') + ); } $sortedImporters[$section] = $importer['importer_class']; diff --git a/app/code/Magento/Deploy/Model/Plugin/ConfigChangeDetector.php b/app/code/Magento/Deploy/Model/Plugin/ConfigChangeDetector.php index 6ebc208ca6a97..0642593ac5528 100644 --- a/app/code/Magento/Deploy/Model/Plugin/ConfigChangeDetector.php +++ b/app/code/Magento/Deploy/Model/Plugin/ConfigChangeDetector.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Deploy\Model\Plugin; use Magento\Deploy\Model\DeploymentConfig\ChangeDetector; @@ -49,7 +50,7 @@ public function beforeDispatch(FrontControllerInterface $subject, RequestInterfa throw new LocalizedException( __( 'The configuration file has changed.' - . ' Run app:config:import or setup:upgrade command to synchronize configuration.' + . ' Run the "app:config:import" or the "setup:upgrade" command to synchronize the configuration.' ) ); } diff --git a/app/code/Magento/Deploy/Test/Unit/Console/Command/App/SensitiveConfigSet/CollectorFactoryTest.php b/app/code/Magento/Deploy/Test/Unit/Console/Command/App/SensitiveConfigSet/CollectorFactoryTest.php index 155acd4c785f0..6ac84b1c83424 100644 --- a/app/code/Magento/Deploy/Test/Unit/Console/Command/App/SensitiveConfigSet/CollectorFactoryTest.php +++ b/app/code/Magento/Deploy/Test/Unit/Console/Command/App/SensitiveConfigSet/CollectorFactoryTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Deploy\Test\Unit\Console\Command\App\SensitiveConfigSet; use Magento\Deploy\Console\Command\App\SensitiveConfigSet\CollectorFactory; @@ -60,7 +61,7 @@ public function testCreate() /** * @expectedException \Magento\Framework\Exception\LocalizedException - * @expectedExceptionMessage Class for type "dummyType" was not declared + * @expectedExceptionMessage The class for "dummyType" type wasn't declared. Enter the class and try again. */ public function testCreateNonExisted() { diff --git a/app/code/Magento/Deploy/Test/Unit/Console/Command/SetModeCommandTest.php b/app/code/Magento/Deploy/Test/Unit/Console/Command/SetModeCommandTest.php index 33ffbf20c5bd9..588dd40ad6c4b 100644 --- a/app/code/Magento/Deploy/Test/Unit/Console/Command/SetModeCommandTest.php +++ b/app/code/Magento/Deploy/Test/Unit/Console/Command/SetModeCommandTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Deploy\Test\Unit\Console\Command; use Magento\Deploy\Console\Command\SetModeCommand; @@ -95,7 +96,7 @@ public function testSetInvalidMode() $tester = new CommandTester($this->command); $tester->execute(['mode' => 'invalid-mode']); $this->assertContains( - "Cannot switch into given mode", + 'The mode can\'t be switched to "invalid-mode".', $tester->getDisplay() ); } diff --git a/app/code/Magento/Deploy/Test/Unit/Model/DeploymentConfig/HashTest.php b/app/code/Magento/Deploy/Test/Unit/Model/DeploymentConfig/HashTest.php index 4afe9aa267d69..a67f32eb36457 100644 --- a/app/code/Magento/Deploy/Test/Unit/Model/DeploymentConfig/HashTest.php +++ b/app/code/Magento/Deploy/Test/Unit/Model/DeploymentConfig/HashTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Deploy\Test\Unit\Model\DeploymentConfig; use Magento\Deploy\Model\DeploymentConfig\DataCollector; @@ -137,7 +138,7 @@ public function testRegenerate() /** * @return void * @expectedException \Magento\Framework\Exception\LocalizedException - * @expectedExceptionMessage Hash has not been saved + * @expectedExceptionMessage The hash isn't saved. */ public function testRegenerateWithException() { diff --git a/app/code/Magento/Deploy/Test/Unit/Model/DeploymentConfig/ImporterPoolTest.php b/app/code/Magento/Deploy/Test/Unit/Model/DeploymentConfig/ImporterPoolTest.php index 73d90b4795d04..36c5dd9e734db 100644 --- a/app/code/Magento/Deploy/Test/Unit/Model/DeploymentConfig/ImporterPoolTest.php +++ b/app/code/Magento/Deploy/Test/Unit/Model/DeploymentConfig/ImporterPoolTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Deploy\Test\Unit\Model\DeploymentConfig; use Magento\Deploy\Model\DeploymentConfig\ImporterPool; @@ -68,7 +69,7 @@ public function testGetImporters() /** * @return void * @expectedException \Magento\Framework\Exception\ConfigurationMismatchException - * @expectedExceptionMessage Parameter "importer_class" must be present. + * @expectedExceptionMessage The parameter "importer_class" is missing. Set the "importer_class" and try again. */ public function testGetImportersEmptyParameterClass() { diff --git a/app/code/Magento/Deploy/Test/Unit/Model/Plugin/ConfigChangeDetectorTest.php b/app/code/Magento/Deploy/Test/Unit/Model/Plugin/ConfigChangeDetectorTest.php index 62cb1bab3b330..a3b6cf241b708 100644 --- a/app/code/Magento/Deploy/Test/Unit/Model/Plugin/ConfigChangeDetectorTest.php +++ b/app/code/Magento/Deploy/Test/Unit/Model/Plugin/ConfigChangeDetectorTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Deploy\Test\Unit\Model\Plugin; use Magento\Deploy\Model\Plugin\ConfigChangeDetector; @@ -63,7 +64,7 @@ public function testBeforeDispatchWithoutException() * @return void * @expectedException \Magento\Framework\Exception\LocalizedException * @codingStandardsIgnoreStart - * @expectedExceptionMessage The configuration file has changed. Run app:config:import or setup:upgrade command to synchronize configuration. + * @expectedExceptionMessage The configuration file has changed. Run the "app:config:import" or the "setup:upgrade" command to synchronize the configuration. * @codingStandardsIgnoreEnd */ public function testBeforeDispatchWithException() diff --git a/app/code/Magento/Deploy/etc/module.xml b/app/code/Magento/Deploy/etc/module.xml index a61f9e1546e05..d4785cd7a3112 100644 --- a/app/code/Magento/Deploy/etc/module.xml +++ b/app/code/Magento/Deploy/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/Developer/Console/Command/GeneratePatchCommand.php b/app/code/Magento/Developer/Console/Command/GeneratePatchCommand.php new file mode 100644 index 0000000000000..7a7deba98ea4e --- /dev/null +++ b/app/code/Magento/Developer/Console/Command/GeneratePatchCommand.php @@ -0,0 +1,124 @@ +componentRegistrar = $componentRegistrar; + parent::__construct(); + } + + /** + * {@inheritdoc} + * @throws InvalidArgumentException + */ + protected function configure() + { + $this->setName(self::COMMAND_NAME) + ->setDescription('Generate patch and put it in specific folder.') + ->setDefinition([ + new InputArgument( + self::MODULE_NAME, + InputArgument::REQUIRED, + 'Module name' + ), + new InputArgument( + self::INPUT_KEY_PATCH_NAME, + InputArgument::REQUIRED, + 'Patch name' + ), + new InputOption( + self::INPUT_KEY_IS_REVERTABLE, + null, + InputOption::VALUE_OPTIONAL, + 'Check whether patch is revertable or not.', + false + ), + new InputOption( + self::INPUT_KEY_PATCH_TYPE, + null, + InputOption::VALUE_OPTIONAL, + 'Find out what type of patch should be generated.', + 'data' + ), + ]); + + parent::configure(); + } + + /** + * Patch template + * + * @return string + */ + private function getPatchTemplate() + { + return file_get_contents(__DIR__ . '/patch_template.php.dist'); + } + + /** + * {@inheritdoc} + * @throws \InvalidArgumentException + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $moduleName = $input->getArgument(self::MODULE_NAME); + $patchName = $input->getArgument(self::INPUT_KEY_PATCH_NAME); + $type = $input->getOption(self::INPUT_KEY_PATCH_TYPE); + $modulePath = $this->componentRegistrar->getPath(ComponentRegistrar::MODULE, $moduleName); + $preparedModuleName = str_replace('_', '\\', $moduleName); + $preparedType = ucfirst($type); + $patchInterface = sprintf('%sPatchInterface', $preparedType); + $patchTemplateData = $this->getPatchTemplate(); + $patchTemplateData = str_replace('%moduleName%', $preparedModuleName, $patchTemplateData); + $patchTemplateData = str_replace('%patchType%', $preparedType, $patchTemplateData); + $patchTemplateData = str_replace('%patchInterface%', $patchInterface, $patchTemplateData); + $patchTemplateData = str_replace('%class%', $patchName, $patchTemplateData); + $patchDir = $patchToFile = $modulePath . '/Setup/Patch/' . $preparedType; + + if (!is_dir($patchDir)) { + mkdir($patchDir, 0777, true); + } + $patchToFile = $patchDir . '/' . $patchName . '.php'; + file_put_contents($patchToFile, $patchTemplateData); + return Cli::RETURN_SUCCESS; + } +} diff --git a/app/code/Magento/Developer/Console/Command/patch_template.php.dist b/app/code/Magento/Developer/Console/Command/patch_template.php.dist new file mode 100644 index 0000000000000..cbb6b4dd5d7fa --- /dev/null +++ b/app/code/Magento/Developer/Console/Command/patch_template.php.dist @@ -0,0 +1,70 @@ +moduleDataSetup = $moduleDataSetup; + } + + /** + * Do Upgrade + * + * @return void + */ + public function apply() + { + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return [ + + ]; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return ''; + } + +} diff --git a/app/code/Magento/Developer/Test/Unit/Console/Command/_files/test.xml b/app/code/Magento/Developer/Test/Unit/Console/Command/_files/test.xml index ce31b046500f7..8112b9e8c46db 100644 --- a/app/code/Magento/Developer/Test/Unit/Console/Command/_files/test.xml +++ b/app/code/Magento/Developer/Test/Unit/Console/Command/_files/test.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/Developer/etc/di.xml b/app/code/Magento/Developer/etc/di.xml index f68d01b8339d0..2254c94a8a913 100644 --- a/app/code/Magento/Developer/etc/di.xml +++ b/app/code/Magento/Developer/etc/di.xml @@ -105,6 +105,7 @@ Magento\Developer\Console\Command\TemplateHintsEnableCommand Magento\Developer\Console\Command\ProfilerDisableCommand Magento\Developer\Console\Command\ProfilerEnableCommand + Magento\Developer\Console\Command\GeneratePatchCommand diff --git a/app/code/Magento/Developer/etc/module.xml b/app/code/Magento/Developer/etc/module.xml index 96a8828b00c4b..e3cf8132e3e92 100644 --- a/app/code/Magento/Developer/etc/module.xml +++ b/app/code/Magento/Developer/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/Dhl/Model/Validator/XmlValidator.php b/app/code/Magento/Dhl/Model/Validator/XmlValidator.php index a489832b47b20..762dcbe5939c2 100644 --- a/app/code/Magento/Dhl/Model/Validator/XmlValidator.php +++ b/app/code/Magento/Dhl/Model/Validator/XmlValidator.php @@ -49,7 +49,7 @@ public function validate($xmlResponse, $isShippingLabel = false) { if (strlen(trim($xmlResponse)) > 0 && strpos(trim($xmlResponse), 'xmlSecurity->scan($xmlResponse)) { - throw new DocumentValidationException(__('Security validation of XML document has been failed.')); + throw new DocumentValidationException(__('The security validation of the XML document has failed.')); } $xml = simplexml_load_string($xmlResponse, \Magento\Shipping\Model\Simplexml\Element::class); diff --git a/app/code/Magento/Dhl/Setup/InstallData.php b/app/code/Magento/Dhl/Setup/InstallData.php deleted file mode 100644 index 48f359aa63659..0000000000000 --- a/app/code/Magento/Dhl/Setup/InstallData.php +++ /dev/null @@ -1,68 +0,0 @@ -localeResolver = $localeResolver; - } - - /** - * {@inheritdoc} - */ - public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context) - { - $days = (new DataBundle())->get( - $this->localeResolver->getLocale() - )['calendar']['gregorian']['dayNames']['format']['abbreviated']; - - $select = $setup->getConnection()->select()->from( - $setup->getTable('core_config_data'), - ['config_id', 'value'] - )->where( - 'path = ?', - 'carriers/dhl/shipment_days' - ); - - foreach ($setup->getConnection()->fetchAll($select) as $configRow) { - $row = [ - 'value' => implode( - ',', - array_intersect_key(iterator_to_array($days), array_flip(explode(',', $configRow['value']))) - ) - ]; - $setup->getConnection()->update( - $setup->getTable('core_config_data'), - $row, - ['config_id = ?' => $configRow['config_id']] - ); - } - } -} diff --git a/app/code/Magento/Dhl/Setup/Patch/Data/PrepareShipmentDays.php b/app/code/Magento/Dhl/Setup/Patch/Data/PrepareShipmentDays.php new file mode 100644 index 0000000000000..ce026c3e643ad --- /dev/null +++ b/app/code/Magento/Dhl/Setup/Patch/Data/PrepareShipmentDays.php @@ -0,0 +1,99 @@ +moduleDataSetup = $moduleDataSetup; + $this->localeResolver = $localeResolver; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + $days = (new DataBundle())->get( + $this->localeResolver->getLocale() + )['calendar']['gregorian']['dayNames']['format']['abbreviated']; + + $select = $this->moduleDataSetup->getConnection()->select()->from( + $this->moduleDataSetup->getTable('core_config_data'), + ['config_id', 'value'] + )->where( + 'path = ?', + 'carriers/dhl/shipment_days' + ); + foreach ($this->moduleDataSetup->getConnection()->fetchAll($select) as $configRow) { + $row = [ + 'value' => implode( + ',', + array_intersect_key(iterator_to_array($days), array_flip(explode(',', $configRow['value']))) + ) + ]; + $this->moduleDataSetup->getConnection()->update( + $this->moduleDataSetup->getTable('core_config_data'), + $row, + ['config_id = ?' => $configRow['config_id']] + ); + } + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return []; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.0'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } +} diff --git a/app/code/Magento/Dhl/Test/Unit/Model/Validator/XmlValidatorTest.php b/app/code/Magento/Dhl/Test/Unit/Model/Validator/XmlValidatorTest.php index 3d7893fea118f..26d879422389d 100644 --- a/app/code/Magento/Dhl/Test/Unit/Model/Validator/XmlValidatorTest.php +++ b/app/code/Magento/Dhl/Test/Unit/Model/Validator/XmlValidatorTest.php @@ -123,7 +123,7 @@ public function invalidXmlResponseProvider() [ [ 'file' => 'invalidDHLResponse.xml', - 'errorMessage' => 'Security validation of XML document has been failed.', + 'errorMessage' => 'The security validation of the XML document has failed.', 'isGenerateXml' => false, ], ], diff --git a/app/code/Magento/Dhl/etc/module.xml b/app/code/Magento/Dhl/etc/module.xml index 4723b14763a12..b1af1baf97fc2 100644 --- a/app/code/Magento/Dhl/etc/module.xml +++ b/app/code/Magento/Dhl/etc/module.xml @@ -6,6 +6,6 @@ */ --> - + diff --git a/app/code/Magento/Directory/Model/CountryInformationAcquirer.php b/app/code/Magento/Directory/Model/CountryInformationAcquirer.php index 4eaa18d9672d1..69c8f21f5a235 100644 --- a/app/code/Magento/Directory/Model/CountryInformationAcquirer.php +++ b/app/code/Magento/Directory/Model/CountryInformationAcquirer.php @@ -103,7 +103,7 @@ public function getCountryInfo($countryId) if (!$country) { throw new NoSuchEntityException( __( - 'Requested country is not available.' + "The country isn't available." ) ); } diff --git a/app/code/Magento/Directory/Model/Observer.php b/app/code/Magento/Directory/Model/Observer.php index 8ad67ad191018..e35c2de5cee5b 100644 --- a/app/code/Magento/Directory/Model/Observer.php +++ b/app/code/Magento/Directory/Model/Observer.php @@ -9,6 +9,7 @@ * * @author Magento Core Team */ + namespace Magento\Directory\Model; class Observer @@ -113,7 +114,8 @@ public function scheduledUpdateCurrencyRates($schedule) $rates = $importModel->fetchRates(); $errors = $importModel->getMessages(); } catch (\Exception $e) { - $importWarnings[] = __('FATAL ERROR:') . ' ' . __('We can\'t initialize the import model.'); + $importWarnings[] = __('FATAL ERROR:') . ' ' + . __("The import model can't be initialized. Verify the model and try again."); throw $e; } } else { diff --git a/app/code/Magento/Directory/Setup/DataInstaller.php b/app/code/Magento/Directory/Setup/DataInstaller.php new file mode 100644 index 0000000000000..9fccc16e1d49b --- /dev/null +++ b/app/code/Magento/Directory/Setup/DataInstaller.php @@ -0,0 +1,76 @@ +data = $data; + $this->resourceConnection = $resourceConnection; + } + + /** + * Add country-region data. + * + * @param AdapterInterface $adapter + * @param array $data + */ + public function addCountryRegions(AdapterInterface $adapter, array $data) + { + /** + * Fill table directory/country_region + * Fill table directory/country_region_name for en_US locale + */ + foreach ($data as $row) { + $bind = ['country_id' => $row[0], 'code' => $row[1], 'default_name' => $row[2]]; + $adapter->insert($this->resourceConnection->getTableName('directory_country_region'), $bind); + $regionId = $adapter->lastInsertId($this->resourceConnection->getTableName('directory_country_region')); + $bind = ['locale' => 'en_US', 'region_id' => $regionId, 'name' => $row[2]]; + $adapter->insert($this->resourceConnection->getTableName('directory_country_region_name'), $bind); + } + /** + * Upgrade core_config_data general/region/state_required field. + */ + $countries = $this->data->getCountryCollection()->getCountriesWithRequiredStates(); + $adapter->update( + $this->resourceConnection->getTableName('core_config_data'), + [ + 'value' => implode(',', array_keys($countries)) + ], + [ + 'scope="default"', + 'scope_id=0', + 'path=?' => \Magento\Directory\Helper\Data::XML_PATH_STATES_REQUIRED + ] + ); + } +} diff --git a/app/code/Magento/Directory/Setup/Patch/Data/AddDataForCroatia.php b/app/code/Magento/Directory/Setup/Patch/Data/AddDataForCroatia.php new file mode 100644 index 0000000000000..000d803446713 --- /dev/null +++ b/app/code/Magento/Directory/Setup/Patch/Data/AddDataForCroatia.php @@ -0,0 +1,115 @@ +moduleDataSetup = $moduleDataSetup; + $this->dataInstallerFactory = $dataInstallerFactory; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + /** @var DataInstaller $dataInstaller */ + $dataInstaller = $this->dataInstallerFactory->create(); + $dataInstaller->addCountryRegions( + $this->moduleDataSetup->getConnection(), + $this->getDataForCroatia() + ); + } + + /** + * Croatian states data. + * + * @return array + */ + private function getDataForCroatia() + { + return [ + ['HR', 'HR-01', 'Zagrebačka županija'], + ['HR', 'HR-02', 'Krapinsko-zagorska županija'], + ['HR', 'HR-03', 'Sisačko-moslavačka županija'], + ['HR', 'HR-04', 'Karlovačka županija'], + ['HR', 'HR-05', 'Varaždinska županija'], + ['HR', 'HR-06', 'Koprivničko-križevačka županija'], + ['HR', 'HR-07', 'Bjelovarsko-bilogorska županija'], + ['HR', 'HR-08', 'Primorsko-goranska županija'], + ['HR', 'HR-09', 'Ličko-senjska županija'], + ['HR', 'HR-10', 'Virovitičko-podravska županija'], + ['HR', 'HR-11', 'Požeško-slavonska županija'], + ['HR', 'HR-12', 'Brodsko-posavska županija'], + ['HR', 'HR-13', 'Zadarska županija'], + ['HR', 'HR-14', 'Osječko-baranjska županija'], + ['HR', 'HR-15', 'Šibensko-kninska županija'], + ['HR', 'HR-16', 'Vukovarsko-srijemska županija'], + ['HR', 'HR-17', 'Splitsko-dalmatinska županija'], + ['HR', 'HR-18', 'Istarska županija'], + ['HR', 'HR-19', 'Dubrovačko-neretvanska županija'], + ['HR', 'HR-20', 'Međimurska županija'], + ['HR', 'HR-21', 'Grad Zagreb'] + ]; + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return [ + InitializeDirectoryData::class, + ]; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.1'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } +} diff --git a/app/code/Magento/Directory/Setup/Patch/Data/AddDataForIndia.php b/app/code/Magento/Directory/Setup/Patch/Data/AddDataForIndia.php new file mode 100644 index 0000000000000..0e4532c636fc1 --- /dev/null +++ b/app/code/Magento/Directory/Setup/Patch/Data/AddDataForIndia.php @@ -0,0 +1,130 @@ +moduleDataSetup = $moduleDataSetup; + $this->dataInstallerFactory = $dataInstallerFactory; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + /** @var DataInstaller $dataInstaller */ + $dataInstaller = $this->dataInstallerFactory->create(); + $dataInstaller->addCountryRegions( + $this->moduleDataSetup->getConnection(), + $this->getDataForIndia() + ); + } + + /** + * Indian states data. + * + * @return array + */ + private function getDataForIndia() + { + return [ + ['IN', 'AN', 'Andaman and Nicobar Islands'], + ['IN', 'AP', 'Andhra Pradesh'], + ['IN', 'AR', 'Arunachal Pradesh'], + ['IN', 'AS', 'Assam'], + ['IN', 'BR', 'Bihar'], + ['IN', 'CH', 'Chandigarh'], + ['IN', 'CT', 'Chhattisgarh'], + ['IN', 'DN', 'Dadra and Nagar Haveli'], + ['IN', 'DD', 'Daman and Diu'], + ['IN', 'DL', 'Delhi'], + ['IN', 'GA', 'Goa'], + ['IN', 'GJ', 'Gujarat'], + ['IN', 'HR', 'Haryana'], + ['IN', 'HP', 'Himachal Pradesh'], + ['IN', 'JK', 'Jammu and Kashmir'], + ['IN', 'JH', 'Jharkhand'], + ['IN', 'KA', 'Karnataka'], + ['IN', 'KL', 'Kerala'], + ['IN', 'LD', 'Lakshadweep'], + ['IN', 'MP', 'Madhya Pradesh'], + ['IN', 'MH', 'Maharashtra'], + ['IN', 'MN', 'Manipur'], + ['IN', 'ML', 'Meghalaya'], + ['IN', 'MZ', 'Mizoram'], + ['IN', 'NL', 'Nagaland'], + ['IN', 'OR', 'Odisha'], + ['IN', 'PY', 'Puducherry'], + ['IN', 'PB', 'Punjab'], + ['IN', 'RJ', 'Rajasthan'], + ['IN', 'SK', 'Sikkim'], + ['IN', 'TN', 'Tamil Nadu'], + ['IN', 'TG', 'Telangana'], + ['IN', 'TR', 'Tripura'], + ['IN', 'UP', 'Uttar Pradesh'], + ['IN', 'UT', 'Uttarakhand'], + ['IN', 'WB', 'West Bengal'] + ]; + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return [ + InitializeDirectoryData::class, + ]; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.2'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } +} diff --git a/app/code/Magento/Directory/Setup/InstallData.php b/app/code/Magento/Directory/Setup/Patch/Data/InitializeDirectoryData.php similarity index 92% rename from app/code/Magento/Directory/Setup/InstallData.php rename to app/code/Magento/Directory/Setup/Patch/Data/InitializeDirectoryData.php index 33c3ae4558e16..3226a693a29a7 100644 --- a/app/code/Magento/Directory/Setup/InstallData.php +++ b/app/code/Magento/Directory/Setup/Patch/Data/InitializeDirectoryData.php @@ -4,40 +4,47 @@ * See COPYING.txt for license details. */ -namespace Magento\Directory\Setup; +namespace Magento\Directory\Setup\Patch\Data; use Magento\Directory\Helper\Data; -use Magento\Framework\Setup\InstallDataInterface; -use Magento\Framework\Setup\ModuleContextInterface; use Magento\Framework\Setup\ModuleDataSetupInterface; +use Magento\Setup\Model\Patch\DataPatchInterface; +use Magento\Setup\Model\Patch\PatchVersionInterface; /** - * @codeCoverageIgnore + * Class InitializeDirectoryData + * @package Magento\Directory\Setup\Patch */ -class InstallData implements InstallDataInterface +class InitializeDirectoryData implements DataPatchInterface, PatchVersionInterface { /** - * Directory data - * - * @var Data + * @var ModuleDataSetupInterface */ - private $directoryData; + private $moduleDataSetup; /** - * Init - * - * @param Data $directoryData + * @var \Magento\Directory\Helper\DataFactory */ - public function __construct(Data $directoryData) - { - $this->directoryData = $directoryData; + private $directoryDataFactory; + + /** + * InitializeDirectoryData constructor. + * @param ModuleDataSetupInterface $moduleDataSetup + * @param \Magento\Directory\Helper\DataFactory $directoryDataFactory + */ + public function __construct( + ModuleDataSetupInterface $moduleDataSetup, + \Magento\Directory\Helper\DataFactory $directoryDataFactory + ) { + $this->moduleDataSetup = $moduleDataSetup; + $this->directoryDataFactory = $directoryDataFactory; } /** * {@inheritdoc} * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ - public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context) + public function apply() { /** * Fill table directory/country @@ -291,8 +298,11 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ]; $columns = ['country_id', 'iso2_code', 'iso3_code']; - $setup->getConnection()->insertArray($setup->getTable('directory_country'), $columns, $data); - + $this->moduleDataSetup->getConnection()->insertArray( + $this->moduleDataSetup->getTable('directory_country'), + $columns, + $data + ); /** * Fill table directory/country_region * Fill table directory/country_region_name for en_US locale @@ -810,16 +820,21 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ['BR', 'TO', 'Tocantins'], ['BR', 'DF', 'Distrito Federal'], ]; - foreach ($data as $row) { $bind = ['country_id' => $row[0], 'code' => $row[1], 'default_name' => $row[2]]; - $setup->getConnection()->insert($setup->getTable('directory_country_region'), $bind); - $regionId = $setup->getConnection()->lastInsertId($setup->getTable('directory_country_region')); - + $this->moduleDataSetup->getConnection()->insert( + $this->moduleDataSetup->getTable('directory_country_region'), + $bind + ); + $regionId = $this->moduleDataSetup->getConnection()->lastInsertId( + $this->moduleDataSetup->getTable('directory_country_region') + ); $bind = ['locale' => 'en_US', 'region_id' => $regionId, 'name' => $row[2]]; - $setup->getConnection()->insert($setup->getTable('directory_country_region_name'), $bind); + $this->moduleDataSetup->getConnection()->insert( + $this->moduleDataSetup->getTable('directory_country_region_name'), + $bind + ); } - /** * Fill table directory/currency_rate */ @@ -829,12 +844,14 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ['USD', 'EUR', 0.706700000000], ['USD', 'USD', 1], ]; - $columns = ['currency_from', 'currency_to', 'rate']; - $setup->getConnection()->insertArray($setup->getTable('directory_currency_rate'), $columns, $data); - - $setup->getConnection()->insert( - $setup->getTable('core_config_data'), + $this->moduleDataSetup->getConnection()->insertArray( + $this->moduleDataSetup->getTable('directory_currency_rate'), + $columns, + $data + ); + $this->moduleDataSetup->getConnection()->insert( + $this->moduleDataSetup->getTable('core_config_data'), [ 'scope' => 'default', 'scope_id' => 0, @@ -842,10 +859,11 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface 'value' => 1 ] ); - - $countries = $this->directoryData->getCountryCollection()->getCountriesWithRequiredStates(); - $setup->getConnection()->insert( - $setup->getTable('core_config_data'), + /** @var \Magento\Directory\Helper\Data $helper */ + $helper = $this->directoryDataFactory->create(); + $countries = $helper->getCountryCollection()->getCountriesWithRequiredStates(); + $this->moduleDataSetup->getConnection()->insert( + $this->moduleDataSetup->getTable('core_config_data'), [ 'scope' => 'default', 'scope_id' => 0, @@ -854,4 +872,28 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ] ); } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return []; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.0'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } } diff --git a/app/code/Magento/Directory/Setup/UpgradeData.php b/app/code/Magento/Directory/Setup/UpgradeData.php deleted file mode 100644 index 4ee9ea33673d7..0000000000000 --- a/app/code/Magento/Directory/Setup/UpgradeData.php +++ /dev/null @@ -1,166 +0,0 @@ -directoryData = $directoryData; - } - - /** - * Upgrades data for Directry module. - * - * @param ModuleDataSetupInterface $setup - * @param ModuleContextInterface $context - * @return void - */ - public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context) - { - if (version_compare($context->getVersion(), '2.0.1', '<')) { - $this->addCountryRegions($setup, $this->getDataForCroatia()); - } - if (version_compare($context->getVersion(), '2.0.2', '<')) { - $this->addCountryRegions($setup, $this->getDataForIndia()); - } - } - - /** - * Croatian states data. - * - * @return array - */ - private function getDataForCroatia() - { - return [ - ['HR', 'HR-01', 'Zagrebačka županija'], - ['HR', 'HR-02', 'Krapinsko-zagorska županija'], - ['HR', 'HR-03', 'Sisačko-moslavačka županija'], - ['HR', 'HR-04', 'Karlovačka županija'], - ['HR', 'HR-05', 'Varaždinska županija'], - ['HR', 'HR-06', 'Koprivničko-križevačka županija'], - ['HR', 'HR-07', 'Bjelovarsko-bilogorska županija'], - ['HR', 'HR-08', 'Primorsko-goranska županija'], - ['HR', 'HR-09', 'Ličko-senjska županija'], - ['HR', 'HR-10', 'Virovitičko-podravska županija'], - ['HR', 'HR-11', 'Požeško-slavonska županija'], - ['HR', 'HR-12', 'Brodsko-posavska županija'], - ['HR', 'HR-13', 'Zadarska županija'], - ['HR', 'HR-14', 'Osječko-baranjska županija'], - ['HR', 'HR-15', 'Šibensko-kninska županija'], - ['HR', 'HR-16', 'Vukovarsko-srijemska županija'], - ['HR', 'HR-17', 'Splitsko-dalmatinska županija'], - ['HR', 'HR-18', 'Istarska županija'], - ['HR', 'HR-19', 'Dubrovačko-neretvanska županija'], - ['HR', 'HR-20', 'Međimurska županija'], - ['HR', 'HR-21', 'Grad Zagreb'] - ]; - } - - /** - * Indian states data. - * - * @return array - */ - private function getDataForIndia() - { - return [ - ['IN', 'AN', 'Andaman and Nicobar Islands'], - ['IN', 'AP', 'Andhra Pradesh'], - ['IN', 'AR', 'Arunachal Pradesh'], - ['IN', 'AS', 'Assam'], - ['IN', 'BR', 'Bihar'], - ['IN', 'CH', 'Chandigarh'], - ['IN', 'CT', 'Chhattisgarh'], - ['IN', 'DN', 'Dadra and Nagar Haveli'], - ['IN', 'DD', 'Daman and Diu'], - ['IN', 'DL', 'Delhi'], - ['IN', 'GA', 'Goa'], - ['IN', 'GJ', 'Gujarat'], - ['IN', 'HR', 'Haryana'], - ['IN', 'HP', 'Himachal Pradesh'], - ['IN', 'JK', 'Jammu and Kashmir'], - ['IN', 'JH', 'Jharkhand'], - ['IN', 'KA', 'Karnataka'], - ['IN', 'KL', 'Kerala'], - ['IN', 'LD', 'Lakshadweep'], - ['IN', 'MP', 'Madhya Pradesh'], - ['IN', 'MH', 'Maharashtra'], - ['IN', 'MN', 'Manipur'], - ['IN', 'ML', 'Meghalaya'], - ['IN', 'MZ', 'Mizoram'], - ['IN', 'NL', 'Nagaland'], - ['IN', 'OR', 'Odisha'], - ['IN', 'PY', 'Puducherry'], - ['IN', 'PB', 'Punjab'], - ['IN', 'RJ', 'Rajasthan'], - ['IN', 'SK', 'Sikkim'], - ['IN', 'TN', 'Tamil Nadu'], - ['IN', 'TG', 'Telangana'], - ['IN', 'TR', 'Tripura'], - ['IN', 'UP', 'Uttar Pradesh'], - ['IN', 'UT', 'Uttarakhand'], - ['IN', 'WB', 'West Bengal'] - ]; - } - - /** - * Add country regions data to appropriate tables. - * - * @param ModuleDataSetupInterface $setup - * @param array $data - * @return void - */ - private function addCountryRegions(ModuleDataSetupInterface $setup, array $data) - { - /** - * Fill table directory/country_region - * Fill table directory/country_region_name for en_US locale - */ - foreach ($data as $row) { - $bind = ['country_id' => $row[0], 'code' => $row[1], 'default_name' => $row[2]]; - $setup->getConnection()->insert($setup->getTable('directory_country_region'), $bind); - $regionId = $setup->getConnection()->lastInsertId($setup->getTable('directory_country_region')); - $bind = ['locale' => 'en_US', 'region_id' => $regionId, 'name' => $row[2]]; - $setup->getConnection()->insert($setup->getTable('directory_country_region_name'), $bind); - } - /** - * Upgrade core_config_data general/region/state_required field. - */ - $countries = $this->directoryData->getCountryCollection()->getCountriesWithRequiredStates(); - $setup->getConnection()->update( - $setup->getTable('core_config_data'), - [ - 'value' => implode(',', array_keys($countries)) - ], - [ - 'scope="default"', - 'scope_id=0', - 'path=?' => Data::XML_PATH_STATES_REQUIRED - ] - ); - } -} diff --git a/app/code/Magento/Directory/Test/Unit/Model/CountryInformationAcquirerTest.php b/app/code/Magento/Directory/Test/Unit/Model/CountryInformationAcquirerTest.php index 3f963cb2b82af..a3037d6481925 100644 --- a/app/code/Magento/Directory/Test/Unit/Model/CountryInformationAcquirerTest.php +++ b/app/code/Magento/Directory/Test/Unit/Model/CountryInformationAcquirerTest.php @@ -143,8 +143,8 @@ public function testGetCountryInfo() /** * test GetGetCountryInfoNotFound * - * @expectedException \Magento\Framework\Exception\NoSuchEntityException - * @expectedExceptionMessage Requested country is not available. + * @expectedException \Magento\Framework\Exception\NoSuchEntityException + * @expectedExceptionMessage The country isn't available. */ public function testGetCountryInfoNotFound() { diff --git a/app/code/Magento/Directory/etc/module.xml b/app/code/Magento/Directory/etc/module.xml index a3735ca6ddde1..3a750db5e7cfd 100644 --- a/app/code/Magento/Directory/etc/module.xml +++ b/app/code/Magento/Directory/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/Downloadable/Model/LinkRepository.php b/app/code/Magento/Downloadable/Model/LinkRepository.php index b84a8284c9083..0898f1924e538 100644 --- a/app/code/Magento/Downloadable/Model/LinkRepository.php +++ b/app/code/Magento/Downloadable/Model/LinkRepository.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Downloadable\Model; use Magento\Catalog\Api\Data\ProductInterface; @@ -176,20 +177,22 @@ public function save($sku, LinkInterface $link, $isGlobalScopeContent = true) return $this->updateLink($product, $link, $isGlobalScopeContent); } else { if ($product->getTypeId() !== \Magento\Downloadable\Model\Product\Type::TYPE_DOWNLOADABLE) { - throw new InputException(__('Provided product must be type \'downloadable\'.')); + throw new InputException( + __('The product needs to be the downloadable type. Verify the product and try again.') + ); } $validateLinkContent = !($link->getLinkType() === 'file' && $link->getLinkFile()); $validateSampleContent = !($link->getSampleType() === 'file' && $link->getSampleFile()); if (!$this->contentValidator->isValid($link, $validateLinkContent, $validateSampleContent)) { - throw new InputException(__('Provided link information is invalid.')); + throw new InputException(__('The link information is invalid. Verify the link and try again.')); } if (!in_array($link->getLinkType(), ['url', 'file'], true)) { - throw new InputException(__('Invalid link type.')); + throw new InputException(__('The link type is invalid. Verify and try again.')); } $title = $link->getTitle(); if (empty($title)) { - throw new InputException(__('Link title cannot be empty.')); + throw new InputException(__('The link title is empty. Enter the link title and try again.')); } return $this->saveLink($product, $link, $isGlobalScopeContent); } @@ -283,18 +286,22 @@ protected function updateLink( /** @var $existingLink \Magento\Downloadable\Model\Link */ $existingLink = $this->linkFactory->create()->load($link->getId()); if (!$existingLink->getId()) { - throw new NoSuchEntityException(__('There is no downloadable link with provided ID.')); + throw new NoSuchEntityException( + __('No downloadable link with the provided ID was found. Verify the ID and try again.') + ); } $linkFieldValue = $product->getData( $this->getMetadataPool()->getMetadata(ProductInterface::class)->getLinkField() ); if ($existingLink->getProductId() != $linkFieldValue) { - throw new InputException(__('Provided downloadable link is not related to given product.')); + throw new InputException( + __("The downloadable link isn't related to the product. Verify the link and try again.") + ); } $validateLinkContent = !($link->getLinkFileContent() === null); $validateSampleContent = !($link->getSampleFileContent() === null); if (!$this->contentValidator->isValid($link, $validateLinkContent, $validateSampleContent)) { - throw new InputException(__('Provided link information is invalid.')); + throw new InputException(__('The link information is invalid. Verify the link and try again.')); } if ($isGlobalScopeContent) { $product->setStoreId(0); @@ -302,7 +309,7 @@ protected function updateLink( $title = $link->getTitle(); if (empty($title)) { if ($isGlobalScopeContent) { - throw new InputException(__('Link title cannot be empty.')); + throw new InputException(__('The link title is empty. Enter the link title and try again.')); } } @@ -325,12 +332,14 @@ public function delete($id) /** @var $link \Magento\Downloadable\Model\Link */ $link = $this->linkFactory->create()->load($id); if (!$link->getId()) { - throw new NoSuchEntityException(__('There is no downloadable link with provided ID.')); + throw new NoSuchEntityException( + __('No downloadable link with the provided ID was found. Verify the ID and try again.') + ); } try { $link->delete(); } catch (\Exception $exception) { - throw new StateException(__('Cannot delete link with id %1', $link->getId()), $exception); + throw new StateException(__('The link with "%1" ID can\'t be deleted.', $link->getId()), $exception); } return true; } diff --git a/app/code/Magento/Downloadable/Model/SampleRepository.php b/app/code/Magento/Downloadable/Model/SampleRepository.php index 5b9e8e784b9f3..0c7d2b96f1b53 100644 --- a/app/code/Magento/Downloadable/Model/SampleRepository.php +++ b/app/code/Magento/Downloadable/Model/SampleRepository.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Downloadable\Model; use Magento\Catalog\Api\Data\ProductInterface; @@ -183,20 +184,24 @@ public function save( return $this->updateSample($product, $sample, $isGlobalScopeContent); } else { if ($product->getTypeId() !== Type::TYPE_DOWNLOADABLE) { - throw new InputException(__('Provided product must be type \'downloadable\'.')); + throw new InputException( + __('The product needs to be the downloadable type. Verify the product and try again.') + ); } $validateSampleContent = !($sample->getSampleType() === 'file' && $sample->getSampleFile()); if (!$this->contentValidator->isValid($sample, $validateSampleContent)) { - throw new InputException(__('Provided sample information is invalid.')); + throw new InputException( + __('The sample information is invalid. Verify the information and try again.') + ); } if (!in_array($sample->getSampleType(), ['url', 'file'], true)) { - throw new InputException(__('Invalid sample type.')); + throw new InputException(__('The sample type is invalid. Verify the sample type and try again.')); } $title = $sample->getTitle(); if (empty($title)) { - throw new InputException(__('Sample title cannot be empty.')); + throw new InputException(__('The sample title is empty. Enter the title and try again.')); } return $this->saveSample($product, $sample, $isGlobalScopeContent); @@ -271,18 +276,22 @@ protected function updateSample( $existingSample = $this->sampleFactory->create()->load($sampleId); if (!$existingSample->getId()) { - throw new NoSuchEntityException(__('There is no downloadable sample with provided ID.')); + throw new NoSuchEntityException( + __('No downloadable sample with the provided ID was found. Verify the ID and try again.') + ); } $linkFieldValue = $product->getData( $this->getMetadataPool()->getMetadata(ProductInterface::class)->getLinkField() ); if ($existingSample->getProductId() != $linkFieldValue) { - throw new InputException(__('Provided downloadable sample is not related to given product.')); + throw new InputException( + __("The downloadable sample isn't related to the product. Verify the link and try again.") + ); } $validateFileContent = $sample->getSampleFileContent() === null ? false : true; if (!$this->contentValidator->isValid($sample, $validateFileContent)) { - throw new InputException(__('Provided sample information is invalid.')); + throw new InputException(__('The sample information is invalid. Verify the information and try again.')); } if ($isGlobalScopeContent) { $product->setStoreId(0); @@ -291,7 +300,7 @@ protected function updateSample( $title = $sample->getTitle(); if (empty($title)) { if ($isGlobalScopeContent) { - throw new InputException(__('Sample title cannot be empty.')); + throw new InputException(__('The sample title is empty. Enter the title and try again.')); } // use title from GLOBAL scope $existingSample->setTitle(null); @@ -314,12 +323,14 @@ public function delete($id) /** @var $sample \Magento\Downloadable\Model\Sample */ $sample = $this->sampleFactory->create()->load($id); if (!$sample->getId()) { - throw new NoSuchEntityException(__('There is no downloadable sample with provided ID.')); + throw new NoSuchEntityException( + __('No downloadable sample with the provided ID was found. Verify the ID and try again.') + ); } try { $sample->delete(); } catch (\Exception $exception) { - throw new StateException(__('Cannot delete sample with id %1', $sample->getId()), $exception); + throw new StateException(__('The sample with "%1" ID can\'t be deleted.', $sample->getId()), $exception); } return true; } diff --git a/app/code/Magento/Downloadable/Setup/InstallData.php b/app/code/Magento/Downloadable/Setup/Patch/Data/InstallDownloadableAttributes.php similarity index 81% rename from app/code/Magento/Downloadable/Setup/InstallData.php rename to app/code/Magento/Downloadable/Setup/Patch/Data/InstallDownloadableAttributes.php index e015f3a23c191..11dae04d6a9c1 100644 --- a/app/code/Magento/Downloadable/Setup/InstallData.php +++ b/app/code/Magento/Downloadable/Setup/Patch/Data/InstallDownloadableAttributes.php @@ -4,33 +4,41 @@ * See COPYING.txt for license details. */ -namespace Magento\Downloadable\Setup; +namespace Magento\Downloadable\Setup\Patch\Data; use Magento\Eav\Setup\EavSetup; use Magento\Eav\Setup\EavSetupFactory; -use Magento\Framework\Setup\InstallDataInterface; -use Magento\Framework\Setup\ModuleContextInterface; +use Magento\Framework\App\ResourceConnection; use Magento\Framework\Setup\ModuleDataSetupInterface; +use Magento\Setup\Model\Patch\DataPatchInterface; +use Magento\Setup\Model\Patch\PatchVersionInterface; /** - * @codeCoverageIgnore + * Class InstallDownloadableAttributes + * @package Magento\Downloadable\Setup\Patch */ -class InstallData implements InstallDataInterface +class InstallDownloadableAttributes implements DataPatchInterface, PatchVersionInterface { /** - * EAV setup factory - * + * @var \Magento\Framework\Setup\ModuleDataSetupInterface + */ + private $moduleDataSetup; + + /** * @var EavSetupFactory */ private $eavSetupFactory; /** - * Init - * + * InstallDownloadableAttributes constructor. + * @param ModuleDataSetupInterface $moduleDataSetup * @param EavSetupFactory $eavSetupFactory */ - public function __construct(EavSetupFactory $eavSetupFactory) - { + public function __construct( + ModuleDataSetupInterface $moduleDataSetup, + EavSetupFactory $eavSetupFactory + ) { + $this->moduleDataSetup = $moduleDataSetup; $this->eavSetupFactory = $eavSetupFactory; } @@ -38,10 +46,10 @@ public function __construct(EavSetupFactory $eavSetupFactory) * {@inheritdoc} * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ - public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context) + public function apply() { /** @var EavSetup $eavSetup */ - $eavSetup = $this->eavSetupFactory->create(['setup' => $setup]); + $eavSetup = $this->eavSetupFactory->create(['setup' => $this->moduleDataSetup]); /** * Add attributes to the eav/attribute table */ @@ -95,7 +103,6 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface 'apply_to' => 'downloadable' ] ); - $eavSetup->addAttribute( \Magento\Catalog\Model\Product::ENTITY, 'links_title', @@ -120,7 +127,6 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface 'apply_to' => 'downloadable' ] ); - $eavSetup->addAttribute( \Magento\Catalog\Model\Product::ENTITY, 'links_exist', @@ -146,7 +152,6 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface 'used_in_product_listing' => 1 ] ); - $fieldList = [ 'price', 'special_price', @@ -157,7 +162,6 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface 'tier_price', 'weight', ]; - // make these attributes applicable to downloadable products foreach ($fieldList as $field) { $applyTo = explode( @@ -175,4 +179,28 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface } } } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return []; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.0'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } } diff --git a/app/code/Magento/Downloadable/Test/Unit/Helper/DownloadTest.php b/app/code/Magento/Downloadable/Test/Unit/Helper/DownloadTest.php index 3142900613296..226660b865240 100644 --- a/app/code/Magento/Downloadable/Test/Unit/Helper/DownloadTest.php +++ b/app/code/Magento/Downloadable/Test/Unit/Helper/DownloadTest.php @@ -102,7 +102,7 @@ public function testGetFileSizeNoResource() */ public function testGetFileSizeInvalidLinkType() { - $this->_helper->setResource(self::FILE_PATH, 'invalid link type'); + $this->_helper->setResource(self::FILE_PATH, 'The link type is invalid. Verify and try again.'); $this->_helper->getFileSize(); } diff --git a/app/code/Magento/Downloadable/Test/Unit/Model/LinkRepositoryTest.php b/app/code/Magento/Downloadable/Test/Unit/Model/LinkRepositoryTest.php index d835f25523353..f771233fad7bb 100644 --- a/app/code/Magento/Downloadable/Test/Unit/Model/LinkRepositoryTest.php +++ b/app/code/Magento/Downloadable/Test/Unit/Model/LinkRepositoryTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Downloadable\Test\Unit\Model; use Magento\Downloadable\Model\LinkRepository; @@ -259,7 +260,7 @@ public function testCreate() /** * @expectedException \Magento\Framework\Exception\InputException - * @expectedExceptionMessage Link title cannot be empty. + * @expectedExceptionMessage The link title is empty. Enter the link title and try again. */ public function testCreateThrowsExceptionIfTitleIsEmpty() { @@ -421,7 +422,7 @@ public function testUpdateWithExistingFile() /** * @expectedException \Magento\Framework\Exception\InputException - * @expectedExceptionMessage Link title cannot be empty. + * @expectedExceptionMessage The link title is empty. Enter the link title and try again. */ public function testUpdateThrowsExceptionIfTitleIsEmptyAndScopeIsGlobal() { @@ -469,7 +470,7 @@ public function testDelete() /** * @expectedException \Magento\Framework\Exception\NoSuchEntityException - * @expectedExceptionMessage There is no downloadable link with provided ID. + * @expectedExceptionMessage No downloadable link with the provided ID was found. Verify the ID and try again. */ public function testDeleteThrowsExceptionIfLinkIdIsNotValid() { diff --git a/app/code/Magento/Downloadable/Test/Unit/Model/SampleRepositoryTest.php b/app/code/Magento/Downloadable/Test/Unit/Model/SampleRepositoryTest.php index 79a314cee5423..8e13bd83b039e 100644 --- a/app/code/Magento/Downloadable/Test/Unit/Model/SampleRepositoryTest.php +++ b/app/code/Magento/Downloadable/Test/Unit/Model/SampleRepositoryTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Downloadable\Test\Unit\Model; use Magento\Downloadable\Model\SampleRepository; @@ -206,7 +207,7 @@ public function testCreate() /** * @expectedException \Magento\Framework\Exception\InputException - * @expectedExceptionMessage Sample title cannot be empty. + * @expectedExceptionMessage The sample title is empty. Enter the title and try again. */ public function testCreateThrowsExceptionIfTitleIsEmpty() { @@ -341,7 +342,7 @@ public function testUpdateWithExistingFile() /** * @expectedException \Magento\Framework\Exception\InputException - * @expectedExceptionMessage Sample title cannot be empty. + * @expectedExceptionMessage The sample title is empty. Enter the title and try again. */ public function testUpdateThrowsExceptionIfTitleIsEmptyAndScopeIsGlobal() { @@ -388,7 +389,7 @@ public function testDelete() /** * @expectedException \Magento\Framework\Exception\NoSuchEntityException - * @expectedExceptionMessage There is no downloadable sample with provided ID. + * @expectedExceptionMessage No downloadable sample with the provided ID was found. Verify the ID and try again. */ public function testDeleteThrowsExceptionIfSampleIdIsNotValid() { diff --git a/app/code/Magento/Downloadable/etc/module.xml b/app/code/Magento/Downloadable/etc/module.xml index 4c4e165feb014..72aadff621eca 100644 --- a/app/code/Magento/Downloadable/etc/module.xml +++ b/app/code/Magento/Downloadable/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/DownloadableGraphQl/etc/module.xml b/app/code/Magento/DownloadableGraphQl/etc/module.xml index 0b89ef36c5373..3f97f6f0accb7 100644 --- a/app/code/Magento/DownloadableGraphQl/etc/module.xml +++ b/app/code/Magento/DownloadableGraphQl/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/DownloadableImportExport/etc/module.xml b/app/code/Magento/DownloadableImportExport/etc/module.xml index c59a8a2f6f14f..9cba501ba5da7 100644 --- a/app/code/Magento/DownloadableImportExport/etc/module.xml +++ b/app/code/Magento/DownloadableImportExport/etc/module.xml @@ -7,7 +7,7 @@ --> - + diff --git a/app/code/Magento/Eav/Model/Attribute/GroupRepository.php b/app/code/Magento/Eav/Model/Attribute/GroupRepository.php index 0714f8efac88c..07ca71d95eba5 100644 --- a/app/code/Magento/Eav/Model/Attribute/GroupRepository.php +++ b/app/code/Magento/Eav/Model/Attribute/GroupRepository.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Eav\Model\Attribute; use Magento\Framework\Api\SearchCriteria\CollectionProcessorInterface; @@ -99,7 +100,7 @@ public function save(\Magento\Eav\Api\Data\AttributeGroupInterface $group) } if ($existingGroup->getAttributeSetId() != $group->getAttributeSetId()) { throw new StateException( - __('Attribute group does not belong to provided attribute set') + __("The attribute group doesn't belong to the provided attribute set.") ); } } @@ -107,7 +108,7 @@ public function save(\Magento\Eav\Api\Data\AttributeGroupInterface $group) try { $this->groupResource->save($group); } catch (\Exception $e) { - throw new StateException(__('Cannot save attributeGroup')); + throw new StateException(__("The attributeGroup can't be saved.")); } return $group; } @@ -140,7 +141,9 @@ public function get($groupId) $group = $this->groupFactory->create(); $this->groupResource->load($group, $groupId); if (!$group->getId()) { - throw new NoSuchEntityException(__('Group with id "%1" does not exist.', $groupId)); + throw new NoSuchEntityException( + __('The group with the "%1" ID doesn\'t exist. Verify the ID and try again.', $groupId) + ); } return $group; } @@ -155,7 +158,7 @@ public function delete(\Magento\Eav\Api\Data\AttributeGroupInterface $group) } catch (\Exception $e) { throw new StateException( __( - 'Cannot delete attributeGroup with id %1', + 'The attribute group with id "%1" can\'t be deleted.', $group->getId() ), $e diff --git a/app/code/Magento/Eav/Model/AttributeManagement.php b/app/code/Magento/Eav/Model/AttributeManagement.php index b76116c6f964c..31f962db3ee53 100644 --- a/app/code/Magento/Eav/Model/AttributeManagement.php +++ b/app/code/Magento/Eav/Model/AttributeManagement.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Eav\Model; use Magento\Framework\App\ObjectManager; @@ -98,19 +99,24 @@ public function assign($entityTypeCode, $attributeSetId, $attributeGroupId, $att try { $attributeSet = $this->setRepository->get($attributeSetId); } catch (NoSuchEntityException $ex) { - throw new NoSuchEntityException(__('AttributeSet with id "%1" does not exist.', $attributeSetId)); + throw new NoSuchEntityException( + __( + 'The AttributeSet with a "%1" ID doesn\'t exist. Verify the attributeSet and try again.', + $attributeSetId + ) + ); } $setEntityType = $this->entityTypeFactory->create()->getEntityType($attributeSet->getEntityTypeId()); if ($setEntityType->getEntityTypeCode() != $entityTypeCode) { - throw new InputException(__('Wrong attribute set id provided')); + throw new InputException(__('The attribute set ID is incorrect. Verify the ID and try again.')); } //Check if group exists. If not - expected exception $attributeGroup = $this->groupRepository->get($attributeGroupId); if ($attributeGroup->getAttributeSetId() != $attributeSetId) { - throw new InputException(__('Attribute group does not belong to attribute set')); + throw new InputException(__('The attribute group doesn\'t belong to the attribute set.')); } /** @var \Magento\Eav\Api\Data\AttributeInterface $attribute */ @@ -135,7 +141,9 @@ public function unassign($attributeSetId, $attributeCode) try { $attributeSet = $this->setRepository->get($attributeSetId); } catch (NoSuchEntityException $e) { - throw new NoSuchEntityException(__('Attribute set not found: %1', $attributeSetId)); + throw new NoSuchEntityException( + __('The "%1" attribute set wasn\'t found. Verify and try again.', $attributeSetId) + ); } $setEntityType = $this->entityTypeFactory->create()->getEntityType($attributeSet->getEntityTypeId()); @@ -148,11 +156,15 @@ public function unassign($attributeSetId, $attributeCode) if (!$attribute->getEntityAttributeId()) { throw new InputException( - __('Attribute "%1" not found in attribute set %2.', $attributeCode, $attributeSetId) + __( + 'The "%1" attribute wasn\'t found in the "%2" attribute set. Enter the attribute and try again.', + $attributeCode, + $attributeSetId + ) ); } if (!$attribute->getIsUserDefined()) { - throw new StateException(__('System attribute can not be deleted')); + throw new StateException(__("The system attribute can't be deleted.")); } $attribute->deleteEntity(); return true; diff --git a/app/code/Magento/Eav/Model/AttributeRepository.php b/app/code/Magento/Eav/Model/AttributeRepository.php index 3f20558d03d78..120c868a9d41b 100644 --- a/app/code/Magento/Eav/Model/AttributeRepository.php +++ b/app/code/Magento/Eav/Model/AttributeRepository.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Eav\Model; use Magento\Framework\Api\SearchCriteria\CollectionProcessor; @@ -87,7 +88,7 @@ public function save(\Magento\Eav\Api\Data\AttributeInterface $attribute) try { $this->eavResource->save($attribute); } catch (\Exception $e) { - throw new StateException(__('Cannot save attribute')); + throw new StateException(__("The attribute can't be saved.")); } return $attribute; } @@ -154,7 +155,10 @@ public function get($entityTypeCode, $attributeCode) $attribute = $this->eavConfig->getAttribute($entityTypeCode, $attributeCode); if (!$attribute || !$attribute->getAttributeId()) { throw new NoSuchEntityException( - __('Attribute with attributeCode "%1" does not exist.', $attributeCode) + __( + 'The attribute with a "%1" attributeCode doesn\'t exist. Verify the attribute and try again.', + $attributeCode + ) ); } return $attribute; @@ -168,7 +172,7 @@ public function delete(\Magento\Eav\Api\Data\AttributeInterface $attribute) try { $this->eavResource->delete($attribute); } catch (\Exception $e) { - throw new StateException(__('Cannot delete attribute.')); + throw new StateException(__("The attribute can't be deleted.")); } return true; } @@ -183,7 +187,9 @@ public function deleteById($attributeId) $this->eavResource->load($attribute, $attributeId); if (!$attribute->getAttributeId()) { - throw new NoSuchEntityException(__('Attribute with id "%1" does not exist.', $attributeId)); + throw new NoSuchEntityException( + __('The attribute with a "%1" ID doesn\'t exist. Verify the attribute and try again.', $attributeId) + ); } $this->delete($attribute); diff --git a/app/code/Magento/Eav/Model/AttributeSetRepository.php b/app/code/Magento/Eav/Model/AttributeSetRepository.php index d0b7ed3ccaa28..caab82da3910d 100644 --- a/app/code/Magento/Eav/Model/AttributeSetRepository.php +++ b/app/code/Magento/Eav/Model/AttributeSetRepository.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Eav\Model; use Magento\Eav\Api\AttributeSetRepositoryInterface; @@ -93,7 +94,12 @@ public function save(AttributeSetInterface $attributeSet) try { $this->attributeSetResource->save($attributeSet); } catch (\Exception $exception) { - throw new CouldNotSaveException(__('There was an error saving attribute set.')); + throw new CouldNotSaveException( + __( + 'The attribute set couldn\'t be saved due to an error. ' + . 'Verify your information and try again. If the error persists, please try again later.' + ) + ); } return $attributeSet; } @@ -159,9 +165,14 @@ public function delete(AttributeSetInterface $attributeSet) try { $this->attributeSetResource->delete($attributeSet); } catch (\Magento\Framework\Exception\StateException $exception) { - throw new CouldNotDeleteException(__('Default attribute set can not be deleted')); + throw new CouldNotDeleteException(__('The default attribute set can\'t be deleted.')); } catch (\Exception $exception) { - throw new CouldNotDeleteException(__('There was an error deleting attribute set.')); + throw new CouldNotDeleteException( + __( + 'The attribute set couldn\'t be deleted due to an error. ' + . 'Try again — if the error persists, please try again later.' + ) + ); } return true; } diff --git a/app/code/Magento/Eav/Model/Entity/AbstractEntity.php b/app/code/Magento/Eav/Model/Entity/AbstractEntity.php index ef80f12b26721..7159cedb61cee 100644 --- a/app/code/Magento/Eav/Model/Entity/AbstractEntity.php +++ b/app/code/Magento/Eav/Model/Entity/AbstractEntity.php @@ -365,7 +365,7 @@ public function unsetAttributes($attributes = null) } if (!is_array($attributes)) { - throw new LocalizedException(__('Unknown parameter')); + throw new LocalizedException(__('This parameter is unknown. Verify and try again.')); } foreach ($attributes as $attrCode) { diff --git a/app/code/Magento/Eav/Model/Entity/Attribute.php b/app/code/Magento/Eav/Model/Entity/Attribute.php index a2c2cdcb5ae55..3a2bfad06db25 100644 --- a/app/code/Magento/Eav/Model/Entity/Attribute.php +++ b/app/code/Magento/Eav/Model/Entity/Attribute.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Eav\Model\Entity; use Magento\Framework\Api\AttributeValueFactory; @@ -252,7 +253,10 @@ public function beforeSave() ) ) { throw new LocalizedException( - __('An attribute code must not be more than %1 characters.', self::ATTRIBUTE_CODE_MAX_LENGTH) + __( + 'The attribute code needs to be %1 characters or fewer. Re-enter the code and try again.', + self::ATTRIBUTE_CODE_MAX_LENGTH + ) ); } @@ -263,7 +267,9 @@ public function beforeSave() $numberFormatter = new \NumberFormatter($this->_localeResolver->getLocale(), \NumberFormatter::DECIMAL); $defaultValue = $numberFormatter->parse($defaultValue); if ($defaultValue === false) { - throw new LocalizedException(__('Invalid default decimal value')); + throw new LocalizedException( + __('The default decimal value is invalid. Verify the value and try again.') + ); } $this->setDefaultValue($defaultValue); } @@ -286,7 +292,7 @@ public function beforeSave() $defaultValue = $this->dateTimeFormatter->formatObject(new \DateTime($defaultValue), $format); $this->setDefaultValue($defaultValue); } catch (\Exception $e) { - throw new LocalizedException(__('Invalid default date')); + throw new LocalizedException(__('The default date is invalid. Verify the date and try again.')); } } } diff --git a/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php b/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php index 19877a51c4869..4d3c79db2dfcd 100644 --- a/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php +++ b/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php @@ -243,7 +243,7 @@ public function loadByCode($entityType, $code) $entityTypeId = $entityType->getId(); } if (empty($entityTypeId)) { - throw new LocalizedException(__('Invalid entity supplied')); + throw new LocalizedException(__('The entity supplied is invalid. Verify the entity and try again.')); } $this->_getResource()->loadByCode($this, $entityTypeId, $code); $this->_afterLoad(); @@ -550,7 +550,12 @@ public function getBackend() } $backend = $this->_universalFactory->create($this->getBackendModel()); if (!$backend) { - throw new LocalizedException(__('Invalid backend model specified: %1', $this->getBackendModel())); + throw new LocalizedException( + __( + 'The "%1" backend model is invalid. Verify the backend model and try again.', + $this->getBackendModel() + ) + ); } $this->_backend = $backend->setAttribute($this); } diff --git a/app/code/Magento/Eav/Model/Entity/Attribute/Backend/AbstractBackend.php b/app/code/Magento/Eav/Model/Entity/Attribute/Backend/AbstractBackend.php index 38e7b883f4ea5..53c32e1cbfba4 100644 --- a/app/code/Magento/Eav/Model/Entity/Attribute/Backend/AbstractBackend.php +++ b/app/code/Magento/Eav/Model/Entity/Attribute/Backend/AbstractBackend.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Eav\Model\Entity\Attribute\Backend; use Magento\Framework\Exception\LocalizedException; @@ -238,7 +239,9 @@ public function validate($object) && $attribute->isValueEmpty($attribute->getDefaultValue()) ) { $label = $attribute->getFrontend()->getLabel(); - throw new LocalizedException(__('The value of attribute "%1" must be set', $label)); + throw new LocalizedException( + __('The "%1" attribute value is empty. Set the attribute and try again.', $label) + ); } if ($attribute->getIsUnique() @@ -251,7 +254,9 @@ public function validate($object) if ($attribute->getIsUnique()) { if (!$attribute->getEntity()->checkAttributeUniqueValue($attribute, $object)) { $label = $attribute->getFrontend()->getLabel(); - throw new LocalizedException(__('The value of attribute "%1" must be unique', $label)); + throw new LocalizedException( + __('The value of the "%1" attribute isn\'t unique. Set a unique value and try again.', $label) + ); } } diff --git a/app/code/Magento/Eav/Model/Entity/Attribute/OptionManagement.php b/app/code/Magento/Eav/Model/Entity/Attribute/OptionManagement.php index b0508fd8cc626..938abdf30057b 100644 --- a/app/code/Magento/Eav/Model/Entity/Attribute/OptionManagement.php +++ b/app/code/Magento/Eav/Model/Entity/Attribute/OptionManagement.php @@ -41,12 +41,12 @@ public function __construct( public function add($entityType, $attributeCode, $option) { if (empty($attributeCode)) { - throw new InputException(__('Empty attribute code')); + throw new InputException(__('The attribute code is empty. Enter the code and try again.')); } $attribute = $this->attributeRepository->get($entityType, $attributeCode); if (!$attribute->usesSource()) { - throw new StateException(__('Attribute %1 doesn\'t work with options', $attributeCode)); + throw new StateException(__('The "%1" attribute doesn\'t work with options.', $attributeCode)); } $optionId = $this->getOptionId($option); @@ -68,7 +68,7 @@ public function add($entityType, $attributeCode, $option) try { $this->resourceModel->save($attribute); } catch (\Exception $e) { - throw new StateException(__('Cannot save attribute %1', $attributeCode)); + throw new StateException(__('The "%1" attribute can\'t be saved.', $attributeCode)); } return true; @@ -80,12 +80,12 @@ public function add($entityType, $attributeCode, $option) public function delete($entityType, $attributeCode, $optionId) { if (empty($attributeCode)) { - throw new InputException(__('Empty attribute code')); + throw new InputException(__('The attribute code is empty. Enter the code and try again.')); } $attribute = $this->attributeRepository->get($entityType, $attributeCode); if (!$attribute->usesSource()) { - throw new StateException(__('Attribute %1 doesn\'t have any option', $attributeCode)); + throw new StateException(__('The "%1" attribute has no option.', $attributeCode)); } $this->validateOption($attribute, $optionId); @@ -99,7 +99,7 @@ public function delete($entityType, $attributeCode, $optionId) try { $this->resourceModel->save($attribute); } catch (\Exception $e) { - throw new StateException(__('Cannot save attribute %1', $attributeCode)); + throw new StateException(__('The "%1" attribute can\'t be saved.', $attributeCode)); } return true; @@ -111,14 +111,14 @@ public function delete($entityType, $attributeCode, $optionId) public function getItems($entityType, $attributeCode) { if (empty($attributeCode)) { - throw new InputException(__('Empty attribute code')); + throw new InputException(__('The attribute code is empty. Enter the code and try again.')); } $attribute = $this->attributeRepository->get($entityType, $attributeCode); try { $options = $attribute->getOptions(); } catch (\Exception $e) { - throw new StateException(__('Cannot load options for attribute %1', $attributeCode)); + throw new StateException(__('The options for "%1" attribute can\'t be loaded.', $attributeCode)); } return $options; @@ -134,7 +134,11 @@ protected function validateOption($attribute, $optionId) { if (!$attribute->getSource()->getOptionText($optionId)) { throw new NoSuchEntityException( - __('Attribute %1 does not contain option with Id %2', $attribute->getAttributeCode(), $optionId) + __( + 'The "%1" attribute doesn\'t include an option with "%2" ID.', + $attribute->getAttributeCode(), + $optionId + ) ); } } diff --git a/app/code/Magento/Eav/Model/Entity/Attribute/Set.php b/app/code/Magento/Eav/Model/Entity/Attribute/Set.php index 5434f05610467..da7d5fac089cb 100644 --- a/app/code/Magento/Eav/Model/Entity/Attribute/Set.php +++ b/app/code/Magento/Eav/Model/Entity/Attribute/Set.php @@ -220,7 +220,12 @@ public function organizeData($data) foreach ($data['not_attributes'] as $entityAttributeId) { $entityAttribute = $this->_resourceAttribute->getEntityAttribute($entityAttributeId); if (!$entityAttribute) { - throw new LocalizedException(__('Entity attribute with id "%1" not found', $entityAttributeId)); + throw new LocalizedException( + __( + 'The entity attribute with the "%1" ID isn\'t found. Reset the attribute and try again.', + $entityAttributeId + ) + ); } $modelAttribute = $this->_eavConfig->getAttribute( $this->getEntityTypeId(), @@ -282,11 +287,13 @@ public function validate() { $attributeSetName = $this->getAttributeSetName(); if ($attributeSetName == '') { - throw new LocalizedException(__('Attribute set name is empty.')); + throw new LocalizedException(__('The attribute set name is empty. Enter the name and try again.')); } if (!$this->_getResource()->validate($this, $attributeSetName)) { - throw new LocalizedException(__('An attribute set named "%1" already exists.', $attributeSetName)); + throw new LocalizedException( + __('A "%1" attribute set name already exists. Create a new name and try again.', $attributeSetName) + ); } return true; diff --git a/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php b/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php index 48dbb80fe6d14..76e7c7655ba84 100644 --- a/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php +++ b/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Eav\Model\Entity\Collection; use Magento\Framework\App\ResourceConnection\SourceProviderInterface; @@ -246,7 +247,9 @@ public function setEntity($entity) } elseif (is_string($entity) || $entity instanceof \Magento\Framework\App\Config\Element) { $this->_entity = $this->_eavEntityFactory->create()->setType($entity); } else { - throw new LocalizedException(__('Invalid entity supplied: %1', print_r($entity, 1))); + throw new LocalizedException( + __('The "%1" entity supplied is invalid. Verify the entity and try again.', print_r($entity, 1)) + ); } return $this; } @@ -302,7 +305,9 @@ public function setObject($object = null) public function addItem(\Magento\Framework\DataObject $object) { if (!$object instanceof $this->_itemObjectClass) { - throw new LocalizedException(__('Attempt to add an invalid object')); + throw new LocalizedException( + __("The object wasn't added because it's invalid. To continue, enter a valid object and try again.") + ); } return parent::addItem($object); } @@ -495,7 +500,12 @@ public function addAttributeToSelect($attribute, $joinType = false) $attrInstance = $this->_eavConfig->getAttribute($this->getEntity()->getType(), $attribute); } if (empty($attrInstance)) { - throw new LocalizedException(__('Invalid attribute requested: %1', (string)$attribute)); + throw new LocalizedException( + __( + 'The "%1" attribute requested is invalid. Verify the attribute and try again.', + (string)$attribute + ) + ); } $this->_selectAttributes[$attrInstance->getAttributeCode()] = $attrInstance->getId(); } @@ -662,7 +672,7 @@ public function joinAttribute($alias, $attribute, $bind, $filter = null, $joinTy } if (!$bindAttribute || !$bindAttribute->isStatic() && !$bindAttribute->getId()) { - throw new LocalizedException(__('Invalid foreign key')); + throw new LocalizedException(__('The foreign key is invalid. Verify the foreign key and try again.')); } // try to explode combined entity/attribute if supplied @@ -686,7 +696,7 @@ public function joinAttribute($alias, $attribute, $bind, $filter = null, $joinTy } } if (!$entity || !$entity->getTypeId()) { - throw new LocalizedException(__('Invalid entity type')); + throw new LocalizedException(__('The entity type is invalid. Verify the entity type and try again.')); } // cache entity @@ -699,7 +709,7 @@ public function joinAttribute($alias, $attribute, $bind, $filter = null, $joinTy $attribute = $entity->getAttribute($attribute); } if (!$attribute) { - throw new LocalizedException(__('Invalid attribute type')); + throw new LocalizedException(__('The attribute type is invalid. Verify the attribute type and try again.')); } if (empty($filter)) { @@ -819,7 +829,7 @@ public function joinTable($table, $bind, $fields = null, $cond = null, $joinType } foreach ($fields as $alias => $field) { if (isset($this->_joinFields[$alias])) { - throw new LocalizedException(__('A joint field with this alias (%1) is already declared.', $alias)); + throw new LocalizedException(__('A joint field with a "%1" alias is already declared.', $alias)); } $this->_joinFields[$alias] = ['table' => $tableAlias, 'field' => $field]; } @@ -1269,7 +1279,9 @@ protected function _setItemAttributeValue($valueInfo) $entityIdField = $this->getEntity()->getEntityIdField(); $entityId = $valueInfo[$entityIdField]; if (!isset($this->_itemsById[$entityId])) { - throw new LocalizedException(__('Data integrity: No header row found for attribute')); + throw new LocalizedException( + __('A header row is missing for an attribute. Verify the header row and try again.') + ); } $attributeCode = array_search($valueInfo['attribute_id'], $this->_selectAttributes); if (!$attributeCode) { @@ -1321,7 +1333,9 @@ protected function _getAttributeFieldName($attributeCode) $attribute = $this->getAttribute($attributeCode); if (!$attribute) { - throw new LocalizedException(__('Invalid attribute name: %1', $attributeCode)); + throw new LocalizedException( + __('The "%1" attribute name is invalid. Reset the name and try again.', $attributeCode) + ); } if ($attribute->isStatic()) { @@ -1380,7 +1394,9 @@ protected function _addAttributeJoin($attributeCode, $joinType = 'inner') } if (!$attribute) { - throw new LocalizedException(__('Invalid attribute name: %1', $attributeCode)); + throw new LocalizedException( + __('The "%1" attribute name is invalid. Reset the name and try again.', $attributeCode) + ); } if ($attribute->getBackend()->isStatic()) { diff --git a/app/code/Magento/Eav/Model/Entity/GetCustomAttributeCodes.php b/app/code/Magento/Eav/Model/Entity/GetCustomAttributeCodes.php new file mode 100644 index 0000000000000..a77b298f5d209 --- /dev/null +++ b/app/code/Magento/Eav/Model/Entity/GetCustomAttributeCodes.php @@ -0,0 +1,52 @@ +customAttributesCodes[$cacheKey])) { + $this->customAttributesCodes[$cacheKey] = $this->getEavAttributesCodes($metadataService); + } + return $this->customAttributesCodes[$cacheKey]; + } + + /** + * Receive a list of EAV attributes using provided metadata service. + * + * @param MetadataServiceInterface $metadataService + * @param string|null $entityType + * @return string[] + */ + private function getEavAttributesCodes(MetadataServiceInterface $metadataService, string $entityType = null) + { + $attributeCodes = []; + $customAttributesMetadata = $metadataService->getCustomAttributesMetadata($entityType); + if (is_array($customAttributesMetadata)) { + /** @var $attribute \Magento\Framework\Api\MetadataObjectInterface */ + foreach ($customAttributesMetadata as $attribute) { + $attributeCodes[] = $attribute->getAttributeCode(); + } + } + return $attributeCodes; + } +} diff --git a/app/code/Magento/Eav/Model/Entity/GetCustomAttributeCodesInterface.php b/app/code/Magento/Eav/Model/Entity/GetCustomAttributeCodesInterface.php new file mode 100644 index 0000000000000..c73d626e7364d --- /dev/null +++ b/app/code/Magento/Eav/Model/Entity/GetCustomAttributeCodesInterface.php @@ -0,0 +1,20 @@ +getTypeId()) { - throw new LocalizedException(__('Invalid form type.')); + throw new LocalizedException(__('The form type is invalid. Reset the type and try again.')); } if (!$this->getAttributeId()) { - throw new LocalizedException(__('Invalid EAV attribute')); + throw new LocalizedException(__('The EAV attribute is invalid. Verify the attribute and try again.')); } return parent::beforeSave(); diff --git a/app/code/Magento/Eav/Model/Form/Fieldset.php b/app/code/Magento/Eav/Model/Form/Fieldset.php index a0c706c3d03a5..f43a10f074a3a 100644 --- a/app/code/Magento/Eav/Model/Form/Fieldset.php +++ b/app/code/Magento/Eav/Model/Form/Fieldset.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Eav\Model\Form; /** @@ -72,7 +73,9 @@ protected function _construct() public function beforeSave() { if (!$this->getTypeId()) { - throw new \Magento\Framework\Exception\LocalizedException(__('Invalid form type.')); + throw new \Magento\Framework\Exception\LocalizedException( + __('The form type is invalid. Reset the type and try again.') + ); } if (!$this->getStoreId() && $this->getLabel()) { $this->setStoreLabel($this->getStoreId(), $this->getLabel()); diff --git a/app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute.php b/app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute.php index d64d5774fef1f..25858f6a3454d 100644 --- a/app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute.php +++ b/app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Eav\Model\ResourceModel\Entity; use Magento\Eav\Model\Config; @@ -393,7 +394,9 @@ protected function _processAttributeOptions($object, $option) protected function _checkDefaultOptionValue($values) { if (!isset($values[0])) { - throw new \Magento\Framework\Exception\LocalizedException(__('Default option value is not defined')); + throw new \Magento\Framework\Exception\LocalizedException( + __("The default option isn't defined. Set the option and try again.") + ); } } diff --git a/app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute/Set.php b/app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute/Set.php index 77ceb192cfdc6..4e1762730a8d9 100644 --- a/app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute/Set.php +++ b/app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute/Set.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Eav\Model\ResourceModel\Entity\Attribute; class Set extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb @@ -103,7 +104,7 @@ protected function _beforeDelete(\Magento\Framework\Model\AbstractModel $object) ->getDefaultAttributeSetId(); if ($object->getAttributeSetId() == $defaultAttributeSetId) { throw new \Magento\Framework\Exception\StateException( - __('Default attribute set can not be deleted') + __('The default attribute set can\'t be deleted.') ); } return parent::_beforeDelete($object); diff --git a/app/code/Magento/Eav/Setup/EavSetup.php b/app/code/Magento/Eav/Setup/EavSetup.php index 13f55308e6fa6..6e81ddc36e9c9 100644 --- a/app/code/Magento/Eav/Setup/EavSetup.php +++ b/app/code/Magento/Eav/Setup/EavSetup.php @@ -3,12 +3,15 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Eav\Setup; use Magento\Eav\Model\Entity\Setup\Context; use Magento\Eav\Model\Entity\Setup\PropertyMapperInterface; use Magento\Eav\Model\ResourceModel\Entity\Attribute\Group\CollectionFactory; use Magento\Framework\App\CacheInterface; +use Magento\Framework\App\ObjectManager; +use Magento\Framework\App\ResourceConnection; use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Setup\ModuleDataSetupInterface; @@ -99,7 +102,7 @@ public function __construct( /** * Gets setup model - * + * @deprecated * @return ModuleDataSetupInterface */ public function getSetup() @@ -201,7 +204,10 @@ public function addEntityType($code, array $params) if ($this->getEntityType($code, 'entity_type_id')) { $this->updateEntityType($code, $data); } else { - $this->setup->getConnection()->insert($this->setup->getTable('eav_entity_type'), $data); + $this->setup->getConnection()->insert( + $this->setup->getTable('eav_entity_type'), + $data + ); } if (isset($params['entity_type_id'])) { @@ -264,7 +270,7 @@ public function getEntityTypeId($entityTypeId) $entityTypeId = $this->getEntityType($entityTypeId, 'entity_type_id'); } if (!is_numeric($entityTypeId)) { - throw new LocalizedException(__('Wrong entity ID')); + throw new LocalizedException(__('The entity ID is incorrect. Verify the ID and try again.')); } return $entityTypeId; @@ -338,7 +344,10 @@ public function addAttributeSet($entityTypeId, $name, $sortOrder = null, $setId if ($setId) { $this->updateAttributeSet($entityTypeId, $setId, $data); } else { - $this->setup->getConnection()->insert($this->setup->getTable('eav_attribute_set'), $data); + $this->setup->getConnection()->insert( + $this->setup->getTable('eav_attribute_set'), + $data + ); $this->addAttributeGroup($entityTypeId, $name, $this->_generalGroupName); } @@ -403,7 +412,7 @@ public function getAttributeSetId($entityTypeId, $setId) $setId = $this->getAttributeSet($entityTypeId, $setId, 'attribute_set_id'); } if (!is_numeric($setId)) { - throw new LocalizedException(__('Wrong attribute set ID')); + throw new LocalizedException(__('The attribute set ID is incorrect. Verify the ID and try again.')); } return $setId; @@ -549,7 +558,10 @@ public function addAttributeGroup($entityTypeId, $setId, $name, $sortOrder = nul } $data['attribute_group_code'] = $attributeGroupCode; } - $this->setup->getConnection()->insert($this->setup->getTable('eav_attribute_group'), $data); + $this->setup->getConnection()->insert( + $this->setup->getTable('eav_attribute_group'), + $data + ); } return $this; @@ -665,7 +677,7 @@ public function getAttributeGroupId($entityTypeId, $setId, $groupId) } if (!is_numeric($groupId)) { - throw new LocalizedException(__('Wrong attribute group ID')); + throw new LocalizedException(__('The attribute group ID is incorrect. Verify the ID and try again.')); } return $groupId; } @@ -896,13 +908,17 @@ public function addAttributeOption($option) $data = [ 'sort_order' => isset($option['order'][$optionId]) ? $option['order'][$optionId] : 0, ]; - $this->setup->getConnection()->update($optionTable, $data, ['option_id=?' => $intOptionId]); + $this->setup->getConnection()->update( + $optionTable, + $data, + ['option_id=?' => $intOptionId] + ); } // Default value if (!isset($values[0])) { throw new \Magento\Framework\Exception\LocalizedException( - __('Default option value is not defined') + __("The default option isn't defined. Set the option and try again.") ); } $condition = ['option_id =?' => $intOptionId]; @@ -970,7 +986,10 @@ private function _updateAttribute($entityTypeId, $id, $field, $value = null, $so $bind = []; foreach ($field as $k => $v) { if (isset($attributeFields[$k])) { - $bind[$k] = $this->setup->getConnection()->prepareColumnValue($attributeFields[$k], $v); + $bind[$k] = $this->setup->getConnection()->prepareColumnValue( + $attributeFields[$k], + $v + ); } } if (!$bind) { @@ -1016,16 +1035,23 @@ private function _updateAttributeAdditionalData($entityTypeId, $id, $field, $val if (!$additionalTable) { return $this; } - $additionalTableExists = $this->setup->getConnection()->isTableExists($this->setup->getTable($additionalTable)); + $additionalTableExists = $this->setup->getConnection()->isTableExists( + $this->setup->getTable($additionalTable) + ); if (!$additionalTableExists) { return $this; } - $attributeFields = $this->setup->getConnection()->describeTable($this->setup->getTable($additionalTable)); + $attributeFields = $this->setup->getConnection()->describeTable( + $this->setup->getTable($additionalTable) + ); if (is_array($field)) { $bind = []; foreach ($field as $k => $v) { if (isset($attributeFields[$k])) { - $bind[$k] = $this->setup->getConnection()->prepareColumnValue($attributeFields[$k], $v); + $bind[$k] = $this->setup->getConnection()->prepareColumnValue( + $attributeFields[$k], + $v + ); } } if (!$bind) { @@ -1358,7 +1384,10 @@ public function addAttributeToGroup($entityType, $setId, $groupId, $attributeId, } $sortOrder = is_numeric($sortOrder) ? $sortOrder : 1; $data['sort_order'] = $sortOrder; - $this->setup->getConnection()->insert($this->setup->getTable('eav_entity_attribute'), $data); + $this->setup->getConnection()->insert( + $this->setup->getTable('eav_entity_attribute'), + $data + ); } return $this; @@ -1439,7 +1468,9 @@ public function installEntities($entities = null) */ private function _getAttributeTableFields() { - return $this->setup->getConnection()->describeTable($this->setup->getTable('eav_attribute')); + return $this->setup->getConnection()->describeTable( + $this->setup->getTable('eav_attribute') + ); } /** @@ -1463,8 +1494,13 @@ private function _insertAttribute(array $data) return $this; } - $this->setup->getConnection()->insert($this->setup->getTable('eav_attribute'), $bind); - $attributeId = $this->setup->getConnection()->lastInsertId($this->setup->getTable('eav_attribute')); + $this->setup->getConnection()->insert( + $this->setup->getTable('eav_attribute'), + $bind + ); + $attributeId = $this->setup->getConnection()->lastInsertId( + $this->setup->getTable('eav_attribute') + ); $this->_insertAttributeAdditionalData( $data['entity_type_id'], array_merge(['attribute_id' => $attributeId], $data) @@ -1486,10 +1522,14 @@ private function _insertAttributeAdditionalData($entityTypeId, array $data) if (!$additionalTable) { return $this; } - $additionalTableExists = $this->setup->getConnection()->isTableExists($this->setup->getTable($additionalTable)); + $additionalTableExists = $this->setup->getConnection()->isTableExists( + $this->setup->getTable($additionalTable) + ); if ($additionalTable && $additionalTableExists) { $bind = []; - $fields = $this->setup->getConnection()->describeTable($this->setup->getTable($additionalTable)); + $fields = $this->setup->getConnection()->describeTable( + $this->setup->getTable($additionalTable) + ); foreach ($data as $k => $v) { if (isset($fields[$k])) { $bind[$k] = $this->setup->getConnection()->prepareColumnValue($fields[$k], $v); @@ -1498,7 +1538,10 @@ private function _insertAttributeAdditionalData($entityTypeId, array $data) if (!$bind) { return $this; } - $this->setup->getConnection()->insert($this->setup->getTable($additionalTable), $bind); + $this->setup->getConnection()->insert( + $this->setup->getTable($additionalTable), + $bind + ); } return $this; diff --git a/app/code/Magento/Eav/Setup/InstallData.php b/app/code/Magento/Eav/Setup/Patch/Data/InitializeAttributeModels.php similarity index 69% rename from app/code/Magento/Eav/Setup/InstallData.php rename to app/code/Magento/Eav/Setup/Patch/Data/InitializeAttributeModels.php index ca2156d62ee42..260704ddd400c 100644 --- a/app/code/Magento/Eav/Setup/InstallData.php +++ b/app/code/Magento/Eav/Setup/Patch/Data/InitializeAttributeModels.php @@ -4,43 +4,51 @@ * See COPYING.txt for license details. */ -namespace Magento\Eav\Setup; +namespace Magento\Eav\Setup\Patch\Data; use Magento\Eav\Setup\EavSetupFactory; -use Magento\Framework\Setup\InstallDataInterface; -use Magento\Framework\Setup\ModuleContextInterface; use Magento\Framework\Setup\ModuleDataSetupInterface; +use Magento\Framework\App\ResourceConnection; +use Magento\Setup\Model\Patch\DataPatchInterface; +use Magento\Setup\Model\Patch\PatchVersionInterface; /** - * @codeCoverageIgnore + * Class InitializeAttributeModels + * @package Magento\Eav\Setup\Patch */ -class InstallData implements InstallDataInterface +class InitializeAttributeModels implements DataPatchInterface, PatchVersionInterface { /** - * EAV setup factory - * + * @var \Magento\Framework\Setup\ModuleDataSetupInterface + */ + private $moduleDataSetup; + /** * @var EavSetupFactory */ private $eavSetupFactory; /** - * Init - * + * InitializeAttributeModels constructor. + * @param \Magento\Framework\Setup\ModuleDataSetupInterface $moduleDataSetup + * @param ModuleDataSetupInterface $moduleDataSetup * @param EavSetupFactory $eavSetupFactory */ - public function __construct(EavSetupFactory $eavSetupFactory) - { + public function __construct( + \Magento\Framework\Setup\ModuleDataSetupInterface $moduleDataSetup, + EavSetupFactory $eavSetupFactory + ) { $this->eavSetupFactory = $eavSetupFactory; + $this->moduleDataSetup = $moduleDataSetup; } /** * {@inheritdoc} */ - public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context) + public function apply() { - $setup->startSetup(); + $this->moduleDataSetup->startSetup(); /** @var \Magento\Framework\Module\Setup\Migration $migrationSetup */ - $migrationSetup = $setup->createMigrationSetup(); + $migrationSetup = $this->moduleDataSetup->createMigrationSetup(); $migrationSetup->appendClassAliasReplace( 'eav_attribute', @@ -70,7 +78,6 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface \Magento\Framework\Module\Setup\Migration::FIELD_CONTENT_TYPE_PLAIN, ['attribute_id'] ); - $migrationSetup->appendClassAliasReplace( 'eav_entity_type', 'entity_model', @@ -99,17 +106,40 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface \Magento\Framework\Module\Setup\Migration::FIELD_CONTENT_TYPE_PLAIN, ['entity_type_id'] ); - $migrationSetup->doUpdateClassAliases(); - /** @var \Magento\Eav\Setup\EavSetup $eavSetup */ - $eavSetup = $this->eavSetupFactory->create(['setup' => $setup]); + $eavSetup = $this->eavSetupFactory->create([ + 'setup' => $this->moduleDataSetup + ]); $groups = $eavSetup->getAttributeGroupCollectionFactory(); foreach ($groups as $group) { /** @var $group \Magento\Eav\Model\Entity\Attribute\Group*/ $group->save(); } + $this->moduleDataSetup->endSetup(); + } - $setup->endSetup(); + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return []; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.0'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; } } diff --git a/app/code/Magento/Eav/Test/Unit/Model/Attribute/GroupRepositoryTest.php b/app/code/Magento/Eav/Test/Unit/Model/Attribute/GroupRepositoryTest.php index 9b0f9704887bb..6f9dab002aa0a 100644 --- a/app/code/Magento/Eav/Test/Unit/Model/Attribute/GroupRepositoryTest.php +++ b/app/code/Magento/Eav/Test/Unit/Model/Attribute/GroupRepositoryTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Eav\Test\Unit\Model\Attribute; use Magento\Framework\Api\SearchCriteria\CollectionProcessorInterface; @@ -176,7 +177,7 @@ public function testSaveThrowExceptionIfAttributeSetDoesNotExist() * Test saving throws exception if cannot save group * * @expectedException \Magento\Framework\Exception\StateException - * @expectedExceptionMessage Cannot save attributeGroup + * @expectedExceptionMessage The attributeGroup can't be saved. * @throws \Magento\Framework\Exception\NoSuchEntityException * @throws \Magento\Framework\Exception\StateException * @return void @@ -207,7 +208,7 @@ public function testSaveThrowExceptionIfCannotSaveGroup() * Test saving throws exception if group does not belong to provided set * * @expectedException \Magento\Framework\Exception\StateException - * @expectedExceptionMessage Attribute group does not belong to provided attribute set + * @expectedExceptionMessage The attribute group doesn't belong to the provided attribute set. * @throws \Magento\Framework\Exception\NoSuchEntityException * @throws \Magento\Framework\Exception\StateException * @return void @@ -336,7 +337,7 @@ public function testGet() * Test get throws exception if provided group does not exist * * @expectedException \Magento\Framework\Exception\NoSuchEntityException - * @expectedExceptionMessage Group with id "42" does not exist. + * @expectedExceptionMessage The group with the "42" ID doesn't exist. Verify the ID and try again. * @throws \Magento\Framework\Exception\NoSuchEntityException * @return void */ @@ -367,7 +368,7 @@ public function testDelete() * Test deletion throws exception if provided group does not exist * * @expectedException \Magento\Framework\Exception\StateException - * @expectedExceptionMessage Cannot delete attributeGroup with id + * @expectedExceptionMessage The attribute group with id "42" can't be deleted. * @throws \Magento\Framework\Exception\StateException * @return void */ diff --git a/app/code/Magento/Eav/Test/Unit/Model/AttributeManagementTest.php b/app/code/Magento/Eav/Test/Unit/Model/AttributeManagementTest.php index 21697bf1e22c7..5b78154555809 100644 --- a/app/code/Magento/Eav/Test/Unit/Model/AttributeManagementTest.php +++ b/app/code/Magento/Eav/Test/Unit/Model/AttributeManagementTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Eav\Test\Unit\Model; use Magento\Eav\Model\AttributeManagement; @@ -101,7 +102,7 @@ protected function setUp() /** * * @expectedException \Magento\Framework\Exception\NoSuchEntityException - * @expectedExceptionMessage AttributeSet with id "2" does not exist. + * @expectedExceptionMessage The AttributeSet with a "2" ID doesn't exist. Verify the attributeSet and try again. */ public function testAssignNoSuchEntityException() { @@ -128,7 +129,7 @@ public function testAssignNoSuchEntityException() /** * * @expectedException \Magento\Framework\Exception\InputException - * @expectedExceptionMessage Wrong attribute set id provided + * @expectedExceptionMessage The attribute set ID is incorrect. Verify the ID and try again. */ public function testAssignInputException() { @@ -160,7 +161,7 @@ public function testAssignInputException() /** * * @expectedException \Magento\Framework\Exception\InputException - * @expectedExceptionMessage Attribute group does not belong to attribute set + * @expectedExceptionMessage The attribute group doesn't belong to the attribute set. */ public function testAssignInputExceptionGroupInSet() { @@ -295,7 +296,6 @@ public function testUnassign() /** * @expectedException \Magento\Framework\Exception\InputException - * @expectedExceptionMessage Attribute "code" not found in attribute set 1. */ public function testUnassignInputException() { @@ -335,11 +335,15 @@ public function testUnassignInputException() $attributeMock->expects($this->never())->method('deleteEntity'); $this->attributeManagement->unassign($attributeSetId, $attributeCode); + + $this->expectExceptionMessage( + 'The "code" attribute wasn\'t found in the "1" attribute set. Enter the attribute and try again.' + ); } /** * @expectedException \Magento\Framework\Exception\NoSuchEntityException - * @expectedExceptionMessage Attribute set not found: 1 + * @expectedExceptionMessage The "1234567" attribute set wasn't found. Verify and try again. */ public function testUnassignWithWrongAttributeSet() { @@ -356,7 +360,7 @@ public function testUnassignWithWrongAttributeSet() /** * @expectedException \Magento\Framework\Exception\StateException - * @expectedExceptionMessage System attribute can not be deleted + * @expectedExceptionMessage The system attribute can't be deleted. */ public function testUnassignStateException() { diff --git a/app/code/Magento/Eav/Test/Unit/Model/AttributeRepositoryTest.php b/app/code/Magento/Eav/Test/Unit/Model/AttributeRepositoryTest.php index c225941c9eb35..548a70e07bfc3 100644 --- a/app/code/Magento/Eav/Test/Unit/Model/AttributeRepositoryTest.php +++ b/app/code/Magento/Eav/Test/Unit/Model/AttributeRepositoryTest.php @@ -100,7 +100,7 @@ protected function setUp() /** * @expectedException \Magento\Framework\Exception\InputException - * @expectedExceptionMessage entity_type_code is a required field. + * @expectedExceptionMessage "entity_type_code" is required. Enter and try again. */ public function testGetListInputException() { diff --git a/app/code/Magento/Eav/Test/Unit/Model/AttributeSetRepositoryTest.php b/app/code/Magento/Eav/Test/Unit/Model/AttributeSetRepositoryTest.php index b7724c9cf349d..04cd905d4ff3f 100644 --- a/app/code/Magento/Eav/Test/Unit/Model/AttributeSetRepositoryTest.php +++ b/app/code/Magento/Eav/Test/Unit/Model/AttributeSetRepositoryTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Eav\Test\Unit\Model; use Magento\Eav\Model\AttributeSetRepository; @@ -132,7 +133,6 @@ public function testSave() /** * @return void * @expectedException \Magento\Framework\Exception\CouldNotSaveException - * @expectedExceptionMessage There was an error saving attribute set. */ public function testSaveThrowsExceptionIfGivenEntityCannotBeSaved() { @@ -141,6 +141,11 @@ public function testSaveThrowsExceptionIfGivenEntityCannotBeSaved() new \Exception('Some internal exception message.') ); $this->model->save($attributeSetMock); + + $this->expectExceptionMessage( + "The attribute set couldn't be saved due to an error. Verify your information and try again. " + . "If the error persists, please try again later." + ); } /** @@ -156,7 +161,6 @@ public function testDelete() /** * @return void * @expectedException \Magento\Framework\Exception\CouldNotDeleteException - * @expectedExceptionMessage There was an error deleting attribute set. */ public function testDeleteThrowsExceptionIfGivenEntityCannotBeDeleted() { @@ -165,12 +169,17 @@ public function testDeleteThrowsExceptionIfGivenEntityCannotBeDeleted() new \Magento\Framework\Exception\CouldNotDeleteException(__('Some internal exception message.')) ); $this->model->delete($attributeSetMock); + + $this->expectExceptionMessage( + "The attribute set couldn't be deleted due to an error. " + . "Try again — if the error persists, please try again later." + ); } /** * @return void * @expectedException \Magento\Framework\Exception\CouldNotDeleteException - * @expectedExceptionMessage Default attribute set can not be deleted + * @expectedExceptionMessage The default attribute set can't be deleted. */ public function testDeleteThrowsExceptionIfGivenAttributeSetIsDefault() { diff --git a/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/OptionManagementTest.php b/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/OptionManagementTest.php index 36eb78fd435e7..8900a22f6ab7e 100644 --- a/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/OptionManagementTest.php +++ b/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/OptionManagementTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Eav\Test\Unit\Model\Entity\Attribute; class OptionManagementTest extends \PHPUnit\Framework\TestCase @@ -85,7 +86,7 @@ public function testAdd() /** * @expectedException \Magento\Framework\Exception\InputException - * @expectedExceptionMessage Empty attribute code + * @expectedExceptionMessage The attribute code is empty. Enter the code and try again. */ public function testAddWithEmptyAttributeCode() { @@ -106,7 +107,7 @@ public function testAddWithEmptyAttributeCode() /** * @expectedException \Magento\Framework\Exception\StateException - * @expectedExceptionMessage Attribute testAttribute doesn't work with options + * @expectedExceptionMessage The "testAttribute" attribute doesn't work with options. */ public function testAddWithWrongOptions() { @@ -139,7 +140,7 @@ public function testAddWithWrongOptions() /** * @expectedException \Magento\Framework\Exception\StateException - * @expectedExceptionMessage Cannot save attribute atrCde + * @expectedExceptionMessage The "atrCde" attribute can't be saved. */ public function testAddWithCannotSaveException() { @@ -225,7 +226,7 @@ public function testDelete() /** * @expectedException \Magento\Framework\Exception\StateException - * @expectedExceptionMessage Cannot save attribute atrCode + * @expectedExceptionMessage The "atrCode" attribute can't be saved. */ public function testDeleteWithCannotSaveException() { @@ -261,7 +262,7 @@ public function testDeleteWithCannotSaveException() /** * @expectedException \Magento\Framework\Exception\NoSuchEntityException - * @expectedExceptionMessage Attribute atrCode does not contain option with Id option + * @expectedExceptionMessage The "atrCode" attribute doesn't include an option with "option" ID. */ public function testDeleteWithWrongOption() { @@ -290,7 +291,7 @@ public function testDeleteWithWrongOption() /** * @expectedException \Magento\Framework\Exception\StateException - * @expectedExceptionMessage Attribute atrCode doesn't have any option + * @expectedExceptionMessage The "atrCode" attribute has no option. */ public function testDeleteWithAbsentOption() { @@ -315,7 +316,7 @@ public function testDeleteWithAbsentOption() /** * @expectedException \Magento\Framework\Exception\InputException - * @expectedExceptionMessage Empty attribute code + * @expectedExceptionMessage The attribute code is empty. Enter the code and try again. */ public function testDeleteWithEmptyAttributeCode() { @@ -348,7 +349,7 @@ public function testGetItems() /** * @expectedException \Magento\Framework\Exception\StateException - * @expectedExceptionMessage Cannot load options for attribute atrCode + * @expectedExceptionMessage The options for "atrCode" attribute can't be loaded. */ public function testGetItemsWithCannotLoadException() { @@ -371,7 +372,7 @@ public function testGetItemsWithCannotLoadException() /** * @expectedException \Magento\Framework\Exception\InputException - * @expectedExceptionMessage Empty attribute code + * @expectedExceptionMessage The attribute code is empty. Enter the code and try again. */ public function testGetItemsWithEmptyAttributeCode() { diff --git a/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/SetTest.php b/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/SetTest.php index 78465e57c6236..79f601b154b73 100644 --- a/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/SetTest.php +++ b/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/SetTest.php @@ -65,8 +65,8 @@ public function testValidateWithNonexistentValidName() public function invalidAttributeSetDataProvider() { return [ - ['', 'Attribute set name is empty.'], - ['existing_name', 'An attribute set named "existing_name" already exists.'] + ['', 'The attribute set name is empty. Enter the name and try again.'], + ['existing_name', 'A "existing_name" attribute set name already exists. Create a new name and try again.'] ]; } } diff --git a/app/code/Magento/Eav/Test/Unit/Model/Entity/GetCustomAttributeCodesTest.php b/app/code/Magento/Eav/Test/Unit/Model/Entity/GetCustomAttributeCodesTest.php new file mode 100644 index 0000000000000..0ba247e1fbb65 --- /dev/null +++ b/app/code/Magento/Eav/Test/Unit/Model/Entity/GetCustomAttributeCodesTest.php @@ -0,0 +1,59 @@ +getCustomAttributeCodes = new GetCustomAttributeCodes(); + } + + /** + * Test GetCustomAttributeCodes::execute() will return attribute codes from attributes metadata. + * + * @return void + */ + public function testExecute() + { + $attributeCode = 'testCode'; + $attributeMetadata = $this->getMockBuilder(MetadataObjectInterface::class) + ->disableOriginalConstructor() + ->setMethods(['getAttributeCode']) + ->getMockForAbstractClass(); + $attributeMetadata->expects($this->once()) + ->method('getAttributeCode') + ->willReturn($attributeCode); + /** @var MetadataServiceInterface|\PHPUnit_Framework_MockObject_MockObject $metadataService */ + $metadataService = $this->getMockBuilder(MetadataServiceInterface::class) + ->setMethods(['getCustomAttributesMetadata']) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + $metadataService->expects($this->once()) + ->method('getCustomAttributesMetadata') + ->willReturn([$attributeMetadata]); + $this->assertEquals([$attributeCode], $this->getCustomAttributeCodes->execute($metadataService)); + } +} diff --git a/app/code/Magento/Eav/Test/Unit/Model/ResourceModel/Entity/Attribute/SetTest.php b/app/code/Magento/Eav/Test/Unit/Model/ResourceModel/Entity/Attribute/SetTest.php index 1c66788f8585a..4c2ede60c8798 100644 --- a/app/code/Magento/Eav/Test/Unit/Model/ResourceModel/Entity/Attribute/SetTest.php +++ b/app/code/Magento/Eav/Test/Unit/Model/ResourceModel/Entity/Attribute/SetTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Eav\Test\Unit\Model\ResourceModel\Entity\Attribute; use Magento\Eav\Model\ResourceModel\Entity\Attribute\Set; @@ -116,7 +117,7 @@ protected function setUp() /** * @expectedException \Magento\Framework\Exception\StateException - * @expectedExceptionMessage Default attribute set can not be deleted + * @expectedExceptionMessage The default attribute set can't be deleted. * @return void */ public function testBeforeDeleteStateException() diff --git a/app/code/Magento/Eav/etc/di.xml b/app/code/Magento/Eav/etc/di.xml index 8e897b979d2f0..ae4663cfc236a 100644 --- a/app/code/Magento/Eav/etc/di.xml +++ b/app/code/Magento/Eav/etc/di.xml @@ -8,6 +8,7 @@ + diff --git a/app/code/Magento/Eav/etc/module.xml b/app/code/Magento/Eav/etc/module.xml index acd5807a29f90..7b2b651b2d2f9 100644 --- a/app/code/Magento/Eav/etc/module.xml +++ b/app/code/Magento/Eav/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/EavGraphQl/etc/module.xml b/app/code/Magento/EavGraphQl/etc/module.xml index b61215e836839..795acfaf647af 100644 --- a/app/code/Magento/EavGraphQl/etc/module.xml +++ b/app/code/Magento/EavGraphQl/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/Email/Model/AbstractTemplate.php b/app/code/Magento/Email/Model/AbstractTemplate.php index e6a2f74a0d1a8..4830ecfbb74b3 100644 --- a/app/code/Magento/Email/Model/AbstractTemplate.php +++ b/app/code/Magento/Email/Model/AbstractTemplate.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Email\Model; use Magento\Framework\App\Filesystem\DirectoryList; @@ -535,7 +536,7 @@ protected function cancelDesignConfig() public function setForcedArea($templateId) { if ($this->area) { - throw new \LogicException(__('Area is already set')); + throw new \LogicException(__('The area is already set.')); } $this->area = $this->emailConfig->getTemplateArea($templateId); return $this; @@ -605,7 +606,9 @@ public function getDesignConfig() public function setDesignConfig(array $config) { if (!isset($config['area']) || !isset($config['store'])) { - throw new LocalizedException(__('Design config must have area and store.')); + throw new LocalizedException( + __('The design config needs an area and a store. Verify that both are set and try again.') + ); } $this->getDesignConfig()->setData($config); return $this; diff --git a/app/code/Magento/Email/etc/module.xml b/app/code/Magento/Email/etc/module.xml index e3e0632c641e0..60c11ad2f0d2b 100644 --- a/app/code/Magento/Email/etc/module.xml +++ b/app/code/Magento/Email/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/Email/view/adminhtml/ui_component/design_config_form.xml b/app/code/Magento/Email/view/adminhtml/ui_component/design_config_form.xml index b63f79233383a..91c38c92dc754 100644 --- a/app/code/Magento/Email/view/adminhtml/ui_component/design_config_form.xml +++ b/app/code/Magento/Email/view/adminhtml/ui_component/design_config_form.xml @@ -15,12 +15,12 @@ - Allowed file types: jpg, jpeg, gif, png. To optimize logo for high-resolution displays, upload an image that is 3x normal size and then specify 1x dimensions in the width/height fields below. + To optimize logo for high-resolution displays, upload an image that is 3x normal size and then specify 1x dimensions in the width/height fields below. - fileUploader + imageUploader - + jpg jpeg gif png 2097152 @@ -28,7 +28,7 @@ theme/design_config_fileUploader/save - + diff --git a/app/code/Magento/EncryptionKey/etc/module.xml b/app/code/Magento/EncryptionKey/etc/module.xml index 48ab3e51ba03d..1a70ce0ddfb72 100644 --- a/app/code/Magento/EncryptionKey/etc/module.xml +++ b/app/code/Magento/EncryptionKey/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/Fedex/Setup/InstallData.php b/app/code/Magento/Fedex/Setup/Patch/Data/ConfigureFedexDefaults.php similarity index 76% rename from app/code/Magento/Fedex/Setup/InstallData.php rename to app/code/Magento/Fedex/Setup/Patch/Data/ConfigureFedexDefaults.php index 1591aaa3abf70..56cdf6c60932d 100644 --- a/app/code/Magento/Fedex/Setup/InstallData.php +++ b/app/code/Magento/Fedex/Setup/Patch/Data/ConfigureFedexDefaults.php @@ -4,24 +4,34 @@ * See COPYING.txt for license details. */ -namespace Magento\Fedex\Setup; +namespace Magento\Fedex\Setup\Patch\Data; -use Magento\Framework\Setup\InstallDataInterface; -use Magento\Framework\Setup\ModuleContextInterface; -use Magento\Framework\Setup\ModuleDataSetupInterface; +use Magento\Framework\App\ResourceConnection; +use Magento\Setup\Model\Patch\DataPatchInterface; +use Magento\Setup\Model\Patch\PatchVersionInterface; -/** - * Class InstallData - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - * @codeCoverageIgnore - */ -class InstallData implements InstallDataInterface +class ConfigureFedexDefaults implements DataPatchInterface, PatchVersionInterface { + /** + * @var \Magento\Framework\Setup\ModuleDataSetupInterface + */ + private $moduleDataSetup; + + /** + * ConfigureFedexDefaults constructor. + * @param \Magento\Framework\Setup\ModuleDataSetupInterface $moduleDataSetup + */ + public function __construct( + \Magento\Framework\Setup\ModuleDataSetupInterface $moduleDataSetup + ) { + $this->moduleDataSetup = $moduleDataSetup; + } + /** * {@inheritdoc} - * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ - public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context) + public function apply() { $codes = [ 'method' => [ @@ -64,10 +74,8 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ], ]; - $installer = $setup; - $configDataTable = $installer->getTable('core_config_data'); - $conn = $installer->getConnection(); - + $conn = $this->moduleDataSetup->getConnection(); + $configDataTable = $this->moduleDataSetup->getTable('core_config_data'); $select = $conn->select()->from( $configDataTable )->where( @@ -100,11 +108,34 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface } else { continue; } - if (!empty($mapNew) && $mapNew != $mapOld['value']) { $whereConfigId = $conn->quoteInto('config_id = ?', $mapOld['config_id']); $conn->update($configDataTable, ['value' => $mapNew], $whereConfigId); } } } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return []; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.0'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } } diff --git a/app/code/Magento/Fedex/etc/module.xml b/app/code/Magento/Fedex/etc/module.xml index 8e7afc1c5075d..7eec2b39bb20e 100644 --- a/app/code/Magento/Fedex/etc/module.xml +++ b/app/code/Magento/Fedex/etc/module.xml @@ -6,6 +6,6 @@ */ --> - + diff --git a/app/code/Magento/GiftMessage/Model/CartRepository.php b/app/code/Magento/GiftMessage/Model/CartRepository.php index eeab05f01d09f..f6577d1e1237b 100644 --- a/app/code/Magento/GiftMessage/Model/CartRepository.php +++ b/app/code/Magento/GiftMessage/Model/CartRepository.php @@ -101,15 +101,15 @@ public function save($cartId, \Magento\GiftMessage\Api\Data\MessageInterface $gi $quote = $this->quoteRepository->getActive($cartId); if (0 == $quote->getItemsCount()) { - throw new InputException(__('Gift Messages are not applicable for empty cart')); + throw new InputException(__("Gift messages can't be used for an empty cart. Add an item and try again.")); } if ($quote->isVirtual()) { - throw new InvalidTransitionException(__('Gift Messages are not applicable for virtual products')); + throw new InvalidTransitionException(__("Gift messages can't be used for virtual products.")); } $messageText = $giftMessage->getMessage(); if ($messageText && !$this->helper->isMessagesAllowed('quote', $quote, $this->storeManager->getStore())) { - throw new CouldNotSaveException(__('Gift Message is not available')); + throw new CouldNotSaveException(__("The gift message isn't available.")); } $this->giftMessageManager->setMessage($quote, 'quote', $giftMessage); return true; diff --git a/app/code/Magento/GiftMessage/Model/GiftMessageManager.php b/app/code/Magento/GiftMessage/Model/GiftMessageManager.php index e01da4c526252..605fd221462d9 100644 --- a/app/code/Magento/GiftMessage/Model/GiftMessageManager.php +++ b/app/code/Magento/GiftMessage/Model/GiftMessageManager.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\GiftMessage\Model; use Magento\Framework\Exception\CouldNotSaveException; @@ -98,7 +99,7 @@ public function add($giftMessages, $quote) * @param \Magento\GiftMessage\Api\Data\MessageInterface $giftMessage The gift message. * @param null|int $entityId The entity ID. * @return void - * @throws \Magento\Framework\Exception\CouldNotSaveException The specified gift message is not available. + * @throws \Magento\Framework\Exception\CouldNotSaveException The gift message isn't available. */ public function setMessage(\Magento\Quote\Model\Quote $quote, $type, $giftMessage, $entityId = null) { @@ -111,7 +112,7 @@ public function setMessage(\Magento\Quote\Model\Quote $quote, $type, $giftMessag try { $this->add($message, $quote); } catch (\Exception $e) { - throw new CouldNotSaveException(__('Could not add gift message to shopping cart')); + throw new CouldNotSaveException(__("The gift message couldn't be added to Cart.")); } } } diff --git a/app/code/Magento/GiftMessage/Model/ItemRepository.php b/app/code/Magento/GiftMessage/Model/ItemRepository.php index 6d369e083b135..3c62a489af4ab 100644 --- a/app/code/Magento/GiftMessage/Model/ItemRepository.php +++ b/app/code/Magento/GiftMessage/Model/ItemRepository.php @@ -85,7 +85,9 @@ public function get($cartId, $itemId) */ $quote = $this->quoteRepository->getActive($cartId); if (!$item = $quote->getItemById($itemId)) { - throw new NoSuchEntityException(__('There is no item with provided id in the cart')); + throw new NoSuchEntityException( + __('No item with the provided ID was found in the Cart. Verify the ID and try again.') + ); }; $messageId = $item->getGiftMessageId(); if (!$messageId) { @@ -114,16 +116,19 @@ public function save($cartId, \Magento\GiftMessage\Api\Data\MessageInterface $gi if (!$item = $quote->getItemById($itemId)) { throw new NoSuchEntityException( - __('There is no product with provided itemId: %1 in the cart', $itemId) + __( + 'No product with the "%1" itemId exists in the Cart. Verify your information and try again.', + $itemId + ) ); }; if ($item->getIsVirtual()) { - throw new InvalidTransitionException(__('Gift Messages are not applicable for virtual products')); + throw new InvalidTransitionException(__('Gift messages can\'t be used for virtual products.')); } $messageText = $giftMessage->getMessage(); if ($messageText && !$this->helper->isMessagesAllowed('items', $quote, $this->storeManager->getStore())) { - throw new CouldNotSaveException(__('Gift Message is not available')); + throw new CouldNotSaveException(__("The gift message isn't available.")); } $this->giftMessageManager->setMessage($quote, 'quote_item', $giftMessage, $itemId); return true; diff --git a/app/code/Magento/GiftMessage/Model/OrderItemRepository.php b/app/code/Magento/GiftMessage/Model/OrderItemRepository.php index 4be7483dfe672..943552e2b75bc 100644 --- a/app/code/Magento/GiftMessage/Model/OrderItemRepository.php +++ b/app/code/Magento/GiftMessage/Model/OrderItemRepository.php @@ -86,18 +86,25 @@ public function get($orderId, $orderItemId) { /** @var \Magento\Sales\Api\Data\OrderItemInterface $orderItem */ if (!$orderItem = $this->getItemById($orderId, $orderItemId)) { - throw new NoSuchEntityException(__('There is no item with provided id in the order')); + throw new NoSuchEntityException( + __('No item with the provided ID was found in the Order. Verify the ID and try again.') + ); }; if (!$this->helper->isMessagesAllowed('order_item', $orderItem, $this->storeManager->getStore())) { throw new NoSuchEntityException( - __('There is no item with provided id in the order or gift message isn\'t allowed') + __( + "No item with the provided ID was found in the Order, or a gift message isn't allowed. " + . "Verify and try again." + ) ); } $messageId = $orderItem->getGiftMessageId(); if (!$messageId) { - throw new NoSuchEntityException(__('There is no item with provided id in the order')); + throw new NoSuchEntityException( + __('No item with the provided ID was found in the Order. Verify the ID and try again.') + ); } return $this->messageFactory->create()->load($messageId); @@ -113,14 +120,16 @@ public function save($orderId, $orderItemId, \Magento\GiftMessage\Api\Data\Messa /** @var \Magento\Sales\Api\Data\OrderItemInterface $orderItem */ if (!$orderItem = $this->getItemById($orderId, $orderItemId)) { - throw new NoSuchEntityException(__('There is no item with provided id in the order')); + throw new NoSuchEntityException( + __('No item with the provided ID was found in the Order. Verify the ID and try again.') + ); }; if ($order->getIsVirtual()) { - throw new InvalidTransitionException(__('Gift Messages are not applicable for virtual products')); + throw new InvalidTransitionException(__("Gift messages can't be used for virtual products.")); } if (!$this->helper->isMessagesAllowed('order_item', $orderItem, $this->storeManager->getStore())) { - throw new CouldNotSaveException(__('Gift Message is not available')); + throw new CouldNotSaveException(__("The gift message isn't available.")); } $message = []; @@ -136,7 +145,10 @@ public function save($orderId, $orderItemId, \Magento\GiftMessage\Api\Data\Messa $this->giftMessageSaveModel->saveAllInOrder(); unset($this->orders[$orderId]); } catch (\Exception $e) { - throw new CouldNotSaveException(__('Could not add gift message to order: "%1"', $e->getMessage()), $e); + throw new CouldNotSaveException( + __('The gift message couldn\'t be added to the "%1" order.', $e->getMessage()), + $e + ); } return true; } diff --git a/app/code/Magento/GiftMessage/Model/OrderRepository.php b/app/code/Magento/GiftMessage/Model/OrderRepository.php index 1960281367e3a..abf38f1287b7a 100644 --- a/app/code/Magento/GiftMessage/Model/OrderRepository.php +++ b/app/code/Magento/GiftMessage/Model/OrderRepository.php @@ -83,13 +83,15 @@ public function get($orderId) if (!$this->helper->isMessagesAllowed('order', $order, $this->storeManager->getStore())) { throw new NoSuchEntityException( - __('There is no order with provided id or gift message isn\'t allowed') + __("Either no order exists with this ID or gift message isn't allowed.") ); } $messageId = $order->getGiftMessageId(); if (!$messageId) { - throw new NoSuchEntityException(__('There is no item with provided id in the order')); + throw new NoSuchEntityException( + __('No item with the provided ID was found in the Order. Verify the ID and try again.') + ); } return $this->messageFactory->create()->load($messageId); @@ -103,18 +105,20 @@ public function save($orderId, \Magento\GiftMessage\Api\Data\MessageInterface $g /** @var \Magento\Sales\Api\Data\OrderInterface $order */ $order = $this->orderFactory->create()->load($orderId); if (!$order->getEntityId()) { - throw new NoSuchEntityException(__('There is no order with provided id')); + throw new NoSuchEntityException(__('No order exists with this ID. Verify your information and try again.')); }; if (0 == $order->getTotalItemCount()) { - throw new InputException(__('Gift Messages are not applicable for empty order')); + throw new InputException( + __("Gift messages can't be used for an empty order. Create an order, add an item, and try again.") + ); } if ($order->getIsVirtual()) { - throw new InvalidTransitionException(__('Gift Messages are not applicable for virtual products')); + throw new InvalidTransitionException(__("Gift messages can't be used for virtual products.")); } if (!$this->helper->isMessagesAllowed('order', $order, $this->storeManager->getStore())) { - throw new CouldNotSaveException(__('Gift Message is not available')); + throw new CouldNotSaveException(__("The gift message isn't available.")); } $message = []; @@ -130,7 +134,10 @@ public function save($orderId, \Magento\GiftMessage\Api\Data\MessageInterface $g try { $this->giftMessageSaveModel->saveAllInOrder(); } catch (\Exception $e) { - throw new CouldNotSaveException(__('Could not add gift message to order: "%1"', $e->getMessage()), $e); + throw new CouldNotSaveException( + __('The gift message couldn\'t be added to the "%1" order.', $e->getMessage()), + $e + ); } return true; } diff --git a/app/code/Magento/GiftMessage/Model/Plugin/OrderSave.php b/app/code/Magento/GiftMessage/Model/Plugin/OrderSave.php index 260780828faba..8cddc0582f13f 100644 --- a/app/code/Magento/GiftMessage/Model/Plugin/OrderSave.php +++ b/app/code/Magento/GiftMessage/Model/Plugin/OrderSave.php @@ -74,7 +74,7 @@ protected function saveOrderGiftMessage(\Magento\Sales\Api\Data\OrderInterface $ $this->giftMessageOrderRepository->save($order->getEntityId(), $giftMessage); } catch (\Exception $e) { throw new CouldNotSaveException( - __('Could not add gift message to order: "%1"', $e->getMessage()), + __('The gift message couldn\'t be added to the "%1" order.', $e->getMessage()), $e ); } @@ -109,7 +109,7 @@ protected function saveOrderItemGiftMessage(\Magento\Sales\Api\Data\OrderInterfa ); } catch (\Exception $e) { throw new CouldNotSaveException( - __('Could not add gift message to order\'s item: "%1"', $e->getMessage()), + __('The gift message couldn\'t be added to the "%1" order item.', $e->getMessage()), $e ); } diff --git a/app/code/Magento/GiftMessage/Setup/InstallData.php b/app/code/Magento/GiftMessage/Setup/Patch/Data/AddGiftMessageAttributes.php similarity index 75% rename from app/code/Magento/GiftMessage/Setup/InstallData.php rename to app/code/Magento/GiftMessage/Setup/Patch/Data/AddGiftMessageAttributes.php index cc181bce56dc1..aed7a4a73edeb 100644 --- a/app/code/Magento/GiftMessage/Setup/InstallData.php +++ b/app/code/Magento/GiftMessage/Setup/Patch/Data/AddGiftMessageAttributes.php @@ -4,54 +4,51 @@ * See COPYING.txt for license details. */ -namespace Magento\GiftMessage\Setup; +namespace Magento\GiftMessage\Setup\Patch\Data; use Magento\Catalog\Setup\CategorySetupFactory; -use Magento\Framework\Setup\InstallDataInterface; -use Magento\Framework\Setup\ModuleContextInterface; -use Magento\Framework\Setup\ModuleDataSetupInterface; use Magento\Quote\Setup\QuoteSetupFactory; use Magento\Sales\Setup\SalesSetupFactory; +use Magento\Framework\App\ResourceConnection; +use Magento\Setup\Model\Patch\DataPatchInterface; +use Magento\Setup\Model\Patch\PatchVersionInterface; -/** - * @codeCoverageIgnore - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) - */ -class InstallData implements InstallDataInterface +class AddGiftMessageAttributes implements DataPatchInterface, PatchVersionInterface { /** - * Category setup factory - * + * @var \Magento\Framework\Setup\ModuleDataSetupInterface + */ + private $moduleDataSetup; + + /** * @var CategorySetupFactory */ - protected $categorySetupFactory; + private $categorySetupFactory; /** - * Quote setup factory - * * @var QuoteSetupFactory */ - protected $quoteSetupFactory; + private $quoteSetupFactory; /** - * Sales setup factory - * * @var SalesSetupFactory */ - protected $salesSetupFactory; + private $salesSetupFactory; /** - * Init - * + * AddGiftMessageAttributes constructor. + * @param \Magento\Framework\Setup\ModuleDataSetupInterface $moduleDataSetup * @param CategorySetupFactory $categorySetupFactory * @param QuoteSetupFactory $quoteSetupFactory * @param SalesSetupFactory $salesSetupFactory */ public function __construct( + \Magento\Framework\Setup\ModuleDataSetupInterface $moduleDataSetup, CategorySetupFactory $categorySetupFactory, QuoteSetupFactory $quoteSetupFactory, SalesSetupFactory $salesSetupFactory ) { + $this->moduleDataSetup = $moduleDataSetup; $this->categorySetupFactory = $categorySetupFactory; $this->quoteSetupFactory = $quoteSetupFactory; $this->salesSetupFactory = $salesSetupFactory; @@ -60,7 +57,7 @@ public function __construct( /** * {@inheritdoc} */ - public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context) + public function apply() { /** * Add 'gift_message_id' attributes for entities @@ -68,22 +65,21 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $options = ['type' => \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, 'visible' => false, 'required' => false]; $entities = ['quote', 'quote_address', 'quote_item', 'quote_address_item']; /** @var \Magento\Quote\Setup\QuoteSetup $quoteSetup */ - $quoteSetup = $this->quoteSetupFactory->create(['setup' => $setup]); + $quoteSetup = $this->quoteSetupFactory->create(['setup' => $this->moduleDataSetup]); foreach ($entities as $entity) { $quoteSetup->addAttribute($entity, 'gift_message_id', $options); } /** @var \Magento\Sales\Setup\SalesSetup $salesSetup */ - $salesSetup = $this->salesSetupFactory->create(['setup' => $setup]); + $salesSetup = $this->salesSetupFactory->create(['setup' => $this->moduleDataSetup]); $salesSetup->addAttribute('order', 'gift_message_id', $options); $salesSetup->addAttribute('order_item', 'gift_message_id', $options); /** * Add 'gift_message_available' attributes for entities */ $salesSetup->addAttribute('order_item', 'gift_message_available', $options); - /** @var \Magento\Catalog\Setup\CategorySetup $catalogSetup */ - $catalogSetup = $this->categorySetupFactory->create(['setup' => $setup]); + $catalogSetup = $this->categorySetupFactory->create(['setup' => $this->moduleDataSetup]); $catalogSetup->addAttribute( \Magento\Catalog\Model\Product::ENTITY, 'gift_message_available', @@ -108,11 +104,9 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface 'is_filterable_in_grid' => false, ] ); - $groupName = 'Autosettings'; $entityTypeId = $catalogSetup->getEntityTypeId(\Magento\Catalog\Model\Product::ENTITY); $attributeSetId = $catalogSetup->getAttributeSetId($entityTypeId, 'Default'); - $attribute = $catalogSetup->getAttribute($entityTypeId, 'gift_message_available'); if ($attribute) { $catalogSetup->addAttributeToGroup( @@ -124,4 +118,28 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ); } } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return []; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.0'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } } diff --git a/app/code/Magento/GiftMessage/Setup/Patch/Data/MoveGiftMessageToGiftOptionsGroup.php b/app/code/Magento/GiftMessage/Setup/Patch/Data/MoveGiftMessageToGiftOptionsGroup.php new file mode 100644 index 0000000000000..f903346db60d2 --- /dev/null +++ b/app/code/Magento/GiftMessage/Setup/Patch/Data/MoveGiftMessageToGiftOptionsGroup.php @@ -0,0 +1,96 @@ +moduleDataSetup = $moduleDataSetup; + $this->categorySetupFactory = $categorySetupFactory; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + $this->moduleDataSetup->getConnection()->startSetup(); + + /** @var \Magento\Catalog\Setup\CategorySetup $categorySetup */ + $categorySetup = $this->categorySetupFactory->create(['setup' => $this->moduleDataSetup]); + $entityTypeId = $categorySetup->getEntityTypeId(Product::ENTITY); + $attributeSetId = $categorySetup->getDefaultAttributeSetId(Product::ENTITY); + $attribute = $categorySetup->getAttribute($entityTypeId, 'gift_message_available'); + + $groupName = 'Gift Options'; + + if (!$categorySetup->getAttributeGroup(Product::ENTITY, $attributeSetId, $groupName)) { + $categorySetup->addAttributeGroup(Product::ENTITY, $attributeSetId, $groupName, 60); + } + $categorySetup->addAttributeToGroup( + $entityTypeId, + $attributeSetId, + $groupName, + $attribute['attribute_id'], + 10 + ); + $this->moduleDataSetup->getConnection()->endSetup(); + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return [ + AddGiftMessageAttributes::class, + ]; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.1'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } +} diff --git a/app/code/Magento/GiftMessage/Setup/Patch/Data/UpdateGiftMessageAttribute.php b/app/code/Magento/GiftMessage/Setup/Patch/Data/UpdateGiftMessageAttribute.php new file mode 100644 index 0000000000000..8337ac3d8967c --- /dev/null +++ b/app/code/Magento/GiftMessage/Setup/Patch/Data/UpdateGiftMessageAttribute.php @@ -0,0 +1,89 @@ +moduleDataSetup = $moduleDataSetup; + $this->categorySetupFactory = $categorySetupFactory; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + $this->moduleDataSetup->getConnection()->startSetup(); + + /** @var \Magento\Catalog\Setup\CategorySetup $categorySetup */ + $categorySetup = $this->categorySetupFactory->create(['setup' => $this->moduleDataSetup]); + $entityTypeId = $categorySetup->getEntityTypeId(Product::ENTITY); + $attribute = $categorySetup->getAttribute($entityTypeId, 'gift_message_available'); + $categorySetup->updateAttribute( + $entityTypeId, + $attribute['attribute_id'], + 'source_model', + \Magento\Catalog\Model\Product\Attribute\Source\Boolean::class + ); + $this->moduleDataSetup->getConnection()->endSetup(); + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return [ + MoveGiftMessageToGiftOptionsGroup::class + ]; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.1.0'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } +} diff --git a/app/code/Magento/GiftMessage/Setup/UpgradeData.php b/app/code/Magento/GiftMessage/Setup/UpgradeData.php deleted file mode 100644 index 36ceb94961608..0000000000000 --- a/app/code/Magento/GiftMessage/Setup/UpgradeData.php +++ /dev/null @@ -1,71 +0,0 @@ -categorySetupFactory = $categorySetupFactory; - } - - /** - * {@inheritdoc} - */ - public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context) - { - $setup->startSetup(); - - /** @var \Magento\Catalog\Setup\CategorySetup $categorySetup */ - $categorySetup = $this->categorySetupFactory->create(['setup' => $setup]); - $entityTypeId = $categorySetup->getEntityTypeId(Product::ENTITY); - $attributeSetId = $categorySetup->getDefaultAttributeSetId(Product::ENTITY); - $attribute = $categorySetup->getAttribute($entityTypeId, 'gift_message_available'); - - if (version_compare($context->getVersion(), '2.0.1', '<')) { - $groupName = 'Gift Options'; - - if (!$categorySetup->getAttributeGroup(Product::ENTITY, $attributeSetId, $groupName)) { - $categorySetup->addAttributeGroup(Product::ENTITY, $attributeSetId, $groupName, 60); - } - - $categorySetup->addAttributeToGroup( - $entityTypeId, - $attributeSetId, - $groupName, - $attribute['attribute_id'], - 10 - ); - } - - if (version_compare($context->getVersion(), '2.1.0', '<')) { - $categorySetup->updateAttribute( - $entityTypeId, - $attribute['attribute_id'], - 'source_model', - \Magento\Catalog\Model\Product\Attribute\Source\Boolean::class - ); - } - - $setup->endSetup(); - } -} diff --git a/app/code/Magento/GiftMessage/Test/Unit/Model/CartRepositoryTest.php b/app/code/Magento/GiftMessage/Test/Unit/Model/CartRepositoryTest.php index b013b4a6de7b4..e41cb48550176 100644 --- a/app/code/Magento/GiftMessage/Test/Unit/Model/CartRepositoryTest.php +++ b/app/code/Magento/GiftMessage/Test/Unit/Model/CartRepositoryTest.php @@ -4,6 +4,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\GiftMessage\Test\Unit\Model; use Magento\GiftMessage\Model\CartRepository; @@ -134,7 +135,7 @@ public function testGet() /** * @expectedException \Magento\Framework\Exception\InputException - * @expectedExceptionMessage Gift Messages are not applicable for empty cart + * @expectedExceptionMessage Gift messages can't be used for an empty cart. Add an item and try again. */ public function testSaveWithInputException() { @@ -144,7 +145,7 @@ public function testSaveWithInputException() /** * @expectedException \Magento\Framework\Exception\State\InvalidTransitionException - * @expectedExceptionMessage Gift Messages are not applicable for virtual products + * @expectedExceptionMessage Gift messages can't be used for virtual products. */ public function testSaveWithInvalidTransitionException() { diff --git a/app/code/Magento/GiftMessage/Test/Unit/Model/GiftMessageManagerTest.php b/app/code/Magento/GiftMessage/Test/Unit/Model/GiftMessageManagerTest.php index a70a946e77fe5..5956a4f5a1f15 100644 --- a/app/code/Magento/GiftMessage/Test/Unit/Model/GiftMessageManagerTest.php +++ b/app/code/Magento/GiftMessage/Test/Unit/Model/GiftMessageManagerTest.php @@ -312,7 +312,7 @@ public function testAddWithQuoteAddressItem() /** * @expectedException \Magento\Framework\Exception\CouldNotSaveException - * @expectedExceptionMessage Could not add gift message to shopping cart + * @expectedExceptionMessage The gift message couldn't be added to Cart. */ public function testSetMessageCouldNotAddGiftMessageException() { diff --git a/app/code/Magento/GiftMessage/Test/Unit/Model/GuestItemRepositoryTest.php b/app/code/Magento/GiftMessage/Test/Unit/Model/GuestItemRepositoryTest.php index f9985a1f92daa..fab9f961f1e4c 100644 --- a/app/code/Magento/GiftMessage/Test/Unit/Model/GuestItemRepositoryTest.php +++ b/app/code/Magento/GiftMessage/Test/Unit/Model/GuestItemRepositoryTest.php @@ -4,6 +4,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\GiftMessage\Test\Unit\Model; use Magento\GiftMessage\Model\ItemRepository; @@ -115,7 +116,7 @@ protected function setUp() /** * @expectedException \Magento\Framework\Exception\NoSuchEntityException - * @expectedExceptionMessage There is no item with provided id in the cart + * @expectedExceptionMessage No item with the provided ID was found in the Cart. Verify the ID and try again. */ public function testGetWithNoSuchEntityException() { @@ -163,20 +164,22 @@ public function testGet() /** * @expectedException \Magento\Framework\Exception\NoSuchEntityException - * @expectedExceptionMessage There is no product with provided itemId: 1 in the cart */ public function testSaveWithNoSuchEntityException() { $itemId = 1; $this->quoteMock->expects($this->once())->method('getItemById')->with($itemId)->will($this->returnValue(null)); - $this->itemRepository->save($this->cartId, $this->messageMock, $itemId); + + $this->expectExceptionMessage( + 'No product with the "1" itemId exists in the Cart. Verify your information and try again.' + ); } /** * @expectedException \Magento\Framework\Exception\State\InvalidTransitionException - * @expectedExceptionMessage Gift Messages are not applicable for virtual products + * @expectedExceptionMessage Gift messages can't be used for virtual products. */ public function testSaveWithInvalidTransitionException() { diff --git a/app/code/Magento/GiftMessage/Test/Unit/Model/ItemRepositoryTest.php b/app/code/Magento/GiftMessage/Test/Unit/Model/ItemRepositoryTest.php index 9b0970a3ae2ea..589dcaf2154fc 100644 --- a/app/code/Magento/GiftMessage/Test/Unit/Model/ItemRepositoryTest.php +++ b/app/code/Magento/GiftMessage/Test/Unit/Model/ItemRepositoryTest.php @@ -4,6 +4,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\GiftMessage\Test\Unit\Model; use Magento\GiftMessage\Model\ItemRepository; @@ -115,7 +116,7 @@ protected function setUp() /** * @expectedException \Magento\Framework\Exception\NoSuchEntityException - * @expectedExceptionMessage There is no item with provided id in the cart + * @expectedExceptionMessage No item with the provided ID was found in the Cart. Verify the ID and try again. */ public function testGetWithNoSuchEntityException() { @@ -163,20 +164,22 @@ public function testGet() /** * @expectedException \Magento\Framework\Exception\NoSuchEntityException - * @expectedExceptionMessage There is no product with provided itemId: 1 in the cart */ public function testSaveWithNoSuchEntityException() { $itemId = 1; $this->quoteMock->expects($this->once())->method('getItemById')->with($itemId)->will($this->returnValue(null)); - $this->itemRepository->save($this->cartId, $this->messageMock, $itemId); + + $this->expectExceptionMessage( + 'No product with the "1" itemId exists in the Cart. Verify your information and try again.' + ); } /** * @expectedException \Magento\Framework\Exception\State\InvalidTransitionException - * @expectedExceptionMessage Gift Messages are not applicable for virtual products + * @expectedExceptionMessage Gift messages can't be used for virtual products. */ public function testSaveWithInvalidTransitionException() { diff --git a/app/code/Magento/GiftMessage/Test/Unit/Model/OrderItemRepositoryTest.php b/app/code/Magento/GiftMessage/Test/Unit/Model/OrderItemRepositoryTest.php index d6847259dbe5c..ae85e32eceeb6 100644 --- a/app/code/Magento/GiftMessage/Test/Unit/Model/OrderItemRepositoryTest.php +++ b/app/code/Magento/GiftMessage/Test/Unit/Model/OrderItemRepositoryTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\GiftMessage\Test\Unit\Model; use Magento\Framework\Exception\NoSuchEntityException; @@ -169,7 +170,10 @@ public function testGetNoSuchEntityExceptionOnGetItemById() $this->orderItemRepository->get($orderId, $orderItemId); $this->fail('Expected NoSuchEntityException not caught'); } catch (NoSuchEntityException $exception) { - $this->assertEquals('There is no item with provided id in the order', $exception->getMessage()); + $this->assertEquals( + 'No item with the provided ID was found in the Order. Verify the ID and try again.', + $exception->getMessage() + ); } } @@ -206,7 +210,8 @@ public function testGetNoSuchEntityExceptionOnIsMessageAllowed() $this->fail('Expected NoSuchEntityException not caught'); } catch (NoSuchEntityException $exception) { $this->assertEquals( - 'There is no item with provided id in the order or gift message isn\'t allowed', + "No item with the provided ID was found in the Order, or a gift message isn't allowed. " + . "Verify and try again.", $exception->getMessage() ); } @@ -248,7 +253,10 @@ public function testGetNoSuchEntityExceptionOnGetGiftMessageId() $this->orderItemRepository->get($orderId, $orderItemId); $this->fail('Expected NoSuchEntityException not caught'); } catch (NoSuchEntityException $exception) { - $this->assertEquals('There is no item with provided id in the order', $exception->getMessage()); + $this->assertEquals( + 'No item with the provided ID was found in the Order. Verify the ID and try again.', + $exception->getMessage() + ); } } @@ -336,7 +344,10 @@ public function testSaveNoSuchEntityException() $this->orderItemRepository->save($orderId, $orderItemId, $messageMock); $this->fail('Expected NoSuchEntityException not caught'); } catch (NoSuchEntityException $exception) { - $this->assertEquals('There is no item with provided id in the order', $exception->getMessage()); + $this->assertEquals( + 'No item with the provided ID was found in the Order. Verify the ID and try again.', + $exception->getMessage() + ); } } @@ -375,7 +386,7 @@ public function testSaveInvalidTransitionException() $this->orderItemRepository->save($orderId, $orderItemId, $messageMock); $this->fail('Expected InvalidTransitionException not caught'); } catch (InvalidTransitionException $exception) { - $this->assertEquals('Gift Messages are not applicable for virtual products', $exception->getMessage()); + $this->assertEquals("Gift messages can't be used for virtual products.", $exception->getMessage()); } } @@ -418,7 +429,7 @@ public function testSaveCouldNotSaveException() $this->orderItemRepository->save($orderId, $orderItemId, $messageMock); $this->fail('Expected CouldNotSaveException not caught'); } catch (CouldNotSaveException $exception) { - $this->assertEquals('Gift Message is not available', $exception->getMessage()); + $this->assertEquals("The gift message isn't available.", $exception->getMessage()); } } @@ -482,7 +493,7 @@ public function testSaveCouldNotSaveExceptionOnSaveAllInOrder() $this->fail('Expected CouldNotSaveException not caught'); } catch (CouldNotSaveException $exception) { $this->assertEquals( - 'Could not add gift message to order: "' . $excep->getMessage() . '"', + 'The gift message couldn\'t be added to the "' . $excep->getMessage() . '" order.', $exception->getMessage() ); } diff --git a/app/code/Magento/GiftMessage/Test/Unit/Model/Plugin/OrderSaveTest.php b/app/code/Magento/GiftMessage/Test/Unit/Model/Plugin/OrderSaveTest.php index ec8a8841f6477..2170864407ea4 100644 --- a/app/code/Magento/GiftMessage/Test/Unit/Model/Plugin/OrderSaveTest.php +++ b/app/code/Magento/GiftMessage/Test/Unit/Model/Plugin/OrderSaveTest.php @@ -128,7 +128,7 @@ public function testAfterSaveGiftMessages() /** * @expectedException \Magento\Framework\Exception\CouldNotSaveException - * @expectedMessage Could not add gift message to order:Test message + * @expectedMessage The gift message couldn't be added to the "Test message" order. */ public function testAfterSaveIfGiftMessagesNotExist() { @@ -155,7 +155,7 @@ public function testAfterSaveIfGiftMessagesNotExist() /** * @expectedException \Magento\Framework\Exception\CouldNotSaveException - * @expectedMessage Could not add gift message to order:Test message + * @expectedMessage The gift message couldn't be added to the "Test message" order. */ public function testAfterSaveIfItemGiftMessagesNotExist() { diff --git a/app/code/Magento/GiftMessage/etc/module.xml b/app/code/Magento/GiftMessage/etc/module.xml index bb4ea1dbc2ee6..893045cb0c649 100644 --- a/app/code/Magento/GiftMessage/etc/module.xml +++ b/app/code/Magento/GiftMessage/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/GoogleAdwords/etc/module.xml b/app/code/Magento/GoogleAdwords/etc/module.xml index ee582ec6304c6..90399bd1c3cfb 100644 --- a/app/code/Magento/GoogleAdwords/etc/module.xml +++ b/app/code/Magento/GoogleAdwords/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/GoogleAnalytics/etc/module.xml b/app/code/Magento/GoogleAnalytics/etc/module.xml index bd401c26f391a..494ec7a23425d 100644 --- a/app/code/Magento/GoogleAnalytics/etc/module.xml +++ b/app/code/Magento/GoogleAnalytics/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/GoogleOptimizer/etc/module.xml b/app/code/Magento/GoogleOptimizer/etc/module.xml index 25d7462587cb6..2ceff61f59dbd 100644 --- a/app/code/Magento/GoogleOptimizer/etc/module.xml +++ b/app/code/Magento/GoogleOptimizer/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/GraphQl/etc/module.xml b/app/code/Magento/GraphQl/etc/module.xml index b8cd9138da4ed..4d8b2090a8514 100644 --- a/app/code/Magento/GraphQl/etc/module.xml +++ b/app/code/Magento/GraphQl/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/GroupedImportExport/etc/module.xml b/app/code/Magento/GroupedImportExport/etc/module.xml index a0518abc4660e..4274acded9f22 100644 --- a/app/code/Magento/GroupedImportExport/etc/module.xml +++ b/app/code/Magento/GroupedImportExport/etc/module.xml @@ -6,6 +6,6 @@ */ --> - + diff --git a/app/code/Magento/GroupedProduct/Setup/InstallData.php b/app/code/Magento/GroupedProduct/Setup/Patch/Data/InitializeGroupedProductLinks.php similarity index 53% rename from app/code/Magento/GroupedProduct/Setup/InstallData.php rename to app/code/Magento/GroupedProduct/Setup/Patch/Data/InitializeGroupedProductLinks.php index f58cd65785420..757d02b6f3a0f 100644 --- a/app/code/Magento/GroupedProduct/Setup/InstallData.php +++ b/app/code/Magento/GroupedProduct/Setup/Patch/Data/InitializeGroupedProductLinks.php @@ -4,37 +4,48 @@ * See COPYING.txt for license details. */ -namespace Magento\GroupedProduct\Setup; +namespace Magento\GroupedProduct\Setup\Patch\Data; use Magento\Catalog\Model\Product; use Magento\Eav\Setup\EavSetup; use Magento\Eav\Setup\EavSetupFactory; -use Magento\Framework\Setup\InstallDataInterface; -use Magento\Framework\Setup\ModuleContextInterface; -use Magento\Framework\Setup\ModuleDataSetupInterface; +use Magento\Framework\App\ResourceConnection; +use Magento\Setup\Model\Patch\DataPatchInterface; +use Magento\Setup\Model\Patch\PatchVersionInterface; /** - * @codeCoverageIgnore + * Class InitializeGroupedProductLinks + * @package Magento\GroupedProduct\Setup\Patch */ -class InstallData implements InstallDataInterface +class InitializeGroupedProductLinks implements DataPatchInterface, PatchVersionInterface { + /** + * @var \Magento\Framework\Setup\ModuleDataSetupInterface + */ + private $moduleDataSetup; + /** * @var EavSetupFactory */ private $eavSetupFactory; /** + * InitializeGroupedProductLinks constructor. + * @param \Magento\Framework\Setup\ModuleDataSetupInterface $moduleDataSetup * @param EavSetupFactory $eavSetupFactory */ - public function __construct(EavSetupFactory $eavSetupFactory) - { + public function __construct( + \Magento\Framework\Setup\ModuleDataSetupInterface $moduleDataSetup, + EavSetupFactory $eavSetupFactory + ) { + $this->moduleDataSetup = $moduleDataSetup; $this->eavSetupFactory = $eavSetupFactory; } /** * {@inheritdoc} */ - public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context) + public function apply() { /** * Install grouped product link type @@ -43,23 +54,24 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface 'link_type_id' => \Magento\GroupedProduct\Model\ResourceModel\Product\Link::LINK_TYPE_GROUPED, 'code' => 'super', ]; - $setup->getConnection() - ->insertOnDuplicate($setup->getTable('catalog_product_link_type'), $data); + $this->moduleDataSetup->getConnection()->insertOnDuplicate( + $this->moduleDataSetup->getTable('catalog_product_link_type'), + $data + ); /** * Install grouped product link attributes */ - $select = $setup->getConnection() + $select = $this->moduleDataSetup->getConnection() ->select() ->from( - ['c' => $setup->getTable('catalog_product_link_attribute')] + ['c' => $this->moduleDataSetup->getTable('catalog_product_link_attribute')] ) ->where( "c.link_type_id=?", \Magento\GroupedProduct\Model\ResourceModel\Product\Link::LINK_TYPE_GROUPED ); - $result = $setup->getConnection()->fetchAll($select); - + $result = $this->moduleDataSetup->getConnection()->fetchAll($select); if (!$result) { $data = [ [ @@ -73,12 +85,13 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface 'data_type' => 'decimal' ], ]; - - $setup->getConnection()->insertMultiple($setup->getTable('catalog_product_link_attribute'), $data); + $this->moduleDataSetup->getConnection()->insertMultiple( + $this->moduleDataSetup->getTable('catalog_product_link_attribute'), + $data + ); } - /** @var EavSetup $eavSetup */ - $eavSetup = $this->eavSetupFactory->create(['setup' => $setup]); + $eavSetup = $this->eavSetupFactory->create(['setup' => $this->moduleDataSetup]); $field = 'country_of_manufacture'; $applyTo = explode(',', $eavSetup->getAttribute(Product::ENTITY, $field, 'apply_to')); if (!in_array('grouped', $applyTo)) { @@ -86,4 +99,28 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $eavSetup->updateAttribute(Product::ENTITY, $field, 'apply_to', implode(',', $applyTo)); } } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return []; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.0'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } } diff --git a/app/code/Magento/GroupedProduct/Setup/Patch/Data/UpdateProductRelations.php b/app/code/Magento/GroupedProduct/Setup/Patch/Data/UpdateProductRelations.php new file mode 100644 index 0000000000000..403be33a8b499 --- /dev/null +++ b/app/code/Magento/GroupedProduct/Setup/Patch/Data/UpdateProductRelations.php @@ -0,0 +1,96 @@ +moduleDataSetup = $moduleDataSetup; + $this->relationProcessor = $relationProcessor; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + $this->moduleDataSetup->getConnection()->startSetup(); + + $connection = $this->moduleDataSetup->getConnection(); + $select = $connection->select() + ->from( + $this->relationProcessor->getTable('catalog_product_link'), + ['product_id', 'linked_product_id'] + ) + ->where('link_type_id = ?', Link::LINK_TYPE_GROUPED); + + $connection->query( + $connection->insertFromSelect( + $select, + $this->relationProcessor->getMainTable(), + ['parent_id', 'child_id'], + AdapterInterface::INSERT_IGNORE + ) + ); + + $this->moduleDataSetup->getConnection()->endSetup(); + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return [ + InitializeGroupedProductLinks::class + ]; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.1'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } +} diff --git a/app/code/Magento/GroupedProduct/Setup/UpgradeData.php b/app/code/Magento/GroupedProduct/Setup/UpgradeData.php deleted file mode 100644 index 85abe8c414eb0..0000000000000 --- a/app/code/Magento/GroupedProduct/Setup/UpgradeData.php +++ /dev/null @@ -1,59 +0,0 @@ -relationProcessor = $relationProcessor; - } - - /** - * {@inheritdoc} - */ - public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context) - { - $setup->startSetup(); - - if (version_compare($context->getVersion(), '2.0.1', '<')) { - $connection = $setup->getConnection(); - $select = $connection->select() - ->from( - $this->relationProcessor->getTable('catalog_product_link'), - ['product_id', 'linked_product_id'] - ) - ->where('link_type_id = ?', Link::LINK_TYPE_GROUPED); - - $connection->query( - $connection->insertFromSelect( - $select, - $this->relationProcessor->getMainTable(), - ['parent_id', 'child_id'], - AdapterInterface::INSERT_IGNORE - ) - ); - } - - $setup->endSetup(); - } -} diff --git a/app/code/Magento/GroupedProduct/etc/module.xml b/app/code/Magento/GroupedProduct/etc/module.xml index b5aa60db102a2..c1c1e902faab0 100644 --- a/app/code/Magento/GroupedProduct/etc/module.xml +++ b/app/code/Magento/GroupedProduct/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/GroupedProductGraphQl/etc/module.xml b/app/code/Magento/GroupedProductGraphQl/etc/module.xml index f21eb8577db31..5482cf54ba014 100644 --- a/app/code/Magento/GroupedProductGraphQl/etc/module.xml +++ b/app/code/Magento/GroupedProductGraphQl/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/ImportExport/etc/module.xml b/app/code/Magento/ImportExport/etc/module.xml index 1ade855bc3a8d..afbe57df9558b 100644 --- a/app/code/Magento/ImportExport/etc/module.xml +++ b/app/code/Magento/ImportExport/etc/module.xml @@ -6,6 +6,6 @@ */ --> - + diff --git a/app/code/Magento/Indexer/Console/Command/IndexerReindexCommand.php b/app/code/Magento/Indexer/Console/Command/IndexerReindexCommand.php index 43065ada77271..6eab92f65117a 100644 --- a/app/code/Magento/Indexer/Console/Command/IndexerReindexCommand.php +++ b/app/code/Magento/Indexer/Console/Command/IndexerReindexCommand.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Indexer\Console\Command; use Magento\Framework\Console\Cli; @@ -237,7 +238,9 @@ private function getIndexerIdsBySharedIndex($sharedIndex) private function validateSharedIndex($sharedIndex) { if (empty($sharedIndex)) { - throw new \InvalidArgumentException('sharedIndex must be a valid shared index identifier'); + throw new \InvalidArgumentException( + 'The sharedIndex is an invalid shared index identifier. Verify the identifier and try again.' + ); } $indexerIds = $this->getIndexerIdsBySharedIndex($sharedIndex); if (empty($indexerIds)) { diff --git a/app/code/Magento/Indexer/Setup/InstallData.php b/app/code/Magento/Indexer/Setup/Patch/Data/InitializeIndexerState.php similarity index 68% rename from app/code/Magento/Indexer/Setup/InstallData.php rename to app/code/Magento/Indexer/Setup/Patch/Data/InitializeIndexerState.php index 98a49d6799b13..fdb9b28ea0b32 100644 --- a/app/code/Magento/Indexer/Setup/InstallData.php +++ b/app/code/Magento/Indexer/Setup/Patch/Data/InitializeIndexerState.php @@ -4,33 +4,41 @@ * See COPYING.txt for license details. */ -namespace Magento\Indexer\Setup; +namespace Magento\Indexer\Setup\Patch\Data; use Magento\Framework\Encryption\Encryptor; use Magento\Framework\Encryption\EncryptorInterface; use Magento\Framework\Indexer\StateInterface; use Magento\Framework\Json\EncoderInterface; -use Magento\Framework\Setup\ModuleContextInterface; -use Magento\Framework\Setup\ModuleDataSetupInterface; use Magento\Framework\Indexer\ConfigInterface; use Magento\Indexer\Model\ResourceModel\Indexer\State\CollectionFactory; use Magento\Indexer\Model\Indexer\State; use Magento\Indexer\Model\Indexer\StateFactory; -use Magento\Framework\Setup\InstallDataInterface; +use Magento\Framework\App\ResourceConnection; +use Magento\Setup\Model\Patch\DataPatchInterface; +use Magento\Setup\Model\Patch\PatchVersionInterface; /** - * @codeCoverageIgnore - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * Class InitializeIndexerState + * @package Magento\Indexer\Setup\Patch */ -class InstallData implements InstallDataInterface +class InitializeIndexerState implements DataPatchInterface, PatchVersionInterface { /** - * Indexer collection factory - * + * @var \Magento\Framework\Setup\ModuleDataSetupInterface + */ + private $moduleDataSetup; + + /** * @var CollectionFactory */ private $statesFactory; + /** + * @var StateFactory + */ + private $stateFactory; + /** * @var ConfigInterface */ @@ -47,41 +55,29 @@ class InstallData implements InstallDataInterface private $encoder; /** - * @var StateFactory - */ - private $stateFactory; - - /** - * Init - * - * @param CollectionFactory $statesFactory - * @param StateFactory $stateFactory - * @param ConfigInterface $config - * @param EncryptorInterface $encryptor - * @param EncoderInterface $encoder - * @internal param StateFactory $stateFactory + * PatchInitial constructor. + * @param \Magento\Framework\Setup\ModuleDataSetupInterface $moduleDataSetup */ public function __construct( + \Magento\Framework\Setup\ModuleDataSetupInterface $moduleDataSetup, CollectionFactory $statesFactory, StateFactory $stateFactory, ConfigInterface $config, EncryptorInterface $encryptor, EncoderInterface $encoder ) { + $this->moduleDataSetup = $moduleDataSetup; $this->statesFactory = $statesFactory; + $this->stateFactory = $stateFactory; $this->config = $config; $this->encryptor = $encryptor; $this->encoder = $encoder; - $this->stateFactory = $stateFactory; } /** * {@inheritdoc} - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - * @SuppressWarnings(PHPMD.ExcessiveMethodLength) - * @SuppressWarnings(PHPMD.NPathComplexity) */ - public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context) + public function apply() { /** @var State[] $stateIndexers */ $stateIndexers = []; @@ -106,4 +102,28 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface } } } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return []; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.1.0'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } } diff --git a/app/code/Magento/Indexer/etc/module.xml b/app/code/Magento/Indexer/etc/module.xml index 914e2835c0a61..cd84bb9cf2157 100644 --- a/app/code/Magento/Indexer/etc/module.xml +++ b/app/code/Magento/Indexer/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/InstantPurchase/Model/InstantPurchaseOption.php b/app/code/Magento/InstantPurchase/Model/InstantPurchaseOption.php index a780d9716bd94..214b93560669f 100644 --- a/app/code/Magento/InstantPurchase/Model/InstantPurchaseOption.php +++ b/app/code/Magento/InstantPurchase/Model/InstantPurchaseOption.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\InstantPurchase\Model; use Magento\Customer\Model\Address; @@ -101,7 +102,9 @@ public function isAvailable(): bool public function getPaymentToken(): PaymentTokenInterface { if (!isset($this->paymentToken)) { - throw new LocalizedException(__('Payment method is not defined for instance purchase.')); + throw new LocalizedException( + __("A payment method isn't defined for instance purchase. Verify and try again.") + ); } return $this->paymentToken; } diff --git a/app/code/Magento/InstantPurchase/etc/module.xml b/app/code/Magento/InstantPurchase/etc/module.xml index 462786b2d6ae6..ec647edf6f220 100644 --- a/app/code/Magento/InstantPurchase/etc/module.xml +++ b/app/code/Magento/InstantPurchase/etc/module.xml @@ -6,5 +6,5 @@ */ --> - + diff --git a/app/code/Magento/Integration/Controller/Adminhtml/Integration/Save.php b/app/code/Magento/Integration/Controller/Adminhtml/Integration/Save.php index dfddd8b954bd3..cb2fcb2ba0e29 100644 --- a/app/code/Magento/Integration/Controller/Adminhtml/Integration/Save.php +++ b/app/code/Magento/Integration/Controller/Adminhtml/Integration/Save.php @@ -56,7 +56,7 @@ public function execute() return; } if ($integrationData[Info::DATA_SETUP_TYPE] == IntegrationModel::TYPE_CONFIG) { - throw new LocalizedException(__('Cannot edit integrations created via config file.')); + throw new LocalizedException(__("The integrations created in the config file can't be edited.")); } } $this->validateUser(); diff --git a/app/code/Magento/Integration/Controller/Adminhtml/Integration/TokensExchange.php b/app/code/Magento/Integration/Controller/Adminhtml/Integration/TokensExchange.php index e295198766501..a49561dd95ade 100644 --- a/app/code/Magento/Integration/Controller/Adminhtml/Integration/TokensExchange.php +++ b/app/code/Magento/Integration/Controller/Adminhtml/Integration/TokensExchange.php @@ -4,6 +4,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Integration\Controller\Adminhtml\Integration; use Magento\Integration\Model\Integration as IntegrationModel; @@ -57,7 +58,10 @@ public function execute() $consumer = $this->_oauthService->loadConsumer($integration->getConsumerId()); if (!$consumer->getId()) { throw new \Magento\Framework\Oauth\Exception( - __('A consumer with ID %1 does not exist', $integration->getConsumerId()) + __( + 'A consumer with "%1" ID doesn\'t exist. Verify the ID and try again.', + $integration->getConsumerId() + ) ); } /** Initialize response body */ diff --git a/app/code/Magento/Integration/Model/AdminTokenService.php b/app/code/Magento/Integration/Model/AdminTokenService.php index 080181b5d8d61..5a030325e9fbd 100644 --- a/app/code/Magento/Integration/Model/AdminTokenService.php +++ b/app/code/Magento/Integration/Model/AdminTokenService.php @@ -87,7 +87,10 @@ public function createAdminAccessToken($username, $password) * Need to make sure that this is refactored once exception handling is updated in Auth Model. */ throw new AuthenticationException( - __('You did not sign in correctly or your account is temporarily disabled.') + __( + 'The account sign-in was incorrect or your account is disabled temporarily. ' + . 'Please wait and try again later.' + ) ); } $this->getRequestThrottler()->resetAuthenticationFailuresCount($username, RequestThrottler::USER_TYPE_ADMIN); @@ -114,7 +117,7 @@ public function revokeAdminAccessToken($adminId) $token->delete(); } } catch (\Exception $e) { - throw new LocalizedException(__('The tokens could not be revoked.')); + throw new LocalizedException(__("The tokens couldn't be revoked.")); } return true; } diff --git a/app/code/Magento/Integration/Model/AuthorizationService.php b/app/code/Magento/Integration/Model/AuthorizationService.php index 1375116bd96d4..b51f1a773b8a7 100644 --- a/app/code/Magento/Integration/Model/AuthorizationService.php +++ b/app/code/Magento/Integration/Model/AuthorizationService.php @@ -104,7 +104,7 @@ public function grantPermissions($integrationId, $resources) } catch (\Exception $e) { $this->_logger->critical($e); throw new LocalizedException( - __('Sorry, something went wrong granting permissions. You can find out more in the exceptions log.') + __('An error occurred during the attempt to grant permissions. For details, see the exceptions log.') ); } } diff --git a/app/code/Magento/Integration/Model/CredentialsValidator.php b/app/code/Magento/Integration/Model/CredentialsValidator.php index d736a1f490063..f058d5ac77bd8 100644 --- a/app/code/Magento/Integration/Model/CredentialsValidator.php +++ b/app/code/Magento/Integration/Model/CredentialsValidator.php @@ -25,10 +25,10 @@ public function validate($username, $password) { $exception = new InputException(); if (!is_string($username) || strlen($username) == 0) { - $exception->addError(__('%fieldName is a required field.', ['fieldName' => 'username'])); + $exception->addError(__('"%fieldName" is required. Enter and try again.', ['fieldName' => 'username'])); } if (!is_string($password) || strlen($password) == 0) { - $exception->addError(__('%fieldName is a required field.', ['fieldName' => 'password'])); + $exception->addError(__('"%fieldName" is required. Enter and try again.', ['fieldName' => 'password'])); } if ($exception->wasErrorAdded()) { throw $exception; diff --git a/app/code/Magento/Integration/Model/CustomerTokenService.php b/app/code/Magento/Integration/Model/CustomerTokenService.php index 947ca6f9f8821..3c245804a9f6e 100644 --- a/app/code/Magento/Integration/Model/CustomerTokenService.php +++ b/app/code/Magento/Integration/Model/CustomerTokenService.php @@ -80,7 +80,10 @@ public function createCustomerAccessToken($username, $password) } catch (\Exception $e) { $this->getRequestThrottler()->logAuthenticationFailure($username, RequestThrottler::USER_TYPE_CUSTOMER); throw new AuthenticationException( - __('You did not sign in correctly or your account is temporarily disabled.') + __( + 'The account sign-in was incorrect or your account is disabled temporarily. ' + . 'Please wait and try again later.' + ) ); } $this->getRequestThrottler()->resetAuthenticationFailuresCount($username, RequestThrottler::USER_TYPE_CUSTOMER); @@ -107,7 +110,7 @@ public function revokeCustomerAccessToken($customerId) $token->delete(); } } catch (\Exception $e) { - throw new LocalizedException(__('The tokens could not be revoked.')); + throw new LocalizedException(__("The tokens couldn't be revoked.")); } return true; } diff --git a/app/code/Magento/Integration/Model/IntegrationService.php b/app/code/Magento/Integration/Model/IntegrationService.php index 6acb692273957..9818d76c94456 100644 --- a/app/code/Magento/Integration/Model/IntegrationService.php +++ b/app/code/Magento/Integration/Model/IntegrationService.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Integration\Model; use Magento\Integration\Model\Integration as IntegrationModel; @@ -129,7 +130,7 @@ private function _checkIntegrationByName($name) { $integration = $this->_integrationFactory->create()->load($name, 'name'); if ($integration->getId()) { - throw new IntegrationException(__('Integration with name \'%1\' exists.', $name)); + throw new IntegrationException(__('The integration with name "%1" exists.', $name)); } } @@ -144,7 +145,7 @@ protected function _loadIntegrationById($integrationId) { $integration = $this->_integrationFactory->create()->load($integrationId); if (!$integration->getId()) { - throw new IntegrationException(__('Integration with ID \'%1\' does not exist.', $integrationId)); + throw new IntegrationException(__('The integration with ID "%1" doesn\'t exist.', $integrationId)); } return $integration; } diff --git a/app/code/Magento/Integration/Model/Oauth/Token/Provider.php b/app/code/Magento/Integration/Model/Oauth/Token/Provider.php index c43118b4f76d6..cc8c40be4bc63 100644 --- a/app/code/Magento/Integration/Model/Oauth/Token/Provider.php +++ b/app/code/Magento/Integration/Model/Oauth/Token/Provider.php @@ -258,7 +258,7 @@ protected function _getToken($token) { if (!$this->validateOauthToken($token)) { throw new \Magento\Framework\Oauth\Exception( - __('Token is not the correct length') + __('The token length is invalid. Check the length and try again.') ); } diff --git a/app/code/Magento/Integration/Model/Oauth/Token/RequestThrottler.php b/app/code/Magento/Integration/Model/Oauth/Token/RequestThrottler.php index 9af6510d0930e..9ec907a657c92 100644 --- a/app/code/Magento/Integration/Model/Oauth/Token/RequestThrottler.php +++ b/app/code/Magento/Integration/Model/Oauth/Token/RequestThrottler.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Integration\Model\Oauth\Token; use Magento\Integration\Model\Oauth\Token\RequestLog\ReaderInterface as RequestLogReader; @@ -65,7 +66,10 @@ public function throttle($userName, $userType) $count = $this->requestLogReader->getFailuresCount($userName, $userType); if ($count >= $this->requestLogConfig->getMaxFailuresCount()) { throw new AuthenticationException( - __('You did not sign in correctly or your account is temporarily disabled.') + __( + 'The account sign-in was incorrect or your account is disabled temporarily. ' + . 'Please wait and try again later.' + ) ); } } diff --git a/app/code/Magento/Integration/Model/OauthService.php b/app/code/Magento/Integration/Model/OauthService.php index 859f3815d0702..03aaf27319c0c 100644 --- a/app/code/Magento/Integration/Model/OauthService.php +++ b/app/code/Magento/Integration/Model/OauthService.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Integration\Model; use Magento\Framework\Oauth\Helper\Oauth as OauthHelper; @@ -129,7 +130,9 @@ public function createConsumer($consumerData) throw $exception; } catch (\Exception $exception) { throw new \Magento\Framework\Oauth\Exception( - __('Unexpected error. Unable to create oAuth consumer account.') + __( + "The oAuth consumer account couldn't be created due to an unexpected error. Please try again later." + ) ); } } @@ -186,7 +189,7 @@ public function loadConsumer($consumerId) throw $exception; } catch (\Exception $exception) { throw new \Magento\Framework\Oauth\Exception( - __('Unexpected error. Unable to load oAuth consumer account.') + __("The oAuth consumer account couldn't be loaded due to an unexpected error. Please try again later.") ); } } @@ -202,7 +205,7 @@ public function loadConsumerByKey($key) throw $exception; } catch (\Exception $exception) { throw new \Magento\Framework\Oauth\Exception( - __('Unexpected error. Unable to load oAuth consumer account.') + __("The oAuth consumer account couldn't be loaded due to an unexpected error. Please try again later.") ); } } @@ -218,7 +221,7 @@ public function postToConsumer($consumerId, $endpointUrl) $consumer->save(); if (!$consumer->getId()) { throw new \Magento\Framework\Oauth\Exception( - __('A consumer with ID %1 does not exist', $consumerId) + __('A consumer with "%1" ID doesn\'t exist. Verify the ID and try again.', $consumerId) ); } $consumerData = $consumer->getData(); @@ -245,7 +248,7 @@ public function postToConsumer($consumerId, $endpointUrl) } catch (\Exception $exception) { $this->_logger->critical($exception); throw new \Magento\Framework\Oauth\Exception( - __('Unable to post data to consumer due to an unexpected error') + __('The attempt to post data to consumer failed due to an unexpected error. Please try again later.') ); } } @@ -287,7 +290,9 @@ protected function _loadConsumerById($consumerId) { $consumer = $this->_consumerFactory->create()->load($consumerId); if (!$consumer->getId()) { - throw new IntegrationException(__('Consumer with ID \'%1\' does not exist.', $consumerId)); + throw new IntegrationException( + __('A consumer with ID "%1" doesn\'t exist. Verify the ID and try again.', $consumerId) + ); } return $consumer; } diff --git a/app/code/Magento/Integration/Setup/Patch/Data/RemoveInactiveTokens.php b/app/code/Magento/Integration/Setup/Patch/Data/RemoveInactiveTokens.php new file mode 100644 index 0000000000000..1f5148dd2d2ea --- /dev/null +++ b/app/code/Magento/Integration/Setup/Patch/Data/RemoveInactiveTokens.php @@ -0,0 +1,132 @@ +moduleDataSetup = $moduleDataSetup; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + $this->moduleDataSetup->getConnection()->startSetup(); + + $this->removeRevokedTokens(); + $this->removeTokensFromInactiveAdmins(); + $this->removeTokensFromInactiveCustomers(); + + $this->moduleDataSetup->getConnection()->endSetup(); + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return []; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.2.0'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } + + /** + * Remove revoked tokens. + * + * @return void + */ + private function removeRevokedTokens() + { + $oauthTokenTable = $this->moduleDataSetup->getTable('oauth_token'); + + $where = ['revoked = ?' => 1]; + $this->moduleDataSetup->getConnection()->delete($oauthTokenTable, $where); + } + + /** + * Remove inactive admin users tokens + * + * @return void + */ + private function removeTokensFromInactiveAdmins() + { + $oauthTokenTable = $this->moduleDataSetup->getTable('oauth_token'); + $adminUserTable = $this->moduleDataSetup->getTable('admin_user'); + + $select = $this->moduleDataSetup->getConnection()->select()->from( + $adminUserTable, + ['user_id', 'is_active'] + ); + + $admins = $this->moduleDataSetup->getConnection()->fetchAll($select); + foreach ($admins as $admin) { + if ($admin['is_active'] == 0) { + $where = ['admin_id = ?' => (int)$admin['user_id']]; + $this->moduleDataSetup->getConnection()->delete($oauthTokenTable, $where); + } + } + } + + /** + * Remove tokens for inactive customers + * + * @return void + */ + private function removeTokensFromInactiveCustomers() + { + $oauthTokenTable = $this->moduleDataSetup->getTable('oauth_token'); + $adminUserTable = $this->moduleDataSetup->getTable('customer_entity'); + + $select = $this->moduleDataSetup->getConnection()->select()->from( + $adminUserTable, + ['entity_id', 'is_active'] + ); + + $admins = $this->moduleDataSetup->getConnection()->fetchAll($select); + foreach ($admins as $admin) { + if ($admin['is_active'] == 0) { + $where = ['customer_id = ?' => (int)$admin['entity_id']]; + $this->moduleDataSetup->getConnection()->delete($oauthTokenTable, $where); + } + } + } +} diff --git a/app/code/Magento/Integration/Setup/UpgradeData.php b/app/code/Magento/Integration/Setup/UpgradeData.php deleted file mode 100644 index b376d6a2b8b1e..0000000000000 --- a/app/code/Magento/Integration/Setup/UpgradeData.php +++ /dev/null @@ -1,96 +0,0 @@ -startSetup(); - - if (version_compare($context->getVersion(), '2.2.0', '<')) { - $this->removeRevokedTokens($setup); - $this->removeTokensFromInactiveAdmins($setup); - $this->removeTokensFromInactiveCustomers($setup); - } - - $setup->endSetup(); - } - - /** - * Remove any revoked tokens from oauth_token table - * - * @param ModuleDataSetupInterface $setup - * @return void - */ - private function removeRevokedTokens($setup) - { - $oauthTokenTable = $setup->getTable('oauth_token'); - - $where = ['revoked = ?' => 1]; - $setup->getConnection()->delete($oauthTokenTable, $where); - } - - /** - * Remove any tokens from oauth_token table where admin is inactive - * - * @param ModuleDataSetupInterface $setup - * @return void - */ - private function removeTokensFromInactiveAdmins($setup) - { - $oauthTokenTable = $setup->getTable('oauth_token'); - $adminUserTable = $setup->getTable('admin_user'); - - $select = $setup->getConnection()->select()->from( - $adminUserTable, - ['user_id', 'is_active'] - ); - - $admins = $setup->getConnection()->fetchAll($select); - foreach ($admins as $admin) { - if ($admin['is_active'] == 0) { - $where = ['admin_id = ?' => (int)$admin['user_id']]; - $setup->getConnection()->delete($oauthTokenTable, $where); - } - } - } - - /** - * Remove any tokens from oauth_token table where customer is inactive - * - * @param ModuleDataSetupInterface $setup - * @return void - */ - private function removeTokensFromInactiveCustomers($setup) - { - $oauthTokenTable = $setup->getTable('oauth_token'); - $adminUserTable = $setup->getTable('customer_entity'); - - $select = $setup->getConnection()->select()->from( - $adminUserTable, - ['entity_id', 'is_active'] - ); - - $admins = $setup->getConnection()->fetchAll($select); - foreach ($admins as $admin) { - if ($admin['is_active'] == 0) { - $where = ['customer_id = ?' => (int)$admin['entity_id']]; - $setup->getConnection()->delete($oauthTokenTable, $where); - } - } - } -} diff --git a/app/code/Magento/Integration/Test/Unit/Controller/Adminhtml/Integration/DeleteTest.php b/app/code/Magento/Integration/Test/Unit/Controller/Adminhtml/Integration/DeleteTest.php index e0fba2a85d776..dcb0ddccf6f83 100644 --- a/app/code/Magento/Integration/Test/Unit/Controller/Adminhtml/Integration/DeleteTest.php +++ b/app/code/Magento/Integration/Test/Unit/Controller/Adminhtml/Integration/DeleteTest.php @@ -156,7 +156,7 @@ public function testDeleteActionForServiceIntegrationException() ->willReturn(self::INTEGRATION_ID); // Use real translate model $this->_translateModelMock = null; - $exceptionMessage = __("Integration with ID '%1' doesn't exist.", $intData[Info::DATA_ID]); + $exceptionMessage = __('The integration with ID "%1" doesn\'t exist.', $intData[Info::DATA_ID]); $invalidIdException = new IntegrationException($exceptionMessage); $this->_integrationSvcMock->expects($this->once()) ->method('delete') @@ -178,7 +178,7 @@ public function testDeleteActionForServiceGenericException() ->willReturn(self::INTEGRATION_ID); // Use real translate model $this->_translateModelMock = null; - $exceptionMessage = __("Integration with ID '%1' doesn't exist.", $intData[Info::DATA_ID]); + $exceptionMessage = __('The integration with ID "%1" doesn\'t exist.', $intData[Info::DATA_ID]); $invalidIdException = new \Exception($exceptionMessage); $this->_integrationSvcMock->expects($this->once()) ->method('delete') diff --git a/app/code/Magento/Integration/Test/Unit/Controller/Adminhtml/Integration/SaveTest.php b/app/code/Magento/Integration/Test/Unit/Controller/Adminhtml/Integration/SaveTest.php index 739af68173642..63026cb99e0a0 100644 --- a/app/code/Magento/Integration/Test/Unit/Controller/Adminhtml/Integration/SaveTest.php +++ b/app/code/Magento/Integration/Test/Unit/Controller/Adminhtml/Integration/SaveTest.php @@ -181,7 +181,7 @@ public function testSaveActionExceptionDuringServiceCreation() public function testSaveActionExceptionOnIntegrationsCreatedFromConfigFile() { - $exceptionMessage = 'Cannot edit integrations created via config file.'; + $exceptionMessage = "The integrations created in the config file can't be edited."; $intData = new \Magento\Framework\DataObject( [ Info::DATA_NAME => 'nameTest', @@ -215,7 +215,7 @@ public function testSaveActionExceptionOnIntegrationsCreatedFromConfigFile() */ public function testSaveActionUserLockedException() { - $exceptionMessage = __('Your account is temporarily disabled.'); + $exceptionMessage = __('Your account is temporarily disabled. Please try again later.'); $passwordString = '1234567'; $this->_requestMock->expects($this->exactly(2)) @@ -254,7 +254,8 @@ public function testSaveActionUserLockedException() public function testSaveActionAuthenticationException() { $passwordString = '1234567'; - $exceptionMessage = __('You have entered an invalid password for current user.'); + $exceptionMessage = + __('The password entered for the current user is invalid. Verify the password and try again.'); $this->_requestMock->expects($this->any()) ->method('getParam') diff --git a/app/code/Magento/Integration/Test/Unit/Model/AdminTokenServiceTest.php b/app/code/Magento/Integration/Test/Unit/Model/AdminTokenServiceTest.php index 6fd8799045292..e0b1113e80d8d 100644 --- a/app/code/Magento/Integration/Test/Unit/Model/AdminTokenServiceTest.php +++ b/app/code/Magento/Integration/Test/Unit/Model/AdminTokenServiceTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Integration\Test\Unit\Model; use Magento\Integration\Model\Oauth\Token; @@ -116,7 +117,7 @@ public function testRevokeAdminAccessTokenWithoutAdminId() /** * @expectedException \Magento\Framework\Exception\LocalizedException - * @expectedExceptionMessage The tokens could not be revoked. + * @expectedExceptionMessage The tokens couldn't be revoked. */ public function testRevokeAdminAccessTokenCannotRevoked() { diff --git a/app/code/Magento/Integration/Test/Unit/Model/AuthorizationServiceTest.php b/app/code/Magento/Integration/Test/Unit/Model/AuthorizationServiceTest.php index 475fb75d68517..230cb1e94fec8 100644 --- a/app/code/Magento/Integration/Test/Unit/Model/AuthorizationServiceTest.php +++ b/app/code/Magento/Integration/Test/Unit/Model/AuthorizationServiceTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Integration\Test\Unit\Model; use Magento\Authorization\Model\ResourceModel\Rules; @@ -177,7 +178,6 @@ public function testGrantPermissionsNoRole() /** * @expectedException \Magento\Framework\Exception\LocalizedException - * @expectedExceptionMessage Sorry, something went wrong granting permissions. */ public function testGrantPermissionsException() { @@ -197,6 +197,10 @@ public function testGrantPermissionsException() $this->rulesMock->expects($this->any())->method('saveRel')->will($this->throwException(new \Exception())); $this->integrationAuthorizationService->grantPermissions(self::INTEGRATION_ID, $this->resources); + + $this->expectExceptionMessage( + 'An error occurred during the attempt to grant permissions. For details, see the exceptions log.' + ); } public function testGrantAllPermissions() diff --git a/app/code/Magento/Integration/Test/Unit/Model/CredentialsValidatorTest.php b/app/code/Magento/Integration/Test/Unit/Model/CredentialsValidatorTest.php index cd9e2657fa324..94d72b47c24e2 100644 --- a/app/code/Magento/Integration/Test/Unit/Model/CredentialsValidatorTest.php +++ b/app/code/Magento/Integration/Test/Unit/Model/CredentialsValidatorTest.php @@ -22,7 +22,7 @@ protected function setUp() /** * @expectedException \Magento\Framework\Exception\InputException - * @expectedExceptionMessage username is a required field. + * @expectedExceptionMessage "username" is required. Enter and try again. */ public function testValidateNoUsername() { @@ -34,7 +34,7 @@ public function testValidateNoUsername() /** * @expectedException \Magento\Framework\Exception\InputException - * @expectedExceptionMessage password is a required field. + * @expectedExceptionMessage "password" is required. Enter and try again. */ public function testValidateNoPassword() { diff --git a/app/code/Magento/Integration/Test/Unit/Model/CustomerTokenServiceTest.php b/app/code/Magento/Integration/Test/Unit/Model/CustomerTokenServiceTest.php index ecd4788545c0a..1a7c819343294 100644 --- a/app/code/Magento/Integration/Test/Unit/Model/CustomerTokenServiceTest.php +++ b/app/code/Magento/Integration/Test/Unit/Model/CustomerTokenServiceTest.php @@ -117,7 +117,7 @@ public function testRevokeCustomerAccessTokenWithoutCustomerId() /** * @expectedException \Magento\Framework\Exception\LocalizedException - * @expectedExceptionMessage The tokens could not be revoked. + * @expectedExceptionMessage The tokens couldn't be revoked. */ public function testRevokeCustomerAccessTokenCannotRevoked() { diff --git a/app/code/Magento/Integration/Test/Unit/Model/IntegrationServiceTest.php b/app/code/Magento/Integration/Test/Unit/Model/IntegrationServiceTest.php index 60c7d43193344..09b02419fb0e8 100644 --- a/app/code/Magento/Integration/Test/Unit/Model/IntegrationServiceTest.php +++ b/app/code/Magento/Integration/Test/Unit/Model/IntegrationServiceTest.php @@ -5,6 +5,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Integration\Test\Unit\Model; use Magento\Integration\Model\Integration; @@ -149,7 +150,7 @@ public function testCreateSuccess() /** * @expectedException \Magento\Framework\Exception\IntegrationException - * @expectedExceptionMessage Integration with name 'Integration Name' exists. + * @expectedExceptionMessage The integration with name "Integration Name" exists. */ public function testCreateIntegrationAlreadyExistsException() { @@ -244,7 +245,7 @@ public function testUpdateSuccessNameChanged() /** * @expectedException \Magento\Framework\Exception\IntegrationException - * @expectedExceptionMessage Integration with name 'Another Integration Name' exists. + * @expectedExceptionMessage The integration with name "Another Integration Name" exists. */ public function testUpdateException() { @@ -297,7 +298,7 @@ public function testGet() /** * @expectedException \Magento\Framework\Exception\IntegrationException - * @expectedExceptionMessage Integration with ID '1' does not exist. + * @expectedExceptionMessage The integration with ID "1" doesn't exist. */ public function testGetException() { @@ -385,7 +386,7 @@ public function testDelete() /** * @expectedException \Magento\Framework\Exception\IntegrationException - * @expectedExceptionMessage Integration with ID '1' does not exist. + * @expectedExceptionMessage The integration with ID "1" doesn't exist. */ public function testDeleteException() { diff --git a/app/code/Magento/Integration/Test/Unit/Model/Oauth/Token/ProviderTest.php b/app/code/Magento/Integration/Test/Unit/Model/Oauth/Token/ProviderTest.php index b7a5193f443ff..2fe0632a0ae69 100644 --- a/app/code/Magento/Integration/Test/Unit/Model/Oauth/Token/ProviderTest.php +++ b/app/code/Magento/Integration/Test/Unit/Model/Oauth/Token/ProviderTest.php @@ -340,7 +340,7 @@ public function testValidateRequestTokenNotExistentToken() /** * @expectedException \Magento\Framework\Oauth\Exception - * @expectedExceptionMessage Token is not the correct length + * @expectedExceptionMessage The token length is invalid. Check the length and try again. */ public function testValidateRequestTokenIncorrectLengthToken() { diff --git a/app/code/Magento/Integration/Test/Unit/Model/OauthServiceTest.php b/app/code/Magento/Integration/Test/Unit/Model/OauthServiceTest.php index 85d8b50097aed..9b8293c285c04 100644 --- a/app/code/Magento/Integration/Test/Unit/Model/OauthServiceTest.php +++ b/app/code/Magento/Integration/Test/Unit/Model/OauthServiceTest.php @@ -5,6 +5,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Integration\Test\Unit\Model; use Magento\Integration\Model\Oauth\Token; @@ -141,7 +142,7 @@ public function testDelete() /** * @return void * @expectedException \Magento\Framework\Exception\IntegrationException - * @expectedExceptionMessage Consumer with ID '1' does not exist. + * @expectedExceptionMessage A consumer with ID "1" doesn't exist. Verify the ID and try again. */ public function testDeleteException() { @@ -288,7 +289,6 @@ public function testLoadConsumer() /** * @return void * @expectedException \Magento\Framework\Oauth\Exception - * @expectedExceptionMessage Unexpected error. Unable to load oAuth consumer account. */ public function testLoadConsumerException() { @@ -298,10 +298,19 @@ public function testLoadConsumerException() 'load' )->will( $this->throwException( - new \Magento\Framework\Oauth\Exception(__('Unexpected error. Unable to load oAuth consumer account.')) + new \Magento\Framework\Oauth\Exception( + __( + "The oAuth consumer account couldn't be loaded due to an unexpected error. " + . "Please try again later." + ) + ) ) ); $this->_service->loadConsumer(self::VALUE_CONSUMER_ID); + + $this->expectExceptionMessage( + "The oAuth consumer account couldn't be loaded due to an unexpected error. Please try again later." + ); } /** @@ -328,7 +337,6 @@ public function testLoadConsumerByKey() /** * @return void * @expectedException \Magento\Framework\Oauth\Exception - * @expectedExceptionMessage Unexpected error. Unable to load oAuth consumer account. */ public function testLoadConsumerByKeyException() { @@ -338,10 +346,19 @@ public function testLoadConsumerByKeyException() 'load' )->will( $this->throwException( - new \Magento\Framework\Oauth\Exception(__('Unexpected error. Unable to load oAuth consumer account.')) + new \Magento\Framework\Oauth\Exception( + __( + "The oAuth consumer account couldn't be loaded due to an unexpected error. " + . "Please try again later." + ) + ) ) ); $this->_service->loadConsumerByKey(self::VALUE_CONSUMER_KEY); + + $this->expectExceptionMessage( + "The oAuth consumer account couldn't be loaded due to an unexpected error. Please try again later." + ); } /** diff --git a/app/code/Magento/Integration/Test/Unit/Oauth/OauthTest.php b/app/code/Magento/Integration/Test/Unit/Oauth/OauthTest.php index 4e928985b7ae4..875377776771d 100644 --- a/app/code/Magento/Integration/Test/Unit/Oauth/OauthTest.php +++ b/app/code/Magento/Integration/Test/Unit/Oauth/OauthTest.php @@ -505,7 +505,7 @@ public function testGetAccessTokenVersionRejected() * \Magento\Framework\Oauth\OauthInterface::ERR_PARAMETER_ABSENT * * @expectedException \Magento\Framework\Oauth\OauthInputException - * @expectedExceptionMessage oauth_verifier is a required field. + * @expectedExceptionMessage "oauth_verifier" is required. Enter and try again. */ public function testGetAccessTokenParameterAbsent() { diff --git a/app/code/Magento/Integration/etc/module.xml b/app/code/Magento/Integration/etc/module.xml index c5e2aa75a8d05..abd407c981d6f 100644 --- a/app/code/Magento/Integration/etc/module.xml +++ b/app/code/Magento/Integration/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/LayeredNavigation/etc/module.xml b/app/code/Magento/LayeredNavigation/etc/module.xml index 5cc794c622aaf..0fcfcba834c3b 100644 --- a/app/code/Magento/LayeredNavigation/etc/module.xml +++ b/app/code/Magento/LayeredNavigation/etc/module.xml @@ -6,6 +6,6 @@ */ --> - + diff --git a/app/code/Magento/Marketplace/etc/module.xml b/app/code/Magento/Marketplace/etc/module.xml index b696e5206e524..8490bd835110d 100644 --- a/app/code/Magento/Marketplace/etc/module.xml +++ b/app/code/Magento/Marketplace/etc/module.xml @@ -6,5 +6,5 @@ */ --> - + diff --git a/app/code/Magento/MediaStorage/Helper/File/Media.php b/app/code/Magento/MediaStorage/Helper/File/Media.php index 72b99728a99cc..0bacd44bdc13f 100644 --- a/app/code/Magento/MediaStorage/Helper/File/Media.php +++ b/app/code/Magento/MediaStorage/Helper/File/Media.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\MediaStorage\Helper\File; use Magento\Framework\App\Filesystem\DirectoryList; @@ -61,7 +62,9 @@ public function collectFileInfo($mediaDirectory, $path) $dir = $this->filesystem->getDirectoryRead(DirectoryList::MEDIA); $relativePath = $dir->getRelativePath($fullPath); if (!$dir->isFile($relativePath)) { - throw new \Magento\Framework\Exception\LocalizedException(__('File %1 does not exist', $fullPath)); + throw new \Magento\Framework\Exception\LocalizedException( + __('The "%1" file doesn\'t exist. Verify the file and try again.', $fullPath) + ); } if (!$dir->isReadable($relativePath)) { throw new \Magento\Framework\Exception\LocalizedException(__('File %1 is not readable', $fullPath)); diff --git a/app/code/Magento/MediaStorage/Test/Unit/Helper/File/MediaTest.php b/app/code/Magento/MediaStorage/Test/Unit/Helper/File/MediaTest.php index 0c50b6e130484..59f0d08ba3adb 100644 --- a/app/code/Magento/MediaStorage/Test/Unit/Helper/File/MediaTest.php +++ b/app/code/Magento/MediaStorage/Test/Unit/Helper/File/MediaTest.php @@ -97,7 +97,7 @@ public function pathDataProvider() /** * @expectedException \Magento\Framework\Exception\LocalizedException - * @expectedExceptionMessage File mediaDir/path does not exist + * @expectedExceptionMessage The "mediaDir/path" file doesn't exist. Verify the file and try again. */ public function testCollectFileInfoNotFile() { diff --git a/app/code/Magento/MediaStorage/etc/module.xml b/app/code/Magento/MediaStorage/etc/module.xml index 84a749721f50f..6a04d4641e66d 100644 --- a/app/code/Magento/MediaStorage/etc/module.xml +++ b/app/code/Magento/MediaStorage/etc/module.xml @@ -6,5 +6,5 @@ */ --> - + diff --git a/app/code/Magento/Msrp/Setup/Patch/Data/ChangePriceAttributeDefaultScope.php b/app/code/Magento/Msrp/Setup/Patch/Data/ChangePriceAttributeDefaultScope.php new file mode 100644 index 0000000000000..b924b6052369f --- /dev/null +++ b/app/code/Magento/Msrp/Setup/Patch/Data/ChangePriceAttributeDefaultScope.php @@ -0,0 +1,96 @@ +moduleDataSetup = $moduleDataSetup; + $this->categorySetupFactory = $categorySetupFactory; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + /** @var \Magento\Catalog\Setup\CategorySetup $categorySetup */ + $categorySetup = $this->categorySetupFactory->create(); + $this->moduleDataSetup->getConnection()->startSetup(); + $entityTypeId = $categorySetup->getEntityTypeId(\Magento\Catalog\Model\Product::ENTITY); + $this->changePriceAttributeDefaultScope($categorySetup, $entityTypeId); + $this->moduleDataSetup->getConnection()->endSetup(); + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return [ + InitializeMsrpAttributes::class + ]; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.1.3'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } + + /** + * Change default scope for price attribute. + * + * @param \Magento\Catalog\Setup\CategorySetup $categorySetup + * @param int $entityTypeId + */ + private function changePriceAttributeDefaultScope($categorySetup, $entityTypeId) + { + $attribute = $categorySetup->getAttribute($entityTypeId, 'msrp'); + $categorySetup->updateAttribute( + $entityTypeId, + $attribute['attribute_id'], + 'is_global', + \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_GLOBAL + ); + } +} diff --git a/app/code/Magento/Msrp/Setup/InstallData.php b/app/code/Magento/Msrp/Setup/Patch/Data/InitializeMsrpAttributes.php similarity index 76% rename from app/code/Magento/Msrp/Setup/InstallData.php rename to app/code/Magento/Msrp/Setup/Patch/Data/InitializeMsrpAttributes.php index 02bcc9d465f9a..f47d106da94b3 100644 --- a/app/code/Magento/Msrp/Setup/InstallData.php +++ b/app/code/Magento/Msrp/Setup/Patch/Data/InitializeMsrpAttributes.php @@ -4,44 +4,48 @@ * See COPYING.txt for license details. */ -namespace Magento\Msrp\Setup; +namespace Magento\Msrp\Setup\Patch\Data; use Magento\Eav\Setup\EavSetup; use Magento\Eav\Setup\EavSetupFactory; use Magento\Framework\Setup\InstallDataInterface; use Magento\Framework\Setup\ModuleContextInterface; use Magento\Framework\Setup\ModuleDataSetupInterface; +use Magento\Framework\App\ResourceConnection; +use Magento\Setup\Model\Patch\DataPatchInterface; +use Magento\Setup\Model\Patch\PatchVersionInterface; -/** - * @codeCoverageIgnore - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) - */ -class InstallData implements InstallDataInterface +class InitializeMsrpAttributes implements DataPatchInterface, PatchVersionInterface { /** - * EAV setup factory - * + * @var \Magento\Framework\Setup\ModuleDataSetupInterface + */ + private $moduleDataSetup; + + /** * @var EavSetupFactory */ private $eavSetupFactory; /** - * Init - * - * @param EavSetupFactory $eavSetupFactory + * PatchInitial constructor. + * @param \Magento\Framework\Setup\ModuleDataSetupInterface $moduleDataSetup */ - public function __construct(EavSetupFactory $eavSetupFactory) - { + public function __construct( + \Magento\Framework\Setup\ModuleDataSetupInterface $moduleDataSetup, + EavSetupFactory $eavSetupFactory + ) { + $this->moduleDataSetup = $moduleDataSetup; $this->eavSetupFactory = $eavSetupFactory; } /** * {@inheritdoc} */ - public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context) + public function apply() { /** @var EavSetup $eavSetup */ - $eavSetup = $this->eavSetupFactory->create(['setup' => $setup]); + $eavSetup = $this->eavSetupFactory->create(['setup' => $this->moduleDataSetup]); $productTypes = [ \Magento\Catalog\Model\Product\Type::TYPE_SIMPLE, @@ -50,7 +54,6 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface \Magento\Catalog\Model\Product\Type::TYPE_BUNDLE, ]; $productTypes = join(',', $productTypes); - $eavSetup->addAttribute( \Magento\Catalog\Model\Product::ENTITY, 'msrp', @@ -75,7 +78,6 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface 'is_filterable_in_grid' => true, ] ); - $eavSetup->addAttribute( \Magento\Catalog\Model\Product::ENTITY, 'msrp_display_actual_price_type', @@ -101,4 +103,28 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ] ); } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return []; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.0'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } } diff --git a/app/code/Magento/Msrp/Setup/UpgradeData.php b/app/code/Magento/Msrp/Setup/UpgradeData.php deleted file mode 100644 index 326cefb364f44..0000000000000 --- a/app/code/Magento/Msrp/Setup/UpgradeData.php +++ /dev/null @@ -1,63 +0,0 @@ -categorySetupFactory = $categorySetupFactory; - } - - /** - * {@inheritdoc} - */ - public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context) - { - /** @var \Magento\Catalog\Setup\CategorySetup $categorySetup */ - $categorySetup = $this->categorySetupFactory->create(['setup' => $setup]); - $entityTypeId = $categorySetup->getEntityTypeId(\Magento\Catalog\Model\Product::ENTITY); - - if (version_compare($context->getVersion(), '2.1.3', '<')) { - $this->changePriceAttributeDefaultScope($categorySetup, $entityTypeId); - } - $setup->endSetup(); - } - - /** - * @param \Magento\Catalog\Setup\CategorySetup $categorySetup - * @param int $entityTypeId - * @return void - */ - private function changePriceAttributeDefaultScope($categorySetup, $entityTypeId) - { - $attribute = $categorySetup->getAttribute($entityTypeId, 'msrp'); - $categorySetup->updateAttribute( - $entityTypeId, - $attribute['attribute_id'], - 'is_global', - \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_GLOBAL - ); - } -} diff --git a/app/code/Magento/Msrp/etc/module.xml b/app/code/Magento/Msrp/etc/module.xml index 8d6c0e61a44f0..e0d98fbb28c20 100644 --- a/app/code/Magento/Msrp/etc/module.xml +++ b/app/code/Magento/Msrp/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/Multishipping/Model/Checkout/Type/Multishipping.php b/app/code/Magento/Multishipping/Model/Checkout/Type/Multishipping.php index a3edd57d54e05..fdbe1d24ba1f5 100644 --- a/app/code/Magento/Multishipping/Model/Checkout/Type/Multishipping.php +++ b/app/code/Magento/Multishipping/Model/Checkout/Type/Multishipping.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Multishipping\Model\Checkout\Type; use Magento\Customer\Api\AddressRepositoryInterface; @@ -396,7 +397,11 @@ public function setShippingItemsInformation($info) $maxQty = $this->helper->getMaximumQty(); if ($allQty > $maxQty) { throw new \Magento\Framework\Exception\LocalizedException( - __('Maximum qty allowed for Shipping to multiple addresses is %1', $maxQty) + __( + "The maximum quantity can't be more than %1 when shipping to multiple addresses. " + . "Change the quantity and try again.", + $maxQty + ) ); } $quote = $this->getQuote(); @@ -478,7 +483,7 @@ protected function _addShippingItem($quoteItemId, $data) if ($addressId && $quoteItem) { if (!$this->isAddressIdApplicable($addressId)) { - throw new LocalizedException(__('Please check shipping address information.')); + throw new LocalizedException(__('Verify the shipping address information and continue.')); } /** @@ -526,7 +531,7 @@ protected function _addShippingItem($quoteItemId, $data) public function updateQuoteCustomerShippingAddress($addressId) { if (!$this->isAddressIdApplicable($addressId)) { - throw new LocalizedException(__('Please check shipping address information.')); + throw new LocalizedException(__('Verify the shipping address information and continue.')); } try { $address = $this->addressRepository->getById($addressId); @@ -553,7 +558,7 @@ public function updateQuoteCustomerShippingAddress($addressId) public function setQuoteCustomerBillingAddress($addressId) { if (!$this->isAddressIdApplicable($addressId)) { - throw new LocalizedException(__('Please check billing address information.')); + throw new LocalizedException(__('Verify the billing address information and continue.')); } try { $address = $this->addressRepository->getById($addressId); @@ -588,7 +593,7 @@ public function setShippingMethods($methods) $address->setShippingMethod($methods[$addressId]); } elseif (!$address->getShippingMethod()) { throw new \Magento\Framework\Exception\LocalizedException( - __('Please select shipping methods for all addresses.') + __('Set shipping methods for all addresses. Verify the shipping methods and try again.') ); } } @@ -608,12 +613,15 @@ public function setPaymentMethod($payment) { if (!isset($payment['method'])) { throw new \Magento\Framework\Exception\LocalizedException( - __('A payment method is not defined.') + __("A payment method isn't defined. Verify and try again.") ); } if (!$this->paymentSpecification->isSatisfiedBy($payment['method'])) { throw new \Magento\Framework\Exception\LocalizedException( - __('The requested payment method is not available for multishipping.') + __( + "This payment method can't be used for shipping to multiple addresses. " + . "Change the payment method and try again." + ) ); } $quote = $this->getQuote(); @@ -660,7 +668,7 @@ protected function _prepareOrder(\Magento\Quote\Model\Quote\Address $address) $_quoteItem = $item->getQuoteItem(); if (!$_quoteItem) { throw new \Magento\Checkout\Exception( - __('Item not found or already ordered') + __("The item isn't found, or it's already ordered.") ); } $item->setProductType( @@ -692,7 +700,7 @@ protected function _validate() $paymentMethod = $quote->getPayment()->getMethodInstance(); if (!$paymentMethod->isAvailable($quote)) { throw new \Magento\Framework\Exception\LocalizedException( - __('Please specify a payment method.') + __("The payment method isn't selected. Enter the payment method and try again.") ); } @@ -701,27 +709,29 @@ protected function _validate() $addressValidation = $address->validate(); if ($addressValidation !== true) { throw new \Magento\Framework\Exception\LocalizedException( - __('Please check shipping addresses information.') + __('Verify the shipping address information and continue.') ); } $method = $address->getShippingMethod(); $rate = $address->getShippingRateByCode($method); if (!$method || !$rate) { throw new \Magento\Framework\Exception\LocalizedException( - __('Please specify shipping methods for all addresses.') + __('Set shipping methods for all addresses. Verify the shipping methods and try again.') ); } // Checks if a country id present in the allowed countries list. if (!in_array($address->getCountryId(), $this->allowedCountryReader->getAllowedCountries())) { throw new \Magento\Framework\Exception\LocalizedException( - __('Some addresses cannot be used due to country-specific configurations.') + __("Some addresses can't be used due to the configurations for specific countries.") ); } } $addressValidation = $quote->getBillingAddress()->validate(); if ($addressValidation !== true) { - throw new \Magento\Framework\Exception\LocalizedException(__('Please check billing address information.')); + throw new \Magento\Framework\Exception\LocalizedException( + __('Verify the billing address information and continue.') + ); } return $this; } @@ -906,7 +916,7 @@ private function getDefaultAddressByDataKey($key, $defaultAddressIdFromCustomer) $addressId = $defaultAddressIdFromCustomer; if (!$addressId) { /** Default address is not available, try to find any customer address */ - $filter = $this->filterBuilder->setField('parent_id') + $filter = $this->filterBuilder->setField('parent_id') ->setValue($this->getCustomer()->getId()) ->setConditionType('eq') ->create(); diff --git a/app/code/Magento/Multishipping/Test/Unit/Model/Checkout/Type/MultishippingTest.php b/app/code/Magento/Multishipping/Test/Unit/Model/Checkout/Type/MultishippingTest.php index 749fd178ec7c3..b2e484e148f43 100644 --- a/app/code/Magento/Multishipping/Test/Unit/Model/Checkout/Type/MultishippingTest.php +++ b/app/code/Magento/Multishipping/Test/Unit/Model/Checkout/Type/MultishippingTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Multishipping\Test\Unit\Model\Checkout\Type; use Magento\Checkout\Model\Session; @@ -242,7 +243,7 @@ public function testSetShippingItemsInformation() /** * @expectedException \Magento\Framework\Exception\LocalizedException - * @expectedExceptionMessage Please check shipping address information. + * @expectedExceptionMessage Verify the shipping address information and continue. */ public function testSetShippingItemsInformationForAddressLeak() { @@ -288,7 +289,7 @@ public function testUpdateQuoteCustomerShippingAddress() /** * @expectedException \Magento\Framework\Exception\LocalizedException - * @expectedExceptionMessage Please check shipping address information. + * @expectedExceptionMessage Verify the shipping address information and continue. */ public function testUpdateQuoteCustomerShippingAddressForAddressLeak() { @@ -318,7 +319,7 @@ public function testSetQuoteCustomerBillingAddress() /** * @expectedException \Magento\Framework\Exception\LocalizedException - * @expectedExceptionMessage Please check billing address information. + * @expectedExceptionMessage Verify the billing address information and continue. */ public function testSetQuoteCustomerBillingAddressForAddressLeak() { @@ -368,7 +369,7 @@ public function testSetShippingMethods() * Tests exception for addresses with country id not in the allowed countries list. * * @expectedException \Magento\Framework\Exception\LocalizedException - * @expectedExceptionMessage Some addresses cannot be used due to country-specific configurations. + * @expectedExceptionMessage Some addresses can't be used due to the configurations for specific countries. */ public function testCreateOrdersCountryNotPresentInAllowedListException() { diff --git a/app/code/Magento/Multishipping/etc/module.xml b/app/code/Magento/Multishipping/etc/module.xml index f77de32c24a2f..c2ad47e4ccab5 100644 --- a/app/code/Magento/Multishipping/etc/module.xml +++ b/app/code/Magento/Multishipping/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/NewRelicReporting/etc/module.xml b/app/code/Magento/NewRelicReporting/etc/module.xml index 84092d710d002..4a824c622fe05 100644 --- a/app/code/Magento/NewRelicReporting/etc/module.xml +++ b/app/code/Magento/NewRelicReporting/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/Newsletter/etc/module.xml b/app/code/Magento/Newsletter/etc/module.xml index 5da16a9a3e9ba..23e9d84b203cf 100644 --- a/app/code/Magento/Newsletter/etc/module.xml +++ b/app/code/Magento/Newsletter/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/OfflinePayments/etc/module.xml b/app/code/Magento/OfflinePayments/etc/module.xml index dfea6036c2e92..7388b5631aeb9 100644 --- a/app/code/Magento/OfflinePayments/etc/module.xml +++ b/app/code/Magento/OfflinePayments/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/OfflineShipping/Model/Carrier/Tablerate.php b/app/code/Magento/OfflineShipping/Model/Carrier/Tablerate.php index 87d4b984cf933..2c4fc9a4ccfe1 100644 --- a/app/code/Magento/OfflineShipping/Model/Carrier/Tablerate.php +++ b/app/code/Magento/OfflineShipping/Model/Carrier/Tablerate.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\OfflineShipping\Model\Carrier; use Magento\Framework\Exception\LocalizedException; @@ -228,7 +229,9 @@ public function getCode($type, $code = '') ]; if (!isset($codes[$type])) { - throw new LocalizedException(__('Please correct Table Rate code type: %1.', $type)); + throw new LocalizedException( + __('The "%1" code type for Table Rate is incorrect. Verify the type and try again.', $type) + ); } if ('' === $code) { @@ -236,7 +239,9 @@ public function getCode($type, $code = '') } if (!isset($codes[$type][$code])) { - throw new LocalizedException(__('Please correct Table Rate code for type %1: %2.', $type, $code)); + throw new LocalizedException( + __('The "%1: %2" code type for Table Rate is incorrect. Verify the type and try again.', $type, $code) + ); } return $codes[$type][$code]; diff --git a/app/code/Magento/OfflineShipping/Model/ResourceModel/Carrier/Tablerate/CSV/RowParser.php b/app/code/Magento/OfflineShipping/Model/ResourceModel/Carrier/Tablerate/CSV/RowParser.php index 4d2e11ebb8a1e..9431973fdfe91 100644 --- a/app/code/Magento/OfflineShipping/Model/ResourceModel/Carrier/Tablerate/CSV/RowParser.php +++ b/app/code/Magento/OfflineShipping/Model/ResourceModel/Carrier/Tablerate/CSV/RowParser.php @@ -62,7 +62,12 @@ public function parse( ) { // validate row if (count($rowData) < 5) { - throw new RowException(__('Please correct Table Rates format in the Row #%1.', $rowNumber)); + throw new RowException( + __( + 'The Table Rates File Format is incorrect in row number "%1". Verify the format and try again.', + $rowNumber + ) + ); } $countryId = $this->getCountryId($rowData, $rowNumber, $columnResolver); @@ -99,7 +104,13 @@ private function getCountryId(array $rowData, $rowNumber, ColumnResolver $column } elseif ($countryCode === '*' || $countryCode === '') { $countryId = '0'; } else { - throw new RowException(__('Please correct Country "%1" in the Row #%2.', $countryCode, $rowNumber)); + throw new RowException( + __( + 'The "%1" country in row number "%2" is incorrect. Verify the country and try again.', + $countryCode, + $rowNumber + ) + ); } return $countryId; } @@ -121,7 +132,14 @@ private function getRegionId(array $rowData, $rowNumber, ColumnResolver $columnR } elseif ($regionCode === '*' || $regionCode === '') { $regionId = 0; } else { - throw new RowException(__('Please correct Region/State "%1" in the Row #%2.', $regionCode, $rowNumber)); + throw new RowException( + __( + 'The "%1" region or state in row number "%2" is incorrect. ' + . 'Verify the region or state and try again.', + $regionCode, + $rowNumber + ) + ); } return $regionId; } @@ -181,7 +199,13 @@ private function getPrice(array $rowData, $rowNumber, ColumnResolver $columnReso $priceValue = $columnResolver->getColumnValue(ColumnResolver::COLUMN_PRICE, $rowData); $price = $this->_parseDecimalValue($priceValue); if ($price === false) { - throw new RowException(__('Please correct Shipping Price "%1" in the Row #%2.', $priceValue, $rowNumber)); + throw new RowException( + __( + 'The "%1" shipping price in row number "%2" is incorrect. Verify the shipping price and try again.', + $priceValue, + $rowNumber + ) + ); } return $price; } diff --git a/app/code/Magento/OfflineShipping/Model/ResourceModel/Carrier/Tablerate/Import.php b/app/code/Magento/OfflineShipping/Model/ResourceModel/Carrier/Tablerate/Import.php index 1012394f22fcb..a5b0d7e87d2e1 100644 --- a/app/code/Magento/OfflineShipping/Model/ResourceModel/Carrier/Tablerate/Import.php +++ b/app/code/Magento/OfflineShipping/Model/ResourceModel/Carrier/Tablerate/Import.php @@ -16,6 +16,9 @@ use Magento\OfflineShipping\Model\ResourceModel\Carrier\Tablerate\CSV\RowParser; use Magento\Store\Model\StoreManagerInterface; +/** + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ class Import { /** @@ -178,7 +181,9 @@ private function getHeaders(ReadInterface $file) // check and skip headers $headers = $file->readCsv(); if ($headers === false || count($headers) < 5) { - throw new LocalizedException(__('Please correct Table Rates File Format.')); + throw new LocalizedException( + __('The Table Rates File Format is incorrect. Verify the format and try again.') + ); } return $headers; } diff --git a/app/code/Magento/OfflineShipping/Setup/Patch/Data/UpdateQuoteShippingAddresses.php b/app/code/Magento/OfflineShipping/Setup/Patch/Data/UpdateQuoteShippingAddresses.php new file mode 100644 index 0000000000000..e88da3b8a77e7 --- /dev/null +++ b/app/code/Magento/OfflineShipping/Setup/Patch/Data/UpdateQuoteShippingAddresses.php @@ -0,0 +1,97 @@ +moduleDataSetup = $moduleDataSetup; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + // setup default + $this->moduleDataSetup->getConnection()->startSetup(); + $connection = $this->moduleDataSetup->getConnection(); + $salesConnection = $this->moduleDataSetup->getConnection('sales'); + $checkoutConnection = $this->moduleDataSetup->getConnection('checkout'); + $connection->update( + $this->moduleDataSetup->getTable('salesrule'), + ['simple_free_shipping' => 0], + [new \Zend_Db_Expr('simple_free_shipping IS NULL')] + ); + $this->moduleDataSetup->getConnection()->endSetup(); + + // setup sales + $salesConnection->startSetup(); + $salesConnection->update( + $this->moduleDataSetup->getTable('sales_order_item'), + ['free_shipping' => 0], + [new \Zend_Db_Expr('free_shipping IS NULL')] + ); + $salesConnection->endSetup(); + + // setup checkout + $checkoutConnection->startSetup(); + $checkoutConnection->update( + $this->moduleDataSetup->getTable('quote_address'), + ['free_shipping' => 0], + [new \Zend_Db_Expr('free_shipping IS NULL')] + ); + $checkoutConnection->update( + $this->moduleDataSetup->getTable('quote_item'), + ['free_shipping' => 0], + [new \Zend_Db_Expr('free_shipping IS NULL')] + ); + $checkoutConnection->endSetup(); + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return []; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.1'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } +} diff --git a/app/code/Magento/OfflineShipping/Setup/UpgradeData.php b/app/code/Magento/OfflineShipping/Setup/UpgradeData.php deleted file mode 100644 index f0a11c66ca6de..0000000000000 --- a/app/code/Magento/OfflineShipping/Setup/UpgradeData.php +++ /dev/null @@ -1,69 +0,0 @@ -startSetup(); - if ($context->getVersion() && version_compare($context->getVersion(), '2.0.1') < 0) { - $this->updateQuoteShippingAddresses($setup); - } - $setup->endSetup(); - } - - /** - * Replace Null with '0' for 'free_shipping' and 'simple_free_shipping' accordingly to upgraded schema. - * - * @param ModuleDataSetupInterface $setup - * @return void - */ - private function updateQuoteShippingAddresses(ModuleDataSetupInterface $setup) - { - $setup->getConnection()->update( - $setup->getTable('salesrule'), - ['simple_free_shipping' => 0], - [new \Zend_Db_Expr('simple_free_shipping IS NULL')] - ); - $setup->getConnection($this->salesConnectionName)->update( - $setup->getTable('sales_order_item'), - ['free_shipping' => 0], - [new \Zend_Db_Expr('free_shipping IS NULL')] - ); - $setup->getConnection($this->quoteConnectionName)->update( - $setup->getTable('quote_address'), - ['free_shipping' => 0], - [new \Zend_Db_Expr('free_shipping IS NULL')] - ); - $setup->getConnection($this->quoteConnectionName)->update( - $setup->getTable('quote_item'), - ['free_shipping' => 0], - [new \Zend_Db_Expr('free_shipping IS NULL')] - ); - } -} diff --git a/app/code/Magento/OfflineShipping/Test/Unit/Model/ResourceModel/Carrier/Tablerate/CSV/RowParserTest.php b/app/code/Magento/OfflineShipping/Test/Unit/Model/ResourceModel/Carrier/Tablerate/CSV/RowParserTest.php index 2f6c5ca600bd3..4807d4956d266 100644 --- a/app/code/Magento/OfflineShipping/Test/Unit/Model/ResourceModel/Carrier/Tablerate/CSV/RowParserTest.php +++ b/app/code/Magento/OfflineShipping/Test/Unit/Model/ResourceModel/Carrier/Tablerate/CSV/RowParserTest.php @@ -143,7 +143,7 @@ public function parseWithExceptionDataProvider() [$conditionFullName, $rowData, 40], [ColumnResolver::COLUMN_PRICE, $rowData, 350], ], - 'Please correct Country "XX" in the Row #120.', + 'The "XX" country in row number "120" is incorrect. Verify the country and try again.', ], [ $rowData, @@ -155,7 +155,7 @@ public function parseWithExceptionDataProvider() [$conditionFullName, $rowData, 40], [ColumnResolver::COLUMN_PRICE, $rowData, 350], ], - 'Please correct Region/State "AA" in the Row #120.', + 'The "AA" region or state in row number "120" is incorrect. Verify the region or state and try again.', ], [ $rowData, @@ -179,7 +179,7 @@ public function parseWithExceptionDataProvider() [$conditionFullName, $rowData, 40], [ColumnResolver::COLUMN_PRICE, $rowData, 'BBB'], ], - 'Please correct Shipping Price "BBB" in the Row #120.', + 'The "BBB" shipping price in row number "120" is incorrect. Verify the shipping price and try again.', ], ]; } diff --git a/app/code/Magento/OfflineShipping/Test/Unit/Model/ResourceModel/Carrier/Tablerate/ImportTest.php b/app/code/Magento/OfflineShipping/Test/Unit/Model/ResourceModel/Carrier/Tablerate/ImportTest.php index 14fa8129532fa..4e433c380f753 100644 --- a/app/code/Magento/OfflineShipping/Test/Unit/Model/ResourceModel/Carrier/Tablerate/ImportTest.php +++ b/app/code/Magento/OfflineShipping/Test/Unit/Model/ResourceModel/Carrier/Tablerate/ImportTest.php @@ -193,7 +193,7 @@ public function testGetDataWithDuplicatedLine() /** * @expectedException \Magento\Framework\Exception\LocalizedException - * @expectedExceptionMessage Please correct Table Rates File Format. + * @expectedExceptionMessage The Table Rates File Format is incorrect. Verify the format and try again. * @SuppressWarnings(PHPMD.UnusedLocalVariable) */ public function testGetDataFromEmptyFile() diff --git a/app/code/Magento/OfflineShipping/etc/module.xml b/app/code/Magento/OfflineShipping/etc/module.xml index 7df8c8cc0db75..c65f99d59c9c5 100644 --- a/app/code/Magento/OfflineShipping/etc/module.xml +++ b/app/code/Magento/OfflineShipping/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/PageCache/etc/module.xml b/app/code/Magento/PageCache/etc/module.xml index 53420ac17d93e..17e83e7cff7d4 100644 --- a/app/code/Magento/PageCache/etc/module.xml +++ b/app/code/Magento/PageCache/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/Payment/Gateway/Command/CommandManagerPool.php b/app/code/Magento/Payment/Gateway/Command/CommandManagerPool.php index b1de33b6dad7b..6561fd42dc3c5 100644 --- a/app/code/Magento/Payment/Gateway/Command/CommandManagerPool.php +++ b/app/code/Magento/Payment/Gateway/Command/CommandManagerPool.php @@ -50,7 +50,7 @@ public function get($paymentProviderCode) { if (!isset($this->executors[$paymentProviderCode])) { throw new NotFoundException( - __('Command Executor for %1 is not defined.', $paymentProviderCode) + __('The "%1" command executor isn\'t defined. Verify the executor and try again.', $paymentProviderCode) ); } diff --git a/app/code/Magento/Payment/Gateway/Command/CommandPool.php b/app/code/Magento/Payment/Gateway/Command/CommandPool.php index f866914463d4d..9c90147b2850d 100644 --- a/app/code/Magento/Payment/Gateway/Command/CommandPool.php +++ b/app/code/Magento/Payment/Gateway/Command/CommandPool.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Payment\Gateway\Command; use Magento\Framework\ObjectManager\TMap; @@ -48,7 +49,9 @@ public function __construct( public function get($commandCode) { if (!isset($this->commands[$commandCode])) { - throw new NotFoundException(__('Command %1 does not exist.', $commandCode)); + throw new NotFoundException( + __('The "%1" command doesn\'t exist. Verify the command and try again.', $commandCode) + ); } return $this->commands[$commandCode]; diff --git a/app/code/Magento/Payment/Gateway/Http/Converter/HtmlFormConverter.php b/app/code/Magento/Payment/Gateway/Http/Converter/HtmlFormConverter.php index 82b6e8de8b068..e10d3e6693751 100644 --- a/app/code/Magento/Payment/Gateway/Http/Converter/HtmlFormConverter.php +++ b/app/code/Magento/Payment/Gateway/Http/Converter/HtmlFormConverter.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Payment\Gateway\Http\Converter; use Magento\Payment\Gateway\Http\ConverterException; @@ -29,7 +30,9 @@ public function convert($response) libxml_use_internal_errors(true); if (!$document->loadHTML($response)) { - throw new ConverterException(__('Wrong gateway response format.')); + throw new ConverterException( + __('The gateway response format was incorrect. Verify the format and try again.') + ); } libxml_use_internal_errors(false); diff --git a/app/code/Magento/Payment/Gateway/Validator/ValidatorPool.php b/app/code/Magento/Payment/Gateway/Validator/ValidatorPool.php index 91503734277f3..3a6c65a7145a1 100644 --- a/app/code/Magento/Payment/Gateway/Validator/ValidatorPool.php +++ b/app/code/Magento/Payment/Gateway/Validator/ValidatorPool.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Payment\Gateway\Validator; use Magento\Framework\Exception\NotFoundException; @@ -48,7 +49,7 @@ public function __construct( public function get($code) { if (!isset($this->validators[$code])) { - throw new NotFoundException(__('Validator for field %1 does not exist.', $code)); + throw new NotFoundException(__('The validator for the "%1" field doesn\'t exist.', $code)); } return $this->validators[$code]; diff --git a/app/code/Magento/Payment/Model/Method/Adapter.php b/app/code/Magento/Payment/Model/Method/Adapter.php index 85c1584eb44f8..6c7ef372a8854 100644 --- a/app/code/Magento/Payment/Model/Method/Adapter.php +++ b/app/code/Magento/Payment/Model/Method/Adapter.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Payment\Model\Method; use Magento\Framework\App\ObjectManager; @@ -538,7 +539,7 @@ private function executeCommand($commandCode, array $arguments = []) } if ($this->commandPool === null) { - throw new \DomainException('Command pool is not configured for use.'); + throw new \DomainException("The command pool isn't configured for use."); } $command = $this->commandPool->get($commandCode); diff --git a/app/code/Magento/Payment/etc/module.xml b/app/code/Magento/Payment/etc/module.xml index 5593a94ca0d91..ece160e6ae3eb 100644 --- a/app/code/Magento/Payment/etc/module.xml +++ b/app/code/Magento/Payment/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + 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 cb28c0ed69bbb..bbd06cd7c48f3 100644 --- a/app/code/Magento/Payment/view/frontend/templates/transparent/iframe.phtml +++ b/app/code/Magento/Payment/view/frontend/templates/transparent/iframe.phtml @@ -40,7 +40,9 @@ $params = $block->getParams(); $(parent).trigger('clearTimeout'); fullScreenLoader.stopLoader(); globalMessageList.addErrorMessage({ - message: $t('An error occurred on the server. Please try to place the order again.') + message: $t( + 'A server error stopped your order from being placed. Please try to place your order again.' + ) }); } ); diff --git a/app/code/Magento/Paypal/Controller/Express/AbstractExpress/PlaceOrder.php b/app/code/Magento/Paypal/Controller/Express/AbstractExpress/PlaceOrder.php index 1222679593f36..eb4c35b02696c 100644 --- a/app/code/Magento/Paypal/Controller/Express/AbstractExpress/PlaceOrder.php +++ b/app/code/Magento/Paypal/Controller/Express/AbstractExpress/PlaceOrder.php @@ -4,6 +4,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Paypal\Controller\Express\AbstractExpress; use Magento\Paypal\Model\Api\ProcessableException as ApiProcessableException; @@ -66,7 +67,10 @@ public function execute() !$this->agreementsValidator->isValid(array_keys($this->getRequest()->getPost('agreement', []))) ) { $e = new \Magento\Framework\Exception\LocalizedException( - __('Please agree to all the terms and conditions before placing the order.') + __( + "The order wasn't placed. " + . "First, agree to the terms and conditions, then try placing your order again." + ) ); $this->messageManager->addExceptionMessage( $e, @@ -205,6 +209,6 @@ private function redirectToOrderReviewPageAndShowError($errorMessage) protected function isValidationRequired() { return is_array($this->getRequest()->getBeforeForwardInfo()) - && empty($this->getRequest()->getBeforeForwardInfo()); + && empty($this->getRequest()->getBeforeForwardInfo()); } } diff --git a/app/code/Magento/Paypal/Gateway/Payflowpro/Command/AuthorizationCommand.php b/app/code/Magento/Paypal/Gateway/Payflowpro/Command/AuthorizationCommand.php index 2ce757cfa65d9..1dbafaf5ff0c2 100644 --- a/app/code/Magento/Paypal/Gateway/Payflowpro/Command/AuthorizationCommand.php +++ b/app/code/Magento/Paypal/Gateway/Payflowpro/Command/AuthorizationCommand.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Paypal\Gateway\Payflowpro\Command; use Magento\Framework\Exception\LocalizedException; @@ -73,7 +74,7 @@ public function execute(array $commandSubject) } catch (LocalizedException $exception) { $payment->setParentTransactionId($response->getData(Transparent::PNREF)); $this->payflowFacade->void($payment); - throw new LocalizedException(__('Error processing payment, please try again later.')); + throw new LocalizedException(__("The payment couldn't be processed at this time. Please try again later.")); } $this->payflowFacade->setTransStatus($payment, $response); diff --git a/app/code/Magento/Paypal/Model/Ipn.php b/app/code/Magento/Paypal/Model/Ipn.php index 0b12a9f26c8a2..a370bbc77ffb2 100644 --- a/app/code/Magento/Paypal/Model/Ipn.php +++ b/app/code/Magento/Paypal/Model/Ipn.php @@ -106,7 +106,7 @@ protected function _getConfig() $parameters = ['params' => [$methodCode, $order->getStoreId()]]; $this->_config = $this->_configFactory->create($parameters); if (!$this->_config->isMethodActive($methodCode) || !$this->_config->isMethodAvailable()) { - throw new Exception(sprintf('Method "%s" is not available.', $methodCode)); + throw new Exception(sprintf('The "%s" method isn\'t available.', $methodCode)); } /** @link https://cms.paypal.com/cgi-bin/marketingweb?cmd=_render-content&content_ID= * developer/e_howto_admin_IPNIntro */ @@ -118,7 +118,11 @@ protected function _getConfig() $receiver = $this->getRequestData('business') ?: $this->getRequestData('receiver_email'); if (strtolower($merchantEmail) != strtolower($receiver)) { throw new Exception( - sprintf('The requested %s and configured %s merchant emails do not match.', $receiver, $merchantEmail) + sprintf( + 'The requested "%s" and the configured "%s" merchant emails don\'t match.', + $receiver, + $merchantEmail + ) ); } @@ -136,7 +140,7 @@ protected function _getOrder() $incrementId = $this->getRequestData('invoice'); $this->_order = $this->_orderFactory->create()->loadByIncrementId($incrementId); if (!$this->_order->getId()) { - throw new Exception(sprintf('Wrong order ID: "%s".', $incrementId)); + throw new Exception(sprintf('The "%s" order ID is incorrect. Verify the ID and try again.', $incrementId)); } return $this->_order; } @@ -266,7 +270,7 @@ protected function _registerTransaction() $this->_registerPaymentVoid(); break; default: - throw new Exception("Cannot handle payment status '{$paymentStatus}'."); + throw new Exception("The '{$paymentStatus}' payment status couldn't be handled."); } } @@ -370,7 +374,7 @@ public function _registerPaymentPending() return; } if ('order' === $reason) { - throw new Exception('The "order" authorizations are not implemented.'); + throw new Exception('The "order" authorizations aren\'t implemented.'); } // case when was placed using PayPal standard if (\Magento\Sales\Model\Order::STATE_PENDING_PAYMENT == $this->_order->getState() diff --git a/app/code/Magento/Paypal/Model/Payflow/Transparent.php b/app/code/Magento/Paypal/Model/Payflow/Transparent.php index c161580c1b7f1..c308731c69527 100644 --- a/app/code/Magento/Paypal/Model/Payflow/Transparent.php +++ b/app/code/Magento/Paypal/Model/Payflow/Transparent.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Paypal\Model\Payflow; use Magento\Payment\Helper\Formatter; @@ -177,7 +178,7 @@ public function authorize(InfoInterface $payment, $amount) } catch (LocalizedException $exception) { $payment->setParentTransactionId($response->getData(self::PNREF)); $this->void($payment); - throw new LocalizedException(__('Error processing payment. Please try again later.')); + throw new LocalizedException(__("The payment couldn't be processed at this time. Please try again later.")); } $this->setTransStatus($payment, $response); diff --git a/app/code/Magento/Paypal/Model/Payflowpro.php b/app/code/Magento/Paypal/Model/Payflowpro.php index 0e8d6db5e9a28..125aa0f6e65a7 100644 --- a/app/code/Magento/Paypal/Model/Payflowpro.php +++ b/app/code/Magento/Paypal/Model/Payflowpro.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Paypal\Model; use Magento\Framework\DataObject; @@ -653,7 +654,7 @@ public function processErrors(DataObject $response) { if ($response->getResultCode() == self::RESPONSE_CODE_VOID_ERROR) { throw new \Magento\Framework\Exception\State\InvalidTransitionException( - __('You cannot void a verification transaction.') + __("The verification transaction can't be voided. ") ); } elseif ($response->getResultCode() != self::RESPONSE_CODE_APPROVED && $response->getResultCode() != self::RESPONSE_CODE_FRAUDSERVICE_FILTER diff --git a/app/code/Magento/Paypal/Setup/InstallData.php b/app/code/Magento/Paypal/Setup/InstallData.php deleted file mode 100644 index 688d7dabb2ceb..0000000000000 --- a/app/code/Magento/Paypal/Setup/InstallData.php +++ /dev/null @@ -1,83 +0,0 @@ -salesSetupFactory = $salesSetupFactory; - $this->quoteSetupFactory = $quoteSetupFactory; - } - - /** - * {@inheritdoc} - */ - public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context) - { - /** - * Prepare database for install - */ - $setup->startSetup(); - - $quoteInstaller = $this->quoteSetupFactory->create(['resourceName' => 'quote_setup', 'setup' => $setup]); - $salesInstaller = $this->salesSetupFactory->create(['resourceName' => 'sales_setup', 'setup' => $setup]); - /** - * Add paypal attributes to the: - * - sales/flat_quote_payment_item table - * - sales/flat_order table - */ - $quoteInstaller->addAttribute('quote_payment', 'paypal_payer_id', []); - $quoteInstaller->addAttribute('quote_payment', 'paypal_payer_status', []); - $quoteInstaller->addAttribute('quote_payment', 'paypal_correlation_id', []); - $salesInstaller->addAttribute( - 'order', - 'paypal_ipn_customer_notified', - ['type' => 'int', 'visible' => false, 'default' => 0] - ); - - $data = []; - $statuses = [ - 'pending_paypal' => __('Pending PayPal'), - 'paypal_reversed' => __('PayPal Reversed'), - 'paypal_canceled_reversal' => __('PayPal Canceled Reversal'), - ]; - foreach ($statuses as $code => $info) { - $data[] = ['status' => $code, 'label' => $info]; - } - $setup->getConnection() - ->insertArray($setup->getTable('sales_order_status'), ['status', 'label'], $data); - - /** - * Prepare database after install - */ - $setup->endSetup(); - } -} diff --git a/app/code/Magento/Paypal/Setup/Patch/Data/AddPaypalOrderStatuses.php b/app/code/Magento/Paypal/Setup/Patch/Data/AddPaypalOrderStatuses.php new file mode 100644 index 0000000000000..2689d6ab26b82 --- /dev/null +++ b/app/code/Magento/Paypal/Setup/Patch/Data/AddPaypalOrderStatuses.php @@ -0,0 +1,120 @@ +moduleDataSetup = $moduleDataSetup; + $this->quoteSetupFactory = $quoteSetupFactory; + $this->salesSetupFactory = $salesSetupFactory; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + /** + * Prepare database for install + */ + $this->moduleDataSetup->getConnection()->startSetup(); + + $quoteInstaller = $this->quoteSetupFactory->create(); + $salesInstaller = $this->salesSetupFactory->create(); + /** + * Add paypal attributes to the: + * - sales/flat_quote_payment_item table + * - sales/flat_order table + */ + $quoteInstaller->addAttribute('quote_payment', 'paypal_payer_id', []); + $quoteInstaller->addAttribute('quote_payment', 'paypal_payer_status', []); + $quoteInstaller->addAttribute('quote_payment', 'paypal_correlation_id', []); + $salesInstaller->addAttribute( + 'order', + 'paypal_ipn_customer_notified', + ['type' => 'int', 'visible' => false, 'default' => 0] + ); + $data = []; + $statuses = [ + 'pending_paypal' => __('Pending PayPal'), + 'paypal_reversed' => __('PayPal Reversed'), + 'paypal_canceled_reversal' => __('PayPal Canceled Reversal'), + ]; + foreach ($statuses as $code => $info) { + $data[] = ['status' => $code, 'label' => $info]; + } + $this->moduleDataSetup->getConnection()->insertArray( + $this->moduleDataSetup->getTable('sales_order_status'), + ['status', 'label'], + $data + ); + /** + * Prepare database after install + */ + $this->moduleDataSetup->getConnection()->endSetup(); + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return []; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.0'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } +} 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 9b67cedb47885..e6a994cba78c3 100644 --- a/app/code/Magento/Paypal/Test/Unit/Model/Payflow/TransparentTest.php +++ b/app/code/Magento/Paypal/Test/Unit/Model/Payflow/TransparentTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Paypal\Test\Unit\Model\Payflow; use Magento\Paypal\Block\Payment\Info; @@ -277,7 +278,7 @@ public function testAuthorizeException() /** * @expectedException \Magento\Framework\Exception\LocalizedException - * @expectedExceptionMessage Error processing payment. Please try again later. + * @expectedExceptionMessage The payment couldn't be processed at this time. Please try again later. */ public function testAuthorizeValidationException() { diff --git a/app/code/Magento/Paypal/etc/module.xml b/app/code/Magento/Paypal/etc/module.xml index 056fc1a80e8ac..3049d9a2891b4 100644 --- a/app/code/Magento/Paypal/etc/module.xml +++ b/app/code/Magento/Paypal/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/Persistent/etc/module.xml b/app/code/Magento/Persistent/etc/module.xml index 452130810c4bb..4f6e0744ce6ef 100644 --- a/app/code/Magento/Persistent/etc/module.xml +++ b/app/code/Magento/Persistent/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/ProductAlert/Controller/Add/Price.php b/app/code/Magento/ProductAlert/Controller/Add/Price.php index 6effaacd9624d..04e623105e645 100644 --- a/app/code/Magento/ProductAlert/Controller/Add/Price.php +++ b/app/code/Magento/ProductAlert/Controller/Add/Price.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\ProductAlert\Controller\Add; use Magento\ProductAlert\Controller\Add as AddController; @@ -98,7 +99,10 @@ public function execute() } return $resultRedirect; } catch (\Exception $e) { - $this->messageManager->addException($e, __('We can\'t update the alert subscription right now.')); + $this->messageManager->addException( + $e, + __("The alert subscription couldn't update at this time. Please try again later.") + ); } $resultRedirect->setUrl($this->_redirect->getRedirectUrl()); return $resultRedirect; diff --git a/app/code/Magento/ProductAlert/Controller/Add/Stock.php b/app/code/Magento/ProductAlert/Controller/Add/Stock.php index 5b89b4b327ee0..56d052f7e11e2 100644 --- a/app/code/Magento/ProductAlert/Controller/Add/Stock.php +++ b/app/code/Magento/ProductAlert/Controller/Add/Stock.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\ProductAlert\Controller\Add; use Magento\ProductAlert\Controller\Add as AddController; @@ -67,7 +68,10 @@ public function execute() $resultRedirect->setUrl($backUrl); return $resultRedirect; } catch (\Exception $e) { - $this->messageManager->addException($e, __('We can\'t update the alert subscription right now.')); + $this->messageManager->addException( + $e, + __("The alert subscription couldn't update at this time. Please try again later.") + ); } $resultRedirect->setUrl($this->_redirect->getRedirectUrl()); return $resultRedirect; diff --git a/app/code/Magento/ProductAlert/Controller/Unsubscribe/Price.php b/app/code/Magento/ProductAlert/Controller/Unsubscribe/Price.php index 9adf15a2e1347..2077b1ff2794b 100644 --- a/app/code/Magento/ProductAlert/Controller/Unsubscribe/Price.php +++ b/app/code/Magento/ProductAlert/Controller/Unsubscribe/Price.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\ProductAlert\Controller\Unsubscribe; use Magento\ProductAlert\Controller\Unsubscribe as UnsubscribeController; @@ -68,11 +69,14 @@ public function execute() $this->messageManager->addSuccess(__('You deleted the alert subscription.')); } catch (NoSuchEntityException $noEntityException) { - $this->messageManager->addError(__('We can\'t find the product.')); + $this->messageManager->addError(__("The product wasn't found. Verify the product and try again.")); $resultRedirect->setPath('customer/account/'); return $resultRedirect; } catch (\Exception $e) { - $this->messageManager->addException($e, __('We can\'t update the alert subscription right now.')); + $this->messageManager->addException( + $e, + __("The alert subscription couldn't update at this time. Please try again later.") + ); } $resultRedirect->setUrl($product->getProductUrl()); return $resultRedirect; diff --git a/app/code/Magento/ProductAlert/Controller/Unsubscribe/Stock.php b/app/code/Magento/ProductAlert/Controller/Unsubscribe/Stock.php index 84ebbaecaaf69..7a6aeb40eb5b7 100644 --- a/app/code/Magento/ProductAlert/Controller/Unsubscribe/Stock.php +++ b/app/code/Magento/ProductAlert/Controller/Unsubscribe/Stock.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\ProductAlert\Controller\Unsubscribe; use Magento\ProductAlert\Controller\Unsubscribe as UnsubscribeController; @@ -70,7 +71,10 @@ public function execute() $resultRedirect->setPath('customer/account/'); return $resultRedirect; } catch (\Exception $e) { - $this->messageManager->addException($e, __('We can\'t update the alert subscription right now.')); + $this->messageManager->addException( + $e, + __("The alert subscription couldn't update at this time. Please try again later.") + ); } $resultRedirect->setUrl($product->getProductUrl()); return $resultRedirect; diff --git a/app/code/Magento/ProductAlert/etc/module.xml b/app/code/Magento/ProductAlert/etc/module.xml index 699faf4b9133b..4d519294ae7ab 100644 --- a/app/code/Magento/ProductAlert/etc/module.xml +++ b/app/code/Magento/ProductAlert/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/ProductVideo/Controller/Adminhtml/Product/Gallery/RetrieveImage.php b/app/code/Magento/ProductVideo/Controller/Adminhtml/Product/Gallery/RetrieveImage.php index 9950526182e3e..23721cb4b1658 100644 --- a/app/code/Magento/ProductVideo/Controller/Adminhtml/Product/Gallery/RetrieveImage.php +++ b/app/code/Magento/ProductVideo/Controller/Adminhtml/Product/Gallery/RetrieveImage.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\ProductVideo\Controller\Adminhtml\Product\Gallery; use Magento\Framework\App\Filesystem\DirectoryList; @@ -199,7 +200,7 @@ protected function retrieveRemoteImage($fileUrl, $localFilePath) $image = $this->curl->read(); if (empty($image)) { throw new LocalizedException( - __('Could not get preview image information. Please check your connection and try again.') + __('The preview image information is unavailable. Check your connection and try again.') ); } $this->fileUtility->saveFile($localFilePath, $image); diff --git a/app/code/Magento/ProductVideo/etc/module.xml b/app/code/Magento/ProductVideo/etc/module.xml index f1f37374ceec5..ac3b6b4f7326b 100644 --- a/app/code/Magento/ProductVideo/etc/module.xml +++ b/app/code/Magento/ProductVideo/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/Quote/Api/GuestShippingMethodManagementInterface.php b/app/code/Magento/Quote/Api/GuestShippingMethodManagementInterface.php index 143b9638835e5..29baac025282c 100644 --- a/app/code/Magento/Quote/Api/GuestShippingMethodManagementInterface.php +++ b/app/code/Magento/Quote/Api/GuestShippingMethodManagementInterface.php @@ -18,7 +18,7 @@ interface GuestShippingMethodManagementInterface * @param string $cartId The shopping cart ID. * @return \Magento\Quote\Api\Data\ShippingMethodInterface[] An array of shipping methods. * @throws \Magento\Framework\Exception\NoSuchEntityException The specified quote does not exist. - * @throws \Magento\Framework\Exception\StateException The shipping address is not set. + * @throws \Magento\Framework\Exception\StateException The shipping address is missing. */ public function getList($cartId); diff --git a/app/code/Magento/Quote/Api/ShippingMethodManagementInterface.php b/app/code/Magento/Quote/Api/ShippingMethodManagementInterface.php index 21905ecabf57f..c6d51857a8d54 100644 --- a/app/code/Magento/Quote/Api/ShippingMethodManagementInterface.php +++ b/app/code/Magento/Quote/Api/ShippingMethodManagementInterface.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Quote\Api; /** @@ -37,7 +38,7 @@ public function estimateByAddressId($cartId, $addressId); * @param int $cartId The shopping cart ID. * @return \Magento\Quote\Api\Data\ShippingMethodInterface[] An array of shipping methods. * @throws \Magento\Framework\Exception\NoSuchEntityException The specified quote does not exist. - * @throws \Magento\Framework\Exception\StateException The shipping address is not set. + * @throws \Magento\Framework\Exception\StateException The shipping address is missing. */ public function getList($cartId); } diff --git a/app/code/Magento/Quote/Model/BillingAddressManagement.php b/app/code/Magento/Quote/Model/BillingAddressManagement.php index 2cbca917c26a1..70a8c94fefad0 100644 --- a/app/code/Magento/Quote/Model/BillingAddressManagement.php +++ b/app/code/Magento/Quote/Model/BillingAddressManagement.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Quote\Model; use Magento\Framework\Exception\InputException; @@ -84,7 +85,7 @@ public function assign($cartId, \Magento\Quote\Api\Data\AddressInterface $addres $this->quoteRepository->save($quote); } catch (\Exception $e) { $this->logger->critical($e); - throw new InputException(__('Unable to save address. Please check input data.')); + throw new InputException(__('The address failed to save. Verify the address and try again.')); } return $quote->getBillingAddress()->getId(); } diff --git a/app/code/Magento/Quote/Model/CouponManagement.php b/app/code/Magento/Quote/Model/CouponManagement.php index 7701e41e0b55a..62515a17f268b 100644 --- a/app/code/Magento/Quote/Model/CouponManagement.php +++ b/app/code/Magento/Quote/Model/CouponManagement.php @@ -53,7 +53,7 @@ public function set($cartId, $couponCode) /** @var \Magento\Quote\Model\Quote $quote */ $quote = $this->quoteRepository->getActive($cartId); if (!$quote->getItemsCount()) { - throw new NoSuchEntityException(__('Cart %1 doesn\'t contain products', $cartId)); + throw new NoSuchEntityException(__('The "%1" Cart doesn\'t contain products.', $cartId)); } $quote->getShippingAddress()->setCollectShippingRates(true); @@ -61,10 +61,12 @@ public function set($cartId, $couponCode) $quote->setCouponCode($couponCode); $this->quoteRepository->save($quote->collectTotals()); } catch (\Exception $e) { - throw new CouldNotSaveException(__('Could not apply coupon code')); + throw new CouldNotSaveException( + __("The coupon code couldn't be applied. Verify the coupon code and try again.") + ); } if ($quote->getCouponCode() != $couponCode) { - throw new NoSuchEntityException(__('Coupon code is not valid')); + throw new NoSuchEntityException(__("The coupon code isn't valid. Verify the code and try again.")); } return true; } @@ -77,17 +79,21 @@ public function remove($cartId) /** @var \Magento\Quote\Model\Quote $quote */ $quote = $this->quoteRepository->getActive($cartId); if (!$quote->getItemsCount()) { - throw new NoSuchEntityException(__('Cart %1 doesn\'t contain products', $cartId)); + throw new NoSuchEntityException(__('The "%1" Cart doesn\'t contain products.', $cartId)); } $quote->getShippingAddress()->setCollectShippingRates(true); try { $quote->setCouponCode(''); $this->quoteRepository->save($quote->collectTotals()); } catch (\Exception $e) { - throw new CouldNotDeleteException(__('Could not delete coupon code')); + throw new CouldNotDeleteException( + __("The coupon code couldn't be deleted. Verify the coupon code and try again.") + ); } if ($quote->getCouponCode() != '') { - throw new CouldNotDeleteException(__('Could not delete coupon code')); + throw new CouldNotDeleteException( + __("The coupon code couldn't be deleted. Verify the coupon code and try again.") + ); } return true; } diff --git a/app/code/Magento/Quote/Model/GuestCart/GuestShippingMethodManagementInterface.php b/app/code/Magento/Quote/Model/GuestCart/GuestShippingMethodManagementInterface.php index e8109a0ac0cee..1cc1a3c8fcbfd 100644 --- a/app/code/Magento/Quote/Model/GuestCart/GuestShippingMethodManagementInterface.php +++ b/app/code/Magento/Quote/Model/GuestCart/GuestShippingMethodManagementInterface.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Quote\Model\GuestCart; /** @@ -20,7 +21,7 @@ interface GuestShippingMethodManagementInterface * @return bool * @throws \Magento\Framework\Exception\InputException The shipping method is not valid for an empty cart. * @throws \Magento\Framework\Exception\CouldNotSaveException The shipping method could not be saved. - * @throws \Magento\Framework\Exception\StateException The billing or shipping address is not set. + * @throws \Magento\Framework\Exception\StateException The billing or shipping address is missing. * @throws \Magento\Framework\Exception\NoSuchEntityException The specified cart contains only virtual products * so the shipping method does not apply. */ @@ -32,7 +33,7 @@ public function set($cartId, $carrierCode, $methodCode); * @param string $cartId The shopping cart ID. * @return \Magento\Quote\Api\Data\ShippingMethodInterface Shipping method. * @throws \Magento\Framework\Exception\NoSuchEntityException The specified shopping cart does not exist. - * @throws \Magento\Framework\Exception\StateException The shipping address is not set. + * @throws \Magento\Framework\Exception\StateException The shipping address is missing. */ public function get($cartId); } diff --git a/app/code/Magento/Quote/Model/GuestCartManagement/Plugin/Authorization.php b/app/code/Magento/Quote/Model/GuestCartManagement/Plugin/Authorization.php index e8aeed63e74a2..5d83757321f7d 100644 --- a/app/code/Magento/Quote/Model/GuestCartManagement/Plugin/Authorization.php +++ b/app/code/Magento/Quote/Model/GuestCartManagement/Plugin/Authorization.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Quote\Model\GuestCartManagement\Plugin; use Magento\Framework\Exception\StateException; @@ -40,7 +41,7 @@ public function beforeAssignCustomer( ) { if ($customerId !== (int)$this->userContext->getUserId()) { throw new StateException( - __('Cannot assign customer to the given cart. You don\'t have permission for this operation.') + __("You don't have the correct permissions to assign the customer to the cart.") ); } } diff --git a/app/code/Magento/Quote/Model/PaymentMethodManagement.php b/app/code/Magento/Quote/Model/PaymentMethodManagement.php index f12b9e5d1fb7f..91d8fe4dbcffd 100644 --- a/app/code/Magento/Quote/Model/PaymentMethodManagement.php +++ b/app/code/Magento/Quote/Model/PaymentMethodManagement.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Quote\Model; use Magento\Framework\Exception\State\InvalidTransitionException; @@ -68,7 +69,9 @@ public function set($cartId, \Magento\Quote\Api\Data\PaymentInterface $method) } else { // check if shipping address is set if ($quote->getShippingAddress()->getCountryId() === null) { - throw new InvalidTransitionException(__('Shipping address is not set')); + throw new InvalidTransitionException( + __('The shipping address is missing. Set the address and try again.') + ); } $quote->getShippingAddress()->setPaymentMethod($payment->getMethod()); } diff --git a/app/code/Magento/Quote/Model/Quote/Item/CartItemPersister.php b/app/code/Magento/Quote/Model/Quote/Item/CartItemPersister.php index e29364d41b498..9b5f5c9a126df 100644 --- a/app/code/Magento/Quote/Model/Quote/Item/CartItemPersister.php +++ b/app/code/Magento/Quote/Model/Quote/Item/CartItemPersister.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Quote\Model\Quote\Item; use Magento\Quote\Api\Data\CartInterface; @@ -62,7 +63,7 @@ public function save(CartInterface $quote, CartItemInterface $item) $currentItem = $quote->getItemById($itemId); if (!$currentItem) { throw new NoSuchEntityException( - __('Cart %1 does not contain item %2', $cartId, $itemId) + __('The %1 Cart doesn\'t contain the %2 item.', $cartId, $itemId) ); } $productType = $currentItem->getProduct()->getTypeId(); @@ -99,7 +100,7 @@ public function save(CartInterface $quote, CartItemInterface $item) } catch (LocalizedException $e) { throw $e; } catch (\Exception $e) { - throw new CouldNotSaveException(__('Could not save quote')); + throw new CouldNotSaveException(__("The quote couldn't be saved.")); } $itemId = $item->getId(); foreach ($quote->getAllItems() as $quoteItem) { @@ -109,6 +110,6 @@ public function save(CartInterface $quote, CartItemInterface $item) return $this->cartItemOptionProcessor->applyCustomOptions($item); } } - throw new CouldNotSaveException(__('Could not save quote')); + throw new CouldNotSaveException(__("The quote couldn't be saved.")); } } diff --git a/app/code/Magento/Quote/Model/Quote/Item/Repository.php b/app/code/Magento/Quote/Model/Quote/Item/Repository.php index d8238628e0eaa..1fb0a2d7107f1 100644 --- a/app/code/Magento/Quote/Model/Quote/Item/Repository.php +++ b/app/code/Magento/Quote/Model/Quote/Item/Repository.php @@ -4,6 +4,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Quote\Model\Quote\Item; use Magento\Framework\App\ObjectManager; @@ -103,14 +104,14 @@ public function deleteById($cartId, $itemId) $quoteItem = $quote->getItemById($itemId); if (!$quoteItem) { throw new NoSuchEntityException( - __('Cart %1 doesn\'t contain item %2', $cartId, $itemId) + __('The %1 Cart doesn\'t contain the %2 item.', $cartId, $itemId) ); } try { $quote->removeItem($itemId); $this->quoteRepository->save($quote); } catch (\Exception $e) { - throw new CouldNotSaveException(__('Could not remove item from quote')); + throw new CouldNotSaveException(__("The item couldn't be removed from the quote.")); } return true; diff --git a/app/code/Magento/Quote/Model/QuoteManagement.php b/app/code/Magento/Quote/Model/QuoteManagement.php index b2cd613ba46a1..d062c0b4d05c1 100644 --- a/app/code/Magento/Quote/Model/QuoteManagement.php +++ b/app/code/Magento/Quote/Model/QuoteManagement.php @@ -235,7 +235,7 @@ public function createEmptyCart() $quote->getShippingAddress()->setCollectShippingRates(true); $this->quoteRepository->save($quote); } catch (\Exception $e) { - throw new CouldNotSaveException(__('Cannot create quote')); + throw new CouldNotSaveException(__("The quote can't be created.")); } return $quote->getId(); } @@ -251,7 +251,7 @@ public function createEmptyCartForCustomer($customerId) try { $this->quoteRepository->save($quote); } catch (\Exception $e) { - throw new CouldNotSaveException(__('Cannot create quote')); + throw new CouldNotSaveException(__("The quote can't be created.")); } return $quote->getId(); } @@ -267,18 +267,18 @@ public function assignCustomer($cartId, $customerId, $storeId) if (!in_array($storeId, $customerModel->load($customerId)->getSharedStoreIds())) { throw new StateException( - __('Cannot assign customer to the given cart. The cart belongs to different store.') + __("The customer can't be assigned to the cart. The cart belongs to a different store.") ); } if ($quote->getCustomerId()) { throw new StateException( - __('Cannot assign customer to the given cart. The cart is not anonymous.') + __("The customer can't be assigned to the cart because the cart isn't anonymous.") ); } try { $this->quoteRepository->getForCustomer($customerId); throw new StateException( - __('Cannot assign customer to the given cart. Customer already has active cart.') + __("The customer can't be assigned to the cart because the customer already has an active cart.") ); } catch (\Magento\Framework\Exception\NoSuchEntityException $e) { } @@ -364,7 +364,7 @@ public function placeOrder($cartId, PaymentInterface $paymentMethod = null) if (null == $order) { throw new LocalizedException( - __('An error occurred on the server. Please try to place the order again.') + __('A server error stopped your order from being placed. Please try to place your order again.') ); } diff --git a/app/code/Magento/Quote/Model/QuoteValidator.php b/app/code/Magento/Quote/Model/QuoteValidator.php index 8d46832df8db2..1f6deca4c1d74 100644 --- a/app/code/Magento/Quote/Model/QuoteValidator.php +++ b/app/code/Magento/Quote/Model/QuoteValidator.php @@ -90,14 +90,16 @@ public function validateBeforeSubmit(QuoteEntity $quote) $this->allowedCountryReader->getAllowedCountries() )) { throw new \Magento\Framework\Exception\LocalizedException( - __('Some addresses cannot be used due to country-specific configurations.') + __("Some addresses can't be used due to the configurations for specific countries.") ); } $method = $quote->getShippingAddress()->getShippingMethod(); $rate = $quote->getShippingAddress()->getShippingRateByCode($method); if (!$method || !$rate) { - throw new \Magento\Framework\Exception\LocalizedException(__('Please specify a shipping method.')); + throw new \Magento\Framework\Exception\LocalizedException( + __('The shipping method is missing. Select the shipping method and try again.') + ); } } if ($quote->getBillingAddress()->validate() !== true) { @@ -109,7 +111,9 @@ public function validateBeforeSubmit(QuoteEntity $quote) ); } if (!$quote->getPayment()->getMethod()) { - throw new \Magento\Framework\Exception\LocalizedException(__('Please select a valid payment method.')); + throw new \Magento\Framework\Exception\LocalizedException( + __('Enter a valid payment method and try again. ') + ); } if (!$quote->validateMinimumAmount($quote->getIsMultiShipping())) { throw new LocalizedException($this->minimumAmountMessage->getMessage()); diff --git a/app/code/Magento/Quote/Model/ShippingAddressManagement.php b/app/code/Magento/Quote/Model/ShippingAddressManagement.php index 0e2be5c9e3692..d8e70c68ba33f 100644 --- a/app/code/Magento/Quote/Model/ShippingAddressManagement.php +++ b/app/code/Magento/Quote/Model/ShippingAddressManagement.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Quote\Model; use Magento\Framework\App\ObjectManager; @@ -87,7 +88,7 @@ public function assign($cartId, \Magento\Quote\Api\Data\AddressInterface $addres $quote = $this->quoteRepository->getActive($cartId); if ($quote->isVirtual()) { throw new NoSuchEntityException( - __('Cart contains virtual product(s) only. Shipping address is not applicable.') + __('The Cart includes virtual product(s) only, so a shipping address is not used.') ); } @@ -116,7 +117,7 @@ public function assign($cartId, \Magento\Quote\Api\Data\AddressInterface $addres $address->save(); } catch (\Exception $e) { $this->logger->critical($e); - throw new InputException(__('Unable to save address. Please check input data.')); + throw new InputException(__('The address failed to save. Verify the address and try again.')); } return $quote->getShippingAddress()->getId(); } @@ -130,7 +131,7 @@ public function get($cartId) $quote = $this->quoteRepository->getActive($cartId); if ($quote->isVirtual()) { throw new NoSuchEntityException( - __('Cart contains virtual product(s) only. Shipping address is not applicable.') + __('The Cart includes virtual product(s) only, so a shipping address is not used.') ); } /** @var \Magento\Quote\Model\Quote\Address $address */ diff --git a/app/code/Magento/Quote/Model/ShippingMethodManagement.php b/app/code/Magento/Quote/Model/ShippingMethodManagement.php index 5d7160d8c384a..ade2649d0b1b0 100644 --- a/app/code/Magento/Quote/Model/ShippingMethodManagement.php +++ b/app/code/Magento/Quote/Model/ShippingMethodManagement.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Quote\Model; use Magento\Customer\Api\Data\AddressInterfaceFactory; @@ -97,7 +98,7 @@ public function get($cartId) /** @var \Magento\Quote\Model\Quote\Address $shippingAddress */ $shippingAddress = $quote->getShippingAddress(); if (!$shippingAddress->getCountryId()) { - throw new StateException(__('Shipping address not set.')); + throw new StateException(__('The shipping address is missing. Set the address and try again.')); } $shippingMethod = $shippingAddress->getShippingMethod(); @@ -131,7 +132,7 @@ public function getList($cartId) $shippingAddress = $quote->getShippingAddress(); if (!$shippingAddress->getCountryId()) { - throw new StateException(__('Shipping address not set.')); + throw new StateException(__('The shipping address is missing. Set the address and try again.')); } $shippingAddress->collectShippingRates(); $shippingRates = $shippingAddress->getGroupedAllShippingRates(); @@ -159,7 +160,7 @@ public function set($cartId, $carrierCode, $methodCode) try { $this->quoteRepository->save($quote->collectTotals()); } catch (\Exception $e) { - throw new CouldNotSaveException(__('Cannot set shipping method. %1', $e->getMessage())); + throw new CouldNotSaveException(__('The shipping method can\'t be set. %1', $e->getMessage())); } return true; } @@ -171,24 +172,26 @@ public function set($cartId, $carrierCode, $methodCode) * @return void * @throws InputException The shipping method is not valid for an empty cart. * @throws CouldNotSaveException The shipping method could not be saved. - * @throws NoSuchEntityException Cart contains only virtual products. Shipping method is not applicable. - * @throws StateException The billing or shipping address is not set. + * @throws NoSuchEntityException CThe Cart includes virtual product(s) only, so a shipping address is not used. + * @throws StateException The billing or shipping address is missing. Set the address and try again. */ public function apply($cartId, $carrierCode, $methodCode) { /** @var \Magento\Quote\Model\Quote $quote */ $quote = $this->quoteRepository->getActive($cartId); if (0 == $quote->getItemsCount()) { - throw new InputException(__('Shipping method is not applicable for empty cart')); + throw new InputException( + __('The shipping method can\'t be set for an empty cart. Add an item to cart and try again.') + ); } if ($quote->isVirtual()) { throw new NoSuchEntityException( - __('Cart contains virtual product(s) only. Shipping method is not applicable.') + __('The Cart includes virtual product(s) only, so a shipping address is not used.') ); } $shippingAddress = $quote->getShippingAddress(); if (!$shippingAddress->getCountryId()) { - throw new StateException(__('Shipping address is not set')); + throw new StateException(__('The shipping address is missing. Set the address and try again.')); } $shippingAddress->setShippingMethod($carrierCode . '_' . $methodCode); } diff --git a/app/code/Magento/Quote/Model/ShippingMethodManagementInterface.php b/app/code/Magento/Quote/Model/ShippingMethodManagementInterface.php index eef2dc3abf09f..64dc7be46d2a1 100644 --- a/app/code/Magento/Quote/Model/ShippingMethodManagementInterface.php +++ b/app/code/Magento/Quote/Model/ShippingMethodManagementInterface.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Quote\Model; /** @@ -20,7 +21,7 @@ interface ShippingMethodManagementInterface * @return bool * @throws \Magento\Framework\Exception\InputException The shipping method is not valid for an empty cart. * @throws \Magento\Framework\Exception\CouldNotSaveException The shipping method could not be saved. - * @throws \Magento\Framework\Exception\StateException The billing or shipping address is not set. + * @throws \Magento\Framework\Exception\StateException The billing or shipping address is missing. * @throws \Magento\Framework\Exception\NoSuchEntityException The specified cart contains only virtual products * so the shipping method does not apply. */ @@ -32,7 +33,7 @@ public function set($cartId, $carrierCode, $methodCode); * @param int $cartId The shopping cart ID. * @return \Magento\Quote\Api\Data\ShippingMethodInterface Shipping method. * @throws \Magento\Framework\Exception\NoSuchEntityException The specified shopping cart does not exist. - * @throws \Magento\Framework\Exception\StateException The shipping address is not set. + * @throws \Magento\Framework\Exception\StateException The shipping address is missing. */ public function get($cartId); } diff --git a/app/code/Magento/Quote/Setup/InstallData.php b/app/code/Magento/Quote/Setup/InstallData.php deleted file mode 100644 index f039c15797c27..0000000000000 --- a/app/code/Magento/Quote/Setup/InstallData.php +++ /dev/null @@ -1,59 +0,0 @@ -quoteSetupFactory = $setupFactory; - } - - /** - * {@inheritdoc} - */ - public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context) - { - /** @var QuoteSetup $quoteSetup */ - $quoteSetup = $this->quoteSetupFactory->create(['setup' => $setup]); - - /** - * Install eav entity types to the eav/entity_type table - */ - $attributes = [ - 'vat_id' => ['type' => Table::TYPE_TEXT], - 'vat_is_valid' => ['type' => Table::TYPE_SMALLINT], - 'vat_request_id' => ['type' => Table::TYPE_TEXT], - 'vat_request_date' => ['type' => Table::TYPE_TEXT], - 'vat_request_success' => ['type' => Table::TYPE_SMALLINT], - ]; - - foreach ($attributes as $attributeCode => $attributeParams) { - $quoteSetup->addAttribute('quote_address', $attributeCode, $attributeParams); - } - } -} diff --git a/app/code/Magento/Quote/Setup/Patch/Data/ConvertSerializedDataToJson.php b/app/code/Magento/Quote/Setup/Patch/Data/ConvertSerializedDataToJson.php new file mode 100644 index 0000000000000..eb190f001409d --- /dev/null +++ b/app/code/Magento/Quote/Setup/Patch/Data/ConvertSerializedDataToJson.php @@ -0,0 +1,84 @@ +moduleDataSetup = $moduleDataSetup; + $this->quoteSetupFactory = $quoteSetupFactory; + $this->convertSerializedDataToJsonFactory = $convertSerializedDataToJsonFactory; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + $quoteSetup = $this->quoteSetupFactory->create(); + $this->convertSerializedDataToJsonFactory->create(['quoteSetup' => $quoteSetup])->convert(); + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return [ + InstallEntityTypes::class + ]; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.6'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } +} diff --git a/app/code/Magento/Quote/Setup/Patch/Data/InstallEntityTypes.php b/app/code/Magento/Quote/Setup/Patch/Data/InstallEntityTypes.php new file mode 100644 index 0000000000000..59c821a0afeec --- /dev/null +++ b/app/code/Magento/Quote/Setup/Patch/Data/InstallEntityTypes.php @@ -0,0 +1,90 @@ +moduleDataSetup = $moduleDataSetup; + $this->quoteSetupFactory = $quoteSetupFactory; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + /** @var QuoteSetup $quoteSetup */ + $quoteSetup = $this->quoteSetupFactory->create(['setup' => $this->moduleDataSetup]); + + /** + * Install eav entity types to the eav/entity_type table + */ + $attributes = [ + 'vat_id' => ['type' => Table::TYPE_TEXT], + 'vat_is_valid' => ['type' => Table::TYPE_SMALLINT], + 'vat_request_id' => ['type' => Table::TYPE_TEXT], + 'vat_request_date' => ['type' => Table::TYPE_TEXT], + 'vat_request_success' => ['type' => Table::TYPE_SMALLINT], + ]; + foreach ($attributes as $attributeCode => $attributeParams) { + $quoteSetup->addAttribute('quote_address', $attributeCode, $attributeParams); + } + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return []; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.0'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } +} diff --git a/app/code/Magento/Quote/Setup/UpgradeData.php b/app/code/Magento/Quote/Setup/UpgradeData.php deleted file mode 100644 index fde232c2e593b..0000000000000 --- a/app/code/Magento/Quote/Setup/UpgradeData.php +++ /dev/null @@ -1,49 +0,0 @@ -quoteSetupFactory = $quoteSetupFactory; - $this->convertSerializedDataToJsonFactory = $convertSerializedDataToJsonFactory; - } - - /** - * {@inheritdoc} - */ - public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context) - { - if (version_compare($context->getVersion(), '2.0.6', '<')) { - $quoteSetup = $this->quoteSetupFactory->create(['setup' => $setup]); - $this->convertSerializedDataToJsonFactory->create(['quoteSetup' => $quoteSetup]) - ->convert(); - } - } -} diff --git a/app/code/Magento/Quote/Test/Unit/Model/BillingAddressManagementTest.php b/app/code/Magento/Quote/Test/Unit/Model/BillingAddressManagementTest.php index 14bc1dcc8efba..4182dbe72dac4 100644 --- a/app/code/Magento/Quote/Test/Unit/Model/BillingAddressManagementTest.php +++ b/app/code/Magento/Quote/Test/Unit/Model/BillingAddressManagementTest.php @@ -128,7 +128,7 @@ public function testSetAddress() /** * @return void * @expectedException \Magento\Framework\Exception\InputException - * @expectedExceptionMessage Unable to save address. Please check input data. + * @expectedExceptionMessage The address failed to save. Verify the address and try again. */ public function testSetAddressWithInabilityToSaveQuote() { diff --git a/app/code/Magento/Quote/Test/Unit/Model/CouponManagementTest.php b/app/code/Magento/Quote/Test/Unit/Model/CouponManagementTest.php index ed32017e7e440..e6ba50e35b4c3 100644 --- a/app/code/Magento/Quote/Test/Unit/Model/CouponManagementTest.php +++ b/app/code/Magento/Quote/Test/Unit/Model/CouponManagementTest.php @@ -76,7 +76,7 @@ public function testGetCoupon() /** * @expectedException \Magento\Framework\Exception\NoSuchEntityException - * @expectedExceptionMessage Cart 33 doesn't contain products + * @expectedExceptionMessage The "33" Cart doesn't contain products. */ public function testSetWhenCartDoesNotContainsProducts() { @@ -91,7 +91,7 @@ public function testSetWhenCartDoesNotContainsProducts() /** * @expectedException \Magento\Framework\Exception\CouldNotSaveException - * @expectedExceptionMessage Could not apply coupon code + * @expectedExceptionMessage The coupon code couldn't be applied. Verify the coupon code and try again. */ public function testSetWhenCouldNotApplyCoupon() { @@ -105,7 +105,7 @@ public function testSetWhenCouldNotApplyCoupon() ->method('getShippingAddress')->will($this->returnValue($this->quoteAddressMock)); $this->quoteAddressMock->expects($this->once())->method('setCollectShippingRates')->with(true); $this->quoteMock->expects($this->once())->method('setCouponCode')->with($couponCode); - $exceptionMessage = 'Could not apply coupon code'; + $exceptionMessage = "The coupon code couldn't be applied. Verify the coupon code and try again."; $exception = new \Magento\Framework\Exception\CouldNotDeleteException(__($exceptionMessage)); $this->quoteMock->expects($this->once())->method('collectTotals')->will($this->returnValue($this->quoteMock)); $this->quoteRepositoryMock->expects($this->once()) @@ -118,7 +118,7 @@ public function testSetWhenCouldNotApplyCoupon() /** * @expectedException \Magento\Framework\Exception\NoSuchEntityException - * @expectedExceptionMessage Coupon code is not valid + * @expectedExceptionMessage The coupon code isn't valid. Verify the code and try again. */ public function testSetWhenCouponCodeIsInvalid() { @@ -160,7 +160,7 @@ public function testSet() /** * @expectedException \Magento\Framework\Exception\NoSuchEntityException - * @expectedExceptionMessage Cart 65 doesn't contain products + * @expectedExceptionMessage The "65" Cart doesn't contain products. */ public function testDeleteWhenCartDoesNotContainsProducts() { @@ -176,7 +176,7 @@ public function testDeleteWhenCartDoesNotContainsProducts() /** * @expectedException \Magento\Framework\Exception\CouldNotDeleteException - * @expectedExceptionMessage Could not delete coupon code + * @expectedExceptionMessage The coupon code couldn't be deleted. Verify the coupon code and try again. */ public function testDeleteWhenCouldNotDeleteCoupon() { @@ -190,7 +190,7 @@ public function testDeleteWhenCouldNotDeleteCoupon() $this->quoteAddressMock->expects($this->once())->method('setCollectShippingRates')->with(true); $this->quoteMock->expects($this->once())->method('setCouponCode')->with(''); $this->quoteMock->expects($this->once())->method('collectTotals')->will($this->returnValue($this->quoteMock)); - $exceptionMessage = 'Could not delete coupon code'; + $exceptionMessage = "The coupon code couldn't be deleted. Verify the coupon code and try again."; $exception = new \Magento\Framework\Exception\CouldNotSaveException(__($exceptionMessage)); $this->quoteMock->expects($this->once())->method('collectTotals')->will($this->returnValue($this->quoteMock)); $this->quoteRepositoryMock->expects($this->once()) @@ -203,7 +203,7 @@ public function testDeleteWhenCouldNotDeleteCoupon() /** * @expectedException \Magento\Framework\Exception\CouldNotDeleteException - * @expectedExceptionMessage Could not delete coupon code + * @expectedExceptionMessage The coupon code couldn't be deleted. Verify the coupon code and try again. */ public function testDeleteWhenCouponIsNotEmpty() { diff --git a/app/code/Magento/Quote/Test/Unit/Model/GuestCartManagement/Plugin/AuthorizationTest.php b/app/code/Magento/Quote/Test/Unit/Model/GuestCartManagement/Plugin/AuthorizationTest.php index 9cde4bbc19184..22962aacc8dac 100644 --- a/app/code/Magento/Quote/Test/Unit/Model/GuestCartManagement/Plugin/AuthorizationTest.php +++ b/app/code/Magento/Quote/Test/Unit/Model/GuestCartManagement/Plugin/AuthorizationTest.php @@ -36,7 +36,7 @@ protected function setUp() /** * @expectedException \Magento\Framework\Exception\StateException - * @expectedMessage Cannot assign customer to the given cart. You don't have permission for this operation. + * @expectedMessage You don't have the correct permissions to assign the customer to the cart. */ public function testBeforeAssignCustomer() { diff --git a/app/code/Magento/Quote/Test/Unit/Model/PaymentMethodManagementTest.php b/app/code/Magento/Quote/Test/Unit/Model/PaymentMethodManagementTest.php index 8143e0e417ead..68b077fcdb965 100644 --- a/app/code/Magento/Quote/Test/Unit/Model/PaymentMethodManagementTest.php +++ b/app/code/Magento/Quote/Test/Unit/Model/PaymentMethodManagementTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Quote\Test\Unit\Model; class PaymentMethodManagementTest extends \PHPUnit\Framework\TestCase @@ -297,7 +298,7 @@ public function testSetSimpleProduct() /** * @expectedException \Magento\Framework\Exception\State\InvalidTransitionException - * @expectedExceptionMessage Shipping address is not set + * @expectedExceptionMessage The shipping address is missing. Set the address and try again. */ public function testSetSimpleProductTrowsExceptionIfShippingAddressNotSet() { diff --git a/app/code/Magento/Quote/Test/Unit/Model/Quote/Item/RepositoryTest.php b/app/code/Magento/Quote/Test/Unit/Model/Quote/Item/RepositoryTest.php index e329a15c5a7f4..4ecd8b021d7f0 100644 --- a/app/code/Magento/Quote/Test/Unit/Model/Quote/Item/RepositoryTest.php +++ b/app/code/Magento/Quote/Test/Unit/Model/Quote/Item/RepositoryTest.php @@ -145,7 +145,7 @@ public function testSave() /** * @return void * @expectedException \Magento\Framework\Exception\NoSuchEntityException - * @expectedExceptionMessage Cart 11 doesn't contain item 5 + * @expectedExceptionMessage The 11 Cart doesn't contain the 5 item. */ public function testDeleteWithInvalidQuoteItem() { @@ -163,7 +163,7 @@ public function testDeleteWithInvalidQuoteItem() /** * @return void * @expectedException \Magento\Framework\Exception\CouldNotSaveException - * @expectedExceptionMessage Could not remove item from quote + * @expectedExceptionMessage The item couldn't be removed from the quote. */ public function testDeleteWithCouldNotSaveException() { @@ -181,7 +181,7 @@ public function testDeleteWithCouldNotSaveException() ->method('removeItem') ->with($itemId) ->willReturn($this->quoteMock); - $exceptionMessage = 'Could not remove item from quote'; + $exceptionMessage = "The item couldn't be removed from the quote."; $exception = new \Magento\Framework\Exception\CouldNotSaveException(__($exceptionMessage)); $this->quoteRepositoryMock->expects($this->once()) ->method('save') diff --git a/app/code/Magento/Quote/Test/Unit/Model/QuoteManagementTest.php b/app/code/Magento/Quote/Test/Unit/Model/QuoteManagementTest.php index 2ca7613796b07..107445bb18d2a 100644 --- a/app/code/Magento/Quote/Test/Unit/Model/QuoteManagementTest.php +++ b/app/code/Magento/Quote/Test/Unit/Model/QuoteManagementTest.php @@ -320,7 +320,7 @@ public function testCreateEmptyCartForCustomerReturnExistsQuote() /** * @expectedException \Magento\Framework\Exception\StateException - * @expectedExceptionMessage Cannot assign customer to the given cart. The cart belongs to different store + * @expectedExceptionMessage The customer can't be assigned to the cart. The cart belongs to a different store. */ public function testAssignCustomerFromAnotherStore() { @@ -364,7 +364,7 @@ public function testAssignCustomerFromAnotherStore() /** * @expectedException \Magento\Framework\Exception\StateException - * @expectedExceptionMessage Cannot assign customer to the given cart. The cart is not anonymous. + * @expectedExceptionMessage The customer can't be assigned to the cart because the cart isn't anonymous. */ public function testAssignCustomerToNonanonymousCart() { @@ -413,7 +413,6 @@ public function testAssignCustomerToNonanonymousCart() /** * @expectedException \Magento\Framework\Exception\StateException - * @expectedExceptionMessage Cannot assign customer to the given cart. Customer already has active cart. */ public function testAssignCustomerNoSuchCustomer() { @@ -463,6 +462,10 @@ public function testAssignCustomerNoSuchCustomer() ->with($customerId); $this->model->assignCustomer($cartId, $customerId, $storeId); + + $this->expectExceptionMessage( + "The customer can't be assigned to the cart because the customer already has an active cart." + ); } public function testAssignCustomer() diff --git a/app/code/Magento/Quote/Test/Unit/Model/QuoteValidatorTest.php b/app/code/Magento/Quote/Test/Unit/Model/QuoteValidatorTest.php index bd53e44afe9db..6865134a04870 100644 --- a/app/code/Magento/Quote/Test/Unit/Model/QuoteValidatorTest.php +++ b/app/code/Magento/Quote/Test/Unit/Model/QuoteValidatorTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Quote\Test\Unit\Model; use Magento\Directory\Model\AllowedCountries; @@ -142,7 +143,7 @@ public function testValidateBeforeSubmitThrowsExceptionIfShippingAddressIsInvali /** * @expectedException \Magento\Framework\Exception\LocalizedException - * @expectedExceptionMessage Please specify a shipping method. + * @expectedExceptionMessage The shipping method is missing. Select the shipping method and try again. */ public function testValidateBeforeSubmitThrowsExceptionIfShippingRateIsNotSelected() { @@ -181,7 +182,7 @@ public function testValidateBeforeSubmitThrowsExceptionIfBillingAddressIsNotVali /** * @expectedException \Magento\Framework\Exception\LocalizedException - * @expectedExceptionMessage Please select a valid payment method. + * @expectedExceptionMessage Enter a valid payment method and try again. */ public function testValidateBeforeSubmitThrowsExceptionIfPaymentMethodIsNotSelected() { @@ -225,7 +226,7 @@ public function testValidateBeforeSubmitThrowsExceptionIfMinimumOrderAmount() * Test case when country id not present in allowed countries list. * * @expectedException \Magento\Framework\Exception\LocalizedException - * @expectedExceptionMessage Some addresses cannot be used due to country-specific configurations. + * @expectedExceptionMessage Some addresses can't be used due to the configurations for specific countries. */ public function testValidateBeforeSubmitThrowsExceptionIfCountrySpecificConfigurations() { diff --git a/app/code/Magento/Quote/Test/Unit/Model/ShippingAddressManagementTest.php b/app/code/Magento/Quote/Test/Unit/Model/ShippingAddressManagementTest.php index c3afd3f053271..e3d5528d62c70 100644 --- a/app/code/Magento/Quote/Test/Unit/Model/ShippingAddressManagementTest.php +++ b/app/code/Magento/Quote/Test/Unit/Model/ShippingAddressManagementTest.php @@ -173,7 +173,7 @@ public function testSetAddress() /** * @expectedException \Magento\Framework\Exception\NoSuchEntityException - * @expectedExceptionMessage Cart contains virtual product(s) only. Shipping address is not applicable + * @expectedExceptionMessage The Cart includes virtual product(s) only, so a shipping address is not used. */ public function testSetAddressForVirtualProduct() { @@ -195,12 +195,12 @@ public function testSetAddressForVirtualProduct() /** * @expectedException \Magento\Framework\Exception\InputException - * @expectedExceptionMessage Unable to save address. Please check input data. + * @expectedExceptionMessage The address failed to save. Verify the address and try again. */ public function testSetAddressWithInabilityToSaveQuote() { $this->quoteAddressMock->expects($this->once())->method('save')->willThrowException( - new \Exception('Unable to save address. Please check input data.') + new \Exception('The address failed to save. Verify the address and try again.') ); $customerAddressId = 150; @@ -265,7 +265,7 @@ public function testGetAddress() /** * @expectedException \Exception - * @expectedExceptionMessage Cart contains virtual product(s) only. Shipping address is not applicable + * @expectedExceptionMessage The Cart includes virtual product(s) only, so a shipping address is not used. */ public function testGetAddressOfQuoteWithVirtualProducts() { diff --git a/app/code/Magento/Quote/Test/Unit/Model/ShippingMethodManagementTest.php b/app/code/Magento/Quote/Test/Unit/Model/ShippingMethodManagementTest.php index af68dcc30a50f..198f1c54a42b4 100644 --- a/app/code/Magento/Quote/Test/Unit/Model/ShippingMethodManagementTest.php +++ b/app/code/Magento/Quote/Test/Unit/Model/ShippingMethodManagementTest.php @@ -168,7 +168,7 @@ protected function setUp() /** * @expectedException \Magento\Framework\Exception\StateException - * @expectedExceptionMessage Shipping address not set. + * @expectedExceptionMessage The shipping address is missing. Set the address and try again. */ public function testGetMethodWhenShippingAddressIsNotSet() { @@ -257,7 +257,7 @@ public function testGetListForEmptyCart() /** * @expectedException \Magento\Framework\Exception\StateException - * @expectedExceptionMessage Shipping address not set. + * @expectedExceptionMessage The shipping address is missing. Set the address and try again. */ public function testGetListWhenShippingAddressIsNotSet() { @@ -307,7 +307,7 @@ public function testGetList() /** * @expectedException \Magento\Framework\Exception\InputException - * @expectedExceptionMessage Shipping method is not applicable for empty cart + * @expectedExceptionMessage The shipping method can't be set for an empty cart. Add an item to cart and try again. */ public function testSetMethodWithInputException() { @@ -326,7 +326,7 @@ public function testSetMethodWithInputException() /** * @expectedException \Magento\Framework\Exception\NoSuchEntityException - * @expectedExceptionMessage Cart contains virtual product(s) only. Shipping method is not applicable. + * @expectedExceptionMessage The Cart includes virtual product(s) only, so a shipping address is not used. */ public function testSetMethodWithVirtualProduct() { @@ -346,7 +346,7 @@ public function testSetMethodWithVirtualProduct() /** * @expectedException \Magento\Framework\Exception\StateException - * @expectedExceptionMessage Shipping address is not set + * @expectedExceptionMessage The shipping address is missing. Set the address and try again. */ public function testSetMethodWithoutShippingAddress() { @@ -368,7 +368,7 @@ public function testSetMethodWithoutShippingAddress() /** * @expectedException \Magento\Framework\Exception\CouldNotSaveException - * @expectedExceptionMessage Cannot set shipping method. Custom Error + * @expectedExceptionMessage The shipping method can't be set. Custom Error */ public function testSetMethodWithCouldNotSaveException() { @@ -404,7 +404,7 @@ public function testSetMethodWithCouldNotSaveException() /** * @expectedException \Magento\Framework\Exception\StateException - * @expectedExceptionMessage Shipping address is not set + * @expectedExceptionMessage The shipping address is missing. Set the address and try again. */ public function testSetMethodWithoutAddress() { diff --git a/app/code/Magento/Quote/etc/module.xml b/app/code/Magento/Quote/etc/module.xml index 6607dea5809b1..852100221b563 100644 --- a/app/code/Magento/Quote/etc/module.xml +++ b/app/code/Magento/Quote/etc/module.xml @@ -6,6 +6,6 @@ */ --> - + diff --git a/app/code/Magento/QuoteAnalytics/etc/module.xml b/app/code/Magento/QuoteAnalytics/etc/module.xml index d72e36b748748..947a792547143 100644 --- a/app/code/Magento/QuoteAnalytics/etc/module.xml +++ b/app/code/Magento/QuoteAnalytics/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/ReleaseNotification/etc/module.xml b/app/code/Magento/ReleaseNotification/etc/module.xml index a57bf26c0bf87..a2d33eb593278 100644 --- a/app/code/Magento/ReleaseNotification/etc/module.xml +++ b/app/code/Magento/ReleaseNotification/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/Reports/Setup/InstallData.php b/app/code/Magento/Reports/Setup/Patch/Data/InitializeReportEntityTypesAndPages.php similarity index 60% rename from app/code/Magento/Reports/Setup/InstallData.php rename to app/code/Magento/Reports/Setup/Patch/Data/InitializeReportEntityTypesAndPages.php index 2ef7f9507380d..e66d1f72737f2 100644 --- a/app/code/Magento/Reports/Setup/InstallData.php +++ b/app/code/Magento/Reports/Setup/Patch/Data/InitializeReportEntityTypesAndPages.php @@ -1,44 +1,51 @@ moduleDataSetup = $moduleDataSetup; $this->pageFactory = $pageFactory; } /** * {@inheritdoc} */ - public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context) + public function apply() { - $setup->startSetup(); + $this->moduleDataSetup->getConnection()->startSetup(); /* * Report Event Types default data */ @@ -64,33 +71,53 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ]; foreach ($eventTypeData as $row) { - $setup->getConnection() - ->insertForce($setup->getTable('report_event_types'), $row); + $this->moduleDataSetup->getConnection() + ->insertForce($this->moduleDataSetup->getTable('report_event_types'), $row); } - /** * Prepare database after data upgrade */ - $setup->endSetup(); - + $this->moduleDataSetup->getConnection()->endSetup(); /** * Cms Page with 'home' identifier page modification for report pages */ /** @var $cms \Magento\Cms\Model\Page */ $cms = $this->pageFactory->create(); $cms->load('home', 'identifier'); - // @codingStandardsIgnoreStart $reportLayoutUpdate = ''; // @codingStandardsIgnoreEnd - /* * Merge and save old layout update data with report layout data */ $cms->setLayoutUpdateXml($cms->getLayoutUpdateXml() . $reportLayoutUpdate) ->save(); } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return []; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.0'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } } diff --git a/app/code/Magento/Reports/etc/module.xml b/app/code/Magento/Reports/etc/module.xml index bfc94f20f1fcd..ed9468539e4b3 100644 --- a/app/code/Magento/Reports/etc/module.xml +++ b/app/code/Magento/Reports/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/RequireJs/etc/module.xml b/app/code/Magento/RequireJs/etc/module.xml index 7935092e2c9b0..e2b8db50762df 100644 --- a/app/code/Magento/RequireJs/etc/module.xml +++ b/app/code/Magento/RequireJs/etc/module.xml @@ -6,5 +6,5 @@ */ --> - + diff --git a/app/code/Magento/Review/Controller/Product/ListAjax.php b/app/code/Magento/Review/Controller/Product/ListAjax.php index 32d608704c241..0180e5a7ee035 100644 --- a/app/code/Magento/Review/Controller/Product/ListAjax.php +++ b/app/code/Magento/Review/Controller/Product/ListAjax.php @@ -19,7 +19,7 @@ class ListAjax extends ProductController public function execute() { if (!$this->initProduct()) { - throw new LocalizedException(__('Cannot initialize product')); + throw new LocalizedException(__("The product can't be initialized.")); } else { /** @var \Magento\Framework\View\Result\Layout $resultLayout */ $resultLayout = $this->resultFactory->create(ResultFactory::TYPE_LAYOUT); diff --git a/app/code/Magento/Review/Helper/Action/Pager.php b/app/code/Magento/Review/Helper/Action/Pager.php index 39c4f3c09d0b7..5d1c5fd308e9c 100644 --- a/app/code/Magento/Review/Helper/Action/Pager.php +++ b/app/code/Magento/Review/Helper/Action/Pager.php @@ -141,7 +141,7 @@ protected function _findItemPositionByValue($value) protected function _getStorageKey() { if (!$this->_storageId) { - throw new LocalizedException(__('Storage key was not set')); + throw new LocalizedException(__("The storage key wasn't set. Add the storage key and try again.")); } return self::STORAGE_PREFIX . $this->_storageId; diff --git a/app/code/Magento/Review/Setup/InstallData.php b/app/code/Magento/Review/Setup/InstallData.php deleted file mode 100644 index 8e9e60d3d64df..0000000000000 --- a/app/code/Magento/Review/Setup/InstallData.php +++ /dev/null @@ -1,76 +0,0 @@ -getConnection()->insert($installer->getTable('review_entity'), ['entity_code' => $entityCode]); - } - - //Fill table review/review_entity - $reviewStatuses = [ - \Magento\Review\Model\Review::STATUS_APPROVED => 'Approved', - \Magento\Review\Model\Review::STATUS_PENDING => 'Pending', - \Magento\Review\Model\Review::STATUS_NOT_APPROVED => 'Not Approved', - ]; - foreach ($reviewStatuses as $k => $v) { - $bind = ['status_id' => $k, 'status_code' => $v]; - $installer->getConnection()->insertForce($installer->getTable('review_status'), $bind); - } - - $data = [ - \Magento\Review\Model\Rating::ENTITY_PRODUCT_CODE => [ - ['rating_code' => 'Quality', 'position' => 0], - ['rating_code' => 'Value', 'position' => 0], - ['rating_code' => 'Price', 'position' => 0], - ], - \Magento\Review\Model\Rating::ENTITY_PRODUCT_REVIEW_CODE => [], - \Magento\Review\Model\Rating::ENTITY_REVIEW_CODE => [], - ]; - - foreach ($data as $entityCode => $ratings) { - //Fill table rating/rating_entity - $installer->getConnection()->insert($installer->getTable('rating_entity'), ['entity_code' => $entityCode]); - $entityId = $installer->getConnection()->lastInsertId($installer->getTable('rating_entity')); - - foreach ($ratings as $bind) { - //Fill table rating/rating - $bind['entity_id'] = $entityId; - $installer->getConnection()->insert($installer->getTable('rating'), $bind); - - //Fill table rating/rating_option - $ratingId = $installer->getConnection()->lastInsertId($installer->getTable('rating')); - $optionData = []; - for ($i = 1; $i <= 5; $i++) { - $optionData[] = ['rating_id' => $ratingId, 'code' => (string)$i, 'value' => $i, 'position' => $i]; - } - $installer->getConnection()->insertMultiple($installer->getTable('rating_option'), $optionData); - } - } - } -} diff --git a/app/code/Magento/Review/Setup/Patch/Data/InitReviewStatusesAndData.php b/app/code/Magento/Review/Setup/Patch/Data/InitReviewStatusesAndData.php new file mode 100644 index 0000000000000..0878169eeb35f --- /dev/null +++ b/app/code/Magento/Review/Setup/Patch/Data/InitReviewStatusesAndData.php @@ -0,0 +1,124 @@ +moduleDataSetup = $moduleDataSetup; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + //Fill table review/review_entity + $reviewEntityCodes = [ + \Magento\Review\Model\Review::ENTITY_PRODUCT_CODE, + \Magento\Review\Model\Review::ENTITY_CUSTOMER_CODE, + \Magento\Review\Model\Review::ENTITY_CATEGORY_CODE, + ]; + foreach ($reviewEntityCodes as $entityCode) { + $this->moduleDataSetup->getConnection()->insert( + $this->moduleDataSetup->getTable('review_entity'), + ['entity_code' => $entityCode] + ); + } + //Fill table review/review_entity + $reviewStatuses = [ + \Magento\Review\Model\Review::STATUS_APPROVED => 'Approved', + \Magento\Review\Model\Review::STATUS_PENDING => 'Pending', + \Magento\Review\Model\Review::STATUS_NOT_APPROVED => 'Not Approved', + ]; + foreach ($reviewStatuses as $k => $v) { + $bind = ['status_id' => $k, 'status_code' => $v]; + $this->moduleDataSetup->getConnection()->insertForce( + $this->moduleDataSetup->getTable('review_status'), + $bind + ); + } + $data = [ + \Magento\Review\Model\Rating::ENTITY_PRODUCT_CODE => [ + ['rating_code' => 'Quality', 'position' => 0], + ['rating_code' => 'Value', 'position' => 0], + ['rating_code' => 'Price', 'position' => 0], + ], + \Magento\Review\Model\Rating::ENTITY_PRODUCT_REVIEW_CODE => [], + \Magento\Review\Model\Rating::ENTITY_REVIEW_CODE => [], + ]; + foreach ($data as $entityCode => $ratings) { + //Fill table rating/rating_entity + $this->moduleDataSetup->getConnection()->insert( + $this->moduleDataSetup->getTable('rating_entity'), + ['entity_code' => $entityCode] + ); + $entityId = $this->moduleDataSetup->getConnection()->lastInsertId( + $this->moduleDataSetup->getTable('rating_entity') + ); + foreach ($ratings as $bind) { + //Fill table rating/rating + $bind['entity_id'] = $entityId; + $this->moduleDataSetup->getConnection()->insert( + $this->moduleDataSetup->getTable('rating'), + $bind + ); + //Fill table rating/rating_option + $ratingId = $this->moduleDataSetup->getConnection()->lastInsertId( + $this->moduleDataSetup->getTable('rating') + ); + $optionData = []; + for ($i = 1; $i <= 5; $i++) { + $optionData[] = ['rating_id' => $ratingId, 'code' => (string)$i, 'value' => $i, 'position' => $i]; + } + $this->moduleDataSetup->getConnection()->insertMultiple( + $this->moduleDataSetup->getTable('rating_option'), + $optionData + ); + } + } + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return []; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.0'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } +} diff --git a/app/code/Magento/Review/etc/module.xml b/app/code/Magento/Review/etc/module.xml index 3f2431edd1707..9ce62a8a0c646 100644 --- a/app/code/Magento/Review/etc/module.xml +++ b/app/code/Magento/Review/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/ReviewAnalytics/etc/module.xml b/app/code/Magento/ReviewAnalytics/etc/module.xml index 65df87bac4af1..ce2f870f2be79 100644 --- a/app/code/Magento/ReviewAnalytics/etc/module.xml +++ b/app/code/Magento/ReviewAnalytics/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/Robots/etc/module.xml b/app/code/Magento/Robots/etc/module.xml index ab04dfb7486f7..6a6b36a66c778 100644 --- a/app/code/Magento/Robots/etc/module.xml +++ b/app/code/Magento/Robots/etc/module.xml @@ -7,7 +7,7 @@ --> - + diff --git a/app/code/Magento/Rss/etc/module.xml b/app/code/Magento/Rss/etc/module.xml index c0daf630f75e8..196d8c3ac5655 100644 --- a/app/code/Magento/Rss/etc/module.xml +++ b/app/code/Magento/Rss/etc/module.xml @@ -6,6 +6,6 @@ */ --> - + diff --git a/app/code/Magento/Rule/etc/module.xml b/app/code/Magento/Rule/etc/module.xml index f5e43eaed237b..ee1bd4605c85e 100644 --- a/app/code/Magento/Rule/etc/module.xml +++ b/app/code/Magento/Rule/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/Sales/Controller/Adminhtml/Order/AddComment.php b/app/code/Magento/Sales/Controller/Adminhtml/Order/AddComment.php index 12038ee375059..07716314ec6e2 100644 --- a/app/code/Magento/Sales/Controller/Adminhtml/Order/AddComment.php +++ b/app/code/Magento/Sales/Controller/Adminhtml/Order/AddComment.php @@ -4,6 +4,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Sales\Controller\Adminhtml\Order; use Magento\Backend\App\Action; @@ -30,7 +31,9 @@ public function execute() try { $data = $this->getRequest()->getPost('history'); if (empty($data['comment']) && $data['status'] == $order->getDataByKey('status')) { - throw new \Magento\Framework\Exception\LocalizedException(__('Please enter a comment.')); + throw new \Magento\Framework\Exception\LocalizedException( + __('The comment is missing. Enter and try again.') + ); } $notify = isset($data['is_customer_notified']) ? $data['is_customer_notified'] : false; diff --git a/app/code/Magento/Sales/Controller/Adminhtml/Order/Create.php b/app/code/Magento/Sales/Controller/Adminhtml/Order/Create.php index 1343b77bcd0ae..a7b41d0a780f3 100644 --- a/app/code/Magento/Sales/Controller/Adminhtml/Order/Create.php +++ b/app/code/Magento/Sales/Controller/Adminhtml/Order/Create.php @@ -327,7 +327,7 @@ protected function _processActionData($action = null) if ($this->_getQuote()->getCouponCode() !== $couponCode) { $this->messageManager->addError( __( - '"%1" coupon code is not valid.', + 'The "%1" coupon code isn\'t valid. Verify the code and try again.', $this->escaper->escapeHtml($couponCode) ) ); diff --git a/app/code/Magento/Sales/Controller/Adminhtml/Order/Create/ConfigureQuoteItems.php b/app/code/Magento/Sales/Controller/Adminhtml/Order/Create/ConfigureQuoteItems.php index 422fe1895b1f0..ba60a916c6daf 100644 --- a/app/code/Magento/Sales/Controller/Adminhtml/Order/Create/ConfigureQuoteItems.php +++ b/app/code/Magento/Sales/Controller/Adminhtml/Order/Create/ConfigureQuoteItems.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Sales\Controller\Adminhtml\Order\Create; class ConfigureQuoteItems extends \Magento\Sales\Controller\Adminhtml\Order\Create @@ -19,12 +20,16 @@ public function execute() try { $quoteItemId = (int)$this->getRequest()->getParam('id'); if (!$quoteItemId) { - throw new \Magento\Framework\Exception\LocalizedException(__('Quote item id is not received.')); + throw new \Magento\Framework\Exception\LocalizedException( + __('The quote item ID needs to be received. Set the ID and try again.') + ); } $quoteItem = $this->_objectManager->create(\Magento\Quote\Model\Quote\Item::class)->load($quoteItemId); if (!$quoteItem->getId()) { - throw new \Magento\Framework\Exception\LocalizedException(__('Quote item is not loaded.')); + throw new \Magento\Framework\Exception\LocalizedException( + __('The quote item needs to be loaded. Load the item and try again.') + ); } $configureResult->setOk(true); diff --git a/app/code/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/AddComment.php b/app/code/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/AddComment.php index cfac8243d091e..4e158efe9702d 100644 --- a/app/code/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/AddComment.php +++ b/app/code/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/AddComment.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Sales\Controller\Adminhtml\Order\Creditmemo; use Magento\Backend\App\Action; @@ -78,7 +79,7 @@ public function execute() $data = $this->getRequest()->getPost('comment'); if (empty($data['comment'])) { throw new \Magento\Framework\Exception\LocalizedException( - __('Please enter a comment.') + __('The comment is missing. Enter and try again.') ); } $this->creditmemoLoader->setOrderId($this->getRequest()->getParam('order_id')); diff --git a/app/code/Magento/Sales/Controller/Adminhtml/Order/Invoice/AddComment.php b/app/code/Magento/Sales/Controller/Adminhtml/Order/Invoice/AddComment.php index 9483abf6354cb..515c0753542a0 100644 --- a/app/code/Magento/Sales/Controller/Adminhtml/Order/Invoice/AddComment.php +++ b/app/code/Magento/Sales/Controller/Adminhtml/Order/Invoice/AddComment.php @@ -4,6 +4,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Sales\Controller\Adminhtml\Order\Invoice; use Magento\Backend\App\Action\Context; @@ -74,7 +75,7 @@ public function execute() $this->getRequest()->setParam('invoice_id', $this->getRequest()->getParam('id')); $data = $this->getRequest()->getPost('comment'); if (empty($data['comment'])) { - throw new LocalizedException(__('Please enter a comment.')); + throw new LocalizedException(__('The comment is missing. Enter and try again.')); } $invoice = $this->getInvoice(); if (!$invoice) { diff --git a/app/code/Magento/Sales/Controller/Adminhtml/Order/Invoice/NewAction.php b/app/code/Magento/Sales/Controller/Adminhtml/Order/Invoice/NewAction.php index 9db9599862f4e..359bbafd45105 100644 --- a/app/code/Magento/Sales/Controller/Adminhtml/Order/Invoice/NewAction.php +++ b/app/code/Magento/Sales/Controller/Adminhtml/Order/Invoice/NewAction.php @@ -4,6 +4,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Sales\Controller\Adminhtml\Order\Invoice; use Magento\Backend\App\Action; @@ -94,7 +95,7 @@ public function execute() if (!$invoice->getTotalQty()) { throw new \Magento\Framework\Exception\LocalizedException( - __('You can\'t create an invoice without products.') + __("The invoice can't be created without products. Add products and try again.") ); } $this->registry->register('current_invoice', $invoice); diff --git a/app/code/Magento/Sales/Controller/Adminhtml/Order/Invoice/Save.php b/app/code/Magento/Sales/Controller/Adminhtml/Order/Invoice/Save.php index c45a1982784e1..d804dff5d48a0 100644 --- a/app/code/Magento/Sales/Controller/Adminhtml/Order/Invoice/Save.php +++ b/app/code/Magento/Sales/Controller/Adminhtml/Order/Invoice/Save.php @@ -4,6 +4,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Sales\Controller\Adminhtml\Order\Invoice; use Magento\Backend\App\Action; @@ -117,7 +118,7 @@ public function execute() $formKeyIsValid = $this->_formKeyValidator->validate($this->getRequest()); $isPost = $this->getRequest()->isPost(); if (!$formKeyIsValid || !$isPost) { - $this->messageManager->addError(__('We can\'t save the invoice right now.')); + $this->messageManager->addError(__("The invoice can't be saved at this time. Please try again later.")); return $resultRedirect->setPath('sales/order/index'); } @@ -146,12 +147,12 @@ public function execute() $invoice = $this->invoiceService->prepareInvoice($order, $invoiceItems); if (!$invoice) { - throw new LocalizedException(__('We can\'t save the invoice right now.')); + throw new LocalizedException(__("The invoice can't be saved at this time. Please try again later.")); } if (!$invoice->getTotalQty()) { throw new \Magento\Framework\Exception\LocalizedException( - __('You can\'t create an invoice without products.') + __("The invoice can't be created without products. Add products and try again.") ); } $this->registry->register('current_invoice', $invoice); @@ -221,7 +222,7 @@ public function execute() } catch (LocalizedException $e) { $this->messageManager->addError($e->getMessage()); } catch (\Exception $e) { - $this->messageManager->addError(__('We can\'t save the invoice right now.')); + $this->messageManager->addError(__("The invoice can't be saved at this time. Please try again later.")); $this->_objectManager->get(\Psr\Log\LoggerInterface::class)->critical($e); } return $resultRedirect->setPath('sales/*/new', ['order_id' => $orderId]); diff --git a/app/code/Magento/Sales/Controller/Adminhtml/Order/Invoice/UpdateQty.php b/app/code/Magento/Sales/Controller/Adminhtml/Order/Invoice/UpdateQty.php index cdb4114f70976..78fb4aff3f275 100644 --- a/app/code/Magento/Sales/Controller/Adminhtml/Order/Invoice/UpdateQty.php +++ b/app/code/Magento/Sales/Controller/Adminhtml/Order/Invoice/UpdateQty.php @@ -4,6 +4,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Sales\Controller\Adminhtml\Order\Invoice; use Magento\Framework\Exception\LocalizedException; @@ -93,7 +94,7 @@ public function execute() if (!$invoice->getTotalQty()) { throw new \Magento\Framework\Exception\LocalizedException( - __('You can\'t create an invoice without products.') + __("The invoice can't be created without products. Add products and try again.") ); } $this->registry->register('current_invoice', $invoice); diff --git a/app/code/Magento/Sales/Model/AdminOrder/Create.php b/app/code/Magento/Sales/Model/AdminOrder/Create.php index 9847c600e691e..679693abd5540 100644 --- a/app/code/Magento/Sales/Model/AdminOrder/Create.php +++ b/app/code/Magento/Sales/Model/AdminOrder/Create.php @@ -14,6 +14,7 @@ use Magento\Quote\Model\Quote\Item; use Magento\Sales\Api\Data\OrderAddressInterface; use Magento\Sales\Model\Order; +use Psr\Log\LoggerInterface; /** * Order create model @@ -1977,12 +1978,12 @@ protected function _validate() if (!$this->getQuote()->isVirtual()) { if (!$this->getQuote()->getShippingAddress()->getShippingMethod()) { - $this->_errors[] = __('Please specify a shipping method.'); + $this->_errors[] = __('The shipping method is missing. Select the shipping method and try again.'); } } if (!$this->getQuote()->getPayment()->getMethod()) { - $this->_errors[] = __('Please specify a payment method.'); + $this->_errors[] = __("The payment method isn't selected. Enter the payment method and try again."); } else { $method = $this->getQuote()->getPayment()->getMethodInstance(); if (!$method->isAvailable($this->getQuote())) { @@ -1996,9 +1997,13 @@ protected function _validate() } } if (!empty($this->_errors)) { + /** @var LoggerInterface $logger */ + $logger = ObjectManager::getInstance()->get(LoggerInterface::class); foreach ($this->_errors as $error) { + $logger->error($error); $this->messageManager->addError($error); } + throw new \Magento\Framework\Exception\LocalizedException(__('Validation is failed.')); } diff --git a/app/code/Magento/Sales/Model/EntityStorage.php b/app/code/Magento/Sales/Model/EntityStorage.php index 3fc0837e7cd58..06f0044715487 100644 --- a/app/code/Magento/Sales/Model/EntityStorage.php +++ b/app/code/Magento/Sales/Model/EntityStorage.php @@ -45,7 +45,7 @@ public function addByIdentifyingFields(FrameworkAbstractModel $object, array $id throw new \Magento\Framework\Exception\InputException(__('Identifying Fields required')); } if (!$object->getId()) { - throw new \Magento\Framework\Exception\InputException(__('Id required')); + throw new \Magento\Framework\Exception\InputException(__('An ID is needed. Set the ID and try again.')); } $this->storageMapper[$storageName][$this->getHash($identifyingFields)] = $object->getId(); $this->registry[$object->getId()] = $object; diff --git a/app/code/Magento/Sales/Model/Order/Address/Validator.php b/app/code/Magento/Sales/Model/Order/Address/Validator.php index e6353f7f28899..31cb5bb1f60ca 100644 --- a/app/code/Magento/Sales/Model/Order/Address/Validator.php +++ b/app/code/Magento/Sales/Model/Order/Address/Validator.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Sales\Model\Order\Address; use Magento\Directory\Helper\Data as DirectoryHelper; @@ -84,7 +85,7 @@ public function validate(Address $address) $warnings = []; foreach ($this->required as $code => $label) { if (!$address->hasData($code)) { - $warnings[] = sprintf('%s is a required field', $label); + $warnings[] = sprintf('"%s" is required. Enter and try again.', $label); } } if (!filter_var($address->getEmail(), FILTER_VALIDATE_EMAIL)) { diff --git a/app/code/Magento/Sales/Model/Order/AddressRepository.php b/app/code/Magento/Sales/Model/Order/AddressRepository.php index 96dc531a82bf4..2aed6ef16817e 100644 --- a/app/code/Magento/Sales/Model/Order/AddressRepository.php +++ b/app/code/Magento/Sales/Model/Order/AddressRepository.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Sales\Model\Order; use Magento\Framework\Api\SearchCriteria\CollectionProcessorInterface; @@ -67,14 +68,16 @@ public function __construct( public function get($id) { if (!$id) { - throw new InputException(__('Id required')); + throw new InputException(__('An ID is needed. Set the ID and try again.')); } if (!isset($this->registry[$id])) { /** @var \Magento\Sales\Api\Data\OrderAddressInterface $entity */ $entity = $this->metadata->getNewInstance()->load($id); if (!$entity->getEntityId()) { - throw new NoSuchEntityException(__('Requested entity doesn\'t exist')); + throw new NoSuchEntityException( + __("The entity that was requested doesn't exist. Verify the entity and try again.") + ); } $this->registry[$id] = $entity; @@ -113,7 +116,7 @@ public function delete(\Magento\Sales\Api\Data\OrderAddressInterface $entity) unset($this->registry[$entity->getEntityId()]); } catch (\Exception $e) { - throw new CouldNotDeleteException(__('Could not delete order address'), $e); + throw new CouldNotDeleteException(__("The order address couldn't be deleted."), $e); } return true; @@ -145,7 +148,7 @@ public function save(\Magento\Sales\Api\Data\OrderAddressInterface $entity) $this->metadata->getMapper()->save($entity); $this->registry[$entity->getEntityId()] = $entity; } catch (\Exception $e) { - throw new CouldNotSaveException(__('Could not save order address'), $e); + throw new CouldNotSaveException(__("The order address couldn't be saved."), $e); } return $this->registry[$entity->getEntityId()]; diff --git a/app/code/Magento/Sales/Model/Order/Creditmemo/Comment/Validator.php b/app/code/Magento/Sales/Model/Order/Creditmemo/Comment/Validator.php index 091bcdf594875..012bd7afa6411 100644 --- a/app/code/Magento/Sales/Model/Order/Creditmemo/Comment/Validator.php +++ b/app/code/Magento/Sales/Model/Order/Creditmemo/Comment/Validator.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Sales\Model\Order\Creditmemo\Comment; use Magento\Sales\Model\Order\Creditmemo\Comment; @@ -34,7 +35,7 @@ public function validate(Comment $comment) $commentData = $comment->getData(); foreach ($this->required as $code => $label) { if (!$comment->hasData($code)) { - $errors[$code] = sprintf('%s is a required field', $label); + $errors[$code] = sprintf('"%s" is required. Enter and try again.', $label); } elseif (empty($commentData[$code])) { $errors[$code] = sprintf('%s can not be empty', $label); } diff --git a/app/code/Magento/Sales/Model/Order/CreditmemoRepository.php b/app/code/Magento/Sales/Model/Order/CreditmemoRepository.php index b866b0de0abfc..a57839b933617 100644 --- a/app/code/Magento/Sales/Model/Order/CreditmemoRepository.php +++ b/app/code/Magento/Sales/Model/Order/CreditmemoRepository.php @@ -70,13 +70,15 @@ public function __construct( public function get($id) { if (!$id) { - throw new InputException(__('Id required')); + throw new InputException(__('An ID is needed. Set the ID and try again.')); } if (!isset($this->registry[$id])) { /** @var \Magento\Sales\Api\Data\CreditmemoInterface $entity */ $entity = $this->metadata->getNewInstance()->load($id); if (!$entity->getEntityId()) { - throw new NoSuchEntityException(__('Requested entity doesn\'t exist')); + throw new NoSuchEntityException( + __("The entity that was requested doesn't exist. Verify the entity and try again.") + ); } $this->registry[$id] = $entity; } @@ -121,7 +123,7 @@ public function delete(\Magento\Sales\Api\Data\CreditmemoInterface $entity) $this->metadata->getMapper()->delete($entity); unset($this->registry[$entity->getEntityId()]); } catch (\Exception $e) { - throw new CouldNotDeleteException(__('Could not delete credit memo'), $e); + throw new CouldNotDeleteException(__("The credit memo couldn't be deleted."), $e); } return true; } @@ -139,7 +141,7 @@ public function save(\Magento\Sales\Api\Data\CreditmemoInterface $entity) $this->metadata->getMapper()->save($entity); $this->registry[$entity->getEntityId()] = $entity; } catch (\Exception $e) { - throw new CouldNotSaveException(__('Could not save credit memo'), $e); + throw new CouldNotSaveException(__("The credit memo couldn't be saved."), $e); } return $this->registry[$entity->getEntityId()]; } diff --git a/app/code/Magento/Sales/Model/Order/Invoice/Comment/Validator.php b/app/code/Magento/Sales/Model/Order/Invoice/Comment/Validator.php index 316764dc6d61c..ac189d2277772 100644 --- a/app/code/Magento/Sales/Model/Order/Invoice/Comment/Validator.php +++ b/app/code/Magento/Sales/Model/Order/Invoice/Comment/Validator.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Sales\Model\Order\Invoice\Comment; use Magento\Sales\Model\Order\Invoice\Comment; @@ -34,7 +35,7 @@ public function validate(Comment $comment) $commentData = $comment->getData(); foreach ($this->required as $code => $label) { if (!$comment->hasData($code)) { - $errors[$code] = sprintf('%s is a required field', $label); + $errors[$code] = sprintf('"%s" is required. Enter and try again.', $label); } elseif (empty($commentData[$code])) { $errors[$code] = sprintf('%s can not be empty', $label); } diff --git a/app/code/Magento/Sales/Model/Order/InvoiceQuantityValidator.php b/app/code/Magento/Sales/Model/Order/InvoiceQuantityValidator.php index d6fca37d664ad..e4fcecbcf11ac 100644 --- a/app/code/Magento/Sales/Model/Order/InvoiceQuantityValidator.php +++ b/app/code/Magento/Sales/Model/Order/InvoiceQuantityValidator.php @@ -75,7 +75,7 @@ private function checkQtyAvailability(InvoiceInterface $invoice, OrderInterface if ($qtys) { $messages[] = __('The invoice contains one or more items that are not part of the original order.'); } elseif ($totalQty <= 0) { - $messages[] = __('You can\'t create an invoice without products.'); + $messages[] = __("The invoice can't be created without products. Add products and try again."); } return $messages; } diff --git a/app/code/Magento/Sales/Model/Order/InvoiceRepository.php b/app/code/Magento/Sales/Model/Order/InvoiceRepository.php index db8cb2e1d88c8..2244a86260c2f 100644 --- a/app/code/Magento/Sales/Model/Order/InvoiceRepository.php +++ b/app/code/Magento/Sales/Model/Order/InvoiceRepository.php @@ -66,13 +66,15 @@ public function __construct( public function get($id) { if (!$id) { - throw new \Magento\Framework\Exception\InputException(__('ID required')); + throw new \Magento\Framework\Exception\InputException(__('An ID is needed. Set the ID and try again.')); } if (!isset($this->registry[$id])) { /** @var \Magento\Sales\Api\Data\InvoiceInterface $entity */ $entity = $this->metadata->getNewInstance()->load($id); if (!$entity->getEntityId()) { - throw new NoSuchEntityException(__('Requested entity doesn\'t exist')); + throw new NoSuchEntityException( + __("The entity that was requested doesn't exist. Verify the entity and try again.") + ); } $this->registry[$id] = $entity; } diff --git a/app/code/Magento/Sales/Model/Order/ItemRepository.php b/app/code/Magento/Sales/Model/Order/ItemRepository.php index 8ded805546c8a..32741a1a7f943 100644 --- a/app/code/Magento/Sales/Model/Order/ItemRepository.php +++ b/app/code/Magento/Sales/Model/Order/ItemRepository.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Sales\Model\Order; use Magento\Catalog\Api\Data\ProductOptionExtensionFactory; @@ -105,13 +106,15 @@ public function __construct( public function get($id) { if (!$id) { - throw new InputException(__('ID required')); + throw new InputException(__('An ID is needed. Set the ID and try again.')); } if (!isset($this->registry[$id])) { /** @var OrderItemInterface $orderItem */ $orderItem = $this->metadata->getNewInstance()->load($id); if (!$orderItem->getItemId()) { - throw new NoSuchEntityException(__('Requested entity doesn\'t exist')); + throw new NoSuchEntityException( + __("The entity that was requested doesn't exist. Verify the entity and try again.") + ); } $this->addProductOption($orderItem); diff --git a/app/code/Magento/Sales/Model/Order/Payment/Repository.php b/app/code/Magento/Sales/Model/Order/Payment/Repository.php index 87bcc85e00af6..4353f6b1cc391 100644 --- a/app/code/Magento/Sales/Model/Order/Payment/Repository.php +++ b/app/code/Magento/Sales/Model/Order/Payment/Repository.php @@ -80,12 +80,14 @@ public function getList(\Magento\Framework\Api\SearchCriteriaInterface $searchCr public function get($id) { if (!$id) { - throw new \Magento\Framework\Exception\InputException(__('ID required')); + throw new \Magento\Framework\Exception\InputException(__('An ID is needed. Set the ID and try again.')); } if (!isset($this->registry[$id])) { $entity = $this->metaData->getNewInstance()->load($id); if (!$entity->getId()) { - throw new NoSuchEntityException(__('Requested entity doesn\'t exist')); + throw new NoSuchEntityException( + __("The entity that was requested doesn't exist. Verify the entity and try again.") + ); } $this->registry[$id] = $entity; } diff --git a/app/code/Magento/Sales/Model/Order/Payment/Transaction/Repository.php b/app/code/Magento/Sales/Model/Order/Payment/Transaction/Repository.php index a2f1d6bcdfbcc..3caae611d9551 100644 --- a/app/code/Magento/Sales/Model/Order/Payment/Transaction/Repository.php +++ b/app/code/Magento/Sales/Model/Order/Payment/Transaction/Repository.php @@ -100,12 +100,14 @@ public function __construct( public function get($id) { if (!$id) { - throw new \Magento\Framework\Exception\InputException(__('ID required')); + throw new \Magento\Framework\Exception\InputException(__('An ID is needed. Set the ID and try again.')); } if (!$this->entityStorage->has($id)) { $entity = $this->metaData->getNewInstance()->load($id); if (!$entity->getTransactionId()) { - throw new NoSuchEntityException(__('Requested entity doesn\'t exist')); + throw new NoSuchEntityException( + __("The entity that was requested doesn't exist. Verify the entity and try again.") + ); } $this->entityStorage->add($entity); } diff --git a/app/code/Magento/Sales/Model/Order/Shipment/Comment/Validator.php b/app/code/Magento/Sales/Model/Order/Shipment/Comment/Validator.php index 3ccc65bf27512..d48af3cea8450 100644 --- a/app/code/Magento/Sales/Model/Order/Shipment/Comment/Validator.php +++ b/app/code/Magento/Sales/Model/Order/Shipment/Comment/Validator.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Sales\Model\Order\Shipment\Comment; use Magento\Sales\Model\Order\Shipment\Comment; @@ -34,7 +35,7 @@ public function validate(Comment $comment) $commentData = $comment->getData(); foreach ($this->required as $code => $label) { if (!$comment->hasData($code)) { - $errors[$code] = sprintf('%s is a required field', $label); + $errors[$code] = sprintf('"%s" is required. Enter and try again.', $label); } elseif (empty($commentData[$code])) { $errors[$code] = sprintf('%s can not be empty', $label); } diff --git a/app/code/Magento/Sales/Model/Order/Shipment/Track/Validator.php b/app/code/Magento/Sales/Model/Order/Shipment/Track/Validator.php index ddd193f3c50fd..9bd144654b6d3 100644 --- a/app/code/Magento/Sales/Model/Order/Shipment/Track/Validator.php +++ b/app/code/Magento/Sales/Model/Order/Shipment/Track/Validator.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Sales\Model\Order\Shipment\Track; use Magento\Sales\Model\Order\Shipment\Track; @@ -36,7 +37,7 @@ public function validate(Track $track) $commentData = $track->getData(); foreach ($this->required as $code => $label) { if (!$track->hasData($code)) { - $errors[$code] = sprintf('%s is a required field', $label); + $errors[$code] = sprintf('"%s" is required. Enter and try again.', $label); } elseif (empty($commentData[$code])) { $errors[$code] = sprintf('%s can not be empty', $label); } diff --git a/app/code/Magento/Sales/Model/Order/ShipmentRepository.php b/app/code/Magento/Sales/Model/Order/ShipmentRepository.php index d39d27746c92e..0b86bec895b75 100644 --- a/app/code/Magento/Sales/Model/Order/ShipmentRepository.php +++ b/app/code/Magento/Sales/Model/Order/ShipmentRepository.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Sales\Model\Order; use Magento\Framework\Api\SearchCriteria\CollectionProcessorInterface; @@ -66,14 +67,16 @@ public function __construct( public function get($id) { if (!$id) { - throw new InputException(__('Id required')); + throw new InputException(__('An ID is needed. Set the ID and try again.')); } if (!isset($this->registry[$id])) { /** @var \Magento\Sales\Api\Data\ShipmentInterface $entity */ $entity = $this->metadata->getNewInstance()->load($id); if (!$entity->getEntityId()) { - throw new NoSuchEntityException(__('Requested entity doesn\'t exist')); + throw new NoSuchEntityException( + __("The entity that was requested doesn't exist. Verify the entity and try again.") + ); } $this->registry[$id] = $entity; @@ -112,7 +115,7 @@ public function delete(\Magento\Sales\Api\Data\ShipmentInterface $entity) unset($this->registry[$entity->getEntityId()]); } catch (\Exception $e) { - throw new CouldNotDeleteException(__('Could not delete shipment'), $e); + throw new CouldNotDeleteException(__("The shipment couldn't be deleted."), $e); } return true; @@ -144,7 +147,7 @@ public function save(\Magento\Sales\Api\Data\ShipmentInterface $entity) $this->metadata->getMapper()->save($entity); $this->registry[$entity->getEntityId()] = $entity; } catch (\Exception $e) { - throw new CouldNotSaveException(__('Could not save shipment'), $e); + throw new CouldNotSaveException(__("The shipment couldn't be saved."), $e); } return $this->registry[$entity->getEntityId()]; diff --git a/app/code/Magento/Sales/Model/Order/Status.php b/app/code/Magento/Sales/Model/Order/Status.php index bdd15d4d844c6..288955705425f 100644 --- a/app/code/Magento/Sales/Model/Order/Status.php +++ b/app/code/Magento/Sales/Model/Order/Status.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Sales\Model\Order; use Magento\Framework\Exception\LocalizedException; @@ -92,10 +93,14 @@ public function assignState($state, $isDefault = false, $visibleOnFront = false) protected function validateBeforeUnassign($state) { if ($this->getResource()->checkIsStateLast($state)) { - throw new LocalizedException(__('The last status can\'t be unassigned from its current state.')); + throw new LocalizedException( + __("The last status can't be changed and needs to stay assigned to its current state.") + ); } if ($this->getResource()->checkIsStatusUsed($this->getStatus())) { - throw new LocalizedException(__('Status can\'t be unassigned, because it is used by existing order(s).')); + throw new LocalizedException( + __("The status can't be unassigned because the status is currently used by an order.") + ); } } diff --git a/app/code/Magento/Sales/Model/Order/Status/History/Validator.php b/app/code/Magento/Sales/Model/Order/Status/History/Validator.php index 0ba5a6aeb11ce..7a4c62089f771 100644 --- a/app/code/Magento/Sales/Model/Order/Status/History/Validator.php +++ b/app/code/Magento/Sales/Model/Order/Status/History/Validator.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Sales\Model\Order\Status\History; use Magento\Sales\Model\Order\Status\History; @@ -27,7 +28,7 @@ public function validate(History $history) $warnings = []; foreach ($this->requiredFields as $code => $label) { if (!$history->hasData($code)) { - $warnings[] = sprintf('%s is a required field', $label); + $warnings[] = sprintf('"%s" is required. Enter and try again.', $label); } } return $warnings; diff --git a/app/code/Magento/Sales/Model/OrderRepository.php b/app/code/Magento/Sales/Model/OrderRepository.php index 26e833c44d70a..f5ab45c5eb1ba 100644 --- a/app/code/Magento/Sales/Model/OrderRepository.php +++ b/app/code/Magento/Sales/Model/OrderRepository.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Sales\Model; use Magento\Framework\Api\SearchCriteria\CollectionProcessorInterface; @@ -87,13 +88,15 @@ public function __construct( public function get($id) { if (!$id) { - throw new InputException(__('Id required')); + throw new InputException(__('An ID is needed. Set the ID and try again.')); } if (!isset($this->registry[$id])) { /** @var OrderInterface $entity */ $entity = $this->metadata->getNewInstance()->load($id); if (!$entity->getEntityId()) { - throw new NoSuchEntityException(__('Requested entity doesn\'t exist')); + throw new NoSuchEntityException( + __("The entity that was requested doesn't exist. Verify the entity and try again.") + ); } $this->setShippingAssignments($entity); $this->registry[$id] = $entity; diff --git a/app/code/Magento/Sales/Model/ResourceModel/Order/Status.php b/app/code/Magento/Sales/Model/ResourceModel/Order/Status.php index 140ffdea262be..58284759b2fee 100644 --- a/app/code/Magento/Sales/Model/ResourceModel/Order/Status.php +++ b/app/code/Magento/Sales/Model/ResourceModel/Order/Status.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Sales\Model\ResourceModel\Order; use Magento\Framework\App\ResourceConnection; @@ -187,7 +188,7 @@ public function unassignState($status, $state) $this->getConnection()->commit(); } catch (\Exception $e) { $this->getConnection()->rollBack(); - throw new LocalizedException(__('Cannot unassign status from state')); + throw new LocalizedException(__('The status needs to remain assigned to its state.')); } return $this; diff --git a/app/code/Magento/Sales/Model/Validator.php b/app/code/Magento/Sales/Model/Validator.php index f309e00b55cfa..740cfa76afe21 100644 --- a/app/code/Magento/Sales/Model/Validator.php +++ b/app/code/Magento/Sales/Model/Validator.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Sales\Model; use Magento\Framework\Exception\ConfigurationMismatchException; @@ -58,9 +59,7 @@ public function validate($entity, array $validators, $context = null) $validator = $this->objectManager->create($validatorName, $validatorArguments); if (!$validator instanceof ValidatorInterface) { throw new ConfigurationMismatchException( - __( - sprintf('Validator %s is not instance of general validator interface', $validatorName) - ) + __('The "%1" validator is not an instance of the general validator interface.', $validatorName) ); } $messages = array_merge($messages, $validator->validate($entity)); diff --git a/app/code/Magento/Sales/Setup/Patch/Data/ConvertSerializedDataToJson.php b/app/code/Magento/Sales/Setup/Patch/Data/ConvertSerializedDataToJson.php new file mode 100644 index 0000000000000..d29a2e019b01b --- /dev/null +++ b/app/code/Magento/Sales/Setup/Patch/Data/ConvertSerializedDataToJson.php @@ -0,0 +1,154 @@ +moduleDataSetup = $moduleDataSetup; + $this->salesSetupFactory = $salesSetupFactory; + $this->eavConfig = $eavConfig; + $this->aggregatedFieldDataConverter = $aggregatedFieldDataConverter; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + /** @var SalesSetup $salesSetup */ + $salesSetup = $this->salesSetupFactory->create(); + $this->convertSerializedDataToJson($salesSetup); + $this->eavConfig->clear(); + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return [ + UpdateEntityTypes::class + ]; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.6'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } + + /** + * Convert native serialization to JSON. + * + * @param SalesSetup $salesSetup + */ + private function convertSerializedDataToJson(SalesSetup $salesSetup) + { + $fieldsToUpdate = [ + new FieldToConvert( + SerializedToJson::class, + $salesSetup->getTable('sales_invoice_item'), + 'entity_id', + 'tax_ratio' + ), + new FieldToConvert( + SerializedToJson::class, + $salesSetup->getTable('sales_creditmemo_item'), + 'entity_id', + 'tax_ratio' + ), + ]; + $fieldsToUpdate[] = new FieldToConvert( + SerializedDataConverter::class, + $salesSetup->getTable('sales_order_item'), + 'item_id', + 'product_options' + ); + $fieldsToUpdate[] = new FieldToConvert( + SerializedToJson::class, + $salesSetup->getTable('sales_shipment'), + 'entity_id', + 'packages' + ); + $fieldsToUpdate[] = new FieldToConvert( + SalesOrderPaymentDataConverter::class, + $salesSetup->getTable('sales_order_payment'), + 'entity_id', + 'additional_information' + ); + $fieldsToUpdate[] = new FieldToConvert( + SerializedToJson::class, + $salesSetup->getTable('sales_payment_transaction'), + 'transaction_id', + 'additional_information' + ); + $this->aggregatedFieldDataConverter->convert($fieldsToUpdate, $salesSetup->getConnection()); + } +} diff --git a/app/code/Magento/Sales/Setup/Patch/Data/FillQuoteAddressIdInSalesOrderAddress.php b/app/code/Magento/Sales/Setup/Patch/Data/FillQuoteAddressIdInSalesOrderAddress.php new file mode 100644 index 0000000000000..601aa58c8424b --- /dev/null +++ b/app/code/Magento/Sales/Setup/Patch/Data/FillQuoteAddressIdInSalesOrderAddress.php @@ -0,0 +1,145 @@ +moduleDataSetup = $moduleDataSetup; + $this->salesSetupFactory = $salesSetupFactory; + $this->state = $state; + $this->eavConfig = $eavConfig; + $this->addressCollectionFactory = $addressCollectionFactory; + $this->orderFactory = $orderFactory; + $this->quoteFactory = $quoteFactory; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + $this->state->emulateAreaCode( + \Magento\Backend\App\Area\FrontNameResolver::AREA_CODE, + [$this, 'fillQuoteAddressIdInSalesOrderAddress'] + ); + $this->eavConfig->clear(); + } + + /** + * Fill quote_address_id in table sales_order_address if it is empty. + */ + public function fillQuoteAddressIdInSalesOrderAddress() + { + $addressCollection = $this->addressCollectionFactory->create(); + /** @var \Magento\Sales\Model\Order\Address $orderAddress */ + foreach ($addressCollection as $orderAddress) { + if (!$orderAddress->getData('quote_address_id')) { + $orderId = $orderAddress->getParentId(); + $addressType = $orderAddress->getAddressType(); + + /** @var \Magento\Sales\Model\Order $order */ + $order = $this->orderFactory->create()->load($orderId); + $quoteId = $order->getQuoteId(); + $quote = $this->quoteFactory->create()->load($quoteId); + + if ($addressType == \Magento\Sales\Model\Order\Address::TYPE_SHIPPING) { + $quoteAddressId = $quote->getShippingAddress()->getId(); + $orderAddress->setData('quote_address_id', $quoteAddressId); + } elseif ($addressType == \Magento\Sales\Model\Order\Address::TYPE_BILLING) { + $quoteAddressId = $quote->getBillingAddress()->getId(); + $orderAddress->setData('quote_address_id', $quoteAddressId); + } + + $orderAddress->save(); + } + } + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return [ + ConvertSerializedDataToJson::class + ]; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.8'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } +} diff --git a/app/code/Magento/Sales/Setup/InstallData.php b/app/code/Magento/Sales/Setup/Patch/Data/InstallOrderStatusesAndInitialSalesConfig.php similarity index 73% rename from app/code/Magento/Sales/Setup/InstallData.php rename to app/code/Magento/Sales/Setup/Patch/Data/InstallOrderStatusesAndInitialSalesConfig.php index d4fef6a690513..4f4ec5f12f68f 100644 --- a/app/code/Magento/Sales/Setup/InstallData.php +++ b/app/code/Magento/Sales/Setup/Patch/Data/InstallOrderStatusesAndInitialSalesConfig.php @@ -4,67 +4,56 @@ * See COPYING.txt for license details. */ -namespace Magento\Sales\Setup; +namespace Magento\Sales\Setup\Patch\Data; -use Magento\Framework\Setup\InstallDataInterface; -use Magento\Framework\Setup\ModuleContextInterface; -use Magento\Framework\Setup\ModuleDataSetupInterface; -use Magento\SalesSequence\Model\Builder; -use Magento\SalesSequence\Model\Config as SequenceConfig; +use Magento\Sales\Setup\SalesSetupFactory; +use Magento\Framework\App\ResourceConnection; +use Magento\Setup\Model\Patch\DataPatchInterface; +use Magento\Setup\Model\Patch\PatchVersionInterface; /** - * Class InstallData - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - * @codeCoverageIgnore + * Class InstallOrderStatusesAndInitialSalesConfig + * @package Magento\Sales\Setup\Patch */ -class InstallData implements InstallDataInterface +class InstallOrderStatusesAndInitialSalesConfig implements DataPatchInterface, PatchVersionInterface { /** - * Sales setup factory - * - * @var SalesSetupFactory - */ - private $salesSetupFactory; - - /** - * @var Builder + * @var \Magento\Framework\Setup\ModuleDataSetupInterface */ - private $sequenceBuilder; + private $moduleDataSetup; /** - * @var SequenceConfig + * @var SalesSetupFactory */ - private $sequenceConfig; + private $salesSetupFactory; /** + * InstallOrderStatusesAndInitialSalesConfig constructor. + * @param \Magento\Framework\Setup\ModuleDataSetupInterface $moduleDataSetup * @param SalesSetupFactory $salesSetupFactory - * @param Builder $sequenceBuilder - * @param SequenceConfig $sequenceConfig */ public function __construct( - SalesSetupFactory $salesSetupFactory, - Builder $sequenceBuilder, - SequenceConfig $sequenceConfig + \Magento\Framework\Setup\ModuleDataSetupInterface $moduleDataSetup, + SalesSetupFactory $salesSetupFactory ) { + $this->moduleDataSetup = $moduleDataSetup; $this->salesSetupFactory = $salesSetupFactory; - $this->sequenceBuilder = $sequenceBuilder; - $this->sequenceConfig = $sequenceConfig; } /** * {@inheritdoc} + * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ - public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context) + public function apply() { /** @var \Magento\Sales\Setup\SalesSetup $salesSetup */ - $salesSetup = $this->salesSetupFactory->create(['setup' => $setup]); + $salesSetup = $this->salesSetupFactory->create(['setup' => $this->moduleDataSetup]); /** * Install eav entity types to the eav/entity_type table */ $salesSetup->installEntities(); - /** * Install order statuses from config */ @@ -83,8 +72,11 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface foreach ($statuses as $code => $info) { $data[] = ['status' => $code, 'label' => $info]; } - $setup->getConnection()->insertArray($setup->getTable('sales_order_status'), ['status', 'label'], $data); - + $this->moduleDataSetup->getConnection()->insertArray( + $this->moduleDataSetup->getTable('sales_order_status'), + ['status', 'label'], + $data + ); /** * Install order states from config */ @@ -130,7 +122,6 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface 'visible_on_front' => true, ], ]; - foreach ($states as $code => $info) { if (isset($info['statuses'])) { foreach ($info['statuses'] as $status => $statusInfo) { @@ -142,14 +133,12 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface } } } - $setup->getConnection()->insertArray( - $setup->getTable('sales_order_status_state'), + $this->moduleDataSetup->getConnection()->insertArray( + $this->moduleDataSetup->getTable('sales_order_status_state'), ['status', 'state', 'is_default'], $data ); - $entitiesToAlter = ['order_address']; - $attributes = [ 'vat_id' => ['type' => \Magento\Framework\DB\Ddl\Table::TYPE_TEXT], 'vat_is_valid' => ['type' => \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT], @@ -157,21 +146,43 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface 'vat_request_date' => ['type' => \Magento\Framework\DB\Ddl\Table::TYPE_TEXT], 'vat_request_success' => ['type' => \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT], ]; - foreach ($entitiesToAlter as $entityName) { foreach ($attributes as $attributeCode => $attributeParams) { $salesSetup->addAttribute($entityName, $attributeCode, $attributeParams); } } - /** Update visibility for states */ $states = ['new', 'processing', 'complete', 'closed', 'canceled', 'holded', 'payment_review']; foreach ($states as $state) { - $setup->getConnection()->update( - $setup->getTable('sales_order_status_state'), + $this->moduleDataSetup->getConnection()->update( + $this->moduleDataSetup->getTable('sales_order_status_state'), ['visible_on_front' => 1], ['state = ?' => $state] ); } } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return []; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.0'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } } diff --git a/app/code/Magento/Sales/Setup/Patch/Data/UpdateEntityTypeModelForInvoice.php b/app/code/Magento/Sales/Setup/Patch/Data/UpdateEntityTypeModelForInvoice.php new file mode 100644 index 0000000000000..4d918924240c1 --- /dev/null +++ b/app/code/Magento/Sales/Setup/Patch/Data/UpdateEntityTypeModelForInvoice.php @@ -0,0 +1,86 @@ +moduleDataSetup = $moduleDataSetup; + $this->salesSetupFactory = $salesSetupFactory; + $this->eavConfig = $eavConfig; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + $salesSetup = $this->salesSetupFactory->create(); + //Correct wrong source model for "invoice" entity type, introduced by mistake in 2.0.1 upgrade. + $salesSetup->updateEntityType( + 'invoice', + 'entity_model', + \Magento\Sales\Model\ResourceModel\Order\Invoice::class + ); + $this->eavConfig->clear(); + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return [ + FillQuoteAddressIdInSalesOrderAddress::class + ]; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.9'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } +} diff --git a/app/code/Magento/Sales/Setup/Patch/Data/UpdateEntityTypes.php b/app/code/Magento/Sales/Setup/Patch/Data/UpdateEntityTypes.php new file mode 100644 index 0000000000000..af31152acde3b --- /dev/null +++ b/app/code/Magento/Sales/Setup/Patch/Data/UpdateEntityTypes.php @@ -0,0 +1,81 @@ +moduleDataSetup = $moduleDataSetup; + $this->salesSetupFactory = $salesSetupFactory; + $this->eavConfig = $eavConfig; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + $salesSetup = $this->salesSetupFactory->create(); + $salesSetup->updateEntityTypes(); + $this->eavConfig->clear(); + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return [ + InstallOrderStatusesAndInitialSalesConfig::class + ]; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.1'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } +} diff --git a/app/code/Magento/Sales/Setup/SalesSetup.php b/app/code/Magento/Sales/Setup/SalesSetup.php index cfaa9106d1c7c..bfc05c549ddb3 100644 --- a/app/code/Magento/Sales/Setup/SalesSetup.php +++ b/app/code/Magento/Sales/Setup/SalesSetup.php @@ -10,6 +10,7 @@ use Magento\Eav\Setup\EavSetup; use Magento\Framework\App\CacheInterface; use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Framework\App\ResourceConnection; use Magento\Framework\Encryption\EncryptorInterface; use Magento\Framework\Setup\ModuleDataSetupInterface; diff --git a/app/code/Magento/Sales/Setup/UpgradeData.php b/app/code/Magento/Sales/Setup/UpgradeData.php deleted file mode 100644 index 16455d616d853..0000000000000 --- a/app/code/Magento/Sales/Setup/UpgradeData.php +++ /dev/null @@ -1,203 +0,0 @@ -salesSetupFactory = $salesSetupFactory; - $this->eavConfig = $eavConfig; - $this->aggregatedFieldConverter = $aggregatedFieldConverter; - $this->addressCollectionFactory = $addressCollFactory; - $this->orderFactory = $orderFactory; - $this->quoteFactory = $quoteFactory; - $this->state = $state; - } - - /** - * {@inheritdoc} - */ - public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context) - { - $salesSetup = $this->salesSetupFactory->create(['setup' => $setup]); - if (version_compare($context->getVersion(), '2.0.1', '<')) { - $salesSetup->updateEntityTypes(); - } - if (version_compare($context->getVersion(), '2.0.6', '<')) { - $this->convertSerializedDataToJson($context->getVersion(), $salesSetup); - } - if (version_compare($context->getVersion(), '2.0.8', '<')) { - $this->state->emulateAreaCode( - \Magento\Backend\App\Area\FrontNameResolver::AREA_CODE, - [$this, 'fillQuoteAddressIdInSalesOrderAddress'], - [$setup] - ); - } - if (version_compare($context->getVersion(), '2.0.9', '<')) { - //Correct wrong source model for "invoice" entity type, introduced by mistake in 2.0.1 upgrade. - $salesSetup->updateEntityType( - 'invoice', - 'entity_model', - \Magento\Sales\Model\ResourceModel\Order\Invoice::class - ); - } - $this->eavConfig->clear(); - } - - /** - * Convert data from serialized to JSON encoded - * - * @param string $setupVersion - * @param SalesSetup $salesSetup - * @return void - */ - private function convertSerializedDataToJson($setupVersion, SalesSetup $salesSetup) - { - $fieldsToUpdate = [ - new FieldToConvert( - SerializedToJson::class, - $salesSetup->getTable('sales_invoice_item'), - 'entity_id', - 'tax_ratio' - ), - new FieldToConvert( - SerializedToJson::class, - $salesSetup->getTable('sales_creditmemo_item'), - 'entity_id', - 'tax_ratio' - ), - ]; - if (version_compare($setupVersion, '2.0.5', '<')) { - $fieldsToUpdate[] = new FieldToConvert( - SerializedDataConverter::class, - $salesSetup->getTable('sales_order_item'), - 'item_id', - 'product_options' - ); - $fieldsToUpdate[] = new FieldToConvert( - SerializedToJson::class, - $salesSetup->getTable('sales_shipment'), - 'entity_id', - 'packages' - ); - $fieldsToUpdate[] = new FieldToConvert( - SalesOrderPaymentDataConverter::class, - $salesSetup->getTable('sales_order_payment'), - 'entity_id', - 'additional_information' - ); - $fieldsToUpdate[] = new FieldToConvert( - SerializedToJson::class, - $salesSetup->getTable('sales_payment_transaction'), - 'transaction_id', - 'additional_information' - ); - } - $this->aggregatedFieldConverter->convert($fieldsToUpdate, $salesSetup->getConnection()); - } - - /** - * Fill quote_address_id in table sales_order_address if it is empty. - */ - public function fillQuoteAddressIdInSalesOrderAddress() - { - $addressCollection = $this->addressCollectionFactory->create(); - /** @var \Magento\Sales\Model\Order\Address $orderAddress */ - foreach ($addressCollection as $orderAddress) { - if (!$orderAddress->getData('quote_address_id')) { - $orderId = $orderAddress->getParentId(); - $addressType = $orderAddress->getAddressType(); - - /** @var \Magento\Sales\Model\Order $order */ - $order = $this->orderFactory->create()->load($orderId); - $quoteId = $order->getQuoteId(); - $quote = $this->quoteFactory->create()->load($quoteId); - - if ($addressType == \Magento\Sales\Model\Order\Address::TYPE_SHIPPING) { - $quoteAddressId = $quote->getShippingAddress()->getId(); - $orderAddress->setData('quote_address_id', $quoteAddressId); - } elseif ($addressType == \Magento\Sales\Model\Order\Address::TYPE_BILLING) { - $quoteAddressId = $quote->getBillingAddress()->getId(); - $orderAddress->setData('quote_address_id', $quoteAddressId); - } - - $orderAddress->save(); - } - } - } -} diff --git a/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/Create/ProcessDataTest.php b/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/Create/ProcessDataTest.php index 2b6436395a0cf..85ed8b9470282 100644 --- a/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/Create/ProcessDataTest.php +++ b/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/Create/ProcessDataTest.php @@ -239,7 +239,7 @@ public function isApplyDiscountDataProvider() { return [ [true, '123', '"%1" coupon code was not applied. Do not apply discount is selected for item(s)', null], - [false, '123', '"%1" coupon code is not valid.', '132'], + [false, '123', 'The "%1" coupon code isn\'t valid. Verify the code and try again.', '132'], ]; } } diff --git a/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/Creditmemo/AddCommentTest.php b/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/Creditmemo/AddCommentTest.php index 29ae1b94704dc..dce080ad03591 100644 --- a/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/Creditmemo/AddCommentTest.php +++ b/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/Creditmemo/AddCommentTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Sales\Test\Unit\Controller\Adminhtml\Order\Creditmemo; /** @@ -215,7 +216,7 @@ public function testExecuteException() */ public function testExecuteNoComment() { - $message = 'Please enter a comment.'; + $message = 'The comment is missing. Enter and try again.'; $response = ['error' => true, 'message' => $message]; $data = []; diff --git a/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/EmailTest.php b/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/EmailTest.php index 3c87b558bb1c9..bb826be85850c 100644 --- a/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/EmailTest.php +++ b/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/EmailTest.php @@ -195,7 +195,9 @@ public function testEmailNoOrderId() ->method('get') ->with(null) ->willThrowException( - new \Magento\Framework\Exception\NoSuchEntityException(__('Requested entity doesn\'t exist')) + new \Magento\Framework\Exception\NoSuchEntityException( + __("The entity that was requested doesn't exist. Verify the entity and try again.") + ) ); $this->messageManager->expects($this->once()) ->method('addError') diff --git a/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/Invoice/SaveTest.php b/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/Invoice/SaveTest.php index 6bd02f0c16317..3ffa0971770b1 100644 --- a/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/Invoice/SaveTest.php +++ b/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/Invoice/SaveTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Sales\Test\Unit\Controller\Adminhtml\Order\Invoice; use Magento\Backend\App\Action; @@ -122,7 +123,7 @@ public function testExecuteNotValidPost() ->willReturn(false); $this->messageManagerMock->expects($this->once()) ->method('addError') - ->with('We can\'t save the invoice right now.'); + ->with("The invoice can't be saved at this time. Please try again later."); $redirectMock->expects($this->once()) ->method('setPath') ->with('sales/order/index') diff --git a/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/ViewTest.php b/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/ViewTest.php index 9677ade99c6eb..97b3fe630aa52 100644 --- a/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/ViewTest.php +++ b/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/ViewTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Sales\Test\Unit\Controller\Adminhtml\Order; /** @@ -218,7 +219,9 @@ public function testExecuteNoOrder() ->method('get') ->with($orderIdParam) ->willThrowException( - new \Magento\Framework\Exception\NoSuchEntityException(__('Requested entity doesn\'t exist')) + new \Magento\Framework\Exception\NoSuchEntityException( + __("The entity that was requested doesn't exist. Verify the entity and try again.") + ) ); $this->initOrderFail(); $this->prepareRedirect(); diff --git a/app/code/Magento/Sales/Test/Unit/Model/InvoiceRepositoryTest.php b/app/code/Magento/Sales/Test/Unit/Model/InvoiceRepositoryTest.php index 5309c2064c5a7..56e9a91a52aff 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/InvoiceRepositoryTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/InvoiceRepositoryTest.php @@ -80,7 +80,7 @@ public function testGet() /** * @expectedException \Magento\Framework\Exception\InputException - * @expectedExceptionMessage ID required + * @expectedExceptionMessage An ID is needed. Set the ID and try again. */ public function testGetNoId() { @@ -89,7 +89,7 @@ public function testGetNoId() /** * @expectedException \Magento\Framework\Exception\NoSuchEntityException - * @expectedExceptionMessage Requested entity doesn't exist + * @expectedExceptionMessage The entity that was requested doesn't exist. Verify the entity and try again. */ public function testGetEntityNoId() { diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/Address/ValidatorTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/Address/ValidatorTest.php index d83a3e34ec00a..e3a3367858bfd 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/Address/ValidatorTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/Address/ValidatorTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Sales\Test\Unit\Model\Order\Address; /** @@ -125,7 +126,7 @@ public function providerAddressData() 'co.co.co', 'coco-shipping', [ - 'Street is a required field', + '"Street" is required. Enter and try again.', 'Email has a wrong format', 'Address type doesn\'t match required options' ] diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/AddressRepositoryTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/AddressRepositoryTest.php index 87f4a9103be6f..33f1c2f8923af 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/AddressRepositoryTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/AddressRepositoryTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Sales\Test\Unit\Model\Order; use Magento\Framework\Api\SearchCriteria\CollectionProcessorInterface; @@ -176,7 +177,7 @@ public function testDelete() /** * @expectedException \Magento\Framework\Exception\CouldNotDeleteException - * @expectedExceptionMessage Could not delete order address + * @expectedExceptionMessage The order address couldn't be deleted. */ public function testDeleteWithException() { @@ -233,7 +234,7 @@ public function testSave() /** * @expectedException \Magento\Framework\Exception\CouldNotSaveException - * @expectedExceptionMessage Could not save order address + * @expectedExceptionMessage The order address couldn't be saved. */ public function testSaveWithException() { diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/Creditmemo/Comment/ValidatorTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/Creditmemo/Comment/ValidatorTest.php index 97526ae544752..673523a70e53c 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/Creditmemo/Comment/ValidatorTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/Creditmemo/Comment/ValidatorTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Sales\Test\Unit\Model\Order\Creditmemo\Comment; /** @@ -82,7 +83,7 @@ public function providerCommentData() ], [ 'parent_id' => 'Parent Creditmemo Id can not be empty', - 'comment' => 'Comment is a required field' + 'comment' => '"Comment" is required. Enter and try again.' ] ] ]; diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/CreditmemoRepositoryTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/CreditmemoRepositoryTest.php index c27a1b1a4e224..6a4db2e0cf715 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/CreditmemoRepositoryTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/CreditmemoRepositoryTest.php @@ -81,7 +81,7 @@ public function testGet() /** * @expectedException \Magento\Framework\Exception\InputException - * @expectedExceptionMessage Id required + * @expectedExceptionMessage An ID is needed. Set the ID and try again. */ public function testGetNoId() { @@ -90,7 +90,7 @@ public function testGetNoId() /** * @expectedException \Magento\Framework\Exception\NoSuchEntityException - * @expectedExceptionMessage Requested entity doesn't exist + * @expectedExceptionMessage The entity that was requested doesn't exist. Verify the entity and try again. */ public function testGetEntityNoId() { @@ -167,7 +167,7 @@ public function testDelete() /** * @expectedException \Magento\Framework\Exception\CouldNotDeleteException - * @expectedExceptionMessage Could not delete credit memo + * @expectedExceptionMessage The credit memo couldn't be deleted. */ public function testDeleteWithException() { @@ -216,7 +216,7 @@ public function testSave() /** * @expectedException \Magento\Framework\Exception\CouldNotSaveException - * @expectedExceptionMessage Could not save credit memo + * @expectedExceptionMessage The credit memo couldn't be saved. */ public function testSaveWithException() { diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/Invoice/Comment/ValidatorTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/Invoice/Comment/ValidatorTest.php index 0bc9839e26652..6d2a903f7098c 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/Invoice/Comment/ValidatorTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/Invoice/Comment/ValidatorTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Sales\Test\Unit\Model\Order\Invoice\Comment; /** @@ -82,7 +83,7 @@ public function providerCommentData() ], [ 'parent_id' => 'Parent Invoice Id can not be empty', - 'comment' => 'Comment is a required field' + 'comment' => '"Comment" is required. Enter and try again.' ] ] ]; diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/InvoiceQuantityValidatorTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/InvoiceQuantityValidatorTest.php index 5d3e9ae22e78b..14d6df5c1c8f1 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/InvoiceQuantityValidatorTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/InvoiceQuantityValidatorTest.php @@ -136,7 +136,7 @@ public function testValidateNoOrder() public function testValidateNoInvoiceItems() { - $expectedResult = [__('You can\'t create an invoice without products.')]; + $expectedResult = [__("The invoice can't be created without products. Add products and try again.")]; $orderItemId = 1; $invoiceItemMock = $this->getInvoiceItemMock($orderItemId, 0); $this->invoiceMock->expects($this->once()) diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/ItemRepositoryTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/ItemRepositoryTest.php index 0c34e5bdffd4a..8be2c3c8612d7 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/ItemRepositoryTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/ItemRepositoryTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Sales\Test\Unit\Model\Order; use Magento\Sales\Model\Order\ItemRepository; @@ -91,7 +92,7 @@ protected function setUp() /** * @expectedException \Magento\Framework\Exception\InputException - * @expectedExceptionMessage ID required + * @expectedExceptionMessage An ID is needed. Set the ID and try again. */ public function testGetWithNoId() { @@ -110,7 +111,7 @@ public function testGetWithNoId() /** * @expectedException \Magento\Framework\Exception\NoSuchEntityException - * @expectedExceptionMessage Requested entity doesn't exist + * @expectedExceptionMessage The entity that was requested doesn't exist. Verify the entity and try again. */ public function testGetEmptyEntity() { diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/Shipment/Comment/ValidatorTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/Shipment/Comment/ValidatorTest.php index a3de503f2f8c9..ff414f808cfa2 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/Shipment/Comment/ValidatorTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/Shipment/Comment/ValidatorTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Sales\Test\Unit\Model\Order\Shipment\Comment; /** @@ -82,7 +83,7 @@ public function providerCommentData() ], [ 'parent_id' => 'Parent Shipment Id can not be empty', - 'comment' => 'Comment is a required field' + 'comment' => '"Comment" is required. Enter and try again.' ] ] ]; diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/Shipment/Track/ValidatorTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/Shipment/Track/ValidatorTest.php index 5207f951a4a41..77374c29d105d 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/Shipment/Track/ValidatorTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/Shipment/Track/ValidatorTest.php @@ -90,9 +90,9 @@ public function providerTrackData() ], [ 'parent_id' => 'Parent Track Id can not be empty', - 'order_id' => 'Order Id is a required field', + 'order_id' => '"Order Id" is required. Enter and try again.', 'track_number' => 'Number can not be empty', - 'carrier_code' => 'Carrier Code is a required field' + 'carrier_code' => '"Carrier Code" is required. Enter and try again.' ] ] ]; diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/ShipmentRepositoryTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/ShipmentRepositoryTest.php index 38097bf4bd562..6785c6c4aec51 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/ShipmentRepositoryTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/ShipmentRepositoryTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Sales\Test\Unit\Model\Order; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; @@ -169,7 +170,7 @@ public function testDelete() /** * @expectedException \Magento\Framework\Exception\CouldNotDeleteException - * @expectedExceptionMessage Could not delete shipment + * @expectedExceptionMessage The shipment couldn't be deleted. */ public function testDeleteWithException() { @@ -226,7 +227,7 @@ public function testSave() /** * @expectedException \Magento\Framework\Exception\CouldNotSaveException - * @expectedExceptionMessage Could not save shipment + * @expectedExceptionMessage The shipment couldn't be saved. */ public function testSaveWithException() { diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/Status/History/ValidatorTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/Status/History/ValidatorTest.php index b72a9363eb8f7..ce9b57436c6e7 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/Status/History/ValidatorTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/Status/History/ValidatorTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Sales\Test\Unit\Model\Order\Status\History; use \Magento\Sales\Model\Order\Status\History\Validator; @@ -27,6 +28,6 @@ public function testValidateNegative() ->with('parent_id') ->will($this->returnValue(false)); $validator = new Validator(); - $this->assertEquals(['Order Id is a required field'], $validator->validate($history)); + $this->assertEquals(['"Order Id" is required. Enter and try again.'], $validator->validate($history)); } } diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/StatusTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/StatusTest.php index 781a55262abf9..d2a08330126dc 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/StatusTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/StatusTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Sales\Test\Unit\Model\Order; /** @@ -86,7 +87,7 @@ public function testUnassignStateSuccess() * Test for method unassignState state is last * * @expectedException \Magento\Framework\Exception\LocalizedException - * @expectedExceptionMessage The last status can't be unassigned from its current state. + * @expectedExceptionMessage The last status can't be changed and needs to stay assigned to its current state. */ public function testUnassignStateStateIsLast() { @@ -105,7 +106,7 @@ public function testUnassignStateStateIsLast() * Test for method unassignState status in use * * @expectedException \Magento\Framework\Exception\LocalizedException - * @expectedExceptionMessage Status can't be unassigned, because it is used by existing order(s). + * @expectedExceptionMessage The status can't be unassigned because the status is currently used by an order. */ public function testUnassignStateStatusUsed() { diff --git a/app/code/Magento/Sales/etc/module.xml b/app/code/Magento/Sales/etc/module.xml index b234cdad876cc..11eebaa3d5a3d 100644 --- a/app/code/Magento/Sales/etc/module.xml +++ b/app/code/Magento/Sales/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/SalesAnalytics/etc/module.xml b/app/code/Magento/SalesAnalytics/etc/module.xml index 7a15075a4bc21..54f67fa13aa36 100644 --- a/app/code/Magento/SalesAnalytics/etc/module.xml +++ b/app/code/Magento/SalesAnalytics/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/SalesInventory/etc/module.xml b/app/code/Magento/SalesInventory/etc/module.xml index f40a587f66fed..7d71924d3591f 100644 --- a/app/code/Magento/SalesInventory/etc/module.xml +++ b/app/code/Magento/SalesInventory/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/SalesRule/Setup/InstallData.php b/app/code/Magento/SalesRule/Setup/InstallData.php deleted file mode 100644 index 6d234aa803ddc..0000000000000 --- a/app/code/Magento/SalesRule/Setup/InstallData.php +++ /dev/null @@ -1,45 +0,0 @@ -createMigrationSetup(); - $setup->startSetup(); - - $installer->appendClassAliasReplace( - 'salesrule', - 'conditions_serialized', - \Magento\Framework\Module\Setup\Migration::ENTITY_TYPE_MODEL, - \Magento\Framework\Module\Setup\Migration::FIELD_CONTENT_TYPE_SERIALIZED, - ['rule_id'] - ); - $installer->appendClassAliasReplace( - 'salesrule', - 'actions_serialized', - \Magento\Framework\Module\Setup\Migration::ENTITY_TYPE_MODEL, - \Magento\Framework\Module\Setup\Migration::FIELD_CONTENT_TYPE_SERIALIZED, - ['rule_id'] - ); - - $installer->doUpdateClassAliases(); - - $setup->endSetup(); - } -} diff --git a/app/code/Magento/SalesRule/Setup/Patch/Data/ConvertSerializedDataToJson.php b/app/code/Magento/SalesRule/Setup/Patch/Data/ConvertSerializedDataToJson.php new file mode 100644 index 0000000000000..807ca7ea4a794 --- /dev/null +++ b/app/code/Magento/SalesRule/Setup/Patch/Data/ConvertSerializedDataToJson.php @@ -0,0 +1,113 @@ +metadataPool = $metadataPool; + $this->aggregatedFieldConverter = $aggregatedFieldConverter; + $this->moduleDataSetup = $moduleDataSetup; + } + + /** + * Do Upgrade + * + * @return void + */ + public function apply() + { + $this->moduleDataSetup->getConnection()->startSetup(); + $this->convertSerializedDataToJson(); + $this->moduleDataSetup->getConnection()->endSetup(); + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return [ + PrepareRuleModelSerializedData::class + ]; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.2'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } + + /** + * Convert native serialized data to json. + * + * @return void + */ + private function convertSerializedDataToJson() + { + $metadata = $this->metadataPool->getMetadata(\Magento\SalesRule\Api\Data\RuleInterface::class); + $this->aggregatedFieldConverter->convert( + [ + new \Magento\Framework\DB\FieldToConvert( + \Magento\Framework\DB\DataConverter\SerializedToJson::class, + $this->moduleDataSetup->getTable('salesrule'), + $metadata->getLinkField(), + 'conditions_serialized' + ), + new \Magento\Framework\DB\FieldToConvert( + \Magento\Framework\DB\DataConverter\SerializedToJson::class, + $this->moduleDataSetup->getTable('salesrule'), + $metadata->getLinkField(), + 'actions_serialized' + ), + ], + $this->moduleDataSetup->getConnection() + ); + } +} diff --git a/app/code/Magento/SalesRule/Setup/Patch/Data/FillSalesRuleProductAttributeTable.php b/app/code/Magento/SalesRule/Setup/Patch/Data/FillSalesRuleProductAttributeTable.php new file mode 100644 index 0000000000000..d3605431543bf --- /dev/null +++ b/app/code/Magento/SalesRule/Setup/Patch/Data/FillSalesRuleProductAttributeTable.php @@ -0,0 +1,129 @@ +ruleColletionFactory = $ruleColletionFactory; + $this->serializer = $serializer; + $this->resourceModelRule = $resourceModelRule; + $this->moduleDataSetup = $moduleDataSetup; + $this->appState = $appState; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + $this->moduleDataSetup->getConnection()->startSetup(); + $this->appState->emulateAreaCode( + \Magento\Backend\App\Area\FrontNameResolver::AREA_CODE, + [$this, 'fillSalesRuleProductAttributeTable'] + ); + $this->fillSalesRuleProductAttributeTable(); + $this->moduleDataSetup->getConnection()->endSetup(); + } + + /** + * Fill attribute table for sales rule + */ + public function fillSalesRuleProductAttributeTable() + { + /** @var \Magento\SalesRule\Model\ResourceModel\Rule\Collection $ruleCollection */ + $ruleCollection = $this->ruleColletionFactory->create(); + /** @var \Magento\SalesRule\Model\Rule $rule */ + foreach ($ruleCollection as $rule) { + // Save product attributes used in rule + $conditions = $rule->getConditions()->asArray(); + $actions = $rule->getActions()->asArray(); + $serializedConditions = $this->serializer->serialize($conditions); + $serializedActions = $this->serializer->serialize($actions); + $conditionAttributes = $this->resourceModelRule->getProductAttributes($serializedConditions); + $actionAttributes = $this->resourceModelRule->getProductAttributes($serializedActions); + $ruleProductAttributes = array_merge($conditionAttributes, $actionAttributes); + if ($ruleProductAttributes) { + $this->resourceModelRule->setActualProductAttributes($rule, $ruleProductAttributes); + } + } + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return [ + ConvertSerializedDataToJson::class + ]; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.3'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } +} diff --git a/app/code/Magento/SalesRule/Setup/Patch/Data/PrepareRuleModelSerializedData.php b/app/code/Magento/SalesRule/Setup/Patch/Data/PrepareRuleModelSerializedData.php new file mode 100644 index 0000000000000..4a68a2d42c8e2 --- /dev/null +++ b/app/code/Magento/SalesRule/Setup/Patch/Data/PrepareRuleModelSerializedData.php @@ -0,0 +1,84 @@ +moduleDataSetup = $moduleDataSetup; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + $installer = $this->moduleDataSetup->createMigrationSetup(); + $this->moduleDataSetup->startSetup(); + + $installer->appendClassAliasReplace( + 'salesrule', + 'conditions_serialized', + \Magento\Framework\Module\Setup\Migration::ENTITY_TYPE_MODEL, + \Magento\Framework\Module\Setup\Migration::FIELD_CONTENT_TYPE_SERIALIZED, + ['rule_id'] + ); + $installer->appendClassAliasReplace( + 'salesrule', + 'actions_serialized', + \Magento\Framework\Module\Setup\Migration::ENTITY_TYPE_MODEL, + \Magento\Framework\Module\Setup\Migration::FIELD_CONTENT_TYPE_SERIALIZED, + ['rule_id'] + ); + $installer->doUpdateClassAliases(); + $this->moduleDataSetup->endSetup(); + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return []; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.0'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } +} diff --git a/app/code/Magento/SalesRule/Setup/UpgradeData.php b/app/code/Magento/SalesRule/Setup/UpgradeData.php deleted file mode 100644 index 9a34d85bba995..0000000000000 --- a/app/code/Magento/SalesRule/Setup/UpgradeData.php +++ /dev/null @@ -1,150 +0,0 @@ -aggregatedFieldConverter = $aggregatedFieldConverter; - $this->metadataPool = $metadataPool; - $this->resourceModelRule = $resourceModelRule; - $this->serializer = $serializer; - $this->state = $state; - $this->ruleColletionFactory = $ruleColletionFactory; - } - - /** - * @inheritdoc - */ - public function upgrade( - \Magento\Framework\Setup\ModuleDataSetupInterface $setup, - \Magento\Framework\Setup\ModuleContextInterface $context - ) { - $setup->startSetup(); - if (version_compare($context->getVersion(), '2.0.2', '<')) { - $this->convertSerializedDataToJson($setup); - } - if (version_compare($context->getVersion(), '2.0.3', '<')) { - $this->state->emulateAreaCode( - \Magento\Backend\App\Area\FrontNameResolver::AREA_CODE, - [$this, 'fillSalesRuleProductAttributeTable'], - [$setup] - ); - $this->fillSalesRuleProductAttributeTable(); - } - $setup->endSetup(); - } - - /** - * Convert metadata from serialized to JSON format: - * - * @param \Magento\Framework\Setup\ModuleDataSetupInterface $setup * - * @return void - */ - public function convertSerializedDataToJson($setup) - { - $metadata = $this->metadataPool->getMetadata(\Magento\SalesRule\Api\Data\RuleInterface::class); - $this->aggregatedFieldConverter->convert( - [ - new \Magento\Framework\DB\FieldToConvert( - \Magento\Framework\DB\DataConverter\SerializedToJson::class, - $setup->getTable('salesrule'), - $metadata->getLinkField(), - 'conditions_serialized' - ), - new \Magento\Framework\DB\FieldToConvert( - \Magento\Framework\DB\DataConverter\SerializedToJson::class, - $setup->getTable('salesrule'), - $metadata->getLinkField(), - 'actions_serialized' - ), - ], - $setup->getConnection() - ); - } - - /** - * Fills blank table salesrule_product_attribute with data. - * - * @return void - */ - public function fillSalesRuleProductAttributeTable() - { - /** @var \Magento\SalesRule\Model\ResourceModel\Rule\Collection $ruleCollection */ - $ruleCollection = $this->ruleColletionFactory->create(); - /** @var \Magento\SalesRule\Model\Rule $rule */ - foreach ($ruleCollection as $rule) { - // Save product attributes used in rule - $conditions = $rule->getConditions()->asArray(); - $actions = $rule->getActions()->asArray(); - $serializedConditions = $this->serializer->serialize($conditions); - $serializedActions = $this->serializer->serialize($actions); - $conditionAttributes = $this->resourceModelRule->getProductAttributes($serializedConditions); - $actionAttributes = $this->resourceModelRule->getProductAttributes($serializedActions); - $ruleProductAttributes = array_merge($conditionAttributes, $actionAttributes); - if ($ruleProductAttributes) { - $this->resourceModelRule->setActualProductAttributes($rule, $ruleProductAttributes); - } - } - } -} diff --git a/app/code/Magento/SalesRule/etc/module.xml b/app/code/Magento/SalesRule/etc/module.xml index f3f160eb7d40b..4344e00b6f840 100644 --- a/app/code/Magento/SalesRule/etc/module.xml +++ b/app/code/Magento/SalesRule/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/SalesSequence/Model/ResourceModel/Meta.php b/app/code/Magento/SalesSequence/Model/ResourceModel/Meta.php index 10cf903d0baed..be566b6119bdd 100644 --- a/app/code/Magento/SalesSequence/Model/ResourceModel/Meta.php +++ b/app/code/Magento/SalesSequence/Model/ResourceModel/Meta.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\SalesSequence\Model\ResourceModel; use Magento\Framework\Exception\LocalizedException as Exception; @@ -117,7 +118,12 @@ protected function _afterLoad(\Magento\Framework\Model\AbstractModel $object) protected function _beforeSave(\Magento\Framework\Model\AbstractModel $object) { if (!$object->getData('active_profile') instanceof ModelProfile) { - throw new NoSuchEntityException(__('Entity Sequence profile not added to meta active profile')); + throw new NoSuchEntityException( + __( + "The entity sequence profile wasn't added to the meta active profile. " + . "Verify the profile and try again." + ) + ); } if (!$object->getData('entity_type') diff --git a/app/code/Magento/SalesSequence/Setup/InstallData.php b/app/code/Magento/SalesSequence/Setup/InstallData.php deleted file mode 100644 index 5c07c37908760..0000000000000 --- a/app/code/Magento/SalesSequence/Setup/InstallData.php +++ /dev/null @@ -1,38 +0,0 @@ -sequenceCreator = $sequenceCreator; - } - - /** - * {@inheritdoc} - */ - public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context) - { - $this->sequenceCreator->create(); - } -} diff --git a/app/code/Magento/SalesSequence/Setup/Patch/Schema/CreateSequence.php b/app/code/Magento/SalesSequence/Setup/Patch/Schema/CreateSequence.php new file mode 100644 index 0000000000000..7295408f98fd6 --- /dev/null +++ b/app/code/Magento/SalesSequence/Setup/Patch/Schema/CreateSequence.php @@ -0,0 +1,68 @@ +sequenceCreator = $sequenceCreator; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + $this->sequenceCreator->create(); + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return [ + \Magento\Store\Setup\Patch\Schema\InitializeStoresAndWebsites::class + ]; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.0'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } +} diff --git a/app/code/Magento/SalesSequence/composer.json b/app/code/Magento/SalesSequence/composer.json index 37b562420383d..1a3c00373a775 100644 --- a/app/code/Magento/SalesSequence/composer.json +++ b/app/code/Magento/SalesSequence/composer.json @@ -6,7 +6,8 @@ }, "require": { "php": "7.0.2|7.0.4|~7.0.6|~7.1.0", - "magento/framework": "100.3.*" + "magento/framework": "100.3.*", + "magento/module-store": "100.3.*" }, "type": "magento2-module", "version": "100.3.0-dev", diff --git a/app/code/Magento/SalesSequence/etc/module.xml b/app/code/Magento/SalesSequence/etc/module.xml index d896811611254..e200d84a3145e 100644 --- a/app/code/Magento/SalesSequence/etc/module.xml +++ b/app/code/Magento/SalesSequence/etc/module.xml @@ -6,6 +6,9 @@ */ --> - + + + + diff --git a/app/code/Magento/SampleData/Setup/InstallData.php b/app/code/Magento/SampleData/Setup/InstallData.php deleted file mode 100644 index edb1bd76cc978..0000000000000 --- a/app/code/Magento/SampleData/Setup/InstallData.php +++ /dev/null @@ -1,36 +0,0 @@ -state = $state; - } - - /** - * @inheritdoc - */ - public function install(Setup\ModuleDataSetupInterface $setup, Setup\ModuleContextInterface $moduleContext) - { - $this->state->clearState(); - } -} diff --git a/app/code/Magento/SampleData/Setup/Patch/Data/ClearSampleDataState.php b/app/code/Magento/SampleData/Setup/Patch/Data/ClearSampleDataState.php new file mode 100644 index 0000000000000..f0f154b477a7a --- /dev/null +++ b/app/code/Magento/SampleData/Setup/Patch/Data/ClearSampleDataState.php @@ -0,0 +1,73 @@ +moduleDataSetup = $moduleDataSetup; + $this->state = $state; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + $this->state->clearState(); + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return []; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.0'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } +} diff --git a/app/code/Magento/SampleData/etc/module.xml b/app/code/Magento/SampleData/etc/module.xml index 965a78871e54f..6746aadc4b408 100644 --- a/app/code/Magento/SampleData/etc/module.xml +++ b/app/code/Magento/SampleData/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/Search/Model/PopularSearchTerms.php b/app/code/Magento/Search/Model/PopularSearchTerms.php new file mode 100644 index 0000000000000..d5ddc0e1dac5f --- /dev/null +++ b/app/code/Magento/Search/Model/PopularSearchTerms.php @@ -0,0 +1,74 @@ +scopeConfig = $scopeConfig; + $this->queryCollection = $queryCollection; + } + + /** + * Check if is cacheable search term + * + * @param string $term + * @param int $storeId + * @return bool + */ + public function isCacheable(string $term, int $storeId) + { + $terms = $this->queryCollection + ->setPopularQueryFilter($storeId) + ->setPageSize($this->getMaxCountCacheableSearchTerms($storeId)) + ->load() + ->getColumnValues('query_text'); + + return in_array($term, $terms); + } + + /** + * Retrieve maximum count cacheable search terms + * + * @param int $storeId + * @return int + */ + private function getMaxCountCacheableSearchTerms(int $storeId) + { + return $this->scopeConfig->getValue( + self::XML_PATH_MAX_COUNT_CACHEABLE_SEARCH_TERMS, + \Magento\Store\Model\ScopeInterface::SCOPE_STORE, + $storeId + ); + } +} diff --git a/app/code/Magento/Search/Model/SynonymGroupRepository.php b/app/code/Magento/Search/Model/SynonymGroupRepository.php index 7b924df56a7e0..6c5bdfb597487 100644 --- a/app/code/Magento/Search/Model/SynonymGroupRepository.php +++ b/app/code/Magento/Search/Model/SynonymGroupRepository.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Search\Model; use Magento\Framework\Exception\CouldNotDeleteException; @@ -73,7 +74,7 @@ public function delete(SynonymGroupInterface $synonymGroup) } catch (\Exception $exception) { throw new CouldNotDeleteException( __( - 'Synonym group with id %1 cannot be deleted. %2', + 'The synonym group with the "%1" ID can\'t be deleted. %2', $synonymGroup->getGroupId(), $exception->getMessage() ) diff --git a/app/code/Magento/Search/etc/module.xml b/app/code/Magento/Search/etc/module.xml index 12c5591109591..2acbc54254eb0 100644 --- a/app/code/Magento/Search/etc/module.xml +++ b/app/code/Magento/Search/etc/module.xml @@ -7,7 +7,7 @@ --> - + diff --git a/app/code/Magento/Security/Model/AdminSessionsManager.php b/app/code/Magento/Security/Model/AdminSessionsManager.php index af690f1899e7b..7503fe04ba480 100644 --- a/app/code/Magento/Security/Model/AdminSessionsManager.php +++ b/app/code/Magento/Security/Model/AdminSessionsManager.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Security\Model; use Magento\Framework\HTTP\PhpEnvironment\RemoteAddress; @@ -205,7 +206,7 @@ public function getLogoutReasonMessageByStatus($statusCode) break; case self::LOGOUT_REASON_USER_LOCKED: $reasonMessage = __( - 'Your account is temporarily disabled.' + 'Your account is temporarily disabled. Please try again later.' ); break; default: diff --git a/app/code/Magento/Security/Model/SecurityChecker/Frequency.php b/app/code/Magento/Security/Model/SecurityChecker/Frequency.php index 5ff06272563a7..5aeb0fca6f0a6 100644 --- a/app/code/Magento/Security/Model/SecurityChecker/Frequency.php +++ b/app/code/Magento/Security/Model/SecurityChecker/Frequency.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Security\Model\SecurityChecker; use Magento\Framework\Exception\SecurityViolationException; @@ -76,7 +77,8 @@ public function check($securityEventType, $accountReference = null, $longIp = nu )) { throw new SecurityViolationException( __( - 'Too many password reset requests. Please wait and try again or contact %1.', + 'We received too many requests for password resets. ' + . 'Please wait and try again later or contact %1.', $this->securityConfig->getCustomerServiceEmail() ) ); diff --git a/app/code/Magento/Security/Model/SecurityChecker/Quantity.php b/app/code/Magento/Security/Model/SecurityChecker/Quantity.php index 7f1d85abeb74b..9d86b55158be5 100644 --- a/app/code/Magento/Security/Model/SecurityChecker/Quantity.php +++ b/app/code/Magento/Security/Model/SecurityChecker/Quantity.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Security\Model\SecurityChecker; use Magento\Framework\Exception\SecurityViolationException; @@ -58,7 +59,8 @@ public function check($securityEventType, $accountReference = null, $longIp = nu if ($collection->count() >= $allowedAttemptsNumber) { throw new SecurityViolationException( __( - 'Too many password reset requests. Please wait and try again or contact %1.', + 'We received too many requests for password resets. ' + . 'Please wait and try again later or contact %1.', $this->securityConfig->getCustomerServiceEmail() ) ); diff --git a/app/code/Magento/Security/Test/Unit/Model/AdminSessionsManagerTest.php b/app/code/Magento/Security/Test/Unit/Model/AdminSessionsManagerTest.php index ddfeaa59ac224..be0bdaecf8de3 100644 --- a/app/code/Magento/Security/Test/Unit/Model/AdminSessionsManagerTest.php +++ b/app/code/Magento/Security/Test/Unit/Model/AdminSessionsManagerTest.php @@ -370,7 +370,7 @@ public function dataProviderLogoutReasonMessage() 'sessionStatus' => \Magento\Security\Model\AdminSessionInfo::LOGGED_OUT ], [ - 'expectedResult' => __('Your account is temporarily disabled.'), + 'expectedResult' => __('Your account is temporarily disabled. Please try again later.'), 'sessionStatus' => \Magento\Security\Model\AdminSessionsManager::LOGOUT_REASON_USER_LOCKED ], [ diff --git a/app/code/Magento/Security/Test/Unit/Model/SecurityChecker/FrequencyTest.php b/app/code/Magento/Security/Test/Unit/Model/SecurityChecker/FrequencyTest.php index b17768bd01f89..732163383f702 100644 --- a/app/code/Magento/Security/Test/Unit/Model/SecurityChecker/FrequencyTest.php +++ b/app/code/Magento/Security/Test/Unit/Model/SecurityChecker/FrequencyTest.php @@ -134,7 +134,6 @@ public function testCheck($securityEventType, $requestsMethod) * @param int $requestsMethod * @dataProvider dataProviderSecurityEventTypeWithRequestsMethod * @expectedException \Magento\Framework\Exception\SecurityViolationException - * @expectedExceptionMessage Too many password reset requests. Please wait and try again or contact test@host.com. */ public function testCheckException($securityEventType, $requestsMethod) { @@ -158,6 +157,11 @@ public function testCheckException($securityEventType, $requestsMethod) ->willReturn($record); $this->model->check($securityEventType); + + $this->expectExceptionMessage( + 'We received too many requests for password resets. ' + . 'Please wait and try again later or contact test@host.com.' + ); } /** diff --git a/app/code/Magento/Security/Test/Unit/Model/SecurityChecker/QuantityTest.php b/app/code/Magento/Security/Test/Unit/Model/SecurityChecker/QuantityTest.php index 94cfde17f5726..e98fd06b9d47e 100644 --- a/app/code/Magento/Security/Test/Unit/Model/SecurityChecker/QuantityTest.php +++ b/app/code/Magento/Security/Test/Unit/Model/SecurityChecker/QuantityTest.php @@ -114,7 +114,6 @@ public function testCheck($securityEventType, $requestsMethod) * @param int $requestsMethod * @dataProvider dataProviderSecurityEventTypeWithRequestsMethod * @expectedException \Magento\Framework\Exception\SecurityViolationException - * @expectedExceptionMessage Too many password reset requests. Please wait and try again or contact test@host.com. */ public function testCheckException($securityEventType, $requestsMethod) { @@ -127,6 +126,11 @@ public function testCheckException($securityEventType, $requestsMethod) ->willReturn($limitNumberPasswordResetRequests); $this->model->check($securityEventType); + + $this->expectExceptionMessage( + 'We received too many requests for password resets. ' + . 'Please wait and try again later or contact test@host.com.' + ); } /** diff --git a/app/code/Magento/Security/etc/module.xml b/app/code/Magento/Security/etc/module.xml index e1f0239be3fdd..9141c4ddbea66 100644 --- a/app/code/Magento/Security/etc/module.xml +++ b/app/code/Magento/Security/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/SendFriend/etc/module.xml b/app/code/Magento/SendFriend/etc/module.xml index fae2b90f710a3..01c267b3c4fcb 100644 --- a/app/code/Magento/SendFriend/etc/module.xml +++ b/app/code/Magento/SendFriend/etc/module.xml @@ -7,7 +7,7 @@ --> - + diff --git a/app/code/Magento/Shipping/Controller/Adminhtml/Order/Shipment/AddComment.php b/app/code/Magento/Shipping/Controller/Adminhtml/Order/Shipment/AddComment.php index 0ac36110d7e6b..483ac21689baf 100644 --- a/app/code/Magento/Shipping/Controller/Adminhtml/Order/Shipment/AddComment.php +++ b/app/code/Magento/Shipping/Controller/Adminhtml/Order/Shipment/AddComment.php @@ -4,6 +4,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Shipping\Controller\Adminhtml\Order\Shipment; use Magento\Sales\Model\Order\Email\Sender\ShipmentCommentSender; @@ -64,7 +65,7 @@ public function execute() $data = $this->getRequest()->getPost('comment'); if (empty($data['comment'])) { throw new \Magento\Framework\Exception\LocalizedException( - __('Please enter a comment.') + __('The comment is missing. Enter and try again.') ); } $this->shipmentLoader->setOrderId($this->getRequest()->getParam('order_id')); diff --git a/app/code/Magento/Shipping/Model/Carrier/AbstractCarrier.php b/app/code/Magento/Shipping/Model/Carrier/AbstractCarrier.php index 29e861cca891f..5575792c346d3 100644 --- a/app/code/Magento/Shipping/Model/Carrier/AbstractCarrier.php +++ b/app/code/Magento/Shipping/Model/Carrier/AbstractCarrier.php @@ -453,7 +453,7 @@ protected function _updateFreeMethodQuote($request) */ public function getFinalPriceWithHandlingFee($cost) { - $handlingFee = $this->getConfigData('handling_fee'); + $handlingFee = (float)$this->getConfigData('handling_fee'); $handlingType = $this->getConfigData('handling_type'); if (!$handlingType) { $handlingType = self::HANDLING_TYPE_FIXED; diff --git a/app/code/Magento/Shipping/Model/Carrier/AbstractCarrierOnline.php b/app/code/Magento/Shipping/Model/Carrier/AbstractCarrierOnline.php index d42da53263ca4..8244fcc4bad9d 100644 --- a/app/code/Magento/Shipping/Model/Carrier/AbstractCarrierOnline.php +++ b/app/code/Magento/Shipping/Model/Carrier/AbstractCarrierOnline.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Shipping\Model\Carrier; use Magento\Framework\Exception\LocalizedException; @@ -655,7 +656,7 @@ public function getMethodPrice($cost, $method = '') public function parseXml($xmlContent, $customSimplexml = 'SimpleXMLElement') { if (!$this->xmlSecurity->scan($xmlContent)) { - throw new LocalizedException(__('Security validation of XML document has been failed.')); + throw new LocalizedException(__('The security validation of the XML document has failed.')); } $xmlElement = simplexml_load_string($xmlContent, $customSimplexml); diff --git a/app/code/Magento/Shipping/Model/Shipping/Labels.php b/app/code/Magento/Shipping/Model/Shipping/Labels.php index 6a1660c9f02ed..5c796d9fa6897 100644 --- a/app/code/Magento/Shipping/Model/Shipping/Labels.php +++ b/app/code/Magento/Shipping/Model/Shipping/Labels.php @@ -91,7 +91,9 @@ public function requestToShipment(Shipment $orderShipment) $shipmentCarrier = $this->_carrierFactory->create($order->getShippingMethod(true)->getCarrierCode()); $baseCurrencyCode = $this->_storeManager->getStore($shipmentStoreId)->getBaseCurrencyCode(); if (!$shipmentCarrier) { - throw new LocalizedException(__('Invalid carrier: %1', $shippingMethod->getCarrierCode())); + throw new LocalizedException( + __('The "%1" carrier is invalid. Verify and try again.', $shippingMethod->getCarrierCode()) + ); } $shipperRegionCode = $this->_scopeConfig->getValue( Shipment::XML_PATH_STORE_REGION_ID, @@ -138,8 +140,8 @@ public function requestToShipment(Shipment $orderShipment) ) { throw new LocalizedException( __( - 'We don\'t have enough information to create shipping labels.' - . ' Please make sure your store information and settings are complete.' + "Shipping labels can't be created. " + . "Verify that the store information and settings are complete and try again." ) ); } diff --git a/app/code/Magento/Shipping/Test/Unit/Model/Carrier/AbstractCarrierOnlineTest.php b/app/code/Magento/Shipping/Test/Unit/Model/Carrier/AbstractCarrierOnlineTest.php index 499f71a271981..6f87eb171a398 100644 --- a/app/code/Magento/Shipping/Test/Unit/Model/Carrier/AbstractCarrierOnlineTest.php +++ b/app/code/Magento/Shipping/Test/Unit/Model/Carrier/AbstractCarrierOnlineTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Shipping\Test\Unit\Model\Carrier; use \Magento\Shipping\Model\Carrier\AbstractCarrierOnline; @@ -118,7 +119,7 @@ public function testParseXml() /** * @expectedException \Magento\Framework\Exception\LocalizedException - * @expectedExceptionMessage Security validation of XML document has been failed. + * @expectedExceptionMessage The security validation of the XML document has failed. */ public function testParseXmlXXEXml() { @@ -134,7 +135,7 @@ public function testParseXmlXXEXml() /** * @expectedException \Magento\Framework\Exception\LocalizedException - * @expectedExceptionMessage Security validation of XML document has been failed. + * @expectedExceptionMessage The security validation of the XML document has failed. */ public function testParseXmlXQBXml() { diff --git a/app/code/Magento/Shipping/etc/module.xml b/app/code/Magento/Shipping/etc/module.xml index af78f43d77644..1a54ecd64b38e 100644 --- a/app/code/Magento/Shipping/etc/module.xml +++ b/app/code/Magento/Shipping/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/Signifyd/etc/module.xml b/app/code/Magento/Signifyd/etc/module.xml index d5adcba88ad9a..264f295e8c528 100644 --- a/app/code/Magento/Signifyd/etc/module.xml +++ b/app/code/Magento/Signifyd/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/Sitemap/etc/module.xml b/app/code/Magento/Sitemap/etc/module.xml index 0cfe3d551d162..cf6327ac94e2c 100644 --- a/app/code/Magento/Sitemap/etc/module.xml +++ b/app/code/Magento/Sitemap/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/Store/Controller/Store/SwitchAction.php b/app/code/Magento/Store/Controller/Store/SwitchAction.php index aa023e400460f..f2872a51db6f4 100644 --- a/app/code/Magento/Store/Controller/Store/SwitchAction.php +++ b/app/code/Magento/Store/Controller/Store/SwitchAction.php @@ -4,6 +4,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Store\Controller\Store; use Magento\Framework\App\Action\Action; @@ -81,7 +82,7 @@ public function execute() } catch (StoreIsInactiveException $e) { $error = __('Requested store is inactive'); } catch (NoSuchEntityException $e) { - $error = __('Requested store is not found'); + $error = __("The store that was requested wasn't found. Verify the store and try again."); } if (isset($error)) { diff --git a/app/code/Magento/Store/Model/Config/Importer/Processor/Create.php b/app/code/Magento/Store/Model/Config/Importer/Processor/Create.php index 768482aa44636..edae49b77ff27 100644 --- a/app/code/Magento/Store/Model/Config/Importer/Processor/Create.php +++ b/app/code/Magento/Store/Model/Config/Importer/Processor/Create.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Store\Model\Config\Importer\Processor; use Magento\Framework\Event\ManagerInterface; @@ -243,7 +244,7 @@ private function detectWebsiteById(array $data, $websiteId) } } - throw new NotFoundException(__('Website was not found')); + throw new NotFoundException(__("The website wasn't found. Verify the website and try again.")); } /** @@ -266,7 +267,7 @@ private function detectGroupById(array $data, $groupId) } } - throw new NotFoundException(__('Group was not found')); + throw new NotFoundException(__("The group wasn't found. Verify the group and try again.")); } /** @@ -289,6 +290,6 @@ private function detectStoreById(array $data, $storeId) } } - throw new NotFoundException(__('Store was not found')); + throw new NotFoundException(__("The store wasn't found. Verify the store and try again.")); } } diff --git a/app/code/Magento/Store/Model/Config/Importer/Processor/ProcessorFactory.php b/app/code/Magento/Store/Model/Config/Importer/Processor/ProcessorFactory.php index 796d3849a740f..3af10deb69590 100644 --- a/app/code/Magento/Store/Model/Config/Importer/Processor/ProcessorFactory.php +++ b/app/code/Magento/Store/Model/Config/Importer/Processor/ProcessorFactory.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Store\Model\Config\Importer\Processor; use Magento\Framework\Exception\ConfigurationMismatchException; @@ -57,7 +58,9 @@ public function __construct( public function create($processorName) { if (!isset($this->processors[$processorName])) { - throw new ConfigurationMismatchException(__('Class for type "%1" was not declared', $processorName)); + throw new ConfigurationMismatchException( + __('The class for "%1" type wasn\'t declared. Enter the class and try again.', $processorName) + ); } $object = $this->objectManager->create($this->processors[$processorName]); diff --git a/app/code/Magento/Store/Model/Resolver/Group.php b/app/code/Magento/Store/Model/Resolver/Group.php index 3235b9c61a8bd..fba1701a53fdd 100644 --- a/app/code/Magento/Store/Model/Resolver/Group.php +++ b/app/code/Magento/Store/Model/Resolver/Group.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Store\Model\Resolver; use Magento\Framework\App\ScopeInterface; @@ -33,7 +34,7 @@ public function getScope($scopeId = null) { $scope = $this->storeManager->getGroup($scopeId); if (!$scope instanceof ScopeInterface) { - throw new InitException(__('Invalid scope object')); + throw new InitException(__('The scope object is invalid. Verify the scope object and try again.')); } return $scope; diff --git a/app/code/Magento/Store/Model/Resolver/Store.php b/app/code/Magento/Store/Model/Resolver/Store.php index afbe10d8e25cb..c01e49cd644a5 100644 --- a/app/code/Magento/Store/Model/Resolver/Store.php +++ b/app/code/Magento/Store/Model/Resolver/Store.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Store\Model\Resolver; class Store implements \Magento\Framework\App\ScopeResolverInterface @@ -28,7 +29,9 @@ public function getScope($scopeId = null) { $scope = $this->_storeManager->getStore($scopeId); if (!$scope instanceof \Magento\Framework\App\ScopeInterface) { - throw new \Magento\Framework\Exception\State\InitException(__('Invalid scope object')); + throw new \Magento\Framework\Exception\State\InitException( + __('The scope object is invalid. Verify the scope object and try again.') + ); } return $scope; diff --git a/app/code/Magento/Store/Model/Resolver/Website.php b/app/code/Magento/Store/Model/Resolver/Website.php index a8b88551d5e9d..87c2664bd1022 100644 --- a/app/code/Magento/Store/Model/Resolver/Website.php +++ b/app/code/Magento/Store/Model/Resolver/Website.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Store\Model\Resolver; class Website implements \Magento\Framework\App\ScopeResolverInterface @@ -29,7 +30,9 @@ public function getScope($scopeId = null) { $scope = $this->_storeManager->getWebsite($scopeId); if (!($scope instanceof \Magento\Framework\App\ScopeInterface)) { - throw new \Magento\Framework\Exception\State\InitException(__('Invalid scope object')); + throw new \Magento\Framework\Exception\State\InitException( + __('The scope object is invalid. Verify the scope object and try again.') + ); } return $scope; diff --git a/app/code/Magento/Store/Model/StoreRepository.php b/app/code/Magento/Store/Model/StoreRepository.php index 35871312da816..7e6773c2d24a3 100644 --- a/app/code/Magento/Store/Model/StoreRepository.php +++ b/app/code/Magento/Store/Model/StoreRepository.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Store\Model; use Magento\Framework\App\ObjectManager; @@ -71,7 +72,9 @@ public function get($code) ]); if ($store->getId() === null) { - throw new NoSuchEntityException(__('Requested store is not found')); + throw new NoSuchEntityException( + __("The store that was requested wasn't found. Verify the store and try again.") + ); } $this->entities[$code] = $store; $this->entitiesById[$store->getId()] = $store; @@ -106,7 +109,9 @@ public function getById($id) ]); if ($store->getId() === null) { - throw new NoSuchEntityException(__('Requested store is not found')); + throw new NoSuchEntityException( + __("The store that was requested wasn't found. Verify the store and try again.") + ); } $this->entitiesById[$id] = $store; diff --git a/app/code/Magento/Store/Model/WebsiteRepository.php b/app/code/Magento/Store/Model/WebsiteRepository.php index 94fd59c7634df..b58936c32f593 100644 --- a/app/code/Magento/Store/Model/WebsiteRepository.php +++ b/app/code/Magento/Store/Model/WebsiteRepository.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Store\Model; use Magento\Framework\App\ObjectManager; @@ -141,7 +142,7 @@ public function getDefault() $this->initDefaultWebsite(); } if (!$this->default) { - throw new \DomainException(__('Default website is not defined')); + throw new \DomainException(__("The default website isn't defined. Set the website and try again.")); } } @@ -183,7 +184,12 @@ private function initDefaultWebsite() foreach ($websites as $data) { if (isset($data['is_default']) && $data['is_default'] == 1) { if ($this->default) { - throw new \DomainException(__('More than one default website is defined')); + throw new \DomainException( + __( + 'The default website is invalid. ' + . 'Make sure no more than one default is defined and try again.' + ) + ); } $website = $this->factory->create([ 'data' => $data diff --git a/app/code/Magento/Store/Setup/Patch/Data/UpdateStoreGroupCodes.php b/app/code/Magento/Store/Setup/Patch/Data/UpdateStoreGroupCodes.php new file mode 100644 index 0000000000000..3d1cba53f8246 --- /dev/null +++ b/app/code/Magento/Store/Setup/Patch/Data/UpdateStoreGroupCodes.php @@ -0,0 +1,103 @@ +moduleDataSetup = $moduleDataSetup; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + $this->updateStoreGroupCodes(); + } + + /** + * Upgrade codes for store groups + */ + private function updateStoreGroupCodes() + { + $connection = $this->moduleDataSetup->getConnection(); + $storeGroupTable = $this->moduleDataSetup->getTable('store_group'); + $select = $connection->select()->from( + $storeGroupTable, + ['group_id', 'name'] + ); + + $groupList = $connection->fetchPairs($select); + + $codes = []; + foreach ($groupList as $groupId => $groupName) { + $code = preg_replace('/\s+/', '_', $groupName); + $code = preg_replace('/[^a-z0-9-_]/', '', strtolower($code)); + $code = preg_replace('/^[^a-z]+/', '', $code); + + if (empty($code)) { + $code = 'store_group'; + } + + if (array_key_exists($code, $codes)) { + $codes[$code]++; + $code = $code . $codes[$code]; + } + $codes[$code] = 1; + + $connection->update( + $storeGroupTable, + ['code' => $code], + ['group_id = ?' => $groupId] + ); + } + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return []; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.1.0'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } +} diff --git a/app/code/Magento/Store/Setup/Recurring.php b/app/code/Magento/Store/Setup/Patch/Schema/InitializeStoresAndWebsites.php similarity index 59% rename from app/code/Magento/Store/Setup/Recurring.php rename to app/code/Magento/Store/Setup/Patch/Schema/InitializeStoresAndWebsites.php index c4ab9196d9f46..506800168eab8 100644 --- a/app/code/Magento/Store/Setup/Recurring.php +++ b/app/code/Magento/Store/Setup/Patch/Schema/InitializeStoresAndWebsites.php @@ -4,52 +4,56 @@ * See COPYING.txt for license details. */ -namespace Magento\Store\Setup; +namespace Magento\Store\Setup\Patch\Schema; use Magento\Catalog\Helper\DefaultCategory; -use Magento\Framework\Setup\InstallSchemaInterface; -use Magento\Framework\Setup\ModuleContextInterface; use Magento\Framework\Setup\SchemaSetupInterface; +use Magento\Setup\Model\Patch\PatchVersionInterface; +use Magento\Setup\Model\Patch\SchemaPatchInterface; /** - * Recurring setup for Store module. - * - * @package Magento\Store\Setup + * Create stores and websites. Actually stores and websites are part of schema as + * other modules schema relies on store and website presence. + * @package Magento\Store\Setup\Patch\Schema */ -class Recurring implements InstallSchemaInterface +class InitializeStoresAndWebsites implements SchemaPatchInterface, PatchVersionInterface { + /** + * @var SchemaSetupInterface + */ + private $schemaSetup; + /** * @var DefaultCategory */ private $defaultCategory; /** - * Get default category. - * - * @deprecated 100.1.0 - * @return DefaultCategory + * @var \Magento\Catalog\Helper\DefaultCategoryFactory */ - private function getDefaultCategory() - { - if ($this->defaultCategory === null) { - $this->defaultCategory = \Magento\Framework\App\ObjectManager::getInstance() - ->get(DefaultCategory::class); - } - return $this->defaultCategory; + private $defaultCategoryFactory; + + /** + * PatchInitial constructor. + * @param SchemaSetupInterface $schemaSetup + */ + public function __construct( + SchemaSetupInterface $schemaSetup, + \Magento\Catalog\Helper\DefaultCategoryFactory $defaultCategoryFactory + ) { + $this->schemaSetup = $schemaSetup; + $this->defaultCategoryFactory = $defaultCategoryFactory; } /** * {@inheritdoc} - * @throws \Exception */ - public function install(SchemaSetupInterface $setup, ModuleContextInterface $context) + public function apply() { - $installer = $setup; - - $installer->startSetup(); - $connection = $installer->getConnection(); + $this->schemaSetup->startSetup(); + $connection = $this->schemaSetup->getConnection(); $select = $connection->select() - ->from($installer->getTable('store_website')) + ->from($this->schemaSetup->getTable('store_website')) ->where('website_id = ?', 0); if ($connection->fetchOne($select) === false) { @@ -57,7 +61,7 @@ public function install(SchemaSetupInterface $setup, ModuleContextInterface $con * Insert websites */ $connection->insertForce( - $installer->getTable('store_website'), + $this->schemaSetup->getTable('store_website'), [ 'website_id' => 0, 'code' => 'admin', @@ -68,7 +72,7 @@ public function install(SchemaSetupInterface $setup, ModuleContextInterface $con ] ); $connection->insertForce( - $installer->getTable('store_website'), + $this->schemaSetup->getTable('store_website'), [ 'website_id' => 1, 'code' => 'base', @@ -83,7 +87,7 @@ public function install(SchemaSetupInterface $setup, ModuleContextInterface $con * Insert store groups */ $connection->insertForce( - $installer->getTable('store_group'), + $this->schemaSetup->getTable('store_group'), [ 'group_id' => 0, 'website_id' => 0, @@ -93,7 +97,7 @@ public function install(SchemaSetupInterface $setup, ModuleContextInterface $con ] ); $connection->insertForce( - $installer->getTable('store_group'), + $this->schemaSetup->getTable('store_group'), [ 'group_id' => 1, 'website_id' => 1, @@ -107,7 +111,7 @@ public function install(SchemaSetupInterface $setup, ModuleContextInterface $con * Insert stores */ $connection->insertForce( - $installer->getTable('store'), + $this->schemaSetup->getTable('store'), [ 'store_id' => 0, 'code' => 'admin', @@ -119,7 +123,7 @@ public function install(SchemaSetupInterface $setup, ModuleContextInterface $con ] ); $connection->insertForce( - $installer->getTable('store'), + $this->schemaSetup->getTable('store'), [ 'store_id' => 1, 'code' => 'default', @@ -130,7 +134,45 @@ public function install(SchemaSetupInterface $setup, ModuleContextInterface $con 'is_active' => 1 ] ); - $setup->endSetup(); + $this->schemaSetup->endSetup(); } } + + /** + * Get default category. + * + * @deprecated 100.1.0 + * @return DefaultCategory + */ + private function getDefaultCategory() + { + if ($this->defaultCategory === null) { + $this->defaultCategory = $this->defaultCategoryFactory->create(); + } + return $this->defaultCategory; + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return []; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.0'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } } diff --git a/app/code/Magento/Store/Setup/UpgradeData.php b/app/code/Magento/Store/Setup/UpgradeData.php deleted file mode 100644 index c4b2a595c5332..0000000000000 --- a/app/code/Magento/Store/Setup/UpgradeData.php +++ /dev/null @@ -1,68 +0,0 @@ -getVersion(), '2.1.0', '<')) { - $this->updateStoreGroupCodes($setup); - } - } - - /** - * Update column 'code' in store_group table. - * - * @param ModuleDataSetupInterface $setup - * @return void - */ - private function updateStoreGroupCodes($setup) - { - $storeGroupTable = $setup->getTable('store_group'); - $select = $setup->getConnection()->select()->from( - $storeGroupTable, - ['group_id', 'name'] - ); - - $groupList = $setup->getConnection()->fetchPairs($select); - - $codes = []; - foreach ($groupList as $groupId => $groupName) { - $code = preg_replace('/\s+/', '_', $groupName); - $code = preg_replace('/[^a-z0-9-_]/', '', strtolower($code)); - $code = preg_replace('/^[^a-z]+/', '', $code); - - if (empty($code)) { - $code = 'store_group'; - } - - if (array_key_exists($code, $codes)) { - $codes[$code]++; - $code = $code . $codes[$code]; - } - $codes[$code] = 1; - - $setup->getConnection()->update( - $storeGroupTable, - ['code' => $code], - ['group_id = ?' => $groupId] - ); - } - } -} diff --git a/app/code/Magento/Store/Test/Unit/Model/Config/Importer/Processor/ProcessorFactoryTest.php b/app/code/Magento/Store/Test/Unit/Model/Config/Importer/Processor/ProcessorFactoryTest.php index b1042aea78add..7de97407ebc19 100644 --- a/app/code/Magento/Store/Test/Unit/Model/Config/Importer/Processor/ProcessorFactoryTest.php +++ b/app/code/Magento/Store/Test/Unit/Model/Config/Importer/Processor/ProcessorFactoryTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Store\Test\Unit\Model\Config\Importer\Processor; use Magento\Framework\ObjectManagerInterface; @@ -62,7 +63,7 @@ public function testCreate() /** * @expectedException \Magento\Framework\Exception\ConfigurationMismatchException - * @expectedExceptionMessage Class for type "dummyType" was not declared + * @expectedExceptionMessage The class for "dummyType" type wasn't declared. Enter the class and try again. */ public function testCreateNonExisted() { diff --git a/app/code/Magento/Store/Test/Unit/Model/StoreRepositoryTest.php b/app/code/Magento/Store/Test/Unit/Model/StoreRepositoryTest.php index 03b886459a7cc..59a433a76a08b 100644 --- a/app/code/Magento/Store/Test/Unit/Model/StoreRepositoryTest.php +++ b/app/code/Magento/Store/Test/Unit/Model/StoreRepositoryTest.php @@ -76,7 +76,7 @@ private function initDistroList() /** * @expectedException \Magento\Framework\Exception\NoSuchEntityException - * @expectedExceptionMessage Requested store is not found + * @expectedExceptionMessage The store that was requested wasn't found. Verify the store and try again. */ public function testGetWithException() { @@ -128,7 +128,7 @@ public function testGetByIdWithAvailableStoreFromScope() /** * @expectedException \Magento\Framework\Exception\NoSuchEntityException - * @expectedExceptionMessage Requested store is not found + * @expectedExceptionMessage The store that was requested wasn't found. Verify the store and try again. */ public function testGetByIdWithException() { diff --git a/app/code/Magento/Store/Test/Unit/Model/WebsiteRepositoryTest.php b/app/code/Magento/Store/Test/Unit/Model/WebsiteRepositoryTest.php index 80e4973bbe7fe..bd8ac4b6048cf 100644 --- a/app/code/Magento/Store/Test/Unit/Model/WebsiteRepositoryTest.php +++ b/app/code/Magento/Store/Test/Unit/Model/WebsiteRepositoryTest.php @@ -94,7 +94,6 @@ public function testGetDefault() /** * @expectedException \DomainException - * @expectedExceptionMessage More than one default website is defined */ public function testGetDefaultIsSeveral() { @@ -118,11 +117,15 @@ public function testGetDefaultIsSeveral() $this->websiteFactoryMock->expects($this->any())->method('create')->willReturn($websiteMock); $this->model->getDefault(); + + $this->expectExceptionMessage( + "The default website is invalid. Make sure no more than one default is defined and try again." + ); } /** * @expectedException \DomainException - * @expectedExceptionMessage Default website is not defined + * @expectedExceptionMessage The default website isn't defined. Set the website and try again. */ public function testGetDefaultIsZero() { diff --git a/app/code/Magento/Store/Test/Unit/Setup/UpgradeDataTest.php b/app/code/Magento/Store/Test/Unit/Setup/UpgradeDataTest.php deleted file mode 100644 index 0dc7de4224c43..0000000000000 --- a/app/code/Magento/Store/Test/Unit/Setup/UpgradeDataTest.php +++ /dev/null @@ -1,148 +0,0 @@ -objectManagerHelper = new ObjectManager($this); - - $this->connectionMock = $this->getMockBuilder(AdapterInterface::class) - ->getMockForAbstractClass(); - $this->setupMock = $this->getMockBuilder(ModuleDataSetupInterface::class) - ->getMockForAbstractClass(); - $this->setupMock->expects($this->any()) - ->method('getConnection') - ->willReturn($this->connectionMock); - $this->contextMock = $this->getMockBuilder(ModuleContextInterface::class) - ->disableOriginalConstructor() - ->getMockForAbstractClass(); - - $this->model = new UpgradeData(); - } - - /** - * @param array $groupList - * @param array $expectedCodes - * @dataProvider upgradeDataProvider - */ - public function testUpgradeToVersion210(array $groupList, array $expectedCodes) - { - $tableName = 'store_group'; - $this->setupMock->expects($this->once()) - ->method('getTable') - ->willReturn($tableName); - $selectMock = $this->getMockBuilder(Select::class) - ->setMethods(['from']) - ->disableOriginalConstructor() - ->getMockForAbstractClass(); - $this->contextMock->expects($this->once()) - ->method('getVersion') - ->willReturn('2.0.0'); - $this->connectionMock->expects($this->any()) - ->method('select') - ->willReturn($selectMock); - $selectMock->expects($this->once()) - ->method('from') - ->with('store_group', ['group_id', 'name']) - ->willReturnSelf(); - $this->connectionMock->expects($this->once()) - ->method('fetchPairs') - ->with($selectMock) - ->willReturn($groupList); - - $i = 2; - foreach ($expectedCodes as $groupId => $code) { - $this->connectionMock->expects($this->at($i++)) - ->method('update') - ->with( - $tableName, - ['code' => $code], - ['group_id = ?' => $groupId] - ); - } - - $this->model->upgrade($this->setupMock, $this->contextMock); - } - - public function upgradeDataProvider() - { - return [ - [ - [ - 1 => 'Test Group' - ], - [ - 1 => 'test_group' - ] - ], - [ - [ - 1 => 'Test Group', - 2 => 'Test Group', - 3 => 'Test Group', - ], - [ - 1 => 'test_group', - 2 => 'test_group2', - 3 => 'test_group3' - ] - ], - [ - [ - 1 => '123 Group', - 2 => '12345', - 3 => '123456', - 4 => '123456', - 5 => '12Group34', - 6 => '&#*@#&_group' - ], - [ - 1 => 'group', - 2 => 'store_group', - 3 => 'store_group2', - 4 => 'store_group3', - 5 => 'group34', - 6 => 'group2' - ] - ] - ]; - } -} diff --git a/app/code/Magento/Store/etc/config.xml b/app/code/Magento/Store/etc/config.xml index 470337a97dcd9..1011fe3051321 100644 --- a/app/code/Magento/Store/etc/config.xml +++ b/app/code/Magento/Store/etc/config.xml @@ -21,13 +21,13 @@ 0 0 - /tiny_mce/ + /tiny_mce/ 0 - /tiny_mce/ + /tiny_mce/ diff --git a/app/code/Magento/Store/etc/module.xml b/app/code/Magento/Store/etc/module.xml index 644520f9a9e28..b034d18b0a310 100644 --- a/app/code/Magento/Store/etc/module.xml +++ b/app/code/Magento/Store/etc/module.xml @@ -6,6 +6,6 @@ */ --> - + diff --git a/app/code/Magento/Swagger/etc/module.xml b/app/code/Magento/Swagger/etc/module.xml index 8f1086057b57e..fce24b61b4f86 100644 --- a/app/code/Magento/Swagger/etc/module.xml +++ b/app/code/Magento/Swagger/etc/module.xml @@ -6,5 +6,5 @@ */ --> - + 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 6e8ad08efbf6b..27b3767f274bc 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,7 +12,7 @@ * Modified by Magento, Modifications Copyright © Magento, Inc. All rights reserved. */ -/** @var \Magento\Framework\View\Element\Template $block */ +/** @var \Magento\Swagger\Block\Index $block */ $schemaUrl = $block->getSchemaUrl(); ?> diff --git a/app/code/Magento/Swatches/Helper/Media.php b/app/code/Magento/Swatches/Helper/Media.php index c04b0ca945cec..baa90343cc4ab 100644 --- a/app/code/Magento/Swatches/Helper/Media.php +++ b/app/code/Magento/Swatches/Helper/Media.php @@ -68,9 +68,9 @@ class Media extends \Magento\Framework\App\Helper\AbstractHelper protected $swatchImageTypes = ['swatch_image', 'swatch_thumb']; /** - * @var \Magento\Theme\Model\ResourceModel\Theme\Collection + * @var array */ - private $registeredThemesCache; + private $imageConfig; /** * @param \Magento\Catalog\Model\Product\Media\Config $mediaConfig @@ -256,18 +256,14 @@ public function getFolderNameSize($swatchType, $imageConfig = null) */ public function getImageConfig() { - $imageConfig = []; - foreach ($this->getRegisteredThemes() as $theme) { - $config = $this->viewConfig->getViewConfig([ - 'area' => Area::AREA_FRONTEND, - 'themeModel' => $theme, - ]); - $imageConfig = array_merge( - $imageConfig, - $config->getMediaEntities('Magento_Catalog', Image::MEDIA_TYPE_CONFIG_NODE) + if (!$this->imageConfig) { + $this->imageConfig = $this->viewConfig->getViewConfig()->getMediaEntities( + 'Magento_Catalog', + Image::MEDIA_TYPE_CONFIG_NODE ); } - return $imageConfig; + + return $this->imageConfig; } /** @@ -338,16 +334,4 @@ protected function prepareFile($file) { return ltrim(str_replace('\\', '/', $file), '/'); } - - /** - * @return \Magento\Theme\Model\ResourceModel\Theme\Collection - */ - private function getRegisteredThemes() - { - if ($this->registeredThemesCache === null) { - $this->registeredThemesCache = $this->themeCollection->loadRegisteredThemes(); - } - - return $this->registeredThemesCache; - } } diff --git a/app/code/Magento/Swatches/Setup/InstallData.php b/app/code/Magento/Swatches/Setup/InstallData.php deleted file mode 100644 index eab2fd68607bd..0000000000000 --- a/app/code/Magento/Swatches/Setup/InstallData.php +++ /dev/null @@ -1,67 +0,0 @@ -eavSetupFactory = $eavSetupFactory; - } - - /** - * Install new Swatch entity - * - * @SuppressWarnings(PHPMD.UnusedFormalParameter) - * @param ModuleDataSetupInterface $setup - * @param ModuleContextInterface $context - * @return void - */ - public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context) - { - /** @var EavSetup $eavSetup */ - $eavSetup = $this->eavSetupFactory->create(['setup' => $setup]); - - /** - * Install eav entity types to the eav/entity_type table - */ - $eavSetup->addAttribute( - 'catalog_product', - 'swatch_image', - [ - 'type' => 'varchar', - 'label' => 'Swatch', - 'input' => 'media_image', - 'frontend' => \Magento\Catalog\Model\Product\Attribute\Frontend\Image::class, - 'required' => false, - 'sort_order' => 3, - 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE, - 'used_in_product_listing' => true - ] - ); - } -} diff --git a/app/code/Magento/Swatches/Setup/Patch/Data/AddSwatchImageAttribute.php b/app/code/Magento/Swatches/Setup/Patch/Data/AddSwatchImageAttribute.php new file mode 100644 index 0000000000000..760fbc73b9030 --- /dev/null +++ b/app/code/Magento/Swatches/Setup/Patch/Data/AddSwatchImageAttribute.php @@ -0,0 +1,96 @@ +moduleDataSetup = $moduleDataSetup; + $this->eavSetupFactory = $eavSetupFactory; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + /** @var EavSetup $eavSetup */ + $eavSetup = $this->eavSetupFactory->create(['setup' => $this->moduleDataSetup]); + + /** + * Install eav entity types to the eav/entity_type table + */ + $eavSetup->addAttribute( + 'catalog_product', + 'swatch_image', + [ + 'type' => 'varchar', + 'label' => 'Swatch', + 'input' => 'media_image', + 'frontend' => Image::class, + 'required' => false, + 'sort_order' => 3, + 'global' => ScopedAttributeInterface::SCOPE_STORE, + 'used_in_product_listing' => true + ] + ); + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return []; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.0'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } +} diff --git a/app/code/Magento/Swatches/Setup/Patch/Data/AddSwatchImageToDefaultAttribtueSet.php b/app/code/Magento/Swatches/Setup/Patch/Data/AddSwatchImageToDefaultAttribtueSet.php new file mode 100644 index 0000000000000..edd0bb6df46a7 --- /dev/null +++ b/app/code/Magento/Swatches/Setup/Patch/Data/AddSwatchImageToDefaultAttribtueSet.php @@ -0,0 +1,89 @@ +moduleDataSetup = $moduleDataSetup; + $this->eavSetupFactory = $eavSetupFactory; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + $this->moduleDataSetup->getConnection()->startSetup(); + + /** @var \Magento\Eav\Setup\EavSetup $eavSetup */ + $eavSetup = $this->eavSetupFactory->create(['setup' => $this->moduleDataSetup]); + $attributeSetId = $eavSetup->getDefaultAttributeSetId(Product::ENTITY); + $groupId = (int)$eavSetup->getAttributeGroupByCode( + Product::ENTITY, + $attributeSetId, + 'image-management', + 'attribute_group_id' + ); + $eavSetup->addAttributeToGroup(Product::ENTITY, $attributeSetId, $groupId, 'swatch_image'); + + $this->moduleDataSetup->getConnection()->endSetup(); + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return [ + AddSwatchImageAttribute::class + ]; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.1'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } +} diff --git a/app/code/Magento/Swatches/Setup/Patch/Data/ConvertAdditionalDataToJson.php b/app/code/Magento/Swatches/Setup/Patch/Data/ConvertAdditionalDataToJson.php new file mode 100644 index 0000000000000..0ecd5aa668ff0 --- /dev/null +++ b/app/code/Magento/Swatches/Setup/Patch/Data/ConvertAdditionalDataToJson.php @@ -0,0 +1,93 @@ +moduleDataSetup = $moduleDataSetup; + $this->fieldDataConverterFactory = $fieldDataConverterFactory; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + $this->moduleDataSetup->getConnection()->startSetup(); + $this->convertAddDataToJson(); + $this->moduleDataSetup->getConnection()->endSetup(); + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return [ + UpdateAdminTextSwatchValues::class + ]; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.3'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } + + /** + * Convert serialized additional data to json. + */ + private function convertAddDataToJson() + { + $fieldConverter = $this->fieldDataConverterFactory->create(SerializedToJson::class); + $fieldConverter->convert( + $this->moduleDataSetup->getConnection(), + $this->moduleDataSetup->getTable('catalog_eav_attribute'), + 'attribute_id', + 'additional_data' + ); + } +} diff --git a/app/code/Magento/Swatches/Setup/Patch/Data/UpdateAdminTextSwatchValues.php b/app/code/Magento/Swatches/Setup/Patch/Data/UpdateAdminTextSwatchValues.php new file mode 100644 index 0000000000000..abcb67a99d9de --- /dev/null +++ b/app/code/Magento/Swatches/Setup/Patch/Data/UpdateAdminTextSwatchValues.php @@ -0,0 +1,120 @@ +moduleDataSetup = $moduleDataSetup; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + $this->moduleDataSetup->getConnection()->startSetup(); + $this->updateAdminTextSwatchValues(); + $this->moduleDataSetup->getConnection()->endSetup(); + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return [ + AddSwatchImageToDefaultAttribtueSet::class + ]; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.2'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } + + /** + * Update text swatch values for admin panel. + */ + private function updateAdminTextSwatchValues() + { + $connection = $this->moduleDataSetup->getConnection(); + $storeData = $connection + ->select() + ->from($this->moduleDataSetup->getTable('store')) + ->where(Store::STORE_ID . "<> ? ", Store::DEFAULT_STORE_ID) + ->order("sort_order desc") + ->limit(1) + ->query(Zend_Db::FETCH_ASSOC) + ->fetch(); + + if (is_array($storeData)) { + + /** + * update eav_attribute_option_swatch as s + * left join eav_attribute_option_swatch as ls on ls.option_id = s.option_id and ls.store_id = 1 + * set + * + * s.value = ls.value + * where s.store_id = 0 and s.`type` = 0 and s.value = "" + */ + + /** @var \Magento\Framework\DB\Select $select */ + $select = $connection + ->select() + ->joinLeft( + ["ls" => $this->moduleDataSetup->getTable('eav_attribute_option_swatch')], + new Zend_Db_Expr("ls.option_id = s.option_id AND ls.store_id = " . $storeData[Store::STORE_ID]), + ["value"] + ) + ->where("s.store_id = ? ", Store::DEFAULT_STORE_ID) + ->where("s.type = ? ", Swatch::SWATCH_TYPE_TEXTUAL) + ->where("s.value = ? or s.value is null", ""); + + $connection->query( + $connection->updateFromSelect( + $select, + ["s" => $this->moduleDataSetup->getTable('eav_attribute_option_swatch')] + ) + ); + } + } +} diff --git a/app/code/Magento/Swatches/Setup/UpgradeData.php b/app/code/Magento/Swatches/Setup/UpgradeData.php deleted file mode 100644 index 880422a371abd..0000000000000 --- a/app/code/Magento/Swatches/Setup/UpgradeData.php +++ /dev/null @@ -1,149 +0,0 @@ -eavSetupFactory = $eavSetupFactory; - $this->fieldDataConverterFactory = $fieldDataConverterFactory - ?: ObjectManager::getInstance()->get(FieldDataConverterFactory::class); - } - - /** - * {@inheritdoc} - */ - public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context) - { - $setup->startSetup(); - - if (version_compare($context->getVersion(), '2.0.1', '<')) { - /** @var \Magento\Eav\Setup\EavSetup $eavSetup */ - $eavSetup = $this->eavSetupFactory->create(['setup' => $setup]); - $attributeSetId = $eavSetup->getDefaultAttributeSetId(Product::ENTITY); - $groupId = (int)$eavSetup->getAttributeGroupByCode( - Product::ENTITY, - $attributeSetId, - 'image-management', - 'attribute_group_id' - ); - $eavSetup->addAttributeToGroup(Product::ENTITY, $attributeSetId, $groupId, 'swatch_image'); - } - - if (version_compare($context->getVersion(), '2.0.2', '<')) { - $this->updateAdminTextSwatchValues($setup); - } - if (version_compare($context->getVersion(), '2.0.3', '<')) { - $this->convertAddDataToJson($setup); - } - - $setup->endSetup(); - } - - /** - * Add fallback for default scope. - * - * @param ModuleDataSetupInterface $setup - * - * @return void - */ - private function updateAdminTextSwatchValues(ModuleDataSetupInterface $setup) - { - $storeData = $setup->getConnection() - ->select() - ->from($setup->getTable('store')) - ->where(Store::STORE_ID . "<> ? ", Store::DEFAULT_STORE_ID) - ->order("sort_order desc") - ->limit(1) - ->query(Zend_Db::FETCH_ASSOC) - ->fetch(); - - if (is_array($storeData)) { - - /** - * update eav_attribute_option_swatch as s - * left join eav_attribute_option_swatch as ls on ls.option_id = s.option_id and ls.store_id = 1 - * set - * - * s.value = ls.value - * where s.store_id = 0 and s.`type` = 0 and s.value = "" - */ - - /** @var \Magento\Framework\DB\Select $select */ - $select = $setup->getConnection() - ->select() - ->joinLeft( - ["ls" => $setup->getTable('eav_attribute_option_swatch')], - new Zend_Db_Expr("ls.option_id = s.option_id AND ls.store_id = " . $storeData[Store::STORE_ID]), - ["value"] - ) - ->where("s.store_id = ? ", Store::DEFAULT_STORE_ID) - ->where("s.type = ? ", Swatch::SWATCH_TYPE_TEXTUAL) - ->where("s.value = ? or s.value is null", ""); - - $setup->getConnection()->query( - $setup->getConnection()->updateFromSelect( - $select, - ["s" => $setup->getTable('eav_attribute_option_swatch')] - ) - ); - } - } - - /** - * Convert additional data column from serialized view to JSON for swatch attributes. - * - * @param ModuleDataSetupInterface $setup - * @return void - */ - private function convertAddDataToJson(ModuleDataSetupInterface $setup) - { - $fieldConverter = $this->fieldDataConverterFactory->create(SerializedToJson::class); - $fieldConverter->convert( - $setup->getConnection(), - $setup->getTable('catalog_eav_attribute'), - 'attribute_id', - 'additional_data' - ); - } -} diff --git a/app/code/Magento/Swatches/Test/Unit/Helper/MediaTest.php b/app/code/Magento/Swatches/Test/Unit/Helper/MediaTest.php index 920c35e44ebde..7ecfeab53b90d 100644 --- a/app/code/Magento/Swatches/Test/Unit/Helper/MediaTest.php +++ b/app/code/Magento/Swatches/Test/Unit/Helper/MediaTest.php @@ -30,9 +30,6 @@ class MediaTest extends \PHPUnit\Framework\TestCase /** @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\Image\Factory */ protected $imageFactoryMock; - /** @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Theme\Model\ResourceModel\Theme\Collection */ - protected $themeCollectionMock; - /** @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\View\Config */ protected $viewConfigMock; @@ -59,10 +56,6 @@ protected function setUp() $this->storeManagerMock = $this->createPartialMock(\Magento\Store\Model\StoreManager::class, ['getStore']); $this->imageFactoryMock = $this->createMock(\Magento\Framework\Image\Factory::class); - $this->themeCollectionMock = $this->createPartialMock( - \Magento\Theme\Model\ResourceModel\Theme\Collection::class, - ['loadRegisteredThemes'] - ); $this->viewConfigMock = $this->createMock(\Magento\Framework\View\Config::class); @@ -83,7 +76,6 @@ protected function setUp() 'fileStorageDb' => $this->fileStorageDbMock, 'storeManager' => $this->storeManagerMock, 'imageFactory' => $this->imageFactoryMock, - 'themeCollection' => $this->themeCollectionMock, 'configInterface' => $this->viewConfigMock, ] ); @@ -248,10 +240,6 @@ public function testGetImageConfig() protected function generateImageConfig() { - $themeMock = $this->createMock(\Magento\Theme\Model\Theme::class); - $themesArrayMock = [$themeMock]; - $this->themeCollectionMock->expects($this->any())->method('loadRegisteredThemes')->willReturn($themesArrayMock); - $configMock = $this->createMock(\Magento\Framework\Config\View::class); $this->viewConfigMock diff --git a/app/code/Magento/Swatches/etc/module.xml b/app/code/Magento/Swatches/etc/module.xml index 1faec3b2792cb..4c97d8e0d8d1c 100644 --- a/app/code/Magento/Swatches/etc/module.xml +++ b/app/code/Magento/Swatches/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/Swatches/view/adminhtml/ui_component/design_config_form.xml b/app/code/Magento/Swatches/view/adminhtml/ui_component/design_config_form.xml index 66626add3f671..1c58243be3262 100644 --- a/app/code/Magento/Swatches/view/adminhtml/ui_component/design_config_form.xml +++ b/app/code/Magento/Swatches/view/adminhtml/ui_component/design_config_form.xml @@ -15,12 +15,11 @@ - Allowed file types: jpeg, gif, png. - fileUploader + imageUploader - + jpg jpeg gif png 2097152 @@ -28,7 +27,7 @@ theme/design_config_fileUploader/save - + diff --git a/app/code/Magento/Swatches/view/frontend/web/js/swatch-renderer.js b/app/code/Magento/Swatches/view/frontend/web/js/swatch-renderer.js index d1f7c477ba8d7..a24c72c473fe9 100644 --- a/app/code/Magento/Swatches/view/frontend/web/js/swatch-renderer.js +++ b/app/code/Magento/Swatches/view/frontend/web/js/swatch-renderer.js @@ -90,7 +90,7 @@ define([ $title, $corner; - if (!$element.size()) { + if (!$element.length) { $element = $('
    ' @@ -810,7 +810,7 @@ define([ $widget._Rewind(controls); // done if nothing selected - if (selected.size() <= 0) { + if (selected.length <= 0) { return; } @@ -820,7 +820,7 @@ define([ id = $this.attr('attribute-id'), products = $widget._CalcProducts(id); - if (selected.size() === 1 && selected.first().attr('attribute-id') === id) { + if (selected.length === 1 && selected.first().attr('attribute-id') === id) { return; } @@ -1016,7 +1016,7 @@ define([ _EnableProductMediaLoader: function ($this) { var $widget = this; - if ($('body.catalog-product-view').size() > 0) { + if ($('body.catalog-product-view').length > 0) { $this.parents('.column.main').find('.photo.image') .addClass($widget.options.classes.loader); } else { @@ -1035,7 +1035,7 @@ define([ _DisableProductMediaLoader: function ($this) { var $widget = this; - if ($('body.catalog-product-view').size() > 0) { + if ($('body.catalog-product-view').length > 0) { $this.parents('.column.main').find('.photo.image') .removeClass($widget.options.classes.loader); } else { diff --git a/app/code/Magento/SwatchesGraphQl/etc/module.xml b/app/code/Magento/SwatchesGraphQl/etc/module.xml index c57d1c4510189..de2baeee94c57 100644 --- a/app/code/Magento/SwatchesGraphQl/etc/module.xml +++ b/app/code/Magento/SwatchesGraphQl/etc/module.xml @@ -6,5 +6,5 @@ */ --> - + diff --git a/app/code/Magento/SwatchesLayeredNavigation/etc/module.xml b/app/code/Magento/SwatchesLayeredNavigation/etc/module.xml index fb0ac8f1a0685..5b042ef434ddb 100644 --- a/app/code/Magento/SwatchesLayeredNavigation/etc/module.xml +++ b/app/code/Magento/SwatchesLayeredNavigation/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/Tax/Model/Calculation/Rate.php b/app/code/Magento/Tax/Model/Calculation/Rate.php index 1930ee8ec380d..e848afd7f3eca 100644 --- a/app/code/Magento/Tax/Model/Calculation/Rate.php +++ b/app/code/Magento/Tax/Model/Calculation/Rate.php @@ -124,13 +124,13 @@ public function beforeSave() if ($isEmptyValues || $isWrongRange) { throw new \Magento\Framework\Exception\LocalizedException( - __('Make sure all required information is valid.') + __('The required information is invalid. Verify the information and try again.') ); } if (!is_numeric($this->getRate()) || $this->getRate() < 0) { throw new \Magento\Framework\Exception\LocalizedException( - __('The Rate Percent should be a positive number.') + __('The Rate Percent is invalid. Enter a positive number and try again.') ); } @@ -139,12 +139,17 @@ public function beforeSave() $zipTo = $this->getZipTo(); if (strlen($zipFrom) > 9 || strlen($zipTo) > 9) { - throw new \Magento\Framework\Exception\LocalizedException(__('Maximum zip code length is 9.')); + throw new \Magento\Framework\Exception\LocalizedException( + __( + 'The ZIP Code length is invalid. ' + . 'Verify that the length is nine characters or fewer and try again.' + ) + ); } if (!is_numeric($zipFrom) || !is_numeric($zipTo) || $zipFrom < 0 || $zipTo < 0) { throw new \Magento\Framework\Exception\LocalizedException( - __('Use digits only for the zip code.') + __('The ZIP Code is invalid. Use numbers only.') ); } @@ -199,7 +204,7 @@ public function beforeDelete() { if ($this->_isInRule()) { throw new CouldNotDeleteException( - __('The tax rate cannot be removed. It exists in a tax rule.') + __("The tax rate can't be removed because it exists in a tax rule.") ); } return parent::beforeDelete(); diff --git a/app/code/Magento/Tax/Model/Calculation/RateRepository.php b/app/code/Magento/Tax/Model/Calculation/RateRepository.php index 3e7c24ce81015..f8afdf625fd87 100644 --- a/app/code/Magento/Tax/Model/Calculation/RateRepository.php +++ b/app/code/Magento/Tax/Model/Calculation/RateRepository.php @@ -232,7 +232,7 @@ private function validate(\Magento\Tax\Api\Data\TaxRateInterface $taxRate) $countryCode = $taxRate->getTaxCountryId(); if (!\Zend_Validate::is($countryCode, 'NotEmpty')) { - $exception->addError(__('%fieldName is a required field.', ['fieldName' => 'country_id'])); + $exception->addError(__('"%fieldName" is required. Enter and try again.', ['fieldName' => 'country_id'])); } elseif (!\Zend_Validate::is( $this->countryFactory->create()->loadByCode($countryCode)->getId(), 'NotEmpty' @@ -265,11 +265,13 @@ private function validate(\Magento\Tax\Api\Data\TaxRateInterface $taxRate) } if (!is_numeric($taxRate->getRate()) || $taxRate->getRate() < 0) { - $exception->addError(__('%fieldName is a required field.', ['fieldName' => 'percentage_rate'])); + $exception->addError( + __('"%fieldName" is required. Enter and try again.', ['fieldName' => 'percentage_rate']) + ); } if (!\Zend_Validate::is(trim($taxRate->getCode()), 'NotEmpty')) { - $exception->addError(__('%fieldName is a required field.', ['fieldName' => 'code'])); + $exception->addError(__('"%fieldName" is required. Enter and try again.', ['fieldName' => 'code'])); } if ($taxRate->getZipIsRange()) { @@ -292,7 +294,7 @@ private function validate(\Magento\Tax\Api\Data\TaxRateInterface $taxRate) } } else { if (!\Zend_Validate::is(trim($taxRate->getTaxPostcode()), 'NotEmpty')) { - $exception->addError(__('%fieldName is a required field.', ['fieldName' => 'postcode'])); + $exception->addError(__('"%fieldName" is required. Enter and try again.', ['fieldName' => 'postcode'])); } } diff --git a/app/code/Magento/Tax/Model/Calculation/Rule/Validator.php b/app/code/Magento/Tax/Model/Calculation/Rule/Validator.php index 75923748e14cf..2149a0c3c3ca2 100644 --- a/app/code/Magento/Tax/Model/Calculation/Rule/Validator.php +++ b/app/code/Magento/Tax/Model/Calculation/Rule/Validator.php @@ -43,7 +43,11 @@ public function isValid($value) // Position is required and must be 0 or greater if (!\Zend_Validate::is(trim($value->getPosition()), 'NotEmpty')) { - $this->addErrorMessage($messages, '%fieldName is a required field.', ['fieldName' => 'position']); + $this->addErrorMessage( + $messages, + '"%fieldName" is required. Enter and try again.', + ['fieldName' => 'position'] + ); } if (!\Zend_Validate::is(trim($value->getPosition()), 'GreaterThan', [-1])) { $this->addErrorMessage( @@ -55,7 +59,11 @@ public function isValid($value) // Priority is required and must be 0 or greater if (!\Zend_Validate::is(trim($value->getPriority()), 'NotEmpty')) { - $this->addErrorMessage($messages, '%fieldName is a required field.', ['fieldName' => 'priority']); + $this->addErrorMessage( + $messages, + '"%fieldName" is required. Enter and try again.', + ['fieldName' => 'priority'] + ); } if (!\Zend_Validate::is(trim($value->getPriority()), 'GreaterThan', [-1])) { $this->addErrorMessage( @@ -67,14 +75,18 @@ public function isValid($value) // Code is required if (!\Zend_Validate::is(trim($value->getCode()), 'NotEmpty')) { - $this->addErrorMessage($messages, '%fieldName is a required field.', ['fieldName' => 'code']); + $this->addErrorMessage( + $messages, + '"%fieldName" is required. Enter and try again.', + ['fieldName' => 'code'] + ); } // customer tax class ids is required if (($value->getCustomerTaxClassIds() === null) || !$value->getCustomerTaxClassIds()) { $this->addErrorMessage( $messages, - '%fieldName is a required field.', + '"%fieldName" is required. Enter and try again.', ['fieldName' => 'customer_tax_class_ids'] ); } else { // see if the customer tax class ids exist @@ -106,7 +118,7 @@ public function isValid($value) if (($value->getProductTaxClassIds() === null) || !$value->getProductTaxClassIds()) { $this->addErrorMessage( $messages, - '%fieldName is a required field.', + '"%fieldName" is required. Enter and try again.', ['fieldName' => 'product_tax_class_ids'] ); } else { // see if the product tax class ids exist @@ -136,7 +148,11 @@ public function isValid($value) // tax rate ids is required if (($value->getTaxRateIds() === null) || !$value->getTaxRateIds()) { - $this->addErrorMessage($messages, '%fieldName is a required field.', ['fieldName' => 'tax_rate_ids']); + $this->addErrorMessage( + $messages, + '"%fieldName" is required. Enter and try again.', + ['fieldName' => 'tax_rate_ids'] + ); } $this->_addMessages($messages); return empty($messages); diff --git a/app/code/Magento/Tax/Model/TaxClass/Repository.php b/app/code/Magento/Tax/Model/TaxClass/Repository.php index 245fc6964c205..cfb8f82cf0f11 100644 --- a/app/code/Magento/Tax/Model/TaxClass/Repository.php +++ b/app/code/Magento/Tax/Model/TaxClass/Repository.php @@ -179,12 +179,16 @@ protected function validateTaxClassData(\Magento\Tax\Api\Data\TaxClassInterface $exception = new InputException(); if (!\Zend_Validate::is(trim($taxClass->getClassName()), 'NotEmpty')) { - $exception->addError(__('%fieldName is a required field.', ['fieldName' => ClassModel::KEY_NAME])); + $exception->addError( + __('"%fieldName" is required. Enter and try again.', ['fieldName' => ClassModel::KEY_NAME]) + ); } $classType = $taxClass->getClassType(); if (!\Zend_Validate::is(trim($classType), 'NotEmpty')) { - $exception->addError(__('%fieldName is a required field.', ['fieldName' => ClassModel::KEY_TYPE])); + $exception->addError( + __('"%fieldName" is required. Enter and try again.', ['fieldName' => ClassModel::KEY_TYPE]) + ); } elseif ($classType !== TaxClassManagementInterface::TYPE_CUSTOMER && $classType !== TaxClassManagementInterface::TYPE_PRODUCT ) { diff --git a/app/code/Magento/Tax/Setup/InstallData.php b/app/code/Magento/Tax/Setup/Patch/Data/AddTaxAttributeAndTaxClasses.php similarity index 67% rename from app/code/Magento/Tax/Setup/InstallData.php rename to app/code/Magento/Tax/Setup/Patch/Data/AddTaxAttributeAndTaxClasses.php index 31d0798847db5..d6cf3bf6451f1 100644 --- a/app/code/Magento/Tax/Setup/InstallData.php +++ b/app/code/Magento/Tax/Setup/Patch/Data/AddTaxAttributeAndTaxClasses.php @@ -4,49 +4,59 @@ * See COPYING.txt for license details. */ -namespace Magento\Tax\Setup; +namespace Magento\Tax\Setup\Patch\Data; -use Magento\Framework\Setup\InstallDataInterface; -use Magento\Framework\Setup\ModuleContextInterface; -use Magento\Framework\Setup\ModuleDataSetupInterface; use Magento\Directory\Model\RegionFactory; +use Magento\Framework\App\ResourceConnection; +use Magento\Setup\Model\Patch\DataPatchInterface; +use Magento\Setup\Model\Patch\PatchVersionInterface; +use Magento\Tax\Setup\TaxSetup; +use Magento\Tax\Setup\TaxSetupFactory; /** - * @codeCoverageIgnore + * Class AddTacAttributeAndTaxClasses + * @package Magento\Tax\Setup\Patch */ -class InstallData implements InstallDataInterface +class AddTaxAttributeAndTaxClasses implements DataPatchInterface, PatchVersionInterface { /** - * Tax setup factory - * - * @var TaxSetupFactory + * @param TaxSetupFactory $taxSetupFactory */ private $taxSetupFactory; /** - * @var RegionFactory + * @param RegionFactory $directoryRegionFactory */ private $directoryRegionFactory; /** + * @var \Magento\Framework\Setup\ModuleDataSetupInterface + */ + private $moduleDataSetup; + + /** + * AddTacAttributeAndTaxClasses constructor. * @param TaxSetupFactory $taxSetupFactory * @param RegionFactory $directoryRegionFactory + * @param \Magento\Framework\Setup\ModuleDataSetupInterface $moduleDataSetup */ public function __construct( TaxSetupFactory $taxSetupFactory, - RegionFactory $directoryRegionFactory + RegionFactory $directoryRegionFactory, + \Magento\Framework\Setup\ModuleDataSetupInterface $moduleDataSetup ) { $this->taxSetupFactory = $taxSetupFactory; $this->directoryRegionFactory = $directoryRegionFactory; + $this->moduleDataSetup = $moduleDataSetup; } /** * {@inheritdoc} */ - public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context) + public function apply() { /** @var TaxSetup $taxSetup */ - $taxSetup = $this->taxSetupFactory->create(['resourceName' => 'tax_setup', 'setup' => $setup]); + $taxSetup = $this->taxSetupFactory->create(['resourceName' => 'tax_setup', 'setup' => $this->moduleDataSetup]); /** * Add tax_class_id attribute to the 'eav_attribute' table @@ -82,7 +92,6 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface 'is_filterable_in_grid' => true, ] ); - /** * install tax classes */ @@ -99,9 +108,11 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ], ]; foreach ($data as $row) { - $setup->getConnection()->insertForce($setup->getTable('tax_class'), $row); + $this->moduleDataSetup->getConnection()->insertForce( + $this->moduleDataSetup->getTable('tax_class'), + $row + ); } - /** * install tax calculation rates */ @@ -126,7 +137,34 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface ], ]; foreach ($data as $row) { - $setup->getConnection()->insertForce($setup->getTable('tax_calculation_rate'), $row); + $this->moduleDataSetup->getConnection()->insertForce( + $this->moduleDataSetup->getTable('tax_calculation_rate'), + $row + ); } } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return []; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.0'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } } diff --git a/app/code/Magento/Tax/Setup/Patch/Data/UpdateTaxClassAttributeVisibility.php b/app/code/Magento/Tax/Setup/Patch/Data/UpdateTaxClassAttributeVisibility.php new file mode 100644 index 0000000000000..840afb270cb02 --- /dev/null +++ b/app/code/Magento/Tax/Setup/Patch/Data/UpdateTaxClassAttributeVisibility.php @@ -0,0 +1,89 @@ +moduleDataSetup = $moduleDataSetup; + $this->taxSetupFactory = $taxSetupFactory; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + /** @var TaxSetup $taxSetup */ + $taxSetup = $this->taxSetupFactory->create(['resourceName' => 'tax_setup', 'setup' => $this->moduleDataSetup]); + + $this->moduleDataSetup->getConnection()->startSetup(); + + //Update the tax_class_id attribute in the 'catalog_eav_attribute' table + $taxSetup->updateAttribute( + \Magento\Catalog\Model\Product::ENTITY, + 'tax_class_id', + 'is_visible_in_advanced_search', + false + ); + $this->moduleDataSetup->getConnection()->endSetup(); + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return [ + AddTaxAttributeAndTaxClasses::class + ]; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.1'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } +} diff --git a/app/code/Magento/Tax/Setup/Patch/Data/UpdateTaxRegionId.php b/app/code/Magento/Tax/Setup/Patch/Data/UpdateTaxRegionId.php new file mode 100644 index 0000000000000..efe7b04dfb8aa --- /dev/null +++ b/app/code/Magento/Tax/Setup/Patch/Data/UpdateTaxRegionId.php @@ -0,0 +1,127 @@ +moduleDataSetup = $moduleDataSetup; + $this->taxRateRepository = $taxRateRepository; + $this->searchCriteriaFactory = $searchCriteriaFactory; + $this->regionFactory = $regionFactory; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + $this->moduleDataSetup->getConnection()->startSetup(); + + //Update the tax_region_id + $taxRateList = $this->taxRateRepository->getList($this->searchCriteriaFactory->create()); + /** @var \Magento\Tax\Api\Data\TaxRateInterface $taxRateData */ + foreach ($taxRateList->getItems() as $taxRateData) { + $regionCode = $this->parseRegionFromTaxCode($taxRateData->getCode()); + if ($regionCode) { + /** @var \Magento\Directory\Model\Region $region */ + $region = $this->regionFactory->create(); + $region->loadByCode($regionCode, $taxRateData->getTaxCountryId()); + if ($taxRateData->getTaxPostcode() === null) { + $taxRateData->setTaxPostcode('*'); + } + $taxRateData->setTaxRegionId($region->getRegionId()); + $this->taxRateRepository->save($taxRateData); + } + } + $this->moduleDataSetup->getConnection()->endSetup(); + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return [ + UpdateTaxClassAttributeVisibility::class + ]; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.3'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } + + /** + * Parse region from tax code. + * + * @param string $taxCode + * @return string + */ + private function parseRegionFromTaxCode($taxCode) + { + $result = ''; + $parts = explode('-', $taxCode, 3); + + if (isset($parts[1])) { + $result = $parts[1]; + } + + return $result; + } +} diff --git a/app/code/Magento/Tax/Setup/UpgradeData.php b/app/code/Magento/Tax/Setup/UpgradeData.php deleted file mode 100644 index 5ede9cb6180e4..0000000000000 --- a/app/code/Magento/Tax/Setup/UpgradeData.php +++ /dev/null @@ -1,122 +0,0 @@ -taxSetupFactory = $taxSetupFactory; - $this->taxRateRepository = $taxRateRepository; - $this->searchCriteriaFactory = $searchCriteriaFactory; - $this->directoryRegionFactory = $directoryRegionFactory; - } - - /** - * {@inheritdoc} - */ - public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context) - { - /** @var TaxSetup $taxSetup */ - $taxSetup = $this->taxSetupFactory->create(['resourceName' => 'tax_setup', 'setup' => $setup]); - - $setup->startSetup(); - - if (version_compare($context->getVersion(), '2.0.1', '<')) { - //Update the tax_class_id attribute in the 'catalog_eav_attribute' table - $taxSetup->updateAttribute( - \Magento\Catalog\Model\Product::ENTITY, - 'tax_class_id', - 'is_visible_in_advanced_search', - false - ); - } - if (version_compare($context->getVersion(), '2.0.3', '<')) { - //Update the tax_region_id - $taxRateList = $this->taxRateRepository->getList($this->searchCriteriaFactory->create()); - /** @var \Magento\Tax\Api\Data\TaxRateInterface $taxRateData */ - foreach ($taxRateList->getItems() as $taxRateData) { - $regionCode = $this->parseRegionFromTaxCode($taxRateData->getCode()); - if ($regionCode) { - /** @var \Magento\Directory\Model\Region $region */ - $region = $this->directoryRegionFactory->create(); - $region->loadByCode($regionCode, $taxRateData->getTaxCountryId()); - if ($taxRateData->getTaxPostcode() === null) { - $taxRateData->setTaxPostcode('*'); - } - $taxRateData->setTaxRegionId($region->getRegionId()); - $this->taxRateRepository->save($taxRateData); - } - } - } - $setup->endSetup(); - } - - /** - * Parse region code from tax code - * - * @param string $taxCode - * @return string - */ - private function parseRegionFromTaxCode($taxCode) - { - $result = ''; - $parts = explode('-', $taxCode, 3); - - if (isset($parts[1])) { - $result = $parts[1]; - } - - return $result; - } -} diff --git a/app/code/Magento/Tax/Test/Unit/Model/Calculation/RateRepositoryTest.php b/app/code/Magento/Tax/Test/Unit/Model/Calculation/RateRepositoryTest.php index db2053efd41f6..82a1f1803e903 100644 --- a/app/code/Magento/Tax/Test/Unit/Model/Calculation/RateRepositoryTest.php +++ b/app/code/Magento/Tax/Test/Unit/Model/Calculation/RateRepositoryTest.php @@ -391,7 +391,7 @@ public function testValidate() /** * @expectedException \Magento\Framework\Exception\InputException - * @expectedExceptionMessage percentage_rate is a required field. + * @expectedExceptionMessage "percentage_rate" is required. Enter and try again. */ public function testValidateWithNoRate() { @@ -429,7 +429,7 @@ public function testValidateWithNoRate() /** * @expectedException \Magento\Framework\Exception\InputException - * @expectedExceptionMessage percentage_rate is a required field. + * @expectedExceptionMessage "percentage_rate" is required. Enter and try again. */ public function testValidateWithWrongRate() { diff --git a/app/code/Magento/Tax/Test/Unit/Model/Calculation/RateTest.php b/app/code/Magento/Tax/Test/Unit/Model/Calculation/RateTest.php index 5a5abfd828d88..4edb0328b73c2 100644 --- a/app/code/Magento/Tax/Test/Unit/Model/Calculation/RateTest.php +++ b/app/code/Magento/Tax/Test/Unit/Model/Calculation/RateTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Tax\Test\Unit\Model\Calculation; class RateTest extends \PHPUnit\Framework\TestCase @@ -66,33 +67,77 @@ public function exceptionOfValidationDataProvider() { return [ 'fill all required fields 1' => [ - 'exceptionMessage' => 'Make sure all required information is valid.', - 'data' => ['zip_is_range' => true, 'zip_from' => '0111', 'zip_to' => '', - 'code' => '', 'tax_country_id' => '', 'rate' => '', 'tax_postcode' => '', ], + 'exceptionMessage' => 'The required information is invalid. Verify the information and try again.', + 'data' => [ + 'zip_is_range' => true, + 'zip_from' => '0111', + 'zip_to' => '', + 'code' => '', + 'tax_country_id' => '', + 'rate' => '', + 'tax_postcode' => '', + ], ], 'fill all required fields 2' => [ - 'exceptionMessage' => 'Make sure all required information is valid.', - 'data' => ['zip_is_range' => '', 'zip_from' => '', 'zip_to' => '', - 'code' => '', 'tax_country_id' => '', 'rate' => '0.2', 'tax_postcode' => '1234', ], ], + 'exceptionMessage' => 'The required information is invalid. Verify the information and try again.', + 'data' => [ + 'zip_is_range' => '', + 'zip_from' => '', + 'zip_to' => '', + 'code' => '', + 'tax_country_id' => '', + 'rate' => '0.2', + 'tax_postcode' => '1234', + ], + ], 'positive number' => [ - 'exceptionMessage' => 'The Rate Percent should be a positive number.', - 'data' => ['zip_is_range' => '', 'zip_from' => '', 'zip_to' => '', 'code' => 'code', - 'tax_country_id' => 'US', 'rate' => '-1', 'tax_postcode' => '1234', ], + 'exceptionMessage' => 'The Rate Percent is invalid. Enter a positive number and try again.', + 'data' => [ + 'zip_is_range' => '', + 'zip_from' => '', + 'zip_to' => '', + 'code' => 'code', + 'tax_country_id' => 'US', + 'rate' => '-1', + 'tax_postcode' => '1234', + ], ], 'zip code length' => [ - 'exceptionMessage' => 'Maximum zip code length is 9.', - 'data' => ['zip_is_range' => true, 'zip_from' => '1234567890', 'zip_to' => '1234', - 'code' => 'code', 'tax_country_id' => 'US', 'rate' => '1.1', 'tax_postcode' => '1234', ], + 'exceptionMessage' => 'The ZIP Code length is invalid. ' + . 'Verify that the length is nine characters or fewer and try again.', + 'data' => [ + 'zip_is_range' => true, + 'zip_from' => '1234567890', + 'zip_to' => '1234', + 'code' => 'code', + 'tax_country_id' => 'US', + 'rate' => '1.1', + 'tax_postcode' => '1234', + ], ], 'contain characters' => [ - 'exceptionMessage' => 'Use digits only for the zip code.', - 'data' => ['zip_is_range' => true, 'zip_from' => 'foo', 'zip_to' => '1234', 'code' => 'code', - 'tax_country_id' => 'US', 'rate' => '1.1', 'tax_postcode' => '1234', ], + 'exceptionMessage' => 'The ZIP Code is invalid. Use numbers only.', + 'data' => [ + 'zip_is_range' => true, + 'zip_from' => 'foo', + 'zip_to' => '1234', + 'code' => 'code', + 'tax_country_id' => 'US', + 'rate' => '1.1', + 'tax_postcode' => '1234', + ], ], 'equal or greater' => [ 'exceptionMessage' => 'Range To should be equal or greater than Range From.', - 'data' => ['zip_is_range' => true, 'zip_from' => '321', 'zip_to' => '123', 'code' => 'code', - 'tax_country_id' => 'US', 'rate' => '1.1', 'tax_postcode' => '1234', ], + 'data' => [ + 'zip_is_range' => true, + 'zip_from' => '321', + 'zip_to' => '123', + 'code' => 'code', + 'tax_country_id' => 'US', + 'rate' => '1.1', + 'tax_postcode' => '1234', + ], ], ]; } diff --git a/app/code/Magento/Tax/etc/module.xml b/app/code/Magento/Tax/etc/module.xml index a100b0ac01181..6233161192ab9 100644 --- a/app/code/Magento/Tax/etc/module.xml +++ b/app/code/Magento/Tax/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/Tax/view/adminhtml/templates/rule/edit.phtml b/app/code/Magento/Tax/view/adminhtml/templates/rule/edit.phtml index d16c4faeede28..fced077015f4e 100644 --- a/app/code/Magento/Tax/view/adminhtml/templates/rule/edit.phtml +++ b/app/code/Magento/Tax/view/adminhtml/templates/rule/edit.phtml @@ -111,6 +111,7 @@ require([ TaxRateEditableMultiselect.prototype.init = function () { var options = { + mselectContainer: '#tax_rate + section.mselect-list', toggleAddButton:false, addText: '', parse: null, diff --git a/app/code/Magento/TaxGraphQl/etc/module.xml b/app/code/Magento/TaxGraphQl/etc/module.xml index 9a7906f84d273..b8a7a3aaeb79c 100644 --- a/app/code/Magento/TaxGraphQl/etc/module.xml +++ b/app/code/Magento/TaxGraphQl/etc/module.xml @@ -6,5 +6,5 @@ */ --> - + diff --git a/app/code/Magento/TaxImportExport/etc/module.xml b/app/code/Magento/TaxImportExport/etc/module.xml index 192c817c29087..6df24c959d9c2 100644 --- a/app/code/Magento/TaxImportExport/etc/module.xml +++ b/app/code/Magento/TaxImportExport/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/Theme/Block/Html/Footer.php b/app/code/Magento/Theme/Block/Html/Footer.php index 4cd63462ec754..cdb350336f38f 100644 --- a/app/code/Magento/Theme/Block/Html/Footer.php +++ b/app/code/Magento/Theme/Block/Html/Footer.php @@ -57,7 +57,6 @@ protected function _construct() { $this->addData( [ - 'cache_lifetime' => false, 'cache_tags' => [\Magento\Store\Model\Store::CACHE_TAG, \Magento\Cms\Model\Block::CACHE_TAG], ] ); @@ -123,4 +122,14 @@ public function getIdentities() { return [\Magento\Store\Model\Store::CACHE_TAG, \Magento\Cms\Model\Block::CACHE_TAG]; } + + /** + * Get block cache life time + * + * @return int + */ + protected function getCacheLifetime() + { + return parent::getCacheLifetime() ?: 3600; + } } diff --git a/app/code/Magento/Theme/Model/Data/Design/ConfigFactory.php b/app/code/Magento/Theme/Model/Data/Design/ConfigFactory.php index 84aae4f7e51fe..e0b77a1657447 100644 --- a/app/code/Magento/Theme/Model/Data/Design/ConfigFactory.php +++ b/app/code/Magento/Theme/Model/Data/Design/ConfigFactory.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Theme\Model\Data\Design; use Magento\Framework\App\ScopeValidatorInterface; @@ -88,7 +89,7 @@ public function __construct( public function create($scope, $scopeId, array $data = []) { if (!$this->scopeValidator->isValidScope($scope, $scopeId)) { - throw new LocalizedException(__('Invalid scope or scope id')); + throw new LocalizedException(__('The scope or scope ID is invalid. Verify both and try again.')); } $designConfigData = $this->getDesignConfigData($scope, $scopeId); diff --git a/app/code/Magento/Theme/Model/Design/Config/FileUploader/FileProcessor.php b/app/code/Magento/Theme/Model/Design/Config/FileUploader/FileProcessor.php index 1e574d525b457..ecf5bcbea6dfc 100644 --- a/app/code/Magento/Theme/Model/Design/Config/FileUploader/FileProcessor.php +++ b/app/code/Magento/Theme/Model/Design/Config/FileUploader/FileProcessor.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Theme\Model\Design\Config\FileUploader; use Magento\Framework\Exception\LocalizedException; @@ -160,7 +161,7 @@ protected function getBackendModel($code) { $metadata = $this->metadataProvider->get(); if (!(isset($metadata[$code]) && isset($metadata[$code]['backend_model']))) { - throw new LocalizedException(__('Backend model is not specified for %1', $code)); + throw new LocalizedException(__('The backend model isn\'t specified for "%1".', $code)); } return $this->backendModelFactory->createByPath($metadata[$code]['path']); } diff --git a/app/code/Magento/Theme/Model/Design/Config/Validator.php b/app/code/Magento/Theme/Model/Design/Config/Validator.php index 8ac36a31d2ef5..9fed5be6201b4 100644 --- a/app/code/Magento/Theme/Model/Design/Config/Validator.php +++ b/app/code/Magento/Theme/Model/Design/Config/Validator.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Theme\Model\Design\Config; use \Magento\Framework\Exception\LocalizedException; @@ -74,8 +75,8 @@ public function validate(DesignConfigInterface $designConfig) if (isset($params['config_path']) && $params['config_path'] == $data['config_path']) { throw new LocalizedException( __( - "The %templateName contains an incorrect configuration. The template has " . - "a reference to itself. Either remove or change the reference.", + 'The "%templateName" template contains an incorrect configuration, with a reference ' + . 'to itself. Remove or change the reference, then try again.', ["templateName" => $name] ) ); diff --git a/app/code/Magento/Theme/Model/DesignConfigRepository.php b/app/code/Magento/Theme/Model/DesignConfigRepository.php index 9664a4eb6fa79..3a81b8c24b455 100644 --- a/app/code/Magento/Theme/Model/DesignConfigRepository.php +++ b/app/code/Magento/Theme/Model/DesignConfigRepository.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Theme\Model; use Magento\Framework\Indexer\IndexerRegistry; @@ -85,7 +86,9 @@ public function save(DesignConfigInterface $designConfig) if (!($designConfig->getExtensionAttributes() && $designConfig->getExtensionAttributes()->getDesignConfigData()) ) { - throw new LocalizedException(__('Can not save empty config')); + throw new LocalizedException( + __("The config can't be saved because it's empty. Complete the config and try again.") + ); } $this->getValidator()->validate($designConfig); @@ -105,7 +108,9 @@ public function delete(DesignConfigInterface $designConfig) if (!($designConfig->getExtensionAttributes() && $designConfig->getExtensionAttributes()->getDesignConfigData()) ) { - throw new LocalizedException(__('Can not save empty config')); + throw new LocalizedException( + __("The config can't be saved because it's empty. Complete the config and try again.") + ); } $this->configStorage->delete($designConfig); diff --git a/app/code/Magento/Theme/Setup/InstallData.php b/app/code/Magento/Theme/Setup/InstallData.php deleted file mode 100644 index 51d5cd23f6e94..0000000000000 --- a/app/code/Magento/Theme/Setup/InstallData.php +++ /dev/null @@ -1,41 +0,0 @@ -themeRegistration = $themeRegistration; - } - - /** - * {@inheritdoc} - */ - public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context) - { - $this->themeRegistration->register(); - } -} diff --git a/app/code/Magento/Theme/Setup/Patch/Data/ConvertSerializedData.php b/app/code/Magento/Theme/Setup/Patch/Data/ConvertSerializedData.php new file mode 100644 index 0000000000000..4c3f41faedbac --- /dev/null +++ b/app/code/Magento/Theme/Setup/Patch/Data/ConvertSerializedData.php @@ -0,0 +1,113 @@ +moduleDataSetup = $moduleDataSetup; + $this->fieldDataConverterFactory = $fieldDataConverterFactory; + $this->queryModifierFactory = $queryModifierFactory; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + $this->moduleDataSetup->getConnection()->startSetup(); + $this->convertSerializedData(); + $this->moduleDataSetup->getConnection()->endSetup(); + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return [ + RegisterThemes::class + ]; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.2'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } + + /** + * Convert native php serialized data to json. + */ + private function convertSerializedData() + { + $fieldDataConverter = $this->fieldDataConverterFactory->create(SerializedToJson::class); + $queryModifier = $this->queryModifierFactory->create( + 'in', + [ + 'values' => [ + 'path' => [ + 'design/theme/ua_regexp', + ] + ] + ] + ); + $fieldDataConverter->convert( + $this->moduleDataSetup->getConnection(), + $this->moduleDataSetup->getTable('core_config_data'), + 'config_id', + 'value', + $queryModifier + ); + } +} diff --git a/app/code/Magento/Theme/Setup/Patch/Data/RegisterThemes.php b/app/code/Magento/Theme/Setup/Patch/Data/RegisterThemes.php new file mode 100644 index 0000000000000..6c75e0b224bd8 --- /dev/null +++ b/app/code/Magento/Theme/Setup/Patch/Data/RegisterThemes.php @@ -0,0 +1,73 @@ +moduleDataSetup = $moduleDataSetup; + $this->themeRegistration = $themeRegistration; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + $this->themeRegistration->register(); + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return []; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.0'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } +} diff --git a/app/code/Magento/Theme/Setup/UpgradeData.php b/app/code/Magento/Theme/Setup/UpgradeData.php deleted file mode 100644 index ade0e9d3f6c39..0000000000000 --- a/app/code/Magento/Theme/Setup/UpgradeData.php +++ /dev/null @@ -1,85 +0,0 @@ -fieldDataConverterFactory = $fieldDataConverterFactory; - $this->queryModifierFactory = $queryModifierFactory; - } - - /** - * {@inheritdoc} - */ - public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context) - { - $setup->startSetup(); - if (version_compare($context->getVersion(), '2.0.2', '<')) { - $this->upgradeToVersionTwoZeroTwo($setup); - } - $setup->endSetup(); - } - - /** - * Upgrade to version 2.0.2, convert data for `value` field in `core_config_data table` - * from php-serialized to JSON format - * - * @param ModuleDataSetupInterface $setup - * @return void - */ - private function upgradeToVersionTwoZeroTwo(ModuleDataSetupInterface $setup) - { - $fieldDataConverter = $this->fieldDataConverterFactory->create(SerializedToJson::class); - $queryModifier = $this->queryModifierFactory->create( - 'in', - [ - 'values' => [ - 'path' => [ - 'design/theme/ua_regexp', - ] - ] - ] - ); - $fieldDataConverter->convert( - $setup->getConnection(), - $setup->getTable('core_config_data'), - 'config_id', - 'value', - $queryModifier - ); - } -} diff --git a/app/code/Magento/Theme/Test/Unit/Block/Html/FooterTest.php b/app/code/Magento/Theme/Test/Unit/Block/Html/FooterTest.php index 8451e9c5aee6a..52175cc669bbd 100644 --- a/app/code/Magento/Theme/Test/Unit/Block/Html/FooterTest.php +++ b/app/code/Magento/Theme/Test/Unit/Block/Html/FooterTest.php @@ -30,4 +30,18 @@ public function testGetIdentities() $this->block->getIdentities() ); } + + /** + * Check Footer block has cache lifetime. + * + * @throws \ReflectionException + * @return void + */ + public function testGetCacheLifetime() + { + $reflection = new \ReflectionClass($this->block); + $method = $reflection->getMethod('getCacheLifetime'); + $method->setAccessible(true); + $this->assertEquals(3600, $method->invoke($this->block)); + } } diff --git a/app/code/Magento/Theme/Test/Unit/Model/Config/ValidatorTest.php b/app/code/Magento/Theme/Test/Unit/Model/Config/ValidatorTest.php index 4dbc96d84d187..4a1a1982ea653 100644 --- a/app/code/Magento/Theme/Test/Unit/Model/Config/ValidatorTest.php +++ b/app/code/Magento/Theme/Test/Unit/Model/Config/ValidatorTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Theme\Test\Unit\Model\Config; /** @@ -39,7 +40,6 @@ protected function setUp() /** * @expectedException \Magento\Framework\Exception\LocalizedException - * @expectedExceptionMessage The email_header_template contains an incorrect configuration. The template has a */ public function testValidateHasRecursiveReference() { @@ -79,6 +79,11 @@ public function testValidateHasRecursiveReference() ); $this->model->validate($designConfigMock); + + $this->expectExceptionMessage( + 'The "email_header_template" template contains an incorrect configuration, with a reference to itself. ' + . 'Remove or change the reference, then try again.' + ); } public function testValidateNoRecursiveReference() diff --git a/app/code/Magento/Theme/Test/Unit/Model/DesignConfigRepositoryTest.php b/app/code/Magento/Theme/Test/Unit/Model/DesignConfigRepositoryTest.php index b8c72867e8cc2..7ed4f5f656822 100644 --- a/app/code/Magento/Theme/Test/Unit/Model/DesignConfigRepositoryTest.php +++ b/app/code/Magento/Theme/Test/Unit/Model/DesignConfigRepositoryTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Theme\Test\Unit\Model; use Magento\Theme\Model\Data\Design\Config; @@ -115,7 +116,7 @@ public function testSave() } /** - * @expectedExceptionMessage Can not save empty config + * @expectedExceptionMessage The config can't be saved because it's empty. Complete the config and try again. * @expectedException \Magento\Framework\Exception\LocalizedException */ public function testSaveWithoutConfig() diff --git a/app/code/Magento/Theme/etc/module.xml b/app/code/Magento/Theme/etc/module.xml index 8353ee2a46564..ace0df3b92ef8 100644 --- a/app/code/Magento/Theme/etc/module.xml +++ b/app/code/Magento/Theme/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/Theme/view/adminhtml/ui_component/design_config_form.xml b/app/code/Magento/Theme/view/adminhtml/ui_component/design_config_form.xml index ac734699e4d71..48adca3b1a12e 100644 --- a/app/code/Magento/Theme/view/adminhtml/ui_component/design_config_form.xml +++ b/app/code/Magento/Theme/view/adminhtml/ui_component/design_config_form.xml @@ -56,12 +56,12 @@ - Allowed file types: ico, png, gif, jpg, jpeg, apng. Not all browsers support all these formats! + Not all browsers support all these formats! - fileUploader + imageUploader - + jpg jpeg gif png ico apng 2097152 @@ -69,7 +69,7 @@ theme/design_config_fileUploader/save - + @@ -153,12 +153,11 @@ - Allowed file types: png, gif, jpg, jpeg. - fileUploader + imageUploader - + jpg jpeg gif png 2097152 @@ -166,7 +165,7 @@ theme/design_config_fileUploader/save - + diff --git a/app/code/Magento/Tinymce3/etc/module.xml b/app/code/Magento/Tinymce3/etc/module.xml index add50fbd609e1..5180aa2ed4cb4 100644 --- a/app/code/Magento/Tinymce3/etc/module.xml +++ b/app/code/Magento/Tinymce3/etc/module.xml @@ -6,5 +6,5 @@ */ --> - + diff --git a/app/code/Magento/Translation/etc/module.xml b/app/code/Magento/Translation/etc/module.xml index f45ddeb28a8ec..23ebfe1b0751d 100644 --- a/app/code/Magento/Translation/etc/module.xml +++ b/app/code/Magento/Translation/etc/module.xml @@ -6,6 +6,6 @@ */ --> - + diff --git a/app/code/Magento/Ui/Component/Form/Element/DataType/Media/Image.php b/app/code/Magento/Ui/Component/Form/Element/DataType/Media/Image.php new file mode 100644 index 0000000000000..7b923bdbf84bf --- /dev/null +++ b/app/code/Magento/Ui/Component/Form/Element/DataType/Media/Image.php @@ -0,0 +1,83 @@ +storeManager = $storeManager; + $this->fileSize = $fileSize; + parent::__construct($context, $components, $data); + } + + /** + * {@inheritdoc} + */ + public function getComponentName() + { + return static::NAME; + } + + /** + * {@inheritdoc} + */ + public function prepare() + { + // dynamically set max file size based on php ini config if not present in XML + $maxFileSize = $this->getConfiguration()['maxFileSize'] ?? $this->fileSize->getMaxFileSize(); + + $data = array_replace_recursive( + $this->getData(), + [ + 'config' => [ + 'maxFileSize' => $maxFileSize, + 'mediaGallery' => [ + 'openDialogUrl' => $this->getContext()->getUrl('cms/wysiwyg_images/index'), + 'openDialogTitle' => $this->getConfiguration()['openDialogTitle'] ?? __('Insert Images...'), + 'storeId' => $this->storeManager->getStore()->getId(), + ], + ], + ] + ); + + $this->setData($data); + parent::prepare(); + } +} diff --git a/app/code/Magento/Ui/Component/Form/Field.php b/app/code/Magento/Ui/Component/Form/Field.php index 48ca012f56953..e7a627743b63a 100644 --- a/app/code/Magento/Ui/Component/Form/Field.php +++ b/app/code/Magento/Ui/Component/Form/Field.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Ui\Component\Form; use Magento\Framework\Exception\LocalizedException; @@ -73,7 +74,7 @@ public function prepare() $formElement = $this->getData('config/formElement'); if (null === $formElement) { throw new LocalizedException(__( - 'The configuration parameter "formElement" is a required for "%1" field.', + 'The "formElement" configuration parameter is required for the "%1" field.', $this->getName() )); } diff --git a/app/code/Magento/Ui/Component/MassAction/Filter.php b/app/code/Magento/Ui/Component/MassAction/Filter.php index 6b089233c210a..6877303f5c491 100644 --- a/app/code/Magento/Ui/Component/MassAction/Filter.php +++ b/app/code/Magento/Ui/Component/MassAction/Filter.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Ui\Component\MassAction; use Magento\Framework\Api\FilterBuilder; @@ -95,7 +96,7 @@ public function getCollection(AbstractDb $collection) if ('false' !== $excluded) { if (!$isExcludedIdsValid && !$isSelectedIdsValid) { - throw new LocalizedException(__('Please select item(s).')); + throw new LocalizedException(__('An item needs to be selected. Select and try again.')); } } /** @var \Magento\Customer\Model\ResourceModel\Customer\Collection $collection */ @@ -162,7 +163,7 @@ protected function applySelection(AbstractDb $collection) } elseif (is_array($selected) && !empty($selected)) { $collection->addFieldToFilter($collection->getIdFieldName(), ['in' => $selected]); } else { - throw new LocalizedException(__('Please select item(s).')); + throw new LocalizedException(__('An item needs to be selected. Select and try again.')); } } catch (\Exception $e) { throw new LocalizedException(__($e->getMessage())); diff --git a/app/code/Magento/Ui/Config/Reader.php b/app/code/Magento/Ui/Config/Reader.php index 8ff779f63d6e1..f7a781d103c05 100644 --- a/app/code/Magento/Ui/Config/Reader.php +++ b/app/code/Magento/Ui/Config/Reader.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Ui\Config; use Magento\Framework\Config\ConverterInterface as ConfigConverter; @@ -125,7 +126,12 @@ private function readFiles($fileList) ); $output = array_replace_recursive($output, $this->converter->convert($configMerger->getDom())); } catch (ValidationException $e) { - throw new LocalizedException(new Phrase("Invalid XML in file %1:\n%2", [$key, $e->getMessage()])); + throw new LocalizedException( + new Phrase( + 'The XML in file "%1" is invalid:' . "\n%2\nVerify the XML and try again.", + [$key, $e->getMessage()] + ) + ); } } diff --git a/app/code/Magento/Ui/Config/Reader/Definition.php b/app/code/Magento/Ui/Config/Reader/Definition.php index d4a53c584308e..782a75187190b 100644 --- a/app/code/Magento/Ui/Config/Reader/Definition.php +++ b/app/code/Magento/Ui/Config/Reader/Definition.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Ui\Config\Reader; use Magento\Framework\Config\Dom\ValidationException; @@ -53,7 +54,10 @@ private function readFiles($fileList) } } catch (ValidationException $e) { throw new LocalizedException( - new Phrase("Invalid XML in file %1:\n%2", [$key, $e->getMessage()]) + new Phrase( + 'The XML in file "%1" is invalid.' . "\n%2\nVerify the XML and try again.", + [$key, $e->getMessage()] + ) ); } } diff --git a/app/code/Magento/Ui/DataProvider/Modifier/Pool.php b/app/code/Magento/Ui/DataProvider/Modifier/Pool.php index e8ac4d9b362ec..34a24499834d2 100644 --- a/app/code/Magento/Ui/DataProvider/Modifier/Pool.php +++ b/app/code/Magento/Ui/DataProvider/Modifier/Pool.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Ui\DataProvider\Modifier; use Magento\Framework\Exception\LocalizedException; @@ -63,11 +64,13 @@ public function getModifiersInstances() foreach ($this->modifiers as $modifier) { if (empty($modifier['class'])) { - throw new LocalizedException(__('Parameter "class" must be present.')); + throw new LocalizedException(__('The parameter "class" is missing. Set the "class" and try again.')); } if (empty($modifier['sortOrder'])) { - throw new LocalizedException(__('Parameter "sortOrder" must be present.')); + throw new LocalizedException( + __('The parameter "sortOrder" is missing. Set the "sortOrder" and try again.') + ); } $this->modifiersInstances[$modifier['class']] = $this->factory->create($modifier['class']); diff --git a/app/code/Magento/Ui/Model/Manager.php b/app/code/Magento/Ui/Model/Manager.php index 6dca4632fe7fc..e3c56418c8425 100644 --- a/app/code/Magento/Ui/Model/Manager.php +++ b/app/code/Magento/Ui/Model/Manager.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Ui\Model; use ArrayObject; @@ -165,7 +166,10 @@ public function prepareData($name) { if ($name === null || $this->hasData($name)) { throw new LocalizedException( - new \Magento\Framework\Phrase("Invalid UI Component element name: '%1'", [$name]) + new \Magento\Framework\Phrase( + 'The "%1" UI component element name is invalid. Verify the name and try again.', + [$name] + ) ); } $this->componentsPool = $this->arrayObjectFactory->create(); diff --git a/app/code/Magento/Ui/Model/ResourceModel/BookmarkRepository.php b/app/code/Magento/Ui/Model/ResourceModel/BookmarkRepository.php index 1b03b7c402680..3e738baa404c8 100644 --- a/app/code/Magento/Ui/Model/ResourceModel/BookmarkRepository.php +++ b/app/code/Magento/Ui/Model/ResourceModel/BookmarkRepository.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Ui\Model\ResourceModel; use Magento\Framework\Api\SearchCriteria\CollectionProcessorInterface; @@ -91,7 +92,9 @@ public function getById($bookmarkId) $bookmark = $this->bookmarkFactory->create(); $this->bookmarkResourceModel->load($bookmark, $bookmarkId); if (!$bookmark->getId()) { - throw new NoSuchEntityException(__('Bookmark with id "%1" does not exist.', $bookmarkId)); + throw new NoSuchEntityException( + __('The bookmark with "%1" ID doesn\'t exist. Verify your information and try again.', $bookmarkId) + ); } return $bookmark; } diff --git a/app/code/Magento/Ui/Test/Unit/Component/Form/FieldTest.php b/app/code/Magento/Ui/Test/Unit/Component/Form/FieldTest.php index 02db643c321d8..d794208f95778 100644 --- a/app/code/Magento/Ui/Test/Unit/Component/Form/FieldTest.php +++ b/app/code/Magento/Ui/Test/Unit/Component/Form/FieldTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Ui\Test\Unit\Component\Form; use Magento\Ui\Component\Form\Field; @@ -169,7 +170,7 @@ protected function getComponentsMock() * @return void * * @expectedException \Magento\Framework\Exception\LocalizedException - * @expectedExceptionMessage The configuration parameter "formElement" is a required for "test-name" field. + * @expectedExceptionMessage The "formElement" configuration parameter is required for the "test-name" field. */ public function testPrepareException() { diff --git a/app/code/Magento/Ui/Test/Unit/DataProvider/Modifier/PoolTest.php b/app/code/Magento/Ui/Test/Unit/DataProvider/Modifier/PoolTest.php index e411220596028..23e65d1f4c1cc 100644 --- a/app/code/Magento/Ui/Test/Unit/DataProvider/Modifier/PoolTest.php +++ b/app/code/Magento/Ui/Test/Unit/DataProvider/Modifier/PoolTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Ui\Test\Unit\DataProvider\Modifier; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; @@ -100,7 +101,7 @@ public function testWithFewmodifiers() /** * @expectedException \Magento\Framework\Exception\LocalizedException - * @expectedExceptionMessage Parameter "sortOrder" must be present. + * @expectedExceptionMessage The parameter "sortOrder" is missing. Set the "sortOrder" and try again. */ public function testWithSortOrderException() { @@ -119,7 +120,7 @@ public function testWithSortOrderException() /** * @expectedException \Magento\Framework\Exception\LocalizedException - * @expectedExceptionMessage Parameter "class" must be present. + * @expectedExceptionMessage The parameter "class" is missing. Set the "class" and try again. */ public function testWithClassException() { diff --git a/app/code/Magento/Ui/Test/Unit/Model/ManagerTest.php b/app/code/Magento/Ui/Test/Unit/Model/ManagerTest.php index 96468b63314b4..414f52037542d 100644 --- a/app/code/Magento/Ui/Test/Unit/Model/ManagerTest.php +++ b/app/code/Magento/Ui/Test/Unit/Model/ManagerTest.php @@ -154,7 +154,7 @@ public function testPrepareDataWithoutName() { $this->expectException( \Magento\Framework\Exception\LocalizedException::class, - __("Invalid UI Component element name: ''") + __('The "" UI component element name is invalid. Verify the name and try again.') ); $this->manager->prepareData(null); } diff --git a/app/code/Magento/Ui/Test/Unit/Model/ResourceModel/BookmarkRepositoryTest.php b/app/code/Magento/Ui/Test/Unit/Model/ResourceModel/BookmarkRepositoryTest.php index 00a88437c8cb1..5ba14d15f6b06 100644 --- a/app/code/Magento/Ui/Test/Unit/Model/ResourceModel/BookmarkRepositoryTest.php +++ b/app/code/Magento/Ui/Test/Unit/Model/ResourceModel/BookmarkRepositoryTest.php @@ -123,7 +123,7 @@ public function testGetByIdWithException() ->willReturn($this->bookmarkMock); $this->expectException( \Magento\Framework\Exception\NoSuchEntityException::class, - __('Bookmark with id "%1" does not exist.', $notExistsBookmarkId) + __('The bookmark with "%1" ID doesn\'t exist. Verify your information and try again.', $notExistsBookmarkId) ); $this->bookmarkRepository->getById($notExistsBookmarkId); } diff --git a/app/code/Magento/Ui/composer.json b/app/code/Magento/Ui/composer.json index e9ace8bb159c0..2edcc3507970d 100644 --- a/app/code/Magento/Ui/composer.json +++ b/app/code/Magento/Ui/composer.json @@ -10,6 +10,7 @@ "magento/module-authorization": "100.3.*", "magento/module-backend": "100.3.*", "magento/module-eav": "100.3.*", + "magento/module-store": "100.3.*", "magento/module-user": "100.3.*" }, "suggest": { diff --git a/app/code/Magento/Ui/etc/module.xml b/app/code/Magento/Ui/etc/module.xml index 20bd9de1567ee..967c33ae1648c 100644 --- a/app/code/Magento/Ui/etc/module.xml +++ b/app/code/Magento/Ui/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/Ui/etc/ui_components.xsd b/app/code/Magento/Ui/etc/ui_components.xsd index 9a8ede09d59e0..3d3c0d11bb454 100644 --- a/app/code/Magento/Ui/etc/ui_components.xsd +++ b/app/code/Magento/Ui/etc/ui_components.xsd @@ -36,6 +36,7 @@ + diff --git a/app/code/Magento/Ui/etc/ui_configuration.xsd b/app/code/Magento/Ui/etc/ui_configuration.xsd index 5deba03a03b3f..5783323b53188 100644 --- a/app/code/Magento/Ui/etc/ui_configuration.xsd +++ b/app/code/Magento/Ui/etc/ui_configuration.xsd @@ -34,6 +34,7 @@ + @@ -180,6 +181,7 @@ + @@ -615,6 +617,14 @@ + + + + Adds image gallery functionality alongside file uploader functionality. + See fileUploader component documentation for more information. + + + diff --git a/app/code/Magento/Ui/etc/ui_definition.xsd b/app/code/Magento/Ui/etc/ui_definition.xsd index d22605398571d..d1787309d051e 100644 --- a/app/code/Magento/Ui/etc/ui_definition.xsd +++ b/app/code/Magento/Ui/etc/ui_definition.xsd @@ -53,6 +53,7 @@ + diff --git a/app/code/Magento/Ui/view/base/ui_component/etc/definition.map.xml b/app/code/Magento/Ui/view/base/ui_component/etc/definition.map.xml index 06c9312468f89..713cf2217d168 100644 --- a/app/code/Magento/Ui/view/base/ui_component/etc/definition.map.xml +++ b/app/code/Magento/Ui/view/base/ui_component/etc/definition.map.xml @@ -359,6 +359,9 @@ formElements/*[name(.)=../../@formElement]/settings/allowedExtensions + + formElements/*[name(.)=../../@formElement]/settings/openDialogTitle + formElements/*[name(.)=../../@formElement]/settings/customEntry @@ -419,6 +422,15 @@ + + + + + settings/openDialogTitle + + + + diff --git a/app/code/Magento/Ui/view/base/ui_component/etc/definition.xml b/app/code/Magento/Ui/view/base/ui_component/etc/definition.xml index 0f708e4d138dd..88997f4e4cba7 100755 --- a/app/code/Magento/Ui/view/base/ui_component/etc/definition.xml +++ b/app/code/Magento/Ui/view/base/ui_component/etc/definition.xml @@ -144,6 +144,7 @@ + diff --git a/app/code/Magento/Ui/view/base/ui_component/etc/definition/imageUploader.xsd b/app/code/Magento/Ui/view/base/ui_component/etc/definition/imageUploader.xsd new file mode 100644 index 0000000000000..b78defa668a0e --- /dev/null +++ b/app/code/Magento/Ui/view/base/ui_component/etc/definition/imageUploader.xsd @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + Defines the title that appears when opening media browser dialog slideout. + + + + + + diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/file-uploader.js b/app/code/Magento/Ui/view/base/web/js/form/element/file-uploader.js index 4641ae96c9ece..bbac27141ba22 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/element/file-uploader.js +++ b/app/code/Magento/Ui/view/base/web/js/form/element/file-uploader.js @@ -119,7 +119,7 @@ define([ * Adds provided file to the files list. * * @param {Object} file - * @returns {FileUploder} Chainable. + * @returns {FileUploader} Chainable. */ addFile: function (file) { file = this.processFile(file); diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/image-uploader.js b/app/code/Magento/Ui/view/base/web/js/form/element/image-uploader.js new file mode 100644 index 0000000000000..dabb9783abefd --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/js/form/element/image-uploader.js @@ -0,0 +1,99 @@ +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +define([ + 'jquery', + 'underscore', + 'mageUtils', + 'Magento_Ui/js/modal/alert', + 'Magento_Ui/js/lib/validation/validator', + 'Magento_Ui/js/form/element/file-uploader', + 'mage/adminhtml/browser' +], function ($, _, utils, uiAlert, validator, Element, browser) { + 'use strict'; + + return Element.extend({ + + /** + * Assign uid for media gallery + * + * @return {ImageUploader} Chainable. + */ + initConfig: function () { + var mediaGalleryUid = utils.uniqueid(); + + this._super(); + + _.extend(this, { + mediaGalleryUid: mediaGalleryUid + }); + + return this; + }, + + /** + * Add file event callback triggered from media gallery + * + * @param {ImageUploader} imageUploader - UI Class + * @param {Event} e + */ + addFileFromMediaGallery: function (imageUploader, e) { + var $buttonEl = $(e.target), + fileSize = $buttonEl.data('size'), + fileMimeType = $buttonEl.data('mime-type'), + filePathname = $buttonEl.val(), + fileBasename = filePathname.split('/').pop(); + + this.addFile({ + type: fileMimeType, + name: fileBasename, + size: fileSize, + url: filePathname + }); + }, + + /** + * Open the media browser dialog using the + * + * @param {ImageUploader} imageUploader - UI Class + * @param {Event} e + */ + openMediaBrowserDialog: function (imageUploader, e) { + var $buttonEl = $(e.target), + openDialogUrl = this.mediaGallery.openDialogUrl + + 'target_element_id/' + $buttonEl.attr('id') + + '/store/' + this.mediaGallery.storeId + + '/type/image/use_storage_root/1?isAjax=true'; + + browser.openDialog(openDialogUrl, null, null, this.mediaGallery.openDialogTitle); + }, + + /** + * Trigger native browser file upload UI via clicking on 'Upload' button + * + * @param {ImageUploader} imageUploader - UI Class + * @param {Event} e + */ + triggerImageUpload: function (imageUploader, e) { + $(e.target).closest('.file-uploader').find('input[type="file"]').click(); + }, + + /** + * Get list of file extensions allowed in comma delimited format + * + * @return {String} + */ + getAllowedFileExtensionsInCommaDelimitedFormat: function () { + var allowedExtensions = this.allowedExtensions.toUpperCase().split(' '); + + // if jpg and jpeg in allowed extensions, remove jpeg from list + if (allowedExtensions.indexOf('JPG') !== -1 && allowedExtensions.indexOf('JPEG') !== -1) { + allowedExtensions.splice(allowedExtensions.indexOf('JPEG'), 1); + } + + return allowedExtensions.join(', '); + } + }); +}); diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/wysiwyg.js b/app/code/Magento/Ui/view/base/web/js/form/element/wysiwyg.js index 262ded91df548..8ece6aad7f820 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/element/wysiwyg.js +++ b/app/code/Magento/Ui/view/base/web/js/form/element/wysiwyg.js @@ -22,10 +22,12 @@ define([ value: '', $wysiwygEditorButton: '', links: { - value: '${ $.provider }:${ $.dataScope }' + value: '${ $.provider }:${ $.dataScope }', + stageActive: false }, template: 'ui/form/field', elementTmpl: 'ui/form/element/wysiwyg', + stageActive: false, content: '', showSpinner: false, loading: false, diff --git a/app/code/Magento/Ui/view/base/web/templates/form/element/uploader/image.html b/app/code/Magento/Ui/view/base/web/templates/form/element/uploader/image.html new file mode 100644 index 0000000000000..8ae85b567fc5a --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/templates/form/element/uploader/image.html @@ -0,0 +1,53 @@ + +
    + + +
    +
    +
    + +
    + + + +
    + +
    + +
    +
    diff --git a/app/code/Magento/Ups/etc/module.xml b/app/code/Magento/Ups/etc/module.xml index b0500b9aa4f90..cc4599627ffb9 100644 --- a/app/code/Magento/Ups/etc/module.xml +++ b/app/code/Magento/Ups/etc/module.xml @@ -6,6 +6,6 @@ */ --> - + diff --git a/app/code/Magento/UrlRewrite/Controller/Adminhtml/Url/Rewrite/Save.php b/app/code/Magento/UrlRewrite/Controller/Adminhtml/Url/Rewrite/Save.php index 27b2d5088a1c3..6325fe162d9e7 100644 --- a/app/code/Magento/UrlRewrite/Controller/Adminhtml/Url/Rewrite/Save.php +++ b/app/code/Magento/UrlRewrite/Controller/Adminhtml/Url/Rewrite/Save.php @@ -4,6 +4,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\UrlRewrite\Controller\Adminhtml\Url\Rewrite; use Magento\Framework\Exception\LocalizedException; @@ -96,8 +97,8 @@ protected function getTargetPath($model) $rewrite = $this->urlFinder->findOneByData($data); if (!$rewrite) { $message = $model->getEntityType() === self::ENTITY_TYPE_PRODUCT - ? __('The product you chose is not associated with the selected store or category.') - : __('The category you chose is not associated with the selected store.'); + ? __("The selected product isn't associated with the selected store or category.") + : __("The selected category isn't associated with the selected store."); throw new LocalizedException($message); } $targetPath = $rewrite->getRequestPath(); @@ -174,7 +175,10 @@ public function execute() $this->messageManager->addError($e->getMessage()); $session->setUrlRewriteData($data); } catch (\Exception $e) { - $this->messageManager->addException($e, __('Something went wrong while saving URL Rewrite.')); + $this->messageManager->addException( + $e, + __('An error occurred while saving the URL rewrite. Please try to save again.') + ); $session->setUrlRewriteData($data); } } diff --git a/app/code/Magento/UrlRewrite/Setup/Patch/Data/ConvertSerializedDataToJson.php b/app/code/Magento/UrlRewrite/Setup/Patch/Data/ConvertSerializedDataToJson.php new file mode 100644 index 0000000000000..6725aa1f82670 --- /dev/null +++ b/app/code/Magento/UrlRewrite/Setup/Patch/Data/ConvertSerializedDataToJson.php @@ -0,0 +1,91 @@ +moduleDataSetup = $moduleDataSetup; + $this->fieldDataConverterFactory = $fieldDataConverterFactory; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + $this->moduleDataSetup->getConnection()->startSetup(); + $this->convertSerializedDataToJson(); + $this->moduleDataSetup->getConnection()->endSetup(); + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return []; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.1'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } + + /** + * Convert native php serialized data to json. + */ + private function convertSerializedDataToJson() + { + $fieldDataConverter = $this->fieldDataConverterFactory->create(SerializedToJson::class); + $fieldDataConverter->convert( + $this->moduleDataSetup->getConnection(), + $this->moduleDataSetup->getTable('url_rewrite'), + 'url_rewrite_id', + 'metadata' + ); + } +} diff --git a/app/code/Magento/UrlRewrite/Setup/UpgradeData.php b/app/code/Magento/UrlRewrite/Setup/UpgradeData.php deleted file mode 100644 index 7b9bc2020e60c..0000000000000 --- a/app/code/Magento/UrlRewrite/Setup/UpgradeData.php +++ /dev/null @@ -1,63 +0,0 @@ -fieldDataConverterFactory = $fieldDataConverterFactory; - } - - /** - * @inheritdoc - */ - public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context) - { - $setup->startSetup(); - - if (version_compare($context->getVersion(), '2.0.1', '<')) { - $this->convertSerializedDataToJson($setup); - } - - $setup->endSetup(); - } - - /** - * Convert metadata from serialized to JSON format: - * - * @param ModuleDataSetupInterface $setup - * - * @return void - */ - public function convertSerializedDataToJson($setup) - { - $fieldDataConverter = $this->fieldDataConverterFactory->create(SerializedToJson::class); - $fieldDataConverter->convert( - $setup->getConnection(), - $setup->getTable('url_rewrite'), - 'url_rewrite_id', - 'metadata' - ); - } -} diff --git a/app/code/Magento/UrlRewrite/etc/module.xml b/app/code/Magento/UrlRewrite/etc/module.xml index b8845ad04fb5f..eb314b71bc377 100644 --- a/app/code/Magento/UrlRewrite/etc/module.xml +++ b/app/code/Magento/UrlRewrite/etc/module.xml @@ -6,6 +6,6 @@ */ --> - + diff --git a/app/code/Magento/UrlRewriteGraphQl/etc/module.xml b/app/code/Magento/UrlRewriteGraphQl/etc/module.xml index 17b04648630f7..689a792def0dc 100644 --- a/app/code/Magento/UrlRewriteGraphQl/etc/module.xml +++ b/app/code/Magento/UrlRewriteGraphQl/etc/module.xml @@ -6,5 +6,5 @@ */ --> - + diff --git a/app/code/Magento/User/Controller/Adminhtml/Auth.php b/app/code/Magento/User/Controller/Adminhtml/Auth.php index aaa2681a50790..173fdcc764f6f 100644 --- a/app/code/Magento/User/Controller/Adminhtml/Auth.php +++ b/app/code/Magento/User/Controller/Adminhtml/Auth.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\User\Controller\Adminhtml; use Magento\Framework\Encryption\Helper\Security; @@ -49,7 +50,9 @@ protected function _validateResetPasswordLinkToken($userId, $resetPasswordToken) $resetPasswordToken ) || empty($resetPasswordToken) || empty($userId) || $userId < 0 ) { - throw new \Magento\Framework\Exception\LocalizedException(__('Please correct the password reset token.')); + throw new \Magento\Framework\Exception\LocalizedException( + __('The password reset token is incorrect. Verify the token and try again.') + ); } /** @var $user \Magento\User\Model\User */ diff --git a/app/code/Magento/User/Controller/Adminhtml/User/Delete.php b/app/code/Magento/User/Controller/Adminhtml/User/Delete.php index e5fb1590a8cc1..4e7d18774c2f9 100644 --- a/app/code/Magento/User/Controller/Adminhtml/User/Delete.php +++ b/app/code/Magento/User/Controller/Adminhtml/User/Delete.php @@ -4,6 +4,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\User\Controller\Adminhtml\User; use Magento\User\Block\User\Edit\Tab\Main as UserEdit; @@ -29,7 +30,9 @@ public function execute() try { $currentUserPassword = (string)$this->getRequest()->getPost(UserEdit::CURRENT_USER_PASSWORD_FIELD); if (empty($currentUserPassword)) { - throw new AuthenticationException(__('You have entered an invalid password for current user.')); + throw new AuthenticationException( + __('The password entered for the current user is invalid. Verify the password and try again.') + ); } $currentUser->performIdentityCheck($currentUserPassword); /** @var \Magento\User\Model\User $model */ diff --git a/app/code/Magento/User/Controller/Adminhtml/User/Role/SaveRole.php b/app/code/Magento/User/Controller/Adminhtml/User/Role/SaveRole.php index c21e0ba7845a7..9dfe34e435385 100644 --- a/app/code/Magento/User/Controller/Adminhtml/User/Role/SaveRole.php +++ b/app/code/Magento/User/Controller/Adminhtml/User/Role/SaveRole.php @@ -4,6 +4,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\User\Controller\Adminhtml\User\Role; use Magento\Authorization\Model\Acl\Role\Group as RoleGroup; @@ -117,7 +118,9 @@ public function execute() ); return $resultRedirect->setPath('*'); } catch (\Magento\Framework\Exception\AuthenticationException $e) { - $this->messageManager->addError(__('You have entered an invalid password for current user.')); + $this->messageManager->addError( + __('The password entered for the current user is invalid. Verify the password and try again.') + ); return $this->saveDataToSessionAndRedirect($role, $this->getRequest()->getPostValue(), $resultRedirect); } catch (\Magento\Framework\Exception\LocalizedException $e) { $this->messageManager->addError($e->getMessage()); diff --git a/app/code/Magento/User/Controller/Adminhtml/User/Save.php b/app/code/Magento/User/Controller/Adminhtml/User/Save.php index 3b37ce10c0151..4b984b761c1fe 100644 --- a/app/code/Magento/User/Controller/Adminhtml/User/Save.php +++ b/app/code/Magento/User/Controller/Adminhtml/User/Save.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\User\Controller\Adminhtml\User; use Magento\Framework\Exception\AuthenticationException; @@ -79,7 +80,9 @@ public function execute() && !empty($data[$currentUserPasswordField]) && is_string($data[$currentUserPasswordField]); try { if (!($isCurrentUserPasswordValid)) { - throw new AuthenticationException(__('You have entered an invalid password for current user.')); + throw new AuthenticationException( + __('The password entered for the current user is invalid. Verify the password and try again.') + ); } $currentUser->performIdentityCheck($data[$currentUserPasswordField]); $model->save(); @@ -96,7 +99,9 @@ public function execute() ); $this->_redirect('adminhtml/*/'); } catch (\Magento\Framework\Exception\AuthenticationException $e) { - $this->messageManager->addError(__('You have entered an invalid password for current user.')); + $this->messageManager->addError( + __('The password entered for the current user is invalid. Verify the password and try again.') + ); $this->redirectToEdit($model, $data); } catch (\Magento\Framework\Validator\Exception $e) { $messages = $e->getMessages(); diff --git a/app/code/Magento/User/Model/User.php b/app/code/Magento/User/Model/User.php index 2a7d43008f2ad..a5dd6ac2e7813 100644 --- a/app/code/Magento/User/Model/User.php +++ b/app/code/Magento/User/Model/User.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\User\Model; use Magento\Backend\App\Area\FrontNameResolver; @@ -580,11 +581,14 @@ public function verifyIdentity($password) if ($this->_encryptor->validateHash($password, $this->getPassword())) { if ($this->getIsActive() != '1') { throw new AuthenticationException( - __('You did not sign in correctly or your account is temporarily disabled.') + __( + 'The account sign-in was incorrect or your account is disabled temporarily. ' + . 'Please wait and try again later.' + ) ); } if (!$this->hasAssigned2Role($this->getId())) { - throw new AuthenticationException(__('You need more permissions to access this.')); + throw new AuthenticationException(__('More permissions are needed to access this.')); } $result = true; } @@ -669,7 +673,9 @@ protected function _getEncodedPassword($password) public function changeResetPasswordLinkToken($newToken) { if (!is_string($newToken) || empty($newToken)) { - throw new \Magento\Framework\Exception\LocalizedException(__('Please correct the password reset token.')); + throw new \Magento\Framework\Exception\LocalizedException( + __('The password reset token is incorrect. Verify the token and try again.') + ); } $this->setRpToken($newToken); $this->setRpTokenCreatedAt((new \DateTime())->format(\Magento\Framework\Stdlib\DateTime::DATETIME_PHP_FORMAT)); @@ -903,13 +909,13 @@ public function performIdentityCheck($passwordString) $clonedUser->reload(); if ($clonedUser->getLockExpires()) { throw new \Magento\Framework\Exception\State\UserLockedException( - __('Your account is temporarily disabled.') + __('Your account is temporarily disabled. Please try again later.') ); } if (!$isCheckSuccessful) { throw new \Magento\Framework\Exception\AuthenticationException( - __('You have entered an invalid password for current user.') + __('The password entered for the current user is invalid. Verify the password and try again.') ); } diff --git a/app/code/Magento/User/Model/UserValidationRules.php b/app/code/Magento/User/Model/UserValidationRules.php index b878d60356300..e40c785749e03 100644 --- a/app/code/Magento/User/Model/UserValidationRules.php +++ b/app/code/Magento/User/Model/UserValidationRules.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\User\Model; use Magento\Framework\Validator\EmailAddress; @@ -32,13 +33,25 @@ class UserValidationRules public function addUserInfoRules(\Magento\Framework\Validator\DataObject $validator) { $userNameNotEmpty = new NotEmpty(); - $userNameNotEmpty->setMessage(__('User Name is a required field.'), \Zend_Validate_NotEmpty::IS_EMPTY); + $userNameNotEmpty->setMessage( + __('"User Name" is required. Enter and try again.'), + \Zend_Validate_NotEmpty::IS_EMPTY + ); $firstNameNotEmpty = new NotEmpty(); - $firstNameNotEmpty->setMessage(__('First Name is a required field.'), \Zend_Validate_NotEmpty::IS_EMPTY); + $firstNameNotEmpty->setMessage( + __('"First Name" is required. Enter and try again.'), + \Zend_Validate_NotEmpty::IS_EMPTY + ); $lastNameNotEmpty = new NotEmpty(); - $lastNameNotEmpty->setMessage(__('Last Name is a required field.'), \Zend_Validate_NotEmpty::IS_EMPTY); + $lastNameNotEmpty->setMessage( + __('"Last Name" is required. Enter and try again.'), + \Zend_Validate_NotEmpty::IS_EMPTY + ); $emailValidity = new EmailAddress(); - $emailValidity->setMessage(__('Please enter a valid email.'), \Zend_Validate_EmailAddress::INVALID); + $emailValidity->setMessage( + __('Please enter a valid email.'), + \Zend_Validate_EmailAddress::INVALID + ); /** @var $validator \Magento\Framework\Validator\DataObject */ $validator->addRule( diff --git a/app/code/Magento/User/Observer/Backend/AuthObserver.php b/app/code/Magento/User/Observer/Backend/AuthObserver.php index bc5d6af615f13..6021302a5aeb7 100644 --- a/app/code/Magento/User/Observer/Backend/AuthObserver.php +++ b/app/code/Magento/User/Observer/Backend/AuthObserver.php @@ -125,7 +125,10 @@ public function execute(EventObserver $observer) $lockExpires = new \DateTime($lockExpires); if ($lockExpires > new \DateTime()) { throw new UserLockedException( - __('You did not sign in correctly or your account is temporarily disabled.') + __( + 'The account sign-in was incorrect or your account is disabled temporarily. ' + . 'Please wait and try again later.' + ) ); } } diff --git a/app/code/Magento/User/Setup/Patch/Data/UpgradePasswordHashes.php b/app/code/Magento/User/Setup/Patch/Data/UpgradePasswordHashes.php new file mode 100644 index 0000000000000..82e230d3c1a80 --- /dev/null +++ b/app/code/Magento/User/Setup/Patch/Data/UpgradePasswordHashes.php @@ -0,0 +1,98 @@ +moduleDataSetup = $moduleDataSetup; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + $this->moduleDataSetup->getConnection()->startSetup(); + $this->upgradeHash(); + $this->moduleDataSetup->getConnection()->endSetup(); + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return []; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.1'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } + + /** + * Upgrade password hashes. + */ + private function upgradeHash() + { + $connection = $this->moduleDataSetup->getConnection(); + $customerEntityTable = $this->moduleDataSetup->getTable('admin_user'); + + $select = $connection->select()->from( + $customerEntityTable, + ['user_id', 'password'] + ); + + $customers = $connection->fetchAll($select); + foreach ($customers as $customer) { + list($hash, $salt) = explode(Encryptor::DELIMITER, $customer['password']); + + $newHash = $customer['password']; + if (strlen($hash) === 32) { + $newHash = implode(Encryptor::DELIMITER, [$hash, $salt, Encryptor::HASH_VERSION_MD5]); + } elseif (strlen($hash) === 64) { + $newHash = implode(Encryptor::DELIMITER, [$hash, $salt, Encryptor::HASH_VERSION_SHA256]); + } + + $bind = ['password' => $newHash]; + $where = ['user_id = ?' => (int)$customer['user_id']]; + $connection->update($customerEntityTable, $bind, $where); + } + } +} diff --git a/app/code/Magento/User/Setup/Patch/Data/UpgradeSerializedFields.php b/app/code/Magento/User/Setup/Patch/Data/UpgradeSerializedFields.php new file mode 100644 index 0000000000000..568f365ee14d8 --- /dev/null +++ b/app/code/Magento/User/Setup/Patch/Data/UpgradeSerializedFields.php @@ -0,0 +1,93 @@ +moduleDataSetup = $moduleDataSetup; + $this->fieldDataConverterFactory = $fieldDataConverterFactory; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + $this->moduleDataSetup->getConnection()->startSetup(); + $this->upgradeSerializedFields(); + $this->moduleDataSetup->getConnection()->endSetup(); + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return [ + UpgradePasswordHashes::class + ]; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.2'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } + + /** + * Convert serialized data to json. + */ + private function upgradeSerializedFields() + { + $fieldDataConverter = $this->fieldDataConverterFactory->create(SerializedToJson::class); + $fieldDataConverter->convert( + $this->moduleDataSetup->getConnection(), + $this->moduleDataSetup->getTable('admin_user'), + 'user_id', + 'extra' + ); + } +} diff --git a/app/code/Magento/User/Setup/UpgradeData.php b/app/code/Magento/User/Setup/UpgradeData.php deleted file mode 100644 index 805eb152e77e6..0000000000000 --- a/app/code/Magento/User/Setup/UpgradeData.php +++ /dev/null @@ -1,99 +0,0 @@ -fieldDataConverterFactory = $fieldDataConverterFactory; - } - - /** - * @inheritdoc - */ - public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context) - { - $setup->startSetup(); - - if (version_compare($context->getVersion(), '2.0.1', '<')) { - $this->upgradeHash($setup); - } - - if (version_compare($context->getVersion(), '2.0.2', '<')) { - $this->upgradeSerializedFields($setup); - } - - $setup->endSetup(); - } - - /** - * @param ModuleDataSetupInterface $setup - * @return void - */ - private function upgradeHash($setup) - { - $customerEntityTable = $setup->getTable('admin_user'); - - $select = $setup->getConnection()->select()->from( - $customerEntityTable, - ['user_id', 'password'] - ); - - $customers = $setup->getConnection()->fetchAll($select); - foreach ($customers as $customer) { - list($hash, $salt) = explode(Encryptor::DELIMITER, $customer['password']); - - $newHash = $customer['password']; - if (strlen($hash) === 32) { - $newHash = implode(Encryptor::DELIMITER, [$hash, $salt, Encryptor::HASH_VERSION_MD5]); - } elseif (strlen($hash) === 64) { - $newHash = implode(Encryptor::DELIMITER, [$hash, $salt, Encryptor::HASH_VERSION_SHA256]); - } - - $bind = ['password' => $newHash]; - $where = ['user_id = ?' => (int)$customer['user_id']]; - $setup->getConnection()->update($customerEntityTable, $bind, $where); - } - } - - /** - * Convert serialized data in fields to json format - * - * @param ModuleDataSetupInterface $setup - * - * @return void - */ - private function upgradeSerializedFields($setup) - { - $fieldDataConverter = $this->fieldDataConverterFactory->create(SerializedToJson::class); - - $fieldDataConverter->convert( - $setup->getConnection(), - $setup->getTable('admin_user'), - 'user_id', - 'extra' - ); - } -} diff --git a/app/code/Magento/User/Test/Unit/Model/UserTest.php b/app/code/Magento/User/Test/Unit/Model/UserTest.php index 1d63d1aed3e1a..c00325da00c37 100644 --- a/app/code/Magento/User/Test/Unit/Model/UserTest.php +++ b/app/code/Magento/User/Test/Unit/Model/UserTest.php @@ -352,7 +352,8 @@ public function testVerifyIdentityInactiveRecord() $this->model->setIsActive(false); $this->expectException( \Magento\Framework\Exception\AuthenticationException::class, - 'You did not sign in correctly or your account is temporarily disabled.' + 'The account sign-in was incorrect or your account is disabled temporarily. ' + . 'Please wait and try again later.' ); $this->model->verifyIdentity($password); } @@ -372,7 +373,7 @@ public function testVerifyIdentityNoAssignedRoles() $this->resourceMock->expects($this->once())->method('hasAssigned2Role')->willReturn(false); $this->expectException( \Magento\Framework\Exception\AuthenticationException::class, - 'You need more permissions to access this.' + 'More permissions are needed to access this.' ); $this->model->verifyIdentity($password); } @@ -783,14 +784,14 @@ public function testPerformIdentityCheck($verifyIdentityResult, $lockExpires) if ($lockExpires) { $this->expectException( \Magento\Framework\Exception\State\UserLockedException::class, - __('Your account is temporarily disabled.') + __('Your account is temporarily disabled. Please try again later.') ); } if (!$verifyIdentityResult) { $this->expectException( \Magento\Framework\Exception\AuthenticationException::class, - __('You have entered an invalid password for current user.') + __('The password entered for the current user is invalid. Verify the password and try again.') ); } diff --git a/app/code/Magento/User/etc/module.xml b/app/code/Magento/User/etc/module.xml index d3d5f52eddc60..ad4c972ae79d3 100644 --- a/app/code/Magento/User/etc/module.xml +++ b/app/code/Magento/User/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/Usps/Setup/UpgradeData.php b/app/code/Magento/Usps/Setup/Patch/Data/UpdateAllowedMethods.php similarity index 75% rename from app/code/Magento/Usps/Setup/UpgradeData.php rename to app/code/Magento/Usps/Setup/Patch/Data/UpdateAllowedMethods.php index bc29d46836640..772f7cfb1a33a 100644 --- a/app/code/Magento/Usps/Setup/UpgradeData.php +++ b/app/code/Magento/Usps/Setup/Patch/Data/UpdateAllowedMethods.php @@ -4,36 +4,40 @@ * See COPYING.txt for license details. */ -namespace Magento\Usps\Setup; +namespace Magento\Usps\Setup\Patch\Data; -use Magento\Framework\Setup\ModuleContextInterface; -use Magento\Framework\Setup\ModuleDataSetupInterface; -use Magento\Framework\Setup\UpgradeDataInterface; +use Magento\Framework\App\ResourceConnection; +use Magento\Setup\Model\Patch\DataPatchInterface; +use Magento\Setup\Model\Patch\PatchVersionInterface; -class UpgradeData implements UpgradeDataInterface +/** + * Class UpdateAllowedMethods + * @package Magento\Usps\Setup\Patch + */ +class UpdateAllowedMethods implements DataPatchInterface, PatchVersionInterface { /** - * @inheritdoc + * @var \Magento\Framework\Setup\ModuleDataSetupInterface */ - public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context) - { - if (version_compare($context->getVersion(), '2.0.1', '<')) { - $this->updateAllowedMethods($setup); - } + private $moduleDataSetup; + + /** + * UpdateAllowedMethods constructor. + * @param \Magento\Framework\Setup\ModuleDataSetupInterface $moduleDataSetup + */ + public function __construct( + \Magento\Framework\Setup\ModuleDataSetupInterface $moduleDataSetup + ) { + $this->moduleDataSetup = $moduleDataSetup; } /** - * Replaces titles of allowed shipping methods to their codes. - * - * @param ModuleDataSetupInterface $setup - * @return void + * {@inheritdoc} */ - private function updateAllowedMethods(ModuleDataSetupInterface $setup) + public function apply() { - $installer = $setup; - $configDataTable = $installer->getTable('core_config_data'); - $connection = $installer->getConnection(); - + $connection = $this->moduleDataSetup->getConnection(); + $configDataTable = $this->moduleDataSetup->getTable('core_config_data'); $oldToNewMethodCodesMap = [ 'First-Class' => '0_FCLE', 'First-Class Mail International Large Envelope' => 'INT_14', @@ -110,4 +114,28 @@ private function updateAllowedMethods(ModuleDataSetupInterface $setup) } } } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return []; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.1'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } } diff --git a/app/code/Magento/Usps/etc/module.xml b/app/code/Magento/Usps/etc/module.xml index 8a1ec284c6333..0752b0dfe0efd 100644 --- a/app/code/Magento/Usps/etc/module.xml +++ b/app/code/Magento/Usps/etc/module.xml @@ -6,6 +6,6 @@ */ --> - + diff --git a/app/code/Magento/Variable/Model/ResourceModel/Variable/Collection.php b/app/code/Magento/Variable/Model/ResourceModel/Variable/Collection.php index 3b74849352274..64c541e8c70b9 100644 --- a/app/code/Magento/Variable/Model/ResourceModel/Variable/Collection.php +++ b/app/code/Magento/Variable/Model/ResourceModel/Variable/Collection.php @@ -62,7 +62,7 @@ public function addValuesToResult() $this->getSelect()->join( ['value_table' => $this->getTable('variable_value')], 'value_table.variable_id = main_table.variable_id', - ['value_table.value'] + ['value_table.plain_value', 'value_table.html_value'] ); $this->addFieldToFilter('value_table.store_id', ['eq' => $this->getStoreId()]); return $this; diff --git a/app/code/Magento/Variable/Test/Unit/Model/ResourceModel/Variable/CollectionTest.php b/app/code/Magento/Variable/Test/Unit/Model/ResourceModel/Variable/CollectionTest.php new file mode 100644 index 0000000000000..38cf2fefcef97 --- /dev/null +++ b/app/code/Magento/Variable/Test/Unit/Model/ResourceModel/Variable/CollectionTest.php @@ -0,0 +1,94 @@ +getMockBuilder(Select::class) + ->disableOriginalConstructor() + ->getMock(); + $select->expects($this->once()) + ->method('from') + ->with($this->identicalTo(['main_table' => $mainTableName])) + ->willReturnSelf(); + $select->expects($this->once()) + ->method('join') + ->with( + $this->identicalTo(['value_table' => $tableName]), + $this->identicalTo('value_table.variable_id = main_table.variable_id'), + $this->identicalTo(['value_table.plain_value', 'value_table.html_value']) + )->willReturnSelf(); + + $connection = $this->getMockBuilder(AdapterInterface::class) + ->disableOriginalConstructor() + ->setMethods(['select', 'prepareSqlCondition', 'quoteIdentifier']) + ->getMockForAbstractClass(); + $connection->expects($this->any()) + ->method('select') + ->willReturn($select); + $connection->expects($this->once()) + ->method('quoteIdentifier') + ->with($this->identicalTo($field)) + ->willReturn($field); + $connection->expects($this->once()) + ->method('prepareSqlCondition') + ->with( + $this->identicalTo($field), + $this->identicalTo(['eq' => 0]) + )->willReturn('testResultCondition'); + + $resource = $this->getMockBuilder(AbstractDb::class) + ->setMethods(['getTable', 'getMainTable', 'getConnection']) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + $resource->expects($this->any()) + ->method('getConnection') + ->willReturn($connection); + $resource->expects($this->once()) + ->method('getMainTable') + ->willReturn('testMainTable'); + $resource->expects($this->exactly(2)) + ->method('getTable') + ->withConsecutive( + [$mainTableName], + [$tableName] + )->willReturnOnConsecutiveCalls( + $mainTableName, + $tableName + ); + + $objectManager = new ObjectManager($this); + $collection = $objectManager->getObject( + Collection::class, + [ + 'resource' => $resource, + ] + ); + $this->assertInstanceOf(Collection::class, $collection->addValuesToResult()); + } +} diff --git a/app/code/Magento/Variable/etc/module.xml b/app/code/Magento/Variable/etc/module.xml index d85388d46fcbd..50a5afde34992 100644 --- a/app/code/Magento/Variable/etc/module.xml +++ b/app/code/Magento/Variable/etc/module.xml @@ -6,6 +6,6 @@ */ --> - + diff --git a/app/code/Magento/Vault/Model/Ui/Adminhtml/TokensConfigProvider.php b/app/code/Magento/Vault/Model/Ui/Adminhtml/TokensConfigProvider.php index 0cb3182980f55..d79d4ff98f0c8 100644 --- a/app/code/Magento/Vault/Model/Ui/Adminhtml/TokensConfigProvider.php +++ b/app/code/Magento/Vault/Model/Ui/Adminhtml/TokensConfigProvider.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Vault\Model\Ui\Adminhtml; use Magento\Framework\Api\FilterBuilder; @@ -227,7 +228,7 @@ private function getPaymentTokenEntityId() { $paymentToken = $this->getPaymentTokenManagement()->getByPaymentId($this->getOrderPaymentEntityId()); if ($paymentToken === null) { - throw new NoSuchEntityException(__('No available payment tokens for specified order payment.')); + throw new NoSuchEntityException(__('No payment tokens are available for the specified order payment.')); } return $paymentToken->getEntityId(); } diff --git a/app/code/Magento/Vault/Setup/Patch/Data/SetCreditCardAsDefaultTokenType.php b/app/code/Magento/Vault/Setup/Patch/Data/SetCreditCardAsDefaultTokenType.php new file mode 100644 index 0000000000000..c2f7cca8b70e8 --- /dev/null +++ b/app/code/Magento/Vault/Setup/Patch/Data/SetCreditCardAsDefaultTokenType.php @@ -0,0 +1,79 @@ +moduleDataSetup = $moduleDataSetup; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + $this->moduleDataSetup->getConnection()->startSetup(); + + // data update for Vault module < 2.0.1 + // update sets credit card as default token type + $this->moduleDataSetup->getConnection()->update( + $this->moduleDataSetup->getTable('vault_payment_token'), + [ + PaymentTokenInterface::TYPE => CreditCardTokenFactory::TOKEN_TYPE_CREDIT_CARD + ], + PaymentTokenInterface::TYPE . ' = ""' + ); + + $this->moduleDataSetup->getConnection()->endSetup(); + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return []; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.1'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } +} diff --git a/app/code/Magento/Vault/Setup/UpgradeData.php b/app/code/Magento/Vault/Setup/UpgradeData.php deleted file mode 100644 index 7609a28d7f052..0000000000000 --- a/app/code/Magento/Vault/Setup/UpgradeData.php +++ /dev/null @@ -1,36 +0,0 @@ -startSetup(); - - // data update for Vault module < 2.0.1 - if (version_compare($context->getVersion(), '2.0.1', '<')) { - // update sets credit card as default token type - $setup->getConnection()->update($setup->getTable('vault_payment_token'), [ - PaymentTokenInterface::TYPE => CreditCardTokenFactory::TOKEN_TYPE_CREDIT_CARD - ], PaymentTokenInterface::TYPE . ' = ""'); - } - - $setup->endSetup(); - } -} diff --git a/app/code/Magento/Vault/etc/module.xml b/app/code/Magento/Vault/etc/module.xml index 253e7f13aaadc..a6d44d333fc02 100644 --- a/app/code/Magento/Vault/etc/module.xml +++ b/app/code/Magento/Vault/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/Version/etc/module.xml b/app/code/Magento/Version/etc/module.xml index 8108aaa038aee..fe8ace51ea07d 100644 --- a/app/code/Magento/Version/etc/module.xml +++ b/app/code/Magento/Version/etc/module.xml @@ -6,6 +6,6 @@ */ --> - + diff --git a/app/code/Magento/Webapi/Controller/Rest.php b/app/code/Magento/Webapi/Controller/Rest.php index dc061aeea99e7..3c0bf85eb5247 100644 --- a/app/code/Magento/Webapi/Controller/Rest.php +++ b/app/code/Magento/Webapi/Controller/Rest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Webapi\Controller; use Magento\Framework\App\DeploymentConfig; @@ -284,7 +285,7 @@ protected function checkPermissions() if (!$this->authorization->isAllowed($route->getAclResources())) { $params = ['resources' => implode(', ', $route->getAclResources())]; throw new AuthorizationException( - __('Consumer is not authorized to access %resources', $params) + __("The consumer isn't authorized to access %resources.", $params) ); } } diff --git a/app/code/Magento/Webapi/Controller/Rest/RequestValidator.php b/app/code/Magento/Webapi/Controller/Rest/RequestValidator.php index 07e3e7791103c..048c0d86bc312 100644 --- a/app/code/Magento/Webapi/Controller/Rest/RequestValidator.php +++ b/app/code/Magento/Webapi/Controller/Rest/RequestValidator.php @@ -84,7 +84,7 @@ private function checkPermissions() if (!$this->authorization->isAllowed($route->getAclResources())) { $params = ['resources' => implode(', ', $route->getAclResources())]; throw new AuthorizationException( - __('Consumer is not authorized to access %resources', $params) + __("The consumer isn't authorized to access %resources.", $params) ); } } diff --git a/app/code/Magento/Webapi/Controller/Soap/Request/Handler.php b/app/code/Magento/Webapi/Controller/Soap/Request/Handler.php index 0e87805daf60a..72cbbe7481cfa 100644 --- a/app/code/Magento/Webapi/Controller/Soap/Request/Handler.php +++ b/app/code/Magento/Webapi/Controller/Soap/Request/Handler.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Webapi\Controller\Soap\Request; use Magento\Framework\Api\ExtensibleDataInterface; @@ -126,7 +127,7 @@ public function __call($operation, $arguments) if (!$this->authorization->isAllowed($serviceMethodInfo[ServiceMetadata::KEY_ACL_RESOURCES])) { throw new AuthorizationException( __( - 'Consumer is not authorized to access %resources', + "The consumer isn't authorized to access %resources.", ['resources' => implode(', ', $serviceMethodInfo[ServiceMetadata::KEY_ACL_RESOURCES])] ) ); diff --git a/app/code/Magento/Webapi/Model/Soap/Wsdl/Generator.php b/app/code/Magento/Webapi/Model/Soap/Wsdl/Generator.php index fe6a2a353ff57..e14b4a05f41fd 100644 --- a/app/code/Magento/Webapi/Model/Soap/Wsdl/Generator.php +++ b/app/code/Magento/Webapi/Model/Soap/Wsdl/Generator.php @@ -4,6 +4,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Webapi\Model\Soap\Wsdl; use Magento\Webapi\Model\AbstractSchemaGenerator; @@ -375,7 +376,7 @@ protected function getAllowedServicesMetadata($requestedServices) if (!$allowedServicesMetadata) { throw new AuthorizationException( __( - 'Consumer is not authorized to access %resources', + "The consumer isn't authorized to access %resources.", ['resources' => implode(', ', $requestedServices)] ) ); diff --git a/app/code/Magento/Webapi/Test/Unit/Controller/Rest/RequestValidatorTest.php b/app/code/Magento/Webapi/Test/Unit/Controller/Rest/RequestValidatorTest.php index 9d57db911fd51..a0dadd345dd72 100644 --- a/app/code/Magento/Webapi/Test/Unit/Controller/Rest/RequestValidatorTest.php +++ b/app/code/Magento/Webapi/Test/Unit/Controller/Rest/RequestValidatorTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Webapi\Test\Unit\Controller\Rest; class RequestValidatorTest extends \PHPUnit\Framework\TestCase @@ -131,7 +132,7 @@ public function testInSecureRequestOverSecureRoute() /** * @expectedException \Magento\Framework\Exception\AuthorizationException - * @expectedExceptionMessage Consumer is not authorized to access 5, 6 + * @expectedExceptionMessage The consumer isn't authorized to access 5, 6. */ public function testAuthorizationFailed() { diff --git a/app/code/Magento/Webapi/etc/module.xml b/app/code/Magento/Webapi/etc/module.xml index cda30887d0a22..093895b6e0a7a 100644 --- a/app/code/Magento/Webapi/etc/module.xml +++ b/app/code/Magento/Webapi/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/WebapiSecurity/etc/module.xml b/app/code/Magento/WebapiSecurity/etc/module.xml index 5fed15fb373b8..64dc439ad3fdd 100644 --- a/app/code/Magento/WebapiSecurity/etc/module.xml +++ b/app/code/Magento/WebapiSecurity/etc/module.xml @@ -4,5 +4,5 @@ ~ See COPYING.txt for license details. --> - + diff --git a/app/code/Magento/Weee/Model/Attribute/Backend/Weee/Tax.php b/app/code/Magento/Weee/Model/Attribute/Backend/Weee/Tax.php index dfa40a166ba99..11b976a640b07 100644 --- a/app/code/Magento/Weee/Model/Attribute/Backend/Weee/Tax.php +++ b/app/code/Magento/Weee/Model/Attribute/Backend/Weee/Tax.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Weee\Model\Attribute\Backend\Weee; use Magento\Framework\Exception\LocalizedException; @@ -90,7 +91,8 @@ public function validate($object) $key1 = implode('-', [$tax['website_id'], $tax['country'], $state]); if (!empty($dup[$key1])) { throw new LocalizedException( - __('You must set unique country-state combinations within the same fixed product tax') + __('Set unique country-state combinations within the same fixed product tax. ' + . 'Verify the combinations and try again.') ); } $dup[$key1] = 1; diff --git a/app/code/Magento/Weee/Setup/InstallData.php b/app/code/Magento/Weee/Setup/Patch/Data/InitQuoteAndOrderAttributes.php similarity index 79% rename from app/code/Magento/Weee/Setup/InstallData.php rename to app/code/Magento/Weee/Setup/Patch/Data/InitQuoteAndOrderAttributes.php index dd4218cceb99a..d2947686b9af8 100644 --- a/app/code/Magento/Weee/Setup/InstallData.php +++ b/app/code/Magento/Weee/Setup/Patch/Data/InitQuoteAndOrderAttributes.php @@ -4,56 +4,59 @@ * See COPYING.txt for license details. */ -namespace Magento\Weee\Setup; +namespace Magento\Weee\Setup\Patch\Data; -use Magento\Framework\Setup\InstallDataInterface; -use Magento\Framework\Setup\ModuleContextInterface; -use Magento\Framework\Setup\ModuleDataSetupInterface; use Magento\Quote\Setup\QuoteSetup; use Magento\Quote\Setup\QuoteSetupFactory; use Magento\Sales\Setup\SalesSetup; use Magento\Sales\Setup\SalesSetupFactory; +use Magento\Setup\Model\Patch\DataPatchInterface; +use Magento\Setup\Model\Patch\PatchVersionInterface; /** - * @codeCoverageIgnore + * Class InitQuoteAndOrderAttributes + * @package Magento\Weee\Setup\Patch */ -class InstallData implements InstallDataInterface +class InitQuoteAndOrderAttributes implements DataPatchInterface, PatchVersionInterface { /** - * Sales setup factory - * - * @var SalesSetupFactory + * @var \Magento\Framework\Setup\ModuleDataSetupInterface */ - private $salesSetupFactory; + private $moduleDataSetup; /** - * Quote setup factory - * * @var QuoteSetupFactory */ private $quoteSetupFactory; /** - * Init - * - * @param SalesSetupFactory $salesSetupFactory + * @var SalesSetupFactory + */ + private $salesSetupFactory; + + /** + * InitQuoteAndOrderAttributes constructor. + * @param \Magento\Framework\Setup\ModuleDataSetupInterface $moduleDataSetup * @param QuoteSetupFactory $quoteSetupFactory + * @param SalesSetupFactory $salesSetupFactory */ public function __construct( - SalesSetupFactory $salesSetupFactory, - QuoteSetupFactory $quoteSetupFactory + \Magento\Framework\Setup\ModuleDataSetupInterface $moduleDataSetup, + QuoteSetupFactory $quoteSetupFactory, + SalesSetupFactory $salesSetupFactory ) { - $this->salesSetupFactory = $salesSetupFactory; + $this->moduleDataSetup = $moduleDataSetup; $this->quoteSetupFactory = $quoteSetupFactory; + $this->salesSetupFactory = $salesSetupFactory; } /** * {@inheritdoc} */ - public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context) + public function apply() { /** @var QuoteSetup $quoteSetup */ - $quoteSetup = $this->quoteSetupFactory->create(['setup' => $setup]); + $quoteSetup = $this->quoteSetupFactory->create(['setup' => $this->moduleDataSetup]); $quoteSetup->addAttribute('quote_item', 'weee_tax_applied', ['type' => 'text']); $quoteSetup->addAttribute('quote_item', 'weee_tax_applied_amount', ['type' => 'decimal']); $quoteSetup->addAttribute('quote_item', 'weee_tax_applied_row_amount', ['type' => 'decimal']); @@ -65,7 +68,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $quoteSetup->addAttribute('quote_item', 'base_weee_tax_row_disposition', ['type' => 'decimal']); /** @var SalesSetup $salesSetup */ - $salesSetup = $this->salesSetupFactory->create(['setup' => $setup]); + $salesSetup = $this->salesSetupFactory->create(['setup' => $this->moduleDataSetup]); $salesSetup->addAttribute('order_item', 'weee_tax_applied', ['type' => 'text']); $salesSetup->addAttribute('order_item', 'weee_tax_applied_amount', ['type' => 'decimal']); $salesSetup->addAttribute('order_item', 'weee_tax_applied_row_amount', ['type' => 'decimal']); @@ -75,7 +78,6 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $salesSetup->addAttribute('order_item', 'base_weee_tax_applied_row_amnt', ['type' => 'decimal']); $salesSetup->addAttribute('order_item', 'base_weee_tax_disposition', ['type' => 'decimal']); $salesSetup->addAttribute('order_item', 'base_weee_tax_row_disposition', ['type' => 'decimal']); - $salesSetup->addAttribute('invoice_item', 'weee_tax_applied', ['type' => 'text']); $salesSetup->addAttribute('invoice_item', 'weee_tax_applied_amount', ['type' => 'decimal']); $salesSetup->addAttribute('invoice_item', 'weee_tax_applied_row_amount', ['type' => 'decimal']); @@ -85,7 +87,6 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $salesSetup->addAttribute('invoice_item', 'base_weee_tax_applied_row_amnt', ['type' => 'decimal']); $salesSetup->addAttribute('invoice_item', 'base_weee_tax_disposition', ['type' => 'decimal']); $salesSetup->addAttribute('invoice_item', 'base_weee_tax_row_disposition', ['type' => 'decimal']); - $salesSetup->addAttribute('creditmemo_item', 'weee_tax_applied', ['type' => 'text']); $salesSetup->addAttribute('creditmemo_item', 'weee_tax_applied_amount', ['type' => 'decimal']); $salesSetup->addAttribute('creditmemo_item', 'weee_tax_applied_row_amount', ['type' => 'decimal']); @@ -96,4 +97,28 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $salesSetup->addAttribute('creditmemo_item', 'base_weee_tax_disposition', ['type' => 'decimal']); $salesSetup->addAttribute('creditmemo_item', 'base_weee_tax_row_disposition', ['type' => 'decimal']); } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return []; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.0'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } } diff --git a/app/code/Magento/Weee/Test/Unit/Model/Attribute/Backend/Weee/TaxTest.php b/app/code/Magento/Weee/Test/Unit/Model/Attribute/Backend/Weee/TaxTest.php index 28850fa2b84d8..dea5ae513ca31 100644 --- a/app/code/Magento/Weee/Test/Unit/Model/Attribute/Backend/Weee/TaxTest.php +++ b/app/code/Magento/Weee/Test/Unit/Model/Attribute/Backend/Weee/TaxTest.php @@ -97,7 +97,8 @@ public function dataProviderValidate() ['state' => 12, 'country' => 'US', 'website_id' => '1'], ['state' => null, 'country' => 'ES', 'website_id' => '1'] ], - 'expected' => 'You must set unique country-state combinations within the same fixed product tax', + 'expected' => 'Set unique country-state combinations within the same fixed product tax. ' + . 'Verify the combinations and try again.', ] ]; } diff --git a/app/code/Magento/Weee/etc/module.xml b/app/code/Magento/Weee/etc/module.xml index 01fa4fa5fd69e..8064f84577720 100644 --- a/app/code/Magento/Weee/etc/module.xml +++ b/app/code/Magento/Weee/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/Weee/view/adminhtml/web/js/fpt-group.js b/app/code/Magento/Weee/view/adminhtml/web/js/fpt-group.js index b034ae376f596..dc13c93888efd 100644 --- a/app/code/Magento/Weee/view/adminhtml/web/js/fpt-group.js +++ b/app/code/Magento/Weee/view/adminhtml/web/js/fpt-group.js @@ -34,7 +34,10 @@ define([ } return true; - }, $t('You must set unique country-state combinations within the same fixed product tax')); + }, $t( + 'Set unique country-state combinations within the same fixed product tax. ' + + 'Verify the combinations and try again.' + )); this._super(); }, diff --git a/app/code/Magento/WeeeGraphQl/etc/module.xml b/app/code/Magento/WeeeGraphQl/etc/module.xml index c91836164480e..90a5636071f35 100644 --- a/app/code/Magento/WeeeGraphQl/etc/module.xml +++ b/app/code/Magento/WeeeGraphQl/etc/module.xml @@ -6,5 +6,5 @@ */ --> - + diff --git a/app/code/Magento/Widget/Setup/InstallData.php b/app/code/Magento/Widget/Setup/InstallData.php deleted file mode 100644 index 76c2154215290..0000000000000 --- a/app/code/Magento/Widget/Setup/InstallData.php +++ /dev/null @@ -1,46 +0,0 @@ -createMigrationSetup(); - $setup->startSetup(); - - $installer->appendClassAliasReplace( - 'widget_instance', - 'instance_type', - \Magento\Framework\Module\Setup\Migration::ENTITY_TYPE_BLOCK, - \Magento\Framework\Module\Setup\Migration::FIELD_CONTENT_TYPE_PLAIN, - ['instance_id'] - ); - - $installer->appendClassAliasReplace( - 'layout_update', - 'xml', - \Magento\Framework\Module\Setup\Migration::ENTITY_TYPE_BLOCK, - \Magento\Framework\Module\Setup\Migration::FIELD_CONTENT_TYPE_XML, - ['layout_update_id'] - ); - - $installer->doUpdateClassAliases(); - - $setup->endSetup(); - } -} diff --git a/app/code/Magento/Widget/Setup/Patch/Data/ConvertSerializedData.php b/app/code/Magento/Widget/Setup/Patch/Data/ConvertSerializedData.php new file mode 100644 index 0000000000000..1791897b3f7a6 --- /dev/null +++ b/app/code/Magento/Widget/Setup/Patch/Data/ConvertSerializedData.php @@ -0,0 +1,117 @@ +moduleDataSetup = $moduleDataSetup; + $this->queryModifierFactory = $queryModifierFactory; + $this->aggregatedFieldDataConverter = $aggregatedFieldDataConverter; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + $this->convertSerializedData(); + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return [UpgradeModelInstanceClassAliases::class]; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.1'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } + + /** + * Convert native serialized data to json. + */ + private function convertSerializedData() + { + $layoutUpdateQueryModifier = $this->queryModifierFactory->create( + 'like', + [ + 'values' => [ + 'xml' => '%conditions_encoded%' + ] + ] + ); + $this->aggregatedFieldDataConverter->convert( + [ + new FieldToConvert( + SerializedToJson::class, + $this->moduleDataSetup->getTable('widget_instance'), + 'instance_id', + 'widget_parameters' + ), + new FieldToConvert( + LayoutUpdateConverter::class, + $this->moduleDataSetup->getTable('layout_update'), + 'layout_update_id', + 'xml', + $layoutUpdateQueryModifier + ), + ], + $this->moduleDataSetup->getConnection() + ); + } +} diff --git a/app/code/Magento/Widget/Setup/Patch/Data/UpgradeModelInstanceClassAliases.php b/app/code/Magento/Widget/Setup/Patch/Data/UpgradeModelInstanceClassAliases.php new file mode 100644 index 0000000000000..0a82e5fa223f4 --- /dev/null +++ b/app/code/Magento/Widget/Setup/Patch/Data/UpgradeModelInstanceClassAliases.php @@ -0,0 +1,83 @@ +moduleDataSetup = $moduleDataSetup; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + $installer = $this->moduleDataSetup->createMigrationSetup(); + $this->moduleDataSetup->startSetup(); + + $installer->appendClassAliasReplace( + 'widget_instance', + 'instance_type', + \Magento\Framework\Module\Setup\Migration::ENTITY_TYPE_BLOCK, + \Magento\Framework\Module\Setup\Migration::FIELD_CONTENT_TYPE_PLAIN, + ['instance_id'] + ); + $installer->appendClassAliasReplace( + 'layout_update', + 'xml', + \Magento\Framework\Module\Setup\Migration::ENTITY_TYPE_BLOCK, + \Magento\Framework\Module\Setup\Migration::FIELD_CONTENT_TYPE_XML, + ['layout_update_id'] + ); + $installer->doUpdateClassAliases(); + $this->moduleDataSetup->endSetup(); + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return []; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.0'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } +} diff --git a/app/code/Magento/Widget/Setup/UpgradeData.php b/app/code/Magento/Widget/Setup/UpgradeData.php deleted file mode 100644 index de3928d1fb5b8..0000000000000 --- a/app/code/Magento/Widget/Setup/UpgradeData.php +++ /dev/null @@ -1,89 +0,0 @@ -aggregatedFieldConverter = $aggregatedFieldConverter; - $this->queryModifierFactory = $queryModifierFactory; - } - - /** - * {@inheritdoc} - */ - public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context) - { - if (version_compare($context->getVersion(), '2.0.1', '<')) { - $this->upgradeVersionTwoZeroOne($setup); - } - } - - /** - * Upgrade data to version 2.0.1 - * - * @param ModuleDataSetupInterface $setup - * @return void - */ - private function upgradeVersionTwoZeroOne(ModuleDataSetupInterface $setup) - { - $layoutUpdateQueryModifier = $this->queryModifierFactory->create( - 'like', - [ - 'values' => [ - 'xml' => '%conditions_encoded%' - ] - ] - ); - $this->aggregatedFieldConverter->convert( - [ - new FieldToConvert( - SerializedToJson::class, - $setup->getTable('widget_instance'), - 'instance_id', - 'widget_parameters' - ), - new FieldToConvert( - LayoutUpdateConverter::class, - $setup->getTable('layout_update'), - 'layout_update_id', - 'xml', - $layoutUpdateQueryModifier - ), - ], - $setup->getConnection() - ); - } -} diff --git a/app/code/Magento/Widget/etc/module.xml b/app/code/Magento/Widget/etc/module.xml index 69467a38d47f5..4a163a641a290 100644 --- a/app/code/Magento/Widget/etc/module.xml +++ b/app/code/Magento/Widget/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/Wishlist/Controller/Index/Configure.php b/app/code/Magento/Wishlist/Controller/Index/Configure.php index 7e6f4d3ed7939..93a05ffc0ec93 100644 --- a/app/code/Magento/Wishlist/Controller/Index/Configure.php +++ b/app/code/Magento/Wishlist/Controller/Index/Configure.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Wishlist\Controller\Index; use Magento\Framework\App\Action; @@ -66,7 +67,7 @@ public function execute() $item->loadWithOptions($id); if (!$item->getId()) { throw new \Magento\Framework\Exception\LocalizedException( - __('We can\'t load the Wish List item right now.') + __("The Wish List item can't load at this time. Please try again later.") ); } $wishlist = $this->wishlistProvider->getWishlist($item->getWishlistId()); diff --git a/app/code/Magento/Wishlist/Controller/Index/Fromcart.php b/app/code/Magento/Wishlist/Controller/Index/Fromcart.php index 994da75073e96..49396004427f2 100644 --- a/app/code/Magento/Wishlist/Controller/Index/Fromcart.php +++ b/app/code/Magento/Wishlist/Controller/Index/Fromcart.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Wishlist\Controller\Index; use Magento\Checkout\Helper\Cart as CartHelper; @@ -104,7 +105,7 @@ public function execute() $item = $this->cart->getQuote()->getItemById($itemId); if (!$item) { throw new LocalizedException( - __('The requested cart item doesn\'t exist.') + __("The cart item doesn't exist.") ); } diff --git a/app/code/Magento/Wishlist/Setup/UpgradeData.php b/app/code/Magento/Wishlist/Setup/Patch/Data/ConvertSerializedData.php similarity index 59% rename from app/code/Magento/Wishlist/Setup/UpgradeData.php rename to app/code/Magento/Wishlist/Setup/Patch/Data/ConvertSerializedData.php index 10ce3469afe4f..62b50c3e539ed 100644 --- a/app/code/Magento/Wishlist/Setup/UpgradeData.php +++ b/app/code/Magento/Wishlist/Setup/Patch/Data/ConvertSerializedData.php @@ -3,19 +3,28 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\Wishlist\Setup; -use Magento\Framework\Setup\UpgradeDataInterface; -use Magento\Framework\Setup\ModuleContextInterface; -use Magento\Framework\Setup\ModuleDataSetupInterface; +namespace Magento\Wishlist\Setup\Patch\Data; + use Magento\Framework\DB\FieldDataConverterFactory; use Magento\Framework\DB\DataConverter\SerializedToJson; use Magento\Framework\DB\Select\QueryModifierFactory; -use Magento\Framework\DB\Select\InQueryModifier; -use Magento\Framework\DB\Query\Generator; +use Magento\Framework\DB\Query\Generator as QueryGenerator; +use Magento\Framework\App\ResourceConnection; +use Magento\Setup\Model\Patch\DataPatchInterface; +use Magento\Setup\Model\Patch\PatchVersionInterface; -class UpgradeData implements UpgradeDataInterface +/** + * Class ConvertSerializedData + * @package Magento\Wishlist\Setup\Patch + */ +class ConvertSerializedData implements DataPatchInterface, PatchVersionInterface { + /** + * @var \Magento\Framework\Setup\ModuleDataSetupInterface + */ + private $moduleDataSetup; + /** * @var FieldDataConverterFactory */ @@ -27,22 +36,24 @@ class UpgradeData implements UpgradeDataInterface private $queryModifierFactory; /** - * @var Generator + * @var QueryGenerator */ private $queryGenerator; /** - * Constructor - * + * ConvertSerializedData constructor. + * @param \Magento\Framework\Setup\ModuleDataSetupInterface $moduleDataSetup * @param FieldDataConverterFactory $fieldDataConverterFactory * @param QueryModifierFactory $queryModifierFactory - * @param Generator $queryGenerator + * @param QueryGenerator $queryGenerator */ public function __construct( + \Magento\Framework\Setup\ModuleDataSetupInterface $moduleDataSetup, FieldDataConverterFactory $fieldDataConverterFactory, QueryModifierFactory $queryModifierFactory, - Generator $queryGenerator + QueryGenerator $queryGenerator ) { + $this->moduleDataSetup = $moduleDataSetup; $this->fieldDataConverterFactory = $fieldDataConverterFactory; $this->queryModifierFactory = $queryModifierFactory; $this->queryGenerator = $queryGenerator; @@ -51,22 +62,38 @@ public function __construct( /** * {@inheritdoc} */ - public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context) + public function apply() { - if (version_compare($context->getVersion(), '2.0.1', '<')) { - $this->upgradeToVersionTwoZeroOne($setup); - } + $this->convertSerializedData(); + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return []; } /** - * Upgrade to version 2.0.1, convert data for `value` field in `wishlist_item_option table` - * from php-serialized to JSON format - * - * @param ModuleDataSetupInterface $setup - * @return void + * {@inheritdoc} */ - private function upgradeToVersionTwoZeroOne(ModuleDataSetupInterface $setup) + public static function getVersion() + { + return '2.0.1'; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } + + private function convertSerializedData() { + $connection = $this->moduleDataSetup->getConnection(); $fieldDataConverter = $this->fieldDataConverterFactory->create(SerializedToJson::class); $queryModifier = $this->queryModifierFactory->create( 'in', @@ -84,22 +111,22 @@ private function upgradeToVersionTwoZeroOne(ModuleDataSetupInterface $setup) ] ); $fieldDataConverter->convert( - $setup->getConnection(), - $setup->getTable('wishlist_item_option'), + $connection, + $this->moduleDataSetup->getTable('wishlist_item_option'), 'option_id', 'value', $queryModifier ); - $select = $setup->getConnection() + $select = $connection ->select() ->from( - $setup->getTable('catalog_product_option'), + $this->moduleDataSetup->getTable('catalog_product_option'), ['option_id'] ) ->where('type = ?', 'file'); $iterator = $this->queryGenerator->generate('option_id', $select); foreach ($iterator as $selectByRange) { - $codes = $setup->getConnection()->fetchCol($selectByRange); + $codes = $connection->fetchCol($selectByRange); $codes = array_map( function ($id) { return 'option_' . $id; @@ -115,8 +142,8 @@ function ($id) { ] ); $fieldDataConverter->convert( - $setup->getConnection(), - $setup->getTable('wishlist_item_option'), + $connection, + $this->moduleDataSetup->getTable('wishlist_item_option'), 'option_id', 'value', $queryModifier diff --git a/app/code/Magento/Wishlist/Test/Unit/Controller/Index/FromcartTest.php b/app/code/Magento/Wishlist/Test/Unit/Controller/Index/FromcartTest.php index 704d4088130f3..52af38dee0ed3 100644 --- a/app/code/Magento/Wishlist/Test/Unit/Controller/Index/FromcartTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Controller/Index/FromcartTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Wishlist\Test\Unit\Controller\Index; use Magento\Checkout\Helper\Cart as CartHelper; @@ -197,7 +198,7 @@ public function testExecuteNoCartItem() $this->messageManager->expects($this->once()) ->method('addErrorMessage') - ->with(__('The requested cart item doesn\'t exist.')) + ->with(__("The cart item doesn't exist.")) ->willReturnSelf(); $this->resultRedirect->expects($this->once()) diff --git a/app/code/Magento/Wishlist/etc/module.xml b/app/code/Magento/Wishlist/etc/module.xml index e7626f504e1f1..c5ece20d7956b 100644 --- a/app/code/Magento/Wishlist/etc/module.xml +++ b/app/code/Magento/Wishlist/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/code/Magento/WishlistAnalytics/etc/module.xml b/app/code/Magento/WishlistAnalytics/etc/module.xml index 159ed86ee171a..4acd600b66a7b 100644 --- a/app/code/Magento/WishlistAnalytics/etc/module.xml +++ b/app/code/Magento/WishlistAnalytics/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/app/design/adminhtml/Magento/backend/web/css/source/_components.less b/app/design/adminhtml/Magento/backend/web/css/source/_components.less index ac80ba9ef90d9..3f9f0ed00c5ed 100644 --- a/app/design/adminhtml/Magento/backend/web/css/source/_components.less +++ b/app/design/adminhtml/Magento/backend/web/css/source/_components.less @@ -20,4 +20,5 @@ @import 'components/_media-gallery.less'; @import 'components/_resizable-block.less'; @import 'components/_file-uploader.less'; +@import 'components/_image-uploader.less'; @import 'components/_slider.less'; diff --git a/app/design/adminhtml/Magento/backend/web/css/source/components/_image-uploader.less b/app/design/adminhtml/Magento/backend/web/css/source/components/_image-uploader.less new file mode 100644 index 0000000000000..f187697281252 --- /dev/null +++ b/app/design/adminhtml/Magento/backend/web/css/source/components/_image-uploader.less @@ -0,0 +1,45 @@ +// /** +// * Copyright © Magento, Inc. All rights reserved. +// * See COPYING.txt for license details. +// */ + +// +// Components -> Image Uploader +// _____________________________________________ + +.image-uploader { + .image-upload-requirements { + margin-top: 8px; + font-size: .9em; + } + + .image-placeholder { + margin-left: 0; + margin-right: 0; + } + + .image-uploader-spinner { + width: 50%; + height: 50%; + background-size: auto; + margin: 0; + transform: translate(50%, 50%); + position: absolute; + } + + .image-uploader-preview { + width: auto; + } + + .image-uploader-preview-link, + .image-uploader-preview-link .preview-image { + height: inherit; + } +} + +.image-uploader._loading { + .image-placeholder-text, + .product-image-wrapper:before { + display: none; + } +} diff --git a/app/etc/db_schema.xml b/app/etc/db_schema.xml new file mode 100644 index 0000000000000..64573fb6ced30 --- /dev/null +++ b/app/etc/db_schema.xml @@ -0,0 +1,17 @@ + + + + + + + + + +
    +
    diff --git a/app/etc/di.xml b/app/etc/di.xml index 3d883801513ee..5d49b5d26a5a7 100755 --- a/app/etc/di.xml +++ b/app/etc/di.xml @@ -43,6 +43,8 @@ + + system/currency/installed @@ -177,6 +179,7 @@ + @@ -1447,6 +1450,10 @@ Magento\Setup\Model\Declaration\Schema\Operations\AddComplexElement Magento\Setup\Model\Declaration\Schema\Operations\ModifyTable + + Magento\Setup\Model\Declaration\Schema\DataSavior\TableSavior + Magento\Setup\Model\Declaration\Schema\DataSavior\ColumnSavior + @@ -1490,4 +1497,20 @@ + + + schema + + + + + data + + + + + \Magento\Setup\Model\Patch\DataPatchReader + \Magento\Setup\Model\Patch\SchemaPatchReader + +
    diff --git a/composer.json b/composer.json index e0db7a4a99a15..d28fdbf44b091 100644 --- a/composer.json +++ b/composer.json @@ -34,7 +34,7 @@ "colinmollenhour/cache-backend-file": "1.4", "colinmollenhour/cache-backend-redis": "1.10.2", "colinmollenhour/credis": "1.6", - "colinmollenhour/php-redis-session-abstract": "~1.2.2", + "colinmollenhour/php-redis-session-abstract": "~1.3.8", "composer/composer": "1.4.1", "magento/composer": "~1.2.0", "magento/magento-composer-installer": ">=0.1.11", @@ -44,12 +44,12 @@ "pelago/emogrifier": "^2.0.0", "phpseclib/phpseclib": "2.0.*", "ramsey/uuid": "3.6.1", - "sjparkinson/static-review": "~4.1", "symfony/console": "~2.3, !=2.7.0", "symfony/event-dispatcher": "~2.1", "symfony/process": "~2.1", "tedivm/jshrink": "~1.1.0", "tubalmartin/cssmin": "4.1.0", + "webonyx/graphql-php": "^0.11.1", "zendframework/zend-captcha": "^2.7.1", "zendframework/zend-code": "^3.1.0", "zendframework/zend-config": "^2.6.0", @@ -75,8 +75,7 @@ "zendframework/zend-text": "^2.6.0", "zendframework/zend-uri": "^2.5.1", "zendframework/zend-validator": "^2.6.0", - "zendframework/zend-view": "^2.8.1", - "webonyx/graphql-php": "^0.11.1" + "zendframework/zend-view": "^2.8.1" }, "require-dev": { "friendsofphp/php-cs-fixer": "~2.1.1", diff --git a/composer.lock b/composer.lock index ee6328ed75bb4..280c078a4aca0 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "9114dbda66ca0958916c9e26caf374ce", + "content-hash": "461329079b6e93566f104978d025e7fa", "packages": [ { "name": "braintree/braintree_php", @@ -166,21 +166,21 @@ }, { "name": "colinmollenhour/php-redis-session-abstract", - "version": "v1.2.2", + "version": "v1.3.8", "source": { "type": "git", "url": "https://github.com/colinmollenhour/php-redis-session-abstract.git", - "reference": "46968f06eeed7d16e8476d8a1397e224047ac6ff" + "reference": "9f69f5c1be512d5ff168e731e7fa29ab2905d847" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/colinmollenhour/php-redis-session-abstract/zipball/46968f06eeed7d16e8476d8a1397e224047ac6ff", - "reference": "46968f06eeed7d16e8476d8a1397e224047ac6ff", + "url": "https://api.github.com/repos/colinmollenhour/php-redis-session-abstract/zipball/9f69f5c1be512d5ff168e731e7fa29ab2905d847", + "reference": "9f69f5c1be512d5ff168e731e7fa29ab2905d847", "shasum": "" }, "require": { - "colinmollenhour/credis": "1.6", - "php": "~5.5.0|~5.6.0|~7.0.0|~7.1.0" + "colinmollenhour/credis": "~1.6", + "php": "~5.5.0|~5.6.0|~7.0.0|~7.1.0|~7.2.0" }, "type": "library", "autoload": { @@ -199,7 +199,7 @@ ], "description": "A Redis-based session handler with optimistic locking", "homepage": "https://github.com/colinmollenhour/php-redis-session-abstract", - "time": "2017-04-19T14:21:43+00:00" + "time": "2018-01-08T14:53:13+00:00" }, { "name": "composer/ca-bundle", @@ -554,55 +554,6 @@ ], "time": "2017-10-21T13:15:38+00:00" }, - { - "name": "league/climate", - "version": "2.6.1", - "source": { - "type": "git", - "url": "https://github.com/thephpleague/climate.git", - "reference": "28851c909017424f61cc6a62089316313c645d1c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/thephpleague/climate/zipball/28851c909017424f61cc6a62089316313c645d1c", - "reference": "28851c909017424f61cc6a62089316313c645d1c", - "shasum": "" - }, - "require": { - "php": ">=5.4.0" - }, - "require-dev": { - "mockery/mockery": "dev-master", - "phpunit/phpunit": "4.1.*" - }, - "type": "library", - "autoload": { - "psr-4": { - "League\\CLImate\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Joe Tannenbaum", - "email": "hey@joe.codes", - "homepage": "http://joe.codes/", - "role": "Developer" - } - ], - "description": "PHP's best friend for the terminal. CLImate allows you to easily output colored text, special formats, and more.", - "keywords": [ - "cli", - "colors", - "command", - "php", - "terminal" - ], - "time": "2015-01-18T14:31:58+00:00" - }, { "name": "magento/composer", "version": "1.2.0", @@ -1433,60 +1384,6 @@ ], "time": "2015-10-13T18:44:15+00:00" }, - { - "name": "sjparkinson/static-review", - "version": "4.1.1", - "source": { - "type": "git", - "url": "https://github.com/sjparkinson/static-review.git", - "reference": "493c3410cf146a12fca84209bad126c494e125f0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sjparkinson/static-review/zipball/493c3410cf146a12fca84209bad126c494e125f0", - "reference": "493c3410cf146a12fca84209bad126c494e125f0", - "shasum": "" - }, - "require": { - "league/climate": "~2.0", - "php": ">=5.4.0", - "symfony/console": "~2.0", - "symfony/process": "~2.0" - }, - "require-dev": { - "mockery/mockery": "~0.9", - "phpunit/phpunit": "~4.0", - "sensiolabs/security-checker": "~2.0", - "squizlabs/php_codesniffer": "~1.0" - }, - "suggest": { - "sensiolabs/security-checker": "Required for ComposerSecurityReview.", - "squizlabs/php_codesniffer": "Required for PhpCodeSnifferReview." - }, - "bin": [ - "bin/static-review.php" - ], - "type": "library", - "autoload": { - "psr-4": { - "StaticReview\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Samuel Parkinson", - "email": "sam.james.parkinson@gmail.com", - "homepage": "http://samp.im" - } - ], - "description": "An extendable framework for version control hooks.", - "abandoned": "phpro/grumphp", - "time": "2014-09-22T08:40:36+00:00" - }, { "name": "symfony/console", "version": "v2.8.34", diff --git a/dev/tests/acceptance/composer.json b/dev/tests/acceptance/composer.json index 5df5b2391d257..09b3aa586729e 100755 --- a/dev/tests/acceptance/composer.json +++ b/dev/tests/acceptance/composer.json @@ -1,5 +1,4 @@ { - "name": "magento/magento2ce-functional-tests", "description": "Magento 2 (Open Source) Functional Tests", "type": "project", "version": "1.0.0-dev", @@ -26,115 +25,6 @@ "php": "7.0.2|7.0.4|~7.0.6|~7.1.0", "vlucas/phpdotenv": "~2.4" }, - "replace": { - "magento/magento2-functional-test-module-marketplace": "100.0.0-dev", - "magento/magento2-functional-test-module-admin-notification": "100.0.0-dev", - "magento/magento2-functional-test-module-advanced-pricing-import-export": "100.0.0-dev", - "magento/magento2-functional-test-module-authorization": "100.0.0-dev", - "magento/magento2-functional-test-module-authorizenet": "100.0.0-dev", - "magento/magento2-functional-test-module-backend": "100.0.0-dev", - "magento/magento2-functional-test-module-backup": "100.0.0-dev", - "magento/magento2-functional-test-module-braintree": "100.0.0-dev", - "magento/magento2-functional-test-module-bundle": "100.0.0-dev", - "magento/magento2-functional-test-module-bundle-import-export": "100.0.0-dev", - "magento/magento2-functional-test-module-cache-invalidate": "100.0.0-dev", - "magento/magento2-functional-test-module-captcha": "100.0.0-dev", - "magento/magento2-functional-test-module-catalog": "100.0.0-dev", - "magento/magento2-functional-test-module-catalog-import-export": "100.0.0-dev", - "magento/magento2-functional-test-module-catalog-inventory": "100.0.0-dev", - "magento/magento2-functional-test-module-catalog-rule": "100.0.0-dev", - "magento/magento2-functional-test-module-catalog-rule-configurable": "100.0.0-dev", - "magento/magento2-functional-test-module-catalog-search": "100.0.0-dev", - "magento/magento2-functional-test-module-catalog-url-rewrite": "100.0.0-dev", - "magento/magento2-functional-test-module-catalog-widget": "100.0.0-dev", - "magento/magento2-functional-test-module-checkout": "100.0.0-dev", - "magento/magento2-functional-test-module-checkout-agreements": "100.0.0-dev", - "magento/magento2-functional-test-module-cms": "100.0.0-dev", - "magento/magento2-functional-test-module-cms-url-rewrite": "100.0.0-dev", - "magento/magento2-functional-test-module-config": "100.0.0-dev", - "magento/magento2-functional-test-module-configurable-import-export": "100.0.0-dev", - "magento/magento2-functional-test-module-configurable-product": "100.0.0-dev", - "magento/magento2-functional-test-module-configurable-product-sales": "100.0.0-dev", - "magento/magento2-functional-test-module-contact": "100.0.0-dev", - "magento/magento2-functional-test-module-cookie": "100.0.0-dev", - "magento/magento2-functional-test-module-cron": "100.0.0-dev", - "magento/magento2-functional-test-module-currency-symbol": "100.0.0-dev", - "magento/magento2-functional-test-module-customer": "100.0.0-dev", - "magento/magento2-functional-test-module-customer-import-export": "100.0.0-dev", - "magento/magento2-functional-test-module-deploy": "100.0.0-dev", - "magento/magento2-functional-test-module-developer": "100.0.0-dev", - "magento/magento2-functional-test-module-dhl": "100.0.0-dev", - "magento/magento2-functional-test-module-directory": "100.0.0-dev", - "magento/magento2-functional-test-module-downloadable": "100.0.0-dev", - "magento/magento2-functional-test-module-downloadable-import-export": "100.0.0-dev", - "magento/magento2-functional-test-module-eav": "100.0.0-dev", - "magento/magento2-functional-test-module-email": "100.0.0-dev", - "magento/magento2-functional-test-module-encryption-key": "100.0.0-dev", - "magento/magento2-functional-test-module-fedex": "100.0.0-dev", - "magento/magento2-functional-test-module-gift-message": "100.0.0-dev", - "magento/magento2-functional-test-module-google-adwords": "100.0.0-dev", - "magento/magento2-functional-test-module-google-analytics": "100.0.0-dev", - "magento/magento2-functional-test-module-google-optimizer": "100.0.0-dev", - "magento/magento2-functional-test-module-graph-ql": "100.0.0-dev", - "magento/magento2-functional-test-module-grouped-import-export": "100.0.0-dev", - "magento/magento2-functional-test-module-grouped-product": "100.0.0-dev", - "magento/magento2-functional-test-module-import-export": "100.0.0-dev", - "magento/magento2-functional-test-module-indexer": "100.0.0-dev", - "magento/magento2-functional-test-module-instant-purchase": "100.0.0-dev", - "magento/magento2-functional-test-module-integration": "100.0.0-dev", - "magento/magento2-functional-test-module-layered-navigation": "100.0.0-dev", - "magento/magento2-functional-test-module-media-storage": "100.0.0-dev", - "magento/magento2-functional-test-module-msrp": "100.0.0-dev", - "magento/magento2-functional-test-module-multishipping": "100.0.0-dev", - "magento/magento2-functional-test-module-new-relic-reporting": "100.0.0-dev", - "magento/magento2-functional-test-module-newsletter": "100.0.0-dev", - "magento/magento2-functional-test-module-offline-payments": "100.0.0-dev", - "magento/magento2-functional-test-module-offline-shipping": "100.0.0-dev", - "magento/magento2-functional-test-module-page-cache": "100.0.0-dev", - "magento/magento2-functional-test-module-payment": "100.0.0-dev", - "magento/magento2-functional-test-module-paypal": "100.0.0-dev", - "magento/magento2-functional-test-module-persistent": "100.0.0-dev", - "magento/magento2-functional-test-module-product-alert": "100.0.0-dev", - "magento/magento2-functional-test-module-product-video": "100.0.0-dev", - "magento/magento2-functional-test-module-quote": "100.0.0-dev", - "magento/magento2-functional-test-module-reports": "100.0.0-dev", - "magento/magento2-functional-test-module-require-js": "100.0.0-dev", - "magento/magento2-functional-test-module-review": "100.0.0-dev", - "magento/magento2-functional-test-module-robots": "100.0.0-dev", - "magento/magento2-functional-test-module-rss": "100.0.0-dev", - "magento/magento2-functional-test-module-rule": "100.0.0-dev", - "magento/magento2-functional-test-module-sales": "100.0.0-dev", - "magento/magento2-functional-test-module-sales-inventory": "100.0.0-dev", - "magento/magento2-functional-test-module-sales-rule": "100.0.0-dev", - "magento/magento2-functional-test-module-sales-sequence": "100.0.0-dev", - "magento/magento2-functional-test-module-sample-data": "100.0.0-dev", - "magento/magento2-functional-test-module-search": "100.0.0-dev", - "magento/magento2-functional-test-module-security": "100.0.0-dev", - "magento/magento2-functional-test-module-send-friend": "100.0.0-dev", - "magento/magento2-functional-test-module-shipping": "100.0.0-dev", - "magento/magento2-functional-test-module-sitemap": "100.0.0-dev", - "magento/magento2-functional-test-module-store": "100.0.0-dev", - "magento/magento2-functional-test-module-swagger": "100.0.0-dev", - "magento/magento2-functional-test-module-swatches": "100.0.0-dev", - "magento/magento2-functional-test-module-swatches-layered-navigation": "100.0.0-dev", - "magento/magento2-functional-test-module-tax": "100.0.0-dev", - "magento/magento2-functional-test-module-tax-import-export": "100.0.0-dev", - "magento/magento2-functional-test-module-theme": "100.0.0-dev", - "magento/magento2-functional-test-module-translation": "100.0.0-dev", - "magento/magento2-functional-test-module-ui": "100.0.0-dev", - "magento/magento2-functional-test-module-ups": "100.0.0-dev", - "magento/magento2-functional-test-module-url-rewrite": "100.0.0-dev", - "magento/magento2-functional-test-module-user": "100.0.0-dev", - "magento/magento2-functional-test-module-usps": "100.0.0-dev", - "magento/magento2-functional-test-module-variable": "100.0.0-dev", - "magento/magento2-functional-test-module-vault": "100.0.0-dev", - "magento/magento2-functional-test-module-version": "100.0.0-dev", - "magento/magento2-functional-test-module-webapi": "100.0.0-dev", - "magento/magento2-functional-test-module-webapi-security": "100.0.0-dev", - "magento/magento2-functional-test-module-weee": "100.0.0-dev", - "magento/magento2-functional-test-module-widget": "100.0.0-dev", - "magento/magento2-functional-test-module-wishlist": "100.0.0-dev" - }, "autoload": { "psr-4": { "Magento\\": "tests/functional/Magento" diff --git a/dev/tests/acceptance/composer.lock b/dev/tests/acceptance/composer.lock index 0ebeeb018e7bd..29cfc59adce97 100644 --- a/dev/tests/acceptance/composer.lock +++ b/dev/tests/acceptance/composer.lock @@ -1641,11 +1641,11 @@ }, { "name": "magento/magento2-functional-testing-framework", - "version": "2.0.2", + "version": "2.0.3", "source": { "type": "git", "url": "git@github.com:magento/magento2-functional-testing-framework.git", - "reference": "4ecb0ae9e6ac43e56d8a93c44406ccf7accdc21d" + "reference": "22c803fc16024d417d920d03fdd95dea84779dd6" }, "require": { "codeception/codeception": "~2.3.4", @@ -1659,6 +1659,7 @@ "brainmaestro/composer-git-hooks": "^2.3", "codacy/coverage": "^1.4", "codeception/aspect-mock": "^2.0", + "goaop/framework": "2.1.2", "phpmd/phpmd": "^2.6.0", "rregeer/phpunit-coverage-check": "^0.1.4", "sebastian/phpcpd": "~3.0", diff --git a/dev/tests/acceptance/tests/_data/magento-again.jpg b/dev/tests/acceptance/tests/_data/magento-again.jpg new file mode 100644 index 0000000000000..c377daf8fb0b3 Binary files /dev/null and b/dev/tests/acceptance/tests/_data/magento-again.jpg differ diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Analytics/Test/AdminConfigurationEnableDisableAnalyticsCest.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Analytics/Test/AdminConfigurationEnableDisableAnalyticsCest.xml index 3380f6e771c05..c7ca8b799d243 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Analytics/Test/AdminConfigurationEnableDisableAnalyticsCest.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Analytics/Test/AdminConfigurationEnableDisableAnalyticsCest.xml @@ -6,41 +6,39 @@ */ --> - - - - - - - <description value="An admin user can enable/disable Advanced Reporting."/> - <severity value="NORMAL"/> - <testCaseId value="MAGETWO-66465"/> - <group value="analytics"/> - </annotations> - <after> - <amOnPage stepKey="amOnLogoutPage" url="admin/admin/auth/logout/"/> - </after> - <actionGroup ref="LoginActionGroup" stepKey="loginAsAdmin"/> - <!--Goto admin stores configure page --> - <amOnPage stepKey="amOnAdminConfig" url="{{AdminConfigPage.url}}"/> - <!--Enable Advanced Reporting--> - <click stepKey="clickAdvancedReportingConfigMenu" selector="{{AdminConfigSection.advancedReportingMenuItem}}"/> - <see stepKey="seeAdvancedReportingServiceLabel" selector="{{AdminConfigSection.advancedReportingServiceLabel}}" userInput="Advanced Reporting Service"/> - <selectOption stepKey="selectAdvancedReportingService" selector="{{AdminConfigSection.advancedReportingService}}" userInput="Enable"/> - <see stepKey="seeAdvancedReportingIndustryLabel" selector="{{AdminConfigSection.advancedReportingIndustryLabel}}" userInput="Industry"/> - <selectOption stepKey="selectAdvancedReportingIndustry" selector="{{AdminConfigSection.advancedReportingIndustry}}" userInput="Apps and Games"/> - <click stepKey="clickSaveConfigButton" selector="{{AdminConfigSection.saveButton}}"/> - <see stepKey="seeSaveConfigurationMessage" selector="{{AdminConfigSection.advancedReportingSuccessMessage}}" userInput="You saved the configuration."/> - <see stepKey="seeAdvancedReportingService" selector="{{AdminConfigSection.advancedReportingService}}" userInput="Enable"/> - <see stepKey="seeAdvancedReportingServiceStatus" selector="{{AdminConfigSection.advancedReportingServiceStatus}}" userInput="Subscription status: Pending"/> - <!--Disable Advanced Reporting--> - <see stepKey="seeAdvancedReportingServiceLabel" selector="{{AdminConfigSection.advancedReportingServiceLabel}}" userInput="Advanced Reporting Service"/> - <selectOption stepKey="selectAdvancedReportingService" selector="{{AdminConfigSection.advancedReportingService}}" userInput="Disable"/> - <click stepKey="clickSaveConfigButton" selector="{{AdminConfigSection.saveButton}}"/> - <see stepKey="seeSaveConfigurationMessage" selector="{{AdminConfigSection.advancedReportingSuccessMessage}}" userInput="You saved the configuration."/> - <see stepKey="seeAdvancedReportingService" selector="{{AdminConfigSection.advancedReportingService}}" userInput="Disable"/> - <see stepKey="seeAdvancedReportingServiceStatus" selector="{{AdminConfigSection.advancedReportingServiceStatus}}" userInput="Subscription status: Disabled"/> - - </test> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd"> + <test name="EnableDisableAdvancedReporting"> + <annotations> + <features value="Analytics"/> + <stories value="Enable/disable Advanced Reporting"/> + <title value="Enable Disable Advanced Reporting"/> + <description value="An admin user can enable/disable Advanced Reporting."/> + <severity value="NORMAL"/> + <testCaseId value="MAGETWO-66465"/> + <group value="analytics"/> + </annotations> + <after> + <amOnPage stepKey="amOnLogoutPage" url="admin/admin/auth/logout/"/> + </after> + <actionGroup ref="LoginActionGroup" stepKey="loginAsAdmin"/> + <!--Goto admin stores configure page --> + <amOnPage stepKey="amOnAdminConfig" url="{{AdminConfigPage.url}}"/> + <!--Enable Advanced Reporting--> + <click stepKey="clickAdvancedReportingConfigMenu" selector="{{AdminConfigSection.advancedReportingMenuItem}}"/> + <see stepKey="seeAdvancedReportingServiceLabelEnabled" selector="{{AdminConfigSection.advancedReportingServiceLabel}}" userInput="Advanced Reporting Service"/> + <selectOption stepKey="selectAdvancedReportingServiceEnabled" selector="{{AdminConfigSection.advancedReportingService}}" userInput="Enable"/> + <see stepKey="seeAdvancedReportingIndustryLabel" selector="{{AdminConfigSection.advancedReportingIndustryLabel}}" userInput="Industry"/> + <selectOption stepKey="selectAdvancedReportingIndustry" selector="{{AdminConfigSection.advancedReportingIndustry}}" userInput="Apps and Games"/> + <click stepKey="clickSaveConfigButtonEnabled" selector="{{AdminConfigSection.saveButton}}"/> + <see stepKey="seeSaveConfigurationMessageEnabled" selector="{{AdminConfigSection.advancedReportingSuccessMessage}}" userInput="You saved the configuration."/> + <see stepKey="seeAdvancedReportingServiceEnabled" selector="{{AdminConfigSection.advancedReportingService}}" userInput="Enable"/> + <see stepKey="seeAdvancedReportingServiceStatusEnabled" selector="{{AdminConfigSection.advancedReportingServiceStatus}}" userInput="Subscription status: Pending"/> + <!--Disable Advanced Reporting--> + <see stepKey="seeAdvancedReportingServiceLabelDisabled" selector="{{AdminConfigSection.advancedReportingServiceLabel}}" userInput="Advanced Reporting Service"/> + <selectOption stepKey="selectAdvancedReportingServiceDisabled" selector="{{AdminConfigSection.advancedReportingService}}" userInput="Disable"/> + <click stepKey="clickSaveConfigButtonDisabled" selector="{{AdminConfigSection.saveButton}}"/> + <see stepKey="seeSaveConfigurationMessageDisabled" selector="{{AdminConfigSection.advancedReportingSuccessMessage}}" userInput="You saved the configuration."/> + <see stepKey="seeAdvancedReportingServiceDisabled" selector="{{AdminConfigSection.advancedReportingService}}" userInput="Disable"/> + <see stepKey="seeAdvancedReportingServiceStatusDisabled" selector="{{AdminConfigSection.advancedReportingServiceStatus}}" userInput="Subscription status: Disabled"/> + </test> </tests> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Analytics/Test/AdminConfigurationPermissionCest.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Analytics/Test/AdminConfigurationPermissionCest.xml index b0c3754b0527c..c5f070dd4cadb 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Analytics/Test/AdminConfigurationPermissionCest.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Analytics/Test/AdminConfigurationPermissionCest.xml @@ -55,7 +55,7 @@ <fillField stepKey="fillUsernameNoReport" selector="{{AdminLoginFormSection.username}}" userInput="$$noReportUser.username$$"/> <fillField stepKey="fillPasswordNoReport" selector="{{AdminLoginFormSection.password}}" userInput="$$noReportUser.password$$"/> <click stepKey="clickOnSignIn2" selector="{{AdminLoginFormSection.signIn}}"/> - <waitForPageLoad stepKey="wait3" time="10"/> + <waitForPageLoad stepKey="wait5" time="10"/> <amOnPage stepKey="amOnAdminConfig2" url="{{AdminConfigPage.url}}"/> <dontSee stepKey="dontSeeAdvancedReportingConfigMenuItem" selector="{{AdminConfigSection.advancedReportingMenuItem}}" userInput="Advanced Reporting"/> </test> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/ActionGroup/AdminCategoryActionGroup.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/ActionGroup/AdminCategoryActionGroup.xml index 8d87d768e1545..c8c062c7ae7f9 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/ActionGroup/AdminCategoryActionGroup.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/ActionGroup/AdminCategoryActionGroup.xml @@ -64,4 +64,15 @@ <seeInCurrentUrl url="{{AdminCategoryPage.url}}add" stepKey="seeBackOnCreateCategoryPage"/> <see selector="{{AdminCategoryBasicFieldSection.FieldError('uid')}}" userInput="This is a required field." stepKey="seeErrorMessage"/> </actionGroup> -</actionGroups> \ No newline at end of file + + <actionGroup name="navigateToCreatedCategory"> + <arguments> + <argument name="Category"/> + </arguments> + <amOnPage url="{{AdminCategoryPage.page}}" stepKey="amOnCategoryPage"/> + <waitForPageLoad stepKey="waitForPageLoad2"/> + <click selector="{{AdminCategorySidebarTreeSection.categoryInTree(Category.Name)}}" stepKey="navigateToCreatedCategory" /> + <waitForPageLoad stepKey="waitForPageLoad2"/> + <waitForLoadingMaskToDisappear stepKey="waitForSpinner" /> + </actionGroup> +</actionGroups> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Section/AdminCategoryBasicFieldSection.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Section/AdminCategoryBasicFieldSection.xml index 92d90c9b8a46c..e905bfd01c711 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Section/AdminCategoryBasicFieldSection.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Section/AdminCategoryBasicFieldSection.xml @@ -15,6 +15,11 @@ <element name="ContentTab" type="input" selector="input[name='name']"/> <element name="FieldError" type="text" selector=".admin__field-error[data-bind='attr: {for: {{field}}}, text: error']" parameterized="true"/> </section> + <section name="CategoryContentSection"> + <element name="SelectFromGalleryBtn" type="button" selector="//label[text()='Select from Gallery']"/> + <element name="ImagePlaceHolder" type="button" selector=".file-uploader-summary.product-image-wrapper"/> + <element name="Upload" type="button" selector=".file-uploader-area input"/> + </section> <section name="CatalogWYSIWYGSection"> <element name="ShowHideBtn" type="button" selector="#togglecategory_form_description"/> <element name="TinyMCE4" type="text" selector=".mce-branding-powered-by"/> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/AdminAddImageToWYSIWYGCatalogCest.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/AdminAddImageToWYSIWYGCatalogCest.xml index 62adf4573999b..77f85a2522c09 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/AdminAddImageToWYSIWYGCatalogCest.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/AdminAddImageToWYSIWYGCatalogCest.xml @@ -31,42 +31,20 @@ <waitForElementVisible selector="{{CatalogWYSIWYGSection.TinyMCE4}}" stepKey="waitForTinyMCE4" /> <click selector="{{CatalogWYSIWYGSection.InsertImageIcon}}" stepKey="clickInsertImageIcon" /> <waitForPageLoad stepKey="waitForPageLoad" /> - <click selector="{{CatalogWYSIWYGSection.Browse}}" stepKey="clickBrowse" /> - <waitForPageLoad stepKey="waitForPageLoad1" /> - <waitForLoadingMaskToDisappear stepKey="waitForLoading1" /> - <waitForLoadingMaskToDisappear stepKey="waitForLoading2" /> - <see selector="{{CatalogWYSIWYGSection.CancelBtn}}" userInput="Cancel" stepKey="seeCancelBtn" /> - <see selector="{{CatalogWYSIWYGSection.CreateFolder}}" userInput="Create Folder" stepKey="seeCreateFolderBtn" /> - <see selector="{{CatalogWYSIWYGSection.InsertFile}}" userInput="Add Selected" stepKey="seeAddSelectedBtn" /> - <click selector="{{CatalogWYSIWYGSection.CreateFolder}}" stepKey="createFolder"/> - <waitForElementVisible selector="{{CatalogWYSIWYGSection.FolderName}}" stepKey="waitForPopUp" /> - <fillField selector="{{CatalogWYSIWYGSection.FolderName}}" userInput="{{ImageFolder.name}}" stepKey="fillFolderName" /> - <click selector="{{CatalogWYSIWYGSection.AcceptFolderName}}" stepKey="acceptFolderName" /> - <waitForLoadingMaskToDisappear stepKey="waitForLoading3" /> - <conditionalClick selector="{{CatalogWYSIWYGSection.StorageRootArrow}}" dependentSelector="{{CatalogWYSIWYGSection.checkIfArrowExpand}}" stepKey="clickArrowIfCloses" visible="true"/> - <waitForText userInput="{{ImageFolder.name}}" stepKey="waitForNewFolder" /> - <click userInput="{{ImageFolder.name}}" stepKey="clickOnCreatedFolder" /> - <waitForLoadingMaskToDisappear stepKey="waitForLoading5" /> - <attachFile selector="{{CatalogWYSIWYGSection.BrowseUploadImage}}" userInput="{{ImageUpload.file}}" stepKey="uploadImage1"/> - <waitForLoadingMaskToDisappear stepKey="waitForLoading6" /> - <waitForElementVisible selector="{{CatalogWYSIWYGSection.image(ImageUpload.file)}}" stepKey="waitForUploadImage1" /> - <seeElement selector="{{CatalogWYSIWYGSection.imageSelected(ImageUpload.file)}}" stepKey="seeImageSelected" /> - <see selector="{{CatalogWYSIWYGSection.DeleteSelectedBtn}}" userInput="Delete Selected" stepKey="seeDeleteBtn"/> - <click selector="{{CatalogWYSIWYGSection.DeleteSelectedBtn}}" stepKey="clickDeleteSelected" /> - <waitForText userInput="OK" stepKey="waitForConfirm" /> - <click selector="{{CatalogWYSIWYGSection.confirmDelete}}" stepKey="confirmDelete" /> - <waitForElementNotVisible selector="{{CatalogWYSIWYGSection.image(ImageUpload.file)}}" stepKey="waitForImageDeleted" /> - <dontSeeElement selector="{{CatalogWYSIWYGSection.image(ImageUpload.file)}}" stepKey="dontSeeImage" /> - <attachFile selector="{{CatalogWYSIWYGSection.BrowseUploadImage}}" userInput="{{ImageUpload.file}}" stepKey="uploadImage2"/> - <waitForLoadingMaskToDisappear stepKey="waitForLoading9" /> - <waitForElementVisible selector="{{CatalogWYSIWYGSection.image(ImageUpload.file)}}" stepKey="waitForUploadImage2" /> - <click selector="{{CatalogWYSIWYGSection.InsertFile}}" stepKey="clickInsertBtn" /> - <waitForLoadingMaskToDisappear stepKey="waitForLoading7" /> - <waitForElementVisible selector="{{CatalogWYSIWYGSection.OkBtn}}" stepKey="waitForOkBtn" /> - <fillField selector="{{CatalogWYSIWYGSection.ImageDescription}}" userInput="{{ImageUpload.content}}" stepKey="fillImageDescription" /> - <fillField selector="{{CatalogWYSIWYGSection.Height}}" userInput="{{ImageUpload.height}}" stepKey="fillImageHeight" /> - <click selector="{{CatalogWYSIWYGSection.OkBtn}}" stepKey="clickOkBtn" /> - <waitForPageLoad stepKey="wait3"/> + <actionGroup ref="clickBrowseBtnOnUploadPopup" stepKey="clickBrowserBtn"/> + <actionGroup ref="VerifyMediaGalleryStorageActions" stepKey="VerifyMediaGalleryStorageBtn"/> + <actionGroup ref="CreateImageFolder" stepKey="CreateImageFolder"> + <argument name="ImageFolder" value="ImageFolder"/> + </actionGroup> + <actionGroup ref="attachImage" stepKey="attachImage1"> + <argument name="Image" value="ImageUpload"/> + </actionGroup> + <actionGroup ref="deleteImage" stepKey="deleteImage"/> + <actionGroup ref="attachImage" stepKey="attachImage2"> + <argument name="Image" value="ImageUpload"/> + </actionGroup> + <actionGroup ref="saveImage" stepKey="insertImage"/> + <actionGroup ref="fillOutUploadImagePopup" stepKey="fillOutUploadImagePopup" /> <click selector="{{AdminCategoryMainActionsSection.SaveButton}}" stepKey="saveCatalog"/> <amOnPage url="/{{SimpleSubCategory.name_lwr}}.html" stepKey="goToCategoryFrontPage"/> <waitForPageLoad stepKey="waitForPageLoad2"/> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/AdminAddImageToWYSIWYGProductCest.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/AdminAddImageToWYSIWYGProductCest.xml index f8e6aa33c96d8..572c535eabd54 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/AdminAddImageToWYSIWYGProductCest.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/AdminAddImageToWYSIWYGProductCest.xml @@ -48,9 +48,9 @@ <conditionalClick selector="{{ProductDescriptionWYSIWYGToolbarSection.StorageRootArrow}}" dependentSelector="{{ProductDescriptionWYSIWYGToolbarSection.checkIfArrowExpand}}" stepKey="clickArrowIfCloses1" visible="true"/> <waitForText userInput="{{ImageFolder.name}}" stepKey="waitForNewFolder1" /> <click userInput="{{ImageFolder.name}}" stepKey="clickOnCreatedFolder1" /> - <waitForLoadingMaskToDisappear stepKey="waitForLoading5" /> + <waitForLoadingMaskToDisappear stepKey="waitForLoading4" /> <attachFile selector="{{ProductDescriptionWYSIWYGToolbarSection.BrowseUploadImage}}" userInput="{{ImageUpload.file}}" stepKey="uploadImage1"/> - <waitForLoadingMaskToDisappear stepKey="waitForLoading6" /> + <waitForLoadingMaskToDisappear stepKey="waitForLoading5" /> <waitForElementVisible selector="{{ProductDescriptionWYSIWYGToolbarSection.image(ImageUpload.file)}}" stepKey="waitForUploadImage1" /> <seeElement selector="{{ProductDescriptionWYSIWYGToolbarSection.imageSelected(ImageUpload.file)}}" stepKey="seeImageSelected1" /> <see selector="{{ProductDescriptionWYSIWYGToolbarSection.DeleteSelectedBtn}}" userInput="Delete Selected" stepKey="seeDeleteBtn1"/> @@ -60,10 +60,10 @@ <waitForElementNotVisible selector="{{ProductDescriptionWYSIWYGToolbarSection.image(ImageUpload.file)}}" stepKey="waitForImageDeleted1" /> <dontSeeElement selector="{{ProductDescriptionWYSIWYGToolbarSection.image(ImageUpload.file)}}" stepKey="dontSeeImage1" /> <attachFile selector="{{ProductDescriptionWYSIWYGToolbarSection.BrowseUploadImage}}" userInput="{{ImageUpload.file}}" stepKey="uploadImage2"/> - <waitForLoadingMaskToDisappear stepKey="waitForLoading7" /> + <waitForLoadingMaskToDisappear stepKey="waitForLoading6" /> <waitForElementVisible selector="{{ProductDescriptionWYSIWYGToolbarSection.image(ImageUpload.file)}}" stepKey="waitForUploadImage2" /> <click selector="{{ProductDescriptionWYSIWYGToolbarSection.InsertFile}}" stepKey="clickInsertBtn1" /> - <waitForLoadingMaskToDisappear stepKey="waitForLoading8" /> + <waitForLoadingMaskToDisappear stepKey="waitForLoading7" /> <waitForElementVisible selector="{{ProductDescriptionWYSIWYGToolbarSection.OkBtn}}" stepKey="waitForOkBtn1" /> <fillField selector="{{ProductDescriptionWYSIWYGToolbarSection.ImageDescription}}" userInput="{{ImageUpload.content}}" stepKey="fillImageDescription1" /> <fillField selector="{{ProductDescriptionWYSIWYGToolbarSection.Height}}" userInput="{{ImageUpload.height}}" stepKey="fillImageHeight1" /> @@ -74,14 +74,13 @@ <waitForPageLoad stepKey="waitForPageLoad4" /> <click selector="{{ProductShortDescriptionWYSIWYGToolbarSection.Browse}}" stepKey="clickBrowse2" /> <waitForPageLoad stepKey="waitForPageLoad5" /> - <waitForLoadingMaskToDisappear stepKey="waitForLoading9" /> - <waitForLoadingMaskToDisappear stepKey="waitForLoading10" /> + <waitForLoadingMaskToDisappear stepKey="waitForLoading8" /> <see selector="{{ProductShortDescriptionWYSIWYGToolbarSection.CancelBtn}}" userInput="Cancel" stepKey="seeCancelBtn2" /> <see selector="{{ProductShortDescriptionWYSIWYGToolbarSection.CreateFolder}}" userInput="Create Folder" stepKey="seeCreateFolderBtn2" /> <see selector="{{ProductShortDescriptionWYSIWYGToolbarSection.InsertFile}}" userInput="Add Selected" stepKey="seeAddSelectedBtn2" /> <attachFile selector="{{ProductShortDescriptionWYSIWYGToolbarSection.BrowseUploadImage}}" userInput="{{ImageUpload1.file}}" stepKey="uploadImage3"/> <waitForElementVisible selector="{{ProductShortDescriptionWYSIWYGToolbarSection.image(ImageUpload1.file)}}" stepKey="waitForUploadImage3" /> - <waitForLoadingMaskToDisappear stepKey="waitForLoading13" /> + <waitForLoadingMaskToDisappear stepKey="waitForLoading9" /> <wait time="3" stepKey="waitMore" /> <waitForElement selector="{{ProductShortDescriptionWYSIWYGToolbarSection.DeleteSelectedBtn}}" stepKey="waitForDeletebtn" /> <see selector="{{ProductShortDescriptionWYSIWYGToolbarSection.DeleteSelectedBtn}}" userInput="Delete Selected" stepKey="seeDeleteBtn2"/> @@ -89,19 +88,19 @@ <waitForText userInput="OK" stepKey="waitForConfirm3" /> <click selector="{{ProductShortDescriptionWYSIWYGToolbarSection.confirmDelete}}" stepKey="confirmDelete2" /> <attachFile selector="{{ProductShortDescriptionWYSIWYGToolbarSection.BrowseUploadImage}}" userInput="{{ImageUpload1.file}}" stepKey="uploadImage4"/> - <waitForLoadingMaskToDisappear stepKey="waitForLoading14" /> + <waitForLoadingMaskToDisappear stepKey="waitForLoading10" /> <waitForElementVisible selector="{{ProductShortDescriptionWYSIWYGToolbarSection.image(ImageUpload1.file)}}" stepKey="waitForUploadImage4" /> <click selector="{{ProductShortDescriptionWYSIWYGToolbarSection.InsertFile}}" stepKey="clickInsertBtn" /> - <waitForLoadingMaskToDisappear stepKey="waitForLoading15" /> + <waitForLoadingMaskToDisappear stepKey="waitForLoading11" /> <waitForElementVisible selector="{{ProductShortDescriptionWYSIWYGToolbarSection.OkBtn}}" stepKey="waitForOkBtn2" /> <fillField selector="{{ProductShortDescriptionWYSIWYGToolbarSection.ImageDescription}}" userInput="{{ImageUpload1.content}}" stepKey="fillImageDescription2" /> <fillField selector="{{ProductShortDescriptionWYSIWYGToolbarSection.Height}}" userInput="{{ImageUpload1.height}}" stepKey="fillImageHeight2" /> <click selector="{{ProductShortDescriptionWYSIWYGToolbarSection.OkBtn}}" stepKey="clickOkBtn2" /> <waitForPageLoad stepKey="waitForPageLoad6"/> <click selector="{{AdminProductFormActionSection.saveButton}}" stepKey="saveProduct"/> - <waitForLoadingMaskToDisappear stepKey="waitForLoading13" /> + <waitForLoadingMaskToDisappear stepKey="waitForLoading12" /> <amOnPage url="{{_defaultProduct.name}}.html" stepKey="navigateToProductPage"/> - <waitForPageLoad stepKey="waitForPageLoad2"/> + <waitForPageLoad stepKey="waitForPageLoad7"/> <seeElement selector="{{StorefrontProductInfoMainSection.mediaDescription}}" stepKey="assertMediaDescription"/> <seeElement selector="{{StorefrontProductInfoMainSection.mediaShortDescription}}" stepKey="assertMediaShortDescription"/> <after> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/EndToEndB2CAdminTest.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/EndToEndB2CAdminTest.xml index 2feae54c43abe..981530993f067 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/EndToEndB2CAdminTest.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/EndToEndB2CAdminTest.xml @@ -16,6 +16,8 @@ <description value="Admin creates products, creates and manages categories, creates promotions, creates an order, processes an order, processes a return, uses admin grids"/> <severity value="CRITICAL"/> <testCaseId value="MAGETWO-87014"/> + <!-- Skipped; see MAGETWO-88218 --> + <group value="skip"/> </annotations> <before> <!--Login to Admin Area--> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/VerifyDefaultWYSIWYGToolbarOnProductCest.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/VerifyDefaultWYSIWYGToolbarOnProductCest.xml index 7b0b4e95dd4e6..26852d17e6440 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/VerifyDefaultWYSIWYGToolbarOnProductCest.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/VerifyDefaultWYSIWYGToolbarOnProductCest.xml @@ -80,7 +80,7 @@ <seeElement selector="{{ProductShortDescriptionWYSIWYGToolbarSection.InsertLink}}" stepKey="assertInfo25"/> <seeElement selector="{{ProductShortDescriptionWYSIWYGToolbarSection.InsertImageIcon}}" stepKey="assertInfo26"/> <seeElement selector="{{ProductShortDescriptionWYSIWYGToolbarSection.InsertTable}}" stepKey="assertInfo27"/> - <seeElement selector="{{ProductShortDescriptionWYSIWYGToolbarSection.SpecialCharacter}}" stepKey="assertInfo27"/> + <seeElement selector="{{ProductShortDescriptionWYSIWYGToolbarSection.SpecialCharacter}}" stepKey="assertInfo28"/> <after> <actionGroup ref="DisabledWYSIWYG" stepKey="disableWYSIWYG"/> <actionGroup ref="logout" stepKey="logout"/> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/ActionGroup/AssignBlockToCMSPageActionGroup.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/ActionGroup/AssignBlockToCMSPageActionGroup.xml new file mode 100644 index 0000000000000..5c787549ab9d0 --- /dev/null +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/ActionGroup/AssignBlockToCMSPageActionGroup.xml @@ -0,0 +1,50 @@ +<?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="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AssignBlockToCMSPage"> + <arguments> + <argument name="Block" defaultValue=""/> + <argument name="CmsPage" defaultValue=""/> + </arguments> + <amOnPage url="{{CmsPagesPage.url}}" stepKey="amOnEditPage"/> + <waitForPageLoad stepKey="waitForPageLoad1"/> + <conditionalClick selector="{{CmsPagesPageActionsSection.clearAll}}" dependentSelector="{{CmsPagesPageActionsSection.activeFilters}}" stepKey="clickToResetFilter" visible="true"/> + <waitForPageLoad stepKey="waitForGridReload"/> + <conditionalClick selector="//div[contains(@data-role, 'grid-wrapper')]/table/thead/tr/th/span[contains(text(), 'ID')]" dependentSelector="//span[contains(text(), 'ID')]/parent::th[not(contains(@class, '_descend'))]/parent::tr/parent::thead/parent::table/parent::div[contains(@data-role, 'grid-wrapper')]" stepKey="clickToAttemptSortByIdDescending1" visible="true"/> + <waitForLoadingMaskToDisappear stepKey="waitForFirstIdSortDescendingToFinish1" /> + <!-- Conditional Click again in case it goes from default state to ascending on first click --> + <conditionalClick selector="//div[contains(@data-role, 'grid-wrapper')]/table/thead/tr/th/span[contains(text(), 'ID')]" dependentSelector="//span[contains(text(), 'ID')]/parent::th[not(contains(@class, '_descend'))]/parent::tr/parent::thead/parent::table/parent::div[contains(@data-role, 'grid-wrapper')]" stepKey="secondClickToAttemptSortByIdDescending2" visible="true"/> + <waitForLoadingMaskToDisappear stepKey="waitForSecondIdSortDescendingToFinish1" /> + <waitForElementVisible selector="{{CmsPagesPageActionsSection.select(CmsPage.identifier)}}" stepKey="waitForCMSPageGrid" /> + <click selector="{{CmsPagesPageActionsSection.select(CmsPage.identifier)}}" stepKey="clickSelect" /> + <waitForElementVisible selector="{{CmsPagesPageActionsSection.edit(CmsPage.identifier)}}" stepKey="waitForEditLink" /> + <click selector="{{CmsPagesPageActionsSection.edit(CmsPage.identifier)}}" stepKey="clickEdit" /> + <waitForPageLoad stepKey="waitForPageLoad2" /> + <click selector="{{CmsNewPagePageContentSection.header}}" stepKey="clickContentTab" /> + <waitForElementVisible selector="{{TinyMCESection.TinyMCE4}}" stepKey="waitForTinyMCE4"/> + <seeElement selector="{{TinyMCESection.InsertWidgetIcon}}" stepKey="seeWidgetIcon" /> + <click selector="{{TinyMCESection.InsertWidgetIcon}}" stepKey="clickInsertWidgetIcon" /> + <waitForPageLoad stepKey="waitForPageLoad3" /> + <selectOption selector="{{WidgetSection.WidgetType}}" userInput="CMS Static Block" stepKey="selectCMSStaticBlock" /> + <waitForLoadingMaskToDisappear stepKey="waitForLoading1" /> + <selectOption selector="{{WidgetSection.WidgetTemplate}}" userInput="CMS Static Block Default Template" stepKey="selectTemplate" /> + <click selector="{{WidgetSection.BtnChooser}}" stepKey="clickSelectPageBtn" /> + <waitForLoadingMaskToDisappear stepKey="waitForLoading2" /> + <fillField selector="//input[@name='chooser_identifier']" userInput="{{Block.identifier}}" stepKey="fillBlockIdentifier"/> + <click selector="//div[@class='modal-inner-wrap']//button[@title='Search']" stepKey="clickSearchBtn" /> + <waitForLoadingMaskToDisappear stepKey="waitForSecondIdSortDescendingToFinish2" /> + <waitForElementVisible selector="{{WidgetSection.BlockPage(Block.identifier)}}" stepKey="waitForBlockTitle" /> + <click selector="{{WidgetSection.BlockPage(Block.identifier)}}" stepKey="selectPreCreateBlock" /> + <wait time="3" stepKey="wait1" /> + <click selector="{{WidgetSection.InsertWidget}}" stepKey="clickInsertWidgetBtn" /> + <waitForLoadingMaskToDisappear stepKey="waitForLoading3" /> + <waitForPageLoad stepKey="waitForPageLoad4" /> + <click selector="{{CmsNewPagePageActionsSection.savePage}}" stepKey="clickSavePage"/> + </actionGroup> +</actionGroups> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/ActionGroup/CMSActionGroup.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/ActionGroup/CMSActionGroup.xml new file mode 100644 index 0000000000000..c7df21c09c1d6 --- /dev/null +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/ActionGroup/CMSActionGroup.xml @@ -0,0 +1,45 @@ +<?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="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Test/etc/actionGroupSchema.xsd"> + <actionGroup name="navigateToCreatedCMSPage"> + <arguments> + <argument name="CMSPage" defaultValue=""/> + </arguments> + <amOnPage url="{{CmsPagesPage.url}}" stepKey="navigateToCMSPagesGrid"/> + <waitForPageLoad stepKey="waitForPageLoad1"/> + <conditionalClick selector="{{CmsPagesPageActionsSection.clearAll}}" dependentSelector="{{CmsPagesPageActionsSection.activeFilters}}" stepKey="clickToResetFilter" visible="true"/> + <waitForPageLoad stepKey="waitForPageLoad2"/> + <conditionalClick selector="//div[contains(@data-role, 'grid-wrapper')]/table/thead/tr/th/span[contains(text(), 'ID')]" dependentSelector="//span[contains(text(), 'ID')]/parent::th[not(contains(@class, '_descend'))]/parent::tr/parent::thead/parent::table/parent::div[contains(@data-role, 'grid-wrapper')]" stepKey="clickToAttemptSortByIdDescending" visible="true"/> + <waitForLoadingMaskToDisappear stepKey="waitForFirstIdSortDescendingToFinish" /> + <!-- Conditional Click again in case it goes from default state to ascending on first click --> + <conditionalClick selector="//div[contains(@data-role, 'grid-wrapper')]/table/thead/tr/th/span[contains(text(), 'ID')]" dependentSelector="//span[contains(text(), 'ID')]/parent::th[not(contains(@class, '_descend'))]/parent::tr/parent::thead/parent::table/parent::div[contains(@data-role, 'grid-wrapper')]" stepKey="secondClickToAttemptSortByIdDescending" visible="true"/> + <waitForLoadingMaskToDisappear stepKey="waitForSecondIdSortDescendingToFinish" /> + <click selector="{{CmsPagesPageActionsSection.select(CMSPage.identifier)}}" stepKey="clickSelectCreatedCMSPage" /> + <click selector="{{CmsPagesPageActionsSection.edit(CMSPage.identifier)}}" stepKey="navigateToCreatedCMSPage" /> + <waitForPageLoad stepKey="waitForPageLoad3"/> + <click selector="{{CmsNewPagePageContentSection.header}}" stepKey="clickExpandContentTabForPage"/> + <waitForLoadingMaskToDisappear stepKey="waitForLoadingMaskOfStagingSection" /> + </actionGroup> + <actionGroup name="navigateToCreatedCMSBlockPage"> + <arguments> + <argument name="CMSBlockPage" defaultValue=""/> + </arguments> + <amOnPage url="{{CmsBlocksPage.url}}" stepKey="navigateToCMSBlocksGrid"/> + <waitForPageLoad stepKey="waitForPageLoad1"/> + <conditionalClick selector="{{BlockPageActionsSection.idColumn}}" dependentSelector="//span[contains(text(), 'ID')]/parent::th[not(contains(@class, '_descend'))]/parent::tr/parent::thead/parent::table/parent::div[contains(@data-role, 'grid-wrapper')]" stepKey="clickToAttemptSortByIdDescending" visible="true"/> + <waitForLoadingMaskToDisappear stepKey="waitForFirstIdSortDescendingToFinish" /> + <!-- Conditional Click again in case it goes from default state to ascending on first click --> + <conditionalClick selector="{{BlockPageActionsSection.idColumn}}" dependentSelector="//span[contains(text(), 'ID')]/parent::th[not(contains(@class, '_descend'))]/parent::tr/parent::thead/parent::table/parent::div[contains(@data-role, 'grid-wrapper')]" stepKey="secondClickToAttemptSortByIdDescending" visible="true"/> + <waitForLoadingMaskToDisappear stepKey="waitForSecondIdSortDescendingToFinish" /> + <click selector="{{BlockPageActionsSection.select(CMSBlockPage.identifier)}}" stepKey="clickSelectCreatedCMSBlock" /> + <click selector="{{BlockPageActionsSection.edit(CMSBlockPage.identifier)}}" stepKey="navigateToCreatedCMSBlock" /> + <waitForPageLoad stepKey="waitForPageLoad2"/> + <waitForLoadingMaskToDisappear stepKey="waitForLoadingMaskOfStagingSection" /> + </actionGroup> +</actionGroups> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/ActionGroup/SelectImageFromMediaStorageActionGroup.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/ActionGroup/SelectImageFromMediaStorageActionGroup.xml new file mode 100644 index 0000000000000..3fcc2ae8337d0 --- /dev/null +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/ActionGroup/SelectImageFromMediaStorageActionGroup.xml @@ -0,0 +1,72 @@ +<?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="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Test/etc/actionGroupSchema.xsd"> + <actionGroup name="clickBrowseBtnOnUploadPopup"> + <click selector="{{MediaGallerySection.Browse}}" stepKey="clickBrowse" /> + <waitForPageLoad stepKey="waitForPageLoad1" /> + </actionGroup> + <actionGroup name="VerifyMediaGalleryStorageActions"> + <waitForPageLoad stepKey="waitForPageLoad1" /> + <waitForLoadingMaskToDisappear stepKey="waitForLoading1" /> + <waitForLoadingMaskToDisappear stepKey="waitForLoading2" /> + <see selector="{{MediaGallerySection.CancelBtn}}" userInput="Cancel" stepKey="seeCancelBtn" /> + <see selector="{{MediaGallerySection.CreateFolder}}" userInput="Create Folder" stepKey="seeCreateFolderBtn" /> + <see selector="{{MediaGallerySection.InsertFile}}" userInput="Add Selected" stepKey="seeAddSelectedBtn" /> + </actionGroup> + <actionGroup name="CreateImageFolder"> + <arguments> + <argument name="ImageFolder" defaultValue="ImageFolder"/> + </arguments> + <click selector="{{MediaGallerySection.CreateFolder}}" stepKey="createFolder"/> + <waitForElementVisible selector="{{MediaGallerySection.FolderName}}" stepKey="waitForPopUp" /> + <fillField selector="{{MediaGallerySection.FolderName}}" userInput="{{ImageFolder.name}}" stepKey="fillFolderName" /> + <click selector="{{MediaGallerySection.AcceptFolderName}}" stepKey="acceptFolderName" /> + <waitForLoadingMaskToDisappear stepKey="waitForLoading3" /> + <conditionalClick selector="{{MediaGallerySection.StorageRootArrow}}" dependentSelector="{{MediaGallerySection.checkIfArrowExpand}}" stepKey="clickArrowIfCloses" visible="true"/> + <waitForText userInput="{{ImageFolder.name}}" stepKey="waitForNewFolder" /> + <click userInput="{{ImageFolder.name}}" stepKey="clickOnCreatedFolder" /> + <waitForLoadingMaskToDisappear stepKey="waitForLoading5" /> + </actionGroup> + <actionGroup name="attachImage"> + <arguments> + <argument name="Image" defaultValue=""/> + </arguments> + <attachFile selector="{{MediaGallerySection.BrowseUploadImage}}" userInput="{{Image.value}}" stepKey="uploadImage1"/> + <waitForLoadingMaskToDisappear stepKey="waitForLoading6" /> + <waitForElementVisible selector="{{MediaGallerySection.image(Image.value)}}" stepKey="waitForUploadImage1" /> + <seeElement selector="{{MediaGallerySection.imageSelected(Image.value)}}" stepKey="seeImageSelected" /> + </actionGroup> + <actionGroup name="deleteImage"> + <see selector="{{MediaGallerySection.DeleteSelectedBtn}}" userInput="Delete Selected" stepKey="seeDeleteBtn"/> + <click selector="{{MediaGallerySection.DeleteSelectedBtn}}" stepKey="clickDeleteSelected" /> + <waitForText userInput="OK" stepKey="waitForConfirm" /> + <click selector="{{MediaGallerySection.confirmDelete}}" stepKey="confirmDelete" /> + <waitForElementNotVisible selector="{{MediaGallerySection.image(ImageUpload.file)}}" stepKey="waitForImageDeleted" /> + <dontSeeElement selector="{{MediaGallerySection.image(ImageUpload.file)}}" stepKey="dontSeeImage" /> + </actionGroup> + <actionGroup name="saveImage"> + <click selector="{{MediaGallerySection.InsertFile}}" stepKey="clickInsertBtn" /> + <waitForPageLoad stepKey="waitForPageLoad2"/> + </actionGroup> + <actionGroup name="fillOutUploadImagePopup"> + <waitForElementVisible selector="{{MediaGallerySection.OkBtn}}" stepKey="waitForOkBtn" /> + <fillField selector="{{MediaGallerySection.ImageDescription}}" userInput="{{ImageUpload.content}}" stepKey="fillImageDescription" /> + <fillField selector="{{MediaGallerySection.Height}}" userInput="{{ImageUpload.height}}" stepKey="fillImageHeight" /> + <click selector="{{MediaGallerySection.OkBtn}}" stepKey="clickOkBtn" /> + <waitForPageLoad stepKey="wait3"/> + </actionGroup> + <actionGroup name="verifyOversizeValidationMsg"> + <see userInput="this is oversize" stepKey="seeValidationMsg"/> + <click selector="#OK" stepKey="clickOKBtn"/> + </actionGroup> + <actionGroup name="verifyWrongExtensionValidationMsg"> + <see userInput="this is wrong extension" stepKey="seeValidationMsg"/> + <click selector="#OK" stepKey="clickOKBtn"/> + </actionGroup> +</actionGroups> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Data/CmsPageData.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Data/CmsPageData.xml index a2619ec290708..71071706e96e9 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Data/CmsPageData.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Data/CmsPageData.xml @@ -7,7 +7,7 @@ --> <entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/DataGenerator/etc/dataProfileSchema.xsd"> + xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/DataGenerator/etc/dataProfileSchema.xsd"> <entity name="_defaultCmsPage" type="cms_page"> <data key="title">Test CMS Page</data> <data key="content_heading">Test Content Heading</data> @@ -26,6 +26,17 @@ <data key="file_type">Upload File</data> <data key="shareable">Yes</data> <data key="file">magento.jpg</data> + <data key="value">magento.jpg</data> + <data key="content">Image content. Yeah.</data> + <data key="height">1000</data> + </entity> + <entity name="ImageUpload_1" type="uploadImage"> + <data key="title" unique="suffix">Image1</data> + <data key="price">1.00</data> + <data key="file_type">Upload File</data> + <data key="shareable">Yes</data> + <data key="file">magento-again.jpg</data> + <data key="value">magento-again.jpg</data> <data key="content">Image content. Yeah.</data> <data key="height">1000</data> </entity> @@ -35,6 +46,7 @@ <data key="file_type">Upload File</data> <data key="shareable">Yes</data> <data key="file">magento2.jpg</data> + <data key="value">magento2.jpg</data> <data key="content">Image content. Yeah.</data> <data key="height">1000</data> </entity> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Page/BlockPage.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Page/CmsBlocksPage.xml similarity index 52% rename from dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Page/BlockPage.xml rename to dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Page/CmsBlocksPage.xml index c9715d766ac96..e2db4ced8c4d0 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Page/BlockPage.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Page/CmsBlocksPage.xml @@ -7,8 +7,8 @@ --> <pages xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Page/etc/PageObject.xsd"> - <page name="BlocksPage" url="cms/block/new/" area="admin" module="Magento_Block"> + xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Page/etc/PageObject.xsd"> + <page name="CmsBlocksPage" url="/cms/block/" area="admin" module="Magento_Cms"> <section name="BlockPageActionsSection"/> </page> </pages> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Section/BlockNewPageActionsSection.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Section/BlockNewPageActionsSection.xml index 7dce25478979f..b196bee7981c5 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Section/BlockNewPageActionsSection.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Section/BlockNewPageActionsSection.xml @@ -10,5 +10,6 @@ xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Page/etc/SectionObject.xsd"> <section name="BlockNewPagePageActionsSection"> <element name="saveBlock" type="button" selector="#save" timeout="30"/> + <element name="saveAndContinueEdit" type="button" selector="#save_and_continue"/> </section> </sections> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Section/BlockPageActionsSection.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Section/BlockPageActionsSection.xml index 498de3b667f5c..4d69570e5994e 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Section/BlockPageActionsSection.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Section/BlockPageActionsSection.xml @@ -10,5 +10,10 @@ xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Page/etc/SectionObject.xsd"> <section name="BlockPageActionsSection"> <element name="addNewBlock" type="button" selector="#add" timeout="30"/> + <element name="select" type="button" selector="//div[text()='{{var1}}']//parent::td//following-sibling::td//button[text()='Select']" parameterized="true"/> + <element name="edit" type="button" selector="//div[text()='{{var1}}']//parent::td//following-sibling::td//a[text()='Edit']" parameterized="true"/> + <element name="idColumn" type="button" selector="//div[contains(@data-role, 'grid-wrapper')]/table/thead/tr/th/span[contains(text(), 'ID')]"/> + <element name="clearAll" type="button" selector="//div[@class='admin__data-grid-header']//button[contains(text(), 'Clear all')]"/> + <element name="activeFilters" type="button" selector="//div[@class='admin__data-grid-header']//span[contains(text(), 'Active filters:')]" /> </section> </sections> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Section/CmsNewPagePageActionsSection.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Section/CmsNewPagePageActionsSection.xml index d888debead363..68242033d8c18 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Section/CmsNewPagePageActionsSection.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Section/CmsNewPagePageActionsSection.xml @@ -10,5 +10,6 @@ xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Page/etc/SectionObject.xsd"> <section name="CmsNewPagePageActionsSection"> <element name="savePage" type="button" selector="#save" timeout="30"/> + <element name="saveAndContinueEdit" type="button" selector="#save_and_continue" timeout="30"/> </section> </sections> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Section/CmsNewPagePageContentSection.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Section/CmsNewPagePageContentSection.xml index addc466c4b026..4e794aa412e1b 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Section/CmsNewPagePageContentSection.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Section/CmsNewPagePageContentSection.xml @@ -12,6 +12,7 @@ <element name="header" type="button" selector="div[data-index=content]"/> <element name="contentHeading" type="input" selector="input[name=content_heading]"/> <element name="content" type="input" selector="#cms_page_form_content"/> + <element name="TextArea" type="text" selector="#text_form_content"/> </section> <section name="CmsWYSIWYGSection"> <element name="CheckIfTabExpand" type="button" selector="//div[@data-state-collapsible='closed']//span[text()='Content']"/> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Section/CmsPagesPageActionsSection.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Section/CmsPagesPageActionsSection.xml index 5e6ca7a193613..c302a029792e9 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Section/CmsPagesPageActionsSection.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Section/CmsPagesPageActionsSection.xml @@ -18,5 +18,7 @@ <element name="select" type="button" selector="//div[text()='{{var1}}']/parent::td//following-sibling::td[@class='data-grid-actions-cell']//button[text()='Select']" parameterized="true"/> <element name="edit" type="button" selector="//div[text()='{{var1}}']/parent::td//following-sibling::td[@class='data-grid-actions-cell']//a[text()='Edit']" parameterized="true"/> <element name="preview" type="button" selector="//div[text()='{{var1}}']/parent::td//following-sibling::td[@class='data-grid-actions-cell']//a[text()='Preview']" parameterized="true"/> + <element name="clearAll" type="button" selector="//div[@class='admin__data-grid-header']//button[contains(text(), 'Clear all')]"/> + <element name="activeFilters" type="button" selector="//div[@class='admin__data-grid-header']//span[contains(text(), 'Active filters:')]" /> </section> </sections> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Test/AdminAddImageToWYSIWYGBlockCest.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Test/AdminAddImageToWYSIWYGBlockCest.xml index f01d4fdfa472d..d03ed796c4be3 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Test/AdminAddImageToWYSIWYGBlockCest.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Test/AdminAddImageToWYSIWYGBlockCest.xml @@ -23,7 +23,7 @@ <actionGroup ref="EnabledWYSIWYG" stepKey="enableWYSIWYG"/> <actionGroup ref="SwitchToVersion4ActionGroup" stepKey="switchToTinyMCE4" /> </before> - <amOnPage url="{{BlocksPage.url}}" stepKey="amOnNewBlockPage"/> + <amOnPage url="{{CmsNewBlock.url}}" stepKey="amOnNewBlockPage"/> <waitForPageLoad stepKey="waitForPageLoad1"/> <fillField selector="{{BlockNewPageBasicFieldsSection.blockTitle}}" userInput="{{_defaultBlock.title}}" stepKey="fillFieldTitle1"/> <fillField selector="{{BlockNewPageBasicFieldsSection.identifier}}" userInput="{{_defaultBlock.identifier}}" stepKey="fillFieldIdentifier"/> @@ -31,52 +31,29 @@ <waitForElementVisible selector="{{TinyMCESection.TinyMCE4}}" stepKey="waitForTinyMCE" /> <click selector="{{TinyMCESection.InsertImageIcon}}" stepKey="clickInsertImageIcon" /> <waitForPageLoad stepKey="waitForPageLoad2" /> - <click selector="{{MediaGallerySection.Browse}}" stepKey="clickBrowse" /> - <waitForPageLoad stepKey="waitForPageLoad3" /> - <waitForLoadingMaskToDisappear stepKey="waitForLoading1" /> - <waitForLoadingMaskToDisappear stepKey="waitForLoading2" /> - <waitForElement selector="{{MediaGallerySection.CancelBtn}}" stepKey="waitForContent" /> - <see selector="{{MediaGallerySection.CancelBtn}}" userInput="Cancel" stepKey="seeCancelBtn" /> - <see selector="{{MediaGallerySection.CreateFolder}}" userInput="Create Folder" stepKey="seeCreateFolderBtn" /> - <see selector="{{MediaGallerySection.InsertFile}}" userInput="Add Selected" stepKey="seeAddSelectedBtn" /> - <click selector="{{MediaGallerySection.CreateFolder}}" stepKey="createFolder"/> - <waitForElementVisible selector="{{MediaGallerySection.FolderName}}" stepKey="waitForPopUp" /> - <fillField selector="{{MediaGallerySection.FolderName}}" userInput="{{ImageFolder.name}}" stepKey="fillFolderName" /> - <waitForElement selector="{{MediaGallerySection.AcceptFolderName}}" stepKey="waitForAcceptBtn" /> - <wait time="3" stepKey="wait"/> - <click selector="{{MediaGallerySection.AcceptFolderName}}" stepKey="acceptFolderName" /> - <waitForPageLoad stepKey="waitForPageLoad4" /> - <conditionalClick selector="{{MediaGallerySection.StorageRootArrow}}" dependentSelector="{{MediaGallerySection.checkIfArrowExpand}}" stepKey="clickArrowIfCloses" visible="true"/> - <waitForText userInput="{{ImageFolder.name}}" stepKey="waitForNewFolder" /> - <click userInput="{{ImageFolder.name}}" stepKey="clickOnCreatedFolder" /> - <waitForLoadingMaskToDisappear stepKey="waitForLoading3" /> - <attachFile selector="{{MediaGallerySection.BrowseUploadImage}}" userInput="{{ImageUpload.file}}" stepKey="uploadImage1"/> - <waitForLoadingMaskToDisappear stepKey="waitForLoading4" /> - <waitForElementVisible selector="{{MediaGallerySection.image(ImageUpload.file)}}" stepKey="waitForUploadImage1" /> - <seeElement selector="{{MediaGallerySection.imageSelected(ImageUpload.file)}}" stepKey="seeImageSelected" /> - <see selector="{{MediaGallerySection.DeleteSelectedBtn}}" userInput="Delete Selected" stepKey="seeDeleteBtn"/> - <click selector="{{MediaGallerySection.DeleteSelectedBtn}}" stepKey="clickDeleteSelected" /> - <waitForText userInput="OK" stepKey="waitForConfirm" /> - <click selector="{{MediaGallerySection.confirmDelete}}" stepKey="confirmDelete" /> - <waitForElementNotVisible selector="{{MediaGallerySection.image(ImageUpload.file)}}" stepKey="waitForImageDeleted" /> - <dontSeeElement selector="{{MediaGallerySection.image(ImageUpload.file)}}" stepKey="dontSeeImage" /> - <attachFile selector="{{MediaGallerySection.BrowseUploadImage}}" userInput="{{ImageUpload.file}}" stepKey="uploadImage2"/> - <waitForLoadingMaskToDisappear stepKey="waitForLoading5" /> - <waitForElementVisible selector="{{MediaGallerySection.image(ImageUpload.file)}}" stepKey="waitForUploadImage2" /> - <click selector="{{MediaGallerySection.InsertFile}}" stepKey="clickInsertBtn" /> - <waitForLoadingMaskToDisappear stepKey="waitForLoading6" /> - <waitForElementVisible selector="{{MediaGallerySection.OkBtn}}" stepKey="waitForOkBtn" /> - <fillField selector="{{MediaGallerySection.ImageDescription}}" userInput="{{ImageUpload.content}}" stepKey="fillImageDescription" /> - <fillField selector="{{MediaGallerySection.Height}}" userInput="{{ImageUpload.height}}" stepKey="fillImageHeight" /> - <click selector="{{MediaGallerySection.OkBtn}}" stepKey="clickOkBtn" /> - <waitForPageLoad stepKey="waitForPageLoad5"/> + <actionGroup ref="clickBrowseBtnOnUploadPopup" stepKey="clickBrowserBtn"/> + <actionGroup ref="VerifyMediaGalleryStorageActions" stepKey="VerifyMediaGalleryStorageBtn"/> + <actionGroup ref="CreateImageFolder" stepKey="CreateImageFolder"> + <argument name="ImageFolder" value="ImageFolder"/> + </actionGroup> + <actionGroup ref="attachImage" stepKey="attachImage1"> + <argument name="Image" value="ImageUpload"/> + </actionGroup> + <actionGroup ref="deleteImage" stepKey="deleteImage"/> + <actionGroup ref="attachImage" stepKey="attachImage2"> + <argument name="Image" value="ImageUpload"/> + </actionGroup> + <actionGroup ref="saveImage" stepKey="insertImage"/> + <actionGroup ref="fillOutUploadImagePopup" stepKey="fillOutUploadImagePopup" /> <click selector="{{BlockNewPagePageActionsSection.saveBlock}}" stepKey="clickSaveBlock"/> <amOnPage url="{{CmsPagesPage.url}}" stepKey="amOnEditPage"/> <waitForPageLoad stepKey="waitForPageLoad6"/> + <conditionalClick selector="{{CmsPagesPageActionsSection.clearAll}}" dependentSelector="{{CmsPagesPageActionsSection.activeFilters}}" stepKey="clickToResetFilter" visible="true"/> + <waitForPageLoad stepKey="waitForGridReload"/> <click selector="{{CmsPagesPageActionsSection.FilterBtn}}" stepKey="clickFiltersBtn" /> <fillField selector="{{CmsPagesPageActionsSection.URLKey}}" userInput="$$createCMSPage.identifier$$" stepKey="fillOutURLKey" /> <click selector="{{CmsPagesPageActionsSection.ApplyFiltersBtn}}" stepKey="clickApplyBtn" /> - <waitForLoadingMaskToDisappear stepKey="waitForLoading9" /> + <waitForLoadingMaskToDisappear stepKey="waitForLoading7" /> <actionGroup ref="SortByIdDescendingActionGroup" stepKey="sortByIdDescending" /> <waitForElementVisible selector="{{CmsPagesPageActionsSection.select('$$createCMSPage.identifier$$')}}" stepKey="waitForCMSPageGrid" /> <click selector="{{CmsPagesPageActionsSection.select('$$createCMSPage.identifier$$')}}" stepKey="clickSelect" /> @@ -89,16 +66,16 @@ <click selector="{{TinyMCESection.InsertWidgetIcon}}" stepKey="clickInsertWidgetIcon" /> <waitForPageLoad stepKey="waitForPageLoad8" /> <selectOption selector="{{WidgetSection.WidgetType}}" userInput="CMS Static Block" stepKey="selectCMSStaticBlock" /> - <waitForLoadingMaskToDisappear stepKey="waitForLoading7" /> + <waitForLoadingMaskToDisappear stepKey="waitForLoading8" /> <selectOption selector="{{WidgetSection.WidgetTemplate}}" userInput="CMS Static Block Default Template" stepKey="selectTemplate" /> <click selector="{{WidgetSection.BtnChooser}}" stepKey="clickSelectPageBtn" /> - <waitForLoadingMaskToDisappear stepKey="waitForLoading8" /> + <waitForLoadingMaskToDisappear stepKey="waitForLoading9" /> <actionGroup ref="SortByIdDescendingActionGroup" stepKey="sortByIdDescending2" /> <waitForElementVisible selector="{{WidgetSection.BlockPage(_defaultBlock.identifier)}}" stepKey="waitForBlockTitle" /> <click selector="{{WidgetSection.BlockPage(_defaultBlock.identifier)}}" stepKey="selectPreCreateBlock" /> <wait time="3" stepKey="wait1" /> <click selector="{{WidgetSection.InsertWidget}}" stepKey="clickInsertWidgetBtn" /> - <waitForLoadingMaskToDisappear stepKey="waitForLoading9" /> + <waitForLoadingMaskToDisappear stepKey="waitForLoading10" /> <waitForPageLoad stepKey="waitForPageLoad9" /> <click selector="{{CmsNewPagePageActionsSection.savePage}}" stepKey="clickSavePage"/> <waitForPageLoad stepKey="waitForPageLoad10"/> @@ -108,6 +85,10 @@ <!--see image on Storefront--> <seeElement selector="{{StorefrontBlockSection.mediaDescription}}" stepKey="assertMediaDescription"/> <after> + <amOnPage url="{{CmsPagesPage.url}}" stepKey="amOnEditPage"/> + <waitForPageLoad stepKey="waitForPageLoad"/> + <conditionalClick selector="{{CmsPagesPageActionsSection.clearAll}}" dependentSelector="{{CmsPagesPageActionsSection.activeFilters}}" stepKey="clickToResetFilter" visible="true"/> + <waitForPageLoad stepKey="waitForGridReload"/> <deleteData createDataKey="createCMSPage" stepKey="deletePreReqCMSPage" /> <actionGroup ref="DisabledWYSIWYG" stepKey="disableWYSIWYG"/> <actionGroup ref="logout" stepKey="logout"/> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Test/AdminAddImageToWYSIWYGCMSCest.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Test/AdminAddImageToWYSIWYGCMSCest.xml index f490a221b311b..6ef5d561d1dd9 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Test/AdminAddImageToWYSIWYGCMSCest.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Test/AdminAddImageToWYSIWYGCMSCest.xml @@ -29,42 +29,21 @@ <waitForElementVisible selector="{{TinyMCESection.TinyMCE4}}" stepKey="waitForTinyMCE4" /> <click selector="{{TinyMCESection.InsertImageIcon}}" stepKey="clickInsertImageIcon" /> <waitForPageLoad stepKey="waitForPageLoad" /> - <click selector="{{MediaGallerySection.Browse}}" stepKey="clickBrowse" /> - <waitForPageLoad stepKey="waitForPageLoad1" /> - <waitForLoadingMaskToDisappear stepKey="waitForLoading1" /> - <waitForLoadingMaskToDisappear stepKey="waitForLoading2" /> - <see selector="{{MediaGallerySection.CancelBtn}}" userInput="Cancel" stepKey="seeCancelBtn" /> - <see selector="{{MediaGallerySection.CreateFolder}}" userInput="Create Folder" stepKey="seeCreateFolderBtn" /> - <see selector="{{MediaGallerySection.InsertFile}}" userInput="Add Selected" stepKey="seeAddSelectedBtn" /> - <click selector="{{MediaGallerySection.CreateFolder}}" stepKey="createFolder"/> - <waitForElementVisible selector="{{MediaGallerySection.FolderName}}" stepKey="waitForPopUp" /> - <fillField selector="{{MediaGallerySection.FolderName}}" userInput="{{ImageFolder.name}}" stepKey="fillFolderName" /> - <click selector="{{MediaGallerySection.AcceptFolderName}}" stepKey="acceptFolderName" /> - <waitForLoadingMaskToDisappear stepKey="waitForLoading3" /> - <conditionalClick selector="{{MediaGallerySection.StorageRootArrow}}" dependentSelector="{{MediaGallerySection.checkIfArrowExpand}}" stepKey="clickArrowIfCloses" visible="true"/> - <waitForText userInput="{{ImageFolder.name}}" stepKey="waitForNewFolder" /> - <click userInput="{{ImageFolder.name}}" stepKey="clickOnCreatedFolder" /> - <waitForLoadingMaskToDisappear stepKey="waitForLoading5" /> - <attachFile selector="{{MediaGallerySection.BrowseUploadImage}}" userInput="{{ImageUpload.file}}" stepKey="uploadImage1"/> - <waitForLoadingMaskToDisappear stepKey="waitForLoading6" /> - <waitForElementVisible selector="{{MediaGallerySection.image(ImageUpload.file)}}" stepKey="waitForUploadImage1" /> - <seeElement selector="{{MediaGallerySection.imageSelected(ImageUpload.file)}}" stepKey="seeImageSelected" /> - <see selector="{{MediaGallerySection.DeleteSelectedBtn}}" userInput="Delete Selected" stepKey="seeDeleteBtn"/> - <click selector="{{MediaGallerySection.DeleteSelectedBtn}}" stepKey="clickDeleteSelected" /> - <waitForText userInput="OK" stepKey="waitForConfirm" /> - <click selector="{{MediaGallerySection.confirmDelete}}" stepKey="confirmDelete" /> - <waitForElementNotVisible selector="{{MediaGallerySection.image(ImageUpload.file)}}" stepKey="waitForImageDeleted" /> - <dontSeeElement selector="{{MediaGallerySection.image(ImageUpload.file)}}" stepKey="dontSeeImage" /> - <attachFile selector="{{MediaGallerySection.BrowseUploadImage}}" userInput="{{ImageUpload.file}}" stepKey="uploadImage2"/> - <waitForLoadingMaskToDisappear stepKey="waitForLoading9" /> - <waitForElementVisible selector="{{MediaGallerySection.image(ImageUpload.file)}}" stepKey="waitForUploadImage2" /> - <click selector="{{MediaGallerySection.InsertFile}}" stepKey="clickInsertBtn" /> - <waitForLoadingMaskToDisappear stepKey="waitForLoading7" /> - <waitForElementVisible selector="{{MediaGallerySection.OkBtn}}" stepKey="waitForOkBtn" /> - <fillField selector="{{MediaGallerySection.ImageDescription}}" userInput="{{ImageUpload.content}}" stepKey="fillImageDescription" /> - <fillField selector="{{MediaGallerySection.Height}}" userInput="{{ImageUpload.height}}" stepKey="fillImageHeight" /> - <click selector="{{MediaGallerySection.OkBtn}}" stepKey="clickOkBtn" /> - <waitForPageLoad stepKey="wait3"/> + <actionGroup ref="clickBrowseBtnOnUploadPopup" stepKey="clickBrowserBtn"/> + <actionGroup ref="VerifyMediaGalleryStorageActions" stepKey="VerifyMediaGalleryStorageBtn"/> + <actionGroup ref="CreateImageFolder" stepKey="CreateImageFolder"> + <argument name="ImageFolder" value="ImageFolder"/> + </actionGroup> + <actionGroup ref="attachImage" stepKey="attachImage1"> + <argument name="Image" value="ImageUpload"/> + </actionGroup> + <actionGroup ref="deleteImage" stepKey="deleteImage"/> + + <actionGroup ref="attachImage" stepKey="attachImage2"> + <argument name="Image" value="ImageUpload"/> + </actionGroup> + <actionGroup ref="saveImage" stepKey="insertImage"/> + <actionGroup ref="fillOutUploadImagePopup" stepKey="fillOutUploadImagePopup" /> <click selector="{{CmsNewPagePageSeoSection.header}}" stepKey="clickExpandSearchEngineOptimisation"/> <fillField selector="{{CmsNewPagePageSeoSection.urlKey}}" userInput="{{_defaultCmsPage.identifier}}" stepKey="fillFieldUrlKey"/> <click selector="{{CmsNewPagePageActionsSection.savePage}}" stepKey="clickSavePage"/> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Test/AdminAddVariableToWYSIWYGBlockCest.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Test/AdminAddVariableToWYSIWYGBlockCest.xml index 5f92a5766a65c..b4cdf6fe44801 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Test/AdminAddVariableToWYSIWYGBlockCest.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Test/AdminAddVariableToWYSIWYGBlockCest.xml @@ -32,8 +32,8 @@ <fillField selector="{{StoreConfigSection.City}}" userInput="{{_defaultVariable.city}}" stepKey="fillCity" /> <click selector="{{StoreConfigSection.Save}}" stepKey="saveConfig"/> <!--Main test--> - <amOnPage url="{{BlocksPage.url}}" stepKey="amOnNewBlockPage"/> - <waitForPageLoad stepKey="waitForPageLoad2"/> + <amOnPage url="{{CmsNewBlock.url}}" stepKey="amOnNewBlockPage"/> + <waitForPageLoad stepKey="waitForGridToLoad"/> <fillField selector="{{BlockNewPageBasicFieldsSection.blockTitle}}" userInput="{{_defaultBlock.title}}" stepKey="fillFieldTitle1"/> <fillField selector="{{BlockNewPageBasicFieldsSection.identifier}}" userInput="{{_defaultBlock.identifier}}" stepKey="fillFieldIdentifier"/> <selectOption selector="{{BlockNewPageBasicFieldsSection.storeView}}" userInput="All Store View" stepKey="selectAllStoreView" /> @@ -78,6 +78,8 @@ <click selector="{{BlockNewPagePageActionsSection.saveBlock}}" stepKey="clickSaveBlock"/> <amOnPage url="{{CmsPagesPage.url}}" stepKey="amOnEditPage"/> <waitForPageLoad stepKey="waitForPageLoad7"/> + <conditionalClick selector="{{CmsPagesPageActionsSection.clearAll}}" dependentSelector="{{CmsPagesPageActionsSection.activeFilters}}" stepKey="clickToResetFilter1" visible="true"/> + <waitForPageLoad stepKey="waitForFilterReload"/> <click selector="{{CmsPagesPageActionsSection.FilterBtn}}" stepKey="clickFiltersBtn" /> <fillField selector="{{CmsPagesPageActionsSection.URLKey}}" userInput="$$createCMSPage.identifier$$" stepKey="fillOutURLKey" /> <click selector="{{CmsPagesPageActionsSection.ApplyFiltersBtn}}" stepKey="clickApplyBtn" /> @@ -109,6 +111,8 @@ <click selector="{{CmsNewPagePageActionsSection.savePage}}" stepKey="clickSavePage"/> <waitForPageLoad stepKey="waitForPageLoadAfterSaveCmsPage" /> <see userInput="You saved the page." stepKey="seeSuccessMessage"/> + <conditionalClick selector="{{BlockPageActionsSection.clearAll}}" dependentSelector="{{BlockPageActionsSection.activeFilters}}" stepKey="clickToResetFilter" visible="true"/> + <waitForPageLoad stepKey="waitForPageLoad2"/> <amOnPage url="$$createCMSPage.identifier$$" stepKey="amOnPageTestPage1"/> <waitForPageLoad stepKey="waitForPageLoad11" /> <!--see Default Variable on Storefront--> @@ -124,6 +128,10 @@ <!--see custom variable blank--> <dontSee userInput="{{customVariable.html}}" stepKey="dontSeeCustomVariableName" /> <after> + <amOnPage url="{{CmsPagesPage.url}}" stepKey="amOnEditPage"/> + <waitForPageLoad stepKey="waitForPageLoad2"/> + <conditionalClick selector="{{CmsPagesPageActionsSection.clearAll}}" dependentSelector="{{CmsPagesPageActionsSection.activeFilters}}" stepKey="clickToResetFilter" visible="true"/> + <waitForPageLoad stepKey="waitForGridReload"/> <deleteData createDataKey="createCMSPage" stepKey="deletePreReqCMSPage" /> <actionGroup ref="DisabledWYSIWYG" stepKey="disableWYSIWYG"/> <actionGroup ref="logout" stepKey="logout"/> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Test/AdminAddVariableToWYSIWYGCMSCest.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Test/AdminAddVariableToWYSIWYGCMSCest.xml index 23384f1c04a73..32aa574611b68 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Test/AdminAddVariableToWYSIWYGCMSCest.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Test/AdminAddVariableToWYSIWYGCMSCest.xml @@ -11,7 +11,7 @@ <annotations> <features value="MAGETWO-36659-[CMS] WYSIWYG update"/> <stories value="MAGETWO-42158-Variable with WYSIWYG "/> - <group value="Cms"/> + <group value="skip"/> <title value="Insert default Magento variable into content of WYSIWYG on CMS Pages"/> <description value="Insert default Magento variable into content of WYSIWYG on CMS Pages"/> <severity value="CRITICAL"/> @@ -86,8 +86,9 @@ <see userInput="{{customVariable.html}}" stepKey="seeCustomVariable2" /> <!--Delete Custom Variable--> <actionGroup ref="DeleteCustomVariableActionGroup" stepKey="deleteCustomVariable" /> + <actionGroup ref="ClearCacheActionGroup" stepKey="clearCache" /> <!--Refresh Storefront--> - <amOnPage url="{{_defaultCmsPage.identifier}}" stepKey="amOnPageTestPage"/> + <amOnPage url="{{_defaultCmsPage.identifier}}" stepKey="amOnPageTestPageRefresh"/> <waitForPageLoad stepKey="waitForPageLoad7" /> <!--see custom variable blank--> <dontSee userInput="{{customVariable.html}}" stepKey="dontSeeCustomVariableName" /> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Test/AdminAddWidgetToWYSIWYGBlockCest.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Test/AdminAddWidgetToWYSIWYGBlockCest.xml index e6963d5b9def4..d15bd4bc662cf 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Test/AdminAddWidgetToWYSIWYGBlockCest.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Test/AdminAddWidgetToWYSIWYGBlockCest.xml @@ -16,7 +16,6 @@ <description value="Admin should be able to add widget to WYSIWYG content Block"/> <severity value="CRITICAL"/> <testCaseId value="MAGETWO-84654"/> - <group value="skip" /> </annotations> <before> <createData entity="_defaultCmsPage" stepKey="createCMSPage" /> @@ -24,7 +23,7 @@ <actionGroup ref="EnabledWYSIWYG" stepKey="enableWYSIWYG"/> <actionGroup ref="SwitchToVersion4ActionGroup" stepKey="switchToTinyMCE4" /> </before> - <amOnPage url="{{BlocksPage.url}}" stepKey="amOnNewBlockPage"/> + <amOnPage url="{{CmsNewBlock.url}}" stepKey="amOnNewBlockPage"/> <waitForPageLoad stepKey="waitForPageLoad1"/> <fillField selector="{{BlockNewPageBasicFieldsSection.blockTitle}}" userInput="{{_defaultBlock.title}}" stepKey="fillFieldTitle"/> <fillField selector="{{BlockNewPageBasicFieldsSection.identifier}}" userInput="{{_defaultBlock.identifier}}" stepKey="fillFieldIdentifier"/> @@ -47,10 +46,12 @@ <click selector="{{BlockNewPagePageActionsSection.saveBlock}}" stepKey="clickSaveBlock"/> <amOnPage url="{{CmsPagesPage.url}}" stepKey="amOnEditPage"/> <waitForPageLoad stepKey="waitForPageLoad3"/> + <conditionalClick selector="{{CmsPagesPageActionsSection.clearAll}}" dependentSelector="{{CmsPagesPageActionsSection.activeFilters}}" stepKey="clickToResetFilter" visible="true"/> + <waitForPageLoad stepKey="waitForGridReload"/> <click selector="{{CmsPagesPageActionsSection.FilterBtn}}" stepKey="clickFiltersBtn" /> <fillField selector="{{CmsPagesPageActionsSection.URLKey}}" userInput="$$createCMSPage.identifier$$" stepKey="fillOutURLKey" /> <click selector="{{CmsPagesPageActionsSection.ApplyFiltersBtn}}" stepKey="clickApplyBtn" /> - <waitForLoadingMaskToDisappear stepKey="waitForLoading3" /> + <waitForLoadingMaskToDisappear stepKey="waitForLoading1" /> <actionGroup ref="SortByIdDescendingActionGroup" stepKey="sortByIdDescending" /> <waitForElementVisible selector="{{CmsPagesPageActionsSection.select('$$createCMSPage.identifier$$')}}" stepKey="waitForCMSPageGrid" /> <click selector="{{CmsPagesPageActionsSection.select('$$createCMSPage.identifier$$')}}" stepKey="clickSelect" /> @@ -72,7 +73,7 @@ <click selector="{{WidgetSection.BlockPage(_defaultBlock.identifier)}}" stepKey="selectPreCreateBlock" /> <wait time="3" stepKey="wait1" /> <click selector="{{WidgetSection.InsertWidget}}" stepKey="clickInsertWidgetBtn" /> - <waitForLoadingMaskToDisappear stepKey="waitForLoading" /> + <waitForLoadingMaskToDisappear stepKey="waitForLoading2" /> <waitForPageLoad stepKey="waitForPageLoad6" /> <click selector="{{CmsNewPagePageActionsSection.savePage}}" stepKey="clickSavePage"/> <see userInput="You saved the page." stepKey="seeSuccessMessage"/> @@ -80,6 +81,10 @@ <waitForPageLoad stepKey="waitForPageLoad7" /> <see userInput="Home page" stepKey="seeHomePageCMSPage"/> <after> + <amOnPage url="{{CmsPagesPage.url}}" stepKey="amOnEditPage"/> + <waitForPageLoad stepKey="waitForPageLoad2"/> + <conditionalClick selector="{{CmsPagesPageActionsSection.clearAll}}" dependentSelector="{{CmsPagesPageActionsSection.activeFilters}}" stepKey="clickToResetFilter" visible="true"/> + <waitForPageLoad stepKey="waitForGridReload"/> <deleteData createDataKey="createCMSPage" stepKey="deletePreReqCMSPage" /> <actionGroup ref="DisabledWYSIWYG" stepKey="disableWYSIWYG"/> <actionGroup ref="logout" stepKey="logout"/> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Test/AdminAddWidgetToWYSIWYGWithCMSPageLinkTypeCest.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Test/AdminAddWidgetToWYSIWYGWithCMSPageLinkTypeCest.xml index 3e50ce671cd3c..bbcca1571db54 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Test/AdminAddWidgetToWYSIWYGWithCMSPageLinkTypeCest.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Test/AdminAddWidgetToWYSIWYGWithCMSPageLinkTypeCest.xml @@ -53,6 +53,7 @@ <waitForLoadingMaskToDisappear stepKey="waitForLoading" /> <scrollTo selector="{{CmsNewPagePageSeoSection.header}}" stepKey="scrollToSearchEngineTab" /> <click selector="{{CmsNewPagePageSeoSection.header}}" stepKey="clickExpandSearchEngineOptimisation"/> + <wait stepKey="waitForPageLoad5" time="10" /> <fillField selector="{{CmsNewPagePageSeoSection.urlKey}}" userInput="{{_defaultCmsPage.identifier}}" stepKey="fillFieldUrlKey"/> <click selector="{{CmsNewPagePageActionsSection.savePage}}" stepKey="clickSavePage"/> <see userInput="You saved the page." stepKey="seeSuccessMessage"/> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Test/AdminAddWidgetToWYSIWYGWithRecentlyComparedProductsTypeCest.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Test/AdminAddWidgetToWYSIWYGWithRecentlyComparedProductsTypeCest.xml index 66ae4a5d1cc53..102de9727adb6 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Test/AdminAddWidgetToWYSIWYGWithRecentlyComparedProductsTypeCest.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Test/AdminAddWidgetToWYSIWYGWithRecentlyComparedProductsTypeCest.xml @@ -64,13 +64,13 @@ <waitForPageLoad stepKey="waitForPage" /> <click selector="{{WidgetSection.CompareBtn}}" stepKey="clickCompareBtn" /> <amOnPage url="$$createPreReqCategory.name$$.html" stepKey="amOnCatalogPage" /> - <waitForPageLoad stepKey="waitForPage" /> <waitForPageLoad stepKey="waitForPage1" /> + <waitForPageLoad stepKey="waitForPage2" /> <waitForElementVisible selector="{{WidgetSection.ClearCompare}}" stepKey="waitForClearBtn" /> <click selector="{{WidgetSection.ClearCompare}}" stepKey="clickClearCompareBtn" /> <waitForElementVisible selector="{{WidgetSection.AcceptClear}}" stepKey=""/> <click selector="{{WidgetSection.AcceptClear}}" stepKey="acceptClearCompare" /> - <waitForPageLoad stepKey="waitForPage2" /> + <waitForPageLoad stepKey="waitForPage3" /> <amOnPage url="{{_defaultCmsPage.identifier}}" stepKey="amOnPageTestPage"/> <waitForPageLoad stepKey="wait5" /> <!--see widget on Storefront--> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Test/AdminCreateCmsPageTest.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Test/AdminCreateCmsPageTest.xml index bbbb282c17678..f8b3c3733a827 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Test/AdminCreateCmsPageTest.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Test/AdminCreateCmsPageTest.xml @@ -16,13 +16,15 @@ <description value="You should be able to create a CMS Page via the Admin."/> <severity value="CRITICAL"/> <testCaseId value="MAGETWO-25580"/> - <group value="cms"/> + <group value="Cms"/> </annotations> + <before> + <actionGroup ref="LoginActionGroup" stepKey="loginGetFromGeneralFile"/> + <actionGroup ref="DisabledWYSIWYG" stepKey="disableWYSIWYG"/> + </before> <after> <amOnPage url="admin/admin/auth/logout/" stepKey="amOnLogoutPage"/> </after> - - <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin1"/> <amOnPage url="{{CmsPagesPage.url}}" stepKey="amOnPagePagesGrid"/> <waitForPageLoad stepKey="waitForPageLoad1"/> <click selector="{{CmsPagesPageActionsSection.addNewPage}}" stepKey="clickAddNewPage"/> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Test/VerifyTinyMCEv4IsNativeWYSIWYGOnBlockCest.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Test/VerifyTinyMCEv4IsNativeWYSIWYGOnBlockCest.xml index c6faf6bdce28f..adcc522cbf8ba 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Test/VerifyTinyMCEv4IsNativeWYSIWYGOnBlockCest.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Test/VerifyTinyMCEv4IsNativeWYSIWYGOnBlockCest.xml @@ -24,7 +24,7 @@ <actionGroup ref="EnabledWYSIWYG" stepKey="enableWYSIWYG"/> <actionGroup ref="SwitchToVersion4ActionGroup" stepKey="switchToTinyMCE4" /> </before> - <amOnPage url="{{BlocksPage.url}}" stepKey="amOnNewBlockPage"/> + <amOnPage url="{{CmsNewBlock.url}}" stepKey="amOnNewBlockPage"/> <waitForPageLoad stepKey="waitForPageLoad1"/> <fillField selector="{{BlockNewPageBasicFieldsSection.blockTitle}}" userInput="{{_defaultBlock.title}}" stepKey="fillFieldTitle"/> <fillField selector="{{BlockNewPageBasicFieldsSection.identifier}}" userInput="{{_defaultBlock.identifier}}" stepKey="fillFieldIdentifier"/> @@ -41,6 +41,8 @@ <click selector="{{BlockNewPagePageActionsSection.saveBlock}}" stepKey="clickSaveBlock"/> <amOnPage url="{{CmsPagesPage.url}}" stepKey="amOnEditPage"/> <waitForPageLoad stepKey="waitForPageLoad2"/> + <conditionalClick selector="{{CmsPagesPageActionsSection.clearAll}}" dependentSelector="{{CmsPagesPageActionsSection.activeFilters}}" stepKey="clickToResetFilter" visible="true"/> + <waitForPageLoad stepKey="waitForGridReload"/> <click selector="{{CmsPagesPageActionsSection.FilterBtn}}" stepKey="clickFiltersBtn" /> <fillField selector="{{CmsPagesPageActionsSection.URLKey}}" userInput="$$createPreReqCMSPage.identifier$$" stepKey="fillOutURLKey" /> <click selector="{{CmsPagesPageActionsSection.ApplyFiltersBtn}}" stepKey="clickApplyBtn" /> @@ -80,6 +82,10 @@ <!--see content of Block on Storefront--> <see userInput="Hello Block Page!" stepKey="seeContent"/> <after> + <amOnPage url="{{CmsPagesPage.url}}" stepKey="amOnEditPage"/> + <waitForPageLoad stepKey="waitForPageLoad"/> + <conditionalClick selector="{{CmsPagesPageActionsSection.clearAll}}" dependentSelector="{{CmsPagesPageActionsSection.activeFilters}}" stepKey="clickToResetFilter" visible="true"/> + <waitForPageLoad stepKey="waitForGridReload"/> <deleteData createDataKey="createPreReqCMSPage" stepKey="deletePreReqCMSPage" /> <actionGroup ref="DisabledWYSIWYG" stepKey="disableWYSIWYG"/> <actionGroup ref="logout" stepKey="logout"/> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Config/Page/AdminConfigPage.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Config/Page/AdminConfigPage.xml index 870a172b38dcf..9ae1ecab1c26e 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Config/Page/AdminConfigPage.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Config/Page/AdminConfigPage.xml @@ -9,4 +9,7 @@ <page name="AdminConfigPage" url="admin/system_config/" area="admin" module="Magento_Config"> <section name="AdminConfigSection"/> </page> + <page name="AdminContentManagementPage" url="admin/system_config/edit/section/cms/" area="admin" module="Magento_Config"> + <section name="ContentManagementSection"/> + </page> </pages> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Newsletter/Section/NewsletterTemplateSection.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Newsletter/Section/NewsletterTemplateSection.xml index bda79f52a131a..53b44ddd33527 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Newsletter/Section/NewsletterTemplateSection.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Newsletter/Section/NewsletterTemplateSection.xml @@ -15,6 +15,7 @@ <element name="save" type="button" selector="button[data-role='template-save']"/> </section> <section name="NewsletterWYSIWYGSection"> + <element name="TextArea" type="text" selector="#text" /> <element name="TinyMCE4" type="text" selector=".mce-branding-powered-by" /> <element name="TinyMCE3" type="text" selector="#cms_page_form_content_tbl"/> <element name="ShowHideBtn" type="button" selector="#toggletext"/> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Newsletter/Test/AdminAddImageToWYSIWYGNewsletterCest.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Newsletter/Test/AdminAddImageToWYSIWYGNewsletterCest.xml index a8e08bccec8c4..11d5155c8dea2 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Newsletter/Test/AdminAddImageToWYSIWYGNewsletterCest.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Newsletter/Test/AdminAddImageToWYSIWYGNewsletterCest.xml @@ -11,7 +11,7 @@ <annotations> <features value="MAGETWO-36659-[CMS] WYSIWYG update"/> <stories value="MAGETWO-47309-Apply new WYSIWYG in Newsletter"/> - <group value="Newsletter"/> + <group value="skip"/> <title value="Admin should be able to add image to WYSIWYG content of Newsletter"/> <description value="Admin should be able to add image to WYSIWYG content Newsletter"/> <severity value="CRITICAL"/> @@ -31,51 +31,28 @@ <waitForElementVisible selector="{{NewsletterWYSIWYGSection.TinyMCE4}}" stepKey="waitForTinyMCE4"/> <click selector="{{TinyMCESection.InsertImageIcon}}" stepKey="clickInsertImageIcon" /> <waitForPageLoad stepKey="waitForPageLoad" /> - <click selector="{{MediaGallerySection.Browse}}" stepKey="clickBrowse" /> - <waitForElement selector="{{MediaGallerySection.CancelBtn}}" stepKey="waitForCancelBtn" /> - <waitForPageLoad stepKey="waitForPageLoad2" /> - <waitForLoadingMaskToDisappear stepKey="waitForLoading1" /> - <waitForLoadingMaskToDisappear stepKey="waitForLoading2" /> - <waitForElement selector="{{MediaGallerySection.StorageRootArrow}}" stepKey="waitForStorageFoot" /> - <see selector="{{MediaGallerySection.CancelBtn}}" userInput="Cancel" stepKey="seeCancelBtn" /> - <see selector="{{MediaGallerySection.CreateFolder}}" userInput="Create Folder" stepKey="seeCreateFolderBtn" /> - <see selector="{{MediaGallerySection.InsertFile}}" userInput="Add Selected" stepKey="seeAddSelectedBtn" /> - <click selector="{{MediaGallerySection.CreateFolder}}" stepKey="createFolder"/> - <waitForElementVisible selector="{{MediaGallerySection.FolderName}}" stepKey="waitForPopUp" /> - <fillField selector="{{MediaGallerySection.FolderName}}" userInput="{{ImageFolder.name}}" stepKey="fillFolderName" /> - <click selector="{{MediaGallerySection.AcceptFolderName}}" stepKey="acceptFolderName" /> - <waitForLoadingMaskToDisappear stepKey="waitForLoading3" /> - <conditionalClick selector="{{MediaGallerySection.StorageRootArrow}}" dependentSelector="{{MediaGallerySection.checkIfArrowExpand}}" stepKey="clickArrowIfCloses" visible="true"/> - <waitForText userInput="{{ImageFolder.name}}" stepKey="waitForNewFolder" /> - <click userInput="{{ImageFolder.name}}" stepKey="clickOnCreatedFolder" /> - <waitForLoadingMaskToDisappear stepKey="waitForLoading5" /> - <attachFile selector="{{MediaGallerySection.BrowseUploadImage}}" userInput="{{ImageUpload.file}}" stepKey="uploadImage1"/> - <waitForLoadingMaskToDisappear stepKey="waitForLoading6" /> - <waitForElementVisible selector="{{MediaGallerySection.image(ImageUpload.file)}}" stepKey="waitForUploadImage1" /> - <seeElement selector="{{MediaGallerySection.imageSelected(ImageUpload.file)}}" stepKey="seeImageSelected" /> - <see selector="{{MediaGallerySection.DeleteSelectedBtn}}" userInput="Delete Selected" stepKey="seeDeleteBtn"/> - <click selector="{{MediaGallerySection.DeleteSelectedBtn}}" stepKey="clickDeleteSelected" /> - <waitForText userInput="OK" stepKey="waitForConfirm" /> - <click selector="{{MediaGallerySection.confirmDelete}}" stepKey="confirmDelete" /> - <waitForElementNotVisible selector="{{MediaGallerySection.image(ImageUpload.file)}}" stepKey="waitForImageDeleted" /> - <dontSeeElement selector="{{MediaGallerySection.image(ImageUpload.file)}}" stepKey="dontSeeImage" /> - <attachFile selector="{{MediaGallerySection.BrowseUploadImage}}" userInput="{{ImageUpload.file}}" stepKey="uploadImage2"/> - <waitForLoadingMaskToDisappear stepKey="waitForLoading9" /> - <waitForElementVisible selector="{{MediaGallerySection.image(ImageUpload.file)}}" stepKey="waitForUploadImage2" /> - <click selector="{{MediaGallerySection.InsertFile}}" stepKey="clickInsertBtn" /> - <waitForLoadingMaskToDisappear stepKey="waitForLoading7" /> - <waitForElementVisible selector="{{MediaGallerySection.OkBtn}}" stepKey="waitForOkBtn" /> - <fillField selector="{{MediaGallerySection.ImageDescription}}" userInput="{{ImageUpload.content}}" stepKey="fillImageDescription" /> - <fillField selector="{{MediaGallerySection.Height}}" userInput="{{ImageUpload.height}}" stepKey="fillImageHeight" /> - <click selector="{{MediaGallerySection.OkBtn}}" stepKey="clickOkBtn" /> - <waitForPageLoad stepKey="waitForPageLoad8"/> + <actionGroup ref="clickBrowseBtnOnUploadPopup" stepKey="clickBrowserBtn"/> + <actionGroup ref="VerifyMediaGalleryStorageActions" stepKey="VerifyMediaGalleryStorageBtn"/> + <actionGroup ref="CreateImageFolder" stepKey="CreateImageFolder"> + <argument name="ImageFolder" value="ImageFolder"/> + </actionGroup> + <actionGroup ref="attachImage" stepKey="attachImage1"> + <argument name="Image" value="ImageUpload"/> + </actionGroup> + <actionGroup ref="deleteImage" stepKey="deleteImage"/> + + <actionGroup ref="attachImage" stepKey="attachImage2"> + <argument name="Image" value="ImageUpload"/> + </actionGroup> + <actionGroup ref="saveImage" stepKey="insertImage"/> + <actionGroup ref="fillOutUploadImagePopup" stepKey="fillOutUploadImagePopup" /> <!--Go to Storefront--> <click selector="{{BasicFieldNewsletterSection.save}}" stepKey="clickSaveTemplate"/> <waitForPageLoad stepKey="waitForPageLoad10" /> <click selector="{{NewsletterWYSIWYGSection.Preview(_defaultNewsletter.name)}}" stepKey="clickPreview" /> <switchToWindow stepKey="switchToWindow" userInput="action_window"/> <switchToIFrame userInput="preview_iframe" stepKey="switchToIframe" /> - <waitForPageLoad stepKey="waitForPageLoad9"/> + <waitForElementVisible selector="{{StorefrontNewsletterSection.mediaDescription}}" stepKey="waitForPageLoad9"/> <seeElement selector="{{StorefrontNewsletterSection.mediaDescription}}" stepKey="assertMediaDescription"/> <closeTab stepKey="closeTab"/> <after> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Newsletter/Test/AdminAddVariableToWYSIWYGNewsletterCest.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Newsletter/Test/AdminAddVariableToWYSIWYGNewsletterCest.xml index fa40177cc9fa3..a2831623d109a 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Newsletter/Test/AdminAddVariableToWYSIWYGNewsletterCest.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Newsletter/Test/AdminAddVariableToWYSIWYGNewsletterCest.xml @@ -32,7 +32,7 @@ <click selector="{{StoreConfigSection.Save}}" stepKey="saveConfig"/> <!--Main test--> <amOnPage url="{{NewsletterTemplateForm.url}}" stepKey="amOnNewsletterTemplatePage"/> - <waitForPageLoad stepKey="waitForPageLoad1"/> + <waitForPageLoad stepKey="waitForPageLoad2"/> <fillField selector="{{BasicFieldNewsletterSection.templateName}}" userInput="{{_defaultNewsletter.name}}" stepKey="fillTemplateName" /> <fillField selector="{{BasicFieldNewsletterSection.templateSubject}}" userInput="{{_defaultNewsletter.subject}}" stepKey="fillTemplateSubject" /> <fillField selector="{{BasicFieldNewsletterSection.senderName}}" userInput="{{_defaultNewsletter.senderName}}" stepKey="fillSenderName" /> @@ -92,7 +92,7 @@ <click selector="{{NewsletterWYSIWYGSection.Preview(_defaultNewsletter.name)}}" stepKey="clickPreview2" /> <switchToWindow userInput="action_window" stepKey="switchToWindow2"/> <switchToIFrame userInput="preview_iframe" stepKey="switchToIframe2" /> - <waitForPageLoad stepKey="waitForPageLoad8"/> + <wait time="10" stepKey="waitForPageLoad8"/> <!--see custom variable blank--> <dontSee userInput="{{customVariable.html}}" stepKey="dontSeeCustomVariableName" /> <closeTab stepKey="closeTab"/> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Newsletter/Test/AdminAddWidgetToWYSIWYGNewsletterCest.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Newsletter/Test/AdminAddWidgetToWYSIWYGNewsletterCest.xml index 85ba7e6fcc9c3..b21879ff175e8 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Newsletter/Test/AdminAddWidgetToWYSIWYGNewsletterCest.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Newsletter/Test/AdminAddWidgetToWYSIWYGNewsletterCest.xml @@ -48,7 +48,7 @@ <click selector="{{NewsletterWYSIWYGSection.Preview(_defaultNewsletter.name)}}" stepKey="clickPreview" /> <switchToWindow stepKey="switchToWindow" userInput="action_window"/> <switchToIFrame userInput="preview_iframe" stepKey="switchToIframe" /> - <waitForPageLoad stepKey="waitForPageLoad9"/> + <waitForText userInput="Home page" stepKey="waitForPageLoad9"/> <see userInput="Home page" stepKey="seeHomePageCMSPage"/> <closeTab stepKey="closeTab"/> <after> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Newsletter/Test/VerifyTinyMCEv4IsNativeWYSIWYGOnNewsletterCest.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Newsletter/Test/VerifyTinyMCEv4IsNativeWYSIWYGOnNewsletterCest.xml index f9571a6e7477e..d60f19d2f8def 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Newsletter/Test/VerifyTinyMCEv4IsNativeWYSIWYGOnNewsletterCest.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Newsletter/Test/VerifyTinyMCEv4IsNativeWYSIWYGOnNewsletterCest.xml @@ -43,7 +43,7 @@ <click selector="{{NewsletterWYSIWYGSection.Preview(_defaultNewsletter.name)}}" stepKey="clickPreview" /> <switchToWindow stepKey="switchToWindow" userInput="action_window"/> <switchToIFrame userInput="preview_iframe" stepKey="switchToIframe" /> - <waitForPageLoad stepKey="waitForPageLoad2"/> + <waitForText userInput="Hello World From Newsletter Template!" stepKey="waitForPageLoad2"/> <see userInput="Hello World From Newsletter Template!" stepKey="seeContent" /> <closeTab stepKey="closeTab"/> <after> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SampleTemplates/Test/TemplateTestFile.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SampleTemplates/Test/TemplateTestFile.xml index 8b7270673aba0..1610e4dfa2cbb 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SampleTemplates/Test/TemplateTestFile.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SampleTemplates/Test/TemplateTestFile.xml @@ -8,7 +8,7 @@ <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd"> - <test name=""> + <test name="templateTestName"> <annotations> <features value=""/> <stories value=""/> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SampleTests/Test/SampleTest.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SampleTests/Test/SampleTest.xml index 955958a5cf722..9e4a470b88950 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SampleTests/Test/SampleTest.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SampleTests/Test/SampleTest.xml @@ -56,7 +56,7 @@ <dontSeeCookie userInput="cookieName" stepKey="dontSeeCookie1"/> <dontSeeCookie userInput="cookieName" parameterArray="['domainName' => 'stuff']" stepKey="dontSeeCookie2"/> <dontSeeCurrentUrlEquals url="/stuff" stepKey="dontSeeCurrentUrlEquals"/> - <dontSeeCurrentUrlMatches url="~$/users/(\d+)~" stepKey="dontSeeCurrentUrlMatches"/> + <dontSeeCurrentUrlMatches regex="~$/users/(\d+)~" stepKey="dontSeeCurrentUrlMatches"/> <dontSeeElement selector=".error" stepKey="dontSeeElement1"/> <dontSeeElement selector="input" parameterArray="['name' => 'login']" stepKey="dontSeeElement2"/> <dontSeeElementInDOM selector="#stuff" stepKey="dontSeeElementInDOM1"/> @@ -79,7 +79,7 @@ <fillField selectorArray="['name' => 'email']" userInput="stuff" stepKey="fillField2"/> <grabAttributeFrom selector="#target" userInput="title" stepKey="grabAttributeFrom"/> <grabCookie userInput="cookie" parameterArray="['domain' => 'www.google.com']" stepKey="grabCookie"/> - <grabFromCurrentUrl url="~$/user/(\d+)/~" stepKey="grabFromCurrentUrl"/> + <grabFromCurrentUrl regex="~$/user/(\d+)/~" stepKey="grabFromCurrentUrl"/> <grabMultiple selector="a" userInput="href" stepKey="grabMultiple"/> <grabPageSource stepKey="grabPageSource1"/> <grabTextFrom selector="h1" stepKey="grabTextFrom1"/> @@ -119,7 +119,7 @@ <seeCookie userInput="PHPSESSID" stepKey="seeCookie1"/> <seeCookie userInput="PHPSESSID" parameterArray="['domainName' => 'www.google.com']" stepKey="seeCookie2"/> <seeCurrentUrlEquals url="/" stepKey="seeCurrentUrlEquals"/> - <seeCurrentUrlMatches url="~$/users/(\d+)~" stepKey="seeCurrentUrlMatches"/> + <seeCurrentUrlMatches regex="~$/users/(\d+)~" stepKey="seeCurrentUrlMatches"/> <seeElement selector=".error" stepKey="seeElement1"/> <seeElement selectorArray="['css' => 'form input']" stepKey="seeElement2"/> <seeElement selector=".error" parameterArray="['name' => 'login']" stepKey="seeElement3"/> @@ -217,7 +217,7 @@ <dontSee userInput="{$randomStuff}" stepKey="dontSee1"/> <dontSeeCookie userInput="{$randomStuff}" stepKey="dontSeeCookie1"/> <dontSeeCurrentUrlEquals url="{$randomStuff}" stepKey="dontSeeCurrentUrlEquals1"/> - <dontSeeCurrentUrlMatches url="{$randomStuff}" stepKey="dontSeeCurrentUrlMatches1"/> + <dontSeeCurrentUrlMatches regex="{$randomStuff}" stepKey="dontSeeCurrentUrlMatches1"/> <dontSeeInCurrentUrl url="{$randomStuff}" stepKey="dontSeeInCurrentUrl1"/> <dontSeeInField selector="#stuff" userInput="{$randomStuff}" stepKey="dontSeeInField1"/> <dontSeeInPageSource userInput="{$randomStuff}" stepKey="dontSeeInPageSource1"/> @@ -227,7 +227,7 @@ <fillField userInput="{$randomStuff}" selector="#field" stepKey="fillField1"/> <grabAttributeFrom selector="#stuff" userInput="{$randomStuff}" stepKey="grabAttributeFrom1"/> <grabCookie userInput="{$randomStuff}" stepKey="grabValueFrom1"/> - <grabFromCurrentUrl url="{$randomStuff}" stepKey="grabFromCurrentUrl"/> + <grabFromCurrentUrl regex="{$randomStuff}" stepKey="grabFromCurrentUrl"/> <grabMultiple selector="a" userInput="{$randomStuff}" stepKey="grabMultiple1"/> <loadSessionSnapshot userInput="{$randomStuff}" stepKey="loadSessionSnapshot"/> <pressKey selector="a" userInput="{$randomStuff}" stepKey="pressKey1"/> @@ -235,7 +235,7 @@ <see userInput="{$randomStuff}" stepKey="see1"/> <seeCookie userInput="{$randomStuff}" stepKey="seeCookie1"/> <seeCurrentUrlEquals url="{$randomStuff}" stepKey="seeCurrentUrlEquals1"/> - <seeCurrentUrlMatches url="{$randomStuff}" stepKey="seeCurrentUrlMatches1"/> + <seeCurrentUrlMatches regex="{$randomStuff}" stepKey="seeCurrentUrlMatches1"/> <seeInCurrentUrl url="{$randomStuff}" stepKey="seeInCurrentUrl1"/> <seeInField selector="a" userInput="{$randomStuff}" stepKey="seeInField1"/> <seeInPopup userInput="{$randomStuff}" stepKey="seeInPopup"/> @@ -245,9 +245,9 @@ <seeOptionIsSelected selector="#stuff" userInput="{$randomStuff}" stepKey="seeOptionIsSelected1"/> <selectOption selector="#stuff" userInput="{$randomStuff}" stepKey="selectOption1"/> <switchToIFrame userInput="{$randomStuff}" stepKey="switchToIFrame1"/> - <switchToNextTab userInput="{$randomStuff}" stepKey="switchToNextTab1"/> + <switchToNextTab userInput="{$randomStuff}" stepKey="switchToNextTab2"/> <switchToPreviousTab userInput="{$randomStuff}" stepKey="switchToPreviousTab1"/> - <switchToNextTab userInput="{$randomStuff}" stepKey="switchToNextTab1"/> + <switchToNextTab userInput="{$randomStuff}" stepKey="switchToNextTab3"/> <switchToWindow userInput="{$randomStuff}" stepKey="switchToWindow1"/> <typeInPopup userInput="{$randomStuff}" stepKey="typeInPopup"/> <unselectOption selector="#option" userInput="{$randomStuff}" stepKey="unselectOption1"/> diff --git a/dev/tests/api-functional/_files/Magento/TestModule1/etc/module.xml b/dev/tests/api-functional/_files/Magento/TestModule1/etc/module.xml index f0226e0745afa..a649cb9c357ff 100644 --- a/dev/tests/api-functional/_files/Magento/TestModule1/etc/module.xml +++ b/dev/tests/api-functional/_files/Magento/TestModule1/etc/module.xml @@ -6,5 +6,5 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> - <module name="Magento_TestModule1" setup_version="1.0"/> + <module name="Magento_TestModule1" /> </config> diff --git a/dev/tests/api-functional/_files/Magento/TestModule2/etc/module.xml b/dev/tests/api-functional/_files/Magento/TestModule2/etc/module.xml index b2d84c04a8caf..93312a82384cc 100644 --- a/dev/tests/api-functional/_files/Magento/TestModule2/etc/module.xml +++ b/dev/tests/api-functional/_files/Magento/TestModule2/etc/module.xml @@ -6,5 +6,5 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> - <module name="Magento_TestModule2" setup_version="1.0"/> + <module name="Magento_TestModule2" /> </config> diff --git a/dev/tests/api-functional/_files/Magento/TestModule3/Service/V1/Error.php b/dev/tests/api-functional/_files/Magento/TestModule3/Service/V1/Error.php index 6e681fbdd4687..3713396e5dd26 100644 --- a/dev/tests/api-functional/_files/Magento/TestModule3/Service/V1/Error.php +++ b/dev/tests/api-functional/_files/Magento/TestModule3/Service/V1/Error.php @@ -5,6 +5,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\TestModule3\Service\V1; use Magento\Framework\Exception\AuthorizationException; @@ -63,7 +64,7 @@ public function serviceException() */ public function authorizationException() { - throw new AuthorizationException(__('Consumer is not authorized to access %1', 'resourceN')); + throw new AuthorizationException(__("The consumer isn't authorized to access %1.", 'resourceN')); } /** diff --git a/dev/tests/api-functional/_files/Magento/TestModule3/etc/module.xml b/dev/tests/api-functional/_files/Magento/TestModule3/etc/module.xml index 8863cb69e1fcc..f7940be3e768c 100644 --- a/dev/tests/api-functional/_files/Magento/TestModule3/etc/module.xml +++ b/dev/tests/api-functional/_files/Magento/TestModule3/etc/module.xml @@ -6,5 +6,5 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> - <module name="Magento_TestModule3" setup_version="1.0"/> + <module name="Magento_TestModule3" /> </config> diff --git a/dev/tests/api-functional/_files/Magento/TestModule4/etc/module.xml b/dev/tests/api-functional/_files/Magento/TestModule4/etc/module.xml index 11732fbd97aed..3a5670ccd54b0 100644 --- a/dev/tests/api-functional/_files/Magento/TestModule4/etc/module.xml +++ b/dev/tests/api-functional/_files/Magento/TestModule4/etc/module.xml @@ -6,5 +6,5 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> - <module name="Magento_TestModule4" setup_version="1.0"/> + <module name="Magento_TestModule4" /> </config> diff --git a/dev/tests/api-functional/_files/Magento/TestModule5/etc/module.xml b/dev/tests/api-functional/_files/Magento/TestModule5/etc/module.xml index 1f735f68b1bf6..31c70e18a7935 100644 --- a/dev/tests/api-functional/_files/Magento/TestModule5/etc/module.xml +++ b/dev/tests/api-functional/_files/Magento/TestModule5/etc/module.xml @@ -6,5 +6,5 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> - <module name="Magento_TestModule5" setup_version="1.0"/> + <module name="Magento_TestModule5" /> </config> diff --git a/dev/tests/api-functional/_files/Magento/TestModuleDefaultHydrator/etc/module.xml b/dev/tests/api-functional/_files/Magento/TestModuleDefaultHydrator/etc/module.xml index 3d10999829bf3..ca4ded8ff3190 100644 --- a/dev/tests/api-functional/_files/Magento/TestModuleDefaultHydrator/etc/module.xml +++ b/dev/tests/api-functional/_files/Magento/TestModuleDefaultHydrator/etc/module.xml @@ -1,11 +1,11 @@ <?xml version="1.0"?> <!-- /** - * Copyright © 2015 Magento. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd"> - <module name="Magento_TestModuleDefaultHydrator" setup_version="2.0.0"> + <module name="Magento_TestModuleDefaultHydrator"> </module> </config> diff --git a/dev/tests/api-functional/_files/Magento/TestModuleGraphQlQuery/etc/module.xml b/dev/tests/api-functional/_files/Magento/TestModuleGraphQlQuery/etc/module.xml index 5202dce8ce595..c4ad9ac7f3876 100644 --- a/dev/tests/api-functional/_files/Magento/TestModuleGraphQlQuery/etc/module.xml +++ b/dev/tests/api-functional/_files/Magento/TestModuleGraphQlQuery/etc/module.xml @@ -6,5 +6,5 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> - <module name="Magento_TestModuleGraphQlQuery" setup_version="1.0"/> + <module name="Magento_TestModuleGraphQlQuery" /> </config> diff --git a/dev/tests/api-functional/_files/Magento/TestModuleGraphQlQueryExtension/etc/module.xml b/dev/tests/api-functional/_files/Magento/TestModuleGraphQlQueryExtension/etc/module.xml index 419d1e92fe9ce..e6a8affe747eb 100644 --- a/dev/tests/api-functional/_files/Magento/TestModuleGraphQlQueryExtension/etc/module.xml +++ b/dev/tests/api-functional/_files/Magento/TestModuleGraphQlQueryExtension/etc/module.xml @@ -6,5 +6,5 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> - <module name="Magento_TestModuleGraphQlQueryExtension" setup_version="1.0"/> + <module name="Magento_TestModuleGraphQlQueryExtension" /> </config> diff --git a/dev/tests/api-functional/_files/Magento/TestModuleIntegrationFromConfig/etc/module.xml b/dev/tests/api-functional/_files/Magento/TestModuleIntegrationFromConfig/etc/module.xml index eaf0f69a596fa..cd78d204dc9ae 100644 --- a/dev/tests/api-functional/_files/Magento/TestModuleIntegrationFromConfig/etc/module.xml +++ b/dev/tests/api-functional/_files/Magento/TestModuleIntegrationFromConfig/etc/module.xml @@ -6,6 +6,6 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> - <module name="Magento_TestModuleIntegrationFromConfig" setup_version="0.0.1" active="true"> + <module name="Magento_TestModuleIntegrationFromConfig" active="true"> </module> </config> diff --git a/dev/tests/api-functional/_files/Magento/TestModuleJoinDirectives/etc/module.xml b/dev/tests/api-functional/_files/Magento/TestModuleJoinDirectives/etc/module.xml index e5ab9c1860103..afb3a091f5fb6 100644 --- a/dev/tests/api-functional/_files/Magento/TestModuleJoinDirectives/etc/module.xml +++ b/dev/tests/api-functional/_files/Magento/TestModuleJoinDirectives/etc/module.xml @@ -6,5 +6,5 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> - <module name="Magento_TestModuleJoinDirectives" setup_version="1.0"/> + <module name="Magento_TestModuleJoinDirectives" /> </config> diff --git a/dev/tests/api-functional/_files/Magento/TestModuleMSC/etc/module.xml b/dev/tests/api-functional/_files/Magento/TestModuleMSC/etc/module.xml index 4ebbe995e020e..1e3752b1e93ff 100644 --- a/dev/tests/api-functional/_files/Magento/TestModuleMSC/etc/module.xml +++ b/dev/tests/api-functional/_files/Magento/TestModuleMSC/etc/module.xml @@ -6,5 +6,5 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> - <module name="Magento_TestModuleMSC" setup_version="1.0"/> + <module name="Magento_TestModuleMSC" /> </config> diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/AttributeSetManagementTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/AttributeSetManagementTest.php index c645712dafca1..8ad55207b5f8b 100644 --- a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/AttributeSetManagementTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/AttributeSetManagementTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Catalog\Api; use Magento\TestFramework\Helper\Bootstrap; @@ -82,7 +83,6 @@ public function testCreateThrowsExceptionIfGivenAttributeSetAlreadyHasId() /** * @expectedException \Exception - * @expectedExceptionMessage Can not create attribute set based on not existing attribute set */ public function testCreateThrowsExceptionIfGivenSkeletonIdIsInvalid() { @@ -95,11 +95,14 @@ public function testCreateThrowsExceptionIfGivenSkeletonIdIsInvalid() 'skeletonId' => 0, ]; $this->_webApiCall($this->createServiceInfo, $arguments); + + $this->expectExceptionMessage( + "The attribute set couldn't be created because it's based on a non-existing attribute set." + ); } /** * @expectedException \Exception - * @expectedExceptionMessage Can not create attribute set based on non product attribute set. */ public function testCreateThrowsExceptionIfGivenSkeletonIdHasWrongEntityType() { @@ -112,11 +115,14 @@ public function testCreateThrowsExceptionIfGivenSkeletonIdHasWrongEntityType() 'skeletonId' => 7, ]; $this->_webApiCall($this->createServiceInfo, $arguments); + + $this->expectExceptionMessage( + "The attribute set couldn't be created because it's based on a non-product attribute set." + ); } /** * @expectedException \Exception - * @expectedExceptionMessage Can not create attribute set based on not existing attribute set */ public function testCreateThrowsExceptionIfGivenSkeletonAttributeSetDoesNotExist() { @@ -129,11 +135,15 @@ public function testCreateThrowsExceptionIfGivenSkeletonAttributeSetDoesNotExist 'skeletonId' => 9999, ]; $this->_webApiCall($this->createServiceInfo, $arguments); + + $this->expectExceptionMessage( + "The attribute set couldn't be created because it's based on a non-existing attribute set." + ); } /** * @expectedException \Exception - * @expectedExceptionMessage Attribute set name is empty. + * @expectedExceptionMessage The attribute set name is empty. Enter the name and try again. */ public function testCreateThrowsExceptionIfAttributeSetNameIsEmpty() { @@ -156,7 +166,7 @@ public function testCreateThrowsExceptionIfAttributeSetWithGivenNameAlreadyExist $entityTypeCode = 'catalog_product'; $entityType = $this->getEntityTypeByCode($entityTypeCode); $attributeSetName = 'Default'; - $expectedMessage = 'An attribute set named "Default" already exists.'; + $expectedMessage = 'A "Default" attribute set name already exists. Create a new name and try again.'; $arguments = [ 'attributeSet' => [ diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductAttributeManagementTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductAttributeManagementTest.php index 13e927be66d66..810e533f1f2f8 100644 --- a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductAttributeManagementTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductAttributeManagementTest.php @@ -57,7 +57,7 @@ public function testAssignAttributeWrongAttributeSet() $payload = $this->getAttributeData(); $payload['attributeSetId'] = -1; - $expectedMessage = 'AttributeSet with id "%1" does not exist.'; + $expectedMessage = 'The AttributeSet with a "%1" ID doesn\'t exist. Verify the attributeSet and try again.'; try { $this->_webApiCall($this->getAssignServiceInfo(), $payload); @@ -80,7 +80,7 @@ public function testAssignAttributeWrongAttributeGroup() { $payload = $this->getAttributeData(); $payload['attributeGroupId'] = -1; - $expectedMessage = 'Group with id "%1" does not exist.'; + $expectedMessage = 'The group with the "%1" ID doesn\'t exist. Verify the ID and try again.'; try { $this->_webApiCall($this->getAssignServiceInfo(), $payload); @@ -103,7 +103,8 @@ public function testAssignAttributeWrongAttribute() { $payload = $this->getAttributeData(); $payload['attributeCode'] = 'badCode'; - $expectedMessage = 'Attribute with attributeCode "%1" does not exist.'; + $expectedMessage = + 'The attribute with a "%1" attributeCode doesn\'t exist. Verify the attribute and try again.'; try { $this->_webApiCall($this->getAssignServiceInfo(), $payload); diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductAttributeMediaGalleryManagementInterfaceTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductAttributeMediaGalleryManagementInterfaceTest.php index ca9ad9897bf8c..0a990ab8d6a6b 100644 --- a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductAttributeMediaGalleryManagementInterfaceTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductAttributeMediaGalleryManagementInterfaceTest.php @@ -4,6 +4,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Catalog\Api; use Magento\Framework\Api\Data\ImageContentInterface; @@ -384,7 +385,7 @@ public function testCreateThrowsExceptionIfProvidedImageHasWrongMimeType() /** * @expectedException \Exception - * @expectedExceptionMessage Requested product doesn't exist + * @expectedExceptionMessage The product that was requested doesn't exist. Verify the product and try again. */ public function testCreateThrowsExceptionIfTargetProductDoesNotExist() { @@ -433,7 +434,7 @@ public function testCreateThrowsExceptionIfProvidedImageNameContainsForbiddenCha /** * @expectedException \Exception - * @expectedExceptionMessage Requested product doesn't exist + * @expectedExceptionMessage The product that was requested doesn't exist. Verify the product and try again. */ public function testUpdateThrowsExceptionIfTargetProductDoesNotExist() { @@ -457,7 +458,7 @@ public function testUpdateThrowsExceptionIfTargetProductDoesNotExist() /** * @magentoApiDataFixture Magento/Catalog/_files/product_with_image.php * @expectedException \Exception - * @expectedExceptionMessage There is no image with provided ID. + * @expectedExceptionMessage No image with the provided ID was found. Verify the ID and try again. */ public function testUpdateThrowsExceptionIfThereIsNoImageWithGivenId() { @@ -481,7 +482,7 @@ public function testUpdateThrowsExceptionIfThereIsNoImageWithGivenId() /** * @expectedException \Exception - * @expectedExceptionMessage Requested product doesn't exist + * @expectedExceptionMessage The product that was requested doesn't exist. Verify the product and try again. */ public function testDeleteThrowsExceptionIfTargetProductDoesNotExist() { @@ -497,7 +498,7 @@ public function testDeleteThrowsExceptionIfTargetProductDoesNotExist() /** * @magentoApiDataFixture Magento/Catalog/_files/product_with_image.php * @expectedException \Exception - * @expectedExceptionMessage There is no image with provided ID. + * @expectedExceptionMessage No image with the provided ID was found. Verify the ID and try again. */ public function testDeleteThrowsExceptionIfThereIsNoImageWithGivenId() { @@ -609,7 +610,10 @@ public function testGetListForAbsentSku() 'sku' => $productSku, ]; if (TESTS_WEB_API_ADAPTER == self::ADAPTER_SOAP) { - $this->expectException('SoapFault', 'Requested product doesn\'t exist'); + $this->expectException( + 'SoapFault', + "The product that was requested doesn't exist. Verify the product and try again." + ); } else { $this->expectException('Exception', '', 404); } diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductAttributeRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductAttributeRepositoryTest.php index e48c5ad018db4..5241e281b342d 100644 --- a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductAttributeRepositoryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductAttributeRepositoryTest.php @@ -4,6 +4,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Catalog\Api; use Magento\Framework\Webapi\Exception as HTTPExceptionCodes; @@ -243,7 +244,8 @@ public function testDeleteById() public function testDeleteNoSuchEntityException() { $attributeCode = 'some_test_code'; - $expectedMessage = 'Attribute with attributeCode "%1" does not exist.'; + $expectedMessage = + 'The attribute with a "%1" attributeCode doesn\'t exist. Verify the attribute and try again.'; $serviceInfo = [ 'rest' => [ 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 8791a47cef396..4f430d19a0a97 100644 --- a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductRepositoryInterfaceTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductRepositoryInterfaceTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Catalog\Api; use Magento\Catalog\Api\Data\ProductInterface; @@ -100,7 +101,7 @@ public function testGetNoSuchEntityException() ], ]; - $expectedMessage = 'Requested product doesn\'t exist'; + $expectedMessage = "The product that was requested doesn't exist. Verify the product and try again."; try { $this->_webApiCall($serviceInfo, ['sku' => $invalidSku]); @@ -291,7 +292,7 @@ public function testCreateInvalidPriceFormat() { $this->_markTestAsRestOnly("In case of SOAP type casting is handled by PHP SoapServer, no need to test it"); $expectedMessage = 'Error occurred during "price" processing. ' - . 'Invalid type for value: "invalid_format". Expected Type: "float".'; + . 'The "invalid_format" value\'s type is invalid. The "float" type was expected. Verify and try again.'; try { $this->saveProduct(['name' => 'simple', 'price' => 'invalid_format', 'sku' => 'simple']); @@ -313,7 +314,10 @@ public function testDeleteAllStoreCode($fixtureProduct) { $sku = $fixtureProduct[ProductInterface::SKU]; $this->saveProduct($fixtureProduct); - $this->expectException('Exception', 'Requested product doesn\'t exist'); + $this->expectException( + 'Exception', + "The product that was requested doesn't exist. Verify the product and try again." + ); // Delete all with 'all' store code $this->deleteProduct($sku); diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/_files/product_options_update_negative.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/_files/product_options_update_negative.php index 1e713424f8047..2f9888b95b843 100644 --- a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/_files/product_options_update_negative.php +++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/_files/product_options_update_negative.php @@ -17,6 +17,6 @@ 'sku' => 'sku1', 'max_characters' => 10, ], - 'ProductSku should be specified', + 'The ProductSku is empty. Set the ProductSku and try again.', ] ]; diff --git a/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/CartItemRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/CartItemRepositoryTest.php index 0ab81de07818a..c9cad5d597e65 100644 --- a/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/CartItemRepositoryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/CartItemRepositoryTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\ConfigurableProduct\Api; use Magento\TestFramework\TestCase\WebapiAbstract; @@ -105,7 +106,7 @@ public function testAddProductWithIncorrectOptions() /** * @magentoApiDataFixture Magento/ConfigurableProduct/_files/quote_with_configurable_product.php * @expectedException \Exception - * @expectedExceptionMessage Cart %1 does not contain item %2 + * @expectedExceptionMessage The %1 Cart doesn't contain the %2 item. */ public function testUpdateIncorrectItem() { 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 aac8be194d791..9c1caefd174e0 100644 --- a/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/OptionRepositoryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/OptionRepositoryTest.php @@ -85,7 +85,7 @@ public function testGetList() /** * @expectedException \Exception - * @expectedExceptionMessage Requested product doesn't exist + * @expectedExceptionMessage The product that was requested doesn't exist. Verify the product and try again. */ public function testGetUndefinedProduct() { @@ -98,7 +98,7 @@ public function testGetUndefinedProduct() */ public function testGetUndefinedOption() { - $expectedMessage = 'Requested option doesn\'t exist: %1'; + $expectedMessage = 'The "%1" entity that was requested doesn\'t exist. Verify the entity and try again.'; $productSku = 'configurable'; $attributeId = -42; try { diff --git a/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/ProductRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/ProductRepositoryTest.php index 40ebe0873ec3d..dc32bb2fc129a 100644 --- a/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/ProductRepositoryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/ProductRepositoryTest.php @@ -286,7 +286,7 @@ public function testUpdateConfigurableProductLinksWithNonExistingProduct() $productId1, $nonExistingId ]; - $expectedMessage = 'Unable to save product'; + $expectedMessage = 'The product was unable to be saved. Please try again.'; try { $this->saveProduct($response); $this->fail("Expected exception"); @@ -362,7 +362,7 @@ public function testUpdateConfigurableProductLinksWithWithoutVariationAttributes $productId1, $productId2 ]; - $expectedMessage = 'Unable to save product'; + $expectedMessage = 'The product was unable to be saved. Please try again.'; try { $this->saveProduct($response); $this->fail("Expected exception"); diff --git a/dev/tests/api-functional/testsuite/Magento/Customer/Api/AccountManagementTest.php b/dev/tests/api-functional/testsuite/Magento/Customer/Api/AccountManagementTest.php index 452a59d7e702c..b0d1647d8b837 100644 --- a/dev/tests/api-functional/testsuite/Magento/Customer/Api/AccountManagementTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Customer/Api/AccountManagementTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Customer\Api; use Magento\Customer\Api\Data\CustomerInterface as Customer; @@ -322,7 +323,7 @@ public function testValidateResetPasswordLinkTokenInvalidToken() ], ]; - $expectedMessage = 'Reset password token mismatch.'; + $expectedMessage = 'The password token is mismatched. Reset and try again.'; try { if (TESTS_WEB_API_ADAPTER == self::ADAPTER_SOAP) { @@ -366,13 +367,13 @@ public function testInitiatePasswordMissingRequiredFields() 'message' => 'One or more input exceptions have occurred.', 'errors' => [ [ - 'message' => '%fieldName is a required field.', + 'message' => '"%fieldName" is required. Enter and try again.', 'parameters' => [ 'fieldName' => 'email', ], ], [ - 'message' => '%fieldName is a required field.', + 'message' => '"%fieldName" is required. Enter and try again.', 'parameters' => [ 'fieldName' => 'template', ] @@ -575,8 +576,14 @@ public function testValidateCustomerData() $validationResponse = $this->_webApiCall($serviceInfo, $requestData); $this->assertFalse($validationResponse['valid']); - $this->assertEquals('The value of attribute "First Name" must be set', $validationResponse['messages'][0]); - $this->assertEquals('The value of attribute "Last Name" must be set', $validationResponse['messages'][1]); + $this->assertEquals( + 'The "First Name" attribute value is empty. Set the attribute and try again.', + $validationResponse['messages'][0] + ); + $this->assertEquals( + 'The "Last Name" attribute value is empty. Set the attribute and try again.', + $validationResponse['messages'][1] + ); } public function testIsReadonly() 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 5ddd077c7f40e..8da91a3dffc0e 100644 --- a/dev/tests/api-functional/testsuite/Magento/Customer/Api/CustomerRepositoryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Customer/Api/CustomerRepositoryTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Customer\Api; use Magento\Customer\Api\Data\CustomerInterface as Customer; @@ -146,7 +147,7 @@ public function tearDown() * Validate update by invalid customer. * * @expectedException \Exception - * @expectedExceptionMessage Consumer is not authorized to access %resources + * @expectedExceptionMessage The consumer isn't authorized to access %resources. */ public function testInvalidCustomerUpdate() { @@ -432,7 +433,7 @@ public function testCreateCustomerWithoutAddressRequiresException() $expectedException = new InputException(); $expectedException->addError( __( - '%fieldName is a required field.', + '"%fieldName" is required. Enter and try again.', ['fieldName' => Address::FIRSTNAME] ) ); @@ -447,7 +448,7 @@ public function testCreateCustomerWithoutAddressRequiresException() $this->assertEquals(HTTPExceptionCodes::HTTP_BAD_REQUEST, $e->getCode()); $exceptionData = $this->processRestExceptionResult($e); $expectedExceptionData = [ - 'message' => '%fieldName is a required field.', + 'message' => '"%fieldName" is required. Enter and try again.', 'parameters' => ['fieldName' => Address::FIRSTNAME], ]; $this->assertEquals($expectedExceptionData, $exceptionData); @@ -554,7 +555,7 @@ public function testSearchCustomersUsingGETEmptyFilter() $this->assertEquals(HTTPExceptionCodes::HTTP_BAD_REQUEST, $e->getCode()); $exceptionData = $this->processRestExceptionResult($e); $expectedExceptionData = [ - 'message' => '%fieldName is a required field.', + 'message' => '"%fieldName" is required. Enter and try again.', 'parameters' => [ 'fieldName' => 'searchCriteria' ], 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 7dfa5f7086857..999a2daa26065 100644 --- a/dev/tests/api-functional/testsuite/Magento/Customer/Api/GroupRepositoryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Customer/Api/GroupRepositoryTest.php @@ -279,7 +279,7 @@ public function testCreateGroupNoCodeExpectExceptionRest() } catch (\Exception $e) { // @codingStandardsIgnoreStart $this->assertContains( - '{"message":"%fieldName is a required field.","parameters":{"fieldName":"code"}', + '\"%fieldName\" is required. Enter and try again.","parameters":{"fieldName":"code"}', $e->getMessage(), "Exception does not contain expected message." ); @@ -606,7 +606,7 @@ public function testCreateGroupNoCodeExpectExceptionSoap() $this->fail("Expected exception"); } catch (\SoapFault $e) { $this->assertContains( - '%fieldName is a required field.', + '"%fieldName" is required. Enter and try again.', $e->getMessage(), "SoapFault does not contain expected message." ); diff --git a/dev/tests/api-functional/testsuite/Magento/Downloadable/Api/LinkRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Downloadable/Api/LinkRepositoryTest.php index 2cc528af3e84e..c881969a3b679 100644 --- a/dev/tests/api-functional/testsuite/Magento/Downloadable/Api/LinkRepositoryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Downloadable/Api/LinkRepositoryTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Downloadable\Api; use Magento\Catalog\Api\ProductRepositoryInterface; @@ -240,7 +241,7 @@ public function testCreateSavesProvidedUrls() /** * @magentoApiDataFixture Magento/Downloadable/_files/product_downloadable.php * @expectedException \Exception - * @expectedExceptionMessage Invalid link type. + * @expectedExceptionMessage The link type is invalid. Verify and try again. */ public function testCreateThrowsExceptionIfLinkTypeIsNotSpecified() { @@ -542,7 +543,7 @@ public function getInvalidNumberOfDownloads() /** * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php * @expectedException \Exception - * @expectedExceptionMessage Provided product must be type 'downloadable'. + * @expectedExceptionMessage The product needs to be the downloadable type. Verify the product and try again. */ public function testCreateThrowsExceptionIfTargetProductTypeIsNotDownloadable() { @@ -567,7 +568,7 @@ public function testCreateThrowsExceptionIfTargetProductTypeIsNotDownloadable() /** * @expectedException \Exception - * @expectedExceptionMessage Requested product doesn't exist + * @expectedExceptionMessage The product that was requested doesn't exist. Verify the product and try again. */ public function testCreateThrowsExceptionIfTargetProductDoesNotExist() { @@ -662,7 +663,7 @@ public function testUpdateSavesDataInGlobalScopeAndDoesNotAffectValuesStoredInSt /** * @expectedException \Exception - * @expectedExceptionMessage Requested product doesn't exist + * @expectedExceptionMessage The product that was requested doesn't exist. Verify the product and try again. */ public function testUpdateThrowsExceptionIfTargetProductDoesNotExist() { @@ -687,7 +688,7 @@ public function testUpdateThrowsExceptionIfTargetProductDoesNotExist() /** * @magentoApiDataFixture Magento/Downloadable/_files/product_downloadable.php * @expectedException \Exception - * @expectedExceptionMessage There is no downloadable link with provided ID. + * @expectedExceptionMessage No downloadable link with the provided ID was found. Verify the ID and try again. */ public function testUpdateThrowsExceptionIfThereIsNoDownloadableLinkWithGivenId() { @@ -815,7 +816,7 @@ public function testDelete() /** * @expectedException \Exception - * @expectedExceptionMessage There is no downloadable link with provided ID. + * @expectedExceptionMessage No downloadable link with the provided ID was found. Verify the ID and try again. */ public function testDeleteThrowsExceptionIfThereIsNoDownloadableLinkWithGivenId() { @@ -849,7 +850,7 @@ public function testGetListForAbsentProduct($urlTail, $method) $requestData = ['sku' => $sku]; - $expectedMessage = 'Requested product doesn\'t exist'; + $expectedMessage = "The product that was requested doesn't exist. Verify the product and try again."; try { $this->_webApiCall($serviceInfo, $requestData); } catch (\SoapFault $e) { diff --git a/dev/tests/api-functional/testsuite/Magento/Downloadable/Api/SampleRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Downloadable/Api/SampleRepositoryTest.php index c3f9473d8f094..b537947d5e4db 100644 --- a/dev/tests/api-functional/testsuite/Magento/Downloadable/Api/SampleRepositoryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Downloadable/Api/SampleRepositoryTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Downloadable\Api; use Magento\Catalog\Model\Product; @@ -205,7 +206,7 @@ public function testCreateSavesProvidedUrls() /** * @magentoApiDataFixture Magento/Downloadable/_files/product_downloadable.php * @expectedException \Exception - * @expectedExceptionMessage Invalid sample type. + * @expectedExceptionMessage The sample type is invalid. Verify the sample type and try again. */ public function testCreateThrowsExceptionIfSampleTypeIsInvalid() { @@ -325,7 +326,7 @@ public function getInvalidSortOrder() /** * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php * @expectedException \Exception - * @expectedExceptionMessage Provided product must be type 'downloadable'. + * @expectedExceptionMessage The product needs to be the downloadable type. Verify the product and try again. */ public function testCreateThrowsExceptionIfTargetProductTypeIsNotDownloadable() { @@ -345,7 +346,7 @@ public function testCreateThrowsExceptionIfTargetProductTypeIsNotDownloadable() /** * @expectedException \Exception - * @expectedExceptionMessage Requested product doesn't exist + * @expectedExceptionMessage The product that was requested doesn't exist. Verify the product and try again. */ public function testCreateThrowsExceptionIfTargetProductDoesNotExist() { @@ -422,7 +423,7 @@ public function testUpdateSavesDataInGlobalScopeAndDoesNotAffectValuesStoredInSt /** * @expectedException \Exception - * @expectedExceptionMessage Requested product doesn't exist + * @expectedExceptionMessage The product that was requested doesn't exist. Verify the product and try again. */ public function testUpdateThrowsExceptionIfTargetProductDoesNotExist() { @@ -443,7 +444,7 @@ public function testUpdateThrowsExceptionIfTargetProductDoesNotExist() /** * @magentoApiDataFixture Magento/Downloadable/_files/product_downloadable_with_files.php * @expectedException \Exception - * @expectedExceptionMessage There is no downloadable sample with provided ID. + * @expectedExceptionMessage No downloadable sample with the provided ID was found. Verify the ID and try again. */ public function testUpdateThrowsExceptionIfThereIsNoDownloadableSampleWithGivenId() { @@ -506,7 +507,7 @@ public function testDelete() /** * @expectedException \Exception - * @expectedExceptionMessage There is no downloadable sample with provided ID. + * @expectedExceptionMessage No downloadable sample with the provided ID was found. Verify the ID and try again. */ public function testDeleteThrowsExceptionIfThereIsNoDownloadableSampleWithGivenId() { diff --git a/dev/tests/api-functional/testsuite/Magento/Eav/Api/AttributeSetManagementTest.php b/dev/tests/api-functional/testsuite/Magento/Eav/Api/AttributeSetManagementTest.php index 91576b7b049a2..17fc436b2e401 100644 --- a/dev/tests/api-functional/testsuite/Magento/Eav/Api/AttributeSetManagementTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Eav/Api/AttributeSetManagementTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Eav\Api; use Magento\TestFramework\Helper\Bootstrap; @@ -145,7 +146,7 @@ public function testCreateThrowsExceptionIfGivenEntityTypeDoesNotExist() /** * @expectedException \Exception - * @expectedExceptionMessage Attribute set name is empty. + * @expectedExceptionMessage The attribute set name is empty. Enter the name and try again. */ public function testCreateThrowsExceptionIfAttributeSetNameIsEmpty() { @@ -169,7 +170,7 @@ public function testCreateThrowsExceptionIfAttributeSetWithGivenNameAlreadyExist $entityTypeCode = 'catalog_product'; $entityType = $this->getEntityTypeByCode($entityTypeCode); $attributeSetName = 'Default'; - $expectedMessage = 'An attribute set named "Default" already exists.'; + $expectedMessage = 'A "Default" attribute set name already exists. Create a new name and try again.'; $arguments = [ 'entityTypeCode' => $entityTypeCode, diff --git a/dev/tests/api-functional/testsuite/Magento/Eav/Api/AttributeSetRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Eav/Api/AttributeSetRepositoryTest.php index 611234ce9a54e..4e2d98279a4c4 100644 --- a/dev/tests/api-functional/testsuite/Magento/Eav/Api/AttributeSetRepositoryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Eav/Api/AttributeSetRepositoryTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Eav\Api; use Magento\Framework\Api\FilterBuilder; @@ -140,7 +141,7 @@ public function testDeleteById() /** * @expectedException \Exception - * @expectedExceptionMessage Default attribute set can not be deleted + * @expectedExceptionMessage The default attribute set can't be deleted. */ public function testDeleteByIdDefaultAttributeSet() { diff --git a/dev/tests/api-functional/testsuite/Magento/Integration/Model/AdminTokenServiceTest.php b/dev/tests/api-functional/testsuite/Magento/Integration/Model/AdminTokenServiceTest.php index 3fb7b3417b679..4b09361fe023b 100644 --- a/dev/tests/api-functional/testsuite/Magento/Integration/Model/AdminTokenServiceTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Integration/Model/AdminTokenServiceTest.php @@ -302,13 +302,13 @@ private function assertInputExceptionMessages($exception) 'message' => 'One or more input exceptions have occurred.', 'errors' => [ [ - 'message' => '%fieldName is a required field.', + 'message' => '"%fieldName" is required. Enter and try again.', 'parameters' => [ 'fieldName' => 'username', ], ], [ - 'message' => '%fieldName is a required field.', + 'message' => '"%fieldName" is required. Enter and try again.', 'parameters' => [ 'fieldName' => 'password', ] @@ -332,7 +332,8 @@ private function assertInvalidCredentialsException($exception) ); $exceptionData = $this->processRestExceptionResult($exception); $expectedExceptionData = [ - 'message' => 'You did not sign in correctly or your account is temporarily disabled.' + 'message' => 'The account sign-in was incorrect or your account is disabled temporarily. ' + . 'Please wait and try again later.' ]; $this->assertEquals($expectedExceptionData, $exceptionData, "Exception message is invalid."); } @@ -351,7 +352,7 @@ private function assertUnauthorizedAccessException($exception) ); $exceptionData = $this->processRestExceptionResult($exception); $expectedExceptionData = [ - 'message' => 'Consumer is not authorized to access %resources', + 'message' => "The consumer isn't authorized to access %resources.", 'parameters' => [ 'resources' => 'Magento_Backend::store' ] diff --git a/dev/tests/api-functional/testsuite/Magento/Integration/Model/CustomerTokenServiceTest.php b/dev/tests/api-functional/testsuite/Magento/Integration/Model/CustomerTokenServiceTest.php index 1e0a0cb49acc8..05e97a307fec1 100644 --- a/dev/tests/api-functional/testsuite/Magento/Integration/Model/CustomerTokenServiceTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Integration/Model/CustomerTokenServiceTest.php @@ -168,13 +168,13 @@ private function assertInputExceptionMessages($e) 'message' => 'One or more input exceptions have occurred.', 'errors' => [ [ - 'message' => '%fieldName is a required field.', + 'message' => '"%fieldName" is required. Enter and try again.', 'parameters' => [ 'fieldName' => 'username', ], ], [ - 'message' => '%fieldName is a required field.', + 'message' => '"%fieldName" is required. Enter and try again.', 'parameters' => [ 'fieldName' => 'password', ] @@ -286,7 +286,8 @@ private function assertInvalidCredentialsException($e) $this->assertEquals(HTTPExceptionCodes::HTTP_UNAUTHORIZED, $e->getCode(), "Response HTTP code is invalid."); $exceptionData = $this->processRestExceptionResult($e); $expectedExceptionData = [ - 'message' => 'You did not sign in correctly or your account is temporarily disabled.' + 'message' => 'The account sign-in was incorrect or your account is disabled temporarily. ' + . 'Please wait and try again later.' ]; $this->assertEquals($expectedExceptionData, $exceptionData, "Exception message is invalid."); } diff --git a/dev/tests/api-functional/testsuite/Magento/Quote/Api/CartManagementTest.php b/dev/tests/api-functional/testsuite/Magento/Quote/Api/CartManagementTest.php index 66102699bb8fd..80a4acbc563d6 100644 --- a/dev/tests/api-functional/testsuite/Magento/Quote/Api/CartManagementTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Quote/Api/CartManagementTest.php @@ -237,7 +237,7 @@ public function testAssignCustomerThrowsExceptionIfThereIsNoCartWithGivenId() /** * @magentoApiDataFixture Magento/Sales/_files/quote_with_customer.php * @expectedException \Exception - * @expectedExceptionMessage Cannot assign customer to the given cart. The cart is not anonymous. + * @expectedExceptionMessage The customer can't be assigned to the cart because the cart isn't anonymous. */ public function testAssignCustomerThrowsExceptionIfTargetCartIsNotAnonymous() { @@ -272,7 +272,7 @@ public function testAssignCustomerThrowsExceptionIfTargetCartIsNotAnonymous() * @magentoApiDataFixture Magento/Sales/_files/quote.php * @magentoApiDataFixture Magento/Customer/_files/customer_non_default_website_id.php * @expectedException \Exception - * @expectedExceptionMessage Cannot assign customer to the given cart. The cart belongs to different store. + * @expectedExceptionMessage The customer can't be assigned to the cart. The cart belongs to a different store. */ public function testAssignCustomerThrowsExceptionIfCartIsAssignedToDifferentStore() { @@ -309,7 +309,6 @@ public function testAssignCustomerThrowsExceptionIfCartIsAssignedToDifferentStor * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php * @magentoApiDataFixture Magento/Sales/_files/quote.php * @expectedException \Exception - * @expectedExceptionMessage Cannot assign customer to the given cart. Customer already has active cart. */ public function testAssignCustomerThrowsExceptionIfCustomerAlreadyHasActiveCart() { @@ -344,6 +343,10 @@ public function testAssignCustomerThrowsExceptionIfCustomerAlreadyHasActiveCart( 'storeId' => 1, ]; $this->_webApiCall($serviceInfo, $requestData); + + $this->expectExceptionMessage( + "The customer can't be assigned to the cart because the customer already has an active cart." + ); } /** diff --git a/dev/tests/api-functional/testsuite/Magento/Quote/Api/CouponManagementTest.php b/dev/tests/api-functional/testsuite/Magento/Quote/Api/CouponManagementTest.php index f50276fd6ce60..1aee493d8e0cb 100644 --- a/dev/tests/api-functional/testsuite/Magento/Quote/Api/CouponManagementTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Quote/Api/CouponManagementTest.php @@ -80,7 +80,7 @@ public function testDelete() /** * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php * @expectedException \Exception - * @expectedExceptionMessage Coupon code is not valid + * @expectedExceptionMessage The coupon code isn't valid. Verify the code and try again. */ public function testSetCouponThrowsExceptionIfCouponDoesNotExist() { @@ -215,7 +215,7 @@ public function testDeleteMyCoupon() /** * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php * @expectedException \Exception - * @expectedExceptionMessage Coupon code is not valid + * @expectedExceptionMessage The coupon code isn't valid. Verify the code and try again. */ public function testSetMyCouponThrowsExceptionIfCouponDoesNotExist() { diff --git a/dev/tests/api-functional/testsuite/Magento/Quote/Api/GuestCartManagementTest.php b/dev/tests/api-functional/testsuite/Magento/Quote/Api/GuestCartManagementTest.php index e579fb3f62036..bbd1e59f83f90 100644 --- a/dev/tests/api-functional/testsuite/Magento/Quote/Api/GuestCartManagementTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Quote/Api/GuestCartManagementTest.php @@ -182,7 +182,7 @@ public function testAssignCustomerThrowsExceptionIfThereIsNoCartWithGivenId() /** * @magentoApiDataFixture Magento/Sales/_files/quote_with_customer.php * @expectedException \Exception - * @expectedExceptionMessage Cannot assign customer to the given cart. The cart is not anonymous. + * @expectedExceptionMessage The customer can't be assigned to the cart because the cart isn't anonymous. */ public function testAssignCustomerThrowsExceptionIfTargetCartIsNotAnonymous() { @@ -234,7 +234,6 @@ public function testAssignCustomerThrowsExceptionIfTargetCartIsNotAnonymous() * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php * @magentoApiDataFixture Magento/Sales/_files/quote.php * @expectedException \Exception - * @expectedExceptionMessage Cannot assign customer to the given cart. Customer already has active cart. */ public function testAssignCustomerThrowsExceptionIfCustomerAlreadyHasActiveCart() { @@ -286,6 +285,10 @@ public function testAssignCustomerThrowsExceptionIfCustomerAlreadyHasActiveCart( 'storeId' => 1, ]; $this->_webApiCall($serviceInfo, $requestData); + + $this->expectExceptionMessage( + "The customer can't be assigned to the cart because the customer already has an active cart." + ); } /** @@ -330,7 +333,7 @@ public function testPlaceOrder() * @magentoApiDataFixture Magento/Sales/_files/quote.php * @magentoApiDataFixture Magento/Customer/_files/customer.php * @expectedException \Exception - * @expectedExceptionMessage Cannot assign customer to the given cart. You don't have permission for this operation. + * @expectedExceptionMessage You don't have the correct permissions to assign the customer to the cart. */ public function testAssignCustomerByGuestUser() { diff --git a/dev/tests/api-functional/testsuite/Magento/Quote/Api/GuestCouponManagementTest.php b/dev/tests/api-functional/testsuite/Magento/Quote/Api/GuestCouponManagementTest.php index 8dddf99868e4a..9815cf888ff95 100644 --- a/dev/tests/api-functional/testsuite/Magento/Quote/Api/GuestCouponManagementTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Quote/Api/GuestCouponManagementTest.php @@ -105,7 +105,7 @@ public function testDelete() /** * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php * @expectedException \Exception - * @expectedExceptionMessage Coupon code is not valid + * @expectedExceptionMessage The coupon code isn't valid. Verify the code and try again. */ public function testSetCouponThrowsExceptionIfCouponDoesNotExist() { diff --git a/dev/tests/api-functional/testsuite/Magento/Quote/Api/GuestPaymentMethodManagementTest.php b/dev/tests/api-functional/testsuite/Magento/Quote/Api/GuestPaymentMethodManagementTest.php index d0d0f865164c3..e8fa3a6dabce3 100644 --- a/dev/tests/api-functional/testsuite/Magento/Quote/Api/GuestPaymentMethodManagementTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Quote/Api/GuestPaymentMethodManagementTest.php @@ -156,7 +156,7 @@ public function testSetPaymentWithSimpleProduct() /** * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php * @expectedException \Exception - * @expectedExceptionMessage Shipping address is not set + * @expectedExceptionMessage The shipping address is missing. Set the address and try again. */ public function testSetPaymentWithSimpleProductWithoutAddress() { diff --git a/dev/tests/api-functional/testsuite/Magento/Quote/Api/PaymentMethodManagementTest.php b/dev/tests/api-functional/testsuite/Magento/Quote/Api/PaymentMethodManagementTest.php index 6fa83f58587ad..64d5290d5c511 100644 --- a/dev/tests/api-functional/testsuite/Magento/Quote/Api/PaymentMethodManagementTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Quote/Api/PaymentMethodManagementTest.php @@ -122,7 +122,7 @@ public function testSetPaymentWithSimpleProduct() /** * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php * @expectedException \Exception - * @expectedExceptionMessage Shipping address is not set + * @expectedExceptionMessage The shipping address is missing. Set the address and try again. */ public function testSetPaymentWithSimpleProductWithoutAddress() { diff --git a/dev/tests/api-functional/testsuite/Magento/Tax/Api/TaxRateRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Tax/Api/TaxRateRepositoryTest.php index ffd6a3fe39043..3b379fc7e0eb0 100644 --- a/dev/tests/api-functional/testsuite/Magento/Tax/Api/TaxRateRepositoryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Tax/Api/TaxRateRepositoryTest.php @@ -171,7 +171,7 @@ public function testCreateTaxRateWithoutValue() ); } catch (\Exception $e) { $errorObj = $this->processRestExceptionResult($e); - $this->assertEquals('%fieldName is a required field.', $errorObj['message']); + $this->assertEquals('"%fieldName" is required. Enter and try again.', $errorObj['message']); $this->assertEquals(['fieldName' => 'percentage_rate'], $errorObj['parameters']); } } @@ -491,7 +491,7 @@ public function testCannotDeleteTaxRate() $this->_webApiCall($serviceInfo, ['rateId' => $taxRateId]); $this->fail('Expected exception was not raised'); } catch (\Exception $e) { - $expectedMessage = 'The tax rate cannot be removed. It exists in a tax rule.'; + $expectedMessage = "The tax rate can't be removed because it exists in a tax rule."; $this->assertContains( $expectedMessage, diff --git a/dev/tests/api-functional/testsuite/Magento/Webapi/DeserializationTest.php b/dev/tests/api-functional/testsuite/Magento/Webapi/DeserializationTest.php index 98ba33f940f2c..1e870204f00c1 100644 --- a/dev/tests/api-functional/testsuite/Magento/Webapi/DeserializationTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Webapi/DeserializationTest.php @@ -38,7 +38,8 @@ public function testPostRequestWithEmptyBody() 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST, ], ]; - $expectedMessage = '{"message":"%fieldName is a required field.","parameters":{"fieldName":"item"}}'; + $expectedMessage = + '{"message":"\"%fieldName\" is required. Enter and try again.","parameters":{"fieldName":"item"}}'; try { $this->_webApiCall($serviceInfo, RestClient::EMPTY_REQUEST_BODY); } catch (\Exception $e) { @@ -64,7 +65,8 @@ public function testPutRequestWithEmptyBody() 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_PUT, ], ]; - $expectedMessage = '{"message":"%fieldName is a required field.","parameters":{"fieldName":"entityItem"}}'; + $expectedMessage = + '{"message":"\"%fieldName\" is required. Enter and try again.","parameters":{"fieldName":"entityItem"}}'; try { $this->_webApiCall($serviceInfo, RestClient::EMPTY_REQUEST_BODY); } catch (\Exception $e) { diff --git a/dev/tests/api-functional/testsuite/Magento/Webapi/Routing/BaseService.php b/dev/tests/api-functional/testsuite/Magento/Webapi/Routing/BaseService.php index 853c92499aeed..8d59598d7ccc7 100644 --- a/dev/tests/api-functional/testsuite/Magento/Webapi/Routing/BaseService.php +++ b/dev/tests/api-functional/testsuite/Magento/Webapi/Routing/BaseService.php @@ -25,7 +25,7 @@ protected function assertUnauthorizedException($serviceInfo, $requestData = null $this->_assertSoapException( $serviceInfo, $requestData, - 'Consumer is not authorized to access %resources' + "The consumer isn't authorized to access %resources." ); } elseif (TESTS_WEB_API_ADAPTER == self::ADAPTER_REST) { $this->_assertRestUnauthorizedException($serviceInfo, $requestData); @@ -44,7 +44,7 @@ protected function _assertRestUnauthorizedException($serviceInfo, $requestData = $this->_webApiCall($serviceInfo, $requestData); } catch (\Exception $e) { $this->assertContains( - '{"message":"Consumer is not authorized to access %resources"', + '{"message":"The consumer isn\'t authorized to access %resources.', $e->getMessage(), sprintf( 'REST routing did not fail as expected for the method "%s" of service "%s"', diff --git a/dev/tests/api-functional/testsuite/Magento/Webapi/Routing/RestErrorHandlingTest.php b/dev/tests/api-functional/testsuite/Magento/Webapi/Routing/RestErrorHandlingTest.php index 29bb630ff6cd3..62400b1f30ce5 100644 --- a/dev/tests/api-functional/testsuite/Magento/Webapi/Routing/RestErrorHandlingTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Webapi/Routing/RestErrorHandlingTest.php @@ -5,6 +5,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Webapi\Routing; use Magento\TestFramework\Helper\Bootstrap; @@ -72,7 +73,7 @@ public function testUnauthorized() $serviceInfo, [], WebapiException::HTTP_UNAUTHORIZED, - 'Consumer is not authorized to access %1', + "The consumer isn't authorized to access %1.", ['resourceN'] ); } diff --git a/dev/tests/api-functional/testsuite/Magento/Webapi/Routing/SoapErrorHandlingTest.php b/dev/tests/api-functional/testsuite/Magento/Webapi/Routing/SoapErrorHandlingTest.php index ffcb2e52acb72..61ba247645b31 100644 --- a/dev/tests/api-functional/testsuite/Magento/Webapi/Routing/SoapErrorHandlingTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Webapi/Routing/SoapErrorHandlingTest.php @@ -110,7 +110,7 @@ public function testUnauthorized() } catch (\SoapFault $e) { $this->checkSoapFault( $e, - 'Consumer is not authorized to access %resources', + "The consumer isn't authorized to access %resources.", 'env:Sender' ); } diff --git a/dev/tests/api-functional/testsuite/Magento/Webapi/WsdlGenerationFromDataObjectTest.php b/dev/tests/api-functional/testsuite/Magento/Webapi/WsdlGenerationFromDataObjectTest.php index 840649cec8db8..86f27908a96d5 100644 --- a/dev/tests/api-functional/testsuite/Magento/Webapi/WsdlGenerationFromDataObjectTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Webapi/WsdlGenerationFromDataObjectTest.php @@ -71,7 +71,7 @@ public function testNoAuthorizedServices() curl_setopt($connection, CURLOPT_RETURNTRANSFER, 1); $responseContent = curl_exec($connection); $this->assertEquals(curl_getinfo($connection, CURLINFO_HTTP_CODE), 401); - $this->assertContains("Consumer is not authorized to access %resources", $responseContent); + $this->assertContains("The consumer isn't authorized to access %resources.", $responseContent); } public function testInvalidWsdlUrlNoServices() diff --git a/dev/tests/functional/lib/Magento/Mtf/Util/Command/Cli/Config.php b/dev/tests/functional/lib/Magento/Mtf/Util/Command/Cli/Config.php new file mode 100644 index 0000000000000..e7ce89a2c4ce9 --- /dev/null +++ b/dev/tests/functional/lib/Magento/Mtf/Util/Command/Cli/Config.php @@ -0,0 +1,45 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Mtf\Util\Command\Cli; + +use Magento\Mtf\Util\Command\Cli; + +/** + * Handle set configuration for test execution. + */ +class Config extends Cli +{ + /** + * Parameter for reindex command. + */ + const PARAM_CONFIG_SET = 'config:set'; + + /** + * Set configuration. + * + * @param string $path + * @param string $value + * @param string|null $scope + * @param string|null $scopeCode + * @return void + */ + public function setConfig($path, $value, $scope = null, $scopeCode = null) + { + $configurationString = ''; + + if ($scope !== null) { + $configurationString.= sprintf('--scope=%s ', $scope); + } + + if ($scopeCode !== null) { + $configurationString.= sprintf('--scope-code=%s ', $scopeCode); + } + $configurationString.= sprintf('%s %s', $path, $value); + + parent::execute(Config::PARAM_CONFIG_SET . ' ' . $configurationString); + } +} diff --git a/dev/tests/functional/tests/app/Magento/Authorizenet/Test/TestCase/OnePageCheckoutDeclinedTest.xml b/dev/tests/functional/tests/app/Magento/Authorizenet/Test/TestCase/OnePageCheckoutDeclinedTest.xml index 1c589afcc1e20..00c1a1557e05b 100644 --- a/dev/tests/functional/tests/app/Magento/Authorizenet/Test/TestCase/OnePageCheckoutDeclinedTest.xml +++ b/dev/tests/functional/tests/app/Magento/Authorizenet/Test/TestCase/OnePageCheckoutDeclinedTest.xml @@ -17,7 +17,7 @@ <data name="payment/method" xsi:type="string">authorizenet_directpost</data> <data name="creditCard/dataset" xsi:type="string">visa_default</data> <data name="configData" xsi:type="string">authorizenet, authorizenet_wrong_credentials</data> - <data name="expectedErrorMessage" xsi:type="string">An error occurred on the server. Please try to place the order again.</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="tag" xsi:type="string">test_type:3rd_party_test, severity:S2</data> <constraint name="Magento\Checkout\Test\Constraint\AssertCheckoutErrorMessage" /> </variation> diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertAttributeSetForm.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertAttributeSetForm.php index 87ae650d7dc18..1facc65617906 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertAttributeSetForm.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertAttributeSetForm.php @@ -43,7 +43,7 @@ public function processAssert( \PHPUnit_Framework_Assert::assertEquals( $filterAttribute['set_name'], $productSetEdit->getAttributeSetEditBlock()->getAttributeSetName(), - 'Attribute Set not found' + 'The attribute set wasn\'t found.' . "\nExpected: " . $filterAttribute['set_name'] . "\nActual: " . $productSetEdit->getAttributeSetEditBlock()->getAttributeSetName() ); diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertAttributeSetNotInGrid.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertAttributeSetNotInGrid.php index 945014371631d..0e465f218ccf8 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertAttributeSetNotInGrid.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertAttributeSetNotInGrid.php @@ -36,7 +36,8 @@ public function processAssert(CatalogProductSetIndex $productSetPage, CatalogAtt $productSetPage->open(); \PHPUnit_Framework_Assert::assertFalse( $productSetPage->getGrid()->isRowVisible($filterAttributeSet), - 'An attribute set named "' . $filterAttributeSet['set_name'] . '" is present in Attribute Set grid.' + 'A "' . $filterAttributeSet['set_name'] . + '" attribute set name already exists. Create a new name and try again.' ); } diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertAttributeSetOnProductForm.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertAttributeSetOnProductForm.php index 64187b048f3d8..2a6ed4de08fb8 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertAttributeSetOnProductForm.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertAttributeSetOnProductForm.php @@ -66,7 +66,7 @@ public function processAssert( \PHPUnit_Framework_Assert::assertEquals( $attributeSet->getAttributeSetName(), $formAttributeSet, - 'Attribute Set not found on Product form.' + 'The attribute set wasn\'t found on product form.' . "\nExpected: " . $attributeSet->getAttributeSetName() . "\nActual: " . $formAttributeSet ); diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeIsUnique.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeIsUnique.php index 1e417263abed8..688d2821e95f0 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeIsUnique.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeIsUnique.php @@ -25,7 +25,7 @@ class AssertProductAttributeIsUnique extends AbstractConstraint /** * Expected message. */ - const UNIQUE_MESSAGE = 'The value of attribute "%s" must be unique'; + const UNIQUE_MESSAGE = 'The value of the "%s" attribute isn\'t unique. Set a unique value and try again.'; /** * Fixture factory. diff --git a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Constraint/AssertAdvancedSearchEmptyTerm.php b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Constraint/AssertAdvancedSearchEmptyTerm.php index bb46f914aead6..1b2238ded9c54 100644 --- a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Constraint/AssertAdvancedSearchEmptyTerm.php +++ b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Constraint/AssertAdvancedSearchEmptyTerm.php @@ -17,7 +17,7 @@ class AssertAdvancedSearchEmptyTerm extends AbstractConstraint /** * Specify search term error message. */ - const ERROR_MESSAGE = 'Please specify at least one search term.'; + const ERROR_MESSAGE = 'Enter a search term and try again.'; /** * Assert that error message is displayed after searching without entering any search terms. diff --git a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/AdvancedSearchEntityTest.xml b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/AdvancedSearchEntityTest.xml index 386ac28f6c472..4744fa7756c4e 100644 --- a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/AdvancedSearchEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/AdvancedSearchEntityTest.xml @@ -117,7 +117,7 @@ <constraint name="Magento\CatalogSearch\Test\Constraint\AssertAdvancedSearchNoResult" /> </variation> <variation name="AdvancedSearchEntityTestVariation15" summary="Do Advanced Search without entering data" ticketId="MAGETWO-14859"> - <data name="issue" xsi:type="string">MAGETWO-18537: "Please specify at least one search term." error message is missed in Advanced Search</data> + <data name="issue" xsi:type="string">MAGETWO-18537: "Enter a search term and try again." error message is missed in Advanced Search</data> <data name="productSearch/data/name" xsi:type="string" /> <constraint name="Magento\CatalogSearch\Test\Constraint\AssertAdvancedSearchEmptyTerm" /> </variation> diff --git a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/SearchEntityResultsTest.xml b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/SearchEntityResultsTest.xml index d99ee5e234e4d..9a6a66091d427 100644 --- a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/SearchEntityResultsTest.xml +++ b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/SearchEntityResultsTest.xml @@ -102,7 +102,7 @@ <variation name="SearchEntityResultsTestVariation18" summary="Search Configurable Product with Enabled and Disabled Children." ticketId="MAGETWO-69181"> <data name="catalogSearch/data/query_text/value" xsi:type="string">configurableProduct::one_simple_product_not_visible_individually::name</data> <constraint name="Magento\CatalogSearch\Test\Constraint\AssertCatalogSearchResult" /> - <constraint name="Magento\CatalogSearch\Test\Constraint\AssertConfigurableWithDisabledOtpionCatalogSearchNoResult" /> + <constraint name="Magento\CatalogSearch\Test\Constraint\AssertConfigurableWithDisabledOptionCatalogSearchNoResult" /> </variation> </testCase> </config> diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertChangePasswordFailMessage.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertChangePasswordFailMessage.php index 1cc0a94f8812b..361a9d697e430 100644 --- a/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertChangePasswordFailMessage.php +++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertChangePasswordFailMessage.php @@ -18,7 +18,7 @@ class AssertChangePasswordFailMessage extends AbstractConstraint /** * Fail message */ - const FAIL_MESSAGE = 'The password doesn\'t match this account.'; + const FAIL_MESSAGE = "The password doesn't match this account. Verify the password and try again."; /** * Assert that fail message is present diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerBackendDuplicateErrorMessage.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerBackendDuplicateErrorMessage.php index d4658cd2206c4..805f4d923385a 100644 --- a/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerBackendDuplicateErrorMessage.php +++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerBackendDuplicateErrorMessage.php @@ -17,7 +17,7 @@ class AssertCustomerBackendDuplicateErrorMessage extends AbstractConstraint /** * Error save message text. */ - const ERROR_SAVE_MESSAGE = 'A customer with the same email already exists in an associated website.'; + const ERROR_SAVE_MESSAGE = 'A customer with the same email address already exists in an associated website.'; /** * Asserts that error message is displayed while creating customer with the same email. diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerLoginErrorMessage.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerLoginErrorMessage.php index 9cc30b25d37e7..d28faa7ff6fa7 100644 --- a/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerLoginErrorMessage.php +++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerLoginErrorMessage.php @@ -17,7 +17,8 @@ class AssertCustomerLoginErrorMessage extends AbstractConstraint /** * Customer login error message. */ - const ERROR_MESSAGE = 'You did not sign in correctly or your account is temporarily disabled.'; + const ERROR_MESSAGE = + 'The account sign-in was incorrect or your account is disabled temporarily. Please wait and try again later.'; /** * Assert that customer login error message is displayed. diff --git a/dev/tests/functional/tests/app/Magento/Integration/Test/Constraint/AssertIncorrectUserPassword.php b/dev/tests/functional/tests/app/Magento/Integration/Test/Constraint/AssertIncorrectUserPassword.php index d6308752e0df5..dbdd8f0c3708a 100644 --- a/dev/tests/functional/tests/app/Magento/Integration/Test/Constraint/AssertIncorrectUserPassword.php +++ b/dev/tests/functional/tests/app/Magento/Integration/Test/Constraint/AssertIncorrectUserPassword.php @@ -15,7 +15,7 @@ */ class AssertIncorrectUserPassword extends AbstractConstraint { - const ERROR_MESSAGE = "You have entered an invalid password for current user."; + const ERROR_MESSAGE = "The password entered for the current user is invalid. Verify the password and try again."; /** * Assert that an error message is displayed on the Integration page in case current user password is incorrect. diff --git a/dev/tests/functional/tests/app/Magento/Integration/Test/Constraint/AssertIntegrationNameDuplicationErrorMessage.php b/dev/tests/functional/tests/app/Magento/Integration/Test/Constraint/AssertIntegrationNameDuplicationErrorMessage.php index e07572d3aee40..d947e842830c8 100644 --- a/dev/tests/functional/tests/app/Magento/Integration/Test/Constraint/AssertIntegrationNameDuplicationErrorMessage.php +++ b/dev/tests/functional/tests/app/Magento/Integration/Test/Constraint/AssertIntegrationNameDuplicationErrorMessage.php @@ -15,7 +15,7 @@ */ class AssertIntegrationNameDuplicationErrorMessage extends AbstractConstraint { - const ERROR_DUPLICATE_INTEGRATION_NAME = "Integration with name '%s' exists."; + const ERROR_DUPLICATE_INTEGRATION_NAME = 'The integration with name "%s" exists.'; /** * Assert error message is displayed in message block. 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 7a4a1863c4ae6..d4f75f483d725 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">An error occurred on the server. Please try to place the order again.</data> + <data name="expectedErrorMessage" xsi:type="string">A server error stopped your order from being placed. Please try to place your order again.</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">An error occurred on the server. Please try to place the order again.</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="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">An error occurred on the server. Please try to place the order again.</data> + <data name="expectedErrorMessage" xsi:type="string">A server error stopped your order from being placed. Please try to place your order again.</data> <constraint name="Magento\Checkout\Test\Constraint\AssertCheckoutErrorMessage" /> </variation> </testCase> diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Handler/OrderInjectable/Webapi.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Handler/OrderInjectable/Webapi.php index 508ea13b419ca..073fb0967144c 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/Handler/OrderInjectable/Webapi.php +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Handler/OrderInjectable/Webapi.php @@ -171,7 +171,7 @@ protected function setCoupon(OrderInjectable $order) $this->webapiTransport->close(); if ($response !== true) { $this->eventManager->dispatchEvent(['webapi_failed'], [$response]); - throw new \Exception('Could not apply coupon code!'); + throw new \Exception("The coupon code couldn't be applied. Verify the coupon code and try again."); } } @@ -243,7 +243,7 @@ protected function setShippingInformation(OrderInjectable $order) $this->webapiTransport->close(); if (!isset($response['payment_methods'], $response['totals'])) { $this->eventManager->dispatchEvent(['webapi_failed'], [$response]); - throw new \Exception('Could not set shipping method to quote!'); + throw new \Exception("The shipping method can't be set to quote."); } } diff --git a/dev/tests/functional/tests/app/Magento/Security/Test/Constraint/AssertCustomerIsLocked.php b/dev/tests/functional/tests/app/Magento/Security/Test/Constraint/AssertCustomerIsLocked.php index 4badb10085b17..ab9c001a3d65b 100644 --- a/dev/tests/functional/tests/app/Magento/Security/Test/Constraint/AssertCustomerIsLocked.php +++ b/dev/tests/functional/tests/app/Magento/Security/Test/Constraint/AssertCustomerIsLocked.php @@ -15,7 +15,7 @@ class AssertCustomerIsLocked extends AbstractConstraint { const CUSTOMER_LOCKED_MESSAGE = - 'You did not sign in correctly or your account is temporarily disabled.'; + 'The account sign-in was incorrect or your account is disabled temporarily. Please wait and try again later.'; /** * Assert that customer locked message is present on customer login page. diff --git a/dev/tests/functional/tests/app/Magento/Security/Test/Constraint/AssertCustomerResetPasswordFailed.php b/dev/tests/functional/tests/app/Magento/Security/Test/Constraint/AssertCustomerResetPasswordFailed.php index 3089f4b830568..914e9d88d15a1 100644 --- a/dev/tests/functional/tests/app/Magento/Security/Test/Constraint/AssertCustomerResetPasswordFailed.php +++ b/dev/tests/functional/tests/app/Magento/Security/Test/Constraint/AssertCustomerResetPasswordFailed.php @@ -15,7 +15,8 @@ class AssertCustomerResetPasswordFailed extends AbstractConstraint { const TOO_MANY_RESET_REQUESTS_MESSAGE = - 'Too many password reset requests. Please wait and try again or contact hello@example.com.'; + 'We received too many requests for password resets. ' + . 'Please wait and try again later or contact hello@example.com.'; /** * Assert that customer forgot password message is present on customer account forgot password page. diff --git a/dev/tests/functional/tests/app/Magento/Security/Test/Constraint/AssertUserIsLocked.php b/dev/tests/functional/tests/app/Magento/Security/Test/Constraint/AssertUserIsLocked.php index c302c9bdf35ec..22abf3d552464 100644 --- a/dev/tests/functional/tests/app/Magento/Security/Test/Constraint/AssertUserIsLocked.php +++ b/dev/tests/functional/tests/app/Magento/Security/Test/Constraint/AssertUserIsLocked.php @@ -14,7 +14,8 @@ */ class AssertUserIsLocked extends AbstractConstraint { - const USER_ACCOUNT_DISABLED_MESSAGE = 'account is temporarily disabled'; + const USER_ACCOUNT_DISABLED_MESSAGE = 'The account sign-in was incorrect or your account is disabled temporarily. ' + . 'Please wait and try again later.'; /** * Verify that user account has been locked. diff --git a/dev/tests/functional/tests/app/Magento/Security/Test/Constraint/AssertUserPasswordResetFailed.php b/dev/tests/functional/tests/app/Magento/Security/Test/Constraint/AssertUserPasswordResetFailed.php index 2de3bb54f1838..7faa93c94edb0 100644 --- a/dev/tests/functional/tests/app/Magento/Security/Test/Constraint/AssertUserPasswordResetFailed.php +++ b/dev/tests/functional/tests/app/Magento/Security/Test/Constraint/AssertUserPasswordResetFailed.php @@ -15,7 +15,8 @@ class AssertUserPasswordResetFailed extends AbstractConstraint { const TOO_MANY_RESET_REQUESTS_MESSAGE = - 'Too many password reset requests. Please wait and try again or contact hello@example.com.'; + 'We received too many requests for password resets. ' + . 'Please wait and try again later or contact hello@example.com.'; /** * Assert that user reset password failed message is present on user login page. diff --git a/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenCreatingNewIntegrationTest.php b/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenCreatingNewIntegrationTest.php index 2562f57eb8041..778b04047952d 100644 --- a/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenCreatingNewIntegrationTest.php +++ b/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenCreatingNewIntegrationTest.php @@ -24,7 +24,8 @@ * 3. Start to create new Integration. * 4. Fill in all data according to data set (password is incorrect). * 5. Perform action 4 specified number of times. - * 6. "You have entered an invalid password for current user." appears after each attempt. + * 6. "The password entered for the current user is invalid. Verify the password and try again." appears after each + * attempt. * 7. Perform all assertions. * * @ZephyrId MAGETWO-49038 diff --git a/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenCreatingNewRoleTest.php b/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenCreatingNewRoleTest.php index f3dbf81ba5a14..5a62b0d599ca4 100644 --- a/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenCreatingNewRoleTest.php +++ b/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenCreatingNewRoleTest.php @@ -24,7 +24,8 @@ * 3. Start to create new User Role. * 4. Fill in all data according to data set (password is incorrect). * 5. Perform action 4 specified number of times. - * 6. "You have entered an invalid password for current user." appears after each attempt. + * 6. "The password entered for the current user is invalid. Verify the password and try again." appears after each + * attempt. * 7. Perform all assertions. * * @ZephyrId MAGETWO-49036 diff --git a/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenCreatingNewUserTest.php b/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenCreatingNewUserTest.php index 81b57dd5db88d..908f07456e0d8 100644 --- a/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenCreatingNewUserTest.php +++ b/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenCreatingNewUserTest.php @@ -23,7 +23,8 @@ * 3. Click on Add New User. * 4. Fill in all data according to data set (password is incorrect). * 5. Perform action 4 specified number of times. - * 6. "You have entered an invalid password for current user." appears after each attempt. + * 6. "The password entered for the current user is invalid. Verify the password and try again." appears after each + * attempt. * 7. Perform all assertions. * * @ZephyrId MAGETWO-49034 diff --git a/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenEditingIntegrationTest.php b/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenEditingIntegrationTest.php index d1e9c9dee9ec2..6927fa900cbdf 100644 --- a/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenEditingIntegrationTest.php +++ b/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenEditingIntegrationTest.php @@ -25,7 +25,8 @@ * 3. Start to edit existing Integration. * 4. Fill in all data according to data set (password is incorrect). * 5. Perform action 4 specified number of times. - * 6. "You have entered an invalid password for current user." appears after each attempt. + * 6. "The password entered for the current user is invalid. Verify the password and try again." appears after each + * attempt. * 7. Perform all assertions. * * @ZephyrId MAGETWO-49039 diff --git a/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockCustomerOnEditPageTest.php b/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockCustomerOnEditPageTest.php index 6f690302cba2a..d86346ae9a08b 100644 --- a/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockCustomerOnEditPageTest.php +++ b/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockCustomerOnEditPageTest.php @@ -26,7 +26,8 @@ * 3. Click "Change Password" link near "Contact Information". * 4. Fill form according to data set and save (current password is incorrect). * 5. Perform action for specified number of times. - * 6. "The password doesn't match this account." appears after each change password attempt. + * 6. "The password doesn't match this account. Verify the password and try again." appears after each + * change password attempt. * 7. Perform all assertions. * * @ZephyrId MAGETWO-50559 diff --git a/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertIncorrectUserPassword.php b/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertIncorrectUserPassword.php index 3463525a52995..4cca4361d0c6f 100644 --- a/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertIncorrectUserPassword.php +++ b/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertIncorrectUserPassword.php @@ -14,7 +14,7 @@ */ class AssertIncorrectUserPassword extends AbstractConstraint { - const ERROR_MESSAGE = 'You have entered an invalid password for current user.'; + const ERROR_MESSAGE = 'The password entered for the current user is invalid. Verify the password and try again.'; /** * Asserts that invalid password message equals to expected message. diff --git a/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertUserFailedLoginByPermissionMessage.php b/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertUserFailedLoginByPermissionMessage.php index 749075f699dde..d13b07d3f253a 100644 --- a/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertUserFailedLoginByPermissionMessage.php +++ b/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertUserFailedLoginByPermissionMessage.php @@ -15,7 +15,7 @@ */ class AssertUserFailedLoginByPermissionMessage extends AbstractConstraint { - const FAILED_LOGIN_MESSAGE = 'You need more permissions to access this.'; + const FAILED_LOGIN_MESSAGE = 'More permissions are needed to access this.'; /** * Verify incorrect credentials message while login to admin. diff --git a/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertUserFailedLoginMessage.php b/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertUserFailedLoginMessage.php index 8de16b494b4dc..23c291c4cc647 100644 --- a/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertUserFailedLoginMessage.php +++ b/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertUserFailedLoginMessage.php @@ -15,7 +15,8 @@ */ class AssertUserFailedLoginMessage extends AbstractConstraint { - const FAILED_LOGIN_MESSAGE = 'You did not sign in correctly or your account is temporarily disabled.'; + const FAILED_LOGIN_MESSAGE = + 'The account sign-in was incorrect or your account is disabled temporarily. Please wait and try again later.'; /** * Verify incorrect credentials message while login to admin diff --git a/dev/tests/functional/tests/app/Magento/User/Test/TestCase/LockAdminUserEntityTest.php b/dev/tests/functional/tests/app/Magento/User/Test/TestCase/LockAdminUserEntityTest.php index 9aaac5b17a4ca..65662e5405126 100644 --- a/dev/tests/functional/tests/app/Magento/User/Test/TestCase/LockAdminUserEntityTest.php +++ b/dev/tests/functional/tests/app/Magento/User/Test/TestCase/LockAdminUserEntityTest.php @@ -21,7 +21,8 @@ * Steps: * 1. Open Magento admin user login page. * 2. Enter incorrect password specified number of times. - * 3. "You did not sign in correctly or your account is temporarily disabled." appears after each login attempt. + * 3. "The account sign-in was incorrect or your account is disabled temporarily. Please wait and try again later." + * appears after each login attempt. * 4. Perform all assertions. * * @group AuthN_&_AuthZ diff --git a/dev/tests/integration/_files/Magento/TestModuleDirectoryZipCodes/etc/module.xml b/dev/tests/integration/_files/Magento/TestModuleDirectoryZipCodes/etc/module.xml index d3f1e3bc817f0..42fe40496fb2f 100644 --- a/dev/tests/integration/_files/Magento/TestModuleDirectoryZipCodes/etc/module.xml +++ b/dev/tests/integration/_files/Magento/TestModuleDirectoryZipCodes/etc/module.xml @@ -6,7 +6,7 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> - <module name="Magento_TestModuleDirectoryZipCodes" setup_version="0.0.1" active="true"> + <module name="Magento_TestModuleDirectoryZipCodes" active="true"> <sequence> <module name="Magento_Directory"/> </sequence> diff --git a/dev/tests/integration/_files/Magento/TestModuleFakePaymentMethod/etc/module.xml b/dev/tests/integration/_files/Magento/TestModuleFakePaymentMethod/etc/module.xml index de02321ca39ea..a6d0d87ec4e8f 100644 --- a/dev/tests/integration/_files/Magento/TestModuleFakePaymentMethod/etc/module.xml +++ b/dev/tests/integration/_files/Magento/TestModuleFakePaymentMethod/etc/module.xml @@ -6,7 +6,7 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> - <module name="Magento_TestModuleFakePaymentMethod" setup_version="0.0.1"> + <module name="Magento_TestModuleFakePaymentMethod"> <sequence> <module name="Magento_Sales"/> <module name="Magento_Payment"/> diff --git a/dev/tests/integration/_files/Magento/TestModuleSample/etc/module.xml b/dev/tests/integration/_files/Magento/TestModuleSample/etc/module.xml index 3b7f0dbbc6f45..488c79374cedb 100644 --- a/dev/tests/integration/_files/Magento/TestModuleSample/etc/module.xml +++ b/dev/tests/integration/_files/Magento/TestModuleSample/etc/module.xml @@ -6,6 +6,6 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> - <module name="Magento_TestModuleSample" setup_version="0.0.1" active="true"> + <module name="Magento_TestModuleSample" active="true"> </module> </config> diff --git a/dev/tests/integration/_files/Magento/TestModuleWysiwygConfig/Model/Config.php b/dev/tests/integration/_files/Magento/TestModuleWysiwygConfig/Model/Config.php new file mode 100644 index 0000000000000..b74c30c6eef65 --- /dev/null +++ b/dev/tests/integration/_files/Magento/TestModuleWysiwygConfig/Model/Config.php @@ -0,0 +1,32 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\TestModuleWysiwygConfig\Model; + +class Config implements \Magento\Framework\Data\Wysiwyg\ConfigProviderInterface +{ + /** + * Configuration override for WYSIWYG height + * @var string + */ + const CONFIG_HEIGHT = 'something_else'; + + /** + * Configuration override for WYSIWYG content css + * @var string + */ + const CONFIG_CONTENT_CSS = 'something_else.css'; + + /** + * @inheritdoc + */ + public function getConfig($config) + { + $config['height'] = self::CONFIG_HEIGHT; + $config['content_css'] = self::CONFIG_CONTENT_CSS; + + return $config; + } +} diff --git a/dev/tests/integration/_files/Magento/TestModuleWysiwygConfig/etc/adminhtml/di.xml b/dev/tests/integration/_files/Magento/TestModuleWysiwygConfig/etc/adminhtml/di.xml new file mode 100644 index 0000000000000..3366e5fc9685e --- /dev/null +++ b/dev/tests/integration/_files/Magento/TestModuleWysiwygConfig/etc/adminhtml/di.xml @@ -0,0 +1,25 @@ +<?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\Cms\Model\Wysiwyg\CompositeConfigProvider"> + <arguments> + <argument name="wysiwygConfigPostProcessor" xsi:type="array"> + <item name="testAdapter" xsi:type="string">Magento\TestModuleWysiwygConfig\Model\Config</item> + </argument> + <argument name="variablePluginConfigProvider" xsi:type="array"> + <item name="testAdapter" xsi:type="string">Magento\Variable\Model\Variable\ConfigProvider</item> + </argument> + <argument name="widgetPluginConfigProvider" xsi:type="array"> + <item name="testAdapter" xsi:type="string">Magento\Widget\Model\Widget\Config</item> + </argument> + <argument name="galleryConfigProvider" xsi:type="array"> + <item name="testAdapter" xsi:type="string">Magento\Cms\Model\Wysiwyg\Gallery\DefaultConfigProvider</item> + </argument> + </arguments> + </type> +</config> diff --git a/dev/tests/integration/_files/Magento/TestModuleWysiwygConfig/etc/module.xml b/dev/tests/integration/_files/Magento/TestModuleWysiwygConfig/etc/module.xml new file mode 100644 index 0000000000000..1d5fd912894ef --- /dev/null +++ b/dev/tests/integration/_files/Magento/TestModuleWysiwygConfig/etc/module.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:Module/etc/module.xsd"> + <module name="Magento_TestModuleWysiwygConfig" active="true"> + <sequence> + <module name="Magento_Cms"/> + </sequence> + </module> +</config> \ No newline at end of file diff --git a/dev/tests/setup-integration/_files/Magento/TestSetupModule2/registration.php b/dev/tests/integration/_files/Magento/TestModuleWysiwygConfig/registration.php similarity index 80% rename from dev/tests/setup-integration/_files/Magento/TestSetupModule2/registration.php rename to dev/tests/integration/_files/Magento/TestModuleWysiwygConfig/registration.php index cdf684229889c..04a6a7cbc05ba 100644 --- a/dev/tests/setup-integration/_files/Magento/TestSetupModule2/registration.php +++ b/dev/tests/integration/_files/Magento/TestModuleWysiwygConfig/registration.php @@ -7,6 +7,6 @@ use Magento\Framework\Component\ComponentRegistrar; $registrar = new ComponentRegistrar(); -if ($registrar->getPath(ComponentRegistrar::MODULE, 'Magento_TestSetupModule2') === null) { - ComponentRegistrar::register(ComponentRegistrar::MODULE, 'Magento_TestSetupModule2', __DIR__); +if ($registrar->getPath(ComponentRegistrar::MODULE, 'Magento_TestModuleWysiwygConfig') === null) { + ComponentRegistrar::register(ComponentRegistrar::MODULE, 'Magento_TestModuleWysiwygConfig', __DIR__); } diff --git a/dev/tests/integration/framework/Magento/TestFramework/Application.php b/dev/tests/integration/framework/Magento/TestFramework/Application.php index 25784d0073890..29bc3de4c2441 100644 --- a/dev/tests/integration/framework/Magento/TestFramework/Application.php +++ b/dev/tests/integration/framework/Magento/TestFramework/Application.php @@ -546,7 +546,7 @@ public function install($cleanup) private function copyAppConfigFiles() { $globalConfigFiles = Glob::glob( - $this->_globalConfigDir . '/{di.xml,*/di.xml,vendor_path.php}', + $this->_globalConfigDir . '/{di.xml,*/di.xml,db_schema.xml,vendor_path.php}', Glob::GLOB_BRACE ); foreach ($globalConfigFiles as $file) { @@ -626,7 +626,7 @@ protected function _ensureDirExists($dir) { if (!file_exists($dir)) { $old = umask(0); - mkdir($dir); + mkdir($dir, 0777, true); umask($old); } elseif (!is_dir($dir)) { throw new \Magento\Framework\Exception\LocalizedException(__("'%1' is not a directory.", $dir)); diff --git a/dev/tests/integration/testsuite/Magento/Backend/Controller/Adminhtml/AuthTest.php b/dev/tests/integration/testsuite/Magento/Backend/Controller/Adminhtml/AuthTest.php index 7233807d079bc..ef159e6230984 100644 --- a/dev/tests/integration/testsuite/Magento/Backend/Controller/Adminhtml/AuthTest.php +++ b/dev/tests/integration/testsuite/Magento/Backend/Controller/Adminhtml/AuthTest.php @@ -200,7 +200,12 @@ public function testIncorrectLogin($params) $this->getRequest()->setPostValue($params); $this->dispatch('backend/admin/auth/login'); $this->assertSessionMessages( - $this->equalTo(['You did not sign in correctly or your account is temporarily disabled.']), + $this->equalTo( + [ + 'The account sign-in was incorrect or your account is disabled temporarily. ' + . 'Please wait and try again later.' + ] + ), MessageInterface::TYPE_ERROR ); $backendUrlModel = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get( diff --git a/dev/tests/integration/testsuite/Magento/Backend/Controller/Adminhtml/CacheTest.php b/dev/tests/integration/testsuite/Magento/Backend/Controller/Adminhtml/CacheTest.php index 0525c68b04d14..04930661efb43 100644 --- a/dev/tests/integration/testsuite/Magento/Backend/Controller/Adminhtml/CacheTest.php +++ b/dev/tests/integration/testsuite/Magento/Backend/Controller/Adminhtml/CacheTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Backend\Controller\Adminhtml; /** @@ -72,7 +73,7 @@ public function testMassActionsInvalidTypes($action) $this->getRequest()->setParams(['types' => ['invalid_type_1', 'invalid_type_2', 'config']]); $this->dispatch('backend/admin/cache/' . $action); $this->assertSessionMessages( - $this->contains("Specified cache type(s) don't exist: invalid_type_1, invalid_type_2"), + $this->contains("These cache type(s) don't exist: invalid_type_1, invalid_type_2"), \Magento\Framework\Message\MessageInterface::TYPE_ERROR ); } diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/CategoryTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/CategoryTest.php index bfc7e33d5f771..11f49464bbd21 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/CategoryTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/CategoryTest.php @@ -339,7 +339,7 @@ public function testSaveActionCategoryWithDangerRequest() ); $this->dispatch('backend/catalog/category/save'); $this->assertSessionMessages( - $this->equalTo(['The value of attribute "Name" must be set']), + $this->equalTo(['The "Name" attribute value is empty. Set the attribute and try again.']), \Magento\Framework\Message\MessageInterface::TYPE_ERROR ); } diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/ProductTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/ProductTest.php index e1b5b9e0a2c8c..3e67095edcea9 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/ProductTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/ProductTest.php @@ -15,7 +15,7 @@ public function testSaveActionWithDangerRequest() $this->getRequest()->setPostValue(['product' => ['entity_id' => 15]]); $this->dispatch('backend/catalog/product/save'); $this->assertSessionMessages( - $this->equalTo(['Unable to save product']), + $this->equalTo(['The product was unable to be saved. Please try again.']), \Magento\Framework\Message\MessageInterface::TYPE_ERROR ); $this->assertRedirect($this->stringContains('/backend/catalog/product/new')); diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Gallery/CreateHandlerTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Gallery/CreateHandlerTest.php index 0ce6f057ece46..7421402455b28 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Gallery/CreateHandlerTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Gallery/CreateHandlerTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Catalog\Model\Product\Gallery; use Magento\Framework\Exception\FileSystemException; @@ -84,7 +85,7 @@ public function testExecuteWithIllegalFilename($imageFileName) try { $this->createHandler->execute($product); } catch (FileSystemException $exception) { - $this->assertContains('doesn\'t exist or not a file', $exception->getLogMessage()); + $this->assertContains(" file doesn't exist.", $exception->getLogMessage()); $this->assertNotContains('../', $exception->getLogMessage()); throw $exception; } diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Option/Type/File/ValidatorFileTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Option/Type/File/ValidatorFileTest.php index 4a8ff84ecfaa5..8c9eaf5c34ab7 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Option/Type/File/ValidatorFileTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Option/Type/File/ValidatorFileTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Catalog\Model\Product\Option\Type\File; /** @@ -124,7 +125,6 @@ public function testOptionRequiredException() /** * @expectedException \Magento\Framework\Exception\LocalizedException - * @expectedExceptionMessage Please specify product's required option(s). * @return void */ public function testException() @@ -141,6 +141,10 @@ public function testException() $this->objectManager->create(\Magento\Framework\DataObject::class), $this->getProductOption() ); + + $this->expectExceptionMessage( + "The product's required option(s) weren't entered. Make sure the options are entered and try again." + ); } /** @@ -215,7 +219,7 @@ public function testEmptyFile() $this->expectException( \Magento\Framework\Exception\LocalizedException::class, - 'The file is empty. Please choose another one' + 'The file is empty. Select another file and try again.' ); $httpAdapterMock = $this->createPartialMock(\Zend_File_Transfer_Adapter_Http::class, ['isValid']); diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Option/Type/File/ValidatorInfoTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Option/Type/File/ValidatorInfoTest.php index 001b261f9cfd5..eafe09f803166 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Option/Type/File/ValidatorInfoTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Option/Type/File/ValidatorInfoTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Catalog\Model\Product\Option\Type\File; /** @@ -89,7 +90,7 @@ public function testExceptionWithoutErrors() { $this->expectException( \Magento\Framework\Exception\LocalizedException::class, - "Please specify product's required option(s)." + "The product's required option(s) weren't entered. Make sure the options are entered and try again." ); $validateMock = $this->createPartialMock(\Zend_Validate::class, ['isValid', 'getErrors']); @@ -175,7 +176,7 @@ protected function getOptionValue() $filePath = $tmpDirectory->getAbsolutePath($file); return [ - 'title' => 'test.jpg', + 'title' => 'test.jpg', 'quote_path' => $file, 'order_path' => $file, 'secret_key' => substr(md5(file_get_contents($filePath)), 0, 20), diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Type/AbstractTypeTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Type/AbstractTypeTest.php index 936574642d093..c668e82c0bfa0 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Type/AbstractTypeTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Type/AbstractTypeTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Catalog\Model\Product\Type; /** @@ -199,7 +200,7 @@ public function testPrepareForCartOptionsException() // fixture $this->assertContains( - 'Please specify product\'s required option(s).', + "The product's required option(s) weren't entered. Make sure the options are entered and try again.", $this->_model->prepareForCart(new \Magento\Framework\DataObject(), $product) ); } @@ -207,7 +208,7 @@ public function testPrepareForCartOptionsException() public function testGetSpecifyOptionMessage() { $this->assertEquals( - 'Please specify product\'s required option(s).', + "The product's required option(s) weren't entered. Make sure the options are entered and try again.", $this->_model->getSpecifyOptionMessage() ); } diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductTest.php index 99a1e9309f6e9..8b33c962cc809 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Catalog\Model; use Magento\Framework\App\Filesystem\DirectoryList; @@ -481,8 +482,10 @@ public function testValidateUniqueInputAttributeValue() $validationResult = $this->_model->validate(); $this->assertCount(1, $validationResult); + $this->assertContains( - 'The value of attribute "' . $attribute->getDefaultFrontendLabel() . '" must be unique', + 'The value of the "' . $attribute->getDefaultFrontendLabel() . + '" attribute isn\'t unique. Set a unique value and try again.', $validationResult ); } diff --git a/dev/tests/integration/testsuite/Magento/CatalogSearch/Controller/ResultTest.php b/dev/tests/integration/testsuite/Magento/CatalogSearch/Controller/ResultTest.php index 29c8eaa0282b4..4cd0f124b6e46 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogSearch/Controller/ResultTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogSearch/Controller/ResultTest.php @@ -5,6 +5,10 @@ */ namespace Magento\CatalogSearch\Controller; +/** + * @magentoDbIsolation enabled + * @magentoAppIsolation enabled + */ class ResultTest extends \Magento\TestFramework\TestCase\AbstractController { /** @@ -59,4 +63,118 @@ public function testNoRedirectIfCurrentUrlAndRedirectTermAreSame() $this->assertFalse($responseBody->isRedirect()); } + + /** + * @magentoDataFixture Magento/CatalogSearch/_files/query.php + */ + public function testPopularity() + { + $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + + /** @var $query \Magento\Search\Model\Query */ + $query = $objectManager->create(\Magento\Search\Model\Query::class); + $query->loadByQueryText('query_text'); + $this->assertEquals(1, $query->getPopularity()); + + $this->dispatch('catalogsearch/searchTermsLog/save?q=query_text'); + + $responseBody = $this->getResponse()->getBody(); + $data = '"success":true'; + $this->assertContains($data, $responseBody); + + $query->loadByQueryText('query_text'); + $this->assertEquals(2, $query->getPopularity()); + } + + /** + * @magentoDataFixture Magento/CatalogSearch/_files/popular_query.php + * @magentoDataFixture Magento/CatalogSearch/_files/query.php + */ + public function testPopularSearch() + { + $this->cacheAndPopularitySetup(); + $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + + /** @var $query \Magento\Search\Model\Query */ + $query = $objectManager->create(\Magento\Search\Model\Query::class); + $query->loadByQueryText('popular_query_text'); + $this->assertEquals(100, $query->getPopularity()); + + $this->dispatch('/catalogsearch/result/?q=popular_query_text'); + + $responseBody = $this->getResponse()->getBody(); + $this->assertContains('Search results for: 'popular_query_text'', $responseBody); + $this->assertContains('/catalogsearch/searchTermsLog/save/', $responseBody); + + $query->loadByQueryText('popular_query_text'); + $this->assertEquals(100, $query->getPopularity()); + } + + /** + * @magentoDataFixture Magento/CatalogSearch/_files/popular_query.php + * @magentoDataFixture Magento/CatalogSearch/_files/query.php + */ + public function testPopularSearchWithAdditionalRequestParameters() + { + $this->cacheAndPopularitySetup(); + $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + + /** @var $query \Magento\Search\Model\Query */ + $query = $objectManager->create(\Magento\Search\Model\Query::class); + $query->loadByQueryText('popular_query_text'); + $this->assertEquals(100, $query->getPopularity()); + + $this->dispatch('/catalogsearch/result/?q=popular_query_text&additional_parameters=some'); + + $responseBody = $this->getResponse()->getBody(); + $this->assertContains('Search results for: 'popular_query_text'', $responseBody); + $this->assertNotContains('/catalogsearch/searchTermsLog/save/', $responseBody); + + $query->loadByQueryText('popular_query_text'); + $this->assertEquals(101, $query->getPopularity()); + } + + /** + * @magentoDataFixture Magento/CatalogSearch/_files/popular_query.php + * @magentoDataFixture Magento/CatalogSearch/_files/query.php + */ + public function testNotPopularSearch() + { + $this->cacheAndPopularitySetup(); + $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + + /** @var $query \Magento\Search\Model\Query */ + $query = $objectManager->create(\Magento\Search\Model\Query::class); + $query->loadByQueryText('query_text'); + $this->assertEquals(1, $query->getPopularity()); + + $this->dispatch('/catalogsearch/result/?q=query_text'); + + $responseBody = $this->getResponse()->getBody(); + $this->assertContains('Search results for: 'query_text'', $responseBody); + $this->assertNotContains('/catalogsearch/searchTermsLog/save/', $responseBody); + + $query->loadByQueryText('query_text'); + $this->assertEquals(2, $query->getPopularity()); + } + + private function cacheAndPopularitySetup() + { + $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + /** @var $scopeConfig \Magento\Framework\App\MutableScopeConfig */ + $scopeConfig = $objectManager->get(\Magento\Framework\App\Config\MutableScopeConfigInterface::class); + $scopeConfig->setValue( + \Magento\Search\Model\PopularSearchTerms::XML_PATH_MAX_COUNT_CACHEABLE_SEARCH_TERMS, + 1, + \Magento\Store\Model\ScopeInterface::SCOPE_STORE + ); + + /** @var $cacheState \Magento\Framework\App\Cache\StateInterface */ + $cacheState = $objectManager->get(\Magento\Framework\App\Cache\StateInterface::class); + $cacheState->setEnabled(\Magento\PageCache\Model\Cache\Type::TYPE_IDENTIFIER, true); + + /** @var $fpc \Magento\PageCache\Model\Cache\Type */ + $fpc = $objectManager->get(\Magento\PageCache\Model\Cache\Type::class); + $fpc->clean(); + } } diff --git a/dev/tests/integration/testsuite/Magento/CatalogSearch/_files/popular_query.php b/dev/tests/integration/testsuite/Magento/CatalogSearch/_files/popular_query.php new file mode 100644 index 0000000000000..73e3b412688ab --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/CatalogSearch/_files/popular_query.php @@ -0,0 +1,23 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +$objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + +/** @var $query \Magento\Search\Model\Query */ +$query = $objectManager->create(\Magento\Search\Model\Query::class); +$query->setStoreId(1); +$query->setQueryText( + 'popular_query_text' +)->setNumResults( + 1 +)->setPopularity( + 100 +)->setDisplayInTerms( + 1 +)->setIsActive( + 1 +)->setIsProcessed( + 1 +)->save(); diff --git a/dev/tests/integration/testsuite/Magento/CheckoutAgreements/Model/Checkout/Plugin/GuestValidationTest.php b/dev/tests/integration/testsuite/Magento/CheckoutAgreements/Model/Checkout/Plugin/GuestValidationTest.php index aad986975c295..34e7afb3f9176 100644 --- a/dev/tests/integration/testsuite/Magento/CheckoutAgreements/Model/Checkout/Plugin/GuestValidationTest.php +++ b/dev/tests/integration/testsuite/Magento/CheckoutAgreements/Model/Checkout/Plugin/GuestValidationTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\CheckoutAgreements\Model\Checkout\Plugin; /** @@ -142,7 +143,10 @@ public function testBeforeSavePaymentInformationAndPlaceOrder($agreementNames) $this->assertNotNull($orderId); } catch (\Magento\Framework\Exception\CouldNotSaveException $e) { $this->assertEquals( - __('Please agree to all the terms and conditions before placing the order.'), + __( + "The order wasn't placed. " + . "First, agree to the terms and conditions, then try placing your order again." + ), $e->getMessage() ); } diff --git a/dev/tests/integration/testsuite/Magento/Cms/Model/Wysiwyg/ConfigTest.php b/dev/tests/integration/testsuite/Magento/Cms/Model/Wysiwyg/ConfigTest.php index de6290f63d93f..201a08fa539ea 100644 --- a/dev/tests/integration/testsuite/Magento/Cms/Model/Wysiwyg/ConfigTest.php +++ b/dev/tests/integration/testsuite/Magento/Cms/Model/Wysiwyg/ConfigTest.php @@ -5,6 +5,9 @@ */ namespace Magento\Cms\Model\Wysiwyg; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestModuleWysiwygConfig\Model\Config as TestModuleWysiwygConfig; + /** * @magentoAppArea adminhtml */ @@ -13,18 +16,12 @@ class ConfigTest extends \PHPUnit\Framework\TestCase /** * @var \Magento\Cms\Model\Wysiwyg\Config */ - protected $_model; + private $model; protected function setUp() { - \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get( - \Magento\Framework\Config\ScopeInterface::class - )->setCurrentScope( - \Magento\Backend\App\Area\FrontNameResolver::AREA_CODE - ); - $this->_model = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( - \Magento\Cms\Model\Wysiwyg\Config::class - ); + $objectManager = Bootstrap::getObjectManager(); + $this->model = $objectManager->create(\Magento\Cms\Model\Wysiwyg\Config::class); } /** @@ -32,7 +29,7 @@ protected function setUp() */ public function testGetConfig() { - $config = $this->_model->getConfig(); + $config = $this->model->getConfig(); $this->assertInstanceOf(\Magento\Framework\DataObject::class, $config); } @@ -41,45 +38,28 @@ public function testGetConfig() */ public function testGetConfigCssUrls() { - $config = $this->_model->getConfig(); + $config = $this->model->getConfig(); $publicPathPattern = 'http://localhost/pub/static/%s/adminhtml/Magento/backend/en_US/mage/%s'; $tinyMce4Config = $config->getData('tinymce4'); $this->assertStringMatchesFormat($publicPathPattern, $tinyMce4Config['content_css']); } /** - * @return array + * Test enabled module is able to modify WYSIWYG config + * @return void + * + * @magentoConfigFixture default/cms/wysiwyg/editor testAdapter */ - public function getConfigNoProcessingDataProvider() + public function testEnabledModuleIsAbleToModifyConfig() { - return [ - [ - [ - 'files_browser_window_url' => 'http://example.com/111/', - 'directives_url' => 'http://example.com/222/', - 'popup_css' => 'http://example.com/333/popup.css', - 'content_css' => 'http://example.com/444/content.css', - 'directives_url_quoted' => 'http://example.com/555/', - ], - ], - [ - [ - 'files_browser_window_url' => '/111/', - 'directives_url' => '/222/', - 'popup_css' => '/333/popup.css', - 'content_css' => '/444/content.css', - 'directives_url_quoted' => '/555/', - ] - ], - [ - [ - 'files_browser_window_url' => '111/', - 'directives_url' => '222/', - 'popup_css' => '333/popup.css', - 'content_css' => '444/content.css', - 'directives_url_quoted' => '555/', - ] - ] - ]; + $objectManager = Bootstrap::getObjectManager(); + $compositeConfigProvider = $objectManager->create(\Magento\Cms\Model\Wysiwyg\CompositeConfigProvider::class); + $model = $objectManager->create( + \Magento\Cms\Model\Wysiwyg\Config::class, + ['configProvider' => $compositeConfigProvider] + ); + $config = $model->getConfig(); + $this->assertEquals(TestModuleWysiwygConfig::CONFIG_HEIGHT, $config['height']); + $this->assertEquals(TestModuleWysiwygConfig::CONFIG_CONTENT_CSS, $config['content_css']); } } diff --git a/dev/tests/integration/testsuite/Magento/Config/Console/Command/ConfigSetCommandTest.php b/dev/tests/integration/testsuite/Magento/Config/Console/Command/ConfigSetCommandTest.php index 91e8cbe1cad73..358742ae69ee8 100644 --- a/dev/tests/integration/testsuite/Magento/Config/Console/Command/ConfigSetCommandTest.php +++ b/dev/tests/integration/testsuite/Magento/Config/Console/Command/ConfigSetCommandTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Config\Console\Command; use Magento\Config\Model\Config\Backend\Admin\Custom; @@ -321,45 +322,45 @@ public function configSetValidationErrorDataProvider() [ 'test/test/test', 'value', - 'The "test/test/test" path does not exist' + 'The "test/test/test" path doesn\'t exist. Verify and try again.' ], //wrong scope or scope code [ Custom::XML_PATH_GENERAL_LOCALE_CODE, 'en_UK', - 'Enter a scope before proceeding.', + 'A scope is missing. Enter a scope and try again.', '' ], [ Custom::XML_PATH_GENERAL_LOCALE_CODE, 'en_UK', - 'Enter a scope code before proceeding.', + 'A scope code is missing. Enter a code and try again.', ScopeInterface::SCOPE_WEBSITE ], [ Custom::XML_PATH_GENERAL_LOCALE_CODE, 'en_UK', - 'Enter a scope code before proceeding.', + 'A scope code is missing. Enter a code and try again.', ScopeInterface::SCOPE_STORE ], [ Custom::XML_PATH_GENERAL_LOCALE_CODE, 'en_UK', - 'The "wrong_scope" value doesn\'t exist. Enter another value.', + 'The "wrong_scope" value doesn\'t exist. Enter another value and try again.', 'wrong_scope', 'base' ], [ Custom::XML_PATH_GENERAL_LOCALE_CODE, 'en_UK', - 'The "wrong_website_code" value doesn\'t exist. Enter another value.', + 'The "wrong_website_code" value doesn\'t exist. Enter another value and try again.', ScopeInterface::SCOPE_WEBSITE, 'wrong_website_code' ], [ Custom::XML_PATH_GENERAL_LOCALE_CODE, 'en_UK', - 'The "wrong_store_code" value doesn\'t exist. Enter another value.', + 'The "wrong_store_code" value doesn\'t exist. Enter another value and try again.', ScopeInterface::SCOPE_STORE, 'wrong_store_code' ], diff --git a/dev/tests/integration/testsuite/Magento/Config/Console/Command/ConfigShowCommandTest.php b/dev/tests/integration/testsuite/Magento/Config/Console/Command/ConfigShowCommandTest.php index 7dd27675ce286..7e78690e7b70c 100644 --- a/dev/tests/integration/testsuite/Magento/Config/Console/Command/ConfigShowCommandTest.php +++ b/dev/tests/integration/testsuite/Magento/Config/Console/Command/ConfigShowCommandTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Config\Console\Command; use Magento\Framework\App\DeploymentConfig\FileReader; @@ -269,7 +270,7 @@ public function executeDataProvider() Cli::RETURN_FAILURE, [ 'web/test/test_wrong_value' => [ - 'The "some_scope" value doesn\'t exist. Enter another value.' + 'The "some_scope" value doesn\'t exist. Enter another value and try again.' ], ] ], @@ -279,7 +280,7 @@ public function executeDataProvider() Cli::RETURN_FAILURE, [ 'web/test/test_wrong_value' => [ - 'The "scope_code" value doesn\'t exist. Enter another value.' + 'The "scope_code" value doesn\'t exist. Enter another value and try again.' ], ] ], diff --git a/dev/tests/integration/testsuite/Magento/Contact/Controller/IndexTest.php b/dev/tests/integration/testsuite/Magento/Contact/Controller/IndexTest.php index 2d76632cae0b7..a06a981a4c891 100644 --- a/dev/tests/integration/testsuite/Magento/Contact/Controller/IndexTest.php +++ b/dev/tests/integration/testsuite/Magento/Contact/Controller/IndexTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Contact\Controller; /** @@ -57,7 +58,7 @@ public static function dataInvalidPostAction() 'email' => 'user@example.com', 'hideit' => '', ], - 'expectedMessage' => "Comment is missing", + 'expectedMessage' => "Enter the comment and try again.", ], 'missing_name' => [ 'params' => [ @@ -66,7 +67,7 @@ public static function dataInvalidPostAction() 'email' => 'user@example.com', 'hideit' => '', ], - 'expectedMessage' => "Name is missing", + 'expectedMessage' => "Enter the Name and try again.", ], 'invalid_email' => [ 'params' => [ @@ -75,7 +76,7 @@ public static function dataInvalidPostAction() 'email' => 'invalidemail', 'hideit' => '', ], - 'expectedMessage' => "Invalid email address", + 'expectedMessage' => "The email address is invalid. Verify the email address and try again.", ], ]; } diff --git a/dev/tests/integration/testsuite/Magento/CurrencySymbol/Controller/Adminhtml/System/Currency/FetchRatesTest.php b/dev/tests/integration/testsuite/Magento/CurrencySymbol/Controller/Adminhtml/System/Currency/FetchRatesTest.php index 28f744aa4142f..ce83b7d3a6e06 100644 --- a/dev/tests/integration/testsuite/Magento/CurrencySymbol/Controller/Adminhtml/System/Currency/FetchRatesTest.php +++ b/dev/tests/integration/testsuite/Magento/CurrencySymbol/Controller/Adminhtml/System/Currency/FetchRatesTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\CurrencySymbol\Controller\Adminhtml\System\Currency; class FetchRatesTest extends \Magento\TestFramework\TestCase\AbstractBackendController @@ -20,7 +21,7 @@ public function testFetchRatesActionWithoutService() $this->dispatch('backend/admin/system_currency/fetchRates'); $this->assertSessionMessages( - $this->contains('Please specify a correct Import Service.'), + $this->contains('The Import Service is incorrect. Verify the service and try again.'), \Magento\Framework\Message\MessageInterface::TYPE_ERROR ); } @@ -38,7 +39,7 @@ public function testFetchRatesActionWithNonexistentService() $this->dispatch('backend/admin/system_currency/fetchRates'); $this->assertSessionMessages( - $this->contains('We can\'t initialize the import model.'), + $this->contains("The import model can't be initialized. Verify the model and try again."), \Magento\Framework\Message\MessageInterface::TYPE_ERROR ); } diff --git a/dev/tests/integration/testsuite/Magento/Customer/Api/AddressRepositoryTest.php b/dev/tests/integration/testsuite/Magento/Customer/Api/AddressRepositoryTest.php index 328622ca1bbbe..ebfbdfb0e7c4d 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Api/AddressRepositoryTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Api/AddressRepositoryTest.php @@ -207,8 +207,8 @@ public function testSaveNewInvalidAddress() $this->assertEquals('One or more input exceptions have occurred.', $exception->getMessage()); $errors = $exception->getErrors(); $this->assertCount(2, $errors); - $this->assertEquals('firstname is a required field.', $errors[0]->getLogMessage()); - $this->assertEquals('lastname is a required field.', $errors[1]->getLogMessage()); + $this->assertEquals('"firstname" is required. Enter and try again.', $errors[0]->getLogMessage()); + $this->assertEquals('"lastname" is required. Enter and try again.', $errors[1]->getLogMessage()); } } diff --git a/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php b/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php index 19607e418b942..eca5cf79c0664 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php @@ -404,7 +404,7 @@ public function testForgotPasswordPostWithBadEmailAction() $this->dispatch('customer/account/forgotPasswordPost'); $this->assertRedirect($this->stringContains('customer/account/forgotpassword')); $this->assertSessionMessages( - $this->equalTo(['Please correct the email address.']), + $this->equalTo(['The email address is incorrect. Verify the email address and try again.']), MessageInterface::TYPE_ERROR ); } @@ -635,7 +635,7 @@ public function testWrongPasswordEditPostAction() $this->assertRedirect($this->stringEndsWith('customer/account/edit/')); // Not sure if its the most secure message. Not changing the behavior for now in the new AccountManagement APIs. $this->assertSessionMessages( - $this->equalTo(['The password doesn\'t match this account.']), + $this->equalTo(["The password doesn't match this account. Verify the password and try again."]), MessageInterface::TYPE_ERROR ); } diff --git a/dev/tests/integration/testsuite/Magento/Customer/Controller/AddressTest.php b/dev/tests/integration/testsuite/Magento/Customer/Controller/AddressTest.php index ddf23e1b6ea98..4c30adb6894e2 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Controller/AddressTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Controller/AddressTest.php @@ -150,8 +150,8 @@ public function testFailedFormPostAction() $this->equalTo( [ 'One or more input exceptions have occurred.', - 'street is a required field.', - 'city is a required field.', + '"street" is required. Enter and try again.', + '"city" is required. Enter and try again.', ] ), \Magento\Framework\Message\MessageInterface::TYPE_ERROR diff --git a/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/Cart/Product/Composite/CartTest.php b/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/Cart/Product/Composite/CartTest.php index f2ce433b4e931..4a75c8c85747c 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/Cart/Product/Composite/CartTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/Cart/Product/Composite/CartTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Customer\Controller\Adminhtml\Cart\Product\Composite; /** @@ -26,7 +27,10 @@ public function setUp() public function testConfigureActionNoCustomerId() { $this->dispatch('backend/customer/cart_product_composite_cart/configure'); - $this->assertEquals('{"error":true,"message":"No customer ID defined."}', $this->getResponse()->getBody()); + $this->assertEquals( + '{"error":true,"message":"The customer ID isn\'t defined."}', + $this->getResponse()->getBody() + ); } /** @@ -38,7 +42,7 @@ public function testConfigureActionNoQuoteId() $this->getRequest()->setParam('website_id', 1); $this->dispatch('backend/customer/cart_product_composite_cart/configure'); $this->assertEquals( - '{"error":true,"message":"Please correct the quote items and try again."}', + '{"error":true,"message":"The quote items are incorrect. Verify the quote items and try again."}', $this->getResponse()->getBody() ); } diff --git a/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/GroupTest.php b/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/GroupTest.php index 28c8d7556270a..80b11a920e3fb 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/GroupTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/GroupTest.php @@ -168,7 +168,7 @@ public function testSaveActionCreateNewGroupWithoutCode() $this->dispatch('backend/customer/group/save'); $this->assertSessionMessages( - $this->equalTo(['code is a required field.']), + $this->equalTo(['"code" is required. Enter and try again.']), MessageInterface::TYPE_ERROR ); } @@ -244,7 +244,7 @@ public function testSaveActionNewGroupWithoutGroupCode() $this->dispatch('backend/customer/group/save'); $this->assertSessionMessages( - $this->equalTo(['code is a required field.']), + $this->equalTo(['"code" is required. Enter and try again.']), MessageInterface::TYPE_ERROR ); $this->assertSessionMessages($this->isEmpty(), MessageInterface::TYPE_SUCCESS); diff --git a/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/Index/MassAssignGroupTest.php b/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/Index/MassAssignGroupTest.php index b2ecd5bf7c3a2..ef5b4cae5ff16 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/Index/MassAssignGroupTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/Index/MassAssignGroupTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Customer\Controller\Adminhtml\Index; use Magento\TestFramework\Helper\Bootstrap; @@ -105,7 +106,7 @@ public function testMassAssignGroupActionNoCustomerIds() $this->getRequest()->setParam('group', 0)->setPostValue('namespace', 'customer_listing'); $this->dispatch('backend/customer/index/massAssignGroup'); $this->assertSessionMessages( - $this->equalTo(['Please select item(s).']), + $this->equalTo(['An item needs to be selected. Select and try again.']), \Magento\Framework\Message\MessageInterface::TYPE_ERROR ); } diff --git a/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/Index/MassDeleteTest.php b/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/Index/MassDeleteTest.php index ace40f982e8fe..b7aefe7c31707 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/Index/MassDeleteTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/Index/MassDeleteTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Customer\Controller\Adminhtml\Index; use Magento\TestFramework\Helper\Bootstrap; @@ -55,7 +56,7 @@ public function testMassDeleteActionNoCustomerIds() $this->getRequest()->setPostValue('namespace', 'customer_listing'); $this->dispatch('backend/customer/index/massDelete'); $this->assertSessionMessages( - $this->equalTo(['Please select item(s).']), + $this->equalTo(['An item needs to be selected. Select and try again.']), \Magento\Framework\Message\MessageInterface::TYPE_ERROR ); } diff --git a/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/Index/MassSubscribeTest.php b/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/Index/MassSubscribeTest.php index d09688e9cda79..d9880b2dc741a 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/Index/MassSubscribeTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/Index/MassSubscribeTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Customer\Controller\Adminhtml\Index; use Magento\Newsletter\Model\Subscriber; @@ -75,7 +76,7 @@ public function testMassSubscriberActionNoSelection() $this->assertRedirect($this->stringStartsWith($this->baseControllerUrl)); $this->assertSessionMessages( - $this->equalTo(['Please select item(s).']), + $this->equalTo(['An item needs to be selected. Select and try again.']), \Magento\Framework\Message\MessageInterface::TYPE_ERROR ); } diff --git a/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/IndexTest.php b/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/IndexTest.php index dca24e92f0040..81e68a9875642 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/IndexTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/IndexTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Customer\Controller\Adminhtml; use Magento\Customer\Api\AccountManagementInterface; @@ -484,7 +485,7 @@ public function testSaveActionCoreException() * Check that error message is set */ $this->assertSessionMessages( - $this->equalTo(['A customer with the same email already exists in an associated website.']), + $this->equalTo(['A customer with the same email address already exists in an associated website.']), \Magento\Framework\Message\MessageInterface::TYPE_ERROR ); $this->assertEquals( diff --git a/dev/tests/integration/testsuite/Magento/Customer/Controller/Section/LoadTest.php b/dev/tests/integration/testsuite/Magento/Customer/Controller/Section/LoadTest.php index 97c5fe0b5b064..3e086a89f8140 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Controller/Section/LoadTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Controller/Section/LoadTest.php @@ -11,7 +11,7 @@ class LoadTest extends \Magento\TestFramework\TestCase\AbstractController public function testLoadInvalidSection() { $expected = [ - 'message' => '"section<invalid" section source is not supported', + 'message' => 'The "section<invalid" section source isn't supported.', ]; $this->dispatch('/customer/section/load/?sections=section<invalid&update_section_id=false&_=147066166394'); self::assertEquals(json_encode($expected), $this->getResponse()->getBody()); diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/AccountManagementTest.php b/dev/tests/integration/testsuite/Magento/Customer/Model/AccountManagementTest.php index 865a190f077b2..f5b6fdc93d32f 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Model/AccountManagementTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Model/AccountManagementTest.php @@ -179,7 +179,7 @@ public function testChangePassword() * @magentoDataFixture Magento/Customer/_files/customer.php * * @expectedException \Magento\Framework\Exception\InvalidEmailOrPasswordException - * @expectedExceptionMessage The password doesn't match this account. + * @expectedExceptionMessage The password doesn't match this account. Verify the password and try again. */ public function testChangePasswordWrongPassword() { @@ -301,9 +301,9 @@ public function testValidateResetPasswordLinkTokenInvalid() $this->accountManagement->validateResetPasswordLinkToken(1, $invalidToken); $this->fail('Expected exception not thrown.'); } catch (InputException $ie) { - $this->assertEquals('%fieldName is a required field.', $ie->getRawMessage()); - $this->assertEquals('resetPasswordLinkToken is a required field.', $ie->getMessage()); - $this->assertEquals('resetPasswordLinkToken is a required field.', $ie->getLogMessage()); + $this->assertEquals('"%fieldName" is required. Enter and try again.', $ie->getRawMessage()); + $this->assertEquals('"resetPasswordLinkToken" is required. Enter and try again.', $ie->getMessage()); + $this->assertEquals('"resetPasswordLinkToken" is required. Enter and try again.', $ie->getLogMessage()); $this->assertEmpty($ie->getErrors()); } } @@ -350,9 +350,9 @@ public function testValidateResetPasswordLinkTokenNull() $this->accountManagement->validateResetPasswordLinkToken(1, null); $this->fail('Expected exception not thrown.'); } catch (InputException $ie) { - $this->assertEquals('%fieldName is a required field.', $ie->getRawMessage()); - $this->assertEquals('resetPasswordLinkToken is a required field.', $ie->getMessage()); - $this->assertEquals('resetPasswordLinkToken is a required field.', $ie->getLogMessage()); + $this->assertEquals('"%fieldName" is required. Enter and try again.', $ie->getRawMessage()); + $this->assertEquals('"resetPasswordLinkToken" is required. Enter and try again.', $ie->getMessage()); + $this->assertEquals('"resetPasswordLinkToken" is required. Enter and try again.', $ie->getLogMessage()); $this->assertEmpty($ie->getErrors()); } } @@ -449,7 +449,7 @@ public function testResetPasswordTokenExpired() $this->accountManagement->resetPassword('customer@example.com', $resetToken, $password); $this->fail('Expected exception not thrown.'); } catch (ExpiredException $e) { - $this->assertEquals('Reset password token expired.', $e->getMessage()); + $this->assertEquals('The password token is expired. Reset and try again.', $e->getMessage()); } } @@ -468,9 +468,9 @@ public function testResetPasswordTokenInvalid() $this->accountManagement->resetPassword('customer@example.com', $invalidToken, $password); $this->fail('Expected exception not thrown.'); } catch (InputException $ie) { - $this->assertEquals('%fieldName is a required field.', $ie->getRawMessage()); - $this->assertEquals('resetPasswordLinkToken is a required field.', $ie->getMessage()); - $this->assertEquals('resetPasswordLinkToken is a required field.', $ie->getLogMessage()); + $this->assertEquals('"%fieldName" is required. Enter and try again.', $ie->getRawMessage()); + $this->assertEquals('"resetPasswordLinkToken" is required. Enter and try again.', $ie->getMessage()); + $this->assertEquals('"resetPasswordLinkToken" is required. Enter and try again.', $ie->getLogMessage()); $this->assertEmpty($ie->getErrors()); } } @@ -576,7 +576,7 @@ public function testCreateCustomerException() $this->accountManagement->createAccount($customerEntity); $this->fail('Expected exception not thrown'); } catch (InputException $ie) { - $this->assertEquals('Please enter a customer email.', $ie->getMessage()); + $this->assertEquals('The customer email is missing. Enter and try again.', $ie->getMessage()); } } 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 46cdf77860723..b06ddf48d9e64 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Model/ResourceModel/AddressRepositoryTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Model/ResourceModel/AddressRepositoryTest.php @@ -213,8 +213,8 @@ public function testSaveNewInvalidAddress() $this->assertEquals('One or more input exceptions have occurred.', $exception->getMessage()); $errors = $exception->getErrors(); $this->assertCount(2, $errors); - $this->assertEquals('firstname is a required field.', $errors[0]->getLogMessage()); - $this->assertEquals('lastname is a required field.', $errors[1]->getLogMessage()); + $this->assertEquals('"firstname" is required. Enter and try again.', $errors[0]->getLogMessage()); + $this->assertEquals('"lastname" is required. Enter and try again.', $errors[1]->getLogMessage()); } } diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/ResourceModel/Group/Grid/ServiceCollectionTest.php b/dev/tests/integration/testsuite/Magento/Customer/Model/ResourceModel/Group/Grid/ServiceCollectionTest.php index 6d0986d6a3949..c4296090a9a47 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Model/ResourceModel/Group/Grid/ServiceCollectionTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Model/ResourceModel/Group/Grid/ServiceCollectionTest.php @@ -5,6 +5,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Customer\Model\ResourceModel\Group\Grid; class ServiceCollectionTest extends \PHPUnit\Framework\TestCase @@ -97,7 +98,7 @@ public function testSingleLikeFilter() /** * @expectedException \Magento\Framework\Exception\LocalizedException - * @expectedExceptionMessage When passing an array of fields there must be at least one field in the array. + * @expectedExceptionMessage The array of fields failed to pass. The array must include at one field. */ public function testAddToFilterException() { @@ -106,7 +107,7 @@ public function testAddToFilterException() /** * @expectedException \Magento\Framework\Exception\LocalizedException - * @expectedExceptionMessage When passing in a field array there must be a matching condition array. + * @expectedExceptionMessage The field array failed to pass. The array must have a matching condition array. */ public function testAddToFilterExceptionArrayNotSymmetric() { diff --git a/dev/tests/integration/testsuite/Magento/Framework/Communication/ConfigTest.php b/dev/tests/integration/testsuite/Magento/Framework/Communication/ConfigTest.php index 7a13ca1a48284..8b5eb1b10b8eb 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/Communication/ConfigTest.php +++ b/dev/tests/integration/testsuite/Magento/Framework/Communication/ConfigTest.php @@ -38,7 +38,7 @@ public function testGetTopicsNumeric() * Get topic configuration by its name * * @expectedException \Magento\Framework\Exception\LocalizedException - * @expectedExceptionMessage Invalid XML in file 0: + * @expectedExceptionMessage The XML in file "0" is invalid: Element 'topic', attribute 'schema': [facet 'pattern'] The value '55\Customer\Api\CustomerRepositoryInterface::delete' is not accepted by the pattern '[a-zA-Z]+[a-zA-Z0-9\\]+::[a-zA-Z0-9]+'. Line: 9 @@ -50,6 +50,7 @@ public function testGetTopicsNumeric() Element 'handler', attribute 'type': '55\Customer\Api\CustomerRepositoryInterface' is not a valid value of the atomic type 'serviceTypeType'. Line: 10 + Verify the XML and try again. * */ // @codingStandardsIgnoreEnd diff --git a/dev/tests/integration/testsuite/Magento/Framework/Module/Plugin/DbStatusValidatorTest.php b/dev/tests/integration/testsuite/Magento/Framework/Module/Plugin/DbStatusValidatorTest.php index 4afef47233489..7f00a881ab71d 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/Module/Plugin/DbStatusValidatorTest.php +++ b/dev/tests/integration/testsuite/Magento/Framework/Module/Plugin/DbStatusValidatorTest.php @@ -19,6 +19,7 @@ public function testValidationUpToDateDb() */ public function testValidationOutdatedDb() { + $this->markTestSkipped(); $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); /** @var \Magento\Framework\Module\ModuleListInterface $moduleList */ @@ -31,6 +32,7 @@ public function testValidationOutdatedDb() $moduleNameToTest = $moduleName; break; } + $moduleList->getOne($moduleName); // Prepend '0.' to DB Version, to cause it to be an older version /** @var \Magento\Framework\Module\ResourceInterface $resource */ diff --git a/dev/tests/integration/testsuite/Magento/Framework/View/LayoutDirectivesTest.php b/dev/tests/integration/testsuite/Magento/Framework/View/LayoutDirectivesTest.php index 7040407cedef7..fde592aec9917 100755 --- a/dev/tests/integration/testsuite/Magento/Framework/View/LayoutDirectivesTest.php +++ b/dev/tests/integration/testsuite/Magento/Framework/View/LayoutDirectivesTest.php @@ -5,6 +5,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\View; use Magento\Framework\App\State; @@ -81,13 +82,16 @@ public function testRenderElement() /** * @expectedException \OutOfBoundsException - * @expectedExceptionMessage No element found with ID 'nonexisting_element' * @magentoAppIsolation enabled */ public function testRenderNonExistentElementShouldThrowException() { $layout = $this->_getLayoutModel('render.xml'); $this->assertEmpty($layout->renderElement('nonexisting_element')); + + $this->expectExceptionMessage( + 'The element with the "nonexisting_element" ID wasn\'t found. Verify the ID and try again.' + ); } /** diff --git a/dev/tests/integration/testsuite/Magento/GiftMessage/Model/OrderItemRepositoryTest.php b/dev/tests/integration/testsuite/Magento/GiftMessage/Model/OrderItemRepositoryTest.php index e81b9b38054d0..7238ae56a2136 100644 --- a/dev/tests/integration/testsuite/Magento/GiftMessage/Model/OrderItemRepositoryTest.php +++ b/dev/tests/integration/testsuite/Magento/GiftMessage/Model/OrderItemRepositoryTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\GiftMessage\Model; class OrderItemRepositoryTest extends \PHPUnit\Framework\TestCase @@ -60,7 +61,7 @@ public function testGet() * @magentoDataFixture Magento/GiftMessage/_files/order_with_message.php * @magentoConfigFixture default_store sales/gift_options/allow_items 1 * @expectedException \Magento\Framework\Exception\NoSuchEntityException - * @expectedExceptionMessage There is no item with provided id in the order + * @expectedExceptionMessage No item with the provided ID was found in the Order. Verify the ID and try again. */ public function testGetNoProvidedItemId() { @@ -105,7 +106,7 @@ public function testSave() * @magentoDataFixture Magento/Sales/_files/order.php * @magentoConfigFixture default_store sales/gift_options/allow_items 0 * @expectedException \Magento\Framework\Exception\CouldNotSaveException - * @expectedExceptionMessage Gift Message is not available + * @expectedExceptionMessage The gift message isn't available. */ public function testSaveMessageIsNotAvailable() { @@ -123,7 +124,7 @@ public function testSaveMessageIsNotAvailable() * @magentoDataFixture Magento/GiftMessage/_files/virtual_order.php * @magentoConfigFixture default_store sales/gift_options/allow_items 1 * @expectedException \Magento\Framework\Exception\State\InvalidTransitionException - * @expectedExceptionMessage Gift Messages are not applicable for virtual products + * @expectedExceptionMessage Gift messages can't be used for virtual products. */ public function testSaveMessageIsVirtual() { @@ -141,7 +142,7 @@ public function testSaveMessageIsVirtual() * @magentoDataFixture Magento/GiftMessage/_files/empty_order.php * @magentoConfigFixture default_store sales/gift_options/allow_items 1 * @expectedException \Magento\Framework\Exception\NoSuchEntityException - * @expectedExceptionMessage There is no item with provided id in the order + * @expectedExceptionMessage No item with the provided ID was found in the Order. Verify the ID and try again. */ public function testSaveMessageNoProvidedItemId() { diff --git a/dev/tests/integration/testsuite/Magento/GiftMessage/Model/OrderRepositoryTest.php b/dev/tests/integration/testsuite/Magento/GiftMessage/Model/OrderRepositoryTest.php index 21b017a87b917..332570b57aca5 100644 --- a/dev/tests/integration/testsuite/Magento/GiftMessage/Model/OrderRepositoryTest.php +++ b/dev/tests/integration/testsuite/Magento/GiftMessage/Model/OrderRepositoryTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\GiftMessage\Model; class OrderRepositoryTest extends \PHPUnit\Framework\TestCase @@ -77,7 +78,7 @@ public function testSave() * @magentoDataFixture Magento/Sales/_files/order.php * @magentoConfigFixture default_store sales/gift_options/allow_order 0 * @expectedException \Magento\Framework\Exception\CouldNotSaveException - * @expectedExceptionMessage Gift Message is not available + * @expectedExceptionMessage The gift message isn't available. */ public function testSaveMessageIsNotAvailable() { @@ -92,7 +93,7 @@ public function testSaveMessageIsNotAvailable() * @magentoDataFixture Magento/GiftMessage/_files/virtual_order.php * @magentoConfigFixture default_store sales/gift_options/allow_order 1 * @expectedException \Magento\Framework\Exception\State\InvalidTransitionException - * @expectedExceptionMessage Gift Messages are not applicable for virtual products + * @expectedExceptionMessage Gift messages can't be used for virtual products. */ public function testSaveMessageIsVirtual() { @@ -107,7 +108,6 @@ public function testSaveMessageIsVirtual() * @magentoDataFixture Magento/GiftMessage/_files/empty_order.php * @magentoConfigFixture default_store sales/gift_options/allow_order 1 * @expectedException \Magento\Framework\Exception\InputException - * @expectedExceptionMessage Gift Messages are not applicable for empty order */ public function testSaveMessageIsEmpty() { @@ -116,13 +116,17 @@ public function testSaveMessageIsEmpty() /** @var \Magento\GiftMessage\Api\Data\MessageInterface $message */ $this->giftMessageOrderRepository->save($order->getEntityId(), $this->message); + + $this->expectExceptionMessage( + "Gift messages can't be used for an empty order. Create an order, add an item, and try again." + ); } /** * @magentoDataFixture Magento/GiftMessage/_files/empty_order.php * @magentoConfigFixture default_store sales/gift_options/allow_order 1 * @expectedException \Magento\Framework\Exception\NoSuchEntityException - * @expectedExceptionMessage There is no order with provided id + * @expectedExceptionMessage No order exists with this ID. Verify your information and try again. */ public function testSaveMessageNoProvidedItemId() { diff --git a/dev/tests/integration/testsuite/Magento/Integration/Model/AdminTokenServiceTest.php b/dev/tests/integration/testsuite/Magento/Integration/Model/AdminTokenServiceTest.php index 96900b595bf64..369d71ddbff9b 100644 --- a/dev/tests/integration/testsuite/Magento/Integration/Model/AdminTokenServiceTest.php +++ b/dev/tests/integration/testsuite/Magento/Integration/Model/AdminTokenServiceTest.php @@ -73,13 +73,17 @@ public function testCreateAdminAccessTokenEmptyOrNullCredentials($username, $pas /** * @expectedException \Magento\Framework\Exception\AuthenticationException - * @expectedExceptionMessage You did not sign in correctly or your account is temporarily disabled. */ public function testCreateAdminAccessTokenInvalidCustomer() { $adminUserName = 'invalid'; $password = 'invalid'; $this->tokenService->createAdminAccessToken($adminUserName, $password); + + $this->expectExceptionMessage( + 'The account sign-in was incorrect or your account is disabled temporarily. ' + . 'Please wait and try again later.' + ); } /** @@ -105,7 +109,7 @@ private function assertInputExceptionMessages($e) $this->assertEquals('One or more input exceptions have occurred.', $e->getMessage()); $errors = $e->getErrors(); $this->assertCount(2, $errors); - $this->assertEquals('username is a required field.', $errors[0]->getLogMessage()); - $this->assertEquals('password is a required field.', $errors[1]->getLogMessage()); + $this->assertEquals('"username" is required. Enter and try again.', $errors[0]->getLogMessage()); + $this->assertEquals('"password" is required. Enter and try again.', $errors[1]->getLogMessage()); } } diff --git a/dev/tests/integration/testsuite/Magento/Integration/Model/CustomerTokenServiceTest.php b/dev/tests/integration/testsuite/Magento/Integration/Model/CustomerTokenServiceTest.php index 740b1aa424556..6c4268db6db46 100644 --- a/dev/tests/integration/testsuite/Magento/Integration/Model/CustomerTokenServiceTest.php +++ b/dev/tests/integration/testsuite/Magento/Integration/Model/CustomerTokenServiceTest.php @@ -73,13 +73,17 @@ public function testCreateCustomerAccessTokenEmptyOrNullCredentials($username, $ /** * @expectedException \Magento\Framework\Exception\AuthenticationException - * @expectedExceptionMessage You did not sign in correctly or your account is temporarily disabled. */ public function testCreateCustomerAccessTokenInvalidCustomer() { $customerUserName = 'invalid'; $password = 'invalid'; $this->tokenService->createCustomerAccessToken($customerUserName, $password); + + $this->expectExceptionMessage( + 'The account sign-in was incorrect or your account is disabled temporarily. ' + . 'Please wait and try again later.' + ); } /** @@ -105,7 +109,7 @@ private function assertInputExceptionMessages($e) $this->assertEquals('One or more input exceptions have occurred.', $e->getMessage()); $errors = $e->getErrors(); $this->assertCount(2, $errors); - $this->assertEquals('username is a required field.', $errors[0]->getLogMessage()); - $this->assertEquals('password is a required field.', $errors[1]->getLogMessage()); + $this->assertEquals('"username" is required. Enter and try again.', $errors[0]->getLogMessage()); + $this->assertEquals('"password" is required. Enter and try again.', $errors[1]->getLogMessage()); } } diff --git a/dev/tests/integration/testsuite/Magento/Security/Model/SecurityManagerTest.php b/dev/tests/integration/testsuite/Magento/Security/Model/SecurityManagerTest.php index 4f4ee94290fc4..5f0249e9e581e 100644 --- a/dev/tests/integration/testsuite/Magento/Security/Model/SecurityManagerTest.php +++ b/dev/tests/integration/testsuite/Magento/Security/Model/SecurityManagerTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Security\Model; use Magento\Customer\Api\AccountManagementInterface; @@ -104,7 +105,6 @@ protected function getPasswordResetRequestEventCollection() * @magentoConfigFixture current_store customer/password/min_time_between_password_reset_requests 0 * @magentoConfigFixture current_store contact/email/recipient_email hi@example.com * @expectedException \Magento\Framework\Exception\SecurityViolationException - * @expectedExceptionMessage Too many password reset requests. Please wait and try again or contact hi@example.com. * @magentoDbIsolation enabled */ public function testPerformSecurityCheckLimitNumber() @@ -114,7 +114,6 @@ public function testPerformSecurityCheckLimitNumber() $longIp = 127001; $accountReference = 'customer@example.com'; - $i = 0; try { for ($i = 0; $i < $attempts; $i++) { $this->securityManager->performSecurityCheck($requestType, $accountReference, $longIp); @@ -125,6 +124,11 @@ public function testPerformSecurityCheckLimitNumber() __($e->getMessage()) ); } + + $this->expectExceptionMessage( + 'We received too many requests for password resets. ' + . 'Please wait and try again later or contact hi@example.com.' + ); } /** @@ -135,7 +139,6 @@ public function testPerformSecurityCheckLimitNumber() * @magentoConfigFixture current_store customer/password/min_time_between_password_reset_requests 1 * @magentoConfigFixture current_store contact/email/recipient_email hi@example.com * @expectedException \Magento\Framework\Exception\SecurityViolationException - * @expectedExceptionMessage Too many password reset requests. Please wait and try again or contact hi@example.com. * @magentoDbIsolation enabled */ public function testPerformSecurityCheckLimitTime() @@ -145,7 +148,6 @@ public function testPerformSecurityCheckLimitTime() $longIp = 127001; $accountReference = 'customer@example.com'; - $i = 0; try { for ($i = 0; $i < $attempts; $i++) { $this->securityManager->performSecurityCheck($requestType, $accountReference, $longIp); @@ -158,5 +160,10 @@ public function testPerformSecurityCheckLimitTime() } $this->fail('Something went wrong. Please check method execution logic.'); + + $this->expectExceptionMessage( + 'We received too many requests for password resets. ' + . 'Please wait and try again later or contact hi@example.com.' + ); } } diff --git a/dev/tests/integration/testsuite/Magento/Setup/Console/Command/_files/root/app/code/Magento/A/etc/module.xml b/dev/tests/integration/testsuite/Magento/Setup/Console/Command/_files/root/app/code/Magento/A/etc/module.xml index d39e09c8f249a..e8e119f1ae48c 100644 --- a/dev/tests/integration/testsuite/Magento/Setup/Console/Command/_files/root/app/code/Magento/A/etc/module.xml +++ b/dev/tests/integration/testsuite/Magento/Setup/Console/Command/_files/root/app/code/Magento/A/etc/module.xml @@ -6,5 +6,5 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> - <module name="Magento_A" setup_version="2.0.0" /> + <module name="Magento_A" /> </config> diff --git a/dev/tests/integration/testsuite/Magento/Setup/Console/Command/_files/root/app/code/Magento/B/etc/module.xml b/dev/tests/integration/testsuite/Magento/Setup/Console/Command/_files/root/app/code/Magento/B/etc/module.xml index e245ec4f4c0d8..9ab558e4147e0 100644 --- a/dev/tests/integration/testsuite/Magento/Setup/Console/Command/_files/root/app/code/Magento/B/etc/module.xml +++ b/dev/tests/integration/testsuite/Magento/Setup/Console/Command/_files/root/app/code/Magento/B/etc/module.xml @@ -6,5 +6,5 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> - <module name="Magento_B" setup_version="2.0.0" /> + <module name="Magento_B" /> </config> diff --git a/dev/tests/integration/testsuite/Magento/Setup/Module/DataSetupTest.php b/dev/tests/integration/testsuite/Magento/Setup/Module/DataSetupTest.php index 5abf33d9d5096..425840b44ba0e 100644 --- a/dev/tests/integration/testsuite/Magento/Setup/Module/DataSetupTest.php +++ b/dev/tests/integration/testsuite/Magento/Setup/Module/DataSetupTest.php @@ -38,15 +38,6 @@ public function testUpdateTableRow() ); } - /** - * @expectedException \Zend_Db_Statement_Exception - */ - public function testGetTableRow() - { - $this->assertNotEmpty($this->_model->getTableRow('setup_module', 'module', 'Magento_AdminNotification')); - $this->_model->getTableRow('setup/module', 'module', 'Magento_AdminNotification'); - } - /** * @expectedException \Zend_Db_Statement_Exception */ diff --git a/dev/tests/integration/testsuite/Magento/Tax/Controller/Adminhtml/RateTest.php b/dev/tests/integration/testsuite/Magento/Tax/Controller/Adminhtml/RateTest.php index 91a845f151eaf..c2f7b498e63e3 100644 --- a/dev/tests/integration/testsuite/Magento/Tax/Controller/Adminhtml/RateTest.php +++ b/dev/tests/integration/testsuite/Magento/Tax/Controller/Adminhtml/RateTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Tax\Controller\Adminhtml; /** @@ -109,7 +110,7 @@ public function ajaxSaveActionDataInvalidDataProvider() { $expectedData = [ 'success' => false, - 'error_message' => 'Make sure all required information is valid.', + 'error_message' => 'The required information is invalid. Verify the information and try again.', ]; return [ [ diff --git a/dev/tests/integration/testsuite/Magento/Tax/Model/Calculation/RateRepositoryTest.php b/dev/tests/integration/testsuite/Magento/Tax/Model/Calculation/RateRepositoryTest.php index 07545754ca1b4..46b77032704eb 100644 --- a/dev/tests/integration/testsuite/Magento/Tax/Model/Calculation/RateRepositoryTest.php +++ b/dev/tests/integration/testsuite/Magento/Tax/Model/Calculation/RateRepositoryTest.php @@ -289,9 +289,9 @@ public function createDataProvider() 'zip_to' => 'to', ], 'error' => [ - 'country_id is a required field.', - 'percentage_rate is a required field.', - 'code is a required field.', + '"country_id" is required. Enter and try again.', + '"percentage_rate" is required. Enter and try again.', + '"code" is required. Enter and try again.', 'Invalid value of "from" provided for the zip_from field.', 'Invalid value of "to" provided for the zip_to field.', ], @@ -303,9 +303,9 @@ public function createDataProvider() 'zip_to' => '', ], 'error' => [ - 'country_id is a required field.', - 'percentage_rate is a required field.', - 'code is a required field.', + '"country_id" is required. Enter and try again.', + '"percentage_rate" is required. Enter and try again.', + '"code" is required. Enter and try again.', 'Invalid value of "" provided for the zip_from field.', 'Invalid value of "" provided for the zip_to field.', ], @@ -313,10 +313,10 @@ public function createDataProvider() 'empty' => [ [], 'error' => [ - 'country_id is a required field.', - 'percentage_rate is a required field.', - 'code is a required field.', - 'postcode is a required field.', + '"country_id" is required. Enter and try again.', + '"percentage_rate" is required. Enter and try again.', + '"code" is required. Enter and try again.', + '"postcode" is required. Enter and try again.', ], ], 'zipRangeAndPostcode' => [ @@ -327,9 +327,9 @@ public function createDataProvider() 'zip_to' => 78780, ], 'error' => [ - 'country_id is a required field.', - 'percentage_rate is a required field.', - 'code is a required field.', + '"country_id" is required. Enter and try again.', + '"percentage_rate" is required. Enter and try again.', + '"code" is required. Enter and try again.', ], ], 'higherRange' => [ @@ -339,9 +339,9 @@ public function createDataProvider() 'zip_to' => 78780, ], 'error' => [ - 'country_id is a required field.', - 'percentage_rate is a required field.', - 'code is a required field.', + '"country_id" is required. Enter and try again.', + '"percentage_rate" is required. Enter and try again.', + '"code" is required. Enter and try again.', 'Range To should be equal or greater than Range From.', ], ], @@ -349,37 +349,37 @@ public function createDataProvider() ['tax_country_id' => 'XX'], 'error' => [ 'Invalid value of "XX" provided for the country_id field.', - 'percentage_rate is a required field.', - 'code is a required field.', - 'postcode is a required field.', + '"percentage_rate" is required. Enter and try again.', + '"code" is required. Enter and try again.', + '"postcode" is required. Enter and try again.', ], ], 'invalidCountry2' => [ ['tax_country_id' => ' '], 'error' => [ - 'country_id is a required field.', - 'percentage_rate is a required field.', - 'code is a required field.', - 'postcode is a required field.', + '"country_id" is required. Enter and try again.', + '"percentage_rate" is required. Enter and try again.', + '"code" is required. Enter and try again.', + '"postcode" is required. Enter and try again.', ], ], 'invalidRegion1' => [ ['tax_region_id' => '-'], 'error' => [ - 'country_id is a required field.', + '"country_id" is required. Enter and try again.', 'Invalid value of "-" provided for the region_id field.', - 'percentage_rate is a required field.', - 'code is a required field.', - 'postcode is a required field.', + '"percentage_rate" is required. Enter and try again.', + '"code" is required. Enter and try again.', + '"postcode" is required. Enter and try again.', ], ], 'spaceRegion' => [ ['tax_region_id' => ' '], 'error' => [ - 'country_id is a required field.', - 'percentage_rate is a required field.', - 'code is a required field.', - 'postcode is a required field.', + '"country_id" is required. Enter and try again.', + '"percentage_rate" is required. Enter and try again.', + '"code" is required. Enter and try again.', + '"postcode" is required. Enter and try again.', ], ], 'emptyPercentageRate' => [ @@ -393,7 +393,7 @@ public function createDataProvider() 'zip_to' => 78780, ], 'error' => [ - 'percentage_rate is a required field.', + '"percentage_rate" is required. Enter and try again.', ], ] diff --git a/dev/tests/integration/testsuite/Magento/Tax/Model/TaxClass/RepositoryTest.php b/dev/tests/integration/testsuite/Magento/Tax/Model/TaxClass/RepositoryTest.php index 14a74c8ad12cd..0340ede79edaf 100644 --- a/dev/tests/integration/testsuite/Magento/Tax/Model/TaxClass/RepositoryTest.php +++ b/dev/tests/integration/testsuite/Magento/Tax/Model/TaxClass/RepositoryTest.php @@ -91,8 +91,8 @@ public function testSaveThrowsExceptionIfGivenDataIsInvalid() $this->taxClassRepository->save($taxClassDataObject); } catch (InputException $e) { $errors = $e->getErrors(); - $this->assertEquals('class_name is a required field.', $errors[0]->getMessage()); - $this->assertEquals('class_type is a required field.', $errors[1]->getMessage()); + $this->assertEquals('"class_name" is required. Enter and try again.', $errors[0]->getMessage()); + $this->assertEquals('"class_type" is required. Enter and try again.', $errors[1]->getMessage()); } } diff --git a/dev/tests/integration/testsuite/Magento/Tax/Model/TaxRuleRepositoryTest.php b/dev/tests/integration/testsuite/Magento/Tax/Model/TaxRuleRepositoryTest.php index 14dd0b7d9bb11..cb45e1971ecab 100644 --- a/dev/tests/integration/testsuite/Magento/Tax/Model/TaxRuleRepositoryTest.php +++ b/dev/tests/integration/testsuite/Magento/Tax/Model/TaxRuleRepositoryTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Tax\Model; use Magento\Framework\Api\Filter; @@ -277,7 +278,7 @@ public function testSaveUpdatesExistingTaxRule() /** * @magentoDbIsolation enabled * @expectedException \Magento\Framework\Exception\CouldNotSaveException - * @expectedExceptionMessage code is a required field + * @expectedExceptionMessage "code" is required. Enter and try again. */ public function testSaveThrowsExceptionIsRequiredFieldsAreMissing() { diff --git a/dev/tests/integration/testsuite/Magento/Theme/Model/Config/ValidatorTest.php b/dev/tests/integration/testsuite/Magento/Theme/Model/Config/ValidatorTest.php index 5f3a1a1706d62..7e54d4f74c9e1 100644 --- a/dev/tests/integration/testsuite/Magento/Theme/Model/Config/ValidatorTest.php +++ b/dev/tests/integration/testsuite/Magento/Theme/Model/Config/ValidatorTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Theme\Model\Config; use Magento\Email\Model\Template; @@ -56,7 +57,6 @@ protected function setUp() /** * @magentoDataFixture Magento/Email/Model/_files/email_template.php * @expectedException \Magento\Framework\Exception\LocalizedException - * @expectedExceptionMessage The email_header_template contains an incorrect configuration. The template has a */ public function testValidateHasRecursiveReference() { @@ -95,6 +95,11 @@ public function testValidateHasRecursiveReference() $designElementMock->expects($this->once())->method('getValue')->willReturn($this->templateModel->getId()); $this->model->validate($designConfigMock); + + $this->expectExceptionMessage( + 'The "email_header_template" template contains an incorrect configuration, with a reference to itself. ' + . 'Remove or change the reference, then try again.' + ); } /** diff --git a/dev/tests/integration/testsuite/Magento/Ui/Config/ConverterTest.php b/dev/tests/integration/testsuite/Magento/Ui/Config/ConverterTest.php index eedb2c1f9c5f4..3f5766eb3f478 100644 --- a/dev/tests/integration/testsuite/Magento/Ui/Config/ConverterTest.php +++ b/dev/tests/integration/testsuite/Magento/Ui/Config/ConverterTest.php @@ -88,6 +88,7 @@ public function getComponentNameDataProvider() ['form'], ['hidden'], ['htmlContent'], + ['imageUploader'], ['input'], ['insertForm'], ['insertListing'], diff --git a/dev/tests/integration/testsuite/Magento/Ui/_files/view/ui_component/arbitrary/imageUploader.xml b/dev/tests/integration/testsuite/Magento/Ui/_files/view/ui_component/arbitrary/imageUploader.xml new file mode 100644 index 0000000000000..ed1fdd38da26f --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Ui/_files/view/ui_component/arbitrary/imageUploader.xml @@ -0,0 +1,104 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<imageUploader xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="isMultipleFiles" xsi:type="boolean">false</item> + <item name="maxFileSize" xsi:type="number">0</item> + <item name="placeholderType" xsi:type="string">string</item> + <item name="allowedExtensions" xsi:type="string">string</item> + <item name="previewTmpl" xsi:type="string">string</item> + <item name="dropZone" xsi:type="string">string</item> + <item name="uploaderConfig" xsi:type="array"> + <item name="anySimpleType" active="false" xsi:type="string">string</item> + </item> + <item name="openDialogTitle" xsi:type="string" translate="true">string</item> + <item name="visible" xsi:type="boolean">false</item> + <item name="disabled" xsi:type="boolean">false</item> + <item name="labelVisible" xsi:type="boolean">false</item> + <item name="showFallbackReset" xsi:type="boolean">false</item> + <item name="focused" xsi:type="boolean">false</item> + <item name="label" xsi:type="string" translate="true">string</item> + <item name="dataType" xsi:type="string">string</item> + <item name="elementTmpl" xsi:type="string">string</item> + <item name="tooltipTpl" xsi:type="string">string</item> + <item name="fallbackResetTpl" xsi:type="string">string</item> + <item name="placeholder" xsi:type="string" translate="true">text</item> + <item name="validation" xsi:type="array"> + <item name="anySimpleType" active="false" xsi:type="boolean">true</item> + </item> + <item name="notice" xsi:type="string" translate="true">string</item> + <item name="required" xsi:type="boolean">false</item> + <item name="switcherConfig" xsi:type="array"> + <item name="name" xsi:type="string">string</item> + <item name="component" xsi:type="string">string</item> + <item name="target" xsi:type="string">string</item> + <item name="property" xsi:type="string">string</item> + <item name="enabled" xsi:type="boolean">true</item> + <item name="rules" xsi:type="array"> + <item name="string" xsi:type="array"> + <item name="value" xsi:type="string">string</item> + <item name="actions" xsi:type="array"> + <item name="string" xsi:type="array"> + <item name="target" xsi:type="string">string</item> + <item name="callback" xsi:type="string">string</item> + <item name="params" xsi:type="array"> + <item name="string" active="true" xsi:type="string"/> + </item> + </item> + </item> + </item> + </item> + </item> + <item name="tooltip" xsi:type="array"> + <item name="link" xsi:type="string">string</item> + <item name="description" xsi:type="string" translate="true">string</item> + </item> + <item name="additionalClasses" xsi:type="array"> + <item name="string" xsi:type="boolean">false</item> + </item> + <item name="addbefore" xsi:type="string" translate="true">string</item> + <item name="addafter" xsi:type="string" translate="true">string</item> + <item name="provider" xsi:type="string">string</item> + <item name="component" xsi:type="string">string</item> + <item name="template" xsi:type="string">string</item> + <item name="sortOrder" xsi:type="number">0</item> + <item name="displayArea" xsi:type="string">string</item> + <item name="storageConfig" xsi:type="array"> + <item name="provider" xsi:type="string">string</item> + <item name="namespace" xsi:type="string">string</item> + <item name="path" xsi:type="url" path="string"> + <param name="string">string</param> + </item> + </item> + <item name="statefull" xsi:type="array"> + <item name="anySimpleType" xsi:type="boolean">true</item> + </item> + <item name="imports" xsi:type="array"> + <item name="string" xsi:type="string">string</item> + </item> + <item name="exports" xsi:type="array"> + <item name="string" xsi:type="string">string</item> + </item> + <item name="links" xsi:type="array"> + <item name="string" xsi:type="string">string</item> + </item> + <item name="listens" xsi:type="array"> + <item name="string" xsi:type="string">string</item> + </item> + <item name="ns" xsi:type="string">string</item> + <item name="componentType" xsi:type="string">string</item> + <item name="dataScope" xsi:type="string">string</item> + </item> + <item name="js_config" xsi:type="array"> + <item name="deps" xsi:type="array"> + <item name="0" xsi:type="string">string</item> + </item> + </item> + </argument> +</imageUploader> diff --git a/dev/tests/integration/testsuite/Magento/Ui/_files/view/ui_component/expected/imageUploader.php b/dev/tests/integration/testsuite/Magento/Ui/_files/view/ui_component/expected/imageUploader.php new file mode 100644 index 0000000000000..0a9324ddb9284 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Ui/_files/view/ui_component/expected/imageUploader.php @@ -0,0 +1,411 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +return [ + 'arguments' => [ + 'data' => [ + 'name' => 'data', + 'xsi:type' => 'array', + 'item' => [ + 'config' => [ + 'name' => 'config', + 'xsi:type' => 'array', + 'item' => [ + 'isMultipleFiles' => [ + 'name' => 'isMultipleFiles', + 'xsi:type' => 'boolean', + 'value' => 'false', + ], + 'maxFileSize' => [ + 'name' => 'maxFileSize', + 'xsi:type' => 'number', + 'value' => '0', + ], + 'placeholderType' => [ + 'name' => 'placeholderType', + 'xsi:type' => 'string', + 'value' => 'string', + ], + 'allowedExtensions' => [ + 'name' => 'allowedExtensions', + 'xsi:type' => 'string', + 'value' => 'string', + ], + 'previewTmpl' => [ + 'name' => 'previewTmpl', + 'xsi:type' => 'string', + 'value' => 'string', + ], + 'dropZone' => [ + 'name' => 'dropZone', + 'xsi:type' => 'string', + 'value' => 'string', + ], + 'openDialogTitle' => [ + 'name' => 'openDialogTitle', + 'xsi:type' => 'string', + 'value' => 'string', + 'translate' => 'true' + ], + 'uploaderConfig' => [ + 'name' => 'uploaderConfig', + 'xsi:type' => 'array', + 'item' => [ + 'anySimpleType' => [ + 'name' => 'anySimpleType', + 'xsi:type' => 'string', + 'value' => 'string', + 'active' => 'false', + ], + ], + ], + 'visible' => [ + 'name' => 'visible', + 'xsi:type' => 'boolean', + 'value' => 'false', + ], + 'disabled' => [ + 'name' => 'disabled', + 'xsi:type' => 'boolean', + 'value' => 'false', + ], + 'labelVisible' => [ + 'name' => 'labelVisible', + 'xsi:type' => 'boolean', + 'value' => 'false', + ], + 'showFallbackReset' => [ + 'name' => 'showFallbackReset', + 'xsi:type' => 'boolean', + 'value' => 'false', + ], + 'focused' => [ + 'name' => 'focused', + 'xsi:type' => 'boolean', + 'value' => 'false', + ], + 'label' => [ + 'name' => 'label', + 'translate' => 'true', + 'xsi:type' => 'string', + 'value' => 'string', + ], + 'dataType' => [ + 'name' => 'dataType', + 'xsi:type' => 'string', + 'value' => 'string', + ], + 'elementTmpl' => [ + 'name' => 'elementTmpl', + 'xsi:type' => 'string', + 'value' => 'string', + ], + 'tooltipTpl' => [ + 'name' => 'tooltipTpl', + 'xsi:type' => 'string', + 'value' => 'string', + ], + 'fallbackResetTpl' => [ + 'name' => 'fallbackResetTpl', + 'xsi:type' => 'string', + 'value' => 'string', + ], + 'placeholder' => [ + 'name' => 'placeholder', + 'xsi:type' => 'string', + 'value' => 'text', + 'translate' => 'true', + ], + 'validation' => [ + 'name' => 'validation', + 'xsi:type' => 'array', + 'item' => [ + 'anySimpleType' => [ + 'name' => 'anySimpleType', + 'xsi:type' => 'boolean', + 'value' => 'true', + 'active' => 'false', + ], + ], + ], + 'notice' => [ + 'name' => 'notice', + 'translate' => 'true', + 'xsi:type' => 'string', + 'value' => 'string', + ], + 'required' => [ + 'name' => 'required', + 'xsi:type' => 'boolean', + 'value' => 'false', + ], + 'switcherConfig' => [ + 'name' => 'switcherConfig', + 'xsi:type' => 'array', + 'item' => [ + 'name' => [ + 'name' => 'name', + 'xsi:type' => 'string', + 'value' => 'string', + ], + 'component' => [ + 'name' => 'component', + 'xsi:type' => 'string', + 'value' => 'string', + ], + 'target' => [ + 'name' => 'target', + 'xsi:type' => 'string', + 'value' => 'string', + ], + 'property' => [ + 'name' => 'property', + 'xsi:type' => 'string', + 'value' => 'string', + ], + 'enabled' => [ + 'name' => 'enabled', + 'xsi:type' => 'boolean', + 'value' => 'true', + ], + 'rules' => [ + 'name' => 'rules', + 'xsi:type' => 'array', + 'item' => [ + 'string' => [ + 'name' => 'string', + 'xsi:type' => 'array', + 'item' => [ + 'value' => [ + 'name' => 'value', + 'xsi:type' => 'string', + 'value' => 'string', + ], + 'actions' => [ + 'name' => 'actions', + 'xsi:type' => 'array', + 'item' => [ + 'string' => [ + 'name' => 'string', + 'xsi:type' => 'array', + 'item' => [ + 'target' => [ + 'name' => 'target', + 'xsi:type' => 'string', + 'value' => 'string', + ], + 'callback' => [ + 'name' => 'callback', + 'xsi:type' => 'string', + 'value' => 'string', + ], + 'params' => [ + 'name' => 'params', + 'xsi:type' => 'array', + 'item' => [ + 'string' => [ + 'name' => 'string', + 'active' => 'true', + 'xsi:type' => 'string', + ], + ], + ], + ], + ], + ], + ], + ], + ], + ], + ], + ], + ], + 'tooltip' => [ + 'name' => 'tooltip', + 'xsi:type' => 'array', + 'item' => [ + 'link' => [ + 'name' => 'link', + 'xsi:type' => 'string', + 'value' => 'string', + ], + 'description' => [ + 'name' => 'description', + 'translate' => 'true', + 'xsi:type' => 'string', + 'value' => 'string', + ], + ], + ], + 'additionalClasses' => [ + 'name' => 'additionalClasses', + 'xsi:type' => 'array', + 'item' => [ + 'string' => [ + 'name' => 'string', + 'xsi:type' => 'boolean', + 'value' => 'false', + ], + ], + ], + 'addbefore' => [ + 'name' => 'addbefore', + 'translate' => 'true', + 'xsi:type' => 'string', + 'value' => 'string', + ], + 'addafter' => [ + 'name' => 'addafter', + 'translate' => 'true', + 'xsi:type' => 'string', + 'value' => 'string', + ], + 'provider' => [ + 'name' => 'provider', + 'xsi:type' => 'string', + 'value' => 'string', + ], + 'component' => [ + 'name' => 'component', + 'xsi:type' => 'string', + 'value' => 'string', + ], + 'template' => [ + 'name' => 'template', + 'xsi:type' => 'string', + 'value' => 'string', + ], + 'sortOrder' => [ + 'name' => 'sortOrder', + 'xsi:type' => 'number', + 'value' => '0', + ], + 'displayArea' => [ + 'name' => 'displayArea', + 'xsi:type' => 'string', + 'value' => 'string', + ], + 'storageConfig' => [ + 'name' => 'storageConfig', + 'xsi:type' => 'array', + 'item' => [ + 'provider' => [ + 'name' => 'provider', + 'xsi:type' => 'string', + 'value' => 'string', + ], + 'namespace' => [ + 'name' => 'namespace', + 'xsi:type' => 'string', + 'value' => 'string', + ], + 'path' => [ + 'name' => 'path', + 'xsi:type' => 'url', + 'param' => [ + 'string' => [ + 'name' => 'string', + 'value' => 'string', + ], + ], + 'path' => 'string', + ], + ], + ], + 'statefull' => [ + 'name' => 'statefull', + 'xsi:type' => 'array', + 'item' => [ + 'anySimpleType' => [ + 'name' => 'anySimpleType', + 'xsi:type' => 'boolean', + 'value' => 'true', + ], + ], + ], + 'imports' => [ + 'name' => 'imports', + 'xsi:type' => 'array', + 'item' => [ + 'string' => [ + 'name' => 'string', + 'xsi:type' => 'string', + 'value' => 'string', + ], + ], + ], + 'exports' => [ + 'name' => 'exports', + 'xsi:type' => 'array', + 'item' => [ + 'string' => [ + 'name' => 'string', + 'xsi:type' => 'string', + 'value' => 'string', + ], + ], + ], + 'links' => [ + 'name' => 'links', + 'xsi:type' => 'array', + 'item' => [ + 'string' => [ + 'name' => 'string', + 'xsi:type' => 'string', + 'value' => 'string', + ], + ], + ], + 'listens' => [ + 'name' => 'listens', + 'xsi:type' => 'array', + 'item' => [ + 'string' => [ + 'name' => 'string', + 'xsi:type' => 'string', + 'value' => 'string', + ], + ], + ], + 'ns' => [ + 'name' => 'ns', + 'xsi:type' => 'string', + 'value' => 'string', + ], + 'componentType' => [ + 'name' => 'componentType', + 'xsi:type' => 'string', + 'value' => 'string', + ], + 'dataScope' => [ + 'name' => 'dataScope', + 'xsi:type' => 'string', + 'value' => 'string', + ], + ], + ], + 'js_config' => [ + 'name' => 'js_config', + 'xsi:type' => 'array', + 'item' => [ + 'deps' => [ + 'name' => 'deps', + 'xsi:type' => 'array', + 'item' => [ + 0 => [ + 'name' => 0, + 'xsi:type' => 'string', + 'value' => 'string', + ], + ], + ], + ], + ], + ], + ], + ], + 'children' => [], + 'uiComponentType' => 'imageUploader', +]; diff --git a/dev/tests/integration/testsuite/Magento/Ui/_files/view/ui_component/mixed/imageUploader.xml b/dev/tests/integration/testsuite/Magento/Ui/_files/view/ui_component/mixed/imageUploader.xml new file mode 100644 index 0000000000000..81fb2bdff70f4 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Ui/_files/view/ui_component/mixed/imageUploader.xml @@ -0,0 +1,116 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<imageUploader xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd" + name="string" + template="string" + component="string" + class="string" + provider="string" + sortOrder="0" + displayArea="string"> + <settings> + + <!-- uiElementSettings --> + <statefull> + <property xsi:type="boolean" name="anySimpleType">true</property> + </statefull> + <imports> + <link active="false" name="string">string</link> + </imports> + <exports> + <link active="false" name="string">string</link> + </exports> + <links> + <link active="false" name="string">string</link> + </links> + <listens> + <link active="false" name="string">string</link> + </listens> + <deps> + <dep active="false">string</dep> + </deps> + <ns>string</ns> + <componentType>string</componentType> + <dataScope>string</dataScope> + <storageConfig> + <provider>string</provider> + <namespace>string</namespace> + <path path="string"> + <param name="string">string</param> + </path> + </storageConfig> + <!-- /uiElementSettings --> + + <!-- abstractSettings--> + <additionalClasses> + <class name="string">false</class> + </additionalClasses> + <label translate="false">string</label> + <addBefore translate="false">string</addBefore> + <addAfter translate="false">string</addAfter> + <dataType>string</dataType> + <elementTmpl>string</elementTmpl> + <visible>false</visible> + <disabled>false</disabled> + <notice translate="false">string</notice> + <focused>false</focused> + <tooltipTpl>string</tooltipTpl> + <fallbackResetTpl>string</fallbackResetTpl> + <placeholder translate="true">text</placeholder> + <labelVisible>false</labelVisible> + <showFallbackReset>false</showFallbackReset> + <required>false</required> + <validation> + <rule xsi:type="boolean" active="false" name="anySimpleType">true</rule> + </validation> + <switcherConfig> + <component>string</component> + <name>string</name> + <target>string</target> + <property>string</property> + <enabled>true</enabled> + <argument name="string" xsi:type="array"> + <item name="string" xsi:type="string">string</item> + </argument> + <rules> + <rule name="string"> + <value>string</value> + <actions> + <action name="string"> + <target>string</target> + <callback>string</callback> + <params> + <param name="string" active="true" xsi:type="string"/> + </params> + </action> + </actions> + </rule> + </rules> + </switcherConfig> + <tooltip> + <link>string</link> + <description translate="true">string</description> + </tooltip> + + <!-- /abstractSettings--> + <isMultipleFiles>false</isMultipleFiles> + <maxFileSize>0</maxFileSize> + <placeholderType>string</placeholderType> + <allowedExtensions>string</allowedExtensions> + <previewTmpl>string</previewTmpl> + <dropZone>string</dropZone> + <uploaderConfig> + <param xsi:type="string" active="false" name="anySimpleType"> + string + </param> + </uploaderConfig> + <openDialogTitle>string</openDialogTitle> + + </settings> +</imageUploader> diff --git a/dev/tests/integration/testsuite/Magento/Ui/_files/view/ui_component/semantic/imageUploader.xml b/dev/tests/integration/testsuite/Magento/Ui/_files/view/ui_component/semantic/imageUploader.xml new file mode 100644 index 0000000000000..eee45874a7706 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Ui/_files/view/ui_component/semantic/imageUploader.xml @@ -0,0 +1,117 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<imageUploader xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd" + name="string" + template="string" + component="string" + class="string" + provider="string" + sortOrder="0" + displayArea="string"> + <settings> + + <!-- uiElementSettings --> + <statefull> + <property xsi:type="boolean" name="anySimpleType">true</property> + </statefull> + <imports> + <link active="false" name="string">string</link> + </imports> + <exports> + <link active="false" name="string">string</link> + </exports> + <links> + <link active="false" name="string">string</link> + </links> + <listens> + <link active="false" name="string">string</link> + </listens> + <deps> + <dep active="false">string</dep> + </deps> + <ns>string</ns> + <componentType>string</componentType> + <dataScope>string</dataScope> + <storageConfig> + <provider>string</provider> + <namespace>string</namespace> + <path path="string"> + <param name="string">string</param> + </path> + </storageConfig> + <!-- /uiElementSettings --> + + <!-- abstractSettings--> + <additionalClasses> + <class name="string">false</class> + </additionalClasses> + <label translate="false">string</label> + <addBefore translate="false">string</addBefore> + <addAfter translate="false">string</addAfter> + <dataType>string</dataType> + <elementTmpl>string</elementTmpl> + <visible>false</visible> + <disabled>false</disabled> + <notice translate="false">string</notice> + <focused>false</focused> + <tooltipTpl>string</tooltipTpl> + <fallbackResetTpl>string</fallbackResetTpl> + <placeholder translate="true">text</placeholder> + <labelVisible>false</labelVisible> + <showFallbackReset>false</showFallbackReset> + <required>false</required> + <validation> + <rule xsi:type="boolean" active="false" name="anySimpleType">true</rule> + </validation> + <switcherConfig> + <component>string</component> + <name>string</name> + <target>string</target> + <property>string</property> + <enabled>true</enabled> + <argument name="string" xsi:type="array"> + <item name="string" xsi:type="string">string</item> + </argument> + <rules> + <rule name="string"> + <value>string</value> + <actions> + <action name="string"> + <target>string</target> + <callback>string</callback> + <params> + <param name="string" active="true" xsi:type="string"/> + </params> + </action> + </actions> + </rule> + </rules> + </switcherConfig> + <tooltip> + <link>string</link> + <description translate="true">string</description> + </tooltip> + + <!-- /abstractSettings--> + <isMultipleFiles>false</isMultipleFiles> + <maxFileSize>0</maxFileSize> + <placeholderType>string</placeholderType> + <allowedExtensions>string</allowedExtensions> + <previewTmpl>string</previewTmpl> + <dropZone>string</dropZone> + + <uploaderConfig> + <param xsi:type="string" active="false" name="anySimpleType"> + string + </param> + </uploaderConfig> + + <openDialogTitle>string</openDialogTitle> + </settings> +</imageUploader> diff --git a/dev/tests/integration/testsuite/Magento/User/Controller/Adminhtml/UserTest.php b/dev/tests/integration/testsuite/Magento/User/Controller/Adminhtml/UserTest.php index cfed67b9ddbdb..995ec5f6bed85 100644 --- a/dev/tests/integration/testsuite/Magento/User/Controller/Adminhtml/UserTest.php +++ b/dev/tests/integration/testsuite/Magento/User/Controller/Adminhtml/UserTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\User\Controller\Adminhtml; use Magento\TestFramework\Bootstrap; @@ -82,7 +83,11 @@ public function testSaveActionMissingCurrentAdminPassword() ] ); $this->dispatch('backend/admin/user/save'); - $this->assertSessionMessages($this->equalTo(['You have entered an invalid password for current user.'])); + $this->assertSessionMessages( + $this->equalTo( + ['The password entered for the current user is invalid. Verify the password and try again.'] + ) + ); $this->assertRedirect($this->stringContains('backend/admin/user/edit')); } diff --git a/dev/tests/integration/testsuite/Magento/User/Model/UserTest.php b/dev/tests/integration/testsuite/Magento/User/Model/UserTest.php index c0fe917f104db..8b85339afd789 100644 --- a/dev/tests/integration/testsuite/Magento/User/Model/UserTest.php +++ b/dev/tests/integration/testsuite/Magento/User/Model/UserTest.php @@ -316,11 +316,11 @@ public function testHasAssigned2Role() /** * @expectedException \Magento\Framework\Exception\LocalizedException - * @expectedExceptionMessage User Name is a required field. - * @expectedExceptionMessage First Name is a required field. - * @expectedExceptionMessage Last Name is a required field. + * @expectedExceptionMessage "User Name" is required. Enter and try again. + * @expectedExceptionMessage "First Name" is required. Enter and try again. + * @expectedExceptionMessage "Last Name" is required. Enter and try again. * @expectedExceptionMessage Please enter a valid email. - * @expectedExceptionMessage Password is required field. + * @expectedExceptionMessage "Password" is required. Enter and try again. * @magentoDbIsolation enabled */ public function testBeforeSaveRequiredFieldsValidation() @@ -498,13 +498,16 @@ public function testPerformIdentityCheck() * * @magentoDataFixture Magento/User/_files/user_with_role.php * @expectedException \Magento\Framework\Exception\AuthenticationException - * @expectedExceptionMessage You have entered an invalid password for current user. */ public function testPerformIdentityCheckWrongPassword() { $this->_model->loadByUsername('adminUser'); $passwordString = 'wrongPassword'; $this->_model->performIdentityCheck($passwordString); + + $this->expectExceptionMessage( + 'The password entered for the current user is invalid. Verify the password and try again.' + ); } /** @@ -512,11 +515,15 @@ public function testPerformIdentityCheckWrongPassword() * * @magentoDataFixture Magento/User/_files/locked_users.php * @expectedException \Magento\Framework\Exception\State\UserLockedException - * @expectedExceptionMessage You did not sign in correctly or your account is temporarily disabled. */ public function testPerformIdentityCheckLockExpires() { $this->_model->loadByUsername('adminUser2'); $this->_model->performIdentityCheck(\Magento\TestFramework\Bootstrap::ADMIN_PASSWORD); + + $this->expectExceptionMessage( + 'The account sign-in was incorrect or your account is disabled temporarily. ' + . 'Please wait and try again later.' + ); } } diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Catalog/adminhtml/js/components/dynamic-rows-import-custom-options.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Catalog/adminhtml/js/components/dynamic-rows-import-custom-options.test.js index c0d88f2f04ea1..3e904cd63821c 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Catalog/adminhtml/js/components/dynamic-rows-import-custom-options.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Catalog/adminhtml/js/components/dynamic-rows-import-custom-options.test.js @@ -55,7 +55,7 @@ define([ describe('Check processingInsertData', function () { it('Check with empty data.', function () { model.processingInsertData(); - expect(model.cacheGridData).toEqual([]); + expect(JSON.parse(JSON.stringify(model.cacheGridData))).toEqual([]); expect(model.insertData).not.toHaveBeenCalled(); }); @@ -64,21 +64,21 @@ define([ 'options': [] }]; model.processingInsertData(data); - expect(model.cacheGridData).toEqual([]); + expect(JSON.parse(JSON.stringify(model.cacheGridData))).toEqual([]); expect(model.insertData).not.toHaveBeenCalled(); }); it('Check with fake imported custom options data.', function () { model.processingInsertData(data); expect(model.insertData).toHaveBeenCalled(); - expect(model.cacheGridData[0]).toEqual({ + expect(JSON.parse(JSON.stringify(model.cacheGridData[0]))).toEqual({ 'option_type_id': 1, 'position': 1, 'values': [{ 'some_fake_value': 1 }] }); - expect(model.cacheGridData[1]).toEqual({ + expect(JSON.parse(JSON.stringify(model.cacheGridData[1]))).toEqual({ 'option_type_id': 2, 'position': 2, 'values': [{}] diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Checkout/frontend/js/view/shipping.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Checkout/frontend/js/view/shipping.test.js index be27e16a13786..5f14bc28f7995 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Checkout/frontend/js/view/shipping.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Checkout/frontend/js/view/shipping.test.js @@ -162,7 +162,9 @@ define(['squire', 'ko', 'jquery', 'jquery/validate'], function (Squire, ko, $) { }; expect(obj.validateShippingInformation()).toBeFalsy(); - expect(obj.errorValidationMessage()).toBe('Please specify a shipping method.'); + expect(obj.errorValidationMessage()).toBe( + 'The shipping method is missing. Select the shipping method and try again.' + ); spyOn(mocks['Magento_Checkout/js/model/quote'], 'shippingMethod').and.returnValue(true); spyOn(mocks['Magento_Customer/js/model/customer'], 'isLoggedIn').and.returnValue(true); expect(obj.validateShippingInformation()).toBeFalsy(); diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/image-uploader.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/image-uploader.test.js new file mode 100644 index 0000000000000..5dd3d43383bdb --- /dev/null +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/image-uploader.test.js @@ -0,0 +1,85 @@ +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +/*eslint max-nested-callbacks: 0*/ + +define([ + 'jquery', + 'Magento_Ui/js/form/element/image-uploader', + 'mage/adminhtml/browser' +], function ($, ImageUploader, browser) { + 'use strict'; + + describe('Magento_Ui/js/form/element/image-uploader', function () { + var component; + + beforeEach(function () { + component = new ImageUploader({ + dataScope: 'abstract' + }); + }); + + describe('initConfig method', function () { + it('sets mediaGalleryUid', function () { + component.initConfig(); + expect(component.mediaGalleryUid).toBeDefined(); + }); + }); + + describe('addFileFromMediaGallery method', function () { + it('adds file', function () { + var $el = $('div'); + + spyOn(component, 'addFile'); + + $el.data({ + 'size': 1024, + 'mime-type': 'image/png' + }); + + $el.val('/pub/media/something.png'); + + component.addFileFromMediaGallery(null, { + target: $el + }); + + expect(component.addFile).toHaveBeenCalledWith({ + type: 'image/png', + name: 'something.png', + url: '/pub/media/something.png', + size: 1024 + }); + }); + }); + + describe('openMediaBrowserDialog method', function () { + it('opens browser dialog', function () { + var $el = $('div'); + + $el.attr('id', 'theTargetId'); + + component.mediaGallery = { + openDialogUrl: 'http://example.com/', + openDialogTitle: 'Hello world', + storeId: 3 + }; + + spyOn(browser, 'openDialog'); + + component.openMediaBrowserDialog(null, { + target: $el + }); + + expect(browser.openDialog).toHaveBeenCalledWith( + 'http://example.com/target_element_id/theTargetId/store/3/type/image/' + + 'use_storage_root/1?isAjax=true', + null, + null, + 'Hello world' + ); + }); + }); + }); +}); diff --git a/dev/tests/js/jasmine/tests/lib/mage/misc.test.js b/dev/tests/js/jasmine/tests/lib/mage/misc.test.js index 45bbe5011c98f..f5dcd166149ef 100644 --- a/dev/tests/js/jasmine/tests/lib/mage/misc.test.js +++ b/dev/tests/js/jasmine/tests/lib/mage/misc.test.js @@ -11,6 +11,40 @@ define([ describe('mageUtils', function () { + it('Check getUrlParameters function', function () { + var fixture, + url, + getParameters; + + fixture = { + 'not valid url': {}, + 'http://example.com/catalogsearch/result/': {}, + 'http://example.com/catalogsearch/result/?': {}, + 'http://example.com/catalogsearch/result/?q': { + q: '' + }, + 'http://example.com/catalogsearch/result/?q=': { + q: '' + }, + 'http://example.com/catalogsearch/result/?q=+Simple+99%2C+8%2F%3F&cat=3': { + q: ' Simple 99, 8/?', + cat: '3' + }, + 'http://example.com/catalogsearch/result/?q=Simple&cat=3&p=1': { + q: 'Simple', + cat: '3', + p: '1' + } + }; + + for (url in fixture) { + if (fixture.hasOwnProperty(url)) { + getParameters = fixture[url]; + expect(utils.getUrlParameters(url)).toEqual(getParameters); + } + } + }); + it('Check convertToMomentFormat function', function () { var format, momentFormat; @@ -35,13 +69,13 @@ define([ it('Check convertToMomentFormat function for all Magento supported locales', function () { var fixture, - localeValues, - format, - expectedValue, - momentFormat, - dt, - m, - p; + localeValues, + format, + expectedValue, + momentFormat, + dt, + m, + p; fixture = { 'af_ZA': { diff --git a/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule1/revisions/drop_table/module.xml b/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule1/revisions/drop_table/module.xml index 5d408109ff1ee..a1b48d0ccb7a3 100644 --- a/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule1/revisions/drop_table/module.xml +++ b/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule1/revisions/drop_table/module.xml @@ -6,5 +6,5 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> - <module name="Magento_TestSetupDeclarationModule1" setup_version="0.0.1"/> + <module name="Magento_TestSetupDeclarationModule1" /> </config> diff --git a/app/code/Magento/Config/Setup/InstallData.php b/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule3/Setup/InstallData.php similarity index 55% rename from app/code/Magento/Config/Setup/InstallData.php rename to dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule3/Setup/InstallData.php index 37b8c72851712..9f8dd9e8c1ebc 100644 --- a/app/code/Magento/Config/Setup/InstallData.php +++ b/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule3/Setup/InstallData.php @@ -3,36 +3,29 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +namespace Magento\TestSetupDeclarationModule3\Setup; -namespace Magento\Config\Setup; - -use Magento\Framework\Module\Setup\Migration; use Magento\Framework\Setup\InstallDataInterface; use Magento\Framework\Setup\ModuleContextInterface; use Magento\Framework\Setup\ModuleDataSetupInterface; /** - * @codeCoverageIgnore + * Class InstallData + * @package Magento\TestSetupDeclarationModule3\Setup */ class InstallData implements InstallDataInterface { /** * {@inheritdoc} + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + * @SuppressWarnings(PHPMD.NPathComplexity) */ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context) { - $installer = $setup->createMigrationSetup(); + $adapter = $setup->getConnection(); $setup->startSetup(); - - $installer->appendClassAliasReplace( - 'core_config_data', - 'value', - Migration::ENTITY_TYPE_MODEL, - Migration::FIELD_CONTENT_TYPE_PLAIN, - ['config_id'] - ); - $installer->doUpdateClassAliases(); - + $adapter->insertArray('reference_table', ['some_integer'], [7, 2, 3, 5]); $setup->endSetup(); } } diff --git a/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule3/Setup/UpgradeData.php b/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule3/Setup/UpgradeData.php new file mode 100644 index 0000000000000..5c1a6b0f4387e --- /dev/null +++ b/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule3/Setup/UpgradeData.php @@ -0,0 +1,29 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\TestSetupDeclarationModule3\Setup; + +use Magento\Framework\Setup\ModuleContextInterface; +use Magento\Framework\Setup\ModuleDataSetupInterface; +use Magento\Framework\Setup\UpgradeDataInterface; + +/** + * Class InstallData + * @package Magento\TestSetupDeclarationModule3\Setup + */ +class UpgradeData implements UpgradeDataInterface +{ + /** + * {@inheritdoc} + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + * @SuppressWarnings(PHPMD.NPathComplexity) + */ + public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context) + { + $setup->startSetup(); + $setup->endSetup(); + } +} diff --git a/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule3/etc/db_schema.xml b/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule3/etc/db_schema.xml new file mode 100644 index 0000000000000..21691d23b6d7b --- /dev/null +++ b/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule3/etc/db_schema.xml @@ -0,0 +1,30 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:setup:Model/Declaration/Schema/etc/schema.xsd"> + <table name="reference_table" resource="default"> + <column xsi:type="tinyint" name="tinyint_ref" padding="7" nullable="false" identity="true" unsigned="false"/> + <column xsi:type="int" name="some_integer" default="0" nullable="false" unsigned="false"/> + <column xsi:type="varchar" name="for_patch_testing" comment="For patch testing" /> + <constraint xsi:type="primary" name="tinyint_primary"> + <column name="tinyint_ref"/> + </constraint> + </table> + <table name="test_table" resource="default"> + <!--Columns--> + <column xsi:type="smallint" identity="true" name="smallint" padding="3" nullable="true"/> + <column xsi:type="tinyint" name="tinyint" padding="7" nullable="true" unsigned="false"/> + <column xsi:type="varchar" name="varchar" length="254" nullable="true"/> + <column xsi:type="varbinary" name="varbinary" default="10101" /> + <constraint xsi:type="foreign" name="some_foreign_key" column="tinyint" table="test_table" + referenceTable="reference_table" referenceColumn="tinyint_ref" onDelete="CASCADE"/> + <constraint xsi:type="primary" name="PRIMARY"> + <column name="smallint" /> + </constraint> + </table> +</schema> diff --git a/dev/tests/setup-integration/_files/Magento/TestSetupModule2/etc/module.xml b/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule3/etc/module.xml similarity index 77% rename from dev/tests/setup-integration/_files/Magento/TestSetupModule2/etc/module.xml rename to dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule3/etc/module.xml index b6a26d50753fb..ed76bd12c9737 100644 --- a/dev/tests/setup-integration/_files/Magento/TestSetupModule2/etc/module.xml +++ b/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule3/etc/module.xml @@ -6,5 +6,5 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> - <module name="Magento_TestSetupModule2" setup_version="0.0.1"/> + <module name="Magento_TestSetupDeclarationModule3" setup_version="0.0.1"/> </config> diff --git a/dev/tests/setup-integration/_files/Magento/TestSetupModule1/registration.php b/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule3/registration.php similarity index 79% rename from dev/tests/setup-integration/_files/Magento/TestSetupModule1/registration.php rename to dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule3/registration.php index a7e2dcfb5319a..94ab9f3a90f54 100644 --- a/dev/tests/setup-integration/_files/Magento/TestSetupModule1/registration.php +++ b/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule3/registration.php @@ -7,6 +7,6 @@ use Magento\Framework\Component\ComponentRegistrar; $registrar = new ComponentRegistrar(); -if ($registrar->getPath(ComponentRegistrar::MODULE, 'Magento_TestSetupModule1') === null) { - ComponentRegistrar::register(ComponentRegistrar::MODULE, 'Magento_TestSetupModule1', __DIR__); +if ($registrar->getPath(ComponentRegistrar::MODULE, 'Magento_TestSetupDeclarationModule3') === null) { + ComponentRegistrar::register(ComponentRegistrar::MODULE, 'Magento_TestSetupDeclarationModule3', __DIR__); } diff --git a/dev/tests/setup-integration/_files/Magento/TestSetupModule1/etc/module.xml b/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule3/revisions/all_patches_revision/module.xml similarity index 77% rename from dev/tests/setup-integration/_files/Magento/TestSetupModule1/etc/module.xml rename to dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule3/revisions/all_patches_revision/module.xml index a69c11e3ad489..5b5eec3ecf1bf 100644 --- a/dev/tests/setup-integration/_files/Magento/TestSetupModule1/etc/module.xml +++ b/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule3/revisions/all_patches_revision/module.xml @@ -6,5 +6,5 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> - <module name="Magento_TestSetupModule1" setup_version="0.0.1"/> + <module name="Magento_TestSetupDeclarationModule3" setup_version="0.0.3"/> </config> diff --git a/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule3/revisions/cyclomatic_and_bic_revision/BicPatch.php b/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule3/revisions/cyclomatic_and_bic_revision/BicPatch.php new file mode 100644 index 0000000000000..bcff205a26899 --- /dev/null +++ b/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule3/revisions/cyclomatic_and_bic_revision/BicPatch.php @@ -0,0 +1,72 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\TestSetupDeclarationModule3\Setup\Patch\Data; + +use Magento\Framework\App\ResourceConnection; +use Magento\Setup\Model\Patch\DataPatchInterface; +use Magento\Setup\Model\Patch\PatchRevertableInterface; +use Magento\Setup\Model\Patch\PatchVersionInterface; + +/** + * @package Magento\TestSetupDeclarationModule3\Setup + */ +class BicPatch implements + DataPatchInterface, + PatchRevertableInterface, + PatchVersionInterface +{ + /** + * @var ResourceConnection + */ + private $resourceConnection; + + /** + * IncrementalSomeIntegerPatch constructor. + * @param ResourceConnection $resourceConnection + */ + public function __construct(ResourceConnection $resourceConnection) + { + $this->resourceConnection = $resourceConnection; + } + + /** + * @return string + */ + public function getVersion() + { + return '0.0.3'; + } + + /** + * @return array + */ + public function getAliases() + { + return []; + } + + /** + * @inheritdoc + */ + public function apply() + { + throw new \Exception("This patch can`t be applied, as it was created to test BIC"); + } + + public function revert() + { + } + + /** + * @return array + */ + public static function getDependencies() + { + return [ + RefBicPatch::class + ]; + } +} diff --git a/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule3/revisions/cyclomatic_and_bic_revision/RefBicPatch.php b/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule3/revisions/cyclomatic_and_bic_revision/RefBicPatch.php new file mode 100644 index 0000000000000..379b38ef1b8aa --- /dev/null +++ b/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule3/revisions/cyclomatic_and_bic_revision/RefBicPatch.php @@ -0,0 +1,72 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\TestSetupDeclarationModule3\Setup\Patch\Data; + +use Magento\Framework\App\ResourceConnection; +use Magento\Setup\Model\Patch\DataPatchInterface; +use Magento\Setup\Model\Patch\PatchRevertableInterface; +use Magento\Setup\Model\Patch\PatchVersionInterface; + +/** + * @package Magento\TestSetupDeclarationModule3\Setup + */ +class RefBicPatch implements + DataPatchInterface, + PatchRevertableInterface, + PatchVersionInterface +{ + /** + * @var ResourceConnection + */ + private $resourceConnection; + + /** + * IncrementalSomeIntegerPatch constructor. + * @param ResourceConnection $resourceConnection + */ + public function __construct(ResourceConnection $resourceConnection) + { + $this->resourceConnection = $resourceConnection; + } + + /** + * @return string + */ + public function getVersion() + { + return '0.0.3'; + } + + /** + * @return array + */ + public function getAliases() + { + return []; + } + + /** + * @inheritdoc + */ + public function apply() + { + throw new \Exception("This patch can`t be applied, as it was created to test BIC"); + } + + public function revert() + { + } + + /** + * @return array + */ + public static function getDependencies() + { + return [ + BicPatch::class + ]; + } +} diff --git a/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule3/revisions/cyclomatic_and_bic_revision/module.xml b/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule3/revisions/cyclomatic_and_bic_revision/module.xml new file mode 100644 index 0000000000000..0beb142b7752a --- /dev/null +++ b/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule3/revisions/cyclomatic_and_bic_revision/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_TestSetupDeclarationModule3" setup_version="0.0.3" /> +</config> diff --git a/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule3/revisions/first_patch_revision/UpgradeData.php b/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule3/revisions/first_patch_revision/UpgradeData.php new file mode 100644 index 0000000000000..dc8a41d24a38f --- /dev/null +++ b/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule3/revisions/first_patch_revision/UpgradeData.php @@ -0,0 +1,39 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\TestSetupDeclarationModule3\Setup; + +use Magento\Framework\Setup\ModuleContextInterface; +use Magento\Framework\Setup\ModuleDataSetupInterface; +use Magento\Framework\Setup\UpgradeDataInterface; + +/** + * Class InstallData + * @package Magento\TestSetupDeclarationModule3\Setup + */ +class UpgradeData implements UpgradeDataInterface +{ + /** + * {@inheritdoc} + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + * @SuppressWarnings(PHPMD.NPathComplexity) + */ + public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context) + { + $adapter = $setup->getConnection(); + $setup->startSetup(); + + if (version_compare($context->getVersion(), '0.0.2') < 0) { + $adapter->insertArray('reference_table', ['some_integer'], [6, 12]); + } + + if (version_compare($context->getVersion(), '0.0.3') < 0) { + $adapter->delete('reference_table', 'some_integer = 7'); + } + + $setup->endSetup(); + } +} diff --git a/dev/tests/setup-integration/_files/UpgradeScripts/TestSetupModule2/etc/module.xml b/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule3/revisions/first_patch_revision/module.xml similarity index 77% rename from dev/tests/setup-integration/_files/UpgradeScripts/TestSetupModule2/etc/module.xml rename to dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule3/revisions/first_patch_revision/module.xml index d781d8991cfe5..5b5eec3ecf1bf 100644 --- a/dev/tests/setup-integration/_files/UpgradeScripts/TestSetupModule2/etc/module.xml +++ b/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule3/revisions/first_patch_revision/module.xml @@ -6,5 +6,5 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> - <module name="Magento_TestSetupModule2" setup_version="0.0.2"/> + <module name="Magento_TestSetupDeclarationModule3" setup_version="0.0.3"/> </config> diff --git a/app/code/Magento/Bundle/etc/config.xml b/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule3/revisions/old_revision/module.xml similarity index 56% rename from app/code/Magento/Bundle/etc/config.xml rename to dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule3/revisions/old_revision/module.xml index 152f04e251c35..7bcf829123f5c 100644 --- a/app/code/Magento/Bundle/etc/config.xml +++ b/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule3/revisions/old_revision/module.xml @@ -5,5 +5,6 @@ * See COPYING.txt for license details. */ --> -<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Store:etc/config.xsd"> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> + <module name="Magento_TestSetupDeclarationModule3" setup_version="0.0.2"/> </config> diff --git a/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule3/revisions/patches_revision/IncrementalSomeIntegerPatch.php b/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule3/revisions/patches_revision/IncrementalSomeIntegerPatch.php new file mode 100644 index 0000000000000..37e976f1a5171 --- /dev/null +++ b/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule3/revisions/patches_revision/IncrementalSomeIntegerPatch.php @@ -0,0 +1,91 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\TestSetupDeclarationModule3\Setup\Patch\Data; + +use Magento\Framework\App\ResourceConnection; +use Magento\Setup\Model\Patch\DataPatchInterface; +use Magento\Setup\Model\Patch\PatchRevertableInterface; +use Magento\Setup\Model\Patch\PatchVersionInterface; + +/** + * Class InstallData + * @package Magento\TestSetupDeclarationModule3\Setup + */ +class IncrementalSomeIntegerPatch implements + DataPatchInterface, + PatchRevertableInterface, + PatchVersionInterface +{ + /** + * @var ResourceConnection + */ + private $resourceConnection; + + /** + * IncrementalSomeIntegerPatch constructor. + * @param ResourceConnection $resourceConnection + */ + public function __construct(ResourceConnection $resourceConnection) + { + $this->resourceConnection = $resourceConnection; + } + + /** + * @return string + */ + public static function getVersion() + { + return '1.0.5'; + } + + /** + * @return array + */ + public function getAliases() + { + return []; + } + + /** + * @inheritdoc + */ + public function apply() + { + $adapter = $this->resourceConnection->getConnection(); + $select = $adapter->select()->from('test_table', 'varchar') + ->where('`smallint` = ?', 1); + $refSelect = $adapter->select()->from('reference_table', 'for_patch_testing') + ->where('`tinyint_ref` = ?', 7); + $varchar = $adapter->fetchOne($select); + $varchar2 = $adapter->fetchOne($refSelect); + $adapter->insert('test_table', ['varchar' => $varchar . "_ref", 'varbinary' => 0101010]); + $adapter->insert('test_table', ['varchar' => $varchar2, 'varbinary' => 0]); + } + + public function revert() + { + $adapter = $this->resourceConnection->getConnection(); + $select = $adapter->select()->from('test_table', 'varchar') + ->where('`smallint` = ?', 1); + $varchar = $adapter->fetchOne($select); + $refSelect = $adapter->select()->from('reference_table', 'for_patch_testing') + ->where('`tinyint_ref` = ?', 7); + $varchar2 = $adapter->fetchOne($refSelect); + $adapter->delete('test_table', ['`varchar` = ?' => $varchar . "_ref"]); + $adapter->delete('test_table', ['`varchar` = ?' => $varchar2]); + } + + /** + * @return array + */ + public static function getDependencies() + { + return [ + ReferenceIncrementalSomeIntegerPatch::class, + NextChainPatch::class + ]; + } +} diff --git a/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule3/revisions/patches_revision/LlNextChainPatch.php b/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule3/revisions/patches_revision/LlNextChainPatch.php new file mode 100644 index 0000000000000..02d200851f051 --- /dev/null +++ b/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule3/revisions/patches_revision/LlNextChainPatch.php @@ -0,0 +1,75 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\TestSetupDeclarationModule3\Setup\Patch\Data; + +use Magento\Framework\App\ResourceConnection; +use Magento\Setup\Model\Patch\DataPatchInterface; +use Magento\Setup\Model\Patch\PatchRevertableInterface; +use Magento\Setup\Model\Patch\PatchVersionInterface; + +/** + * @package Magento\TestSetupDeclarationModule3\Setup + */ +class LlNextChainPatch implements + DataPatchInterface, + PatchRevertableInterface, + PatchVersionInterface +{ + /** + * @var ResourceConnection + */ + private $resourceConnection; + + /** + * IncrementalSomeIntegerPatch constructor. + * @param ResourceConnection $resourceConnection + */ + public function __construct(ResourceConnection $resourceConnection) + { + $this->resourceConnection = $resourceConnection; + } + + /** + * @return string + */ + public static function getVersion() + { + return '0.0.5'; + } + + /** + * @return array + */ + public function getAliases() + { + return []; + } + + /** + * @inheritdoc + */ + public function apply() + { + $adapter = $this->resourceConnection->getConnection(); + $adapter->insertArray('reference_table', ['for_patch_testing'], ['very_secret_string']); + } + + public function revert() + { + $adapter = $this->resourceConnection->getConnection(); + $adapter->delete('reference_table', ['for_patch_testing = ?' => 'very_secret_string']); + } + + /** + * @return array + */ + public static function getDependencies() + { + return [ + ZFirstPatch::class + ]; + } +} diff --git a/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule3/revisions/patches_revision/NextChainPatch.php b/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule3/revisions/patches_revision/NextChainPatch.php new file mode 100644 index 0000000000000..c953663a857fa --- /dev/null +++ b/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule3/revisions/patches_revision/NextChainPatch.php @@ -0,0 +1,90 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\TestSetupDeclarationModule3\Setup\Patch\Data; + +use Magento\Framework\App\ResourceConnection; +use Magento\Setup\Model\Patch\DataPatchInterface; +use Magento\Setup\Model\Patch\PatchRevertableInterface; +use Magento\Setup\Model\Patch\PatchVersionInterface; + +/** + * @package Magento\TestSetupDeclarationModule3\Setup + */ +class NextChainPatch implements + DataPatchInterface, + PatchRevertableInterface, + PatchVersionInterface +{ + /** + * @var ResourceConnection + */ + private $resourceConnection; + + /** + * IncrementalSomeIntegerPatch constructor. + * @param ResourceConnection $resourceConnection + */ + public function __construct(ResourceConnection $resourceConnection) + { + $this->resourceConnection = $resourceConnection; + } + + /** + * @return string + */ + public static function getVersion() + { + return '0.0.6'; + } + + /** + * @return array + */ + public function getAliases() + { + return []; + } + + /** + * @inheritdoc + */ + public function apply() + { + $adapter = $this->resourceConnection->getConnection(); + $refSelect = $adapter->select()->from('reference_table', 'for_patch_testing') + ->where('`tinyint_ref` = ?', 7); + $varchar2 = $adapter->fetchOne($refSelect); + $adapter->update( + 'reference_table', + ['for_patch_testing' => 'changed__' . $varchar2], + ['`tinyint_ref` = ?' => 7] + ); + } + + public function revert() + { + $adapter = $this->resourceConnection->getConnection(); + $refSelect = $adapter->select()->from('reference_table', 'for_patch_testing') + ->where('`tinyint_ref` = ?', 7); + $varchar2 = $adapter->fetchOne($refSelect); + $adapter->update( + 'reference_table', + ['for_patch_testing' => str_replace('changed__', '', $varchar2)], + ['`tinyint_ref` = ?' => 7] + ); + } + + /** + * @return array + */ + public static function getDependencies() + { + return [ + LlNextChainPatch::class, + ZFirstPatch::class + ]; + } +} diff --git a/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule3/revisions/patches_revision/ReferenceIncrementalSomeIntegerPatch.php b/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule3/revisions/patches_revision/ReferenceIncrementalSomeIntegerPatch.php new file mode 100644 index 0000000000000..f109545936393 --- /dev/null +++ b/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule3/revisions/patches_revision/ReferenceIncrementalSomeIntegerPatch.php @@ -0,0 +1,76 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\TestSetupDeclarationModule3\Setup\Patch\Data; + +use Magento\Framework\App\ResourceConnection; +use Magento\Setup\Model\Patch\DataPatchInterface; +use Magento\Setup\Model\Patch\PatchRevertableInterface; +use Magento\Setup\Model\Patch\PatchVersionInterface; + +/** + * Class ReferenceIncrementalSomeIntegerPatch + * @package Magento\TestSetupDeclarationModule3\Setup + */ +class ReferenceIncrementalSomeIntegerPatch implements + DataPatchInterface, + PatchRevertableInterface, + PatchVersionInterface +{ + /** + * @var ResourceConnection + */ + private $resourceConnection; + + /** + * IncrementalSomeIntegerPatch constructor. + * @param ResourceConnection $resourceConnection + */ + public function __construct(ResourceConnection $resourceConnection) + { + $this->resourceConnection = $resourceConnection; + } + + /** + * @return string + */ + public static function getVersion() + { + return '0.0.4'; + } + + /** + * @return array + */ + public function getAliases() + { + return []; + } + + /** + * @inheritdoc + */ + public function apply() + { + $adapter = $this->resourceConnection->getConnection(); + $adapter->insert('test_table', ['varchar' => 'Ololo123', 'varbinary' => 0101010]); + } + + public function revert() + { + $adapter = $this->resourceConnection->getConnection(); + $adapter->delete('test_table', ['`smallint` = ?' => 1]); + } + + /** + * @return array + */ + public static function getDependencies() + { + return [ + ZFirstPatch::class + ]; + } +} diff --git a/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule3/revisions/patches_revision/ZFirstPatch.php b/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule3/revisions/patches_revision/ZFirstPatch.php new file mode 100644 index 0000000000000..f0d457fa84310 --- /dev/null +++ b/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule3/revisions/patches_revision/ZFirstPatch.php @@ -0,0 +1,72 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\TestSetupDeclarationModule3\Setup\Patch\Data; + +use Magento\Framework\App\ResourceConnection; +use Magento\Setup\Exception; +use Magento\Setup\Model\Patch\DataPatchInterface; +use Magento\Setup\Model\Patch\PatchRevertableInterface; +use Magento\Setup\Model\Patch\PatchVersionInterface; + +/** + * Class InstallData + * @package Magento\TestSetupDeclarationModule3\Setup + */ +class ZFirstPatch implements + DataPatchInterface, + PatchVersionInterface, + PatchRevertableInterface +{ + /** + * @var ResourceConnection + */ + private $resourceConnection; + + /** + * IncrementalSomeIntegerPatch constructor. + * @param ResourceConnection $resourceConnection + */ + public function __construct(ResourceConnection $resourceConnection) + { + $this->resourceConnection = $resourceConnection; + } + + /** + * @return string + */ + public static function getVersion() + { + return '0.0.3'; + } + + /** + * @return array + */ + public function getAliases() + { + return []; + } + + public function revert() + { + } + + /** + * @inheritdoc + */ + public function apply() + { + throw new Exception('This patch should be covered by old script!'); + } + + /** + * @return array + */ + public static function getDependencies() + { + return []; + } +} diff --git a/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule4/etc/db_schema.xml b/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule4/etc/db_schema.xml new file mode 100644 index 0000000000000..351a14e5509e1 --- /dev/null +++ b/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule4/etc/db_schema.xml @@ -0,0 +1,19 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:setup:Model/Declaration/Schema/etc/schema.xsd"> + <table name="test_table" resource="default" comment="Test Table"> + <column xsi:type="int" name="page_id" nullable="false" /> + <column xsi:type="varchar" name="email" nullable="false" /> + <column xsi:type="varchar" name="title" /> + <constraint xsi:type="primary" name="PRIMARY"> + <column name="page_id" /> + <column name="email" /> + </constraint> + </table> +</schema> diff --git a/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule4/etc/db_schema_whitelist.json b/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule4/etc/db_schema_whitelist.json new file mode 100644 index 0000000000000..4036481252d46 --- /dev/null +++ b/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule4/etc/db_schema_whitelist.json @@ -0,0 +1,9 @@ +{ + "test_table": { + "column": { + "page_id": true, + "email": true, + "title": true + } + } +} diff --git a/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule4/etc/module.xml b/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule4/etc/module.xml new file mode 100644 index 0000000000000..01f7a6d1b0b2c --- /dev/null +++ b/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule4/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_TestSetupDeclarationModule4" setup_version="1.0.0" /> +</config> diff --git a/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule4/fixture/safe_data_provider.php b/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule4/fixture/safe_data_provider.php new file mode 100644 index 0000000000000..f753e0b633cc1 --- /dev/null +++ b/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule4/fixture/safe_data_provider.php @@ -0,0 +1,27 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +return [ + [ + 'page_id' => 1, + 'email' => '1@gmail.com', + 'title' => 'Title1' + ], + [ + 'page_id' => 2, + 'email' => '2@gmail.com', + 'title' => 'Title2' + ], + [ + 'page_id' => 3, + 'email' => '3@gmail.com', + 'title' => 'Title3' + ], + [ + 'page_id' => 4, + 'email' => '4@gmail.com', + 'title' => 'Title4' + ] +]; diff --git a/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule4/registration.php b/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule4/registration.php new file mode 100644 index 0000000000000..392171b1f5401 --- /dev/null +++ b/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule4/registration.php @@ -0,0 +1,12 @@ +<?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_TestSetupDeclarationModule4') === null) { + ComponentRegistrar::register(ComponentRegistrar::MODULE, 'Magento_TestSetupDeclarationModule4', __DIR__); +} diff --git a/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule4/revisions/remove_title_column/db_schema.xml b/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule4/revisions/remove_title_column/db_schema.xml new file mode 100644 index 0000000000000..a119c3452db58 --- /dev/null +++ b/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule4/revisions/remove_title_column/db_schema.xml @@ -0,0 +1,18 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:setup:Model/Declaration/Schema/etc/schema.xsd"> + <table name="test_table" resource="default" comment="Test Table"> + <column xsi:type="int" name="page_id" nullable="false" /> + <column xsi:type="varchar" name="email" nullable="false" /> + <constraint xsi:type="primary" name="PRIMARY"> + <column name="page_id" /> + <column name="email" /> + </constraint> + </table> +</schema> diff --git a/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule4/revisions/restore_title_column/db_schema.xml b/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule4/revisions/restore_title_column/db_schema.xml new file mode 100644 index 0000000000000..351a14e5509e1 --- /dev/null +++ b/dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule4/revisions/restore_title_column/db_schema.xml @@ -0,0 +1,19 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:setup:Model/Declaration/Schema/etc/schema.xsd"> + <table name="test_table" resource="default" comment="Test Table"> + <column xsi:type="int" name="page_id" nullable="false" /> + <column xsi:type="varchar" name="email" nullable="false" /> + <column xsi:type="varchar" name="title" /> + <constraint xsi:type="primary" name="PRIMARY"> + <column name="page_id" /> + <column name="email" /> + </constraint> + </table> +</schema> diff --git a/dev/tests/setup-integration/_files/Magento/TestSetupModule1/Setup/InstallSchema.php b/dev/tests/setup-integration/_files/Magento/TestSetupModule1/Setup/InstallSchema.php deleted file mode 100644 index 32226670cf10d..0000000000000 --- a/dev/tests/setup-integration/_files/Magento/TestSetupModule1/Setup/InstallSchema.php +++ /dev/null @@ -1,169 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -namespace Magento\TestSetupModule1\Setup; - -use Magento\Framework\Setup\InstallSchemaInterface; -use Magento\Framework\Setup\ModuleContextInterface; -use Magento\Framework\Setup\SchemaSetupInterface; - -/** - * @codeCoverageIgnore - */ -class InstallSchema implements InstallSchemaInterface -{ - /** - * {@inheritdoc} - * - * @SuppressWarnings(PHPMD.ExcessiveMethodLength) - */ - public function install(SchemaSetupInterface $setup, ModuleContextInterface $context) - { - $installer = $setup; - - $installer->startSetup(); - - /** - * Create table 'setup_table1' - */ - $table = $installer->getConnection()->newTable( - $installer->getTable('setup_tests_table1') - )->addColumn( - 'column_with_type_boolean', - \Magento\Framework\DB\Ddl\Table::TYPE_BOOLEAN, - null, - ['nullable' => false, 'default' => 0], - 'Column with type boolean' - )->addColumn( - 'column_with_type_smallint', - \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT, - null, - ['unsigned' => true, 'nullable' => false, 'default' => '0'], - 'Column with type smallint' - )->addColumn( - 'column_with_type_integer', - \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, - null, - ['unsigned' => true, 'identity' => true, 'nullable' => false, 'primary' => true], - 'Column with type integer' - )->addColumn( - 'column_with_type_bigint', - \Magento\Framework\DB\Ddl\Table::TYPE_BIGINT, - null, - ['unsigned' => true, 'nullable' => false, 'primary' => true], - 'Column with type bigint' - )->addColumn( - 'column_with_type_float', - \Magento\Framework\DB\Ddl\Table::TYPE_FLOAT, - null, - ['nullable' => true, 'default' => null], - 'Column with type float' - )->addColumn( - 'column_with_type_numeric', - \Magento\Framework\DB\Ddl\Table::TYPE_NUMERIC, - '12,4', - ['unsigned' => true, 'nullable' => true], - 'Column with type numeric' - )->addColumn( - 'column_with_type_decimal', - \Magento\Framework\DB\Ddl\Table::TYPE_DECIMAL, - '12,4', - ['unsigned' => true, 'nullable' => true], - 'Column with type decimal' - )->addColumn( - 'column_with_type_datetime', - \Magento\Framework\DB\Ddl\Table::TYPE_DATETIME, - null, - ['nullable' => true, 'default' => null], - 'Column with type datetime' - )->addColumn( - 'column_with_type_timestamp_update', - \Magento\Framework\DB\Ddl\Table::TYPE_TIMESTAMP, - null, - ['nullable' => false, 'default' => \Magento\Framework\DB\Ddl\Table::TIMESTAMP_UPDATE], - 'Column with type timestamp update' - )->addColumn( - 'column_with_type_date', - \Magento\Framework\DB\Ddl\Table::TYPE_DATE, - null, - ['nullable' => true, 'default' => null], - 'Column with type date' - )->addColumn( - 'column_with_type_text', - \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, - '64k', - [], - 'Column with type text' - )->addColumn( - 'column_with_type_blob', - \Magento\Framework\DB\Ddl\Table::TYPE_BLOB, - 32, - [], - 'Column with type blob' - )->addColumn( - 'column_with_type_verbinary', - \Magento\Framework\DB\Ddl\Table::TYPE_VARBINARY, - '2m', - [], - 'Column with type varbinary' - )->addIndex( - $installer->getIdxName( - 'setup_tests_table1', - ['column_with_type_text'], - \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_FULLTEXT - ), - ['column_with_type_text'], - ['type' => \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_FULLTEXT] - )->addIndex( - $installer->getIdxName( - 'setup_tests_table1', - 'column_with_type_integer', - \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_INDEX - ), - 'column_with_type_integer', - ['type' => \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_INDEX] - ); - - $installer->getConnection()->createTable($table); - - $relatedTable = $installer->getConnection()->newTable( - $installer->getTable('setup_tests_table1_related') - )->addColumn( - 'column_with_type_timestamp_init_update', - \Magento\Framework\DB\Ddl\Table::TYPE_TIMESTAMP, - null, - ['nullable' => false, 'default' => \Magento\Framework\DB\Ddl\Table::TIMESTAMP_INIT_UPDATE], - 'Column with type timestamp init update' - )->addColumn( - 'column_with_type_timestamp_init', - \Magento\Framework\DB\Ddl\Table::TYPE_TIMESTAMP, - null, - ['nullable' => false, 'default' => \Magento\Framework\DB\Ddl\Table::TIMESTAMP_INIT], - 'Column with type timestamp init' - )->addColumn( - 'column_with_relation', - \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, - null, - ['unsigned' => true, 'nullable' => false], - 'Column with type integer and relation' - )->addForeignKey( - $installer->getFkName( - 'setup_table1_related', - 'column_with_relation', - 'setup_tests_table1', - 'column_with_type_integer' - ), - 'column_with_relation', - $installer->getTable('setup_tests_table1'), - 'column_with_type_integer', - \Magento\Framework\DB\Ddl\Table::ACTION_CASCADE - )->setComment( - 'Related Table' - ); - $installer->getConnection()->createTable($relatedTable); - $installer->endSetup(); - } -} diff --git a/dev/tests/setup-integration/_files/Magento/TestSetupModule2/Setup/InstallData.php b/dev/tests/setup-integration/_files/Magento/TestSetupModule2/Setup/InstallData.php deleted file mode 100644 index 7f115c0881abe..0000000000000 --- a/dev/tests/setup-integration/_files/Magento/TestSetupModule2/Setup/InstallData.php +++ /dev/null @@ -1,61 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\TestSetupModule2\Setup; - -use Magento\Framework\Setup\InstallDataInterface; -use Magento\Framework\Setup\ModuleContextInterface; -use Magento\Framework\Setup\ModuleDataSetupInterface; - -/** - * @codeCoverageIgnore - */ -class InstallData implements InstallDataInterface -{ - /** - * {@inheritdoc} - */ - public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context) - { - $setup->startSetup(); - - $setup->getConnection()->insertForce( - $setup->getTable('setup_tests_entity_table'), - [ - 'website_id' => 1, - 'email_field' => 'entity@example.com', - 'created_at' => '2017-10-30 09:41:25', - 'updated_at' => '2017-10-30 09:45:05', - 'created_in' => 'Default Store View', - 'firstname' => 'John', - 'lastname' => 'Doe', - 'dob' => '1973-12-15', - 'default_billing_address_id' => 1, - 'default_shipping_address_id' => 1 - ] - ); - $setup->getConnection()->insertForce( - $setup->getTable('setup_tests_address_entity'), - [ - 'parent_id' => 1, - 'created_at' => '2017-10-30 09:45:05', - 'updated_at' => '2017-10-30 09:45:05', - 'is_active' => 1, - 'city' => 'city', - 'company' => 'Magento', - 'country_id' => 'US', - 'firstname' => 'John', - 'lastname' => 'Doe', - 'postcode' => '90210', - 'region' => 'Alabama', - 'region_id' => 1, - 'street' => 'street1', - 'telephone' => 12345678, - ] - ); - - $setup->endSetup(); - } -} diff --git a/dev/tests/setup-integration/_files/Magento/TestSetupModule2/Setup/InstallSchema.php b/dev/tests/setup-integration/_files/Magento/TestSetupModule2/Setup/InstallSchema.php deleted file mode 100644 index 44dccfae087f9..0000000000000 --- a/dev/tests/setup-integration/_files/Magento/TestSetupModule2/Setup/InstallSchema.php +++ /dev/null @@ -1,404 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -namespace Magento\TestSetupModule2\Setup; - -use Magento\Framework\Setup\InstallSchemaInterface; -use Magento\Framework\Setup\ModuleContextInterface; -use Magento\Framework\Setup\SchemaSetupInterface; - -/** - * @codeCoverageIgnore - */ -class InstallSchema implements InstallSchemaInterface -{ - /** - * {@inheritdoc} - * - * @SuppressWarnings(PHPMD.ExcessiveMethodLength) - */ - public function install(SchemaSetupInterface $setup, ModuleContextInterface $context) - { - $installer = $setup; - $installer->startSetup(); - - /** - * Create table 'entity_table' - */ - $table = $installer->getConnection()->newTable( - $installer->getTable('setup_tests_entity_table') - )->addColumn( - 'entity_id', - \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, - null, - ['identity' => true, 'unsigned' => true, 'nullable' => false, 'primary' => true], - 'Entity Id' - )->addColumn( - 'website_id', - \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT, - null, - ['unsigned' => true], - 'Website Id' - )->addColumn( - 'email_field', - \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, - 255, - [], - 'Email' - )->addColumn( - 'increment_id', - \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, - 50, - [], - 'Increment Id' - )->addColumn( - 'created_at', - \Magento\Framework\DB\Ddl\Table::TYPE_TIMESTAMP, - null, - ['nullable' => false, 'default' => \Magento\Framework\DB\Ddl\Table::TIMESTAMP_INIT], - 'Created At' - )->addColumn( - 'updated_at', - \Magento\Framework\DB\Ddl\Table::TYPE_TIMESTAMP, - null, - ['nullable' => false, 'default' => \Magento\Framework\DB\Ddl\Table::TIMESTAMP_INIT_UPDATE], - 'Updated At' - )->addColumn( - 'created_in', - \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, - 255, - [], - 'Created From' - )->addColumn( - 'firstname', - \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, - 255, - [], - 'First Name' - )->addColumn( - 'lastname', - \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, - 255, - [], - 'Last Name' - )->addColumn( - 'dob', - \Magento\Framework\DB\Ddl\Table::TYPE_DATE, - null, - [], - 'Date of Birth' - )->addColumn( - 'default_billing_address_id', - \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, - null, - ['unsigned' => true, 'nullable' => true, 'default' => null], - 'Default Billing Address' - )->addColumn( - 'default_shipping_address_id', - \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, - null, - ['unsigned' => true, 'nullable' => true, 'default' => null], - 'Default Shipping Address' - )->addIndex( - $installer->getIdxName( - 'setup_tests_entity_table', - ['email_field', 'website_id'], - \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_UNIQUE - ), - ['email_field', 'website_id'], - ['type' => \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_UNIQUE] - )->addIndex( - $installer->getIdxName('setup_tests_entity_table', ['website_id']), - ['website_id'] - )->addIndex( - $installer->getIdxName('setup_tests_entity_table', ['firstname']), - ['firstname'] - )->addIndex( - $installer->getIdxName('setup_tests_entity_table', ['lastname']), - ['lastname'] - )->addForeignKey( - $installer->getFkName( - 'setup_tests_entity_table', - 'website_id', - 'store_website', - 'website_id' - ), - 'website_id', - $installer->getTable('store_website'), - 'website_id', - \Magento\Framework\DB\Ddl\Table::ACTION_SET_NULL - )->setComment( - 'Entity Table' - ); - $installer->getConnection()->createTable($table); - - /** - * Create table 'address_entity' - */ - $table = $installer->getConnection()->newTable( - $installer->getTable('setup_tests_address_entity') - )->addColumn( - 'entity_id', - \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, - null, - ['identity' => true, 'unsigned' => true, 'nullable' => false, 'primary' => true], - 'Entity Id' - )->addColumn( - 'increment_id', - \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, - 50, - [], - 'Increment Id' - )->addColumn( - 'parent_id', - \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, - null, - ['unsigned' => true, 'nullable' => true], - 'Parent Id' - )->addColumn( - 'created_at', - \Magento\Framework\DB\Ddl\Table::TYPE_TIMESTAMP, - null, - ['nullable' => false, 'default' => \Magento\Framework\DB\Ddl\Table::TIMESTAMP_INIT], - 'Created At' - )->addColumn( - 'updated_at', - \Magento\Framework\DB\Ddl\Table::TYPE_TIMESTAMP, - null, - ['nullable' => false, 'default' => \Magento\Framework\DB\Ddl\Table::TIMESTAMP_INIT_UPDATE], - 'Updated At' - )->addColumn( - 'is_active', - \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT, - null, - ['unsigned' => true, 'nullable' => false, 'default' => '1'], - 'Is Active' - )->addColumn( - 'city', - \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, - 255, - ['nullable' => false], - 'City' - )->addColumn( - 'company', - \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, - 255, - ['nullable' => true, 'default' => null], - 'Company' - )->addColumn( - 'country_id', - \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, - 255, - ['nullable' => false], - 'Country' - )->addColumn( - 'fax', - \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, - 255, - ['nullable' => true, 'default' => null], - 'Fax' - )->addColumn( - 'firstname', - \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, - 255, - ['nullable' => false], - 'First Name' - )->addColumn( - 'lastname', - \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, - 255, - ['nullable' => false], - 'Last Name' - )->addColumn( - 'middlename', - \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, - 255, - ['nullable' => true, 'default' => null], - 'Middle Name' - )->addColumn( - 'postcode', - \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, - 255, - ['nullable' => true, 'default' => null], - 'Zip/Postal Code' - )->addColumn( - 'prefix', - \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, - 40, - ['nullable' => true, 'default' => null], - 'Name Prefix' - )->addColumn( - 'region', - \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, - 255, - ['nullable' => true, 'default' => null], - 'State/Province' - )->addColumn( - 'region_id', - \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, - null, - ['unsigned' => true, 'nullable' => true, 'default' => null], - 'State/Province' - )->addColumn( - 'street', - \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, - null, - ['nullable' => false], - 'Street Address' - )->addColumn( - 'suffix', - \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, - 40, - ['nullable' => true, 'default' => null], - 'Name Suffix' - )->addColumn( - 'telephone', - \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, - 255, - ['nullable' => false], - 'Phone Number' - )->addIndex( - $installer->getIdxName('address_entity', ['parent_id']), - ['parent_id'] - )->addForeignKey( - $installer->getFkName( - 'setup_tests_address_entity', - 'parent_id', - 'setup_tests_entity_table', - 'entity_id' - ), - 'parent_id', - $installer->getTable('setup_tests_entity_table'), - 'entity_id', - \Magento\Framework\DB\Ddl\Table::ACTION_CASCADE, - \Magento\Framework\DB\Ddl\Table::ACTION_CASCADE - )->setComment( - 'Address Entity' - ); - $installer->getConnection()->createTable($table); - - /** - * Create table 'address_entity_datetime' - */ - $table = $installer->getConnection()->newTable( - $installer->getTable('setup_tests_address_entity_datetime') - )->addColumn( - 'value_id', - \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, - null, - ['identity' => true, 'nullable' => false, 'primary' => true], - 'Value Id' - )->addColumn( - 'attribute_id', - \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT, - null, - ['unsigned' => true, 'nullable' => false, 'default' => '0'], - 'Attribute Id' - )->addColumn( - 'entity_id', - \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, - null, - ['unsigned' => true, 'nullable' => false, 'default' => '0'], - 'Entity Id' - )->addColumn( - 'value', - \Magento\Framework\DB\Ddl\Table::TYPE_DATETIME, - null, - ['nullable' => true, 'default' => null], - 'Value' - )->addIndex( - $installer->getIdxName( - 'setup_tests_address_entity_datetime', - ['entity_id', 'attribute_id'], - \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_UNIQUE - ), - ['entity_id', 'attribute_id'], - ['type' => \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_UNIQUE] - )->addIndex( - $installer->getIdxName('setup_tests_address_entity_datetime', ['attribute_id']), - ['attribute_id'] - )->addIndex( - $installer->getIdxName( - 'setup_tests_address_entity_datetime', - ['entity_id', 'attribute_id', 'value'] - ), - ['entity_id', 'attribute_id', 'value'] - )->addForeignKey( - $installer->getFkName( - 'address_entity_datetime', - 'entity_id', - 'address_entity', - 'entity_id' - ), - 'entity_id', - $installer->getTable('setup_tests_address_entity'), - 'entity_id', - \Magento\Framework\DB\Ddl\Table::ACTION_CASCADE - )->setComment( - 'Address Entity Datetime' - ); - $installer->getConnection()->createTable($table); - - /** - * Create table 'address_entity_decimal' - */ - $table = $installer->getConnection()->newTable( - $installer->getTable('setup_tests_address_entity_decimal') - )->addColumn( - 'value_id', - \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, - null, - ['identity' => true, 'nullable' => false, 'primary' => true], - 'Value Id' - )->addColumn( - 'attribute_id', - \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT, - null, - ['unsigned' => true, 'nullable' => false, 'default' => '0'], - 'Attribute Id' - )->addColumn( - 'entity_id', - \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, - null, - ['unsigned' => true, 'nullable' => false, 'default' => '0'], - 'Entity Id' - )->addColumn( - 'value', - \Magento\Framework\DB\Ddl\Table::TYPE_DECIMAL, - '12,4', - ['nullable' => false, 'default' => '0.0000'], - 'Value' - )->addIndex( - $installer->getIdxName( - 'setup_tests_address_entity_decimal', - ['entity_id', 'attribute_id'], - \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_UNIQUE - ), - ['entity_id', 'attribute_id'], - ['type' => \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_UNIQUE] - )->addIndex( - $installer->getIdxName('setup_tests_address_entity_decimal', ['attribute_id']), - ['attribute_id'] - )->addIndex( - $installer->getIdxName('setup_tests_address_entity_decimal', ['entity_id', 'attribute_id', 'value']), - ['entity_id', 'attribute_id', 'value'] - )->addForeignKey( - $installer->getFkName( - 'setup_tests_address_entity_decimal', - 'entity_id', - 'setup_tests_address_entity', - 'entity_id' - ), - 'entity_id', - $installer->getTable('setup_tests_address_entity'), - 'entity_id', - \Magento\Framework\DB\Ddl\Table::ACTION_CASCADE - )->setComment( - 'Address Entity Decimal' - ); - $installer->getConnection()->createTable($table); - } -} diff --git a/dev/tests/setup-integration/_files/UpgradeScripts/TestSetupModule2/Setup/UpgradeData.php b/dev/tests/setup-integration/_files/UpgradeScripts/TestSetupModule2/Setup/UpgradeData.php deleted file mode 100644 index 871346e10e47e..0000000000000 --- a/dev/tests/setup-integration/_files/UpgradeScripts/TestSetupModule2/Setup/UpgradeData.php +++ /dev/null @@ -1,65 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\TestSetupModule2\Setup; - -use Magento\Framework\Setup\UpgradeDataInterface; -use Magento\Framework\Setup\ModuleContextInterface; -use Magento\Framework\Setup\ModuleDataSetupInterface; - -/** - * @codeCoverageIgnore - */ -class UpgradeData implements UpgradeDataInterface -{ - - /** - * {@inheritdoc} - */ - public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context) - { - $setup->startSetup(); - - // data update for TestSetupModule2 module < 0.0.2 - if (version_compare($context->getVersion(), '0.0.2', '<')) { - // add one more row to address_entity table - $setup->getConnection()->insertForce( - $setup->getTable('setup_tests_address_entity'), - [ - 'parent_id' => 1, - 'created_at' => '2017-10-30 13:34:19', - 'updated_at' => '2017-10-30 13:34:19', - 'is_active' => 1, - 'city' => 'Austin', - 'company' => 'X.Commerce', - 'country_id' => 'US', - 'firstname' => 'Joan', - 'lastname' => 'Doe', - 'postcode' => '36351', - 'region' => 'Alabama', - 'region_id' => 1, - 'street' => 'New Brockton', - 'telephone' => 12345678, - ] - ); - $setup->getConnection()->update( - $setup->getTable('setup_tests_entity_table'), - [ - 'increment_id'=> 1 - ], - 'increment_id = null' - ); - - $setup->getConnection()->insertForce( - $setup->getTable('setup_tests_entity_passwords'), - [ - 'entity_id' => 1, - 'password_hash' => '139e2ee2785cd9d9eb5714a02aca579bbcc05f9062996389d6e0e329bab9841b', - ] - ); - } - $setup->endSetup(); - } -} diff --git a/dev/tests/setup-integration/_files/UpgradeScripts/TestSetupModule2/Setup/UpgradeSchema.php b/dev/tests/setup-integration/_files/UpgradeScripts/TestSetupModule2/Setup/UpgradeSchema.php deleted file mode 100755 index 084ef15b5f6ee..0000000000000 --- a/dev/tests/setup-integration/_files/UpgradeScripts/TestSetupModule2/Setup/UpgradeSchema.php +++ /dev/null @@ -1,149 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -namespace Magento\TestSetupModule2\Setup; - -use Magento\Framework\Setup\ModuleContextInterface; -use Magento\Framework\Setup\SchemaSetupInterface; -use Magento\Framework\Setup\UpgradeSchemaInterface; - -/** - * @codeCoverageIgnore - */ -class UpgradeSchema implements UpgradeSchemaInterface -{ - /** - * {@inheritdoc} - * - * @SuppressWarnings(PHPMD.ExcessiveMethodLength) - */ - public function upgrade(SchemaSetupInterface $setup, ModuleContextInterface $context) - { - $setup->startSetup(); - - if (version_compare($context->getVersion(), '0.0.2') < 0) { - $connection = $setup->getConnection(); - - //add new column - $setup->getConnection()->addColumn( - $setup->getTable('setup_tests_entity_table'), - 'group_id', - [ - 'type' => \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT, - 'unsigned' => true, - 'nullable' => false, - 'default' => '0', - 'comment' => 'Group Id' - ] - ); - $setup->getConnection()->addColumn( - $setup->getTable('setup_tests_entity_table'), - 'store_id', - [ - 'type' => \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT, - 'unsigned' => true, - 'default' => '0', - 'comment' => 'Store Id' - ] - ); - - //add index - $connection->addIndex( - $setup->getTable('setup_tests_entity_table'), - $setup->getIdxName('setup_tests_entity_table', ['store_id']), - ['store_id'] - ); - - //modify existing column with type TEXT/TYPE_TIMESTAMP - $setup->getConnection()->modifyColumn( - $setup->getTable('setup_tests_address_entity'), - 'suffix', - [ - 'type' => \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, - 'length' => 100, - ] - )->modifyColumn( - $setup->getTable('setup_tests_entity_table'), - 'created_at', - [ - 'type' => \Magento\Framework\DB\Ddl\Table::TYPE_TIMESTAMP, - 'nullable' => false, - 'default' => \Magento\Framework\DB\Ddl\Table::TIMESTAMP_INIT_UPDATE, - ] - ); - - //addTable - $table = $setup->getConnection() - ->newTable($setup->getTable('setup_tests_entity_passwords')) - ->addColumn( - 'password_id', - \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, - null, - ['identity' => true, 'unsigned' => true, 'nullable' => false, 'primary' => true], - 'Password Id' - ) - ->addColumn( - 'entity_id', - \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, - null, - ['unsigned' => true, 'nullable' => false, 'default' => '0'], - 'User Id' - ) - ->addColumn( - 'password_hash', - \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, - 100, - [], - 'Password Hash' - ) - ->addIndex( - $setup->getIdxName('setup_tests_entity_passwords', ['entity_id']), - ['entity_id'] - ) - ->addForeignKey( - $setup->getFkName( - 'setup_tests_entity_passwords', - 'entity_id', - 'setup_tests_entity_table', - 'entity_id' - ), - 'entity_id', - $setup->getTable('setup_tests_entity_table'), - 'entity_id', - \Magento\Framework\DB\Ddl\Table::ACTION_CASCADE - ) - ->setComment('Entity Passwords'); - - $setup->getConnection()->createTable($table); - //remove foreign key - $connection->dropForeignKey( - $setup->getTable('setup_tests_address_entity_decimal'), - $setup->getFkName( - 'setup_tests_address_entity_decimal', - 'entity_id', - 'setup_tests_address_entity', - 'entity_id' - ) - ); - - //remove index - $connection->dropIndex( - $setup->getTable('setup_tests_address_entity_decimal'), - $setup->getIdxName( - $setup->getTable('setup_tests_address_entity_decimal'), - ['entity_id', 'attribute_id'] - ) - ); - //remove column - $connection->dropColumn($setup->getTable('setup_tests_entity_table'), 'dob'); - - //remove table - $connection->dropTable($setup->getTable('setup_tests_address_entity_datetime')); - } - - $setup->endSetup(); - } -} diff --git a/dev/tests/setup-integration/framework/Magento/TestFramework/Annotation/CopyModules.php b/dev/tests/setup-integration/framework/Magento/TestFramework/Annotation/CopyModules.php index 89d894786b1e3..390dc595c6bda 100644 --- a/dev/tests/setup-integration/framework/Magento/TestFramework/Annotation/CopyModules.php +++ b/dev/tests/setup-integration/framework/Magento/TestFramework/Annotation/CopyModules.php @@ -6,6 +6,7 @@ namespace Magento\TestFramework\Annotation; +use Magento\Framework\Filesystem\Io\File; use Magento\TestFramework\Deploy\CliCommand; use Magento\TestFramework\Deploy\TestModuleManager; @@ -50,4 +51,22 @@ public function startTest(\PHPUnit\Framework\TestCase $test) include_once $path; } } + + /** + * Handler for 'startTest' event + * + * @param \PHPUnit\Framework\TestCase $test + */ + public function endTest(\PHPUnit\Framework\TestCase $test) + { + $annotations = $test->getAnnotations(); + //This annotation can be declared only on method level + if (isset($annotations['method']['moduleName'])) { + $path = MAGENTO_MODULES_PATH . + //Take only module name from Magento_ModuleName + explode("_", $annotations['method']['moduleName'][0])[1]; + + File::rmdirRecursive($path); + } + } } diff --git a/dev/tests/setup-integration/framework/Magento/TestFramework/Deploy/CliCommand.php b/dev/tests/setup-integration/framework/Magento/TestFramework/Deploy/CliCommand.php index 81804a2b8bb8b..3b3ef08ac86e3 100644 --- a/dev/tests/setup-integration/framework/Magento/TestFramework/Deploy/CliCommand.php +++ b/dev/tests/setup-integration/framework/Magento/TestFramework/Deploy/CliCommand.php @@ -72,14 +72,18 @@ public function enableModule($moduleName) /** * Execute upgrade magento command. * + * @param array $installParams * @return string */ - public function upgrade() + public function upgrade($installParams = []) { $initParams = $this->parametersHolder->getInitParams(); - $enableModuleCommand = 'php -f ' . BP . '/bin/magento setup:upgrade -vvv -n --magento-init-params=' + $upgradeCommand = 'php -f ' . BP . '/bin/magento setup:upgrade -vvv -n --magento-init-params=' . $initParams['magento-init-params']; - return $this->shell->execute($enableModuleCommand); + + $upgradeCommand .= ' ' . implode(" ", $this->toCliArguments(array_keys($installParams))); + + return $this->shell->execute($upgradeCommand, array_values($installParams)); } /** @@ -147,6 +151,21 @@ public function cacheClean() $this->shell->execute($command); } + /** + * Uninstall module + * + * @param string $moduleName + */ + public function uninstallModule($moduleName) + { + $initParams = $this->parametersHolder->getInitParams(); + $command = 'php -f ' . BP . '/bin/magento module:uninstall ' . $moduleName . ' --remove-data ' . + ' -vvv --non-composer --magento-init-params=' . + $initParams['magento-init-params']; + + $this->shell->execute($command); + } + /** * Convert from raw params to CLI arguments, like --admin-username. * diff --git a/dev/tests/setup-integration/framework/Magento/TestFramework/Deploy/DescribeTable.php b/dev/tests/setup-integration/framework/Magento/TestFramework/Deploy/DescribeTable.php index b3077a49641f3..640a25c151c80 100644 --- a/dev/tests/setup-integration/framework/Magento/TestFramework/Deploy/DescribeTable.php +++ b/dev/tests/setup-integration/framework/Magento/TestFramework/Deploy/DescribeTable.php @@ -24,7 +24,7 @@ class DescribeTable * * @var array */ - private static $ignoredSystemTables = ['cache', 'cache_tag', 'flag', 'session', 'setup_module']; + private static $ignoredSystemTables = ['cache', 'cache_tag', 'flag', 'session', 'setup_module', 'patch_list']; /** * Constructor. diff --git a/dev/tests/setup-integration/framework/Magento/TestFramework/Deploy/TableData.php b/dev/tests/setup-integration/framework/Magento/TestFramework/Deploy/TableData.php new file mode 100644 index 0000000000000..bb1e743e7c071 --- /dev/null +++ b/dev/tests/setup-integration/framework/Magento/TestFramework/Deploy/TableData.php @@ -0,0 +1,40 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\TestFramework\Deploy; + +use Magento\Framework\App\ResourceConnection; + +/** + * The purpose of this class is to describe what data is in table + */ +class TableData +{ + /** + * @var ResourceConnection + */ + private $resourceConnection; + + /** + * TableData constructor. + * @param ResourceConnection $resourceConnection + */ + public function __construct(ResourceConnection $resourceConnection) + { + $this->resourceConnection = $resourceConnection; + } + + /** + * @param string $tableName + * @return array + */ + public function describeTableData($tableName) + { + $adapter = $this->resourceConnection->getConnection(); + return $adapter->fetchAll( + $adapter->select()->from($tableName) + ); + } +} diff --git a/dev/tests/setup-integration/framework/Magento/TestFramework/Deploy/TestModuleManager.php b/dev/tests/setup-integration/framework/Magento/TestFramework/Deploy/TestModuleManager.php index 482fd4abc7592..e33c84e140029 100644 --- a/dev/tests/setup-integration/framework/Magento/TestFramework/Deploy/TestModuleManager.php +++ b/dev/tests/setup-integration/framework/Magento/TestFramework/Deploy/TestModuleManager.php @@ -60,6 +60,27 @@ public function addModuleFiles($moduleName) } } + /** + * Copy revision folder to main module + * + * @param string $moduleName + * @param string $revisionName + * @param string $dir + * @return void + */ + public function addRevision($moduleName, $revisionName, $dir) + { + $modulePath = str_replace("Magento_", "", $moduleName); + $folder = MAGENTO_MODULES_PATH . $modulePath; + $desiredPath = $folder . '/' . $dir; + $revisionPath = $folder . '/revisions/' . $revisionName . '/'; + + if (!is_dir($desiredPath)) { + mkdir($desiredPath, 0777, true); + } + rename($revisionPath, $desiredPath); + } + /** * Update module version. * @@ -76,7 +97,15 @@ public function updateRevision($moduleName, $revisionName, $fileName, $fileDir) $revisionFile = MAGENTO_MODULES_PATH . $modulePath . "/revisions/" . $revisionName . DIRECTORY_SEPARATOR . $fileName; - if (file_exists($oldFile) && file_exists($revisionFile)) { + if (!file_exists($oldFile)) { + $dir = dirname($oldFile); + if (!is_dir($dir)) { + mkdir($dir, 0777, true); + } + touch($oldFile); + } + + if (file_exists($revisionFile)) { unlink($oldFile); copy($revisionFile, $oldFile); } else { diff --git a/dev/tests/setup-integration/framework/bootstrap.php b/dev/tests/setup-integration/framework/bootstrap.php index eb2ed02a8ce3d..01f60a3376ff8 100644 --- a/dev/tests/setup-integration/framework/bootstrap.php +++ b/dev/tests/setup-integration/framework/bootstrap.php @@ -79,6 +79,7 @@ $application->createInstallDir(); //We do not want to install anything $application->initialize([]); + $application->cleanup(); \Magento\TestFramework\Helper\Bootstrap::setInstance(new \Magento\TestFramework\Helper\Bootstrap($bootstrap)); diff --git a/dev/tests/setup-integration/testsuite/Magento/Setup/DataPatchInstallationTest.php b/dev/tests/setup-integration/testsuite/Magento/Setup/DataPatchInstallationTest.php new file mode 100644 index 0000000000000..d819e3e45b2c6 --- /dev/null +++ b/dev/tests/setup-integration/testsuite/Magento/Setup/DataPatchInstallationTest.php @@ -0,0 +1,238 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Setup; + +use Magento\Framework\Module\ModuleResource; +use Magento\Setup\Model\Patch\PatchHistory; +use Magento\TestFramework\Deploy\CliCommand; +use Magento\TestFramework\Deploy\TableData; +use Magento\TestFramework\Deploy\TestModuleManager; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\TestCase\SetupTestCase; +use Magento\TestSetupDeclarationModule3\Setup\Patch\Data\IncrementalSomeIntegerPatch; +use Magento\TestSetupDeclarationModule3\Setup\Patch\Data\ReferenceIncrementalSomeIntegerPatch; +use Magento\TestSetupDeclarationModule3\Setup\Patch\Data\ZFirstPatch; + +/** + * The purpose of this test is validating schema reader operations. + */ +class DataPatchInstallationTest extends SetupTestCase +{ + /** + * @var TestModuleManager + */ + private $moduleManager; + + /** + * @var CliCommand + */ + private $cliCommad; + + /** + * @var ModuleResource + */ + private $moduleResource; + + /** + * @var PatchHistory + */ + private $patchList; + + /** + * @var TableData + */ + private $tableData; + + public function setUp() + { + $objectManager = Bootstrap::getObjectManager(); + $this->moduleManager = $objectManager->get(TestModuleManager::class); + $this->cliCommad = $objectManager->get(CliCommand::class); + $this->moduleResource = $objectManager->get(ModuleResource::class); + $this->patchList = $objectManager->get(PatchHistory::class); + $this->tableData = $objectManager->get(TableData::class); + } + + /** + * @moduleName Magento_TestSetupDeclarationModule3 + */ + public function testDataPatchesInstallation() + { + $this->cliCommad->install( + ['Magento_TestSetupDeclarationModule3'] + ); + + self::assertEquals( + '0.0.1', + $this->moduleResource->getDataVersion('Magento_TestSetupDeclarationModule3') + ); + + $this->moduleManager->updateRevision( + 'Magento_TestSetupDeclarationModule3', + 'first_patch_revision', + 'module.xml', + 'etc' + ); + $this->movePatches(); + $this->moduleResource->flush(); + $this->cliCommad->upgrade(); + self::assertEquals( + '0.0.3', + $this->moduleResource->getDataVersion('Magento_TestSetupDeclarationModule3') + ); + self::assertTrue($this->patchList->isApplied(IncrementalSomeIntegerPatch::class)); + self::assertTrue($this->patchList->isApplied(ReferenceIncrementalSomeIntegerPatch::class)); + self::assertTrue($this->patchList->isApplied(ZFirstPatch::class)); + $tableData = $this->tableData->describeTableData('test_table'); + self::assertEquals($this->getTestTableData(), $tableData); + } + + /** + * @moduleName Magento_TestSetupDeclarationModule3 + * @expectedException \Magento\Framework\Exception\LocalizedException + */ + public function testCyclomaticDependency() + { + $this->moduleManager->updateRevision( + 'Magento_TestSetupDeclarationModule3', + 'cyclomatic_and_bic_revision', + 'module.xml', + 'etc' + ); + + $this->movePatches(); + /** + * Test whether installation give the same result as upgrade + */ + $this->cliCommad->install( + ['Magento_TestSetupDeclarationModule3'] + ); + $tableData = $this->tableData->describeTableData('test_table'); + self::assertEquals($this->getTestTableData(), $tableData); + $this->moduleManager->updateRevision( + 'Magento_TestSetupDeclarationModule3', + 'cyclomatic_and_bic_revision', + 'BicPatch.php', + 'Setup/Patch/Data' + ); + $this->moduleManager->updateRevision( + 'Magento_TestSetupDeclarationModule3', + 'cyclomatic_and_bic_revision', + 'RefBicPatch.php', + 'Setup/Patch/Data' + ); + + $this->cliCommad->upgrade(); + } + + /** + * Move patches + */ + private function movePatches() + { + //Install with patches + $this->moduleManager->addRevision( + 'Magento_TestSetupDeclarationModule3', + 'patches_revision', + 'Setup/Patch/Data' + ); + //Upgrade with UpgradeData + $this->moduleManager->updateRevision( + 'Magento_TestSetupDeclarationModule3', + 'first_patch_revision', + 'UpgradeData.php', + 'Setup' + ); + + //Upgrade with UpgradeData + $this->moduleManager->updateRevision( + 'Magento_TestSetupDeclarationModule3', + 'first_patch_revision', + 'module.xml', + 'etc' + ); + } + + /** + * @moduleName Magento_TestSetupDeclarationModule3 + */ + public function testPatchesRevert() + { + $this->movePatches(); + $this->cliCommad->install(['Magento_TestSetupDeclarationModule3']); + $this->cliCommad->uninstallModule('Magento_TestSetupDeclarationModule3'); + $testTableData = $this->tableData->describeTableData('test_table'); + $patchListTableData = $this->tableData->describeTableData('patch_list'); + self::assertEmpty($patchListTableData); + self::assertEmpty($testTableData); + $refTableData = $this->tableData->describeTableData('reference_table'); + self::assertEquals($this->getRefTableData(), $refTableData); + } + + /** + * @return array + */ + private function getTestTableData() + { + return [ + [ + 'smallint' => '1', + 'tinyint' => null, + 'varchar' => 'Ololo123', + 'varbinary' => '33288', + ], + [ + 'smallint' => '2', + 'tinyint' => null, + 'varchar' => 'Ololo123_ref', + 'varbinary' => '33288', + ], + [ + 'smallint' => '3', + 'tinyint' => null, + 'varchar' => 'changed__very_secret_string', + 'varbinary' => '0', + ], + ]; + } + + /** + * Retrieve reference table data + * + * @return array + */ + private function getRefTableData() + { + return [ + [ + 'tinyint_ref' => '2', + 'some_integer' => '2', + 'for_patch_testing' => null, + ], + [ + 'tinyint_ref' => '3', + 'some_integer' => '3', + 'for_patch_testing' => null, + ], + [ + 'tinyint_ref' => '4', + 'some_integer' => '5', + 'for_patch_testing' => null, + ], + [ + 'tinyint_ref' => '5', + 'some_integer' => '6', + 'for_patch_testing' => null, + ], + [ + 'tinyint_ref' => '6', + 'some_integer' => '12', + 'for_patch_testing' => null, + ], + ]; + } +} diff --git a/dev/tests/setup-integration/testsuite/Magento/Setup/SafeInstallerTest.php b/dev/tests/setup-integration/testsuite/Magento/Setup/SafeInstallerTest.php new file mode 100644 index 0000000000000..9b953bfdca358 --- /dev/null +++ b/dev/tests/setup-integration/testsuite/Magento/Setup/SafeInstallerTest.php @@ -0,0 +1,90 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Setup; + +use Magento\Framework\App\ResourceConnection; +use Magento\Setup\Model\Declaration\Schema\Diff\SchemaDiff; +use Magento\Setup\Model\Declaration\Schema\SchemaConfigInterface; +use Magento\Setup\Model\Declaration\Schema\Sharding; +use Magento\TestFramework\Deploy\CliCommand; +use Magento\TestFramework\Deploy\DescribeTable; +use Magento\TestFramework\Deploy\TestModuleManager; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\TestCase\SetupTestCase; + +/** + * The purpose of this test is verifying safe declarative installation works. + */ +class SafeInstallerTest extends SetupTestCase +{ + /** + * @var TestModuleManager + */ + private $moduleManager; + + /** + * @var CliCommand + */ + private $cliCommad; + + /** + * @var ResourceConnection + */ + private $resourceConnection; + + public function setUp() + { + $objectManager = Bootstrap::getObjectManager(); + $this->moduleManager = $objectManager->get(TestModuleManager::class); + $this->cliCommad = $objectManager->get(CliCommand::class); + $this->resourceConnection = $objectManager->get(ResourceConnection::class); + } + + /** + * @moduleName Magento_TestSetupDeclarationModule4 + * @dataProviderFromFile Magento/TestSetupDeclarationModule4/fixture/safe_data_provider.php + */ + public function testInstallation() + { + $testTableData = $this->getData(); + $row = reset($testTableData); + $this->cliCommad->install(['Magento_TestSetupDeclarationModule4']); + $adapter = $this->resourceConnection->getConnection(); + $testTableName = $this->resourceConnection->getTableName('test_table'); + $adapter->insertArray( + $this->resourceConnection->getTableName('test_table'), + array_keys($row), + $this->getData() + ); + //Move new db_schema.xml + $this->moduleManager->updateRevision( + 'Magento_TestSetupDeclarationModule4', + 'remove_title_column', + 'db_schema.xml', + 'etc' + ); + $this->cliCommad->upgrade( + [ + '--safe-mode' => true, + ] + ); + //Move new db_schema.xml with restored title field + $this->moduleManager->updateRevision( + 'Magento_TestSetupDeclarationModule4', + 'restore_title_column', + 'db_schema.xml', + 'etc' + ); + $this->cliCommad->upgrade( + [ + '--data-restore' => true, + ] + ); + $testTableSelect = $adapter->select()->from($testTableName); + self::assertEquals($testTableData, $adapter->fetchAll($testTableSelect)); + } +} diff --git a/dev/tests/setup-integration/testsuite/Magento/Setup/SchemaReaderTest.php b/dev/tests/setup-integration/testsuite/Magento/Setup/SchemaReaderTest.php index 86b92ce2720a9..903e217b4a270 100644 --- a/dev/tests/setup-integration/testsuite/Magento/Setup/SchemaReaderTest.php +++ b/dev/tests/setup-integration/testsuite/Magento/Setup/SchemaReaderTest.php @@ -40,6 +40,7 @@ public function setUp() public function testSuccessfullRead() { $schema = $this->reader->read('all'); + unset($schema['table']['patch_list']); self::assertEquals($this->getData(), $schema); } @@ -78,6 +79,7 @@ public function testForeignKeyInterpreter() { $this->updateRevisionTo('foreign_key_interpreter'); $schema = $this->reader->read('all'); + unset($schema['table']['patch_list']); self::assertEquals($this->getData(), $schema); } } diff --git a/dev/tests/setup-integration/testsuite/Magento/Setup/_files/expectedData.php b/dev/tests/setup-integration/testsuite/Magento/Setup/_files/expectedData.php deleted file mode 100644 index 214403fa3d2aa..0000000000000 --- a/dev/tests/setup-integration/testsuite/Magento/Setup/_files/expectedData.php +++ /dev/null @@ -1,46 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -return [ - 'setup_tests_entity_table' => [ - ['entity_id' => '1', - 'website_id' => '1', - 'email_field' => 'entity@example.com', - 'increment_id' => null, - 'created_at' => '2017-10-30 09:41:25', - 'updated_at' => '2017-10-30 09:45:05', - 'created_in' => 'Default Store View', - 'firstname' => 'John', - 'lastname' => 'Doe', - 'default_billing_address_id' => '1', - 'default_shipping_address_id' => '1', - 'dob' => '1973-12-15' - ], - ], - 'setup_tests_address_entity' => [ - [ - 'entity_id' => '1', - 'increment_id' => null, - 'parent_id' => '1', - 'created_at' => '2017-10-30 09:45:05', - 'updated_at' => '2017-10-30 09:45:05', - 'is_active' => '1', - 'city' => 'city', - 'company' => 'Magento', - 'country_id' => 'US', - 'fax' => null, - 'firstname' => 'John', - 'lastname' => 'Doe', - 'middlename' => null, - 'postcode' => '90210', - 'prefix' => null, - 'region' => 'Alabama', - 'region_id' => '1', - 'street' => 'street1', - 'suffix' => null, - 'telephone' => '12345678', - ] - ] -]; diff --git a/dev/tests/setup-integration/testsuite/Magento/Setup/_files/expectedDataAfterUpgrade.php b/dev/tests/setup-integration/testsuite/Magento/Setup/_files/expectedDataAfterUpgrade.php deleted file mode 100644 index 68540dc0939fc..0000000000000 --- a/dev/tests/setup-integration/testsuite/Magento/Setup/_files/expectedDataAfterUpgrade.php +++ /dev/null @@ -1,78 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -return [ - 'setup_tests_entity_table' => [ - [ - 'entity_id' => '1', - 'website_id' => '1', - 'email_field' => 'entity@example.com', - 'increment_id' => null, - 'created_at' => '2017-10-30 09:41:25', - 'updated_at' => '2017-10-30 09:45:05', - 'created_in' => 'Default Store View', - 'firstname' => 'John', - 'lastname' => 'Doe', - 'default_billing_address_id' => '1', - 'default_shipping_address_id' => '1', - 'group_id' => '0', - 'store_id' => '0', - ], - ], - 'setup_tests_address_entity' => [ - [ - 'entity_id' => '1', - 'increment_id' => null, - 'parent_id' => '1', - 'created_at' => '2017-10-30 09:45:05', - 'updated_at' => '2017-10-30 09:45:05', - 'is_active' => '1', - 'city' => 'city', - 'company' => 'Magento', - 'country_id' => 'US', - 'fax' => null, - 'firstname' => 'John', - 'lastname' => 'Doe', - 'middlename' => null, - 'postcode' => '90210', - 'prefix' => null, - 'region' => 'Alabama', - 'region_id' => '1', - 'street' => 'street1', - 'suffix' => null, - 'telephone' => '12345678', - ], - [ - 'entity_id' => '2', - 'increment_id' => null, - 'parent_id' => '1', - 'created_at' => '2017-10-30 13:34:19', - 'updated_at' => '2017-10-30 13:34:19', - 'is_active' => '1', - 'city' => 'Austin', - 'company' => 'X.Commerce', - 'country_id' => 'US', - 'fax' => null, - 'firstname' => 'Joan', - 'lastname' => 'Doe', - 'middlename' => null, - 'postcode' => '36351', - 'prefix' => null, - 'region' => 'Alabama', - 'region_id' => '1', - 'street' => 'New Brockton', - 'suffix' => null, - 'telephone' => '12345678', - - ], - ], - 'setup_tests_entity_passwords' => [ - [ - 'password_id' => '1', - 'entity_id' => '1', - 'password_hash' => '139e2ee2785cd9d9eb5714a02aca579bbcc05f9062996389d6e0e329bab9841b', - ] - ] -]; diff --git a/dev/tests/setup-integration/testsuite/Magento/Setup/_files/expectedIndexes.php b/dev/tests/setup-integration/testsuite/Magento/Setup/_files/expectedIndexes.php deleted file mode 100644 index 76f3479dc53d1..0000000000000 --- a/dev/tests/setup-integration/testsuite/Magento/Setup/_files/expectedIndexes.php +++ /dev/null @@ -1,267 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -return [ - 'setup_tests_table1' => [ - [ - 'COLUMNS_LIST' => [ - 'column_with_type_integer', - 'column_with_type_bigint', - ], - 'INDEX_TYPE' => 'primary', - 'INDEX_METHOD' => 'BTREE', - 'type' => 'primary', - 'fields' => [ - 'column_with_type_integer', - 'column_with_type_bigint', - ], - ], - [ - 'COLUMNS_LIST' => - ['column_with_type_integer',], - 'INDEX_TYPE' => 'index', - 'INDEX_METHOD' => 'BTREE', - 'type' => 'index', - 'fields' => - ['column_with_type_integer',] - ], - [ - 'COLUMNS_LIST' => - ['column_with_type_text',], - 'INDEX_TYPE' => 'fulltext', - 'INDEX_METHOD' => 'FULLTEXT', - 'type' => 'fulltext', - 'fields' => - ['column_with_type_text'], - ], - ], - 'setup_tests_table1_related' => [ - [ - 'COLUMNS_LIST' => [ - 'column_with_relation', - ], - 'INDEX_TYPE' => 'index', - 'INDEX_METHOD' => 'BTREE', - 'type' => 'index', - 'fields' => - ['column_with_relation'], - ], - ], - 'setup_tests_entity_table' => [ - [ - 'COLUMNS_LIST' => [ - 'entity_id', - ], - 'INDEX_TYPE' => 'primary', - 'INDEX_METHOD' => 'BTREE', - 'type' => 'primary', - 'fields' => - ['entity_id'], - ], - [ - 'COLUMNS_LIST' => [ - 'email_field', - 'website_id' - ], - 'INDEX_TYPE' => 'unique', - 'INDEX_METHOD' => 'BTREE', - 'type' => 'unique', - 'fields' => - [ - 'email_field', - 'website_id' - ], - ], - [ - 'COLUMNS_LIST' => [ - 'website_id' - ], - 'INDEX_TYPE' => 'index', - 'INDEX_METHOD' => 'BTREE', - 'type' => 'index', - 'fields' => - [ - 'website_id' - ], - ], - [ - 'COLUMNS_LIST' => [ - 'firstname' - ], - 'INDEX_TYPE' => 'index', - 'INDEX_METHOD' => 'BTREE', - 'type' => 'index', - 'fields' => - [ - 'firstname' - ], - ], - [ - 'COLUMNS_LIST' => [ - 'lastname' - ], - 'INDEX_TYPE' => 'index', - 'INDEX_METHOD' => 'BTREE', - 'type' => 'index', - 'fields' => - [ - 'lastname' - ], - ] - ], - 'setup_tests_address_entity' => [ - [ - 'COLUMNS_LIST' => [ - 'entity_id' - ], - 'INDEX_TYPE' => 'primary', - 'INDEX_METHOD' => 'BTREE', - 'type' => 'primary', - 'fields' => - [ - 'entity_id' - ], - ], - [ - 'COLUMNS_LIST' => [ - 'parent_id' - ], - 'INDEX_TYPE' => 'index', - 'INDEX_METHOD' => 'BTREE', - 'type' => 'index', - 'fields' => [ - 'parent_id' - ], - ] - ], - 'setup_tests_address_entity_datetime' => [ - [ - 'COLUMNS_LIST' => [ - 'value_id' - ], - 'INDEX_TYPE' => 'primary', - 'INDEX_METHOD' => 'BTREE', - 'type' => 'primary', - 'fields' => [ - 'value_id' - ], - ], - [ - 'COLUMNS_LIST' => [ - 'entity_id', - 'attribute_id' - ], - 'INDEX_TYPE' => 'unique', - 'INDEX_METHOD' => 'BTREE', - 'type' => 'unique', - 'fields' => [ - 'entity_id', - 'attribute_id' - ], - ], - [ - 'COLUMNS_LIST' => [ - 'attribute_id' - ], - 'INDEX_TYPE' => 'index', - 'INDEX_METHOD' => 'BTREE', - 'type' => 'index', - 'fields' => [ - 'attribute_id' - ], - ], - [ - 'COLUMNS_LIST' => [ - 'entity_id', - 'attribute_id', - 'value' - ], - 'INDEX_TYPE' => 'index', - 'INDEX_METHOD' => 'BTREE', - 'type' => 'index', - 'fields' => [ - 'entity_id', - 'attribute_id', - 'value' - ], - ], - ], - 'setup_tests_address_entity_decimal' => [ - [ - 'COLUMNS_LIST' => [ - 'value_id' - ], - 'INDEX_TYPE' => 'primary', - 'INDEX_METHOD' => 'BTREE', - 'type' => 'primary', - 'fields' => [ - 'value_id' - ], - ], - [ - 'COLUMNS_LIST' => [ - 'entity_id', - 'attribute_id' - ], - 'INDEX_TYPE' => 'unique', - 'INDEX_METHOD' => 'BTREE', - 'type' => 'unique', - 'fields' => [ - 'entity_id', - 'attribute_id' - ], - ], - [ - 'COLUMNS_LIST' => [ - 'attribute_id' - ], - 'INDEX_TYPE' => 'index', - 'INDEX_METHOD' => 'BTREE', - 'type' => 'index', - 'fields' => [ - 'attribute_id' - ], - ], - [ - 'COLUMNS_LIST' => [ - 'entity_id', - 'attribute_id', - 'value' - ], - 'INDEX_TYPE' => 'index', - 'INDEX_METHOD' => 'BTREE', - 'type' => 'index', - 'fields' => [ - 'entity_id', - 'attribute_id', - 'value' - ], - ], - ], - 'setup_tests_entity_passwords' => [ - [ - 'COLUMNS_LIST' => [ - 'password_id', - ], - 'INDEX_TYPE' => 'primary', - 'INDEX_METHOD' => 'BTREE', - 'type' => 'primary', - 'fields' => [ - 'password_id', - ], - ], - [ - 'COLUMNS_LIST' => [ - 'entity_id', - ], - 'INDEX_TYPE' => 'index', - 'INDEX_METHOD' => 'BTREE', - 'type' => 'index', - 'fields' => [ - 'entity_id', - ], - ], - ] -]; diff --git a/dev/tests/setup-integration/testsuite/Magento/Setup/_files/expectedRelations.php b/dev/tests/setup-integration/testsuite/Magento/Setup/_files/expectedRelations.php deleted file mode 100644 index d4777ec8581f4..0000000000000 --- a/dev/tests/setup-integration/testsuite/Magento/Setup/_files/expectedRelations.php +++ /dev/null @@ -1,38 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -return [ - 'setup_tests_table1' => [], - 'setup_tests_table1_related' => [ - 'COLUMN_NAME' => 'column_with_relation', - 'REF_COLUMN_NAME' => 'column_with_type_integer', - 'ON_DELETE' => 'CASCADE', - ], - 'setup_tests_entity_table' => [ - 'COLUMN_NAME' => 'website_id', - 'REF_COLUMN_NAME' => 'website_id', - 'ON_DELETE' => 'SET NULL', - ], - 'setup_tests_address_entity' => [ - 'COLUMN_NAME' => 'parent_id', - 'REF_COLUMN_NAME' => 'entity_id', - 'ON_DELETE' => 'CASCADE', - ], - 'setup_tests_address_entity_datetime' => [ - 'COLUMN_NAME' => 'entity_id', - 'REF_COLUMN_NAME' => 'entity_id', - 'ON_DELETE' => 'CASCADE', - ], - 'setup_tests_address_entity_decimal' => [ - 'COLUMN_NAME' => 'entity_id', - 'REF_COLUMN_NAME' => 'entity_id', - 'ON_DELETE' => 'CASCADE', - ], - 'setup_tests_entity_passwords' => [ - 'COLUMN_NAME' => 'entity_id', - 'REF_COLUMN_NAME' => 'entity_id', - 'ON_DELETE' => 'CASCADE', - ] -]; diff --git a/dev/tests/setup-integration/testsuite/Magento/Setup/_files/expectedSchema.php b/dev/tests/setup-integration/testsuite/Magento/Setup/_files/expectedSchema.php deleted file mode 100644 index c43291255287b..0000000000000 --- a/dev/tests/setup-integration/testsuite/Magento/Setup/_files/expectedSchema.php +++ /dev/null @@ -1,908 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -return [ - 'setup_tests_table1' => [ - 'column_with_type_boolean' => [ - 'SCHEMA_NAME' => null, - 'COLUMN_NAME' => 'column_with_type_boolean', - 'COLUMN_POSITION' => 1, - 'DATA_TYPE' => 'tinyint', - 'DEFAULT' => '0', - 'NULLABLE' => false, - 'LENGTH' => null, - 'SCALE' => null, - 'PRECISION' => null, - 'UNSIGNED' => null, - 'PRIMARY' => false, - 'PRIMARY_POSITION' => null, - 'IDENTITY' => false, - ], - 'column_with_type_smallint' => [ - 'SCHEMA_NAME' => null, - 'COLUMN_NAME' => 'column_with_type_smallint', - 'COLUMN_POSITION' => 2, - 'DATA_TYPE' => 'smallint', - 'DEFAULT' => '0', - 'NULLABLE' => false, - 'LENGTH' => null, - 'SCALE' => null, - 'PRECISION' => null, - 'UNSIGNED' => true, - 'PRIMARY' => false, - 'PRIMARY_POSITION' => null, - 'IDENTITY' => false, - ], - 'column_with_type_integer' => [ - 'SCHEMA_NAME' => null, - 'COLUMN_NAME' => 'column_with_type_integer', - 'COLUMN_POSITION' => 3, - 'DATA_TYPE' => 'int', - 'DEFAULT' => null, - 'NULLABLE' => false, - 'LENGTH' => null, - 'SCALE' => null, - 'PRECISION' => null, - 'UNSIGNED' => true, - 'PRIMARY' => true, - 'PRIMARY_POSITION' => 1, - 'IDENTITY' => true, - ], - 'column_with_type_bigint' => [ - 'SCHEMA_NAME' => null, - 'COLUMN_NAME' => 'column_with_type_bigint', - 'COLUMN_POSITION' => 4, - 'DATA_TYPE' => 'bigint', - 'DEFAULT' => null, - 'NULLABLE' => false, - 'LENGTH' => null, - 'SCALE' => null, - 'PRECISION' => null, - 'UNSIGNED' => true, - 'PRIMARY' => true, - 'PRIMARY_POSITION' => 2, - 'IDENTITY' => false, - ], - 'column_with_type_float' => [ - 'SCHEMA_NAME' => null, - 'COLUMN_NAME' => 'column_with_type_float', - 'COLUMN_POSITION' => 5, - 'DATA_TYPE' => 'float', - 'DEFAULT' => null, - 'NULLABLE' => true, - 'LENGTH' => null, - 'SCALE' => null, - 'PRECISION' => null, - 'UNSIGNED' => null, - 'PRIMARY' => false, - 'PRIMARY_POSITION' => null, - 'IDENTITY' => false, - ], - 'column_with_type_numeric' => [ - 'SCHEMA_NAME' => null, - 'COLUMN_NAME' => 'column_with_type_numeric', - 'COLUMN_POSITION' => 6, - 'DATA_TYPE' => 'decimal', - 'DEFAULT' => null, - 'NULLABLE' => true, - 'LENGTH' => null, - 'SCALE' => '4', - 'PRECISION' => '12', - 'UNSIGNED' => true, - 'PRIMARY' => false, - 'PRIMARY_POSITION' => null, - 'IDENTITY' => false, - ], - 'column_with_type_decimal' => [ - 'SCHEMA_NAME' => null, - 'COLUMN_NAME' => 'column_with_type_decimal', - 'COLUMN_POSITION' => 7, - 'DATA_TYPE' => 'decimal', - 'DEFAULT' => null, - 'NULLABLE' => true, - 'LENGTH' => null, - 'SCALE' => '4', - 'PRECISION' => '12', - 'UNSIGNED' => true, - 'PRIMARY' => false, - 'PRIMARY_POSITION' => null, - 'IDENTITY' => false, - ], - 'column_with_type_datetime' => [ - 'SCHEMA_NAME' => null, - 'COLUMN_NAME' => 'column_with_type_datetime', - 'COLUMN_POSITION' => 8, - 'DATA_TYPE' => 'datetime', - 'DEFAULT' => null, - 'NULLABLE' => true, - 'LENGTH' => null, - 'SCALE' => null, - 'PRECISION' => null, - 'UNSIGNED' => null, - 'PRIMARY' => false, - 'PRIMARY_POSITION' => null, - 'IDENTITY' => false, - ], - 'column_with_type_timestamp_update' => [ - 'SCHEMA_NAME' => null, - 'COLUMN_NAME' => 'column_with_type_timestamp_update', - 'COLUMN_POSITION' => 9, - 'DATA_TYPE' => 'timestamp', - 'DEFAULT' => '0000-00-00 00:00:00', - 'NULLABLE' => false, - 'LENGTH' => null, - 'SCALE' => null, - 'PRECISION' => null, - 'UNSIGNED' => null, - 'PRIMARY' => false, - 'PRIMARY_POSITION' => null, - 'IDENTITY' => false, - ], - 'column_with_type_date' => [ - 'SCHEMA_NAME' => null, - 'COLUMN_NAME' => 'column_with_type_date', - 'COLUMN_POSITION' => 10, - 'DATA_TYPE' => 'date', - 'DEFAULT' => null, - 'NULLABLE' => true, - 'LENGTH' => null, - 'SCALE' => null, - 'PRECISION' => null, - 'UNSIGNED' => null, - 'PRIMARY' => false, - 'PRIMARY_POSITION' => null, - 'IDENTITY' => false, - ], - 'column_with_type_text' => [ - 'SCHEMA_NAME' => null, - 'COLUMN_NAME' => 'column_with_type_text', - 'COLUMN_POSITION' => 11, - 'DATA_TYPE' => 'text', - 'DEFAULT' => null, - 'NULLABLE' => true, - 'LENGTH' => null, - 'SCALE' => null, - 'PRECISION' => null, - 'UNSIGNED' => null, - 'PRIMARY' => false, - 'PRIMARY_POSITION' => null, - 'IDENTITY' => false, - ], - 'column_with_type_blob' => [ - 'SCHEMA_NAME' => null, - 'COLUMN_NAME' => 'column_with_type_blob', - 'COLUMN_POSITION' => 12, - 'DATA_TYPE' => 'varbinary(32)', - 'DEFAULT' => null, - 'NULLABLE' => true, - 'LENGTH' => null, - 'SCALE' => null, - 'PRECISION' => null, - 'UNSIGNED' => null, - 'PRIMARY' => false, - 'PRIMARY_POSITION' => null, - 'IDENTITY' => false, - ], - 'column_with_type_verbinary' => [ - 'SCHEMA_NAME' => null, - 'COLUMN_NAME' => 'column_with_type_verbinary', - 'COLUMN_POSITION' => 13, - 'DATA_TYPE' => 'mediumblob', - 'DEFAULT' => null, - 'NULLABLE' => true, - 'LENGTH' => null, - 'SCALE' => null, - 'PRECISION' => null, - 'UNSIGNED' => null, - 'PRIMARY' => false, - 'PRIMARY_POSITION' => null, - 'IDENTITY' => false, - ], - ], - 'setup_tests_table1_related' => [ - 'column_with_type_timestamp_init_update' => [ - 'SCHEMA_NAME' => null, - 'COLUMN_NAME' => 'column_with_type_timestamp_init_update', - 'COLUMN_POSITION' => 1, - 'DATA_TYPE' => 'timestamp', - 'DEFAULT' => 'CURRENT_TIMESTAMP', - 'NULLABLE' => false, - 'LENGTH' => null, - 'SCALE' => null, - 'PRECISION' => null, - 'UNSIGNED' => null, - 'PRIMARY' => false, - 'PRIMARY_POSITION' => null, - 'IDENTITY' => false, - ], - 'column_with_type_timestamp_init' => [ - 'SCHEMA_NAME' => null, - 'COLUMN_NAME' => 'column_with_type_timestamp_init', - 'COLUMN_POSITION' => 2, - 'DATA_TYPE' => 'timestamp', - 'DEFAULT' => 'CURRENT_TIMESTAMP', - 'NULLABLE' => false, - 'LENGTH' => null, - 'SCALE' => null, - 'PRECISION' => null, - 'UNSIGNED' => null, - 'PRIMARY' => false, - 'PRIMARY_POSITION' => null, - 'IDENTITY' => false, - ], - 'column_with_relation' => [ - 'SCHEMA_NAME' => null, - 'COLUMN_NAME' => 'column_with_relation', - 'COLUMN_POSITION' => 3, - 'DATA_TYPE' => 'int', - 'DEFAULT' => null, - 'NULLABLE' => false, - 'LENGTH' => null, - 'SCALE' => null, - 'PRECISION' => null, - 'UNSIGNED' => true, - 'PRIMARY' => false, - 'PRIMARY_POSITION' => null, - 'IDENTITY' => false, - ], - ], - 'setup_tests_entity_table' => [ - 'entity_id' => [ - 'SCHEMA_NAME' => null, - 'COLUMN_NAME' => 'entity_id', - 'COLUMN_POSITION' => 1, - 'DATA_TYPE' => 'int', - 'DEFAULT' => null, - 'NULLABLE' => false, - 'LENGTH' => null, - 'SCALE' => null, - 'PRECISION' => null, - 'UNSIGNED' => true, - 'PRIMARY' => true, - 'PRIMARY_POSITION' => 1, - 'IDENTITY' => true, - ], - 'website_id' => [ - 'SCHEMA_NAME' => null, - 'COLUMN_NAME' => 'website_id', - 'COLUMN_POSITION' => 2, - 'DATA_TYPE' => 'smallint', - 'DEFAULT' => null, - 'NULLABLE' => true, - 'LENGTH' => null, - 'SCALE' => null, - 'PRECISION' => null, - 'UNSIGNED' => true, - 'PRIMARY' => false, - 'PRIMARY_POSITION' => null, - 'IDENTITY' => false, - ], - 'email_field' => [ - 'SCHEMA_NAME' => null, - 'COLUMN_NAME' => 'email_field', - 'COLUMN_POSITION' => 3, - 'DATA_TYPE' => 'varchar', - 'DEFAULT' => null, - 'NULLABLE' => true, - 'LENGTH' => '255', - 'SCALE' => null, - 'PRECISION' => null, - 'UNSIGNED' => null, - 'PRIMARY' => false, - 'PRIMARY_POSITION' => null, - 'IDENTITY' => false, - ], - 'increment_id' => [ - 'SCHEMA_NAME' => null, - 'COLUMN_NAME' => 'increment_id', - 'COLUMN_POSITION' => 4, - 'DATA_TYPE' => 'varchar', - 'DEFAULT' => null, - 'NULLABLE' => true, - 'LENGTH' => '50', - 'SCALE' => null, - 'PRECISION' => null, - 'UNSIGNED' => null, - 'PRIMARY' => false, - 'PRIMARY_POSITION' => null, - 'IDENTITY' => false, - ], - 'created_at' => [ - 'SCHEMA_NAME' => null, - 'COLUMN_NAME' => 'created_at', - 'COLUMN_POSITION' => 5, - 'DATA_TYPE' => 'timestamp', - 'DEFAULT' => 'CURRENT_TIMESTAMP', - 'NULLABLE' => false, - 'LENGTH' => null, - 'SCALE' => null, - 'PRECISION' => null, - 'UNSIGNED' => null, - 'PRIMARY' => false, - 'PRIMARY_POSITION' => null, - 'IDENTITY' => false, - ], - 'updated_at' => [ - 'SCHEMA_NAME' => null, - 'COLUMN_NAME' => 'updated_at', - 'COLUMN_POSITION' => 6, - 'DATA_TYPE' => 'timestamp', - 'DEFAULT' => 'CURRENT_TIMESTAMP', - 'NULLABLE' => false, - 'LENGTH' => null, - 'SCALE' => null, - 'PRECISION' => null, - 'UNSIGNED' => null, - 'PRIMARY' => false, - 'PRIMARY_POSITION' => null, - 'IDENTITY' => false, - ], - 'created_in' => [ - 'SCHEMA_NAME' => null, - 'COLUMN_NAME' => 'created_in', - 'COLUMN_POSITION' => 7, - 'DATA_TYPE' => 'varchar', - 'DEFAULT' => null, - 'NULLABLE' => true, - 'LENGTH' => '255', - 'SCALE' => null, - 'PRECISION' => null, - 'UNSIGNED' => null, - 'PRIMARY' => false, - 'PRIMARY_POSITION' => null, - 'IDENTITY' => false, - ], - 'firstname' => [ - 'SCHEMA_NAME' => null, - 'COLUMN_NAME' => 'firstname', - 'COLUMN_POSITION' => 8, - 'DATA_TYPE' => 'varchar', - 'DEFAULT' => null, - 'NULLABLE' => true, - 'LENGTH' => '255', - 'SCALE' => null, - 'PRECISION' => null, - 'UNSIGNED' => null, - 'PRIMARY' => false, - 'PRIMARY_POSITION' => null, - 'IDENTITY' => false, - ], - 'lastname' => [ - 'SCHEMA_NAME' => null, - 'COLUMN_NAME' => 'lastname', - 'COLUMN_POSITION' => 9, - 'DATA_TYPE' => 'varchar', - 'DEFAULT' => null, - 'NULLABLE' => true, - 'LENGTH' => '255', - 'SCALE' => null, - 'PRECISION' => null, - 'UNSIGNED' => null, - 'PRIMARY' => false, - 'PRIMARY_POSITION' => null, - 'IDENTITY' => false, - ], - 'dob' => [ - 'SCHEMA_NAME' => null, - 'COLUMN_NAME' => 'dob', - 'COLUMN_POSITION' => 10, - 'DATA_TYPE' => 'date', - 'DEFAULT' => null, - 'NULLABLE' => true, - 'LENGTH' => null, - 'SCALE' => null, - 'PRECISION' => null, - 'UNSIGNED' => null, - 'PRIMARY' => false, - 'PRIMARY_POSITION' => null, - 'IDENTITY' => false, - ], - 'default_billing_address_id' => [ - 'SCHEMA_NAME' => null, - 'COLUMN_NAME' => 'default_billing_address_id', - 'COLUMN_POSITION' => 11, - 'DATA_TYPE' => 'int', - 'DEFAULT' => null, - 'NULLABLE' => true, - 'LENGTH' => null, - 'SCALE' => null, - 'PRECISION' => null, - 'UNSIGNED' => true, - 'PRIMARY' => false, - 'PRIMARY_POSITION' => null, - 'IDENTITY' => false, - ], - 'default_shipping_address_id' => [ - 'SCHEMA_NAME' => null, - 'COLUMN_NAME' => 'default_shipping_address_id', - 'COLUMN_POSITION' => 12, - 'DATA_TYPE' => 'int', - 'DEFAULT' => null, - 'NULLABLE' => true, - 'LENGTH' => null, - 'SCALE' => null, - 'PRECISION' => null, - 'UNSIGNED' => true, - 'PRIMARY' => false, - 'PRIMARY_POSITION' => null, - 'IDENTITY' => false, - ], - ], - 'setup_tests_address_entity' => [ - 'entity_id' => [ - 'SCHEMA_NAME' => null, - 'COLUMN_NAME' => 'entity_id', - 'COLUMN_POSITION' => 1, - 'DATA_TYPE' => 'int', - 'DEFAULT' => null, - 'NULLABLE' => false, - 'LENGTH' => null, - 'SCALE' => null, - 'PRECISION' => null, - 'UNSIGNED' => true, - 'PRIMARY' => true, - 'PRIMARY_POSITION' => 1, - 'IDENTITY' => true, - ], - 'increment_id' => [ - 'SCHEMA_NAME' => null, - 'COLUMN_NAME' => 'increment_id', - 'COLUMN_POSITION' => 2, - 'DATA_TYPE' => 'varchar', - 'DEFAULT' => null, - 'NULLABLE' => true, - 'LENGTH' => '50', - 'SCALE' => null, - 'PRECISION' => null, - 'UNSIGNED' => null, - 'PRIMARY' => false, - 'PRIMARY_POSITION' => null, - 'IDENTITY' => false, - ], - 'parent_id' => [ - 'SCHEMA_NAME' => null, - 'COLUMN_NAME' => 'parent_id', - 'COLUMN_POSITION' => 3, - 'DATA_TYPE' => 'int', - 'DEFAULT' => null, - 'NULLABLE' => true, - 'LENGTH' => null, - 'SCALE' => null, - 'PRECISION' => null, - 'UNSIGNED' => true, - 'PRIMARY' => false, - 'PRIMARY_POSITION' => null, - 'IDENTITY' => false, - ], - 'created_at' => [ - 'SCHEMA_NAME' => null, - 'COLUMN_NAME' => 'created_at', - 'COLUMN_POSITION' => 4, - 'DATA_TYPE' => 'timestamp', - 'DEFAULT' => 'CURRENT_TIMESTAMP', - 'NULLABLE' => false, - 'LENGTH' => null, - 'SCALE' => null, - 'PRECISION' => null, - 'UNSIGNED' => null, - 'PRIMARY' => false, - 'PRIMARY_POSITION' => null, - 'IDENTITY' => false, - ], - 'updated_at' => [ - 'SCHEMA_NAME' => null, - 'COLUMN_NAME' => 'updated_at', - 'COLUMN_POSITION' => 5, - 'DATA_TYPE' => 'timestamp', - 'DEFAULT' => 'CURRENT_TIMESTAMP', - 'NULLABLE' => false, - 'LENGTH' => null, - 'SCALE' => null, - 'PRECISION' => null, - 'UNSIGNED' => null, - 'PRIMARY' => false, - 'PRIMARY_POSITION' => null, - 'IDENTITY' => false, - ], - 'is_active' => [ - 'SCHEMA_NAME' => null, - 'COLUMN_NAME' => 'is_active', - 'COLUMN_POSITION' => 6, - 'DATA_TYPE' => 'smallint', - 'DEFAULT' => '1', - 'NULLABLE' => false, - 'LENGTH' => null, - 'SCALE' => null, - 'PRECISION' => null, - 'UNSIGNED' => true, - 'PRIMARY' => false, - 'PRIMARY_POSITION' => null, - 'IDENTITY' => false, - ], - 'city' => [ - 'SCHEMA_NAME' => null, - 'COLUMN_NAME' => 'city', - 'COLUMN_POSITION' => 7, - 'DATA_TYPE' => 'varchar', - 'DEFAULT' => null, - 'NULLABLE' => false, - 'LENGTH' => '255', - 'SCALE' => null, - 'PRECISION' => null, - 'UNSIGNED' => null, - 'PRIMARY' => false, - 'PRIMARY_POSITION' => null, - 'IDENTITY' => false, - ], - 'company' => [ - 'SCHEMA_NAME' => null, - 'COLUMN_NAME' => 'company', - 'COLUMN_POSITION' => 8, - 'DATA_TYPE' => 'varchar', - 'DEFAULT' => null, - 'NULLABLE' => true, - 'LENGTH' => '255', - 'SCALE' => null, - 'PRECISION' => null, - 'UNSIGNED' => null, - 'PRIMARY' => false, - 'PRIMARY_POSITION' => null, - 'IDENTITY' => false, - ], - 'country_id' => [ - 'SCHEMA_NAME' => null, - 'COLUMN_NAME' => 'country_id', - 'COLUMN_POSITION' => 9, - 'DATA_TYPE' => 'varchar', - 'DEFAULT' => null, - 'NULLABLE' => false, - 'LENGTH' => '255', - 'SCALE' => null, - 'PRECISION' => null, - 'UNSIGNED' => null, - 'PRIMARY' => false, - 'PRIMARY_POSITION' => null, - 'IDENTITY' => false, - ], - 'fax' => [ - 'SCHEMA_NAME' => null, - 'COLUMN_NAME' => 'fax', - 'COLUMN_POSITION' => 10, - 'DATA_TYPE' => 'varchar', - 'DEFAULT' => null, - 'NULLABLE' => true, - 'LENGTH' => '255', - 'SCALE' => null, - 'PRECISION' => null, - 'UNSIGNED' => null, - 'PRIMARY' => false, - 'PRIMARY_POSITION' => null, - 'IDENTITY' => false, - ], - 'firstname' => [ - 'SCHEMA_NAME' => null, - 'COLUMN_NAME' => 'firstname', - 'COLUMN_POSITION' => 11, - 'DATA_TYPE' => 'varchar', - 'DEFAULT' => null, - 'NULLABLE' => false, - 'LENGTH' => '255', - 'SCALE' => null, - 'PRECISION' => null, - 'UNSIGNED' => null, - 'PRIMARY' => false, - 'PRIMARY_POSITION' => null, - 'IDENTITY' => false, - ], - 'lastname' => [ - 'SCHEMA_NAME' => null, - 'COLUMN_NAME' => 'lastname', - 'COLUMN_POSITION' => 12, - 'DATA_TYPE' => 'varchar', - 'DEFAULT' => null, - 'NULLABLE' => false, - 'LENGTH' => '255', - 'SCALE' => null, - 'PRECISION' => null, - 'UNSIGNED' => null, - 'PRIMARY' => false, - 'PRIMARY_POSITION' => null, - 'IDENTITY' => false, - ], - 'middlename' => [ - 'SCHEMA_NAME' => null, - 'COLUMN_NAME' => 'middlename', - 'COLUMN_POSITION' => 13, - 'DATA_TYPE' => 'varchar', - 'DEFAULT' => null, - 'NULLABLE' => true, - 'LENGTH' => '255', - 'SCALE' => null, - 'PRECISION' => null, - 'UNSIGNED' => null, - 'PRIMARY' => false, - 'PRIMARY_POSITION' => null, - 'IDENTITY' => false, - ], - 'postcode' => [ - 'SCHEMA_NAME' => null, - 'COLUMN_NAME' => 'postcode', - 'COLUMN_POSITION' => 14, - 'DATA_TYPE' => 'varchar', - 'DEFAULT' => null, - 'NULLABLE' => true, - 'LENGTH' => '255', - 'SCALE' => null, - 'PRECISION' => null, - 'UNSIGNED' => null, - 'PRIMARY' => false, - 'PRIMARY_POSITION' => null, - 'IDENTITY' => false, - ], - 'prefix' => [ - 'SCHEMA_NAME' => null, - 'COLUMN_NAME' => 'prefix', - 'COLUMN_POSITION' => 15, - 'DATA_TYPE' => 'varchar', - 'DEFAULT' => null, - 'NULLABLE' => true, - 'LENGTH' => '40', - 'SCALE' => null, - 'PRECISION' => null, - 'UNSIGNED' => null, - 'PRIMARY' => false, - 'PRIMARY_POSITION' => null, - 'IDENTITY' => false, - ], - 'region' => [ - 'SCHEMA_NAME' => null, - 'COLUMN_NAME' => 'region', - 'COLUMN_POSITION' => 16, - 'DATA_TYPE' => 'varchar', - 'DEFAULT' => null, - 'NULLABLE' => true, - 'LENGTH' => '255', - 'SCALE' => null, - 'PRECISION' => null, - 'UNSIGNED' => null, - 'PRIMARY' => false, - 'PRIMARY_POSITION' => null, - 'IDENTITY' => false, - ], - 'region_id' => [ - 'SCHEMA_NAME' => null, - 'COLUMN_NAME' => 'region_id', - 'COLUMN_POSITION' => 17, - 'DATA_TYPE' => 'int', - 'DEFAULT' => null, - 'NULLABLE' => true, - 'LENGTH' => null, - 'SCALE' => null, - 'PRECISION' => null, - 'UNSIGNED' => true, - 'PRIMARY' => false, - 'PRIMARY_POSITION' => null, - 'IDENTITY' => false, - ], - 'street' => [ - 'SCHEMA_NAME' => null, - 'COLUMN_NAME' => 'street', - 'COLUMN_POSITION' => 18, - 'DATA_TYPE' => 'text', - 'DEFAULT' => null, - 'NULLABLE' => false, - 'LENGTH' => null, - 'SCALE' => null, - 'PRECISION' => null, - 'UNSIGNED' => null, - 'PRIMARY' => false, - 'PRIMARY_POSITION' => null, - 'IDENTITY' => false, - ], - 'suffix' => [ - 'SCHEMA_NAME' => null, - 'COLUMN_NAME' => 'suffix', - 'COLUMN_POSITION' => 19, - 'DATA_TYPE' => 'varchar', - 'DEFAULT' => null, - 'NULLABLE' => true, - 'LENGTH' => '40', - 'SCALE' => null, - 'PRECISION' => null, - 'UNSIGNED' => null, - 'PRIMARY' => false, - 'PRIMARY_POSITION' => null, - 'IDENTITY' => false, - ], - 'telephone' => [ - 'SCHEMA_NAME' => null, - 'COLUMN_NAME' => 'telephone', - 'COLUMN_POSITION' => 20, - 'DATA_TYPE' => 'varchar', - 'DEFAULT' => null, - 'NULLABLE' => false, - 'LENGTH' => '255', - 'SCALE' => null, - 'PRECISION' => null, - 'UNSIGNED' => null, - 'PRIMARY' => false, - 'PRIMARY_POSITION' => null, - 'IDENTITY' => false, - ], - - ], - 'setup_tests_address_entity_datetime' => [ - 'value_id' => [ - 'SCHEMA_NAME' => null, - 'COLUMN_NAME' => 'value_id', - 'COLUMN_POSITION' => 1, - 'DATA_TYPE' => 'int', - 'DEFAULT' => null, - 'NULLABLE' => false, - 'LENGTH' => null, - 'SCALE' => null, - 'PRECISION' => null, - 'UNSIGNED' => null, - 'PRIMARY' => true, - 'PRIMARY_POSITION' => 1, - 'IDENTITY' => true, - ], - 'attribute_id' => [ - 'SCHEMA_NAME' => null, - 'COLUMN_NAME' => 'attribute_id', - 'COLUMN_POSITION' => 2, - 'DATA_TYPE' => 'smallint', - 'DEFAULT' => '0', - 'NULLABLE' => false, - 'LENGTH' => null, - 'SCALE' => null, - 'PRECISION' => null, - 'UNSIGNED' => true, - 'PRIMARY' => false, - 'PRIMARY_POSITION' => null, - 'IDENTITY' => false, - ], - 'entity_id' => [ - 'SCHEMA_NAME' => null, - 'COLUMN_NAME' => 'entity_id', - 'COLUMN_POSITION' => 3, - 'DATA_TYPE' => 'int', - 'DEFAULT' => '0', - 'NULLABLE' => false, - 'LENGTH' => null, - 'SCALE' => null, - 'PRECISION' => null, - 'UNSIGNED' => true, - 'PRIMARY' => false, - 'PRIMARY_POSITION' => null, - 'IDENTITY' => false, - ], - 'value' => [ - 'SCHEMA_NAME' => null, - 'COLUMN_NAME' => 'value', - 'COLUMN_POSITION' => 4, - 'DATA_TYPE' => 'datetime', - 'DEFAULT' => null, - 'NULLABLE' => true, - 'LENGTH' => null, - 'SCALE' => null, - 'PRECISION' => null, - 'UNSIGNED' => null, - 'PRIMARY' => false, - 'PRIMARY_POSITION' => null, - 'IDENTITY' => false, - ], - ], - 'setup_tests_address_entity_decimal' => [ - 'value_id' => [ - 'SCHEMA_NAME' => null, - 'COLUMN_NAME' => 'value_id', - 'COLUMN_POSITION' => 1, - 'DATA_TYPE' => 'int', - 'DEFAULT' => null, - 'NULLABLE' => false, - 'LENGTH' => null, - 'SCALE' => null, - 'PRECISION' => null, - 'UNSIGNED' => null, - 'PRIMARY' => true, - 'PRIMARY_POSITION' => 1, - 'IDENTITY' => true, - ], - 'attribute_id' => [ - 'SCHEMA_NAME' => null, - 'COLUMN_NAME' => 'attribute_id', - 'COLUMN_POSITION' => 2, - 'DATA_TYPE' => 'smallint', - 'DEFAULT' => '0', - 'NULLABLE' => false, - 'LENGTH' => null, - 'SCALE' => null, - 'PRECISION' => null, - 'UNSIGNED' => true, - 'PRIMARY' => false, - 'PRIMARY_POSITION' => null, - 'IDENTITY' => false, - ], - 'entity_id' => [ - 'SCHEMA_NAME' => null, - 'COLUMN_NAME' => 'entity_id', - 'COLUMN_POSITION' => 3, - 'DATA_TYPE' => 'int', - 'DEFAULT' => '0', - 'NULLABLE' => false, - 'LENGTH' => null, - 'SCALE' => null, - 'PRECISION' => null, - 'UNSIGNED' => true, - 'PRIMARY' => false, - 'PRIMARY_POSITION' => null, - 'IDENTITY' => false, - ], - 'value' => [ - 'SCHEMA_NAME' => null, - 'COLUMN_NAME' => 'value', - 'COLUMN_POSITION' => 4, - 'DATA_TYPE' => 'decimal', - 'DEFAULT' => '0.0000', - 'NULLABLE' => false, - 'LENGTH' => null, - 'SCALE' => '4', - 'PRECISION' => '12', - 'UNSIGNED' => null, - 'PRIMARY' => false, - 'PRIMARY_POSITION' => null, - 'IDENTITY' => false, - ], - - ], - 'setup_tests_entity_passwords' => [ - 'password_id' => [ - 'SCHEMA_NAME' => null, - 'COLUMN_NAME' => 'password_id', - 'COLUMN_POSITION' => 1, - 'DATA_TYPE' => 'int', - 'DEFAULT' => null, - 'NULLABLE' => false, - 'LENGTH' => null, - 'SCALE' => null, - 'PRECISION' => null, - 'UNSIGNED' => true, - 'PRIMARY' => true, - 'PRIMARY_POSITION' => 1, - 'IDENTITY' => true, - ], - 'entity_id' => [ - 'SCHEMA_NAME' => null, - 'COLUMN_NAME' => 'entity_id', - 'COLUMN_POSITION' => 2, - 'DATA_TYPE' => 'int', - 'DEFAULT' => '0', - 'NULLABLE' => false, - 'LENGTH' => null, - 'SCALE' => null, - 'PRECISION' => null, - 'UNSIGNED' => true, - 'PRIMARY' => false, - 'PRIMARY_POSITION' => null, - 'IDENTITY' => false, - ], - 'password_hash' => [ - 'SCHEMA_NAME' => null, - 'COLUMN_NAME' => 'password_hash', - 'COLUMN_POSITION' => 3, - 'DATA_TYPE' => 'varchar', - 'DEFAULT' => null, - 'NULLABLE' => true, - 'LENGTH' => '100', - 'SCALE' => null, - 'PRECISION' => null, - 'UNSIGNED' => null, - 'PRIMARY' => false, - 'PRIMARY_POSITION' => null, - 'IDENTITY' => false, - ], - ] -]; diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/InstallUpgradeTest.php b/dev/tests/static/testsuite/Magento/Test/Legacy/InstallUpgradeTest.php index 9e9a3418561d1..5c920fb7ad225 100644 --- a/dev/tests/static/testsuite/Magento/Test/Legacy/InstallUpgradeTest.php +++ b/dev/tests/static/testsuite/Magento/Test/Legacy/InstallUpgradeTest.php @@ -42,6 +42,12 @@ function ($file) { 'InstallSchema objects are obsolete. ' . 'Please use declarative schema approach in module\'s etc/db_schema.xml file' ); + $this->assertStringStartsNotWith( + 'InstallData', + basename($file), + 'InstallData objects are obsolete. ' + . 'Please use data patches approach in module\'s Setup/Patch/Data dir' + ); $this->assertStringStartsNotWith( 'data-install-', basename($file), @@ -59,20 +65,27 @@ function ($file) { 'UpgradeSchema scripts are obsolete. ' . 'Please use declarative schema approach in module\'s etc/db_schema.xml file' ); + $this->assertStringStartsNotWith( + 'UpgradeData', + basename($file), + 'UpgradeSchema scripts are obsolete. ' + . 'Please use data patches approach in module\'s Setup/Patch/Data dir' + ); $this->assertStringStartsNotWith( 'data-upgrade-', basename($file), - 'Upgrade scripts are obsolete. Please create class UpgradeData in module\'s Setup folder' + 'Upgrade scripts are obsolete. ' + . 'Please use data patches approach in module\'s Setup/Patch/Data dir' ); $this->assertStringStartsNotWith( 'recurring', basename($file), 'Recurring scripts are obsolete. Please create class Recurring in module\'s Setup folder' ); - if (preg_match('/.*\/(sql|data)/i', dirname($file))) { + if (preg_match('/.*\/(sql\/|data\/)/', dirname($file))) { $this->fail( "Invalid directory:\n" - . "- Create an UpgradeData class within module's Setup folder for data upgrades.\n" + . "- Create an data patch within module's Setup/Patch/Data folder for data upgrades.\n" . "- Use declarative schema approach in module's etc/db_schema.xml file for schema changes." ); } diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/copyright/blacklist.php b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/copyright/blacklist.php index f80151a41573d..d22c3359f267e 100644 --- a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/copyright/blacklist.php +++ b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/copyright/blacklist.php @@ -4,7 +4,7 @@ * See COPYING.txt for license details. */ return [ - '/\.(jpe?g|png|gif|ttf|swf|eot|woff|pdf|mp3|pdf|jar|jbf)$/', + '/\.(jpe?g|png|gif|ttf|swf|eot|woff|pdf|mp3|pdf|jar|jbf|php\.dist)$/', '/pub\/opt\/magento\/var/', '/COPYING\.txt/' ]; diff --git a/dev/tools/Magento/Tools/StaticReview/PhpCsFixerReview.php b/dev/tools/Magento/Tools/StaticReview/PhpCsFixerReview.php deleted file mode 100644 index 113b139555dfb..0000000000000 --- a/dev/tools/Magento/Tools/StaticReview/PhpCsFixerReview.php +++ /dev/null @@ -1,66 +0,0 @@ -<?php -/* - * This file is part of StaticReview - * - * Copyright (c) 2014 Samuel Parkinson <@samparkinson_> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - * - * @see http://github.com/sjparkinson/static-review/blob/master/LICENSE.md - */ -namespace Magento\Tools\StaticReview; - -use StaticReview\File\FileInterface; -use StaticReview\Reporter\ReporterInterface; -use StaticReview\Review\AbstractReview; - -class PhpCsFixerReview extends AbstractReview -{ - /** - * @var array - */ - protected $options; - - /** - * @param array $options - */ - public function __construct($options = []) - { - $this->options = $options; - } - - /** - * Obtained from .php_cs configuration file. - * - * @param FileInterface $file - * @return bool - */ - public function canReview(FileInterface $file) - { - return in_array($file->getExtension(), ['php', 'phtml', 'xml', 'yml']); - } - - /** - * Checks and fixes PHP files using PHP Coding Standards Fixer. - * - * @param ReporterInterface $reporter - * @param FileInterface $file - * @return void - * @SuppressWarnings(PHPMD.UnusedFormalParameter) - */ - public function review(ReporterInterface $reporter, FileInterface $file) - { - $cmd = 'vendor/bin/php-cs-fixer -vvv '; - foreach ($this->options as $key => $value) { - $cmd .= ' --' . $key . '=' . escapeshellarg($value); - } - $cmd .= ' fix ' . escapeshellarg($file->getRelativePath()); - - $process = $this->getProcess($cmd); - $process->run(); - - $process = $this->getProcess('git add ' . escapeshellarg($file->getRelativePath())); - $process->run(); - } -} diff --git a/dev/tools/Magento/Tools/StaticReview/pre-commit b/dev/tools/Magento/Tools/StaticReview/pre-commit deleted file mode 100755 index 0bbb62797f434..0000000000000 --- a/dev/tools/Magento/Tools/StaticReview/pre-commit +++ /dev/null @@ -1,71 +0,0 @@ -#!/usr/bin/env php -<?php -/* - * This file is part of StaticReview - * - * Copyright (c) 2014 Samuel Parkinson <@samparkinson_> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - * - * @see https://github.com/sjparkinson/static-review/blob/master/LICENSE - */ -$included = include __DIR__ . '/../../../../../vendor/autoload.php'; -if (!$included) { - echo 'You must set up the project dependencies, run the following commands:' . PHP_EOL - . 'curl -sS https://getcomposer.org/installer | php' . PHP_EOL - . 'php composer.phar install' . PHP_EOL; - - exit(1); -} - -// Installation: -// vendor/bin/static-review.php hook:install dev/tools/Magento/Tools/StaticReview/pre-commit .git/hooks/pre-commit - -// Reference the required classes and the reviews you want to use. -use League\CLImate\CLImate; -use StaticReview\Reporter\Reporter; -use StaticReview\Review\Composer\ComposerLintReview; -use StaticReview\Review\General\LineEndingsReview; -use StaticReview\Review\General\NoCommitTagReview; -use StaticReview\Review\PHP\PhpLeadingLineReview; -use StaticReview\Review\PHP\PhpLintReview; -use Magento\Tools\StaticReview\PhpCsFixerReview; -use StaticReview\StaticReview; -use StaticReview\VersionControl\GitVersionControl; - -$reporter = new Reporter(); -$climate = new CLImate(); -$git = new GitVersionControl(); - -// Apply review which modifies staged files first -$review = new StaticReview($reporter); -$phpCsFixer = new PhpCsFixerReview(); -$review->addReview($phpCsFixer); -$review->review($git->getStagedFiles()); - -// Apply read-only review then -$review = new StaticReview($reporter); -$review->addReview(new LineEndingsReview()) - ->addReview(new PhpLeadingLineReview()) - ->addReview(new NoCommitTagReview()) - ->addReview(new PhpLintReview()) - ->addReview(new ComposerLintReview()); -$review->review($git->getStagedFiles()); - -// Check if any matching issues were found. -if ($reporter->hasIssues()) { - $climate->out('')->out(''); - - foreach ($reporter->getIssues() as $issue) { - $climate->red($issue); - } - - $climate->out('')->red('✘ Please fix the errors above.'); - - exit(1); -} else { - $climate->out('')->green('✔ Looking good.')->white('Have you tested everything?'); - - exit(0); -} diff --git a/lib/internal/Magento/Framework/Api/AbstractServiceCollection.php b/lib/internal/Magento/Framework/Api/AbstractServiceCollection.php index c5d72b59e12ac..7771c77b51697 100644 --- a/lib/internal/Magento/Framework/Api/AbstractServiceCollection.php +++ b/lib/internal/Magento/Framework/Api/AbstractServiceCollection.php @@ -111,12 +111,14 @@ public function addFieldToFilter($field, $condition) { if (is_array($field) && is_array($condition) && count($field) != count($condition)) { throw new LocalizedException( - new \Magento\Framework\Phrase('When passing in a field array there must be a matching condition array.') + new \Magento\Framework\Phrase( + 'The field array failed to pass. The array must have a matching condition array.' + ) ); } elseif (is_array($field) && !count($field) > 0) { throw new LocalizedException( new \Magento\Framework\Phrase( - 'When passing an array of fields there must be at least one field in the array.' + 'The array of fields failed to pass. The array must include at one field.' ) ); } diff --git a/lib/internal/Magento/Framework/Api/ExtensionAttributesFactory.php b/lib/internal/Magento/Framework/Api/ExtensionAttributesFactory.php index dab0650fc7f6e..e1a4431783da6 100644 --- a/lib/internal/Magento/Framework/Api/ExtensionAttributesFactory.php +++ b/lib/internal/Magento/Framework/Api/ExtensionAttributesFactory.php @@ -49,7 +49,7 @@ public function create($extensibleClassName, $data = []) $interfaceReflection = new \ReflectionClass($this->getExtensibleInterfaceName($extensibleClassName)); $methodReflection = $interfaceReflection->getMethod('getExtensionAttributes'); - if ($methodReflection->getDeclaringClass() == self::EXTENSIBLE_INTERFACE_NAME) { + if ($methodReflection->getDeclaringClass()->getName() === self::EXTENSIBLE_INTERFACE_NAME) { throw new \LogicException( "Method 'getExtensionAttributes' must be overridden in the interfaces " . "which extend '" . self::EXTENSIBLE_INTERFACE_NAME . "'. " diff --git a/lib/internal/Magento/Framework/Api/ImageProcessor.php b/lib/internal/Magento/Framework/Api/ImageProcessor.php index e2c5f8c4083b9..beadb51bc7796 100644 --- a/lib/internal/Magento/Framework/Api/ImageProcessor.php +++ b/lib/internal/Magento/Framework/Api/ImageProcessor.php @@ -139,7 +139,7 @@ public function save( public function processImageContent($entityType, $imageContent) { if (!$this->contentValidator->isValid($imageContent)) { - throw new InputException(new Phrase('The image content is not valid.')); + throw new InputException(new Phrase('The image content is invalid. Verify the content and try again.')); } $fileContent = @base64_decode($imageContent->getBase64EncodedData(), true); diff --git a/lib/internal/Magento/Framework/Api/Test/Unit/Api/ImageProcessorTest.php b/lib/internal/Magento/Framework/Api/Test/Unit/Api/ImageProcessorTest.php index 84dee31b73015..183313cd8d05d 100644 --- a/lib/internal/Magento/Framework/Api/Test/Unit/Api/ImageProcessorTest.php +++ b/lib/internal/Magento/Framework/Api/Test/Unit/Api/ImageProcessorTest.php @@ -119,7 +119,7 @@ public function testSaveWithNoImageData() /** * @expectedException \Magento\Framework\Exception\InputException - * @expectedExceptionMessage The image content is not valid. + * @expectedExceptionMessage The image content is invalid. Verify the content and try again. */ public function testSaveInputException() { diff --git a/lib/internal/Magento/Framework/App/ActionFactory.php b/lib/internal/Magento/Framework/App/ActionFactory.php index f929c38b75219..94f5ef36eb9c9 100644 --- a/lib/internal/Magento/Framework/App/ActionFactory.php +++ b/lib/internal/Magento/Framework/App/ActionFactory.php @@ -5,6 +5,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\App; /** @@ -35,7 +36,9 @@ public function __construct(\Magento\Framework\ObjectManagerInterface $objectMan public function create($actionName) { if (!is_subclass_of($actionName, \Magento\Framework\App\ActionInterface::class)) { - throw new \InvalidArgumentException('Invalid action name provided'); + throw new \InvalidArgumentException( + 'The action name provided is invalid. Verify the action name and try again.' + ); } return $this->_objectManager->create($actionName); } diff --git a/lib/internal/Magento/Framework/App/Config/Initial/Reader.php b/lib/internal/Magento/Framework/App/Config/Initial/Reader.php index c8caefc42c071..161d8a8da702d 100644 --- a/lib/internal/Magento/Framework/App/Config/Initial/Reader.php +++ b/lib/internal/Magento/Framework/App/Config/Initial/Reader.php @@ -105,7 +105,10 @@ public function read() } } catch (\Magento\Framework\Config\Dom\ValidationException $e) { throw new \Magento\Framework\Exception\LocalizedException( - new \Magento\Framework\Phrase("Invalid XML in file %1:\n%2", [$file, $e->getMessage()]) + new \Magento\Framework\Phrase( + 'The XML in file "%1" is invalid:' . "\n%2\nVerify the XML and try again.", + [$file, $e->getMessage()] + ) ); } } diff --git a/lib/internal/Magento/Framework/App/Config/Scope/Validator.php b/lib/internal/Magento/Framework/App/Config/Scope/Validator.php index 694ba70e1e1b0..9c0f60286e093 100644 --- a/lib/internal/Magento/Framework/App/Config/Scope/Validator.php +++ b/lib/internal/Magento/Framework/App/Config/Scope/Validator.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\App\Config\Scope; use InvalidArgumentException; @@ -49,7 +50,7 @@ public function isValid($scope, $scopeCode = null) } if (empty($scope)) { - throw new LocalizedException(new Phrase('Enter a scope before proceeding.')); + throw new LocalizedException(new Phrase('A scope is missing. Enter a scope and try again.')); } $this->validateScopeCode($scopeCode); @@ -58,10 +59,12 @@ public function isValid($scope, $scopeCode = null) $scopeResolver = $this->scopeResolverPool->get($scope); $scopeResolver->getScope($scopeCode)->getId(); } catch (InvalidArgumentException $e) { - throw new LocalizedException(new Phrase('The "%1" value doesn\'t exist. Enter another value.', [$scope])); + throw new LocalizedException( + new Phrase('The "%1" value doesn\'t exist. Enter another value and try again.', [$scope]) + ); } catch (NoSuchEntityException $e) { throw new LocalizedException( - new Phrase('The "%1" value doesn\'t exist. Enter another value.', [$scopeCode]) + new Phrase('The "%1" value doesn\'t exist. Enter another value and try again.', [$scopeCode]) ); } @@ -79,7 +82,7 @@ public function isValid($scope, $scopeCode = null) private function validateScopeCode($scopeCode) { if (empty($scopeCode)) { - throw new LocalizedException(new Phrase('Enter a scope code before proceeding.')); + throw new LocalizedException(new Phrase('A scope code is missing. Enter a code and try again.')); } if (!preg_match('/^[a-z]+[a-z0-9_]*$/', $scopeCode)) { diff --git a/lib/internal/Magento/Framework/App/DeploymentConfig/Reader.php b/lib/internal/Magento/Framework/App/DeploymentConfig/Reader.php index 06a66a2b3f873..ff7077213c5c3 100644 --- a/lib/internal/Magento/Framework/App/DeploymentConfig/Reader.php +++ b/lib/internal/Magento/Framework/App/DeploymentConfig/Reader.php @@ -9,7 +9,9 @@ use Magento\Framework\App\Filesystem\DirectoryList; use Magento\Framework\Config\File\ConfigFilePool; use Magento\Framework\Exception\FileSystemException; +use Magento\Framework\Exception\RuntimeException; use Magento\Framework\Filesystem\DriverPool; +use Magento\Framework\Phrase; /** * Deployment configuration reader. @@ -87,6 +89,7 @@ public function getFiles() * @param string $fileKey The file key (deprecated) * @return array * @throws FileSystemException If file can not be read + * @throws RuntimeException If file is invalid * @throws \Exception If file key is not correct * @see FileReader */ @@ -99,6 +102,9 @@ public function load($fileKey = null) $filePath = $path . '/' . $this->configFilePool->getPath($fileKey); if ($fileDriver->isExists($filePath)) { $result = include $filePath; + if (!is_array($result)) { + throw new RuntimeException(new Phrase("Invalid configuration file: '%1'", [$filePath])); + } } } else { $configFiles = $this->configFilePool->getPaths(); @@ -108,11 +114,14 @@ public function load($fileKey = null) $configFile = $path . '/' . $this->configFilePool->getPath($fileKey); if ($fileDriver->isExists($configFile)) { $fileData = include $configFile; + if (!is_array($fileData)) { + throw new RuntimeException(new Phrase("Invalid configuration file: '%1'", [$configFile])); + } } else { continue; } $allFilesData[$configFile] = $fileData; - if (is_array($fileData) && count($fileData) > 0) { + if ($fileData) { $result = array_replace_recursive($result, $fileData); } } diff --git a/lib/internal/Magento/Framework/App/DeploymentConfig/Writer.php b/lib/internal/Magento/Framework/App/DeploymentConfig/Writer.php index 3ff7a0c9539be..1722ca4fe2577 100644 --- a/lib/internal/Magento/Framework/App/DeploymentConfig/Writer.php +++ b/lib/internal/Magento/Framework/App/DeploymentConfig/Writer.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\App\DeploymentConfig; use Magento\Framework\App\DeploymentConfig; @@ -14,6 +15,7 @@ /** * Deployment configuration writer to files: env.php, config.php. + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class Writer { @@ -144,7 +146,7 @@ public function saveConfig(array $data, $override = false, $pool = null, array $ $this->filesystem->getDirectoryWrite(DirectoryList::CONFIG)->writeFile($writeFilePath, $contents); } catch (FileSystemException $e) { throw new FileSystemException( - new Phrase('Deployment config file %1 is not writable.', [$paths[$fileKey]]) + new Phrase('The "%1" deployment config file isn\'t writable.', [$paths[$fileKey]]) ); } if (function_exists('opcache_invalidate')) { diff --git a/lib/internal/Magento/Framework/App/Language/Dictionary.php b/lib/internal/Magento/Framework/App/Language/Dictionary.php index 02ee6ca2c9579..294490a665cbe 100644 --- a/lib/internal/Magento/Framework/App/Language/Dictionary.php +++ b/lib/internal/Magento/Framework/App/Language/Dictionary.php @@ -85,7 +85,7 @@ public function getDictionary($languageCode) } catch (\Magento\Framework\Config\Dom\ValidationException $e) { throw new \Magento\Framework\Exception\LocalizedException( new \Magento\Framework\Phrase( - "Invalid XML in file %1:\n%2", + 'The XML in file "%1" is invalid:' . "\n%2\nVerify the XML and try again.", [$path . '/language.xml', $e->getMessage()] ), $e diff --git a/lib/internal/Magento/Framework/App/ResourceConnection.php b/lib/internal/Magento/Framework/App/ResourceConnection.php index 55ad76e9113a5..5b9ae925bff27 100644 --- a/lib/internal/Magento/Framework/App/ResourceConnection.php +++ b/lib/internal/Magento/Framework/App/ResourceConnection.php @@ -300,13 +300,14 @@ public function getSchemaName($resourceName) * * @return string */ - private function getTablePrefix() + public function getTablePrefix() { - if (null === $this->tablePrefix) { - $this->tablePrefix = (string)$this->deploymentConfig->get( - ConfigOptionsListConstants::CONFIG_PATH_DB_PREFIX - ); + if ($this->tablePrefix !== null) { + return $this->tablePrefix; } - return $this->tablePrefix; + + return (string) $this->deploymentConfig->get( + ConfigOptionsListConstants::CONFIG_PATH_DB_PREFIX + ); } } diff --git a/lib/internal/Magento/Framework/App/Response/HeaderManager.php b/lib/internal/Magento/Framework/App/Response/HeaderManager.php index 1c2721b862ad1..8b127d5f111a7 100644 --- a/lib/internal/Magento/Framework/App/Response/HeaderManager.php +++ b/lib/internal/Magento/Framework/App/Response/HeaderManager.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\App\Response; use Magento\Framework\App\Response\HeaderProvider\HeaderProviderInterface; @@ -24,7 +25,7 @@ public function __construct($headerProviderList) { foreach ($headerProviderList as $header) { if (!($header instanceof HeaderProviderInterface)) { - throw new LocalizedException(new Phrase('Invalid header provider')); + throw new LocalizedException(new Phrase('The header provider is invalid. Verify and try again.')); } } $this->headerProviders = $headerProviderList; diff --git a/lib/internal/Magento/Framework/App/Scope/Validator.php b/lib/internal/Magento/Framework/App/Scope/Validator.php index 242277ed98e8f..62839e634983e 100644 --- a/lib/internal/Magento/Framework/App/Scope/Validator.php +++ b/lib/internal/Magento/Framework/App/Scope/Validator.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\App\Scope; use InvalidArgumentException; @@ -47,7 +48,7 @@ public function isValid($scope, $scopeCode = null) } if (empty($scope)) { - throw new LocalizedException(new Phrase('Enter a scope before proceeding.')); + throw new LocalizedException(new Phrase('A scope is missing. Enter a scope and try again.')); } $this->validateScopeCode($scopeCode); @@ -56,10 +57,12 @@ public function isValid($scope, $scopeCode = null) $scopeResolver = $this->scopeResolverPool->get($scope); $scopeResolver->getScope($scopeCode)->getId(); } catch (InvalidArgumentException $e) { - throw new LocalizedException(new Phrase('The "%1" value doesn\'t exist. Enter another value.', [$scope])); + throw new LocalizedException( + new Phrase('The "%1" value doesn\'t exist. Enter another value and try again.', [$scope]) + ); } catch (NoSuchEntityException $e) { throw new LocalizedException( - new Phrase('The "%1" value doesn\'t exist. Enter another value.', [$scopeCode]) + new Phrase('The "%1" value doesn\'t exist. Enter another value and try again.', [$scopeCode]) ); } @@ -77,7 +80,7 @@ public function isValid($scope, $scopeCode = null) private function validateScopeCode($scopeCode) { if (empty($scopeCode)) { - throw new LocalizedException(new Phrase('Enter a scope code before proceeding.')); + throw new LocalizedException(new Phrase('A scope code is missing. Enter a code and try again.')); } if (!preg_match('/^[a-z]+[a-z0-9_]*$/', $scopeCode)) { diff --git a/lib/internal/Magento/Framework/App/Test/Unit/Config/Initial/ReaderTest.php b/lib/internal/Magento/Framework/App/Test/Unit/Config/Initial/ReaderTest.php index 56589b20dcd0c..5a504cf6367af 100644 --- a/lib/internal/Magento/Framework/App/Test/Unit/Config/Initial/ReaderTest.php +++ b/lib/internal/Magento/Framework/App/Test/Unit/Config/Initial/ReaderTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\App\Test\Unit\Config\Initial; use Magento\Framework\Filesystem; @@ -132,7 +133,7 @@ function ($arguments) use ($validationStateMock) { /** * @covers \Magento\Framework\App\Config\Initial\Reader::read * @expectedException \Magento\Framework\Exception\LocalizedException - * @expectedExceptionMessageRegExp /Invalid XML in file (.*?)/ + * @expectedExceptionMessage Verify the XML and try again. */ public function testReadInvalidConfig() { diff --git a/lib/internal/Magento/Framework/App/Test/Unit/Config/Scope/ValidatorTest.php b/lib/internal/Magento/Framework/App/Test/Unit/Config/Scope/ValidatorTest.php index f0863a81b7999..1e72017dcf7a8 100644 --- a/lib/internal/Magento/Framework/App/Test/Unit/Config/Scope/ValidatorTest.php +++ b/lib/internal/Magento/Framework/App/Test/Unit/Config/Scope/ValidatorTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\App\Test\Unit\Config\Scope; use Magento\Framework\App\Config\ScopeConfigInterface; @@ -81,7 +82,7 @@ public function testNotEmptyScopeCodeForDefaultScope() /** * @expectedException \Magento\Framework\Exception\LocalizedException - * @expectedExceptionMessage Enter a scope before proceeding. + * @expectedExceptionMessage A scope is missing. Enter a scope and try again. */ public function testEmptyScope() { @@ -90,7 +91,7 @@ public function testEmptyScope() /** * @expectedException \Magento\Framework\Exception\LocalizedException - * @expectedExceptionMessage Enter a scope code before proceeding. + * @expectedExceptionMessage A scope code is missing. Enter a code and try again. */ public function testEmptyScopeCode() { @@ -108,7 +109,7 @@ public function testWrongScopeCodeFormat() /** * @expectedException \Magento\Framework\Exception\LocalizedException - * @expectedExceptionMessage The "not_default_scope" value doesn't exist. Enter another value. + * @expectedExceptionMessage The "not_default_scope" value doesn't exist. Enter another value and try again. */ public function testScopeNotExist() { @@ -123,7 +124,7 @@ public function testScopeNotExist() /** * @expectedException \Magento\Framework\Exception\LocalizedException - * @expectedExceptionMessage The "not_exist_scope_code" value doesn't exist. Enter another value. + * @expectedExceptionMessage The "not_exist_scope_code" value doesn't exist. Enter another value and try again. */ public function testScopeCodeNotExist() { diff --git a/lib/internal/Magento/Framework/App/Test/Unit/DeploymentConfig/ReaderTest.php b/lib/internal/Magento/Framework/App/Test/Unit/DeploymentConfig/ReaderTest.php index 3e3eea322cafd..8f8399263384c 100644 --- a/lib/internal/Magento/Framework/App/Test/Unit/DeploymentConfig/ReaderTest.php +++ b/lib/internal/Magento/Framework/App/Test/Unit/DeploymentConfig/ReaderTest.php @@ -8,26 +8,29 @@ use Magento\Framework\App\DeploymentConfig\Reader; use Magento\Framework\App\Filesystem\DirectoryList; +use Magento\Framework\Config\File\ConfigFilePool; +use Magento\Framework\Filesystem\Driver\File; +use Magento\Framework\Filesystem\DriverPool; class ReaderTest extends \PHPUnit\Framework\TestCase { /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\App\Filesystem\DirectoryList|\PHPUnit_Framework_MockObject_MockObject */ private $dirList; /** - * @var \Magento\Framework\Filesystem\DriverPool|\PHPUnit_Framework_MockObject_MockObject + * @var DriverPool|\PHPUnit_Framework_MockObject_MockObject */ private $driverPool; /** - * @var \Magento\Framework\Filesystem\Driver\File|\PHPUnit_Framework_MockObject_MockObject + * @var File|\PHPUnit_Framework_MockObject_MockObject */ private $fileDriver; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var ConfigFilePool|\PHPUnit_Framework_MockObject_MockObject */ private $configFilePool; @@ -38,7 +41,7 @@ protected function setUp() ->method('getPath') ->with(DirectoryList::CONFIG) ->willReturn(__DIR__ . '/_files'); - $this->fileDriver = $this->createMock(\Magento\Framework\Filesystem\Driver\File::class); + $this->fileDriver = $this->createMock(File::class); $this->fileDriver ->expects($this->any()) ->method('isExists') @@ -51,12 +54,12 @@ protected function setUp() [__DIR__ . '/_files/mergeTwo.php', true], [__DIR__ . '/_files/nonexistent.php', false] ])); - $this->driverPool = $this->createMock(\Magento\Framework\Filesystem\DriverPool::class); + $this->driverPool = $this->createMock(DriverPool::class); $this->driverPool ->expects($this->any()) ->method('getDriver') ->willReturn($this->fileDriver); - $this->configFilePool = $this->createMock(\Magento\Framework\Config\File\ConfigFilePool::class); + $this->configFilePool = $this->createMock(ConfigFilePool::class); $this->configFilePool ->expects($this->any()) ->method('getPaths') @@ -100,13 +103,97 @@ public function testLoad() */ public function testCustomLoad($file, $expected) { - $configFilePool = $this->createMock(\Magento\Framework\Config\File\ConfigFilePool::class); + $configFilePool = $this->createMock(ConfigFilePool::class); $configFilePool->expects($this->any())->method('getPaths')->willReturn([$file]); $configFilePool->expects($this->any())->method('getPath')->willReturn($file); $object = new Reader($this->dirList, $this->driverPool, $configFilePool, $file); $this->assertSame($expected, $object->load($file)); } + /** + * Test Reader::load() will throw exception in case of invalid configuration file(single file). + * + * @expectedException \Magento\Framework\Exception\RuntimeException + * @expectedExceptionMessageRegExp /Invalid configuration file: \'.*\/\_files\/emptyConfig\.php\'/ + * @return void + */ + public function testLoadInvalidConfigurationFileWithFileKey() + { + $fileDriver = $this->getMockBuilder(File::class) + ->disableOriginalConstructor() + ->getMock(); + $fileDriver->expects($this->once()) + ->method('isExists') + ->willReturn(true); + /** @var DriverPool|\PHPUnit_Framework_MockObject_MockObject $driverPool */ + $driverPool = $this->getMockBuilder(DriverPool::class) + ->disableOriginalConstructor() + ->getMock(); + $driverPool + ->expects($this->once()) + ->method('getDriver') + ->willReturn($fileDriver); + /** @var ConfigFilePool|\PHPUnit_Framework_MockObject_MockObject $configFilePool */ + $configFilePool = $this->getMockBuilder(ConfigFilePool::class) + ->disableOriginalConstructor() + ->getMock(); + $configFilePool + ->expects($this->once()) + ->method('getPath') + ->with($this->identicalTo('testConfig')) + ->willReturn('emptyConfig.php'); + $object = new Reader($this->dirList, $driverPool, $configFilePool); + $object->load('testConfig'); + } + + /** + * Test Reader::load() will throw exception in case of invalid configuration file(multiple files). + * + * @expectedException \Magento\Framework\Exception\RuntimeException + * @expectedExceptionMessageRegExp /Invalid configuration file: \'.*\/\_files\/emptyConfig\.php\'/ + * @return void + */ + public function testLoadInvalidConfigurationFile() + { + $fileDriver = $this->getMockBuilder(File::class) + ->disableOriginalConstructor() + ->getMock(); + $fileDriver->expects($this->exactly(2)) + ->method('isExists') + ->willReturn(true); + /** @var DriverPool|\PHPUnit_Framework_MockObject_MockObject $driverPool */ + $driverPool = $this->getMockBuilder(DriverPool::class) + ->disableOriginalConstructor() + ->getMock(); + $driverPool + ->expects($this->once()) + ->method('getDriver') + ->willReturn($fileDriver); + /** @var ConfigFilePool|\PHPUnit_Framework_MockObject_MockObject $configFilePool */ + $configFilePool = $this->getMockBuilder(ConfigFilePool::class) + ->disableOriginalConstructor() + ->getMock(); + $configFilePool->expects($this->exactly(2)) + ->method('getPaths') + ->willReturn( + [ + 'configKeyOne' => 'config.php', + 'testConfig' => 'emptyConfig.php' + ] + ); + $configFilePool->expects($this->exactly(2)) + ->method('getPath') + ->withConsecutive( + [$this->identicalTo('configKeyOne')], + [$this->identicalTo('testConfig')] + )->willReturnOnConsecutiveCalls( + 'config.php', + 'emptyConfig.php' + ); + $object = new Reader($this->dirList, $driverPool, $configFilePool); + $object->load(); + } + /** * @return array */ diff --git a/lib/internal/Magento/Framework/App/Test/Unit/DeploymentConfig/WriterTest.php b/lib/internal/Magento/Framework/App/Test/Unit/DeploymentConfig/WriterTest.php index d4783cd36a051..31d0ca96f1af7 100644 --- a/lib/internal/Magento/Framework/App/Test/Unit/DeploymentConfig/WriterTest.php +++ b/lib/internal/Magento/Framework/App/Test/Unit/DeploymentConfig/WriterTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\App\Test\Unit\DeploymentConfig; use Magento\Framework\App\DeploymentConfig; @@ -243,7 +244,7 @@ public function testSaveConfigOverride() /** * @expectedException \Magento\Framework\Exception\FileSystemException - * @expectedExceptionMessage Deployment config file env.php is not writable. + * @expectedExceptionMessage The "env.php" deployment config file isn't writable. */ public function testSaveConfigException() { diff --git a/lib/internal/Magento/Framework/App/Test/Unit/DeploymentConfig/_files/emptyConfig.php b/lib/internal/Magento/Framework/App/Test/Unit/DeploymentConfig/_files/emptyConfig.php new file mode 100644 index 0000000000000..79549bf674aad --- /dev/null +++ b/lib/internal/Magento/Framework/App/Test/Unit/DeploymentConfig/_files/emptyConfig.php @@ -0,0 +1,6 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +//Example of wrong(empty) configuration file. diff --git a/lib/internal/Magento/Framework/App/Test/Unit/Scope/ValidatorTest.php b/lib/internal/Magento/Framework/App/Test/Unit/Scope/ValidatorTest.php index b9df13c67a863..5c28899b4d405 100644 --- a/lib/internal/Magento/Framework/App/Test/Unit/Scope/ValidatorTest.php +++ b/lib/internal/Magento/Framework/App/Test/Unit/Scope/ValidatorTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\App\Test\Unit\Scope; use Magento\Framework\App\Config\ScopeConfigInterface; @@ -76,7 +77,7 @@ public function testNotEmptyScopeCodeForDefaultScope() /** * @expectedException \Magento\Framework\Exception\LocalizedException - * @expectedExceptionMessage Enter a scope before proceeding. + * @expectedExceptionMessage A scope is missing. Enter a scope and try again. */ public function testEmptyScope() { @@ -85,7 +86,7 @@ public function testEmptyScope() /** * @expectedException \Magento\Framework\Exception\LocalizedException - * @expectedExceptionMessage Enter a scope code before proceeding. + * @expectedExceptionMessage A scope code is missing. Enter a code and try again. */ public function testEmptyScopeCode() { @@ -103,7 +104,7 @@ public function testWrongScopeCodeFormat() /** * @expectedException \Magento\Framework\Exception\LocalizedException - * @expectedExceptionMessage The "not_default_scope" value doesn't exist. Enter another value. + * @expectedExceptionMessage The "not_default_scope" value doesn't exist. Enter another value and try again. */ public function testScopeNotExist() { @@ -118,7 +119,7 @@ public function testScopeNotExist() /** * @expectedException \Magento\Framework\Exception\LocalizedException - * @expectedExceptionMessage The "not_exist_scope_code" value doesn't exist. Enter another value. + * @expectedExceptionMessage The "not_exist_scope_code" value doesn't exist. Enter another value and try again. */ public function testScopeCodeNotExist() { diff --git a/lib/internal/Magento/Framework/Archive/Helper/File.php b/lib/internal/Magento/Framework/Archive/Helper/File.php index 60959a658e3f8..5d2a405578c8c 100644 --- a/lib/internal/Magento/Framework/Archive/Helper/File.php +++ b/lib/internal/Magento/Framework/Archive/Helper/File.php @@ -96,7 +96,7 @@ public function open($mode = 'w+', $chmod = null) if (!is_writable($this->_fileLocation)) { throw new LocalizedException( new \Magento\Framework\Phrase( - 'Permission denied to write to %1', + 'You don\'t have permissions to write to the "%1" file.', [$this->_fileLocation] ) ); @@ -105,7 +105,7 @@ public function open($mode = 'w+', $chmod = null) if (is_file($this->_filePath) && !is_writable($this->_filePath)) { throw new LocalizedException( new \Magento\Framework\Phrase( - "Can't open file %1 for writing. Permission denied.", + 'You don\'t have the permissions to open the "%1" file for writing access.', [$this->_fileName] ) ); @@ -115,13 +115,19 @@ public function open($mode = 'w+', $chmod = null) if ($this->_isReadableMode($mode) && (!is_file($this->_filePath) || !is_readable($this->_filePath))) { if (!is_file($this->_filePath)) { throw new LocalizedException( - new \Magento\Framework\Phrase('File %1 does not exist', [$this->_filePath]) + new \Magento\Framework\Phrase( + 'The "%1" file doesn\'t exist. Verify the file and try again.', + [$this->_filePath] + ) ); } if (!is_readable($this->_filePath)) { throw new LocalizedException( - new \Magento\Framework\Phrase('Permission denied to read file %1', [$this->_filePath]) + new \Magento\Framework\Phrase( + 'You don\'t have permissions to read the "%1" file.', + [$this->_filePath] + ) ); } } @@ -200,7 +206,7 @@ protected function _open($mode) if (false === $this->_fileHandler) { throw new LocalizedException( - new \Magento\Framework\Phrase('Failed to open file %1', [$this->_filePath]) + new \Magento\Framework\Phrase('The "%1" file failed to open.', [$this->_filePath]) ); } } @@ -218,7 +224,7 @@ protected function _write($data) if (false === $result) { throw new LocalizedException( - new \Magento\Framework\Phrase('Failed to write data to %1', [$this->_filePath]) + new \Magento\Framework\Phrase('The data failed to write to "%1".', [$this->_filePath]) ); } } diff --git a/lib/internal/Magento/Framework/Archive/Helper/File/Bz.php b/lib/internal/Magento/Framework/Archive/Helper/File/Bz.php index a3623d2b05c9f..d84cf25c54137 100644 --- a/lib/internal/Magento/Framework/Archive/Helper/File/Bz.php +++ b/lib/internal/Magento/Framework/Archive/Helper/File/Bz.php @@ -24,7 +24,7 @@ protected function _open($mode) if (false === $this->_fileHandler) { throw new \Magento\Framework\Exception\LocalizedException( - new \Magento\Framework\Phrase('Failed to open file %1', [$this->_filePath]) + new \Magento\Framework\Phrase('The "%1" file failed to open.', [$this->_filePath]) ); } } @@ -38,7 +38,7 @@ protected function _write($data) if (false === $result) { throw new \Magento\Framework\Exception\LocalizedException( - new \Magento\Framework\Phrase('Failed to write data to %1', [$this->_filePath]) + new \Magento\Framework\Phrase('The data failed to write to "%1".', [$this->_filePath]) ); } } diff --git a/lib/internal/Magento/Framework/Archive/Helper/File/Gz.php b/lib/internal/Magento/Framework/Archive/Helper/File/Gz.php index db5038963c4f3..5204bcae9ae32 100644 --- a/lib/internal/Magento/Framework/Archive/Helper/File/Gz.php +++ b/lib/internal/Magento/Framework/Archive/Helper/File/Gz.php @@ -24,7 +24,7 @@ protected function _open($mode) if (false === $this->_fileHandler) { throw new \Magento\Framework\Exception\LocalizedException( - new \Magento\Framework\Phrase('Failed to open file %1', [$this->_filePath]) + new \Magento\Framework\Phrase('The "%1" file failed to open.', [$this->_filePath]) ); } } @@ -38,7 +38,7 @@ protected function _write($data) if (empty($result) && !empty($data)) { throw new \Magento\Framework\Exception\LocalizedException( - new \Magento\Framework\Phrase('Failed to write data to %1', [$this->_filePath]) + new \Magento\Framework\Phrase('The data failed to write to "%1".', [$this->_filePath]) ); } } diff --git a/lib/internal/Magento/Framework/Backup/Filesystem/Rollback/Fs.php b/lib/internal/Magento/Framework/Backup/Filesystem/Rollback/Fs.php index 19109001b02c1..14531deda45bb 100644 --- a/lib/internal/Magento/Framework/Backup/Filesystem/Rollback/Fs.php +++ b/lib/internal/Magento/Framework/Backup/Filesystem/Rollback/Fs.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\Backup\Filesystem\Rollback; use Magento\Framework\App\ObjectManager; @@ -66,7 +67,7 @@ public function run() } throw new NotEnoughPermissions( - new Phrase('Unable to make rollback because not all files are writable') + new Phrase("The rollback can't be executed because not all files are writable.") ); } diff --git a/lib/internal/Magento/Framework/Communication/Config/ConfigParser.php b/lib/internal/Magento/Framework/Communication/Config/ConfigParser.php index 350ac247a560c..5456d3c717ad8 100644 --- a/lib/internal/Magento/Framework/Communication/Config/ConfigParser.php +++ b/lib/internal/Magento/Framework/Communication/Config/ConfigParser.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\Communication\Config; use Magento\Framework\Exception\LocalizedException; @@ -30,7 +31,7 @@ public function parseServiceMethod($serviceMethod) if (!isset($matches[1]) || !isset($matches[2])) { throw new LocalizedException( new Phrase( - 'Service method "%serviceMethod" must match the following pattern: "%pattern"', + 'The "%serviceMethod" service method must match the "%pattern" pattern.', ['serviceMethod' => $serviceMethod, 'pattern' => $pattern] ) ); diff --git a/lib/internal/Magento/Framework/Config/AbstractXml.php b/lib/internal/Magento/Framework/Config/AbstractXml.php index a8d0eff6bce74..caead98147bf5 100644 --- a/lib/internal/Magento/Framework/Config/AbstractXml.php +++ b/lib/internal/Magento/Framework/Config/AbstractXml.php @@ -89,7 +89,10 @@ protected function _merge($configFiles) $this->_getDomConfigModel()->merge($content); } catch (\Magento\Framework\Config\Dom\ValidationException $e) { throw new \Magento\Framework\Exception\LocalizedException( - new \Magento\Framework\Phrase("Invalid XML in file %1:\n%2", [$key, $e->getMessage()]) + new \Magento\Framework\Phrase( + 'The XML in file "%1" is invalid:' . "\n%2\nVerify the XML and try again.", + [$key, $e->getMessage()] + ) ); } } diff --git a/lib/internal/Magento/Framework/Config/FileResolverByModule.php b/lib/internal/Magento/Framework/Config/FileResolverByModule.php index bd8a61e0ec234..efd84823dfbc9 100644 --- a/lib/internal/Magento/Framework/Config/FileResolverByModule.php +++ b/lib/internal/Magento/Framework/Config/FileResolverByModule.php @@ -6,7 +6,9 @@ namespace Magento\Framework\Config; use Magento\Framework\Component\ComponentRegistrar; +use Magento\Framework\Filesystem\DriverInterface; use Magento\Framework\Module\Dir; +use Magento\Framework\Oauth\Exception; /** * Application config file resolver. @@ -23,6 +25,11 @@ class FileResolverByModule extends \Magento\Framework\App\Config\FileResolver */ private $componentRegistrar; + /** + * @var DriverInterface + */ + private $driver; + /** * Constructor. * @@ -30,15 +37,18 @@ class FileResolverByModule extends \Magento\Framework\App\Config\FileResolver * @param \Magento\Framework\Filesystem $filesystem * @param FileIteratorFactory $iteratorFactory * @param ComponentRegistrar $componentRegistrar + * @param \Magento\Framework\Filesystem\Driver\File $driver */ public function __construct( \Magento\Framework\Module\Dir\Reader $moduleReader, \Magento\Framework\Filesystem $filesystem, \Magento\Framework\Config\FileIteratorFactory $iteratorFactory, - ComponentRegistrar $componentRegistrar + ComponentRegistrar $componentRegistrar, + \Magento\Framework\Filesystem\Driver\File $driver ) { parent::__construct($moduleReader, $filesystem, $iteratorFactory); $this->componentRegistrar = $componentRegistrar; + $this->driver = $driver; } /** @@ -51,10 +61,15 @@ public function get($filename, $scope) $iterator = $this->_moduleReader->getConfigurationFiles($filename)->toArray(); if ($scope !== self::ALL_MODULES) { $path = $this->componentRegistrar->getPath('module', $scope); - $path .= DIRECTORY_SEPARATOR . Dir::MODULE_ETC_DIR . DIRECTORY_SEPARATOR . $filename; + $path .= '/' . Dir::MODULE_ETC_DIR . '/'. $filename; $iterator = isset($iterator[$path]) ? [$path => $iterator[$path]] : []; } - + $primaryFile = parent::get($filename, 'primary')->toArray(); + if (!$this->driver->isFile(key($primaryFile))) { + throw new \Exception("Primary db_schema file doesn`t exists"); + } + /** Load primary configurations */ + $iterator += $primaryFile; return $iterator; } } diff --git a/lib/internal/Magento/Framework/Config/Reader/Filesystem.php b/lib/internal/Magento/Framework/Config/Reader/Filesystem.php index 744649ad45fa3..e2008b95c3b61 100644 --- a/lib/internal/Magento/Framework/Config/Reader/Filesystem.php +++ b/lib/internal/Magento/Framework/Config/Reader/Filesystem.php @@ -6,6 +6,7 @@ * See COPYING.txt for license details. * */ + namespace Magento\Framework\Config\Reader; /** @@ -152,7 +153,10 @@ protected function _readFiles($fileList) } } catch (\Magento\Framework\Config\Dom\ValidationException $e) { throw new \Magento\Framework\Exception\LocalizedException( - new \Magento\Framework\Phrase("Invalid XML in file %1:\n%2", [$key, $e->getMessage()]) + new \Magento\Framework\Phrase( + 'The XML in file "%1" is invalid:' . "\n%2\nVerify the XML and try again.", + [$key, $e->getMessage()] + ) ); } } 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 bd1aaa7ca791f..d48b9be427628 100644 --- a/lib/internal/Magento/Framework/Config/Test/Unit/Reader/FilesystemTest.php +++ b/lib/internal/Magento/Framework/Config/Test/Unit/Reader/FilesystemTest.php @@ -119,7 +119,7 @@ public function testReadWithInvalidDom() /** * @expectedException \Magento\Framework\Exception\LocalizedException - * @expectedExceptionMessage Invalid XML in file + * @expectedExceptionMessage The XML in file "0" is invalid: */ public function testReadWithInvalidXml() { diff --git a/lib/internal/Magento/Framework/Console/QuestionPerformer/YesNo.php b/lib/internal/Magento/Framework/Console/QuestionPerformer/YesNo.php index 1e9ae60472563..b46612df59296 100644 --- a/lib/internal/Magento/Framework/Console/QuestionPerformer/YesNo.php +++ b/lib/internal/Magento/Framework/Console/QuestionPerformer/YesNo.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\Console\QuestionPerformer; use Magento\Framework\Exception\LocalizedException; @@ -81,7 +82,7 @@ private function getConfirmationQuestion(array $messages) $question->setValidator(function ($answer) { if (!in_array(strtolower($answer), ['yes', 'y', 'no', 'n'])) { throw new LocalizedException( - new Phrase('Please type [y]es or [n]o') + new Phrase('A [y]es or [n]o selection needs to be made. Select and try again.') ); } diff --git a/lib/internal/Magento/Framework/Convert/ConvertArray.php b/lib/internal/Magento/Framework/Convert/ConvertArray.php index 089c25a0da771..1cd377c7d2cc8 100644 --- a/lib/internal/Magento/Framework/Convert/ConvertArray.php +++ b/lib/internal/Magento/Framework/Convert/ConvertArray.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\Convert; use Magento\Framework\Exception\LocalizedException; @@ -24,7 +25,11 @@ class ConvertArray public function assocToXml(array $array, $rootName = '_') { if (empty($rootName) || is_numeric($rootName)) { - throw new LocalizedException(new \Magento\Framework\Phrase('Root element must not be empty or numeric')); + throw new LocalizedException( + new \Magento\Framework\Phrase( + "The root element can't be empty or use numbers. Change the element and try again." + ) + ); } $xmlStr = <<<XML @@ -34,7 +39,9 @@ public function assocToXml(array $array, $rootName = '_') $xml = new \SimpleXMLElement($xmlStr); foreach (array_keys($array) as $key) { if (is_numeric($key)) { - throw new LocalizedException(new \Magento\Framework\Phrase('Array root keys must not be numeric.')); + throw new LocalizedException( + new \Magento\Framework\Phrase('An error occurred. Use non-numeric array root keys and try again.') + ); } } return self::_assocToXml($array, $rootName, $xml); @@ -77,7 +84,8 @@ private function _assocToXml(array $array, $rootName, \SimpleXMLElement $xml) if ($key === $rootName) { throw new LocalizedException( new \Magento\Framework\Phrase( - 'Associative key must not be the same as its parent associative key.' + "An associative key can't be the same as its parent associative key. " + . "Verify and try again." ) ); } @@ -94,7 +102,9 @@ private function _assocToXml(array $array, $rootName, \SimpleXMLElement $xml) } if ($hasNumericKey && $hasStringKey) { throw new LocalizedException( - new \Magento\Framework\Phrase('Associative and numeric keys must not be mixed at one level.') + new \Magento\Framework\Phrase( + "Associative and numeric keys can't be mixed at one level. Verify and try again." + ) ); } return $xml; diff --git a/lib/internal/Magento/Framework/Convert/Test/Unit/ConvertArrayTest.php b/lib/internal/Magento/Framework/Convert/Test/Unit/ConvertArrayTest.php index 70414b2802c8a..d80e2b7e50015 100644 --- a/lib/internal/Magento/Framework/Convert/Test/Unit/ConvertArrayTest.php +++ b/lib/internal/Magento/Framework/Convert/Test/Unit/ConvertArrayTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\Convert\Test\Unit; use \Magento\Framework\Convert\ConvertArray; @@ -34,7 +35,7 @@ public function testAssocToXml() /** * @expectedException \Exception - * @expectedExceptionMessage Associative and numeric keys must not be mixed at one level. + * @expectedExceptionMessage Associative and numeric keys can't be mixed at one level. Verify and try again. */ public function testAssocToXmlExceptionByKey() { diff --git a/lib/internal/Magento/Framework/Crontab/CrontabManager.php b/lib/internal/Magento/Framework/Crontab/CrontabManager.php index 94e2027abd135..6049b7fba6d44 100644 --- a/lib/internal/Magento/Framework/Crontab/CrontabManager.php +++ b/lib/internal/Magento/Framework/Crontab/CrontabManager.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\Crontab; use Magento\Framework\App\Filesystem\DirectoryList; @@ -86,7 +87,7 @@ public function getTasks() public function saveTasks(array $tasks) { if (!$tasks) { - throw new LocalizedException(new Phrase('List of tasks is empty')); + throw new LocalizedException(new Phrase('The list of tasks is empty. Add tasks and try again.')); } $this->checkSupportedOs(); @@ -99,7 +100,7 @@ public function saveTasks(array $tasks) } if (empty($task['command'])) { - throw new LocalizedException(new Phrase('Command should not be empty')); + throw new LocalizedException(new Phrase("The command shouldn't be empty. Enter and try again.")); } $tasks[$key]['command'] = str_replace( diff --git a/lib/internal/Magento/Framework/Crontab/Test/Unit/CrontabManagerTest.php b/lib/internal/Magento/Framework/Crontab/Test/Unit/CrontabManagerTest.php index 5f7984c085ac7..b160eb0a7f95e 100644 --- a/lib/internal/Magento/Framework/Crontab/Test/Unit/CrontabManagerTest.php +++ b/lib/internal/Magento/Framework/Crontab/Test/Unit/CrontabManagerTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\Crontab\Test\Unit; use Magento\Framework\Crontab\CrontabManager; @@ -192,7 +193,7 @@ public function removeTasksDataProvider() /** * @return void * @expectedException \Magento\Framework\Exception\LocalizedException - * @expectedExceptionMessage List of tasks is empty + * @expectedExceptionMessage The list of tasks is empty. Add tasks and try again. */ public function testSaveTasksWithEmptyTasksList() { @@ -219,7 +220,7 @@ public function testSaveTasksWithEmptyTasksList() /** * @return void * @expectedException \Magento\Framework\Exception\LocalizedException - * @expectedExceptionMessage Command should not be empty + * @expectedExceptionMessage The command shouldn't be empty. Enter and try again. */ public function testSaveTasksWithoutCommand() { diff --git a/lib/internal/Magento/Framework/DB/Adapter/Pdo/Mysql.php b/lib/internal/Magento/Framework/DB/Adapter/Pdo/Mysql.php index 7dc88c4369858..97377c94ca91a 100644 --- a/lib/internal/Magento/Framework/DB/Adapter/Pdo/Mysql.php +++ b/lib/internal/Magento/Framework/DB/Adapter/Pdo/Mysql.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\DB\Adapter\Pdo; use Magento\Framework\App\ObjectManager; @@ -581,7 +582,9 @@ protected function _query($sql, $bind = []) public function query($sql, $bind = []) { if (strpos(rtrim($sql, " \t\n\r\0;"), ';') !== false && count($this->_splitMultiQuery($sql)) > 1) { - throw new \Magento\Framework\Exception\LocalizedException(new Phrase('Cannot execute multiple queries')); + throw new \Magento\Framework\Exception\LocalizedException( + new Phrase("Multiple queries can't be executed. Run a single query and try again.") + ); } return $this->_query($sql, $bind); } diff --git a/lib/internal/Magento/Framework/DB/Query/Generator.php b/lib/internal/Magento/Framework/DB/Query/Generator.php index 1d903b05b8f75..0538aec760bd7 100644 --- a/lib/internal/Magento/Framework/DB/Query/Generator.php +++ b/lib/internal/Magento/Framework/DB/Query/Generator.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\DB\Query; use Magento\Framework\Exception\LocalizedException; @@ -75,7 +76,9 @@ public function generate( $fromSelect = $select->getPart(\Magento\Framework\DB\Select::FROM); if (empty($fromSelect)) { throw new LocalizedException( - new \Magento\Framework\Phrase('Select object must have correct "FROM" part') + new \Magento\Framework\Phrase( + 'The select object must have the correct "FROM" part. Verify and try again.' + ) ); } @@ -143,7 +146,9 @@ public function generateByRange( $fromSelect = $select->getPart(\Magento\Framework\DB\Select::FROM); if (empty($fromSelect)) { throw new LocalizedException( - new \Magento\Framework\Phrase('Select object must have correct "FROM" part') + new \Magento\Framework\Phrase( + 'The select object must have the correct "FROM" part. Verify and try again.' + ) ); } diff --git a/lib/internal/Magento/Framework/DB/Test/Unit/Adapter/Pdo/MysqlTest.php b/lib/internal/Magento/Framework/DB/Test/Unit/Adapter/Pdo/MysqlTest.php index c86f097520462..10a8fdb3a8361 100644 --- a/lib/internal/Magento/Framework/DB/Test/Unit/Adapter/Pdo/MysqlTest.php +++ b/lib/internal/Magento/Framework/DB/Test/Unit/Adapter/Pdo/MysqlTest.php @@ -220,7 +220,7 @@ public function testCheckDdlTransaction($ddlQuery) /** * @expectedException \Magento\Framework\Exception\LocalizedException - * @expectedExceptionMessage Cannot execute multiple queries + * @expectedExceptionMessage Multiple queries can't be executed. Run a single query and try again. */ public function testMultipleQueryException() { diff --git a/lib/internal/Magento/Framework/DB/Test/Unit/Tree/NodeTest.php b/lib/internal/Magento/Framework/DB/Test/Unit/Tree/NodeTest.php index 8d3623d485b89..69cd2be4d20a4 100644 --- a/lib/internal/Magento/Framework/DB/Test/Unit/Tree/NodeTest.php +++ b/lib/internal/Magento/Framework/DB/Test/Unit/Tree/NodeTest.php @@ -5,6 +5,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\DB\Test\Unit\Tree; class NodeTest extends \PHPUnit\Framework\TestCase @@ -93,21 +94,21 @@ public function constructorDataProvider() 'node_data' => null, 'keys' => null, ], \Magento\Framework\Exception\LocalizedException::class, - 'Empty array of node information', + 'The node information is empty. Enter the information and try again.', ], [ [ 'node_data' => null, 'keys' => true, ], \Magento\Framework\Exception\LocalizedException::class, - 'Empty array of node information' + 'The node information is empty. Enter the information and try again.' ], [ [ 'node_data' => true, 'keys' => null, ], \Magento\Framework\Exception\LocalizedException::class, - 'Empty keys array' + 'Enter the encryption key and try again.' ] ]; } diff --git a/lib/internal/Magento/Framework/DB/Tree.php b/lib/internal/Magento/Framework/DB/Tree.php index e96b5e123f8dd..a162640e5aa50 100644 --- a/lib/internal/Magento/Framework/DB/Tree.php +++ b/lib/internal/Magento/Framework/DB/Tree.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\DB; use Magento\Framework\DB\Tree\Node; @@ -103,7 +104,9 @@ public function __construct($config = []) $conn->setAttribute(\PDO::ATTR_EMULATE_PREPARES, true); } } else { - throw new LocalizedException(new Phrase('db object is not set in config')); + throw new LocalizedException( + new Phrase('The "db object" isn\'t set in config. Set the "db object" and try again.') + ); } if (!empty($config['table'])) { diff --git a/lib/internal/Magento/Framework/DB/Tree/Node.php b/lib/internal/Magento/Framework/DB/Tree/Node.php index a11faecb851eb..8088718be5e73 100644 --- a/lib/internal/Magento/Framework/DB/Tree/Node.php +++ b/lib/internal/Magento/Framework/DB/Tree/Node.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\DB\Tree; use Magento\Framework\Exception\LocalizedException; @@ -65,10 +66,14 @@ class Node public function __construct($nodeData, $keys) { if (empty($nodeData)) { - throw new LocalizedException(new \Magento\Framework\Phrase('Empty array of node information')); + throw new LocalizedException( + new \Magento\Framework\Phrase('The node information is empty. Enter the information and try again.') + ); } if (empty($keys)) { - throw new LocalizedException(new \Magento\Framework\Phrase('Empty keys array')); + throw new LocalizedException( + new \Magento\Framework\Phrase("The encryption key can't be empty. Enter the key and try again.") + ); } $this->id = $nodeData[$keys['id']]; diff --git a/lib/internal/Magento/Framework/Data/Form.php b/lib/internal/Magento/Framework/Data/Form.php index fbec614dc3c96..abeda0c17542e 100644 --- a/lib/internal/Magento/Framework/Data/Form.php +++ b/lib/internal/Magento/Framework/Data/Form.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\Data; use Magento\Framework\Data\Form\Element\AbstractElement; @@ -175,7 +176,9 @@ public function addElementToCollection($element) public function checkElementId($elementId) { if ($this->_elementIdExists($elementId)) { - throw new \InvalidArgumentException('Element with id "' . $elementId . '" already exists'); + throw new \InvalidArgumentException( + 'An element with a "' . $elementId . '" ID already exists.' + ); } return true; } diff --git a/lib/internal/Magento/Framework/Data/Form/Element/Editor.php b/lib/internal/Magento/Framework/Data/Form/Element/Editor.php index 73e05f6eaa5d1..f2368beadc51a 100644 --- a/lib/internal/Magento/Framework/Data/Form/Element/Editor.php +++ b/lib/internal/Magento/Framework/Data/Form/Element/Editor.php @@ -172,54 +172,7 @@ public function getElementHtml() ' >' . $this->getEscapedValue() . '</textarea>' . - $js . - ' - <script type="text/javascript"> - //<![CDATA[ - window.tinyMCE_GZ = window.tinyMCE_GZ || {}; - window.tinyMCE_GZ.loaded = true; - require([ - "jquery", - "mage/translate", - "mage/adminhtml/events", - "mage/adminhtml/wysiwyg/tiny_mce/setup", - "mage/adminhtml/wysiwyg/widget" - ], function(jQuery){' . - "\n" . - ' (function($) {$.mage.translate.add(' . - $this->serializer->serialize( - $this->getButtonTranslations() - ) . - ')})(jQuery);' . - "\n" . - $jsSetupObject . - ' = new wysiwygSetup("' . - $this->getHtmlId() . - '", ' . - $this->getJsonConfig() . - ');' . - $forceLoad . - ' - editorFormValidationHandler = ' . - $jsSetupObject . - '.onFormValidation.bind(' . - $jsSetupObject . - '); - Event.observe("toggle' . - $this->getHtmlId() . - '", "click", ' . - $jsSetupObject . - '.toggle.bind(' . - $jsSetupObject . - ')); - varienGlobalEvents.attachEventHandler("formSubmit", editorFormValidationHandler); - varienGlobalEvents.clearEventHandlers("open_browser_callback"); - varienGlobalEvents.attachEventHandler("open_browser_callback", ' . - $jsSetupObject . - '.openFileBrowser); - //]]> - }); - </script>'; + $js . $this->getInlineJs($jsSetupObject, $forceLoad); $html = $this->_wrapIntoContainer($html); $html .= $this->getAfterElementHtml(); @@ -516,4 +469,63 @@ protected function isToggleButtonVisible() { return !$this->getConfig()->hasData('toggle_button') || $this->getConfig('toggle_button'); } + + /** + * Returns inline js to initialize wysiwyg adapter + * + * @param string $jsSetupObject + * @param string $forceLoad + * @return string + */ + protected function getInlineJs($jsSetupObject, $forceLoad) + { + $jsString = ' + <script type="text/javascript"> + //<![CDATA[ + window.tinyMCE_GZ = window.tinyMCE_GZ || {}; + window.tinyMCE_GZ.loaded = true; + require([ + "jquery", + "mage/translate", + "mage/adminhtml/events", + "mage/adminhtml/wysiwyg/tiny_mce/setup", + "mage/adminhtml/wysiwyg/widget" + ], function(jQuery){' . + "\n" . + ' (function($) {$.mage.translate.add(' . + $this->serializer->serialize( + $this->getButtonTranslations() + ) . + ')})(jQuery);' . + "\n" . + $jsSetupObject . + ' = new wysiwygSetup("' . + $this->getHtmlId() . + '", ' . + $this->getJsonConfig() . + ');' . + $forceLoad . + ' + editorFormValidationHandler = ' . + $jsSetupObject . + '.onFormValidation.bind(' . + $jsSetupObject . + '); + Event.observe("toggle' . + $this->getHtmlId() . + '", "click", ' . + $jsSetupObject . + '.toggle.bind(' . + $jsSetupObject . + ')); + varienGlobalEvents.attachEventHandler("formSubmit", editorFormValidationHandler); + varienGlobalEvents.clearEventHandlers("open_browser_callback"); + varienGlobalEvents.attachEventHandler("open_browser_callback", ' . + $jsSetupObject . + '.openFileBrowser); + //]]> + }); + </script>'; + return $jsString; + } } diff --git a/lib/internal/Magento/Framework/Data/Structure.php b/lib/internal/Magento/Framework/Data/Structure.php index 9d540e8a49f08..f2c45fa160cc2 100644 --- a/lib/internal/Magento/Framework/Data/Structure.php +++ b/lib/internal/Magento/Framework/Data/Structure.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\Data; use Magento\Framework\Exception\LocalizedException; @@ -63,7 +64,7 @@ public function importElements(array $elements) if ($group !== array_flip($group)) { throw new LocalizedException( new \Magento\Framework\Phrase( - "Invalid format of group '%1': %2", + '"%2" is an invalid format of "%1" group. Verify the format and try again.', [$groupName, var_export($group, 1)] ) ); @@ -94,7 +95,8 @@ protected function _assertParentRelation($elementId) if (empty($this->_elements[$parentId][self::CHILDREN][$elementId])) { throw new LocalizedException( new \Magento\Framework\Phrase( - "Broken parent-child relation: the '%1' is not in the nested set of '%2'.", + 'The "%1" is not in the nested set of "%2", causing the parent-child relation to break. ' + . 'Verify and try again.', [$elementId, $parentId] ) ); @@ -107,7 +109,10 @@ protected function _assertParentRelation($elementId) $this->_assertArray($children); if ($children !== array_flip(array_flip($children))) { throw new LocalizedException( - new \Magento\Framework\Phrase('Invalid format of children: %1', [var_export($children, 1)]) + new \Magento\Framework\Phrase( + 'The "%1" format of children is invalid. Verify and try again.', + [var_export($children, 1)] + ) ); } foreach (array_keys($children) as $childId) { @@ -118,7 +123,8 @@ protected function _assertParentRelation($elementId) ) { throw new LocalizedException( new \Magento\Framework\Phrase( - "Broken parent-child relation: the '%1' is supposed to have '%2' as parent.", + 'The "%1" doesn\'t have "%2" as parent, causing the parent-child relation to break. ' + . 'Verify and try again.', [$childId, $elementId] ) ); @@ -149,7 +155,7 @@ public function createElement($elementId, array $data) { if (isset($this->_elements[$elementId])) { throw new LocalizedException( - new \Magento\Framework\Phrase("Element with ID '%1' already exists.", [$elementId]) + new \Magento\Framework\Phrase('An element with a "%1" ID already exists.', [$elementId]) ); } $this->_elements[$elementId] = []; @@ -225,7 +231,7 @@ public function setAttribute($elementId, $attribute, $value) // break is intentionally omitted case self::CHILDREN: case self::GROUPS: - throw new \InvalidArgumentException("Attribute '{$attribute}' is reserved and cannot be set."); + throw new \InvalidArgumentException("The '{$attribute}' attribute is reserved and can't be set."); default: $this->_elements[$elementId][$attribute] = $value; } @@ -261,7 +267,7 @@ public function renameElement($oldId, $newId) $this->_assertElementExists($oldId); if (!$newId || isset($this->_elements[$newId])) { throw new LocalizedException( - new \Magento\Framework\Phrase("Element with ID '%1' is already defined.", [$newId]) + new \Magento\Framework\Phrase('An element with a "%1" ID is already defined.', [$newId]) ); } @@ -303,13 +309,17 @@ public function setAsChild($elementId, $parentId, $alias = '', $position = null) { if ($elementId == $parentId) { throw new LocalizedException( - new \Magento\Framework\Phrase("The '%1' cannot be set as child to itself.", [$elementId]) + new \Magento\Framework\Phrase( + 'The "%1" was incorrectly set as a child to itself. Resolve the issue and try again.', + [$elementId] + ) ); } if ($this->_isParentRecursively($elementId, $parentId)) { throw new LocalizedException( new \Magento\Framework\Phrase( - "The '%1' is a parent of '%2' recursively, therefore '%3' cannot be set as child to it.", + 'The "%3" cannot be set as child to "%1" because "%1" is a parent of "%2" recursively. ' + . 'Resolve the issue and try again.', [$elementId, $parentId, $elementId] ) ); @@ -542,7 +552,10 @@ protected function _getChildOffset($parentId, $childId) $index = array_search($childId, array_keys($this->getChildren($parentId))); if (false === $index) { throw new LocalizedException( - new \Magento\Framework\Phrase("The '%1' is not a child of '%2'.", [$childId, $parentId]) + new \Magento\Framework\Phrase( + 'The "%1" is not a child of "%2". Resolve the issue and try again.', + [$childId, $parentId] + ) ); } return $index; @@ -595,7 +608,7 @@ protected function _insertChild($targetParentId, $elementId, $offset, $alias) if (!empty($this->_elements[$elementId][self::PARENT])) { throw new LocalizedException( new \Magento\Framework\Phrase( - "The element '%1' already has a parent: '%2'", + 'The element "%1" can\'t have a parent because "%2" is already the parent of "%1".', [$elementId, $this->_elements[$elementId][self::PARENT]] ) ); @@ -604,13 +617,16 @@ protected function _insertChild($targetParentId, $elementId, $offset, $alias) $children = $this->getChildren($targetParentId); if (isset($children[$elementId])) { throw new LocalizedException( - new \Magento\Framework\Phrase("The element '%1' already a child of '%2'", [$elementId, $targetParentId]) + new \Magento\Framework\Phrase( + 'The element "%1" is already a child of "%2".', + [$elementId, $targetParentId] + ) ); } if (false !== array_search($alias, $children)) { throw new LocalizedException( new \Magento\Framework\Phrase( - "The element '%1' already has a child with alias '%2'", + 'The element "%1" can\'t have a child because "%1" already has a child with alias "%2".', [$targetParentId, $alias] ) ); @@ -638,7 +654,9 @@ protected function _insertChild($targetParentId, $elementId, $offset, $alias) private function _assertElementExists($elementId) { if (!isset($this->_elements[$elementId])) { - throw new \OutOfBoundsException("No element found with ID '{$elementId}'."); + throw new \OutOfBoundsException( + 'The element with the "' . $elementId . '" ID wasn\'t found. Verify the ID and try again.' + ); } } diff --git a/lib/internal/Magento/Framework/Data/Test/Unit/FormTest.php b/lib/internal/Magento/Framework/Data/Test/Unit/FormTest.php index 89aff747238a1..fdda09d1462b1 100644 --- a/lib/internal/Magento/Framework/Data/Test/Unit/FormTest.php +++ b/lib/internal/Magento/Framework/Data/Test/Unit/FormTest.php @@ -104,7 +104,7 @@ public function testSettersGetters() /** * @expectedException \InvalidArgumentException - * @expectedExceptionMessage Element with id "1" already exists + * @expectedExceptionMessage An element with a "1" ID already exists. */ public function testElementExistsException() { diff --git a/lib/internal/Magento/Framework/Event/ObserverInterface.php b/lib/internal/Magento/Framework/Event/ObserverInterface.php index 09358e0966216..e7c9b770ea1f5 100644 --- a/lib/internal/Magento/Framework/Event/ObserverInterface.php +++ b/lib/internal/Magento/Framework/Event/ObserverInterface.php @@ -10,6 +10,7 @@ /** * Interface \Magento\Framework\Event\ObserverInterface * + * @api */ interface ObserverInterface { diff --git a/lib/internal/Magento/Framework/Exception/AuthenticationException.php b/lib/internal/Magento/Framework/Exception/AuthenticationException.php index fc097dc5562bd..9b20dea99ccf9 100644 --- a/lib/internal/Magento/Framework/Exception/AuthenticationException.php +++ b/lib/internal/Magento/Framework/Exception/AuthenticationException.php @@ -15,5 +15,5 @@ class AuthenticationException extends LocalizedException /** * @deprecated */ - const AUTHENTICATION_ERROR = 'An authentication error occurred.'; + const AUTHENTICATION_ERROR = 'An authentication error occurred. Verify and try again.'; } diff --git a/lib/internal/Magento/Framework/Exception/AuthorizationException.php b/lib/internal/Magento/Framework/Exception/AuthorizationException.php index 79bf95b22bccf..ed310117d6717 100644 --- a/lib/internal/Magento/Framework/Exception/AuthorizationException.php +++ b/lib/internal/Magento/Framework/Exception/AuthorizationException.php @@ -5,6 +5,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\Exception; /** @@ -15,5 +16,5 @@ class AuthorizationException extends LocalizedException /** * @deprecated */ - const NOT_AUTHORIZED = 'Consumer is not authorized to access %resources'; + const NOT_AUTHORIZED = "The consumer isn't authorized to access %resources."; } diff --git a/lib/internal/Magento/Framework/Exception/InputException.php b/lib/internal/Magento/Framework/Exception/InputException.php index b332c88d42f71..7b1815dc0d1bb 100644 --- a/lib/internal/Magento/Framework/Exception/InputException.php +++ b/lib/internal/Magento/Framework/Exception/InputException.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\Exception; use Magento\Framework\Phrase; @@ -42,7 +43,7 @@ class InputException extends AbstractAggregateException /** * @deprecated */ - const REQUIRED_FIELD = '%fieldName is a required field.'; + const REQUIRED_FIELD = '"%fieldName" is required. Enter and try again.'; /** * Initialize the input exception. @@ -87,7 +88,7 @@ public static function invalidFieldValue($fieldName, $fieldValue, \Exception $ca public static function requiredField($fieldName) { return new self( - new Phrase('%fieldName is a required field.', ['fieldName' => $fieldName]) + new Phrase('"%fieldName" is required. Enter and try again.', ['fieldName' => $fieldName]) ); } } diff --git a/lib/internal/Magento/Framework/Exception/SerializationException.php b/lib/internal/Magento/Framework/Exception/SerializationException.php index 27d0bc0c4371a..bae56b487975c 100644 --- a/lib/internal/Magento/Framework/Exception/SerializationException.php +++ b/lib/internal/Magento/Framework/Exception/SerializationException.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\Exception; use Magento\Framework\Phrase; @@ -22,7 +23,7 @@ class SerializationException extends LocalizedException /** * @deprecated */ - const TYPE_MISMATCH = 'Invalid type for value: "%value". Expected Type: "%type".'; + const TYPE_MISMATCH = 'The "%value" value\'s type is invalid. The "%type" type was expected. Verify and try again.'; /** * @param \Magento\Framework\Phrase $phrase diff --git a/lib/internal/Magento/Framework/Exception/Test/Unit/AuthenticationExceptionTest.php b/lib/internal/Magento/Framework/Exception/Test/Unit/AuthenticationExceptionTest.php index f728a0deacc7e..d0b8744c34ff1 100644 --- a/lib/internal/Magento/Framework/Exception/Test/Unit/AuthenticationExceptionTest.php +++ b/lib/internal/Magento/Framework/Exception/Test/Unit/AuthenticationExceptionTest.php @@ -21,10 +21,13 @@ public function testConstructor() { $authenticationException = new AuthenticationException( new Phrase( - 'An authentication error occurred.', + 'An authentication error occurred. Verify and try again.', ['consumer_id' => 1, 'resources' => 'record2'] ) ); - $this->assertSame('An authentication error occurred.', $authenticationException->getMessage()); + $this->assertSame( + 'An authentication error occurred. Verify and try again.', + $authenticationException->getMessage() + ); } } diff --git a/lib/internal/Magento/Framework/Exception/Test/Unit/AuthorizationExceptionTest.php b/lib/internal/Magento/Framework/Exception/Test/Unit/AuthorizationExceptionTest.php index 9b96587c8d195..667d97f20aa9e 100644 --- a/lib/internal/Magento/Framework/Exception/Test/Unit/AuthorizationExceptionTest.php +++ b/lib/internal/Magento/Framework/Exception/Test/Unit/AuthorizationExceptionTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\Exception\Test\Unit; use \Magento\Framework\Exception\AuthorizationException; @@ -17,10 +18,10 @@ public function testConstructor() { $authorizationException = new AuthorizationException( new Phrase( - 'Consumer is not authorized to access %resources', + 'The consumer isn\'t authorized to access %resources.', ['consumer_id' => 1, 'resources' => 'record2'] ) ); - $this->assertSame('Consumer is not authorized to access record2', $authorizationException->getMessage()); + $this->assertSame("The consumer isn't authorized to access record2.", $authorizationException->getMessage()); } } diff --git a/lib/internal/Magento/Framework/Exception/Test/Unit/InputExceptionTest.php b/lib/internal/Magento/Framework/Exception/Test/Unit/InputExceptionTest.php index edc66f2231025..44cbd7226da49 100644 --- a/lib/internal/Magento/Framework/Exception/Test/Unit/InputExceptionTest.php +++ b/lib/internal/Magento/Framework/Exception/Test/Unit/InputExceptionTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\Exception\Test\Unit; use \Magento\Framework\Exception\InputException; @@ -75,7 +76,9 @@ public function testAddError() $inputException->getLogMessage() ); - $inputException->addError(new Phrase('%fieldName is a required field.', ['fieldName' => 'name'])); + $inputException->addError( + new Phrase('"%fieldName" is required. Enter and try again.', ['fieldName' => 'name']) + ); $this->assertTrue($inputException->wasErrorAdded()); $this->assertCount(2, $inputException->getErrors()); @@ -102,9 +105,9 @@ public function testAddError() $errors[0]->getLogMessage() ); - $this->assertEquals('%fieldName is a required field.', $errors[1]->getRawMessage()); - $this->assertEquals('name is a required field.', $errors[1]->getMessage()); - $this->assertEquals('name is a required field.', $errors[1]->getLogMessage()); + $this->assertEquals('"%fieldName" is required. Enter and try again.', $errors[1]->getRawMessage()); + $this->assertEquals('"name" is required. Enter and try again.', $errors[1]->getMessage()); + $this->assertEquals('"name" is required. Enter and try again.', $errors[1]->getLogMessage()); } /** diff --git a/lib/internal/Magento/Framework/Filesystem/Directory/Write.php b/lib/internal/Magento/Framework/Filesystem/Directory/Write.php index 4566f61b15572..900d8423b31d8 100644 --- a/lib/internal/Magento/Framework/Filesystem/Directory/Write.php +++ b/lib/internal/Magento/Framework/Filesystem/Directory/Write.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\Filesystem\Directory; use Magento\Framework\Exception\FileSystemException; @@ -51,7 +52,7 @@ protected function assertWritable($path) $path = (!$this->driver->isFile($path)) ? $this->getAbsolutePath($this->path, $path) : $this->getAbsolutePath($path); - throw new FileSystemException(new \Magento\Framework\Phrase('The path "%1" is not writable', [$path])); + throw new FileSystemException(new \Magento\Framework\Phrase('The path "%1" is not writable.', [$path])); } } @@ -68,7 +69,7 @@ protected function assertIsFile($path) $absolutePath = $this->driver->getAbsolutePath($this->path, $path); if (!$this->driver->isFile($absolutePath)) { throw new FileSystemException( - new \Magento\Framework\Phrase('The file "%1" doesn\'t exist or not a file', [$absolutePath]) + new \Magento\Framework\Phrase('The "%1" file doesn\'t exist.', [$absolutePath]) ); } } diff --git a/lib/internal/Magento/Framework/Filesystem/Driver/File.php b/lib/internal/Magento/Framework/Filesystem/Driver/File.php index 519ca21deadb2..181fc1adb1558 100644 --- a/lib/internal/Magento/Framework/Filesystem/Driver/File.php +++ b/lib/internal/Magento/Framework/Filesystem/Driver/File.php @@ -5,6 +5,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\Filesystem\Driver; use Magento\Framework\Exception\FileSystemException; @@ -50,7 +51,7 @@ public function isExists($path) $result = @file_exists($this->getScheme() . $path); if ($result === null) { throw new FileSystemException( - new \Magento\Framework\Phrase('Error occurred during execution %1', [$this->getWarningMessage()]) + new \Magento\Framework\Phrase('An error occurred during "%1" execution.', [$this->getWarningMessage()]) ); } return $result; @@ -88,7 +89,7 @@ public function isReadable($path) $result = @is_readable($this->getScheme() . $path); if ($result === null) { throw new FileSystemException( - new \Magento\Framework\Phrase('Error occurred during execution %1', [$this->getWarningMessage()]) + new \Magento\Framework\Phrase('An error occurred during "%1" execution.', [$this->getWarningMessage()]) ); } return $result; @@ -107,7 +108,7 @@ public function isFile($path) $result = @is_file($this->getScheme() . $path); if ($result === null) { throw new FileSystemException( - new \Magento\Framework\Phrase('Error occurred during execution %1', [$this->getWarningMessage()]) + new \Magento\Framework\Phrase('An error occurred during "%1" execution.', [$this->getWarningMessage()]) ); } return $result; @@ -126,7 +127,7 @@ public function isDirectory($path) $result = @is_dir($this->getScheme() . $path); if ($result === null) { throw new FileSystemException( - new \Magento\Framework\Phrase('Error occurred during execution %1', [$this->getWarningMessage()]) + new \Magento\Framework\Phrase('An error occurred during "%1" execution.', [$this->getWarningMessage()]) ); } return $result; @@ -148,7 +149,7 @@ public function fileGetContents($path, $flag = null, $context = null) if (false === $result) { throw new FileSystemException( new \Magento\Framework\Phrase( - 'Cannot read contents from file "%1" %2', + 'The contents from the "%1" file can\'t be read. %2', [$path, $this->getWarningMessage()] ) ); @@ -169,7 +170,7 @@ public function isWritable($path) $result = @is_writable($this->getScheme() . $path); if ($result === null) { throw new FileSystemException( - new \Magento\Framework\Phrase('Error occurred during execution %1', [$this->getWarningMessage()]) + new \Magento\Framework\Phrase('An error occurred during "%1" execution.', [$this->getWarningMessage()]) ); } return $result; @@ -356,7 +357,7 @@ public function symlink($source, $destination, DriverInterface $targetDriver = n if (!$result) { throw new FileSystemException( new \Magento\Framework\Phrase( - 'Cannot create a symlink for "%1" and place it to "%2" %3', + 'A symlink for "%1" can\'t be created and placed to "%2". %3', [ $source, $destination, @@ -380,7 +381,10 @@ public function deleteFile($path) $result = @unlink($this->getScheme() . $path); if (!$result) { throw new FileSystemException( - new \Magento\Framework\Phrase('The file "%1" cannot be deleted %2', [$path, $this->getWarningMessage()]) + new \Magento\Framework\Phrase( + 'The "%1" file can\'t be deleted. %2', + [$path, $this->getWarningMessage()] + ) ); } return $result; @@ -431,7 +435,7 @@ public function changePermissions($path, $permissions) if (!$result) { throw new FileSystemException( new \Magento\Framework\Phrase( - 'Cannot change permissions for path "%1" %2', + 'The permissions can\'t be changed for the "%1" path. %2.', [$path, $this->getWarningMessage()] ) ); @@ -459,7 +463,7 @@ public function changePermissionsRecursively($path, $dirPermissions, $filePermis if (!$result) { throw new FileSystemException( new \Magento\Framework\Phrase( - 'Cannot change permissions for path "%1" %2', + 'The permissions can\'t be changed for the "%1" path. %2.', [$path, $this->getWarningMessage()] ) ); @@ -481,7 +485,7 @@ public function changePermissionsRecursively($path, $dirPermissions, $filePermis if (!$result) { throw new FileSystemException( new \Magento\Framework\Phrase( - 'Cannot change permissions for path "%1" %2', + 'The permissions can\'t be changed for the "%1" path. %2.', [$path, $this->getWarningMessage()] ) ); @@ -508,7 +512,7 @@ public function touch($path, $modificationTime = null) if (!$result) { throw new FileSystemException( new \Magento\Framework\Phrase( - 'The file or directory "%1" cannot be touched %2', + 'The "%1" file or directory can\'t be touched. %2', [$path, $this->getWarningMessage()] ) ); @@ -531,7 +535,7 @@ public function filePutContents($path, $content, $mode = null) if (!$result) { throw new FileSystemException( new \Magento\Framework\Phrase( - 'The specified "%1" file could not be written %2', + 'The specified "%1" file couldn\'t be written. %2', [$path, $this->getWarningMessage()] ) ); @@ -613,7 +617,10 @@ public function fileGetCsv($resource, $length = 0, $delimiter = ',', $enclosure $result = @fgetcsv($resource, $length, $delimiter, $enclosure, $escape); if ($result === null) { throw new FileSystemException( - new \Magento\Framework\Phrase('Wrong CSV handle %1', [$this->getWarningMessage()]) + new \Magento\Framework\Phrase( + 'The "%1" CSV handle is incorrect. Verify the handle and try again.', + [$this->getWarningMessage()] + ) ); } return $result; @@ -631,7 +638,7 @@ public function fileTell($resource) $result = @ftell($resource); if ($result === null) { throw new FileSystemException( - new \Magento\Framework\Phrase('Error occurred during execution %1', [$this->getWarningMessage()]) + new \Magento\Framework\Phrase('An error occurred during "%1" execution.', [$this->getWarningMessage()]) ); } return $result; @@ -652,7 +659,7 @@ public function fileSeek($resource, $offset, $whence = SEEK_SET) if ($result === -1) { throw new FileSystemException( new \Magento\Framework\Phrase( - 'Error occurred during execution of fileSeek %1', + 'An error occurred during "%1" fileSeek execution.', [$this->getWarningMessage()] ) ); @@ -684,7 +691,7 @@ public function fileClose($resource) if (!$result) { throw new FileSystemException( new \Magento\Framework\Phrase( - 'Error occurred during execution of fileClose %1', + 'An error occurred during "%1" fileClose execution.', [$this->getWarningMessage()] ) ); @@ -710,7 +717,7 @@ public function fileWrite($resource, $data) } if (false === $fwrite) { $this->fileSystemException( - 'Error occurred during execution of fileWrite %1', + 'An error occurred during "%1" fileWrite execution.', [$this->getWarningMessage()] ); } @@ -763,7 +770,7 @@ public function filePutCsv($resource, array $data, $delimiter = ',', $enclosure if (!$result) { throw new FileSystemException( new \Magento\Framework\Phrase( - 'Error occurred during execution of filePutCsv %1', + 'An error occurred during "%1" filePutCsv execution.', [$this->getWarningMessage()] ) ); @@ -784,7 +791,7 @@ public function fileFlush($resource) if (!$result) { throw new FileSystemException( new \Magento\Framework\Phrase( - 'Error occurred during execution of fileFlush %1', + 'An error occurred during "%1" fileFlush execution.', [$this->getWarningMessage()] ) ); @@ -806,7 +813,7 @@ public function fileLock($resource, $lockMode = LOCK_EX) if (!$result) { throw new FileSystemException( new \Magento\Framework\Phrase( - 'Error occurred during execution of fileLock %1', + 'An error occurred during "%1" fileLock execution.', [$this->getWarningMessage()] ) ); @@ -827,7 +834,7 @@ public function fileUnlock($resource) if (!$result) { throw new FileSystemException( new \Magento\Framework\Phrase( - 'Error occurred during execution of fileUnlock %1', + 'An error occurred during "%1" fileUnlock execution.', [$this->getWarningMessage()] ) ); diff --git a/lib/internal/Magento/Framework/Filesystem/Driver/Http.php b/lib/internal/Magento/Framework/Filesystem/Driver/Http.php index 09d5372291a0a..236585fa61384 100644 --- a/lib/internal/Magento/Framework/Filesystem/Driver/Http.php +++ b/lib/internal/Magento/Framework/Filesystem/Driver/Http.php @@ -5,6 +5,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\Filesystem\Driver; use Magento\Framework\Exception\FileSystemException; @@ -91,7 +92,7 @@ public function fileGetContents($path, $flags = null, $context = null) if (false === $result) { throw new FileSystemException( new \Magento\Framework\Phrase( - 'Cannot read contents from file "%1" %2', + 'The contents from the "%1" file can\'t be read. %2', [$path, $this->getWarningMessage()] ) ); @@ -115,7 +116,7 @@ public function filePutContents($path, $content, $mode = null, $context = null) if (!$result) { throw new FileSystemException( new \Magento\Framework\Phrase( - 'The specified "%1" file could not be written %2', + 'The specified "%1" file couldn\'t be written. %2', [$path, $this->getWarningMessage()] ) ); @@ -137,7 +138,9 @@ public function fileOpen($path, $mode) $urlProp = $this->parseUrl($this->getScheme() . $path); if (false === $urlProp) { - throw new FileSystemException(new \Magento\Framework\Phrase('Please correct the download URL.')); + throw new FileSystemException( + new \Magento\Framework\Phrase('The download URL is incorrect. Verify and try again.') + ); } $hostname = $urlProp['host']; diff --git a/lib/internal/Magento/Framework/Filesystem/File/Read.php b/lib/internal/Magento/Framework/Filesystem/File/Read.php index e475bea31c380..f48e50b7d693d 100644 --- a/lib/internal/Magento/Framework/Filesystem/File/Read.php +++ b/lib/internal/Magento/Framework/Filesystem/File/Read.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\Filesystem\File; use Magento\Framework\Filesystem\DriverInterface; @@ -72,7 +73,9 @@ protected function open() protected function assertValid() { if (!$this->driver->isExists($this->path)) { - throw new FileSystemException(new \Magento\Framework\Phrase('The file "%1" doesn\'t exist', [$this->path])); + throw new FileSystemException( + new \Magento\Framework\Phrase('The "%1" file doesn\'t exist.', [$this->path]) + ); } return true; } diff --git a/lib/internal/Magento/Framework/Filesystem/File/Write.php b/lib/internal/Magento/Framework/Filesystem/File/Write.php index 03f8b38a6e930..ea2f3a93d66c0 100644 --- a/lib/internal/Magento/Framework/Filesystem/File/Write.php +++ b/lib/internal/Magento/Framework/Filesystem/File/Write.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\Filesystem\File; use Magento\Framework\Filesystem\DriverInterface; @@ -33,7 +34,9 @@ protected function assertValid() { $fileExists = $this->driver->isExists($this->path); if (!$fileExists && preg_match('/r/', $this->mode)) { - throw new FileSystemException(new \Magento\Framework\Phrase('The file "%1" doesn\'t exist', [$this->path])); + throw new FileSystemException( + new \Magento\Framework\Phrase('The "%1" file doesn\'t exist.', [$this->path]) + ); } elseif ($fileExists && preg_match('/x/', $this->mode)) { throw new FileSystemException(new \Magento\Framework\Phrase('The file "%1" already exists', [$this->path])); } diff --git a/lib/internal/Magento/Framework/Filesystem/Io/Ftp.php b/lib/internal/Magento/Framework/Filesystem/Io/Ftp.php index 2a1938df4d687..1aa9d61f8865a 100644 --- a/lib/internal/Magento/Framework/Filesystem/Io/Ftp.php +++ b/lib/internal/Magento/Framework/Filesystem/Io/Ftp.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\Filesystem\Io; use Magento\Framework\Filesystem\DriverInterface; @@ -78,7 +79,7 @@ public function open(array $args = []) { if (empty($args['host'])) { $this->_error = self::ERROR_EMPTY_HOST; - throw new LocalizedException(new Phrase('Empty host specified')); + throw new LocalizedException(new Phrase('The specified host is empty. Set the host and try again.')); } if (empty($args['port'])) { @@ -111,20 +112,22 @@ public function open(array $args = []) } if (!$this->_conn) { $this->_error = self::ERROR_INVALID_CONNECTION; - throw new LocalizedException(new Phrase('Could not establish FTP connection, invalid host or port')); + throw new LocalizedException( + new Phrase("The FTP connection couldn't be established because of an invalid host or port.") + ); } if (!@ftp_login($this->_conn, $this->_config['user'], $this->_config['password'])) { $this->_error = self::ERROR_INVALID_LOGIN; $this->close(); - throw new LocalizedException(new Phrase('Invalid user name or password')); + throw new LocalizedException(new Phrase('The username or password is invalid. Verify both and try again.')); } if (!empty($this->_config['path'])) { if (!@ftp_chdir($this->_conn, $this->_config['path'])) { $this->_error = self::ERROR_INVALID_PATH; $this->close(); - throw new LocalizedException(new Phrase('Invalid path')); + throw new LocalizedException(new Phrase('The path is invalid. Verify and try again.')); } } @@ -132,7 +135,7 @@ public function open(array $args = []) if (!@ftp_pasv($this->_conn, true)) { $this->_error = self::ERROR_INVALID_MODE; $this->close(); - throw new LocalizedException(new Phrase('Invalid file transfer mode')); + throw new LocalizedException(new Phrase('The file transfer mode is invalid. Verify and try again.')); } } diff --git a/lib/internal/Magento/Framework/Filesystem/Test/Unit/Driver/HttpTest.php b/lib/internal/Magento/Framework/Filesystem/Test/Unit/Driver/HttpTest.php index 51a994dc73ff5..f5ad5b22bdd58 100644 --- a/lib/internal/Magento/Framework/Filesystem/Test/Unit/Driver/HttpTest.php +++ b/lib/internal/Magento/Framework/Filesystem/Test/Unit/Driver/HttpTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\Filesystem\Test\Unit\Driver; use \Magento\Framework\Filesystem\Driver\Http; @@ -130,7 +131,7 @@ public function testFilePutContentsFail() /** * @expectedException \Magento\Framework\Exception\FileSystemException - * @expectedExceptionMessage Please correct the download URL. + * @expectedExceptionMessage The download URL is incorrect. Verify and try again. */ public function testFileOpenInvalidUrl() { diff --git a/lib/internal/Magento/Framework/Model/Entity/RepositoryFactory.php b/lib/internal/Magento/Framework/Model/Entity/RepositoryFactory.php index 341ff9226555f..f439c14b6ece0 100644 --- a/lib/internal/Magento/Framework/Model/Entity/RepositoryFactory.php +++ b/lib/internal/Magento/Framework/Model/Entity/RepositoryFactory.php @@ -50,7 +50,8 @@ public function __construct( public function create($entityType) { if (!isset($this->entities[$entityType])) { - $message = sprintf('Repository for entity type %s is not declared', $entityType); + $message = + sprintf('The repository for the "%s" entity type isn\'t declared. Verify and try again.', $entityType); throw new NotFoundException(new \Magento\Framework\Phrase($message)); } return $this->objectManager->get($this->entities[$entityType]); diff --git a/lib/internal/Magento/Framework/Model/Entity/ScopeResolver.php b/lib/internal/Magento/Framework/Model/Entity/ScopeResolver.php index ff7e359447cd8..f965fe65d3cda 100644 --- a/lib/internal/Magento/Framework/Model/Entity/ScopeResolver.php +++ b/lib/internal/Magento/Framework/Model/Entity/ScopeResolver.php @@ -53,7 +53,13 @@ public function getEntityContext($entityType, $entityData = []) foreach ($metadata->getEntityContext() as $contextProviderClass) { $contextProvider = $this->objectManager->get($contextProviderClass); if (!$contextProvider instanceof ScopeProviderInterface) { - throw new ConfigurationMismatchException(new Phrase('Wrong configuration for type %1', [$entityType])); + throw new ConfigurationMismatchException( + new Phrase( + 'The configuration for the "%1" type is incorrect. ' + . 'Verify the type and configuration and try again.', + [$entityType] + ) + ); } $entityContext[] = $contextProvider->getContext($entityType, $entityData); } diff --git a/lib/internal/Magento/Framework/Model/ResourceModel/Iterator.php b/lib/internal/Magento/Framework/Model/ResourceModel/Iterator.php index a61835133b39f..694c230657965 100644 --- a/lib/internal/Magento/Framework/Model/ResourceModel/Iterator.php +++ b/lib/internal/Magento/Framework/Model/ResourceModel/Iterator.php @@ -62,11 +62,13 @@ protected function _getStatement($query, AdapterInterface $connection = null) if (is_string($query)) { if (!$connection instanceof AdapterInterface) { - throw new LocalizedException(new Phrase('Invalid connection')); + throw new LocalizedException( + new Phrase('The connection is invalid. Verify the connection and try again.') + ); } return $connection->query($query); } - throw new LocalizedException(new Phrase('Invalid query')); + throw new LocalizedException(new Phrase('The query is invalid. Verify the query and try again.')); } } diff --git a/lib/internal/Magento/Framework/Module/DbVersionInfo.php b/lib/internal/Magento/Framework/Module/DbVersionInfo.php index bc4f8eeeca40b..fdc74e412ab9d 100644 --- a/lib/internal/Magento/Framework/Module/DbVersionInfo.php +++ b/lib/internal/Magento/Framework/Module/DbVersionInfo.php @@ -130,17 +130,20 @@ private function getDataInfo($moduleName) * @param string $moduleName * @param string|bool $version * @return bool - * @throws \UnexpectedValueException */ private function isModuleVersionEqual($moduleName, $version) { $module = $this->moduleList->getOne($moduleName); - if (empty($module['setup_version'])) { - throw new \UnexpectedValueException("Setup version for module '$moduleName' is not specified"); + $configVer = isset($module['setup_version']) ? $module['setup_version'] : null; + + if (empty($configVer)) { + /** + * If setup_version was removed, this means that we want to ignore old scripts and do installation only + * with declarative schema and data/schema patches + */ + return true; } - $configVer = $module['setup_version']; - return ($version !== false - && version_compare($configVer, $version) === ModuleDataSetupInterface::VERSION_COMPARE_EQUAL); + return version_compare($configVer, $version) === ModuleDataSetupInterface::VERSION_COMPARE_EQUAL; } } diff --git a/lib/internal/Magento/Framework/Module/Declaration/Converter/Dom.php b/lib/internal/Magento/Framework/Module/Declaration/Converter/Dom.php index 4759ee7c4f3d4..990f72c536dd8 100644 --- a/lib/internal/Magento/Framework/Module/Declaration/Converter/Dom.php +++ b/lib/internal/Magento/Framework/Module/Declaration/Converter/Dom.php @@ -26,12 +26,8 @@ public function convert($source) throw new \Exception('Attribute "name" is required for module node.'); } $moduleData['name'] = $nameNode->nodeValue; - $name = $moduleData['name']; $versionNode = $moduleAttributes->getNamedItem('setup_version'); - if ($versionNode === null) { - throw new \Exception("Attribute 'setup_version' is missing for module '{$name}'."); - } - $moduleData['setup_version'] = $versionNode->nodeValue; + $moduleData['setup_version'] = $versionNode ? $versionNode->nodeValue : null; $moduleData['sequence'] = []; /** @var $childNode \DOMNode */ foreach ($moduleNode->childNodes as $childNode) { diff --git a/lib/internal/Magento/Framework/Module/Dir.php b/lib/internal/Magento/Framework/Module/Dir.php index 936fce3a046b7..77174bb51305d 100644 --- a/lib/internal/Magento/Framework/Module/Dir.php +++ b/lib/internal/Magento/Framework/Module/Dir.php @@ -20,6 +20,7 @@ class Dir const MODULE_I18N_DIR = 'i18n'; const MODULE_VIEW_DIR = 'view'; const MODULE_CONTROLLER_DIR = 'Controller'; + const MODULE_SETUP_DIR = 'Setup'; /**#@-*/ /**#@-*/ @@ -45,12 +46,19 @@ public function getDir($moduleName, $type = '') { $path = $this->componentRegistrar->getPath(ComponentRegistrar::MODULE, $moduleName); + // An empty $type means it's getting the directory of the module itself. + if (empty($type) && !isset($path)) { + // Note: do not throw \LogicException, as it would break backwards-compatibility. + throw new \InvalidArgumentException("Module '$moduleName' is not correctly registered."); + } + if ($type) { if (!in_array($type, [ self::MODULE_ETC_DIR, self::MODULE_I18N_DIR, self::MODULE_VIEW_DIR, - self::MODULE_CONTROLLER_DIR + self::MODULE_CONTROLLER_DIR, + self::MODULE_SETUP_DIR ])) { throw new \InvalidArgumentException("Directory type '{$type}' is not recognized."); } diff --git a/lib/internal/Magento/Framework/Module/ModuleResource.php b/lib/internal/Magento/Framework/Module/ModuleResource.php index ed740d459060e..781e84730d68b 100644 --- a/lib/internal/Magento/Framework/Module/ModuleResource.php +++ b/lib/internal/Magento/Framework/Module/ModuleResource.php @@ -134,4 +134,15 @@ public function setDataVersion($moduleName, $version) $this->getConnection()->insert($this->getMainTable(), $data); } } + + /** + * Flush all class cache + * + * @return void + */ + public function flush() + { + self::$dataVersions = null; + self::$schemaVersions = null; + } } diff --git a/lib/internal/Magento/Framework/Module/Test/Unit/DbVersionInfoTest.php b/lib/internal/Magento/Framework/Module/Test/Unit/DbVersionInfoTest.php index f6c978c3cef96..c36d4bf7d5e93 100644 --- a/lib/internal/Magento/Framework/Module/Test/Unit/DbVersionInfoTest.php +++ b/lib/internal/Magento/Framework/Module/Test/Unit/DbVersionInfoTest.php @@ -65,6 +65,12 @@ public function testIsDbSchemaUpToDate($moduleName, $dbVersion, $expectedResult) ->method('getDbVersion') ->with($moduleName) ->will($this->returnValue($dbVersion)); + $this->moduleList->expects(self::once()) + ->method('getOne') + ->with($moduleName) + ->willReturn( + ['setup_version' => $dbVersion] + ); $this->assertEquals( $expectedResult, $this->dbVersionInfo->isSchemaUpToDate($moduleName) @@ -84,6 +90,12 @@ public function testIsDbDataUpToDate($moduleName, $dbVersion, $expectedResult) ->method('getDataVersion') ->with($moduleName) ->will($this->returnValue($dbVersion)); + $this->moduleList->expects(self::once()) + ->method('getOne') + ->with($moduleName) + ->willReturn( + ['setup_version' => $dbVersion] + ); $this->assertEquals( $expectedResult, $this->dbVersionInfo->isDataUpToDate($moduleName) @@ -142,20 +154,18 @@ public function testGetDbVersionErrors() } /** - * @expectedException \UnexpectedValueException - * @expectedExceptionMessage Setup version for module 'Module_No_Schema' is not specified + * Test is DB schema up to date for module with no schema */ public function testIsDbSchemaUpToDateException() { - $this->dbVersionInfo->isSchemaUpToDate('Module_No_Schema'); + $this->assertTrue($this->dbVersionInfo->isSchemaUpToDate('Module_No_Schema')); } /** - * @expectedException \UnexpectedValueException - * @expectedExceptionMessage Setup version for module 'Module_No_Schema' is not specified + * Test is DB Data up to date for module with no schema */ public function testIsDbDataUpToDateException() { - $this->dbVersionInfo->isDataUpToDate('Module_No_Schema'); + $this->assertTrue($this->dbVersionInfo->isDataUpToDate('Module_No_Schema')); } } diff --git a/lib/internal/Magento/Framework/Module/Test/Unit/Declaration/Converter/DomTest.php b/lib/internal/Magento/Framework/Module/Test/Unit/Declaration/Converter/DomTest.php index ec9b41ff1b957..bf878257c89de 100644 --- a/lib/internal/Magento/Framework/Module/Test/Unit/Declaration/Converter/DomTest.php +++ b/lib/internal/Magento/Framework/Module/Test/Unit/Declaration/Converter/DomTest.php @@ -47,7 +47,7 @@ public function convertWithInvalidDomDataProvider() return [ 'Module node without "name" attribute' => ['<?xml version="1.0"?><config><module /></config>'], 'Sequence module node without "name" attribute' => [ - '<?xml version="1.0"?><config><module name="Module_One" setup_version="1.0.0.0">' . + '<?xml version="1.0"?><config><module name="Module_One" >' . '<sequence><module/></sequence></module></config>', ], ]; diff --git a/lib/internal/Magento/Framework/Module/Test/Unit/Declaration/Converter/_files/converted_valid_module.php b/lib/internal/Magento/Framework/Module/Test/Unit/Declaration/Converter/_files/converted_valid_module.php index 810052fe5e237..d572cf2814fc9 100644 --- a/lib/internal/Magento/Framework/Module/Test/Unit/Declaration/Converter/_files/converted_valid_module.php +++ b/lib/internal/Magento/Framework/Module/Test/Unit/Declaration/Converter/_files/converted_valid_module.php @@ -6,12 +6,17 @@ return [ 'Module_One' => [ 'name' => 'Module_One', - 'setup_version' => '1.0.0.0', + 'setup_version' => null, + 'sequence' => [], + ], + 'Module_OneAndHalf' => [ + 'name' => 'Module_OneAndHalf', + 'setup_version' => '2.0', 'sequence' => [], ], 'Module_Two' => [ 'name' => 'Module_Two', - 'setup_version' => '2.0.0.0', + 'setup_version' => null, 'sequence' => ['Module_One'], ] ]; diff --git a/lib/internal/Magento/Framework/Module/Test/Unit/Declaration/Converter/_files/valid_module.xml b/lib/internal/Magento/Framework/Module/Test/Unit/Declaration/Converter/_files/valid_module.xml index cec18c9bae7cc..e55ebcdfd7c2f 100644 --- a/lib/internal/Magento/Framework/Module/Test/Unit/Declaration/Converter/_files/valid_module.xml +++ b/lib/internal/Magento/Framework/Module/Test/Unit/Declaration/Converter/_files/valid_module.xml @@ -7,9 +7,11 @@ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> <!-- commented text --> - <module name="Module_One" setup_version="1.0.0.0"> + <module name="Module_One"> </module> - <module name="Module_Two" setup_version="2.0.0.0"> + <module name="Module_OneAndHalf" setup_version="2.0"> + </module> + <module name="Module_Two"> <sequence> <module name="Module_One" /> </sequence> diff --git a/lib/internal/Magento/Framework/Module/Test/Unit/DirTest.php b/lib/internal/Magento/Framework/Module/Test/Unit/DirTest.php index 335228888cc4b..a1c891df7bcb4 100644 --- a/lib/internal/Magento/Framework/Module/Test/Unit/DirTest.php +++ b/lib/internal/Magento/Framework/Module/Test/Unit/DirTest.php @@ -46,6 +46,16 @@ public function testGetDirModuleSubDir() $this->assertEquals('/Test/Module/etc', $this->_model->getDir('Test_Module', 'etc')); } + public function testGetSetupDirModule() + { + $this->moduleRegistryMock->expects($this->once()) + ->method('getPath') + ->with(ComponentRegistrar::MODULE, 'Test_Module') + ->willReturn('/Test/Module'); + + $this->assertEquals('/Test/Module/Setup', $this->_model->getDir('Test_Module', 'Setup')); + } + /** * @expectedException \InvalidArgumentException * @expectedExceptionMessage Directory type 'unknown' is not recognized @@ -59,4 +69,17 @@ public function testGetDirModuleSubDirUnknown() $this->_model->getDir('Test_Module', 'unknown'); } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage Module 'Test Module' is not correctly registered. + */ + public function testGetDirModuleIncorrectlyRegistered() + { + $this->moduleRegistryMock->expects($this->once()) + ->method('getPath') + ->with($this->identicalTo(ComponentRegistrar::MODULE), $this->identicalTo('Test Module')) + ->willReturn(null); + $this->_model->getDir('Test Module'); + } } diff --git a/lib/internal/Magento/Framework/Module/etc/module.xsd b/lib/internal/Magento/Framework/Module/etc/module.xsd index 839bddb982c73..ffc4101e70700 100644 --- a/lib/internal/Magento/Framework/Module/etc/module.xsd +++ b/lib/internal/Magento/Framework/Module/etc/module.xsd @@ -43,7 +43,7 @@ </xs:element> </xs:all> <xs:attribute name="name" type="moduleName" use="required" /> - <xs:attribute name="setup_version" type="setupVersion" use="required" /> + <xs:attribute name="setup_version" type="setupVersion" use="optional" /> </xs:complexType> <xs:complexType name="moduleSequence"> 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 e278de0fff914..1bcf48d8b0a5e 100644 --- a/lib/internal/Magento/Framework/Mview/Test/Unit/View/ChangelogTest.php +++ b/lib/internal/Magento/Framework/Mview/Test/Unit/View/ChangelogTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\Mview\Test\Unit\View; class ChangelogTest extends \PHPUnit\Framework\TestCase @@ -45,7 +46,7 @@ public function testInstanceOf() /** * @expectedException \Exception - * @expectedExceptionMessage Write DB connection is not available + * @expectedExceptionMessage The write connection to the database isn't available. Please try again later. */ public function testCheckConnectionException() { diff --git a/lib/internal/Magento/Framework/Mview/View/Changelog.php b/lib/internal/Magento/Framework/Mview/View/Changelog.php index 91caf66228360..cdb36a67a1cc4 100644 --- a/lib/internal/Magento/Framework/Mview/View/Changelog.php +++ b/lib/internal/Magento/Framework/Mview/View/Changelog.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\Mview\View; use Magento\Framework\App\ResourceConnection; @@ -58,7 +59,7 @@ public function __construct(\Magento\Framework\App\ResourceConnection $resource) protected function checkConnection() { if (!$this->connection) { - throw new \Exception('Write DB connection is not available'); + throw new \Exception("The write connection to the database isn't available. Please try again later."); } } diff --git a/lib/internal/Magento/Framework/Oauth/Oauth.php b/lib/internal/Magento/Framework/Oauth/Oauth.php index 247b0d4a53009..5e48fb5ed30f9 100644 --- a/lib/internal/Magento/Framework/Oauth/Oauth.php +++ b/lib/internal/Magento/Framework/Oauth/Oauth.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\Oauth; use Magento\Framework\Encryption\Helper\Security; @@ -198,7 +199,7 @@ protected function _validateSignature($params, $consumerSecret, $httpMethod, $re ); if (!Security::compareStrings($calculatedSign, $params['oauth_signature'])) { - throw new Exception(new Phrase('Invalid signature')); + throw new Exception(new Phrase('The signatire is invalid. Verify and try again.')); } } @@ -213,7 +214,7 @@ protected function _validateVersionParam($version) { // validate version if specified if ('1.0' != $version) { - throw new OauthInputException(new Phrase('OAuth version %1 is not supported', [$version])); + throw new OauthInputException(new Phrase('The "%1" Oauth version isn\'t supported.', [$version])); } } @@ -250,7 +251,7 @@ protected function _validateProtocolParams($protocolParams, $requiredParams = [] $protocolParams['oauth_token'] ) ) { - throw new OauthInputException(new Phrase('Token is not the correct length')); + throw new OauthInputException(new Phrase('The token length is invalid. Check the length and try again.')); } // Validate signature method. @@ -284,7 +285,9 @@ protected function _checkRequiredParams($protocolParams, $requiredParams) $exception = new OauthInputException(); foreach ($requiredParams as $param) { if (!isset($protocolParams[$param])) { - $exception->addError(new Phrase('%fieldName is a required field.', ['fieldName' => $param])); + $exception->addError( + new Phrase('"%fieldName" is required. Enter and try again.', ['fieldName' => $param]) + ); } } if ($exception->wasErrorAdded()) { diff --git a/lib/internal/Magento/Framework/Oauth/Test/Unit/OauthInputExceptionTest.php b/lib/internal/Magento/Framework/Oauth/Test/Unit/OauthInputExceptionTest.php index 72bf2fe7a6129..f67fd37c49662 100644 --- a/lib/internal/Magento/Framework/Oauth/Test/Unit/OauthInputExceptionTest.php +++ b/lib/internal/Magento/Framework/Oauth/Test/Unit/OauthInputExceptionTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\Oauth\Test\Unit; use \Magento\Framework\Oauth\OauthInputException; @@ -17,12 +18,14 @@ public function testGetAggregatedErrorMessage() { $exception = new OauthInputException(); foreach (['field1', 'field2'] as $param) { - $exception->addError(new Phrase('%fieldName is a required field.', ['fieldName' => $param])); + $exception->addError( + new Phrase('"%fieldName" is required. Enter and try again.', ['fieldName' => $param]) + ); } $exception->addError(new Phrase('Message with period.')); $this->assertEquals( - 'field1 is a required field, field2 is a required field, Message with period', + '"field1" is required. Enter and try again, "field2" is required. Enter and try again, Message with period', $exception->getAggregatedErrorMessage() ); } diff --git a/lib/internal/Magento/Framework/ObjectManager/Code/Generator/Repository.php b/lib/internal/Magento/Framework/ObjectManager/Code/Generator/Repository.php index b1cdb53288216..362cbb2e887c7 100644 --- a/lib/internal/Magento/Framework/ObjectManager/Code/Generator/Repository.php +++ b/lib/internal/Magento/Framework/ObjectManager/Code/Generator/Repository.php @@ -226,14 +226,18 @@ protected function _getGetMethod() /** @var ParameterReflection $parameterReflection */ $parameterReflection = $methodReflection->getParameters()[0]; $body = "if (!\$id) {\n" - . " throw new \\" . InputException::class . "(new \\Magento\\Framework\\Phrase('ID required'));\n" + . " throw new \\" . InputException::class . "(\n" + . " new \\Magento\\Framework\\Phrase('An ID is needed. Set the ID and try again.')\n" + . " );\n" . "}\n" . "if (!isset(\$this->registry[\$id])) {\n" . " \$entity = \$this->" . $this->_getSourcePersistorPropertyName() . "->loadEntity(\$id);\n" . " if (!\$entity->getId()) {\n" . " throw new \\" . NoSuchEntityException::class . "(\n" - . " new \\Magento\\Framework\\Phrase('Requested entity doesn\\'t exist')\n" + . " new \\Magento\\Framework\\Phrase(\n" + . " 'The entity that was requested doesn\'t exist. Verify the entity and try again.'\n" + . " )\n" . " );\n" . " }\n" . " \$this->registry[\$id] = \$entity;\n" diff --git a/lib/internal/Magento/Framework/ObjectManager/Test/Unit/Code/Generator/_files/SampleRepository.txt b/lib/internal/Magento/Framework/ObjectManager/Test/Unit/Code/Generator/_files/SampleRepository.txt index 222d5c7ffc6d1..5cc2e35598b89 100644 --- a/lib/internal/Magento/Framework/ObjectManager/Test/Unit/Code/Generator/_files/SampleRepository.txt +++ b/lib/internal/Magento/Framework/ObjectManager/Test/Unit/Code/Generator/_files/SampleRepository.txt @@ -71,13 +71,17 @@ class SampleRepository implements SampleRepositoryInterface public function get($id) { if (!$id) { - throw new \Magento\Framework\Exception\InputException(new \Magento\Framework\Phrase('ID required')); + throw new \Magento\Framework\Exception\InputException( + new \Magento\Framework\Phrase('An ID is needed. Set the ID and try again.') + ); } if (!isset($this->registry[$id])) { $entity = $this->sampleInterfacePersistor->loadEntity($id); if (!$entity->getId()) { throw new \Magento\Framework\Exception\NoSuchEntityException( - new \Magento\Framework\Phrase('Requested entity doesn\'t exist') + new \Magento\Framework\Phrase( + 'The entity that was requested doesn\'t exist. Verify the entity and try again.' + ) ); } $this->registry[$id] = $entity; diff --git a/lib/internal/Magento/Framework/ObjectManager/Test/Unit/Code/Generator/_files/TSampleRepository.txt b/lib/internal/Magento/Framework/ObjectManager/Test/Unit/Code/Generator/_files/TSampleRepository.txt index e4067e70670a4..bb2da3499c14d 100644 --- a/lib/internal/Magento/Framework/ObjectManager/Test/Unit/Code/Generator/_files/TSampleRepository.txt +++ b/lib/internal/Magento/Framework/ObjectManager/Test/Unit/Code/Generator/_files/TSampleRepository.txt @@ -71,13 +71,17 @@ class TSampleRepository implements TSampleRepositoryInterface public function get(int $id) : \Magento\Framework\ObjectManager\Code\Generator\TSampleInterface { if (!$id) { - throw new \Magento\Framework\Exception\InputException(new \Magento\Framework\Phrase('ID required')); + throw new \Magento\Framework\Exception\InputException( + new \Magento\Framework\Phrase('An ID is needed. Set the ID and try again.') + ); } if (!isset($this->registry[$id])) { $entity = $this->tSampleInterfacePersistor->loadEntity($id); if (!$entity->getId()) { throw new \Magento\Framework\Exception\NoSuchEntityException( - new \Magento\Framework\Phrase('Requested entity doesn\'t exist') + new \Magento\Framework\Phrase( + 'The entity that was requested doesn\'t exist. Verify the entity and try again.' + ) ); } $this->registry[$id] = $entity; diff --git a/lib/internal/Magento/Framework/Reflection/AttributeTypeResolver.php b/lib/internal/Magento/Framework/Reflection/AttributeTypeResolver.php index f851dbcbc87f2..8af8088ccdb65 100644 --- a/lib/internal/Magento/Framework/Reflection/AttributeTypeResolver.php +++ b/lib/internal/Magento/Framework/Reflection/AttributeTypeResolver.php @@ -48,7 +48,10 @@ public function resolveObjectType($attributeCode, $value, $context) $output = $this->typeProcessor->getArrayItemType($type); if (!(class_exists($output) || interface_exists($output))) { throw new \LogicException( - sprintf('Class "%s" does not exist. Please note that namespace must be specified.', $type) + sprintf( + 'The "%s" class doesn\'t exist and the namespace must be specified. Verify and try again.', + $type + ) ); } } diff --git a/lib/internal/Magento/Framework/Reflection/Test/Unit/AttributeTypeResolverTest.php b/lib/internal/Magento/Framework/Reflection/Test/Unit/AttributeTypeResolverTest.php index f1e1368cafd0b..1f6fa25a51f22 100644 --- a/lib/internal/Magento/Framework/Reflection/Test/Unit/AttributeTypeResolverTest.php +++ b/lib/internal/Magento/Framework/Reflection/Test/Unit/AttributeTypeResolverTest.php @@ -84,7 +84,6 @@ public function testResolveObjectTypeWithConfiguredAttribute() /** * @expectedException \LogicException - * @expectedExceptionMessage Class "\Some\Class" does not exist. Please note that namespace must be specified. */ public function testResolveObjectTypeWithConfiguredAttributeAndNonExistedClass() { @@ -106,5 +105,9 @@ public function testResolveObjectTypeWithConfiguredAttributeAndNonExistedClass() $this->configMock->expects($this->once())->method('get')->willReturn($config); $this->model->resolveObjectType($code, $value, $context); + + $this->expectExceptionMessage( + 'The "\Some\Class" class doesn\'t exist and the namespace must be specified. Verify and try again.' + ); } } diff --git a/lib/internal/Magento/Framework/Reflection/Test/Unit/TypeProcessorTest.php b/lib/internal/Magento/Framework/Reflection/Test/Unit/TypeProcessorTest.php index 9ee4d148d2fb5..4b5cd49dc2fe4 100644 --- a/lib/internal/Magento/Framework/Reflection/Test/Unit/TypeProcessorTest.php +++ b/lib/internal/Magento/Framework/Reflection/Test/Unit/TypeProcessorTest.php @@ -55,7 +55,7 @@ public function testSetTypesData() /** * @expectedException \InvalidArgumentException - * @expectedExceptionMessage Data type "NonExistentType" is not declared. + * @expectedExceptionMessage The "NonExistentType" data type isn't declared. Verify the type and try again. */ public function testGetTypeDataInvalidArgumentException() { @@ -160,7 +160,7 @@ public function testTranslateTypeName() /** * @expectedException \InvalidArgumentException - * @expectedExceptionMessage Invalid parameter type "\Magento\TestModule3\V1\Parameter[]". + * @expectedExceptionMessage The "\Magento\TestModule3\V1\Parameter[]" parameter type is invalid. Verify the parameter and try again. */ public function testTranslateTypeNameInvalidArgumentException() { @@ -213,7 +213,9 @@ public function testProcessSimpleTypeStringArrayToIntArray() public function testProcessSimpleTypeException($value, $type) { $this->expectException( - SerializationException::class, 'Invalid type for value: "' . $value . '". Expected Type: "' . $type . '"' + SerializationException::class, + 'The "' + . $value . '" value\'s type is invalid. The "' . $type . '" type was expected. Verify and try again.' ); $this->_typeProcessor->processSimpleAndAnyType($value, $type); } @@ -228,7 +230,7 @@ public static function processSimpleTypeExceptionProvider() /** * @expectedException \Magento\Framework\Exception\SerializationException - * @expectedExceptionMessage Invalid type for value: "integer". Expected Type: "int[]". + * @expectedExceptionMessage The "integer" value's type is invalid. The "int[]" type was expected. Verify and try again. */ public function testProcessSimpleTypeInvalidType() { diff --git a/lib/internal/Magento/Framework/Reflection/TypeProcessor.php b/lib/internal/Magento/Framework/Reflection/TypeProcessor.php index 74c1bc95b208b..80285853b43c6 100644 --- a/lib/internal/Magento/Framework/Reflection/TypeProcessor.php +++ b/lib/internal/Magento/Framework/Reflection/TypeProcessor.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\Reflection; use Magento\Framework\Exception\SerializationException; @@ -99,7 +100,9 @@ public function setTypesData($typesData) public function getTypeData($typeName) { if (!isset($this->_types[$typeName])) { - throw new \InvalidArgumentException(sprintf('Data type "%s" is not declared.', $typeName)); + throw new \InvalidArgumentException( + sprintf('The "%s" data type isn\'t declared. Verify the type and try again.', $typeName) + ); } return $this->_types[$typeName]; } @@ -137,7 +140,10 @@ public function register($type) $typeSimple = $this->getArrayItemType($type); if (!(class_exists($typeSimple) || interface_exists($typeSimple))) { throw new \LogicException( - sprintf('Class "%s" does not exist. Please note that namespace must be specified.', $type) + sprintf( + 'The "%s" class doesn\'t exist and the namespace must be specified. Verify and try again.', + $type + ) ); } $complexTypeName = $this->translateTypeName($type); @@ -167,7 +173,7 @@ protected function _processComplexType($class) } else { if (!(class_exists($class) || interface_exists($class))) { throw new \InvalidArgumentException( - sprintf('Could not load the "%s" class as parameter type.', $class) + sprintf('The "%s" class couldn\'t load as a parameter type.', $class) ); } $reflection = new ClassReflection($class); @@ -425,7 +431,9 @@ public function translateTypeName($class) return ucfirst($moduleNamespace . $moduleName . implode('', $typeNameParts)); } - throw new \InvalidArgumentException(sprintf('Invalid parameter type "%s".', $class)); + throw new \InvalidArgumentException( + sprintf('The "%s" parameter type is invalid. Verify the parameter and try again.', $class) + ); } /** @@ -464,7 +472,8 @@ public function processSimpleAndAnyType($value, $type) if ($value !== null && !settype($value[$key], $arrayItemType)) { throw new SerializationException( new Phrase( - 'Invalid type for value: "%value". Expected Type: "%type".', + 'The "%value" value\'s type is invalid. The "%type" type was expected. ' + . 'Verify and try again.', ['value' => $value, 'type' => $type] ) ); @@ -476,7 +485,7 @@ public function processSimpleAndAnyType($value, $type) if ($value !== null && !$this->isTypeAny($type) && !$this->setType($value, $type)) { throw new SerializationException( new Phrase( - 'Invalid type for value: "%value". Expected Type: "%type".', + 'The "%value" value\'s type is invalid. The "%type" type was expected. Verify and try again.', ['value' => (string)$value, 'type' => $type] ) ); @@ -484,7 +493,7 @@ public function processSimpleAndAnyType($value, $type) } elseif (!$this->isTypeAny($type)) { throw new SerializationException( new Phrase( - 'Invalid type for value: "%value". Expected Type: "%type".', + 'The "%value" value\'s type is invalid. The "%type" type was expected. Verify and try again.', ['value' => gettype($value), 'type' => $type] ) ); diff --git a/lib/internal/Magento/Framework/Search/Dynamic/Algorithm/Repository.php b/lib/internal/Magento/Framework/Search/Dynamic/Algorithm/Repository.php index 3a964db113ef0..c2d7e4025b3b3 100644 --- a/lib/internal/Magento/Framework/Search/Dynamic/Algorithm/Repository.php +++ b/lib/internal/Magento/Framework/Search/Dynamic/Algorithm/Repository.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\Search\Dynamic\Algorithm; use Magento\Framework\Exception\LocalizedException; @@ -53,7 +54,7 @@ public function get($algorithmType, array $data = []) if (!isset($this->instances[$algorithmType])) { if (!isset($this->algorithms[$algorithmType])) { throw new LocalizedException( - new \Magento\Framework\Phrase('%1 was not found in algorithms', [$algorithmType]) + new \Magento\Framework\Phrase("The %1 value wasn't found in the algorithms.", [$algorithmType]) ); } diff --git a/lib/internal/Magento/Framework/Search/Request/Cleaner.php b/lib/internal/Magento/Framework/Search/Request/Cleaner.php index 984065d1e2a2c..c015f90751a23 100644 --- a/lib/internal/Magento/Framework/Search/Request/Cleaner.php +++ b/lib/internal/Magento/Framework/Search/Request/Cleaner.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\Search\Request; use Magento\Framework\Exception\StateException; @@ -60,7 +61,9 @@ public function clean(array $requestData) $this->clear(); if (empty($requestData['queries']) && empty($requestData['filters'])) { - throw new EmptyRequestDataException(new Phrase('Request query and filters are not set')); + throw new EmptyRequestDataException( + new Phrase("The request query and filters aren't set. Verify the query and filters and try again.") + ); } return $requestData; @@ -82,7 +85,7 @@ private function cleanQuery($queryName) throw new \Exception('Query ' . $queryName . ' does not exist'); } elseif (in_array($queryName, $this->mappedQueries)) { throw new StateException( - new Phrase('Cycle found. Query %1 already used in request hierarchy', [$queryName]) + new Phrase('A cycle was found. The "%1" query is already used in the request hierarchy.', [$queryName]) ); } $this->mappedQueries[] = $queryName; @@ -163,7 +166,10 @@ private function cleanFilter($filterName) throw new \Exception('Filter ' . $filterName . ' does not exist'); } elseif (in_array($filterName, $this->mappedFilters)) { throw new StateException( - new Phrase('Cycle found. Filter %1 already used in request hierarchy', [$filterName]) + new Phrase( + 'A cycle was found. The "%1" filter is already used in the request hierarchy.', + [$filterName] + ) ); } $this->mappedFilters[] = $filterName; diff --git a/lib/internal/Magento/Framework/Search/Request/Mapper.php b/lib/internal/Magento/Framework/Search/Request/Mapper.php index 797d38ac7d39b..7586444d4b197 100644 --- a/lib/internal/Magento/Framework/Search/Request/Mapper.php +++ b/lib/internal/Magento/Framework/Search/Request/Mapper.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\Search\Request; use Magento\Framework\Exception\StateException; @@ -114,7 +115,7 @@ private function mapQuery($queryName) throw new \Exception('Query ' . $queryName . ' does not exist'); } elseif (in_array($queryName, $this->mappedQueries)) { throw new StateException( - new Phrase('Cycle found. Query %1 already used in request hierarchy', [$queryName]) + new Phrase('A cycle was found. The "%1" query is already used in the request hierarchy.', [$queryName]) ); } $this->mappedQueries[] = $queryName; @@ -183,7 +184,10 @@ private function mapFilter($filterName) throw new \Exception('Filter ' . $filterName . ' does not exist'); } elseif (in_array($filterName, $this->mappedFilters)) { throw new StateException( - new Phrase('Cycle found. Filter %1 already used in request hierarchy', [$filterName]) + new Phrase( + 'A cycle was found. The "%1" filter is already used in the request hierarchy.', + [$filterName] + ) ); } $this->mappedFilters[] = $filterName; @@ -351,7 +355,7 @@ public function getBuckets() ); break; default: - throw new StateException(new Phrase('Invalid bucket type')); + throw new StateException(new Phrase('The bucket type is invalid. Verify and try again.')); break; } $buckets[] = $bucket; diff --git a/lib/internal/Magento/Framework/Search/Test/Unit/Request/CleanerTest.php b/lib/internal/Magento/Framework/Search/Test/Unit/Request/CleanerTest.php index 42667b4e171c0..6902dfc70d2c6 100644 --- a/lib/internal/Magento/Framework/Search/Test/Unit/Request/CleanerTest.php +++ b/lib/internal/Magento/Framework/Search/Test/Unit/Request/CleanerTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\Search\Test\Unit\Request; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; @@ -259,7 +260,7 @@ public function testCleanFilterType() /** * @expectedException \Magento\Framework\Exception\StateException - * @expectedExceptionMessage Cycle found. Query filtered_query already used in request hierarchy + * @expectedExceptionMessage A cycle was found. The "filtered_query" query is already used in the request hierarchy. */ public function testCleanQueryCycle() { @@ -338,7 +339,7 @@ public function testCleanQueryNotExists() /** * @expectedException \Magento\Framework\Search\Request\EmptyRequestDataException - * @expectedExceptionMessage Request query and filters are not set + * @expectedExceptionMessage The request query and filters aren't set. Verify the query and filters and try again. */ public function testCleanEmptyQueryAndFilter() { diff --git a/lib/internal/Magento/Framework/Session/SaveHandler/DbTable.php b/lib/internal/Magento/Framework/Session/SaveHandler/DbTable.php index 67ae707860640..6f5937e08455d 100644 --- a/lib/internal/Magento/Framework/Session/SaveHandler/DbTable.php +++ b/lib/internal/Magento/Framework/Session/SaveHandler/DbTable.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\Session\SaveHandler; use Magento\Framework\App\ResourceConnection; @@ -49,10 +50,14 @@ public function __construct(\Magento\Framework\App\ResourceConnection $resource) protected function checkConnection() { if (!$this->connection) { - throw new SessionException(new Phrase('Write DB connection is not available')); + throw new SessionException( + new Phrase("The write connection to the database isn't available. Please try again later.") + ); } if (!$this->connection->isTableExists($this->_sessionTable)) { - throw new SessionException(new Phrase('DB storage table does not exist')); + throw new SessionException( + new Phrase("The database storage table doesn't exist. Verify the table and try again.") + ); } } diff --git a/lib/internal/Magento/Framework/Session/SaveHandler/Redis/Config.php b/lib/internal/Magento/Framework/Session/SaveHandler/Redis/Config.php index 724f949ca5b23..5a4ed1700da55 100644 --- a/lib/internal/Magento/Framework/Session/SaveHandler/Redis/Config.php +++ b/lib/internal/Magento/Framework/Session/SaveHandler/Redis/Config.php @@ -100,6 +100,26 @@ class Config implements \Cm\RedisSession\Handler\ConfigInterface */ const PARAM_BREAK_AFTER = 'session/redis/break_after'; + /** + * Configuration path for comma separated list of sentinel servers + */ + const PARAM_SENTINEL_SERVERS = 'session/redis/sentinel_servers'; + + /** + * Configuration path for sentinel master + */ + const PARAM_SENTINEL_MASTER = 'session/redis/sentinel_master'; + + /** + * Configuration path for verify sentinel master flag + */ + const PARAM_SENTINEL_VERIFY_MASTER = 'session/redis/sentinel_verify_master'; + + /** + * Configuration path for number of sentinel connection retries + */ + const PARAM_SENTINEL_CONNECT_RETRIES = 'session/redis/sentinel_connect_retries'; + /** * Cookie lifetime config path */ @@ -115,6 +135,11 @@ class Config implements \Cm\RedisSession\Handler\ConfigInterface */ const SESSION_MAX_LIFETIME = 31536000; + /** + * Try to break lock for at most this many seconds + */ + const DEFAULT_FAIL_AFTER = 15; + /** * Deployment config * @@ -293,4 +318,44 @@ public function getLifetime() } return (int)$this->scopeConfig->getValue(self::XML_PATH_COOKIE_LIFETIME, StoreScopeInterface::SCOPE_STORE); } + + /** + * {@inheritdoc} + */ + public function getSentinelServers() + { + return $this->deploymentConfig->get(self::PARAM_SENTINEL_SERVERS); + } + + /** + * {@inheritdoc} + */ + public function getSentinelMaster() + { + return $this->deploymentConfig->get(self::PARAM_SENTINEL_MASTER); + } + + /** + * {@inheritdoc} + */ + public function getSentinelVerifyMaster() + { + return $this->deploymentConfig->get(self::PARAM_SENTINEL_VERIFY_MASTER); + } + + /** + * {@inheritdoc} + */ + public function getSentinelConnectRetries() + { + return $this->deploymentConfig->get(self::PARAM_SENTINEL_CONNECT_RETRIES); + } + + /** + * {@inheritdoc} + */ + public function getFailAfter() + { + return self::DEFAULT_FAIL_AFTER; + } } diff --git a/lib/internal/Magento/Framework/Session/Test/Unit/SaveHandler/DbTableTest.php b/lib/internal/Magento/Framework/Session/Test/Unit/SaveHandler/DbTableTest.php index 90b1ee2113472..659c8ab8e389a 100644 --- a/lib/internal/Magento/Framework/Session/Test/Unit/SaveHandler/DbTableTest.php +++ b/lib/internal/Magento/Framework/Session/Test/Unit/SaveHandler/DbTableTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\Session\Test\Unit\SaveHandler; class DbTableTest extends \PHPUnit\Framework\TestCase @@ -88,7 +89,7 @@ public function testCheckConnection() /** * @expectedException \Magento\Framework\Exception\SessionException - * @expectedExceptionMessage Write DB connection is not available + * @expectedExceptionMessage The write connection to the database isn't available. Please try again later. */ public function testCheckConnectionNoConnection() { @@ -105,7 +106,7 @@ public function testCheckConnectionNoConnection() /** * @expectedException \Magento\Framework\Exception\SessionException - * @expectedExceptionMessage DB storage table does not exist + * @expectedExceptionMessage The database storage table doesn't exist. Verify the table and try again. */ public function testCheckConnectionNoTable() { diff --git a/lib/internal/Magento/Framework/Session/Test/Unit/SaveHandler/Redis/ConfigTest.php b/lib/internal/Magento/Framework/Session/Test/Unit/SaveHandler/Redis/ConfigTest.php index 26f3d4c4c4e89..2859b486ec7a1 100644 --- a/lib/internal/Magento/Framework/Session/Test/Unit/SaveHandler/Redis/ConfigTest.php +++ b/lib/internal/Magento/Framework/Session/Test/Unit/SaveHandler/Redis/ConfigTest.php @@ -246,4 +246,49 @@ public function testGetLifetimeFrontend() ->willReturn($expectedLifetime); $this->assertEquals($this->config->getLifetime(), $expectedLifetime); } + + public function testGetSentinelServers() + { + $expected = 'server-1,server-2'; + $this->deploymentConfigMock->expects($this->once()) + ->method('get') + ->with(Config::PARAM_SENTINEL_SERVERS) + ->willReturn($expected); + $this->assertEquals($expected, $this->config->getSentinelServers()); + } + + public function testGetSentinelMaster() + { + $expected = 'master'; + $this->deploymentConfigMock->expects($this->once()) + ->method('get') + ->with(Config::PARAM_SENTINEL_MASTER) + ->willReturn($expected); + $this->assertEquals($this->config->getSentinelMaster(), $expected); + } + + public function testGetSentinelVerifyMaster() + { + $expected = '1'; + $this->deploymentConfigMock->expects($this->once()) + ->method('get') + ->with(Config::PARAM_SENTINEL_VERIFY_MASTER) + ->willReturn($expected); + $this->assertEquals($this->config->getSentinelVerifyMaster(), $expected); + } + + public function testGetSentinelConnectRetries() + { + $expected = '10'; + $this->deploymentConfigMock->expects($this->once()) + ->method('get') + ->willReturn(Config::PARAM_SENTINEL_CONNECT_RETRIES) + ->willReturn($expected); + $this->assertEquals($this->config->getSentinelConnectRetries(), $expected); + } + + public function testGetFailAfter() + { + $this->assertEquals($this->config->getFailAfter(), Config::DEFAULT_FAIL_AFTER); + } } diff --git a/lib/internal/Magento/Framework/Session/Validator.php b/lib/internal/Magento/Framework/Session/Validator.php index 65d3150cdbb59..a132d8644a3c6 100644 --- a/lib/internal/Magento/Framework/Session/Validator.php +++ b/lib/internal/Magento/Framework/Session/Validator.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\Session; use Magento\Framework\Exception\SessionException; @@ -110,7 +111,7 @@ protected function _validate() ) { throw new SessionException( new Phrase( - 'Invalid session %1 value.', + 'The "%1" session value is invalid. Verify and try again.', [self::VALIDATOR_REMOTE_ADDR_KEY] ) ); @@ -122,7 +123,7 @@ protected function _validate() ) { throw new SessionException( new Phrase( - 'Invalid session %1 value.', + 'The "%1" session value is invalid. Verify and try again.', [self::VALIDATOR_HTTP_VIA_KEY] ) ); @@ -137,7 +138,7 @@ protected function _validate() ) { throw new SessionException( new Phrase( - 'Invalid session %1 value.', + 'The "%1" session value is invalid. Verify and try again.', [self::VALIDATOR_HTTP_X_FORWARDED_FOR_KEY] ) ); @@ -154,7 +155,7 @@ protected function _validate() } throw new SessionException( new Phrase( - 'Invalid session %1 value.', + 'The "%1" session value is invalid. Verify and try again.', [self::VALIDATOR_HTTP_USER_AGENT_KEY] ) ); diff --git a/lib/internal/Magento/Framework/Setup/BackupRollback.php b/lib/internal/Magento/Framework/Setup/BackupRollback.php index 53e347ae01de7..6736875368d57 100644 --- a/lib/internal/Magento/Framework/Setup/BackupRollback.php +++ b/lib/internal/Magento/Framework/Setup/BackupRollback.php @@ -147,10 +147,10 @@ public function codeBackup($time, $type = Factory::TYPE_FILESYSTEM) public function codeRollback($rollbackFile, $type = Factory::TYPE_FILESYSTEM, $keepSourceFile = false) { if (preg_match('/[0-9]_(filesystem)_(code|media)\.(tgz)$/', $rollbackFile) !== 1) { - throw new LocalizedException(new Phrase('Invalid rollback file.')); + throw new LocalizedException(new Phrase('The rollback file is invalid. Verify the file and try again.')); } if (!$this->file->isExists($this->backupsDir . '/' . $rollbackFile)) { - throw new LocalizedException(new Phrase('The rollback file does not exist.')); + throw new LocalizedException(new Phrase("The rollback file doesn't exist. Verify the file and try again.")); } /** @var \Magento\Framework\Backup\Filesystem $fsRollback */ $fsRollback = $this->objectManager->create(\Magento\Framework\Backup\Filesystem::class); @@ -172,7 +172,7 @@ public function codeRollback($rollbackFile, $type = Factory::TYPE_FILESYSTEM, $k ); if (!$filesInfo['writable']) { throw new NotEnoughPermissions( - new Phrase('Unable to make rollback because not all files are writable') + new Phrase("The rollback can't be executed because not all files are writable.") ); } $fsRollback->setRootDir($this->directoryList->getRoot()); @@ -225,10 +225,10 @@ public function dbBackup($time) public function dbRollback($rollbackFile, $keepSourceFile = false) { if (preg_match('/[0-9]_(db)(.*?).(sql)$/', $rollbackFile) !== 1) { - throw new LocalizedException(new Phrase('Invalid rollback file.')); + throw new LocalizedException(new Phrase('The rollback file is invalid. Verify the file and try again.')); } if (!$this->file->isExists($this->backupsDir . '/' . $rollbackFile)) { - throw new LocalizedException(new Phrase('The rollback file does not exist.')); + throw new LocalizedException(new Phrase("The rollback file doesn't exist. Verify the file and try again.")); } /** @var \Magento\Framework\Backup\Db $dbRollback */ $dbRollback = $this->objectManager->create(\Magento\Framework\Backup\Db::class); diff --git a/lib/internal/Magento/Framework/Setup/Test/Unit/BackupRollbackTest.php b/lib/internal/Magento/Framework/Setup/Test/Unit/BackupRollbackTest.php index 5105b0dffdebf..abe05e45248bf 100644 --- a/lib/internal/Magento/Framework/Setup/Test/Unit/BackupRollbackTest.php +++ b/lib/internal/Magento/Framework/Setup/Test/Unit/BackupRollbackTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\Setup\Test\Unit; use Magento\Framework\Backup\Factory; @@ -138,7 +139,7 @@ public function testCodeRollback() /** * @expectedException \Magento\Framework\Exception\LocalizedException - * @expectedExceptionMessage The rollback file does not exist. + * @expectedExceptionMessage The rollback file doesn't exist. Verify the file and try again. */ public function testCodeRollbackWithInvalidFilePath() { @@ -150,7 +151,7 @@ public function testCodeRollbackWithInvalidFilePath() /** * @expectedException \Magento\Framework\Exception\LocalizedException - * @expectedExceptionMessage Invalid rollback file. + * @expectedExceptionMessage The rollback file is invalid. Verify the file and try again. */ public function testCodeRollbackWithInvalidFileType() { diff --git a/lib/internal/Magento/Framework/Shell.php b/lib/internal/Magento/Framework/Shell.php index 02b3f114d41f1..9a70bec54811f 100644 --- a/lib/internal/Magento/Framework/Shell.php +++ b/lib/internal/Magento/Framework/Shell.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework; use Magento\Framework\Shell\CommandRendererInterface; @@ -51,7 +52,7 @@ public function execute($command, array $arguments = []) $disabled = explode(',', str_replace(' ', ',', ini_get('disable_functions'))); if (in_array('exec', $disabled)) { - throw new Exception\LocalizedException(new \Magento\Framework\Phrase("exec function is disabled.")); + throw new Exception\LocalizedException(new \Magento\Framework\Phrase('The exec function is disabled.')); } exec($command, $output, $exitCode); diff --git a/lib/internal/Magento/Framework/Shell/Driver.php b/lib/internal/Magento/Framework/Shell/Driver.php index 8a2cd2e5bb57d..f905b5a441ba3 100644 --- a/lib/internal/Magento/Framework/Shell/Driver.php +++ b/lib/internal/Magento/Framework/Shell/Driver.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\Shell; use Magento\Framework\Exception\LocalizedException; @@ -37,7 +38,7 @@ public function execute($command, $arguments) { $disabled = explode(',', str_replace(' ', ',', ini_get('disable_functions'))); if (in_array('exec', $disabled)) { - throw new LocalizedException(new \Magento\Framework\Phrase("exec function is disabled.")); + throw new LocalizedException(new \Magento\Framework\Phrase('The exec function is disabled.')); } $command = $this->commandRenderer->render($command, $arguments); diff --git a/lib/internal/Magento/Framework/Stdlib/Cookie/PhpCookieManager.php b/lib/internal/Magento/Framework/Stdlib/Cookie/PhpCookieManager.php index 618c70b760d09..de5503c144647 100644 --- a/lib/internal/Magento/Framework/Stdlib/Cookie/PhpCookieManager.php +++ b/lib/internal/Magento/Framework/Stdlib/Cookie/PhpCookieManager.php @@ -152,11 +152,11 @@ protected function setCookie($name, $value, array $metadataArray) $params['name'] = $name; if ($value == '') { throw new FailureToSendException( - new Phrase('Unable to delete the cookie with cookieName = %name', $params) + new Phrase('The cookie with "%name" cookieName couldn\'t be deleted.', $params) ); } else { throw new FailureToSendException( - new Phrase('Unable to send the cookie with cookieName = %name', $params) + new Phrase('The cookie with "%name" cookieName couldn\'t be sent. Please try again later.', $params) ); } } diff --git a/lib/internal/Magento/Framework/Stdlib/DateTime/DateTimeFormatter.php b/lib/internal/Magento/Framework/Stdlib/DateTime/DateTimeFormatter.php index 19a960568d9fc..24772955859d6 100644 --- a/lib/internal/Magento/Framework/Stdlib/DateTime/DateTimeFormatter.php +++ b/lib/internal/Magento/Framework/Stdlib/DateTime/DateTimeFormatter.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\Stdlib\DateTime; use Magento\Framework\Exception\LocalizedException; @@ -82,7 +83,9 @@ protected function doFormatObject($object, $format = null, $locale = null) $dateFormat = $timeFormat = \IntlDateFormatter::MEDIUM; $pattern = $format; } else { - throw new LocalizedException(new Phrase('Format type is invalid')); + throw new LocalizedException( + new Phrase('The format type is invalid. Verify the format type and try again.') + ); } $timezone = $object->getTimezone(); diff --git a/lib/internal/Magento/Framework/Stdlib/DateTime/Timezone.php b/lib/internal/Magento/Framework/Stdlib/DateTime/Timezone.php index aedabc936e391..9f182f3dc00a4 100644 --- a/lib/internal/Magento/Framework/Stdlib/DateTime/Timezone.php +++ b/lib/internal/Magento/Framework/Stdlib/DateTime/Timezone.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\Stdlib\DateTime; use Magento\Framework\App\Config\ScopeConfigInterface; @@ -11,7 +12,6 @@ use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Locale\ResolverInterface; use Magento\Framework\Phrase; -use Magento\Framework\Stdlib\DateTime; /** * Timezone library @@ -41,7 +41,7 @@ class Timezone implements TimezoneInterface protected $_scopeResolver; /** - * @var DateTime + * @var \Magento\Framework\Stdlib\DateTime */ protected $_dateTime; @@ -63,7 +63,7 @@ class Timezone implements TimezoneInterface /** * @param ScopeResolverInterface $scopeResolver * @param ResolverInterface $localeResolver - * @param DateTime $dateTime + * @param \Magento\Framework\Stdlib\DateTime $dateTime * @param ScopeConfigInterface $scopeConfig * @param string $scopeType * @param string $defaultTimezonePath @@ -71,7 +71,7 @@ class Timezone implements TimezoneInterface public function __construct( ScopeResolverInterface $scopeResolver, ResolverInterface $localeResolver, - DateTime $dateTime, + \Magento\Framework\Stdlib\DateTime $dateTime, ScopeConfigInterface $scopeConfig, $scopeType, $defaultTimezonePath @@ -318,7 +318,10 @@ public function convertConfigTimeToUtc($date, $format = 'Y-m-d H:i:s') } else { if ($date->getTimezone()->getName() !== $this->getConfigTimezone()) { throw new LocalizedException( - new Phrase('DateTime object timezone must be the same as config - %1', $this->getConfigTimezone()) + new Phrase( + 'The DateTime object timezone needs to be the same as the "%1" timezone in config.', + $this->getConfigTimezone() + ) ); } } diff --git a/lib/internal/Magento/Framework/Stdlib/DateTime/Timezone/Validator.php b/lib/internal/Magento/Framework/Stdlib/DateTime/Timezone/Validator.php index aef2bfb808842..43cc83a702f6c 100644 --- a/lib/internal/Magento/Framework/Stdlib/DateTime/Timezone/Validator.php +++ b/lib/internal/Magento/Framework/Stdlib/DateTime/Timezone/Validator.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\Stdlib\DateTime\Timezone; use Magento\Framework\Exception\ValidatorException; @@ -53,7 +54,10 @@ public function validate($timestamp, $toDate) if ($transitionYear > $this->_yearMaxValue || $transitionYear < $this->_yearMinValue) { throw new ValidatorException( - new Phrase('Transition year is out of system date range.') + new Phrase( + "The transition year isn't included in the system date range. " + . "Verify the year date range and try again." + ) ); } diff --git a/lib/internal/Magento/Framework/Stdlib/Test/Unit/Cookie/PhpCookieManagerTest.php b/lib/internal/Magento/Framework/Stdlib/Test/Unit/Cookie/PhpCookieManagerTest.php index b3cb5f2aeddce..75b8eb2cec8d6 100644 --- a/lib/internal/Magento/Framework/Stdlib/Test/Unit/Cookie/PhpCookieManagerTest.php +++ b/lib/internal/Magento/Framework/Stdlib/Test/Unit/Cookie/PhpCookieManagerTest.php @@ -234,7 +234,7 @@ public function testDeleteCookieWithFailureToSendException() } catch (FailureToSendException $fse) { $this->assertTrue(self::$isSetCookieInvoked); $this->assertSame( - 'Unable to delete the cookie with cookieName = exception_cookie_name', + 'The cookie with "exception_cookie_name" cookieName couldn\'t be deleted.', $fse->getMessage() ); } diff --git a/lib/internal/Magento/Framework/Stdlib/Test/Unit/DateTime/DateTimeFormatterTest.php b/lib/internal/Magento/Framework/Stdlib/Test/Unit/DateTime/DateTimeFormatterTest.php index 5012c6a47f1c5..f5c8f370fe453 100644 --- a/lib/internal/Magento/Framework/Stdlib/Test/Unit/DateTime/DateTimeFormatterTest.php +++ b/lib/internal/Magento/Framework/Stdlib/Test/Unit/DateTime/DateTimeFormatterTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\Stdlib\Test\Unit\DateTime; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; @@ -118,7 +119,7 @@ public function dataProviderFormatObject() /** * @expectedException \Magento\Framework\Exception\LocalizedException - * @expectedExceptionMessage Format type is invalid + * @expectedExceptionMessage The format type is invalid. Verify the format type and try again. */ public function testFormatObjectIfPassedWrongFormat() { diff --git a/lib/internal/Magento/Framework/Stdlib/Test/Unit/DateTime/Timezone/ValidatorTest.php b/lib/internal/Magento/Framework/Stdlib/Test/Unit/DateTime/Timezone/ValidatorTest.php index 71638a38c55b9..4242664c44b30 100644 --- a/lib/internal/Magento/Framework/Stdlib/Test/Unit/DateTime/Timezone/ValidatorTest.php +++ b/lib/internal/Magento/Framework/Stdlib/Test/Unit/DateTime/Timezone/ValidatorTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\Stdlib\Test\Unit\DateTime\Timezone; class ValidatorTest extends \PHPUnit\Framework\TestCase @@ -15,12 +16,15 @@ class ValidatorTest extends \PHPUnit\Framework\TestCase /** * @dataProvider validateWithTimestampOutOfSystemRangeDataProvider * @expectedException \Magento\Framework\Exception\ValidatorException - * @expectedExceptionMessage Transition year is out of system date range. */ public function testValidateWithTimestampOutOfSystemRangeThrowsException($range, $validateArgs) { $this->_validator = new \Magento\Framework\Stdlib\DateTime\Timezone\Validator($range['min'], $range['max']); $this->_validator->validate($validateArgs['timestamp'], $validateArgs['to_date']); + + $this->expectExceptionMessage( + "The transition year isn't included in the system date range. Verify the year date range and try again." + ); } /** diff --git a/lib/internal/Magento/Framework/Test/Unit/App/ResourceConnectionTest.php b/lib/internal/Magento/Framework/Test/Unit/App/ResourceConnectionTest.php index d0bb0b9d73470..686c09e947509 100644 --- a/lib/internal/Magento/Framework/Test/Unit/App/ResourceConnectionTest.php +++ b/lib/internal/Magento/Framework/Test/Unit/App/ResourceConnectionTest.php @@ -61,6 +61,31 @@ protected function setUp() ); } + public function testGetTablePrefixWithInjectedPrefix() + { + /** @var ResourceConnection $resourceConnection */ + $resourceConnection = $this->objectManager->getObject( + ResourceConnection::class, + [ + 'deploymentConfig' => $this->deploymentConfigMock, + 'connectionFactory' => $this->connectionFactoryMock, + 'config' => $this->configMock, + 'tablePrefix' => 'some_prefix' + ] + ); + + self::assertEquals($resourceConnection->getTablePrefix(), 'some_prefix'); + } + + public function testGetTablePrefix() + { + $this->deploymentConfigMock->expects(self::once()) + ->method('get') + ->with(ConfigOptionsListConstants::CONFIG_PATH_DB_PREFIX) + ->willReturn('pref_'); + self::assertEquals('pref_', $this->unit->getTablePrefix()); + } + public function testGetConnectionByName() { $this->deploymentConfigMock->expects(self::once())->method('get') diff --git a/lib/internal/Magento/Framework/Test/Unit/Config/FileResolverByModuleTest.php b/lib/internal/Magento/Framework/Test/Unit/Config/FileResolverByModuleTest.php new file mode 100644 index 0000000000000..1a1f3391f0170 --- /dev/null +++ b/lib/internal/Magento/Framework/Test/Unit/Config/FileResolverByModuleTest.php @@ -0,0 +1,232 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\Test\Unit\Config; + +use Magento\Framework\Config\FileIterator; +use Magento\Framework\Filesystem\DriverInterface; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; + +class FileResolverByModuleTest extends \PHPUnit\Framework\TestCase +{ + /** + * @var \Magento\Framework\Config\FileResolverByModule + */ + private $model; + + /** + * @var ObjectManagerHelper + */ + private $objectManagerHelper; + + /** + * @var \Magento\Framework\Module\Dir\Reader|\PHPUnit_Framework_MockObject_MockObject + */ + private $readerMock; + + /** + * @var \Magento\Framework\Filesystem|\PHPUnit_Framework_MockObject_MockObject + */ + private $filesystemMock; + + /** + * @var \Magento\Framework\Config\FileIteratorFactory|\PHPUnit_Framework_MockObject_MockObject + */ + private $fileIteratorFactoryMock; + + /** + * @var \Magento\Framework\Component\ComponentRegistrar|\PHPUnit_Framework_MockObject_MockObject + */ + private $componentRegistrarMock; + + /** + * @var \Magento\Framework\Filesystem\Driver\File|\PHPUnit_Framework_MockObject_MockObject + */ + private $fileDriver; + + protected function setUp() + { + $this->readerMock = $this->getMockBuilder(\Magento\Framework\Module\Dir\Reader::class) + ->disableOriginalConstructor() + ->getMock(); + $this->filesystemMock = $this->getMockBuilder(\Magento\Framework\Filesystem::class) + ->disableOriginalConstructor() + ->getMock(); + $this->fileIteratorFactoryMock = $this->getMockBuilder(\Magento\Framework\Config\FileIteratorFactory::class) + ->disableOriginalConstructor() + ->getMock(); + $this->componentRegistrarMock = $this->getMockBuilder(\Magento\Framework\Component\ComponentRegistrar::class) + ->disableOriginalConstructor() + ->getMock(); + $this->fileDriver = $this->getMockBuilder(\Magento\Framework\Filesystem\Driver\File::class) + ->disableOriginalConstructor() + ->getMock(); + $this->objectManagerHelper = new ObjectManagerHelper($this); + $this->model = $this->objectManagerHelper->getObject( + \Magento\Framework\Config\FileResolverByModule::class, + [ + 'moduleReader' => $this->readerMock, + 'filesystem' => $this->filesystemMock, + 'iteratorFactory' => $this->fileIteratorFactoryMock, + 'componentRegistrar' => $this->componentRegistrarMock, + 'driver' => $this->fileDriver + ] + ); + } + + public function testGet() + { + $iterator = $this->getMockBuilder(FileIterator::class) + ->disableOriginalConstructor() + ->getMock(); + $iterator->expects(self::once()) + ->method('toArray') + ->willReturn([ + 'some_path' => '<xml>Some Content</xml>' + ]); + $primaryIterator = $this->getMockBuilder(FileIterator::class) + ->disableOriginalConstructor() + ->getMock(); + $primaryIterator->expects(self::once()) + ->method('toArray') + ->willReturn([ + '/www/app/etc/db_schema.xml' => '<xml>Primary Content</xml>' + ]); + $directoryMock = $this->getMockBuilder(\Magento\Framework\Filesystem\Directory\ReadInterface::class) + ->disableOriginalConstructor() + ->getMock(); + $directoryMock->expects(self::once()) + ->method('search') + ->with('{db_schema.xml,*/db_schema.xml}') + ->willReturn(['app/etc/db_schema.xml']); + $directoryMock->expects(self::once()) + ->method('getAbsolutePath') + ->willReturn('/www/app/etc/db_schema.xml'); + $this->readerMock->expects(self::once()) + ->method('getConfigurationFiles') + ->willReturn($iterator); + $this->fileIteratorFactoryMock->expects(self::once()) + ->method('create') + ->with(['/www/app/etc/db_schema.xml']) + ->willReturn($primaryIterator); + $this->fileDriver->expects(self::once()) + ->method('isFile') + ->with('/www/app/etc/db_schema.xml') + ->willReturn(true); + $this->filesystemMock->expects(self::once()) + ->method('getDirectoryRead') + ->willReturn($directoryMock); + self::assertEquals( + $this->model->get('db_schema.xml', 'all'), + [ + 'some_path' => '<xml>Some Content</xml>', + '/www/app/etc/db_schema.xml' => '<xml>Primary Content</xml>' + ] + ); + } + + /** + * @expectedExceptionMessage Primary db_schema file doesn`t exist + */ + public function testGetWithException() + { + $iterator = $this->getMockBuilder(FileIterator::class) + ->disableOriginalConstructor() + ->getMock(); + $iterator->expects(self::once()) + ->method('toArray') + ->willReturn([ + 'some_path' => '<xml>Some Content</xml>' + ]); + $primaryIterator = $this->getMockBuilder(FileIterator::class) + ->disableOriginalConstructor() + ->getMock(); + $primaryIterator->expects(self::once()) + ->method('toArray') + ->willReturn([ + '/www/app/etc/db_schema.xml' => '<xml>Primary Content</xml>' + ]); + $directoryMock = $this->getMockBuilder(\Magento\Framework\Filesystem\Directory\ReadInterface::class) + ->disableOriginalConstructor() + ->getMock(); + $directoryMock->expects(self::once()) + ->method('search') + ->with('{db_schema.xml,*/db_schema.xml}') + ->willReturn(['app/etc/db_schema.xml']); + $directoryMock->expects(self::once()) + ->method('getAbsolutePath') + ->willReturn('/www/app/etc/db_schema.xml'); + $this->readerMock->expects(self::once()) + ->method('getConfigurationFiles') + ->willReturn($iterator); + $this->fileIteratorFactoryMock->expects(self::once()) + ->method('create') + ->with(['/www/app/etc/db_schema.xml']) + ->willReturn($primaryIterator); + $this->fileDriver->expects(self::once()) + ->method('isFile') + ->with('/www/app/etc/db_schema.xml') + ->willReturn(true); + $this->filesystemMock->expects(self::once()) + ->method('getDirectoryRead') + ->willReturn($directoryMock); + $this->model->get('db_schema.xml', 'all'); + } + + public function testGetOneModule() + { + $iterator = $this->getMockBuilder(FileIterator::class) + ->disableOriginalConstructor() + ->getMock(); + $iterator->expects(self::once()) + ->method('toArray') + ->willReturn([ + 'some_path/etc/db_schema.xml' => '<xml>Some Content</xml>' + ]); + $primaryIterator = $this->getMockBuilder(FileIterator::class) + ->disableOriginalConstructor() + ->getMock(); + $primaryIterator->expects(self::once()) + ->method('toArray') + ->willReturn([ + '/www/app/etc/db_schema.xml' => '<xml>Primary Content</xml>' + ]); + $directoryMock = $this->getMockBuilder(\Magento\Framework\Filesystem\Directory\ReadInterface::class) + ->disableOriginalConstructor() + ->getMock(); + $directoryMock->expects(self::once()) + ->method('search') + ->with('{db_schema.xml,*/db_schema.xml}') + ->willReturn(['app/etc/db_schema.xml']); + $directoryMock->expects(self::once()) + ->method('getAbsolutePath') + ->willReturn('/www/app/etc/db_schema.xml'); + $this->readerMock->expects(self::once()) + ->method('getConfigurationFiles') + ->willReturn($iterator); + $this->fileIteratorFactoryMock->expects(self::once()) + ->method('create') + ->with(['/www/app/etc/db_schema.xml']) + ->willReturn($primaryIterator); + $this->fileDriver->expects(self::once()) + ->method('isFile') + ->with('/www/app/etc/db_schema.xml') + ->willReturn(true); + $this->filesystemMock->expects(self::once()) + ->method('getDirectoryRead') + ->willReturn($directoryMock); + $this->componentRegistrarMock->expects(self::once()) + ->method('getPath') + ->with('module', 'Magento_Some') + ->willReturn('some_path'); + self::assertEquals( + [ + 'some_path/etc/db_schema.xml' => '<xml>Some Content</xml>', + '/www/app/etc/db_schema.xml' => '<xml>Primary Content</xml>' + ], + $this->model->get('db_schema.xml', 'Magento_Some') + ); + } +} diff --git a/lib/internal/Magento/Framework/Test/Unit/DB/Query/GeneratorTest.php b/lib/internal/Magento/Framework/Test/Unit/DB/Query/GeneratorTest.php index e5b5876b65f46..bcb90714f9563 100644 --- a/lib/internal/Magento/Framework/Test/Unit/DB/Query/GeneratorTest.php +++ b/lib/internal/Magento/Framework/Test/Unit/DB/Query/GeneratorTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\Test\Unit\DB\Query; use Magento\Framework\DB\Query\BatchIterator; @@ -87,7 +88,7 @@ public function testGenerate() * Test batch generation with invalid select object. * * @expectedException \Magento\Framework\Exception\LocalizedException - * @expectedExceptionMessage Select object must have correct "FROM" part + * @expectedExceptionMessage The select object must have the correct "FROM" part. Verify and try again. * @return void */ public function testGenerateWithoutFromPart() diff --git a/lib/internal/Magento/Framework/Url/ScopeResolver.php b/lib/internal/Magento/Framework/Url/ScopeResolver.php index b43f70713daed..674cb644bca5f 100644 --- a/lib/internal/Magento/Framework/Url/ScopeResolver.php +++ b/lib/internal/Magento/Framework/Url/ScopeResolver.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\Url; /** @@ -40,7 +41,7 @@ public function getScope($scopeId = null) $scope = $this->scopeResolver->getScope($scopeId); if (!$scope instanceof \Magento\Framework\Url\ScopeInterface) { throw new \Magento\Framework\Exception\LocalizedException( - new \Magento\Framework\Phrase('Invalid scope object') + new \Magento\Framework\Phrase('The scope object is invalid. Verify the scope object and try again.') ); } diff --git a/lib/internal/Magento/Framework/Url/Test/Unit/ScopeResolverTest.php b/lib/internal/Magento/Framework/Url/Test/Unit/ScopeResolverTest.php index abc5a3750cb47..8b07cc553d456 100644 --- a/lib/internal/Magento/Framework/Url/Test/Unit/ScopeResolverTest.php +++ b/lib/internal/Magento/Framework/Url/Test/Unit/ScopeResolverTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\Url\Test\Unit; class ScopeResolverTest extends \PHPUnit\Framework\TestCase @@ -50,7 +51,7 @@ public function testGetScope($scopeId) /** * @expectedException \Magento\Framework\Exception\LocalizedException - * @expectedExceptionMessage Invalid scope object + * @expectedExceptionMessage The scope object is invalid. Verify the scope object and try again. */ public function testGetScopeException() { diff --git a/lib/internal/Magento/Framework/View/Asset/Minification.php b/lib/internal/Magento/Framework/View/Asset/Minification.php index 686f794d6318a..33c82a1810db6 100644 --- a/lib/internal/Magento/Framework/View/Asset/Minification.php +++ b/lib/internal/Magento/Framework/View/Asset/Minification.php @@ -143,7 +143,8 @@ public function getExcludes($contentType) if (!isset($this->configCache[self::XML_PATH_MINIFICATION_EXCLUDES][$contentType])) { $this->configCache[self::XML_PATH_MINIFICATION_EXCLUDES][$contentType] = []; $key = sprintf(self::XML_PATH_MINIFICATION_EXCLUDES, $contentType); - foreach (explode("\n", $this->scopeConfig->getValue($key, $this->scope)) as $exclude) { + $excludeValues = $this->getMinificationExcludeValues($key); + foreach ($excludeValues as $exclude) { if (trim($exclude) != '') { $this->configCache[self::XML_PATH_MINIFICATION_EXCLUDES][$contentType][] = trim($exclude); } @@ -151,4 +152,17 @@ public function getExcludes($contentType) } return $this->configCache[self::XML_PATH_MINIFICATION_EXCLUDES][$contentType]; } + + /** + * Get minification exclude values from configuration + * + * @param string $key + * @return string[] + */ + private function getMinificationExcludeValues($key) + { + $configValues = $this->scopeConfig->getValue($key, $this->scope) ?? []; + + return array_values($configValues); + } } diff --git a/lib/internal/Magento/Framework/View/Design/FileResolution/Fallback/TemplateFile.php b/lib/internal/Magento/Framework/View/Design/FileResolution/Fallback/TemplateFile.php index 8150b386eddef..09f87d878ad1c 100644 --- a/lib/internal/Magento/Framework/View/Design/FileResolution/Fallback/TemplateFile.php +++ b/lib/internal/Magento/Framework/View/Design/FileResolution/Fallback/TemplateFile.php @@ -10,6 +10,9 @@ use Magento\Framework\View\Asset\ConfigInterface; use Magento\Framework\View\Design\ThemeInterface; use Magento\Framework\View\Template\Html\MinifierInterface; +use Magento\Framework\App\DeploymentConfig; +use Magento\Framework\App\ObjectManager; +use Magento\Framework\Config\ConfigOptionsListConstants; /** * Provider of template view files @@ -31,21 +34,29 @@ class TemplateFile extends File */ protected $assetConfig; + /** + * @var DeploymentConfig + */ + private $deploymentConfig; + /** * @param ResolverInterface $resolver * @param MinifierInterface $templateMinifier * @param State $appState * @param ConfigInterface $assetConfig + * @param DeploymentConfig $deploymentConfig */ public function __construct( ResolverInterface $resolver, MinifierInterface $templateMinifier, State $appState, - ConfigInterface $assetConfig + ConfigInterface $assetConfig, + DeploymentConfig $deploymentConfig = null ) { $this->appState = $appState; $this->templateMinifier = $templateMinifier; $this->assetConfig = $assetConfig; + $this->deploymentConfig = $deploymentConfig ?: ObjectManager::getInstance()->get(DeploymentConfig::class); parent::__construct($resolver); } @@ -73,7 +84,7 @@ public function getFile($area, ThemeInterface $themeModel, $file, $module = null if ($template && $this->assetConfig->isMinifyHtml()) { switch ($this->appState->getMode()) { case State::MODE_PRODUCTION: - return $this->templateMinifier->getPathToMinified($template); + return $this->getMinifiedTemplateInProduction($template); case State::MODE_DEFAULT: return $this->templateMinifier->getMinified($template); case State::MODE_DEVELOPER: @@ -83,4 +94,24 @@ public function getFile($area, ThemeInterface $themeModel, $file, $module = null } return $template; } + + /** + * Returns path to minified template file + * + * If SCD on demand in production is disabled - returns the path to minified template file. + * Otherwise returns the path to minified template file, + * or minify if file not exist and returns path. + * + * @param string $template + * @return string + */ + private function getMinifiedTemplateInProduction($template) + { + if ($this->deploymentConfig->getConfigData( + ConfigOptionsListConstants::CONFIG_PATH_SCD_ON_DEMAND_IN_PRODUCTION + )) { + return $this->templateMinifier->getMinified($template); + } + return $this->templateMinifier->getPathToMinified($template); + } } diff --git a/lib/internal/Magento/Framework/View/Element/ExceptionHandlerBlock.php b/lib/internal/Magento/Framework/View/Element/ExceptionHandlerBlock.php index 1749eb9c554e1..101eea5349e77 100644 --- a/lib/internal/Magento/Framework/View/Element/ExceptionHandlerBlock.php +++ b/lib/internal/Magento/Framework/View/Element/ExceptionHandlerBlock.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\View\Element; use Magento\Framework\Exception\LocalizedException; @@ -43,7 +44,7 @@ public function __construct($blockName = '') public function __call($method, $args) { throw new LocalizedException( - new Phrase('Block %1 throws exception and cannot be rendered.', [$this->blockName]) + new Phrase('The "%1" block threw an exception, and it can\'t be rendered.', [$this->blockName]) ); } @@ -56,7 +57,7 @@ public function __call($method, $args) public function toHtml() { throw new LocalizedException( - new Phrase('Block %1 throws exception and cannot be rendered.', [$this->blockName]) + new Phrase('The "%1" block threw an exception, and it can\'t be rendered.', [$this->blockName]) ); } } diff --git a/lib/internal/Magento/Framework/View/Element/UiComponentFactory.php b/lib/internal/Magento/Framework/View/Element/UiComponentFactory.php index 93fe88a30f065..626aebeb94269 100755 --- a/lib/internal/Magento/Framework/View/Element/UiComponentFactory.php +++ b/lib/internal/Magento/Framework/View/Element/UiComponentFactory.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\View\Element; use Magento\Framework\Config\DataInterface; @@ -265,13 +266,17 @@ protected function getBundleChildren(array $children = []) foreach ($children as $identifier => $config) { if (!isset($config['componentType'])) { throw new LocalizedException(new Phrase( - 'The configuration parameter "componentType" is a required for "%1" component.', + 'The "componentType" configuration parameter is required for the "%1" component.', $identifier )); } if (!isset($componentArguments['context'])) { - throw new LocalizedException(new \Magento\Framework\Phrase('Each UI component should have context.')); + throw new LocalizedException( + new \Magento\Framework\Phrase( + 'An error occurred with the UI component. Each component needs context. Verify and try again.' + ) + ); } $rawComponentData = $this->definitionData->get($config['componentType']); @@ -382,7 +387,7 @@ protected function mergeMetadataItem(array $bundleComponents, array $metadata, $ if (!$isMerged) { if (!isset($data['arguments']['data']['config']['componentType'])) { throw new LocalizedException(new Phrase( - 'The configuration parameter "componentType" is a required for "%1" component.', + 'The "componentType" configuration parameter is required for the "%1" component.', [$name] )); } diff --git a/lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/TemplateFactory.php b/lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/TemplateFactory.php index cd372399fcbc0..3a49cd85bb701 100644 --- a/lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/TemplateFactory.php +++ b/lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/TemplateFactory.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\View\TemplateEngine\Xhtml; use Magento\Framework\Phrase; @@ -54,7 +55,9 @@ public function create(array $arguments = []) $object = $this->objectManager->create($this->instanceName, $arguments); if (!($object instanceof Template)) { - throw new LocalizedException(new Phrase('This class must inherit from a class "Template"')); + throw new LocalizedException( + new Phrase('This class needs to inherit from a class "Template". Verify the class and try again.') + ); } return $object; diff --git a/lib/internal/Magento/Framework/View/Test/Unit/Asset/MinificationTest.php b/lib/internal/Magento/Framework/View/Test/Unit/Asset/MinificationTest.php index 2f6305f1cc73c..1cc2a3dd7e2b7 100644 --- a/lib/internal/Magento/Framework/View/Test/Unit/Asset/MinificationTest.php +++ b/lib/internal/Magento/Framework/View/Test/Unit/Asset/MinificationTest.php @@ -203,10 +203,10 @@ public function testGetExcludes() ->expects($this->once()) ->method('getValue') ->with('dev/js/minify_exclude') - ->willReturn( - " /tiny_mce/ \n" . - " /tiny_mce2/ " - ); + ->willReturn([ + 'tiny_mce' => '/tiny_mce/', + 'some_other_unique_name' => '/tiny_mce2/' + ]); $expected = ['/tiny_mce/', '/tiny_mce2/']; $this->assertEquals($expected, $this->minification->getExcludes('js')); diff --git a/lib/internal/Magento/Framework/View/Test/Unit/Design/FileResolution/Fallback/TemplateFileTest.php b/lib/internal/Magento/Framework/View/Test/Unit/Design/FileResolution/Fallback/TemplateFileTest.php index 478a8a4d214e0..7e94d7e80a97f 100644 --- a/lib/internal/Magento/Framework/View/Test/Unit/Design/FileResolution/Fallback/TemplateFileTest.php +++ b/lib/internal/Magento/Framework/View/Test/Unit/Design/FileResolution/Fallback/TemplateFileTest.php @@ -10,6 +10,10 @@ use Magento\Framework\View\Design\Fallback\RulePool; use Magento\Framework\View\Design\FileResolution\Fallback\TemplateFile; use Magento\Framework\View\Design\FileResolution\Fallback\ResolverInterface; +use Magento\Framework\View\Template\Html\MinifierInterface; +use Magento\Framework\View\Asset\ConfigInterface; +use Magento\Framework\App\DeploymentConfig; +use Magento\Framework\Config\ConfigOptionsListConstants; class TemplateFileTest extends \PHPUnit\Framework\TestCase { @@ -19,12 +23,12 @@ class TemplateFileTest extends \PHPUnit\Framework\TestCase protected $resolver; /** - * @var \Magento\Framework\View\Template\Html\MinifierInterface|\PHPUnit_Framework_MockObject_MockObject + * @var MinifierInterface|\PHPUnit_Framework_MockObject_MockObject */ protected $minifier; /** - * @var \Magento\Framework\App\State|\PHPUnit_Framework_MockObject_MockObject + * @var State|\PHPUnit_Framework_MockObject_MockObject */ protected $state; @@ -34,26 +38,29 @@ class TemplateFileTest extends \PHPUnit\Framework\TestCase protected $object; /** - * @var \Magento\Framework\View\Asset\ConfigInterface|\PHPUnit_Framework_MockObject_MockObject + * @var DeploymentConfig|\PHPUnit_Framework_MockObject_MockObject + */ + private $deploymentConfigMock; + + /** + * @var ConfigInterface|\PHPUnit_Framework_MockObject_MockObject */ protected $assetConfig; protected function setUp() { - $this->resolver = $this->createMock( - \Magento\Framework\View\Design\FileResolution\Fallback\ResolverInterface::class - ); - $this->minifier = $this->createMock(\Magento\Framework\View\Template\Html\MinifierInterface::class); - $this->state = $this->getMockBuilder( - \Magento\Framework\App\State::class - )->disableOriginalConstructor()->getMock(); - $this->assetConfig = $this->getMockForAbstractClass( - \Magento\Framework\View\Asset\ConfigInterface::class, - [], - '', - false + $this->resolver = $this->getMockForAbstractClass(ResolverInterface::class); + $this->minifier = $this->getMockForAbstractClass(MinifierInterface::class); + $this->state = $this->createMock(State::class); + $this->assetConfig = $this->getMockForAbstractClass(ConfigInterface::class); + $this->deploymentConfigMock = $this->createMock(DeploymentConfig::class); + $this->object = new TemplateFile( + $this->resolver, + $this->minifier, + $this->state, + $this->assetConfig, + $this->deploymentConfigMock ); - $this->object = new TemplateFile($this->resolver, $this->minifier, $this->state, $this->assetConfig); } /** @@ -75,7 +82,7 @@ public function testGetFileWhenStateDeveloper() $this->resolver->expects($this->once()) ->method('resolve') ->with(RulePool::TYPE_TEMPLATE_FILE, 'file.ext', 'frontend', $theme, null, 'Magento_Module') - ->will($this->returnValue($expected)); + ->willReturn($expected); $actual = $this->object->getFile('frontend', $theme, 'file.ext', 'Magento_Module'); $this->assertSame($expected, $actual); @@ -84,10 +91,11 @@ public function testGetFileWhenStateDeveloper() /** * Cover getFile when mode is default * @param string $mode + * @param integer $onDemandInProduction * @param string $method * @dataProvider getMinifiedDataProvider */ - public function testGetFileWhenModifiedNeeded($mode, $method) + public function testGetFileWhenModifiedNeeded($mode, $onDemandInProduction, $method) { $this->assetConfig ->expects($this->once()) @@ -98,13 +106,17 @@ public function testGetFileWhenModifiedNeeded($mode, $method) $expected = 'some/file.ext'; $expectedMinified = '/path/to/minified/some/file.ext'; + $this->deploymentConfigMock->expects($this->any()) + ->method('getConfigData') + ->with(ConfigOptionsListConstants::CONFIG_PATH_SCD_ON_DEMAND_IN_PRODUCTION) + ->willReturn($onDemandInProduction); $this->state->expects($this->once()) ->method('getMode') ->willReturn($mode); $this->resolver->expects($this->once()) ->method('resolve') ->with(RulePool::TYPE_TEMPLATE_FILE, 'file.ext', 'frontend', $theme, null, 'Magento_Module') - ->will($this->returnValue($expected)); + ->willReturn($expected); $this->minifier->expects($this->once()) ->method($method) ->with($expected) @@ -127,9 +139,10 @@ public function testGetFileIfMinificationIsDisabled() $this->resolver->expects($this->once()) ->method('resolve') ->with(RulePool::TYPE_TEMPLATE_FILE, 'file.ext', 'frontend', $theme, null, 'Magento_Module') - ->will($this->returnValue($expected)); + ->willReturn($expected); - $this->state->expects($this->never())->method('getMode'); + $this->state->expects($this->never()) + ->method('getMode'); $actual = $this->object->getFile('frontend', $theme, 'file.ext', 'Magento_Module'); $this->assertSame($expected, $actual); @@ -143,8 +156,10 @@ public function testGetFileIfMinificationIsDisabled() public function getMinifiedDataProvider() { return [ - 'default' => [State::MODE_DEFAULT, 'getMinified'], - 'production' => [State::MODE_PRODUCTION, 'getPathToMinified'], + 'default with on demand' => [State::MODE_DEFAULT, 1, 'getMinified'], + 'default without on demand' => [State::MODE_DEFAULT, 0, 'getMinified'], + 'production with on demand' => [State::MODE_PRODUCTION, 1, 'getMinified'], + 'production without on demand' => [State::MODE_PRODUCTION, 0, 'getPathToMinified'], ]; } } diff --git a/lib/internal/Magento/Framework/Webapi/ServiceInputProcessor.php b/lib/internal/Magento/Framework/Webapi/ServiceInputProcessor.php index f1df2b0ee53f0..bcbecd37d90df 100644 --- a/lib/internal/Magento/Framework/Webapi/ServiceInputProcessor.php +++ b/lib/internal/Magento/Framework/Webapi/ServiceInputProcessor.php @@ -5,6 +5,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\Webapi; use Magento\Framework\Webapi\ServiceTypeToEntityTypeMap; @@ -289,12 +290,21 @@ private function processCustomAttribute($customAttribute) } if (!$customAttributeCode && !isset($customAttribute[AttributeValue::VALUE])) { - throw new SerializationException(new Phrase('There is an empty custom attribute specified.')); + throw new SerializationException( + new Phrase('An empty custom attribute is specified. Enter the attribute and try again.') + ); } elseif (!$customAttributeCode) { - throw new SerializationException(new Phrase('A custom attribute is specified without an attribute code.')); + throw new SerializationException( + new Phrase( + 'A custom attribute is specified with a missing attribute code. Verify the code and try again.' + ) + ); } elseif (!array_key_exists(AttributeValue::VALUE, $customAttribute)) { throw new SerializationException( - new Phrase('Value is not set for attribute code "' . $customAttributeCode . '"') + new Phrase( + 'The "' . $customAttributeCode . + '" attribute code doesn\'t have a value set. Enter the value and try again.' + ) ); } @@ -396,7 +406,9 @@ protected function processInputError($inputError) if (!empty($inputError)) { $exception = new InputException(); foreach ($inputError as $errorParamField) { - $exception->addError(new Phrase('%fieldName is a required field.', ['fieldName' => $errorParamField])); + $exception->addError( + new Phrase('"%fieldName" is required. Enter and try again.', ['fieldName' => $errorParamField]) + ); } if ($exception->wasErrorAdded()) { throw $exception; diff --git a/lib/internal/Magento/Framework/composer.json b/lib/internal/Magento/Framework/composer.json index 785ff07a60f39..b442effe5ffda 100644 --- a/lib/internal/Magento/Framework/composer.json +++ b/lib/internal/Magento/Framework/composer.json @@ -23,7 +23,7 @@ "ext-spl": "*", "ext-xsl": "*", "lib-libxml": "*", - "colinmollenhour/php-redis-session-abstract": "~1.2.2", + "colinmollenhour/php-redis-session-abstract": "~1.3.8", "composer/composer": "1.4.1", "magento/zendframework1": "~1.13.0", "monolog/monolog": "^1.17", diff --git a/lib/web/mage/adminhtml/browser.js b/lib/web/mage/adminhtml/browser.js index 232019d1b0916..26d6679bb3ce5 100644 --- a/lib/web/mage/adminhtml/browser.js +++ b/lib/web/mage/adminhtml/browser.js @@ -265,6 +265,7 @@ define([ node: this.activeNode.id, store: this.options.storeId, 'as_is': targetEl.is('textarea') ? 1 : 0, + 'force_static_path': targetEl.data('force_static_path') ? 1 : 0, 'form_key': FORM_KEY }, context: this, @@ -273,7 +274,11 @@ define([ if (targetEl.is('textarea')) { this.insertAtCursor(targetEl.get(0), data); } else { - targetEl.val(data).trigger('change'); + targetEl + .val(data) + .data('size', fileRow.data('size')) + .data('mime-type', fileRow.data('mime-type')) + .trigger('change'); } MediabrowserUtility.closeDialog(); targetEl.focus(); @@ -472,4 +477,6 @@ define([ breadcrumbs.insertAfter(this.element.find('#content_header')); } }); + + return window.MediabrowserUtility; }); diff --git a/lib/web/mage/utils/misc.js b/lib/web/mage/utils/misc.js index e86cec82ef990..a3d478d468d54 100644 --- a/lib/web/mage/utils/misc.js +++ b/lib/web/mage/utils/misc.js @@ -255,6 +255,38 @@ define([ newFormat = newFormat.replace(/dd|d/g, 'DD'); // replace the date return newFormat; + }, + + /** + * Get Url Parameters. + * + * @param {String} url - Url string + * @returns {Object} + */ + getUrlParameters: function (url) { + var params = {}, + queries = url.split('?'), + temp, + i, + l; + + if (!queries[1]) { + return params; + } + + queries = queries[1].split('&'); + + for (i = 0, l = queries.length; i < l; i++) { + temp = queries[i].split('='); + + if (temp[1]) { + params[temp[0]] = decodeURIComponent(temp[1].replace(/\+/g, '%20')); + } else { + params[temp[0]] = ''; + } + } + + return params; } }; }); diff --git a/lib/web/mage/validation.js b/lib/web/mage/validation.js index 8ab522a318881..a0c9f3ad795e3 100644 --- a/lib/web/mage/validation.js +++ b/lib/web/mage/validation.js @@ -1587,7 +1587,7 @@ return true; }, - $.mage.__('Password cannot be the same as email address.') + $.mage.__('The password can\'t be the same as the email address. Create a new password and try again.') ] }; diff --git a/phpserver/README.md b/phpserver/README.md index 63436c8af7883..6bb814fe5f5f2 100644 --- a/phpserver/README.md +++ b/phpserver/README.md @@ -31,7 +31,7 @@ For more informations about the installation process using the CLI, you can cons ### How to run Magento -Example usage: ```php -S 127.0.0.1:8082 -t ./pub/ ./phpserver/router.php``` +Example usage: ```php -S 127.0.0.1:8082 -t ./pub/ ../phpserver/router.php``` ### What exactly the script does diff --git a/phpserver/router.php b/phpserver/router.php index a12e9178ecad4..06c23ecdfe3cd 100644 --- a/phpserver/router.php +++ b/phpserver/router.php @@ -103,6 +103,7 @@ } else { $debug('file does not exist'); if (strpos($route, 'static/') === 0) { + $route = preg_replace('#static/#', '', $route, 1); $_GET['resource'] = $route; $debug("static: $route"); include($magentoPackagePubDir.'/static.php'); diff --git a/pub/static/.htaccess b/pub/static/.htaccess index 21fe6a63e64ba..a10e234e07ff2 100644 --- a/pub/static/.htaccess +++ b/pub/static/.htaccess @@ -12,6 +12,9 @@ Options -MultiViews <IfModule mod_rewrite.c> RewriteEngine On + ## you can put here your pub/static folder path relative to web root + #RewriteBase /magento/pub/static/ + # Remove signature of the static files that is used to overcome the browser cache RewriteRule ^version.+?/(.+)$ $1 [L] diff --git a/setup/performance-toolkit/benchmark.jmx b/setup/performance-toolkit/benchmark.jmx index 06f41bc36ad9f..304e02f6e0a65 100644 --- a/setup/performance-toolkit/benchmark.jmx +++ b/setup/performance-toolkit/benchmark.jmx @@ -2936,8 +2936,63 @@ if (testLabel <stringProp name="RegexExtractor.match_number">-1</stringProp> </RegexExtractor> <hashTree/> + <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Regular Expression Extractor: isPageCacheable" enabled="true"> + <stringProp name="RegexExtractor.useHeaders">false</stringProp> + <stringProp name="RegexExtractor.refname">isPageCacheable</stringProp> + <stringProp name="RegexExtractor.regex">catalogsearch/searchTermsLog/save</stringProp> + <stringProp name="RegexExtractor.template">$0$</stringProp> + <stringProp name="RegexExtractor.default">0</stringProp> + <stringProp name="RegexExtractor.match_number">1</stringProp> + </RegexExtractor> + <hashTree/> </hashTree> + <IfController guiclass="IfControllerPanel" testclass="IfController" testname="If Controller" enabled="true"> + <stringProp name="IfController.condition">"${isPageCacheable}" != "0"</stringProp> + <boolProp name="IfController.evaluateAll">false</boolProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/search/if_page_cacheable_controller.jmx</stringProp></IfController> + <hashTree> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Search Terms Log" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"> + <elementProp name="q" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.name">q</stringProp> + <stringProp name="Argument.value">${searchTerm}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + </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}catalogsearch/searchTermsLog/save/</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/search/search_terms_log_save.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion: Assert search result" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-547797305">"success":true</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> + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - Set Arguments" enabled="true"> <stringProp name="BeanShellSampler.query"> foundProducts = Integer.parseInt(vars.get("product_url_keys_matchNr")); @@ -3179,8 +3234,63 @@ if (testLabel <stringProp name="RegexExtractor.match_number">-1</stringProp> </RegexExtractor> <hashTree/> + <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Regular Expression Extractor: isPageCacheable" enabled="true"> + <stringProp name="RegexExtractor.useHeaders">false</stringProp> + <stringProp name="RegexExtractor.refname">isPageCacheable</stringProp> + <stringProp name="RegexExtractor.regex">catalogsearch/searchTermsLog/save</stringProp> + <stringProp name="RegexExtractor.template">$0$</stringProp> + <stringProp name="RegexExtractor.default">0</stringProp> + <stringProp name="RegexExtractor.match_number">1</stringProp> + </RegexExtractor> + <hashTree/> </hashTree> + <IfController guiclass="IfControllerPanel" testclass="IfController" testname="If Controller" enabled="true"> + <stringProp name="IfController.condition">"${isPageCacheable}" != "0"</stringProp> + <boolProp name="IfController.evaluateAll">false</boolProp> + <stringProp name="TestPlan.comments">mpaf/tool/fragments/ce/search/if_page_cacheable_controller.jmx</stringProp></IfController> + <hashTree> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Search Terms Log" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"> + <elementProp name="q" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.name">q</stringProp> + <stringProp name="Argument.value">${searchTerm}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + </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}catalogsearch/searchTermsLog/save/</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/search/search_terms_log_save.jmx</stringProp> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion: Assert search result" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-547797305">"success":true</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> + <IfController guiclass="IfControllerPanel" testclass="IfController" testname="If Attribute 1 present in layered navigation" enabled="true"> <stringProp name="IfController.condition">${attribute_1_options_count} > 0</stringProp> <boolProp name="IfController.evaluateAll">false</boolProp> diff --git a/setup/src/Magento/Setup/Console/Command/InstallCommand.php b/setup/src/Magento/Setup/Console/Command/InstallCommand.php index f978d4a6f5c7f..889557a380e05 100644 --- a/setup/src/Magento/Setup/Console/Command/InstallCommand.php +++ b/setup/src/Magento/Setup/Console/Command/InstallCommand.php @@ -67,6 +67,16 @@ class InstallCommand extends AbstractSetupCommand */ const INPUT_KEY_INTERACTIVE_SETUP_SHORTCUT = 'i'; + /** + * Parameter says that in this mode all destructive operations, like column removal will be dumped + */ + const INPUT_KEY_SAFE_INSTALLER_MODE = 'safe-mode'; + + /** + * Parameter allows to restore data, that was dumped with safe mode before + */ + const INPUT_KEY_DATA_RESTORE = 'data-restore'; + /** * Regex for sales_order_increment_prefix validation. */ @@ -175,6 +185,18 @@ protected function configure() InputOption::VALUE_NONE, 'Interactive Magento instalation' ), + new InputOption( + self::INPUT_KEY_SAFE_INSTALLER_MODE, + null, + InputOption::VALUE_NONE, + 'Safe installation of Magento with dumps on destructive operations, like column removal' + ), + new InputOption( + self::INPUT_KEY_DATA_RESTORE, + null, + InputOption::VALUE_NONE, + 'Restore removed data from dumps' + ), ]); $this->setName('setup:install') ->setDescription('Installs the Magento application') diff --git a/setup/src/Magento/Setup/Console/Command/MaintenanceAllowIpsCommand.php b/setup/src/Magento/Setup/Console/Command/MaintenanceAllowIpsCommand.php index 3df2825dfec1d..c2f4d6fce0d59 100644 --- a/setup/src/Magento/Setup/Console/Command/MaintenanceAllowIpsCommand.php +++ b/setup/src/Magento/Setup/Console/Command/MaintenanceAllowIpsCommand.php @@ -24,6 +24,7 @@ class MaintenanceAllowIpsCommand extends AbstractSetupCommand */ const INPUT_KEY_IP = 'ip'; const INPUT_KEY_NONE = 'none'; + const INPUT_KEY_ADD = 'add'; /** * @var MaintenanceMode @@ -69,6 +70,12 @@ protected function configure() InputOption::VALUE_NONE, 'Clear allowed IP addresses' ), + new InputOption( + self::INPUT_KEY_ADD, + null, + InputOption::VALUE_NONE, + 'Add the IP address to existing list' + ), ]; $this->setName('maintenance:allow-ips') ->setDescription('Sets maintenance mode exempt IPs') @@ -91,9 +98,12 @@ protected function execute(InputInterface $input, OutputInterface $output) } if (!empty($addresses)) { + if ($input->getOption(self::INPUT_KEY_ADD)) { + $addresses = array_unique(array_merge($this->maintenanceMode->getAddressInfo(), $addresses)); + } $this->maintenanceMode->setAddresses(implode(',', $addresses)); $output->writeln( - '<info>Set exempt IP-addresses: ' . implode(', ', $this->maintenanceMode->getAddressInfo()) . + '<info>Set exempt IP-addresses: ' . implode(' ', $this->maintenanceMode->getAddressInfo()) . '</info>' ); } diff --git a/setup/src/Magento/Setup/Console/Command/MaintenanceStatusCommand.php b/setup/src/Magento/Setup/Console/Command/MaintenanceStatusCommand.php index 9162cc47f6bd9..0ac8095c31c0c 100644 --- a/setup/src/Magento/Setup/Console/Command/MaintenanceStatusCommand.php +++ b/setup/src/Magento/Setup/Console/Command/MaintenanceStatusCommand.php @@ -54,7 +54,7 @@ protected function execute(InputInterface $input, OutputInterface $output) ($this->maintenanceMode->isOn() ? 'active' : 'not active') . '</info>' ); $addressInfo = $this->maintenanceMode->getAddressInfo(); - $addresses = implode(', ', $addressInfo); + $addresses = implode(' ', $addressInfo); $output->writeln('<info>List of exempt IP-addresses: ' . ($addresses ? $addresses : 'none') . '</info>'); } } diff --git a/setup/src/Magento/Setup/Console/Command/ModuleUninstallCommand.php b/setup/src/Magento/Setup/Console/Command/ModuleUninstallCommand.php index 1d2d202a9590a..74ec0dd41e802 100644 --- a/setup/src/Magento/Setup/Console/Command/ModuleUninstallCommand.php +++ b/setup/src/Magento/Setup/Console/Command/ModuleUninstallCommand.php @@ -10,6 +10,7 @@ use Magento\Framework\App\MaintenanceMode; use Magento\Framework\Backup\Factory; use Magento\Framework\Composer\ComposerInformation; +use Magento\Framework\Console\Cli; use Magento\Framework\Module\DependencyChecker; use Magento\Framework\Module\FullModuleList; use Magento\Framework\Module\PackageInfo; @@ -17,6 +18,7 @@ use Magento\Setup\Model\ModuleRegistryUninstaller; use Magento\Setup\Model\ModuleUninstaller; use Magento\Setup\Model\ObjectManagerProvider; +use Magento\Setup\Model\Patch\PatchApplier; use Magento\Setup\Model\UninstallCollector; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; @@ -38,6 +40,7 @@ class ModuleUninstallCommand extends AbstractModuleCommand const INPUT_KEY_BACKUP_CODE = 'backup-code'; const INPUT_KEY_BACKUP_MEDIA = 'backup-media'; const INPUT_KEY_BACKUP_DB = 'backup-db'; + const INPUT_KEY_NON_COMPOSER_MODULE = 'non-composer'; /** * Deployment Configuration @@ -107,6 +110,11 @@ class ModuleUninstallCommand extends AbstractModuleCommand */ private $maintenanceModeEnabler; + /** + * @var PatchApplier + */ + private $patchApplier; + /** * Constructor * @@ -147,6 +155,19 @@ public function __construct( $maintenanceModeEnabler ?: $this->objectManager->get(MaintenanceModeEnabler::class); } + /** + * @return PatchApplier + */ + private function getPatchApplier() + { + if (!$this->patchApplier) { + $this->patchApplier = $this + ->objectManager->get(PatchApplier::class); + } + + return $this->patchApplier; + } + /** * {@inheritdoc} */ @@ -177,6 +198,12 @@ protected function configure() InputOption::VALUE_NONE, 'Take complete database backup' ), + new InputOption( + self::INPUT_KEY_NON_COMPOSER_MODULE, + null, + InputOption::VALUE_NONE, + 'All modules, that will be past here will be non composer based' + ) ]; $this->setName('module:uninstall') ->setDescription('Uninstalls modules installed by composer') @@ -195,6 +222,7 @@ protected function isModuleRequired() /** * {@inheritdoc} * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.NPathComplexity) */ protected function execute(InputInterface $input, OutputInterface $output) { @@ -207,6 +235,15 @@ protected function execute(InputInterface $input, OutputInterface $output) } $modules = $input->getArgument(self::INPUT_KEY_MODULES); + + if ($input->getOption(self::INPUT_KEY_NON_COMPOSER_MODULE)) { + foreach ($modules as $moduleName) { + $this->getPatchApplier()->revertDataPatches($moduleName); + } + + return Cli::RETURN_SUCCESS; + } + // validate modules input $messages = $this->validate($modules); if (!empty($messages)) { diff --git a/setup/src/Magento/Setup/Console/Command/UpgradeCommand.php b/setup/src/Magento/Setup/Console/Command/UpgradeCommand.php index da19c776fb205..07592f24205f3 100644 --- a/setup/src/Magento/Setup/Console/Command/UpgradeCommand.php +++ b/setup/src/Magento/Setup/Console/Command/UpgradeCommand.php @@ -81,7 +81,19 @@ protected function configure() InputOption::VALUE_OPTIONAL, 'Allows to convert old scripts (InstallSchema, UpgradeSchema) to db_schema.xml format', false - ) + ), + new InputOption( + InstallCommand::INPUT_KEY_SAFE_INSTALLER_MODE, + null, + InputOption::VALUE_NONE, + 'Safe installation of Magento with dumps on destructive operations, like column removal' + ), + new InputOption( + InstallCommand::INPUT_KEY_DATA_RESTORE, + null, + InputOption::VALUE_NONE, + 'Restore removed data from dumps' + ), ]; $this->setName('setup:upgrade') ->setDescription('Upgrades the Magento application, DB data, and schema') diff --git a/setup/src/Magento/Setup/Console/InputValidationException.php b/setup/src/Magento/Setup/Console/InputValidationException.php new file mode 100755 index 0000000000000..efa8a03bcfe49 --- /dev/null +++ b/setup/src/Magento/Setup/Console/InputValidationException.php @@ -0,0 +1,14 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Setup\Console; + +use Symfony\Component\Console\Exception\RuntimeException; + +class InputValidationException extends RuntimeException +{ + +} diff --git a/setup/src/Magento/Setup/Console/Style/MagentoStyle.php b/setup/src/Magento/Setup/Console/Style/MagentoStyle.php new file mode 100755 index 0000000000000..4dec01f9497e1 --- /dev/null +++ b/setup/src/Magento/Setup/Console/Style/MagentoStyle.php @@ -0,0 +1,602 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Setup\Console\Style; + +use Magento\Setup\Console\InputValidationException; +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Exception\RuntimeException; +use Symfony\Component\Console\Formatter\OutputFormatter; +use Symfony\Component\Console\Helper\Helper; +use Symfony\Component\Console\Helper\ProgressBar; +use Symfony\Component\Console\Helper\SymfonyQuestionHelper; +use Symfony\Component\Console\Helper\Table; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\BufferedOutput; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Question\ChoiceQuestion; +use Symfony\Component\Console\Question\ConfirmationQuestion; +use Symfony\Component\Console\Question\Question; +use Symfony\Component\Console\Style\OutputStyle; + +/** + * Magento console output decorator. + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class MagentoStyle extends OutputStyle implements MagentoStyleInterface +{ + /** + * Default console line max length(use for limitation in case terminal width greater than 120 characters). + */ + const MAX_LINE_LENGTH = 120; + + /** + * Console input provider. + * + * @var InputInterface + */ + private $input; + + /** + * Style Guide compliant question helper. + * + * @var SymfonyQuestionHelper + */ + private $questionHelper; + + /** + * Progress output provider. + * + * @var ProgressBar + */ + private $progressBar; + + /** + * Calculated output line length. + * + * @var int + */ + private $lineLength; + + /** + * Console output buffer provider. + * + * @var BufferedOutput + */ + private $bufferedOutput; + + /** + * MagentoStyle constructor. + * + * @param InputInterface $input + * @param OutputInterface $output + */ + public function __construct(InputInterface $input, OutputInterface $output) + { + $this->input = $input; + $this->bufferedOutput = new BufferedOutput($output->getVerbosity(), false, clone $output->getFormatter()); + // Windows cmd wraps lines as soon as the terminal width is reached, whether there are following chars or not. + $currentLength = $this->getTerminalWidth() - (int)(DIRECTORY_SEPARATOR === '\\'); + $this->lineLength = min($currentLength, self::MAX_LINE_LENGTH); + parent::__construct($output); + } + + /** + * Formats a message as a block of text. + * + * @param string|array $messages The message to write in the block + * @param string|null $type The block type (added in [] on first line) + * @param string|null $style The style to apply to the whole block + * @param string $prefix The prefix for the block + * @param bool $padding Whether to add vertical padding + * @return void + */ + public function block( + $messages, + string $type = null, + string $style = null, + string $prefix = ' ', + bool $padding = false + ) { + $messages = is_array($messages) ? array_values($messages) : [$messages]; + $this->autoPrependBlock(); + $this->writeln($this->createBlock($messages, $type, $style, $prefix, $padding)); + $this->newLine(); + } + + /** + * {@inheritdoc} + */ + public function title($message) + { + $this->autoPrependBlock(); + $bar = str_repeat('=', Helper::strlenWithoutDecoration($this->getFormatter(), $message)); + $this->writeln([ + sprintf(' <options=bold>%s</>', OutputFormatter::escapeTrailingBackslash($message)), + sprintf(' <options=bold>%s</>', $bar), + ]); + $this->newLine(); + } + + /** + * {@inheritdoc} + */ + public function section($message) + { + $this->autoPrependBlock(); + $bar = str_repeat('-', Helper::strlenWithoutDecoration($this->getFormatter(), $message)); + $this->writeln([ + sprintf(' <fg=white>%s</>', OutputFormatter::escapeTrailingBackslash($message)), + sprintf(' <fg=white>%s</>', $bar), + ]); + $this->newLine(); + } + + /** + * {@inheritdoc} + */ + public function listing(array $elements) + { + $this->autoPrependText(); + $elements = array_map(function ($element) { + return sprintf(' * %s', $element); + }, $elements); + + $this->writeln($elements); + $this->newLine(); + } + + /** + * {@inheritdoc} + */ + public function text($message) + { + $this->autoPrependText(); + $messages = is_array($message) ? array_values($message) : [$message]; + foreach ($messages as $singleMessage) { + $this->writeln(sprintf(' %s', $singleMessage)); + } + } + + /** + * Formats a command comment. + * + * @param string|array $message + * @param bool $padding + * @return void + */ + public function comment($message, $padding = false) + { + $this->block($message, null, 'comment', ' ', $padding); + } + + /** + * {@inheritdoc} + */ + public function success($message, $padding = true) + { + $this->block($message, 'SUCCESS', 'fg=black;bg=green', ' ', $padding); + } + + /** + * {@inheritdoc} + */ + public function error($message, $padding = true) + { + $this->block($message, 'ERROR', 'fg=white;bg=red', ' ', $padding); + } + + /** + * {@inheritdoc} + */ + public function warning($message, $padding = true) + { + $this->block($message, 'WARNING', 'fg=black;bg=yellow', ' ', $padding); + } + + /** + * {@inheritdoc} + */ + public function note($message, $padding = false) + { + $this->block($message, 'NOTE', 'fg=yellow', ' ', $padding); + } + + /** + * {@inheritdoc} + */ + public function caution($message, $padding = true) + { + $this->block($message, 'CAUTION', 'fg=black;bg=yellow', ' ! ', $padding); + } + + /** + * {@inheritdoc} + */ + public function table(array $headers, array $rows) + { + $style = clone Table::getStyleDefinition('symfony-style-guide'); + $style->setCellHeaderFormat('<info>%s</info>'); + + $table = new Table($this); + $table->setHeaders($headers); + $table->setRows($rows); + $table->setStyle($style); + + $table->render(); + $this->newLine(); + } + + /** + * {@inheritdoc} + * @throws \Symfony\Component\Console\Exception\InvalidArgumentException + */ + public function ask($question, $default = null, $validator = null, $maxAttempts = null) + { + $question = new Question($question, $default); + $question->setValidator($validator); + $question->setMaxAttempts($maxAttempts); + + return $this->askQuestion($question); + } + + /** + * {@inheritdoc} + * @throws \Symfony\Component\Console\Exception\LogicException + */ + public function askHidden($question, $validator = null) + { + $question = new Question($question); + + $question->setHidden(true); + $question->setValidator($validator); + + return $this->askQuestion($question); + } + + /** + * {@inheritdoc} + */ + public function confirm($question, $default = true) + { + return $this->askQuestion(new ConfirmationQuestion($question, $default)); + } + + /** + * {@inheritdoc} + */ + public function choice($question, array $choices, $default = null) + { + if (null !== $default) { + $values = array_flip($choices); + $default = $values[$default]; + } + + return $this->askQuestion(new ChoiceQuestion($question, $choices, $default)); + } + + /** + * {@inheritdoc} + */ + public function progressStart($max = 0) + { + $this->progressBar = $this->createProgressBar($max); + $this->progressBar->start(); + } + + /** + * {@inheritdoc} + * @throws \Symfony\Component\Console\Exception\LogicException + * @throws \Symfony\Component\Console\Exception\RuntimeException + */ + public function progressAdvance($step = 1) + { + $this->getProgressBar()->advance($step); + } + + /** + * {@inheritdoc} + * @throws \Symfony\Component\Console\Exception\RuntimeException + */ + public function progressFinish() + { + $this->getProgressBar()->finish(); + $this->newLine(2); + $this->progressBar = null; + } + + /** + * {@inheritdoc} + */ + public function createProgressBar($max = 0) + { + $progressBar = parent::createProgressBar($max); + $progressBar->setEmptyBarCharacter(' '); + $progressBar->setProgressCharacter('>'); + $progressBar->setBarCharacter('='); + + return $progressBar; + } + + /** + * Ask user question. + * + * @param Question $question + * + * @return string + */ + public function askQuestion(Question $question) + { + if ($this->input->isInteractive()) { + $this->autoPrependBlock(); + } + + if (!$this->questionHelper) { + $this->questionHelper = new SymfonyQuestionHelper(); + } + + $answer = $this->questionHelper->ask($this->input, $this, $question); + + if ($this->input->isInteractive()) { + $this->newLine(); + $this->bufferedOutput->write(PHP_EOL); + } + + return $answer; + } + + /** + * Ask for an missing argument. + * + * @param string $argument + * @param string $question + * @param string|null $default + * @param callable|null $validator + * @param int|null $maxAttempts + * @param bool $comment + * @param string $commentFormat + * @throws \Symfony\Component\Console\Exception\InvalidArgumentException + */ + public function askForMissingArgument( + string $argument, + string $question, + string $default = null, + callable $validator = null, + int $maxAttempts = null, + bool $comment = null, + string $commentFormat = 'Argument [%s] set to: %s' + ) { + try { + if ($this->input->getArgument($argument) === null) { + $this->input->setArgument($argument, $this->ask($question, $default, $validator, $maxAttempts)); + } + $argumentValue = $this->input->getArgument($argument); + $validated = (is_callable($validator) ? $validator($argumentValue) : $argumentValue); + if ((bool)($comment ?? $this->isDebug())) { + $this->comment(sprintf($commentFormat, $argument, $validated)); + } + } catch (InputValidationException $e) { + $this->error('Validation Error: ' . $e->getMessage()); + $this->askForMissingArgument( + $argument, + $question, + $default, + $validator, + $maxAttempts, + $comment, + $commentFormat + ); + } + } + + /** + * Ask for an missing option. + * + * @param string $option + * @param string $question + * @param string|null $default + * @param callable|null $validator + * @param int|null $maxAttempts + * @param bool $comment + * @param string $commentFormat + * @throws \Symfony\Component\Console\Exception\InvalidArgumentException + */ + public function askForMissingOption( + string $option, + string $question, + string $default = null, + callable $validator = null, + int $maxAttempts = null, + bool $comment = null, + string $commentFormat = 'Option [%s] set to: %s' + ) { + try { + if (null === $this->input->getOption($option)) { + $this->input->setOption($option, $this->ask($question, $default, $validator, $maxAttempts)); + } + $optionValue = $this->input->getOption($option); + $validated = (is_callable($validator) ? $validator($optionValue) : $optionValue); + if ((bool)($comment ?? $this->isDebug())) { + $this->comment(sprintf($commentFormat, $option, $validated)); + } + } catch (InputValidationException $e) { + $this->error('Validation Error: ' . $e->getMessage()); + $this->askForMissingOption( + $option, + $question, + $default, + $validator, + $maxAttempts, + $comment, + $commentFormat + ); + } + } + + /** + * {@inheritdoc} + */ + public function writeln($messages, $type = self::OUTPUT_NORMAL) + { + parent::writeln($messages, $type); + $this->bufferedOutput->writeln($this->reduceBuffer($messages), $type); + } + + /** + * {@inheritdoc} + */ + public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL) + { + parent::write($messages, $newline, $type); + $this->bufferedOutput->write($this->reduceBuffer($messages), $newline, $type); + } + + /** + * {@inheritdoc} + */ + public function newLine($count = 1) + { + parent::newLine($count); + $this->bufferedOutput->write(str_repeat(PHP_EOL, $count)); + } + + /** + * Get progress bar instance. + * + * @return ProgressBar + * @throws RuntimeException in case progress bar hasn't been instantiated yet. + */ + private function getProgressBar() + { + if (!$this->progressBar) { + throw new RuntimeException('The ProgressBar is not started.'); + } + + return $this->progressBar; + } + + /** + * @return int + */ + private function getTerminalWidth() + { + $application = new Application(); + $dimensions = $application->getTerminalDimensions(); + + return $dimensions[0] ?: self::MAX_LINE_LENGTH; + } + + /** + * Add empty line before output element in case there were no empty lines before. + * + * @return void + */ + private function autoPrependBlock() + { + $chars = substr($this->bufferedOutput->fetch(), -2); + if (!isset($chars[0])) { + $this->newLine(); //empty history, so we should start with a new line. + } + //Prepend new line for each non LF chars (This means no blank line was output before) + $this->newLine(2 - substr_count($chars, PHP_EOL)); + } + + /** + * Add empty line before text(listing) output element. + * + * @return void + */ + private function autoPrependText() + { + $fetched = $this->bufferedOutput->fetch(); + //Prepend new line if last char isn't EOL: + if (PHP_EOL !== substr($fetched, -1)) { + $this->newLine(); + } + } + + private function reduceBuffer($messages) + { + // We need to know if the two last chars are PHP_EOL + // Preserve the last 4 chars inserted (PHP_EOL on windows is two chars) in the history buffer + return array_map(function ($value) { + return substr($value, -4); + }, array_merge([$this->bufferedOutput->fetch()], (array)$messages)); + } + + /** + * Build output in block style. + * + * @param array $messages + * @param string|null $type + * @param string|null $style + * @param string $prefix + * @param bool $padding + * @return array + */ + private function createBlock( + array $messages, + string $type = null, + string $style = null, + string $prefix = ' ', + bool $padding = false + ) { + $indentLength = 0; + $prefixLength = Helper::strlenWithoutDecoration($this->getFormatter(), $prefix); + if (null !== $type) { + $type = sprintf('[%s] ', $type); + $indentLength = strlen($type); + $lineIndentation = str_repeat(' ', $indentLength); + } + $lines = $this->getBlockLines($messages, $prefixLength, $indentLength); + $firstLineIndex = 0; + if ($padding && $this->isDecorated()) { + $firstLineIndex = 1; + array_unshift($lines, ''); + $lines[] = ''; + } + foreach ($lines as $i => &$line) { + if (null !== $type) { + $line = $firstLineIndex === $i ? $type . $line : $lineIndentation . $line; + } + $line = $prefix . $line; + $multiplier = $this->lineLength - Helper::strlenWithoutDecoration($this->getFormatter(), $line); + $line .= str_repeat(' ', $multiplier); + if ($style) { + $line = sprintf('<%s>%s</>', $style, $line); + } + } + + return $lines; + } + + /** + * Wrap and add new lines for each element. + * + * @param array $messages + * @param int $prefixLength + * @param int $indentLength + * @return array + */ + private function getBlockLines( + array $messages, + int $prefixLength, + int $indentLength + ) { + $lines = [[]]; + foreach ($messages as $key => $message) { + $message = OutputFormatter::escape($message); + $wordwrap = wordwrap($message, $this->lineLength - $prefixLength - $indentLength, PHP_EOL, true); + $lines[] = explode(PHP_EOL, $wordwrap); + if (count($messages) > 1 && $key < count($messages) - 1) { + $lines[][] = ''; + } + } + $lines = array_merge(...$lines); + + return $lines; + } +} diff --git a/setup/src/Magento/Setup/Console/Style/MagentoStyleInterface.php b/setup/src/Magento/Setup/Console/Style/MagentoStyleInterface.php new file mode 100755 index 0000000000000..a7aba31549699 --- /dev/null +++ b/setup/src/Magento/Setup/Console/Style/MagentoStyleInterface.php @@ -0,0 +1,17 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Setup\Console\Style; + +use Symfony\Component\Console\Style\StyleInterface; + +/** + * Interface for output decorator. + */ +interface MagentoStyleInterface extends StyleInterface +{ + +} diff --git a/setup/src/Magento/Setup/Fixtures/ConfigurableProductsFixture.php b/setup/src/Magento/Setup/Fixtures/ConfigurableProductsFixture.php index 420149c79e29a..938a23071feda 100644 --- a/setup/src/Magento/Setup/Fixtures/ConfigurableProductsFixture.php +++ b/setup/src/Magento/Setup/Fixtures/ConfigurableProductsFixture.php @@ -552,7 +552,7 @@ private function getConfigurableProductConfig() if (count($skuPull) !== count(array_unique($skuPull))) { throw new ValidatorException( - __('Sku pattern for configurable product must be unique per attribute set') + __("The configurable product's SKU pattern must be unique in an attribute set.") ); } @@ -591,7 +591,9 @@ private function prepareConfigurableConfig($defaultAttributeSets) } } } else { - throw new ValidatorException(__('Configurable product config is invalid')); + throw new ValidatorException( + __('The configurable product config is invalid. Verify the product and try again.') + ); } return $configurableConfigs; diff --git a/setup/src/Magento/Setup/Fixtures/ImagesFixture.php b/setup/src/Magento/Setup/Fixtures/ImagesFixture.php index 0d8cb7493ff84..84081412335ac 100644 --- a/setup/src/Magento/Setup/Fixtures/ImagesFixture.php +++ b/setup/src/Magento/Setup/Fixtures/ImagesFixture.php @@ -184,13 +184,13 @@ public function printInfo(OutputInterface $output) if (!isset($config['images-count'])) { throw new ValidatorException( - __('Please, specify amount of images to generate') + __("The amount of images to generate wasn't specified. Enter the amount and try again.") ); } if (!isset($config['images-per-product'])) { throw new ValidatorException( - __('Please, specify amount of images per product') + __("The amount of images per product wasn't specified. Enter the amount and try again.") ); } diff --git a/setup/src/Magento/Setup/Model/AdminAccount.php b/setup/src/Magento/Setup/Model/AdminAccount.php index 0fe08794f6a2a..87b113a2c4b34 100644 --- a/setup/src/Magento/Setup/Model/AdminAccount.php +++ b/setup/src/Magento/Setup/Model/AdminAccount.php @@ -165,7 +165,7 @@ public function validateUserMatches() { if (empty($this->data[self::KEY_PASSWORD])) { throw new \Exception( - 'Password is a required field.' + '"Password" is required. Enter and try again.' ); } diff --git a/setup/src/Magento/Setup/Model/ConfigOptionsList/Session.php b/setup/src/Magento/Setup/Model/ConfigOptionsList/Session.php index 3b3fbf33a02e2..c0ec78f046e23 100644 --- a/setup/src/Magento/Setup/Model/ConfigOptionsList/Session.php +++ b/setup/src/Magento/Setup/Model/ConfigOptionsList/Session.php @@ -37,6 +37,10 @@ class Session implements ConfigOptionsListInterface const INPUT_KEY_SESSION_REDIS_DISABLE_LOCKING = 'session-save-redis-disable-locking'; const INPUT_KEY_SESSION_REDIS_MIN_LIFETIME = 'session-save-redis-min-lifetime'; const INPUT_KEY_SESSION_REDIS_MAX_LIFETIME = 'session-save-redis-max-lifetime'; + const INPUT_KEY_SESSION_REDIS_SENTINEL_SERVERS = 'session-save-redis-sentinel-servers'; + const INPUT_KEY_SESSION_REDIS_SENTINEL_MASTER = 'session-save-redis-sentinel-master'; + const INPUT_KEY_SESSION_REDIS_SENTINEL_VERIFY_MASTER = 'session-save-redis-sentinel-verify-master'; + const INPUT_KEY_SESSION_REDIS_SENTINEL_CONNECT_RETRIES = 'session-save-redis-sentinel-connect-retires'; const CONFIG_PATH_SESSION_REDIS = 'session/redis'; const CONFIG_PATH_SESSION_REDIS_HOST = 'session/redis/host'; @@ -57,6 +61,10 @@ class Session implements ConfigOptionsListInterface const CONFIG_PATH_SESSION_REDIS_DISABLE_LOCKING = 'session/redis/disable_locking'; const CONFIG_PATH_SESSION_REDIS_MIN_LIFETIME = 'session/redis/min_lifetime'; const CONFIG_PATH_SESSION_REDIS_MAX_LIFETIME = 'session/redis/max_lifetime'; + const CONFIG_PATH_SESSION_REDIS_SENTINEL_SERVERS = 'session/redis/sentinel_servers'; + const CONFIG_PATH_SESSION_REDIS_SENTINEL_MASTER = 'session/redis/sentinel_master'; + const CONFIG_PATH_SESSION_REDIS_SENTINEL_VERIFY_MASTER = 'session/redis/sentinel_verify_master'; + const CONFIG_PATH_SESSION_REDIS_SENTINEL_CONNECT_RETRIES = 'session/redis/sentinel_connect_retries'; /** * @var array @@ -80,7 +88,9 @@ class Session implements ConfigOptionsListInterface self::INPUT_KEY_SESSION_REDIS_BOT_LIFETIME => '7200', self::INPUT_KEY_SESSION_REDIS_DISABLE_LOCKING => '0', self::INPUT_KEY_SESSION_REDIS_MIN_LIFETIME => '60', - self::INPUT_KEY_SESSION_REDIS_MAX_LIFETIME => '2592000' + self::INPUT_KEY_SESSION_REDIS_MAX_LIFETIME => '2592000', + self::INPUT_KEY_SESSION_REDIS_SENTINEL_VERIFY_MASTER => '0', + self::INPUT_KEY_SESSION_REDIS_SENTINEL_CONNECT_RETRIES => '5', ]; /** @@ -121,6 +131,11 @@ class Session implements ConfigOptionsListInterface self::INPUT_KEY_SESSION_REDIS_DISABLE_LOCKING => self::CONFIG_PATH_SESSION_REDIS_DISABLE_LOCKING, self::INPUT_KEY_SESSION_REDIS_MIN_LIFETIME => self::CONFIG_PATH_SESSION_REDIS_MIN_LIFETIME, self::INPUT_KEY_SESSION_REDIS_MAX_LIFETIME => self::CONFIG_PATH_SESSION_REDIS_MAX_LIFETIME, + self::INPUT_KEY_SESSION_REDIS_SENTINEL_MASTER => self::CONFIG_PATH_SESSION_REDIS_SENTINEL_MASTER, + self::INPUT_KEY_SESSION_REDIS_SENTINEL_SERVERS => self::CONFIG_PATH_SESSION_REDIS_SENTINEL_SERVERS, + self::INPUT_KEY_SESSION_REDIS_SENTINEL_CONNECT_RETRIES => + self::CONFIG_PATH_SESSION_REDIS_SENTINEL_CONNECT_RETRIES, + self::INPUT_KEY_SESSION_REDIS_SENTINEL_VERIFY_MASTER => self::CONFIG_PATH_SESSION_REDIS_SENTINEL_VERIFY_MASTER, ]; /** @@ -246,6 +261,30 @@ public function getOptions() self::CONFIG_PATH_SESSION_REDIS_MAX_LIFETIME, 'Redis max session lifetime, in seconds' ), + new TextConfigOption( + self::INPUT_KEY_SESSION_REDIS_SENTINEL_MASTER, + TextConfigOption::FRONTEND_WIZARD_TEXT, + self::CONFIG_PATH_SESSION_REDIS_SENTINEL_MASTER, + 'Redis Sentinel master' + ), + new TextConfigOption( + self::INPUT_KEY_SESSION_REDIS_SENTINEL_SERVERS, + TextConfigOption::FRONTEND_WIZARD_TEXT, + self::INPUT_KEY_SESSION_REDIS_SENTINEL_SERVERS, + 'Redis Sentinel servers, comma separated' + ), + new TextConfigOption( + self::INPUT_KEY_SESSION_REDIS_SENTINEL_VERIFY_MASTER, + TextConfigOption::FRONTEND_WIZARD_TEXT, + self::CONFIG_PATH_SESSION_REDIS_SENTINEL_VERIFY_MASTER, + 'Redis Sentinel verify master. Values: false (default), true' + ), + new TextConfigOption( + self::INPUT_KEY_SESSION_REDIS_SENTINEL_CONNECT_RETRIES, + TextConfigOption::FRONTEND_WIZARD_TEXT, + self::CONFIG_PATH_SESSION_REDIS_SENTINEL_CONNECT_RETRIES, + 'Redis Sentinel connect retries.' + ), ]; } diff --git a/setup/src/Magento/Setup/Model/Declaration/Schema/DataSavior/ColumnSavior.php b/setup/src/Magento/Setup/Model/Declaration/Schema/DataSavior/ColumnSavior.php new file mode 100644 index 0000000000000..039fd293cf3fc --- /dev/null +++ b/setup/src/Magento/Setup/Model/Declaration/Schema/DataSavior/ColumnSavior.php @@ -0,0 +1,173 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Setup\Model\Declaration\Schema\DataSavior; + +use Magento\Framework\App\ResourceConnection; +use Magento\Framework\DB\SelectFactory; +use Magento\Setup\Model\Declaration\Schema\Dto\Column; +use Magento\Setup\Model\Declaration\Schema\Dto\ElementInterface; +use Magento\Setup\Model\Declaration\Schema\Dto\Table; + +/** + * Allows to dump and restore data for one specific field + */ +class ColumnSavior implements DataSaviorInterface +{ + /** + * @var SelectGeneratorFactory + */ + private $selectGeneratorFactory; + + /** + * @var ResourceConnection + */ + private $resourceConnection; + + /** + * @var UniqueConstraintsResolver + */ + private $uniqueConstraintsResolver; + + /** + * @var DumpAccessorInterface + */ + private $dumpAccessor; + + /** + * @var SelectFactory + */ + private $selectFactory; + + /** + * TableDump constructor. + * @param ResourceConnection $resourceConnection + * @param SelectGeneratorFactory $selectGeneratorFactory + * @param DumpAccessorInterface $dumpAccessor + * @param UniqueConstraintsResolver $uniqueConstraintsResolver + * @param SelectFactory $selectFactory + */ + public function __construct( + ResourceConnection $resourceConnection, + SelectGeneratorFactory $selectGeneratorFactory, + DumpAccessorInterface $dumpAccessor, + UniqueConstraintsResolver $uniqueConstraintsResolver, + SelectFactory $selectFactory + ) { + $this->selectGeneratorFactory = $selectGeneratorFactory; + $this->resourceConnection = $resourceConnection; + $this->uniqueConstraintsResolver = $uniqueConstraintsResolver; + $this->dumpAccessor = $dumpAccessor; + $this->selectFactory = $selectFactory; + } + + /** + * Prepare select to database + * + * @param Column $column + * @param array $fieldsToDump + * @return \Magento\Framework\DB\Select + */ + private function prepareColumnSelect(Column $column, array $fieldsToDump) + { + $adapter = $this->resourceConnection->getConnection($column->getTable()->getResource()); + $select = $this->selectFactory->create($adapter); + $select->from($column->getTable()->getName(), $fieldsToDump); + return $select; + } + + /** + * @inheritdoc + * @param Column | ElementInterface $column + * @return void + */ + public function dump(ElementInterface $column) + { + $columns = $this->uniqueConstraintsResolver->resolve($column->getTable()); + + /** + * Only if table have unique keys or primary key + */ + if ($columns) { + $connectionName = $column->getTable()->getResource(); + $columns[] = $column->getName(); + $select = $this->prepareColumnSelect($column, $columns); + $selectGenerator = $this->selectGeneratorFactory->create(); + $resourceSignature = $this->generateDumpFileSignature($column); + + foreach ($selectGenerator->generator($select, $connectionName) as $data) { + $this->dumpAccessor->save($resourceSignature, $data); + } + } + } + + /** + * Do Insert on duplicate to table, where field should be restored + * + * @param Table $table + * @param array $data + */ + private function applyDumpChunk(Table $table, $data) + { + $columns = []; + $adapter = $this->resourceConnection->getConnection($table->getResource()); + $firstRow = reset($data); + + /** + * Prepare all table fields + */ + foreach ($table->getColumns() as $column) { + $columns[$column->getName()] = $column->getName(); + } + + $adapter->insertOnDuplicate($table->getName(), $data, array_keys($firstRow)); + } + + /** + * @param Column | ElementInterface $column + * @return string + */ + private function generateDumpFileSignature(Column $column) + { + $dimensions = [ + $column->getTable()->getName(), + $column->getElementType(), + $column->getName() + ]; + + return implode("_", $dimensions); + } + + /** + * @param Column | ElementInterface $column + * @inheritdoc + */ + public function restore(ElementInterface $column) + { + $file = $this->generateDumpFileSignature($column); + $generator = $this->dumpAccessor->read($file); + + while ($generator->valid()) { + $data = $generator->current(); + $this->applyDumpChunk( + $column->getTable(), + $data + ); + $generator->next(); + } + + $this->dumpAccessor->destruct($file); + } + + /** + * @param ElementInterface $element + * @return bool + */ + public function isAcceptable(ElementInterface $element) + { + return $element instanceof Column; + } +} diff --git a/setup/src/Magento/Setup/Model/Declaration/Schema/DataSavior/DataSaviorInterface.php b/setup/src/Magento/Setup/Model/Declaration/Schema/DataSavior/DataSaviorInterface.php new file mode 100644 index 0000000000000..de404b4bd7bad --- /dev/null +++ b/setup/src/Magento/Setup/Model/Declaration/Schema/DataSavior/DataSaviorInterface.php @@ -0,0 +1,45 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Setup\Model\Declaration\Schema\DataSavior; + +use Magento\Setup\Model\Declaration\Schema\Dto\ElementInterface; + +/** + * This interface allows to dump data during declarative installation process + * and revert changes with applying previously saved data, if something goes wrong + */ +interface DataSaviorInterface +{ + /** + * Generate dump file by element + * + * For example, it can generate file for removed column is_allowed, in this case + * this file will consists of data in is_allowed column and additional data, that allows + * to identify each `is_allowed` value + * + * @param ElementInterface $element + * @return void + */ + public function dump(ElementInterface $element); + + /** + * Find the field, that was backed up by file name, and tries to restore data + * that is in this file + * + * @param ElementInterface $element + * @return mixed + */ + public function restore(ElementInterface $element); + + /** + * Check whether this element is acceptable by current implementation of data savior + * + * @param ElementInterface $element + * @return bool + */ + public function isAcceptable(ElementInterface $element); +} diff --git a/setup/src/Magento/Setup/Model/Declaration/Schema/DataSavior/DumpAccessorInterface.php b/setup/src/Magento/Setup/Model/Declaration/Schema/DataSavior/DumpAccessorInterface.php new file mode 100644 index 0000000000000..828ab8cc92f63 --- /dev/null +++ b/setup/src/Magento/Setup/Model/Declaration/Schema/DataSavior/DumpAccessorInterface.php @@ -0,0 +1,40 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Setup\Model\Declaration\Schema\DataSavior; + +/** + * Allows to access dump, that can be persisted in any file format or in database + */ +interface DumpAccessorInterface +{ + /** + * Allows to persist data to different sources: file, database, etc + * + * @param string $resource - can be for example absolute path to file + * @param array $data - data format, in which data should be stored + * @return void + */ + public function save($resource, array $data); + + /** + * Allows to read data by batches from different resources + * + * By resource means connection to database to absolute path to file, depends to implementation + * + * @param string $resource + * @return \Generator + */ + public function read($resource); + + /** + * Destruct resource + * + * @param string $resource + * @return void + */ + public function destruct($resource); +} diff --git a/setup/src/Magento/Setup/Model/Declaration/Schema/DataSavior/SelectGenerator.php b/setup/src/Magento/Setup/Model/Declaration/Schema/DataSavior/SelectGenerator.php new file mode 100644 index 0000000000000..28966e604c956 --- /dev/null +++ b/setup/src/Magento/Setup/Model/Declaration/Schema/DataSavior/SelectGenerator.php @@ -0,0 +1,69 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Setup\Model\Declaration\Schema\DataSavior; + +use Magento\Framework\App\ResourceConnection; +use Magento\Framework\Db\Select; + +/** + * Yields data from database by select objects + */ +class SelectGenerator +{ + /** + * @var int + */ + private $batchSize = 12000; + + /** + * @var int + */ + private $baseBatchSize; + + /** + * @var ResourceConnection + */ + private $resourceConnection; + + /** + * TableDump constructor. + * @param ResourceConnection $resourceConnection + * @param int $baseBatchSize + */ + public function __construct( + ResourceConnection $resourceConnection, + $baseBatchSize = 15000 + ) { + $this->baseBatchSize = $baseBatchSize; + $this->resourceConnection = $resourceConnection; + } + + /** + * It retrieves data by batches + * + * Select generator do not know what data he will fetch, so you need to pass builded Select statement in it + * + * @param Select $select + * @param string $connectionName + * @return \Generator + */ + public function generator(Select $select, $connectionName) + { + $page = 0; + $select->limit($this->batchSize, $page * $this->batchSize); + $adapter = $this->resourceConnection->getConnection($connectionName); + $data = $adapter->fetchAll($select); + yield $data; + + while (count($data)) { + ++$page; + $select->limit($this->batchSize, $page * $this->batchSize + 1); + $data = $adapter->fetchAll($select); + yield $data; + } + } +} diff --git a/setup/src/Magento/Setup/Model/Declaration/Schema/DataSavior/SelectGeneratorFactory.php b/setup/src/Magento/Setup/Model/Declaration/Schema/DataSavior/SelectGeneratorFactory.php new file mode 100644 index 0000000000000..0dfdf7ff4b429 --- /dev/null +++ b/setup/src/Magento/Setup/Model/Declaration/Schema/DataSavior/SelectGeneratorFactory.php @@ -0,0 +1,48 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Setup\Model\Declaration\Schema\DataSavior; + +use Magento\Framework\ObjectManagerInterface; + +/** + * Factory which allows to create SQL select generator + */ +class SelectGeneratorFactory +{ + /** + * @var string + */ + private $instanceName; + + /** + * @var ObjectManagerInterface + */ + private $objectManager; + + /** + * SelectGeneratorFactory constructor. + * @param ObjectManagerInterface $objectManager + * @param string $instanceName + */ + public function __construct( + ObjectManagerInterface $objectManager, + $instanceName = SelectGenerator::class + ) { + $this->objectManager = $objectManager; + $this->instanceName = $instanceName; + } + + /** + * Create class instance with specified parameters + * + * @return SelectGenerator + */ + public function create() + { + return $this->objectManager->create($this->instanceName); + } +} diff --git a/setup/src/Magento/Setup/Model/Declaration/Schema/DataSavior/TableSavior.php b/setup/src/Magento/Setup/Model/Declaration/Schema/DataSavior/TableSavior.php new file mode 100644 index 0000000000000..7a715b81b5fb6 --- /dev/null +++ b/setup/src/Magento/Setup/Model/Declaration/Schema/DataSavior/TableSavior.php @@ -0,0 +1,155 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Setup\Model\Declaration\Schema\DataSavior; + +use Magento\Framework\App\ResourceConnection; +use Magento\Framework\DB\SelectFactory; +use Magento\Setup\Model\Declaration\Schema\Dto\ElementInterface; +use Magento\Setup\Model\Declaration\Schema\Dto\Table; + +/** + * Allows to dump and restore data for specific table + */ +class TableSavior implements DataSaviorInterface +{ + /** + * @var SelectGeneratorFactory + */ + private $selectGeneratorFactory; + + /** + * @var ResourceConnection + */ + private $resourceConnection; + + /** + * @var DumpAccessorInterface + */ + private $dumpAccessor; + + /** + * @var SelectFactory + */ + private $selectFactory; + + /** + * TableDump constructor. + * @param ResourceConnection $resourceConnection + * @param SelectGeneratorFactory $selectGeneratorFactory + * @param DumpAccessorInterface $dumpAccessor + * @param SelectFactory $selectFactory + */ + public function __construct( + ResourceConnection $resourceConnection, + SelectGeneratorFactory $selectGeneratorFactory, + DumpAccessorInterface $dumpAccessor, + SelectFactory $selectFactory + ) { + $this->selectGeneratorFactory = $selectGeneratorFactory; + $this->resourceConnection = $resourceConnection; + $this->dumpAccessor = $dumpAccessor; + $this->selectFactory = $selectFactory; + } + + /** + * Prepare select to database + * + * @param Table $table + * @return \Magento\Framework\DB\Select + */ + private function prepareTableSelect(Table $table) + { + $adapter = $this->resourceConnection->getConnection($table->getResource()); + $select = $this->selectFactory->create($adapter); + $select->from($table->getName()); + return $select; + } + + /** + * @inheritdoc + * @param Table | ElementInterface $table + * @return void + */ + public function dump(ElementInterface $table) + { + $connectionName = $table->getResource(); + $select = $this->prepareTableSelect($table); + $selectGenerator = $this->selectGeneratorFactory->create(); + $resourceSignature = $this->generateDumpFileSignature($table); + + foreach ($selectGenerator->generator($select, $connectionName) as $data) { + $this->dumpAccessor->save($resourceSignature, $data); + } + } + + /** + * Prepare list of column names + * + * @param Table $table + * @return array + */ + private function getTableColumnNames(Table $table) + { + $columns = []; + /** + * Prepare all table fields + */ + foreach ($table->getColumns() as $column) { + $columns[] = $column->getName(); + } + + return $columns; + } + + /** + * Do Insert to table, that should be restored + * + * @param Table $table + * @param array $data + */ + private function applyDumpChunk(Table $table, $data) + { + $columns = $this->getTableColumnNames($table); + $adapter = $this->resourceConnection->getConnection($table->getResource()); + $adapter->insertArray($table->getName(), $columns, $data); + } + + /** + * @param Table $table + * @return string + */ + private function generateDumpFileSignature(Table $table) + { + return $table->getName(); + } + + /** + * @param Table | ElementInterface $table + * @inheritdoc + */ + public function restore(ElementInterface $table) + { + $file = $this->generateDumpFileSignature($table); + $generator = $this->dumpAccessor->read($file); + + while ($generator->valid()) { + $data = $generator->current(); + $this->applyDumpChunk($table, $data); + $generator->next(); + } + + $this->dumpAccessor->destruct($file); + } + + /** + * @inheritdoc + */ + public function isAcceptable(ElementInterface $element) + { + return $element instanceof Table; + } +} diff --git a/setup/src/Magento/Setup/Model/Declaration/Schema/DataSavior/UniqueConstraintsResolver.php b/setup/src/Magento/Setup/Model/Declaration/Schema/DataSavior/UniqueConstraintsResolver.php new file mode 100644 index 0000000000000..1ac2f5648e998 --- /dev/null +++ b/setup/src/Magento/Setup/Model/Declaration/Schema/DataSavior/UniqueConstraintsResolver.php @@ -0,0 +1,41 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Setup\Model\Declaration\Schema\DataSavior; + +use Magento\Setup\Model\Declaration\Schema\Dto\Constraints\Internal; +use Magento\Setup\Model\Declaration\Schema\Dto\Table; + +/** + * Search for any unique constraints in table + */ +class UniqueConstraintsResolver +{ + /** + * Retrieve list of all columns that are in one unique constraints. Yields the first constraint and stop on it + * + * @param Table $table + * @return array | bool If method return false, it means that table do not have any unique constraints and can`t be + * processed + */ + public function resolve(Table $table) + { + $primaryKey = $table->getPrimaryConstraint(); + if ($primaryKey) { + return $primaryKey->getColumnNames(); + } + + $constraints = $table->getConstraints(); + + foreach ($constraints as $constraint) { + if ($constraint instanceof Internal) { + return $constraint->getColumnNames(); + } + } + + return false; + } +} diff --git a/setup/src/Magento/Setup/Model/Declaration/Schema/Db/MySQL/DDL/Triggers/MigrateDataFromAnotherTable.php b/setup/src/Magento/Setup/Model/Declaration/Schema/Db/MySQL/DDL/Triggers/MigrateDataFromAnotherTable.php index 237d93fc004db..015a2188b5870 100644 --- a/setup/src/Magento/Setup/Model/Declaration/Schema/Db/MySQL/DDL/Triggers/MigrateDataFromAnotherTable.php +++ b/setup/src/Magento/Setup/Model/Declaration/Schema/Db/MySQL/DDL/Triggers/MigrateDataFromAnotherTable.php @@ -7,6 +7,7 @@ namespace Magento\Setup\Model\Declaration\Schema\Db\MySQL\DDL\Triggers; use Magento\Framework\App\ResourceConnection; +use Magento\Framework\DB\SelectFactory; use Magento\Setup\Model\Declaration\Schema\Db\DDLTriggerInterface; use Magento\Setup\Model\Declaration\Schema\Dto\Column; use Magento\Setup\Model\Declaration\Schema\Dto\ElementInterface; @@ -27,14 +28,23 @@ class MigrateDataFromAnotherTable implements DDLTriggerInterface */ private $resourceConnection; + /** + * @var SelectFactory + */ + private $selectFactory; + /** * Constructor. * * @param ResourceConnection $resourceConnection + * @param SelectFactory $selectFactory */ - public function __construct(ResourceConnection $resourceConnection) - { + public function __construct( + ResourceConnection $resourceConnection, + SelectFactory $selectFactory + ) { $this->resourceConnection = $resourceConnection; + $this->selectFactory = $selectFactory; } /** @@ -59,12 +69,11 @@ public function getCallback(ElementInterface $column) $adapter = $this->resourceConnection->getConnection( $column->getTable()->getResource() ); - $select = $adapter->select() - ->setPart('disable_staging_preview', true) - ->from( - $this->resourceConnection->getTableName($tableMigrateFrom), - [$column->getName() => $columnMigrateFrom] - ); + $select = $this->selectFactory->create($adapter); + $select->from( + $this->resourceConnection->getTableName($tableMigrateFrom), + [$column->getName() => $columnMigrateFrom] + ); //Update only if table exists if ($adapter->isTableExists($tableMigrateFrom)) { $adapter->query( diff --git a/setup/src/Magento/Setup/Model/Declaration/Schema/Declaration/ReaderComposite.php b/setup/src/Magento/Setup/Model/Declaration/Schema/Declaration/ReaderComposite.php index 729eaf0fc5963..098f2f473b996 100644 --- a/setup/src/Magento/Setup/Model/Declaration/Schema/Declaration/ReaderComposite.php +++ b/setup/src/Magento/Setup/Model/Declaration/Schema/Declaration/ReaderComposite.php @@ -27,8 +27,6 @@ class ReaderComposite implements ReaderInterface private $deploymentConfig; /** - * Constructor. - * * @param DeploymentConfig $deploymentConfig * @param ReaderInterface[] $readers */ diff --git a/setup/src/Magento/Setup/Model/Declaration/Schema/Diff/Diff.php b/setup/src/Magento/Setup/Model/Declaration/Schema/Diff/Diff.php index 915e4d399810a..37f9ea4d223d9 100644 --- a/setup/src/Magento/Setup/Model/Declaration/Schema/Diff/Diff.php +++ b/setup/src/Magento/Setup/Model/Declaration/Schema/Diff/Diff.php @@ -9,12 +9,10 @@ use Magento\Developer\Console\Command\TablesWhitelistGenerateCommand; use Magento\Framework\Component\ComponentRegistrar; use Magento\Setup\Model\Declaration\Schema\Dto\ElementInterface; -use Magento\Setup\Model\Declaration\Schema\Dto\Schema; use Magento\Setup\Model\Declaration\Schema\Dto\Table; use Magento\Setup\Model\Declaration\Schema\Dto\TableElementInterface; use Magento\Setup\Model\Declaration\Schema\ElementHistory; use Magento\Setup\Model\Declaration\Schema\ElementHistoryFactory; -use Magento\Setup\Model\Declaration\Schema\Request; /** * Holds information about all changes between 2 schemas: db and declaration XML. @@ -41,16 +39,6 @@ class Diff implements DiffInterface */ private $whiteListTables = []; - /** - * @var Schema - */ - private $schema; - - /** - * @var Request - */ - private $request; - /** * @var ComponentRegistrar */ @@ -177,17 +165,6 @@ private function canBeRegistered(ElementInterface $object, $operation) return isset($whiteList[$object->getNameWithoutPrefix()]); } - /** - * Register request for installation. - * - * @param Request $request - * @return void - */ - public function registerInstallationRequest(Request $request) - { - $this->request = $request; - } - /** * Register DTO object. * @@ -215,34 +192,4 @@ public function register( $this->debugChanges[$operation][] = $history; return $this; } - - /** - * @inheritdoc - */ - public function registerSchema(Schema $schema) - { - $this->schema = $schema; - } - - /** - * Retrieve current schema. - * This function needs for rollback functionality. - * - * @return Schema - */ - public function getCurrentSchemaState() - { - return $this->schema; - } - - /** - * Request holds some information from cli command or UI - * like: save mode or dry-run mode. - * - * @return Request - */ - public function getCurrentInstallationRequest() - { - return $this->request; - } } diff --git a/setup/src/Magento/Setup/Model/Declaration/Schema/Diff/DiffInterface.php b/setup/src/Magento/Setup/Model/Declaration/Schema/Diff/DiffInterface.php index 44ba0212c3688..03e659d0b98d8 100644 --- a/setup/src/Magento/Setup/Model/Declaration/Schema/Diff/DiffInterface.php +++ b/setup/src/Magento/Setup/Model/Declaration/Schema/Diff/DiffInterface.php @@ -49,34 +49,4 @@ public function register( $operation, ElementInterface $oldDtoObject = null ); - - /** - * Register current state of schema to registry. - * - * @param Schema $schema - * @return void - */ - public function registerSchema(Schema $schema); - - /** - * Retrieve current schema object. - * - * @return Schema - */ - public function getCurrentSchemaState(); - - /** - * Return current installation request. - * - * @return Request - */ - public function getCurrentInstallationRequest(); - - /** - * Register installation request with all needed options. - * - * @param Request $request - * @return void - */ - public function registerInstallationRequest(Request $request); } diff --git a/setup/src/Magento/Setup/Model/Declaration/Schema/Dto/Factories/Table.php b/setup/src/Magento/Setup/Model/Declaration/Schema/Dto/Factories/Table.php index b9655fccdeafe..3e17ce30003f2 100644 --- a/setup/src/Magento/Setup/Model/Declaration/Schema/Dto/Factories/Table.php +++ b/setup/src/Magento/Setup/Model/Declaration/Schema/Dto/Factories/Table.php @@ -60,8 +60,15 @@ public function create(array $data) if ($data['engine'] === null) { $data['engine'] = self::DEFAULT_ENGINE; } - $data['nameWithoutPrefix'] = $data['name']; - $data['name'] = $this->resourceConnection->getTableName($data['name']); + $tablePrefix = $this->resourceConnection->getTablePrefix(); + $nameWithoutPrefix = $data['name']; + if (!empty($tablePrefix) && strpos($nameWithoutPrefix, $tablePrefix) === 0) { + $data['nameWithoutPrefix'] = str_replace($tablePrefix, "", $data['name']); + } else { + $data['name'] = $tablePrefix . $data['name']; + $data['nameWithoutPrefix'] = $nameWithoutPrefix; + } + return $this->objectManager->create($this->className, $data); } } diff --git a/setup/src/Magento/Setup/Model/Declaration/Schema/Dto/Table.php b/setup/src/Magento/Setup/Model/Declaration/Schema/Dto/Table.php index 3ff4a7a755563..7c97702e57883 100644 --- a/setup/src/Magento/Setup/Model/Declaration/Schema/Dto/Table.php +++ b/setup/src/Magento/Setup/Model/Declaration/Schema/Dto/Table.php @@ -140,7 +140,7 @@ public function getReferenceConstraints() * and can be only one for table * it name is allocated into it constraint * - * @return bool|Constraint + * @return bool|Internal */ public function getPrimaryConstraint() { diff --git a/setup/src/Magento/Setup/Model/Declaration/Schema/FileSystem/Csv.php b/setup/src/Magento/Setup/Model/Declaration/Schema/FileSystem/Csv.php index 01ddd11e963b9..def2123e6a778 100644 --- a/setup/src/Magento/Setup/Model/Declaration/Schema/FileSystem/Csv.php +++ b/setup/src/Magento/Setup/Model/Declaration/Schema/FileSystem/Csv.php @@ -6,17 +6,48 @@ namespace Magento\Setup\Model\Declaration\Schema\FileSystem; +use Magento\Framework\App\Filesystem\DirectoryList; + /** * CSV file operations wrapper. */ -class Csv +class Csv implements \Magento\Setup\Model\Declaration\Schema\DataSavior\DumpAccessorInterface { /** - * Default batch size. - * + * Folder where will be persisted all csv dumps + */ + const DUMP_FOLDER = 'declarative_dumps_csv'; + + /** * @var int */ - private $batchSize = 15000; + private $baseBatchSize; + + /** + * @var DirectoryList + */ + private $directoryList; + + /** + * @var \Magento\Framework\Filesystem\Driver\File + */ + private $fileDriver; + + /** + * Csv constructor. + * @param DirectoryList $directoryList + * @param \Magento\Framework\Filesystem\Driver\File $fileDriver + * @param int $baseBatchSize + */ + public function __construct( + DirectoryList $directoryList, + \Magento\Framework\Filesystem\Driver\File $fileDriver, + $baseBatchSize = 15000 + ) { + $this->baseBatchSize = $baseBatchSize; + $this->directoryList = $directoryList; + $this->fileDriver = $fileDriver; + } /** * Save to csv data with batches. @@ -27,7 +58,8 @@ class Csv */ public function save($file, array $data) { - if (!count($data)) { + $file = $this->prepareFile($file); + if (!count($data) || !$file) { return $this; } @@ -45,35 +77,101 @@ public function save($file, array $data) return $this; } + /** + * Prepare CSV file name + * + * @param string $file + * @return string | bool + */ + private function prepareFile($file) + { + $absolutePath = $this->directoryList->getPath(DirectoryList::VAR_DIR); + + if (!$this->fileDriver->isWritable($absolutePath)) { + return false; + } + $dumpsPath = $absolutePath . DIRECTORY_SEPARATOR . self::DUMP_FOLDER; + $this->ensureDirExists($dumpsPath); + $filePath = $dumpsPath . DIRECTORY_SEPARATOR . $file . '.csv'; + return $filePath; + } + + /** + * Create directory if not exists + * + * @param string $dir + */ + private function ensureDirExists($dir) + { + if (!$this->fileDriver->isExists($dir)) { + $this->fileDriver->createDirectory($dir); + } + } + /** * File read generator. * + * This generator allows to load to memory only batch, with which we need to work at the moment + * * @param string $file * @return \Generator */ - public function readGenerator($file) + public function read($file) { - $data = []; - if (!file_exists($file)) { - return; - } + $file = $this->prepareFile($file); + if (!$this->fileDriver->isReadable($file)) { + return []; + } + $data = []; $iterator = 0; $fh = fopen($file, 'r'); - yield fgetcsv($fh); + $headers = fgetcsv($fh); + $rowData = fgetcsv($fh); - while ($rowData = fgetcsv($fh)) { - if ($iterator++ > $this->batchSize) { + while ($rowData) { + if ($iterator++ > $this->baseBatchSize) { $iterator = 0; $finalData = $data; $data = []; - yield $finalData; + yield $this->processCsvData($finalData, $headers); } $data[] = $rowData; + $rowData = fgetcsv($fh); } fclose($fh); - yield $data; + yield $this->processCsvData($data, $headers); + } + + /** + * @param array $csvData + * @param array $headers + * @return array + */ + private function processCsvData(array $csvData, array $headers) + { + $result = []; + + foreach ($csvData as $rowIndex => $csvRow) { + foreach ($csvRow as $index => $item) { + $result[$rowIndex][$headers[$index]] = $item; + } + } + + return $result; + } + + /** + * @inheritdoc + */ + public function destruct($resource) + { + $file = $this->prepareFile($resource); + + if ($this->fileDriver->isExists($file)) { + $this->fileDriver->deleteFile($file); + } } } diff --git a/setup/src/Magento/Setup/Model/Declaration/Schema/Operations/AddColumn.php b/setup/src/Magento/Setup/Model/Declaration/Schema/Operations/AddColumn.php index c8a910a2cd463..86cf5859096e4 100644 --- a/setup/src/Magento/Setup/Model/Declaration/Schema/Operations/AddColumn.php +++ b/setup/src/Magento/Setup/Model/Declaration/Schema/Operations/AddColumn.php @@ -20,6 +20,7 @@ /** * Add column to table operation. + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class AddColumn implements OperationInterface { @@ -192,7 +193,7 @@ public function doOperation(ElementHistory $elementHistory) */ $element = $elementHistory->getNew(); $definition = $this->definitionAggregator->toDefinition($element); - + $statement = $this->dbSchemaWriter->addElement( $element->getName(), $element->getTable()->getResource(), diff --git a/setup/src/Magento/Setup/Model/Declaration/Schema/OperationsExecutor.php b/setup/src/Magento/Setup/Model/Declaration/Schema/OperationsExecutor.php index 1f87e43185bca..60f9b32912bf2 100644 --- a/setup/src/Magento/Setup/Model/Declaration/Schema/OperationsExecutor.php +++ b/setup/src/Magento/Setup/Model/Declaration/Schema/OperationsExecutor.php @@ -7,15 +7,22 @@ namespace Magento\Setup\Model\Declaration\Schema; use Magento\Framework\App\ResourceConnection; +use Magento\Setup\Console\Command\InstallCommand; +use Magento\Setup\Model\Declaration\Schema\DataSavior\DataSaviorInterface; use Magento\Setup\Model\Declaration\Schema\Db\DbSchemaWriterInterface; use Magento\Setup\Model\Declaration\Schema\Db\StatementAggregatorFactory; use Magento\Setup\Model\Declaration\Schema\Db\StatementFactory; use Magento\Setup\Model\Declaration\Schema\Diff\DiffInterface; +use Magento\Setup\Model\Declaration\Schema\Dto\ElementInterface; +use Magento\Setup\Model\Declaration\Schema\Operations\AddColumn; +use Magento\Setup\Model\Declaration\Schema\Operations\CreateTable; +use Magento\Setup\Model\Declaration\Schema\Operations\ReCreateTable; /** * Schema operations executor. * * Go through all available SQL operations and execute each one with data from change registry. + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class OperationsExecutor { @@ -49,6 +56,11 @@ class OperationsExecutor */ private $statementAggregatorFactory; + /** + * @var DataSaviorInterface[] + */ + private $dataSaviorsCollection; + /** * Constructor. * @@ -58,9 +70,11 @@ class OperationsExecutor * @param StatementFactory $statementFactory * @param DbSchemaWriterInterface $dbSchemaWriter * @param StatementAggregatorFactory $statementAggregatorFactory + * @param array $dataSaviorsCollection */ public function __construct( array $operations, + array $dataSaviorsCollection, Sharding $sharding, ResourceConnection $resourceConnection, StatementFactory $statementFactory, @@ -73,6 +87,7 @@ public function __construct( $this->statementFactory = $statementFactory; $this->dbSchemaWriter = $dbSchemaWriter; $this->statementAggregatorFactory = $statementAggregatorFactory; + $this->dataSaviorsCollection = $dataSaviorsCollection; } /** @@ -125,38 +140,113 @@ private function endSetupForAllConnections() } } + /** + * Check if during this operation we need to restore data + * + * @param OperationInterface $operation + * @return bool + */ + private function operationIsOppositeToDestructive(OperationInterface $operation) + { + return $operation instanceof AddColumn || + $operation instanceof CreateTable || + $operation instanceof ReCreateTable; + } + /** * Loop through all operations that are configured in di.xml - * and execute them with elements from ChangeRegistry. + * and execute them with elements from Diff. * * @see OperationInterface * @param DiffInterface $diff + * @param array $requestData * @return void * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) */ - public function execute(DiffInterface $diff) + public function execute(DiffInterface $diff, array $requestData) { $this->startSetupForAllConnections(); $tableHistories = $diff->getAll(); if (is_array($tableHistories)) { foreach ($tableHistories as $tableHistory) { + $destructiveElements = []; + $oppositeToDestructiveElements = []; $statementAggregator = $this->statementAggregatorFactory->create(); foreach ($this->operations as $operation) { if (isset($tableHistory[$operation->getOperationName()])) { /** @var ElementHistory $elementHistory */ foreach ($tableHistory[$operation->getOperationName()] as $elementHistory) { - $statementAggregator->addStatements( - $operation->doOperation($elementHistory) - ); + $statementAggregator->addStatements($operation->doOperation($elementHistory)); + + if ($operation->isOperationDestructive()) { + $destructiveElements[] = $elementHistory->getOld(); + } elseif ($this->operationIsOppositeToDestructive($operation)) { + $oppositeToDestructiveElements[] = $elementHistory->getNew(); + } } } } + + $this->doDump($destructiveElements, $requestData); $this->dbSchemaWriter->compile($statementAggregator); + $this->doRestore($oppositeToDestructiveElements, $requestData); } } $this->endSetupForAllConnections(); } + + /** + * Do restore of destructive operations + * + * @param array $elements + * @param array $requestData + */ + private function doRestore(array $elements, array $requestData) + { + $restoreMode = isset($requestData[InstallCommand::INPUT_KEY_DATA_RESTORE]) && + $requestData[InstallCommand::INPUT_KEY_DATA_RESTORE]; + + if ($restoreMode) { + /** + * @var ElementInterface $element + */ + foreach ($elements as $element) { + foreach ($this->dataSaviorsCollection as $dataSavior) { + if ($dataSavior->isAcceptable($element)) { + $dataSavior->restore($element); + break; + } + } + } + } + } + + /** + * Do dump of destructive operations + * + * @param array $elements + * @param array $requestData + */ + private function doDump(array $elements, array $requestData) + { + $safeMode = isset($requestData[InstallCommand::INPUT_KEY_SAFE_INSTALLER_MODE]) && + $requestData[InstallCommand::INPUT_KEY_SAFE_INSTALLER_MODE]; + + if ($safeMode) { + /** + * @var ElementInterface $element + */ + foreach ($elements as $element) { + foreach ($this->dataSaviorsCollection as $dataSavior) { + if ($dataSavior->isAcceptable($element)) { + $dataSavior->dump($element); + break; + } + } + } + } + } } diff --git a/setup/src/Magento/Setup/Model/DeclarationInstaller.php b/setup/src/Magento/Setup/Model/DeclarationInstaller.php index 0c58d1dffe45f..884ae4fdf6da0 100644 --- a/setup/src/Magento/Setup/Model/DeclarationInstaller.php +++ b/setup/src/Magento/Setup/Model/DeclarationInstaller.php @@ -66,10 +66,6 @@ public function installSchema(array $requestData) $declarativeSchema = $this->schemaConfig->getDeclarationConfig(); $dbSchema = $this->schemaConfig->getDbConfig(); $diff = $this->schemaDiff->diff($declarativeSchema, $dbSchema); - $diff->registerSchema($declarativeSchema); - $diff->registerInstallationRequest( - $this->requestFactory->create($requestData) - ); - $this->operationsExecutor->execute($diff); + $this->operationsExecutor->execute($diff, $requestData); } } diff --git a/setup/src/Magento/Setup/Model/FixtureGenerator/EntityGenerator.php b/setup/src/Magento/Setup/Model/FixtureGenerator/EntityGenerator.php index c52cee9f5c184..cd9fd76077fb0 100644 --- a/setup/src/Magento/Setup/Model/FixtureGenerator/EntityGenerator.php +++ b/setup/src/Magento/Setup/Model/FixtureGenerator/EntityGenerator.php @@ -335,7 +335,9 @@ function ($ddl) use ($primaryTable) { } } if (!$foreignKey) { - throw new ValidatorException(__('Cannot find entity id field for table "%1"', $table)); + throw new ValidatorException( + __('The entity ID field for the "%1" table wasn\'t found. Verify the field and try again.', $table) + ); } $this->tableToEntityIdMap[$table] = current($foreignKey)['COLUMN_NAME']; } @@ -374,7 +376,9 @@ function ($data) { } ); if (!$ddl) { - throw new ValidatorException(__('Cannot find primary key for table "%1"', $table)); + throw new ValidatorException( + __('The primary key for the "%1" table wasn\'t found. Verify the key and try again.', $table) + ); } $this->tableToEntityIdMap[$table] = current($ddl)['COLUMN_NAME']; } diff --git a/setup/src/Magento/Setup/Model/Installer.php b/setup/src/Magento/Setup/Model/Installer.php index 7ae5f170d5b89..0fcb15e149b22 100644 --- a/setup/src/Magento/Setup/Model/Installer.php +++ b/setup/src/Magento/Setup/Model/Installer.php @@ -11,6 +11,7 @@ use Magento\Framework\App\DeploymentConfig\Writer; use Magento\Framework\App\Filesystem\DirectoryList; use Magento\Framework\App\MaintenanceMode; +use Magento\Framework\App\ObjectManager; use Magento\Framework\App\State\CleanupFiles; use Magento\Framework\Component\ComponentRegistrar; use Magento\Framework\Config\ConfigOptionsListConstants; @@ -27,6 +28,7 @@ use Magento\Framework\Setup\InstallSchemaInterface; use Magento\Framework\Setup\LoggerInterface; use Magento\Framework\Setup\ModuleDataSetupInterface; +use Magento\Framework\Setup\PatchApplierInterface; use Magento\Framework\Setup\SchemaPersistor; use Magento\Framework\Setup\SchemaSetupInterface; use Magento\Framework\Setup\UpgradeDataInterface; @@ -34,6 +36,12 @@ use Magento\Setup\Console\Command\InstallCommand; use Magento\Setup\Controller\ResponseTypeInterface; use Magento\Setup\Model\ConfigModel as SetupConfigModel; +use Magento\Setup\Model\Patch\PatchApplier; +use Magento\Setup\Model\Patch\PatchApplierFactory; +use Magento\Setup\Model\Patch\PatchHistory; +use Magento\Setup\Model\Patch\PatchReader; +use Magento\Setup\Model\Patch\PatchRegistry; +use Magento\Setup\Model\Patch\PatchRegistryFactory; use Magento\Setup\Module\ConnectionFactory; use Magento\Setup\Module\DataSetupFactory; use Magento\Setup\Module\SetupFactory; @@ -234,6 +242,11 @@ class Installer */ private $schemaPersistor; + /** + * @var PatchApplierFactory + */ + private $patchApplierFactory; + /** * Constructor * @@ -580,7 +593,6 @@ private function setupCoreTables(SchemaSetupInterface $setup) { /* @var $connection \Magento\Framework\DB\Adapter\AdapterInterface */ $connection = $setup->getConnection(); - $setup->startSetup(); $this->setupSessionTable($setup, $connection); @@ -875,6 +887,7 @@ private function throwExceptionForNotWritablePaths(array $paths) * @throws \Magento\Setup\Exception * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ private function handleDBSchemaData($setup, $type) { @@ -890,7 +903,25 @@ private function handleDBSchemaData($setup, $type) /** @var Mysql $adapter */ $adapter = $setup->getConnection(); $schemaListener = $adapter->getSchemaListener(); + $this->patchApplierFactory = $this->objectManagerProvider->get()->create( + PatchApplierFactory::class, + [ + 'objectManager' => $this->objectManagerProvider->get() + ] + ); + /** @var PatchApplier $patchApplier */ + if ($type === 'schema') { + $patchApplier = $this->patchApplierFactory->create(['schemaSetup' => $setup]); + } elseif ($type === 'data') { + $patchApplier = $this->patchApplierFactory->create([ + 'moduleDataSetup' => $setup, + 'objectManager' => $this->objectManagerProvider->get() + ]); + } + foreach ($moduleNames as $moduleName) { + $installer = false; + $upgrader = false; $schemaListener->setModuleName($moduleName); $this->log->log("Module '{$moduleName}':"); $configVer = $this->moduleList->getOne($moduleName)['setup_version']; @@ -903,11 +934,11 @@ private function handleDBSchemaData($setup, $type) if ($upgrader) { $this->log->logInline("Upgrading $type.. "); $upgrader->upgrade($setup, $moduleContextList[$moduleName]); - } - if ($type === 'schema') { - $resource->setDbVersion($moduleName, $configVer); - } elseif ($type === 'data') { - $resource->setDataVersion($moduleName, $configVer); + if ($type === 'schema') { + $resource->setDbVersion($moduleName, $configVer); + } elseif ($type === 'data') { + $resource->setDataVersion($moduleName, $configVer); + } } } } elseif ($configVer) { @@ -921,12 +952,25 @@ private function handleDBSchemaData($setup, $type) $this->log->logInline("Upgrading $type... "); $upgrader->upgrade($setup, $moduleContextList[$moduleName]); } + } + + if ($installer || $upgrader) { if ($type === 'schema') { $resource->setDbVersion($moduleName, $configVer); } elseif ($type === 'data') { $resource->setDataVersion($moduleName, $configVer); } } + + /** + * Applying data patches after old upgrade data scripts + */ + if ($type === 'schema') { + $patchApplier->applySchemaPatch($moduleName); + } elseif ($type === 'data') { + $patchApplier->applyDataPatch($moduleName); + } + $this->logProgress(); } diff --git a/setup/src/Magento/Setup/Model/InstallerFactory.php b/setup/src/Magento/Setup/Model/InstallerFactory.php index 15c68408f9564..0fb933dd46cb4 100644 --- a/setup/src/Magento/Setup/Model/InstallerFactory.php +++ b/setup/src/Magento/Setup/Model/InstallerFactory.php @@ -6,11 +6,9 @@ namespace Magento\Setup\Model; -use Magento\Setup\Model\Declaration\Schema\Generated\MysqlDumpSchemaParser; use Zend\ServiceManager\ServiceLocatorInterface; use Magento\Setup\Module\ResourceFactory; use Magento\Framework\App\ErrorHandler; -use Magento\Framework\App\State\CleanupFiles; use Magento\Framework\Setup\LoggerInterface; /** diff --git a/setup/src/Magento/Setup/Model/ModuleUninstaller.php b/setup/src/Magento/Setup/Model/ModuleUninstaller.php index b7d26b09a3754..270cebf7b57df 100644 --- a/setup/src/Magento/Setup/Model/ModuleUninstaller.php +++ b/setup/src/Magento/Setup/Model/ModuleUninstaller.php @@ -5,6 +5,7 @@ */ namespace Magento\Setup\Model; +use Magento\Setup\Model\Patch\PatchApplier; use Symfony\Component\Console\Output\OutputInterface; /** @@ -31,6 +32,10 @@ class ModuleUninstaller * @var \Magento\Setup\Module\SetupFactory */ private $setupFactory; + /** + * @var PatchApplier + */ + private $patchApplier; /** * Constructor @@ -39,6 +44,7 @@ class ModuleUninstaller * @param \Magento\Framework\Composer\Remove $remove * @param UninstallCollector $collector * @param \Magento\Setup\Module\SetupFactory $setupFactory + * @param PatchApplier $patchApplier */ public function __construct( ObjectManagerProvider $objectManagerProvider, @@ -52,6 +58,18 @@ public function __construct( $this->setupFactory = $setupFactory; } + /** + * @return PatchApplier + */ + private function getPatchApplier() + { + if (!$this->patchApplier) { + $this->patchApplier = $this->objectManager->get(PatchApplier::class); + } + + return $this->patchApplier; + } + /** * Invoke remove data routine in each specified module * @@ -71,9 +89,9 @@ public function uninstallData(OutputInterface $output, array $modules) $setupModel, new ModuleContext($resource->getDbVersion($module) ?: '') ); - } else { - $output->writeln("<info>No data to clear in $module</info>"); } + + $this->getPatchApplier()->revertDataPatches($module); } } diff --git a/setup/src/Magento/Setup/Model/Patch/DataPatchInterface.php b/setup/src/Magento/Setup/Model/Patch/DataPatchInterface.php new file mode 100644 index 0000000000000..2c81df6f176b6 --- /dev/null +++ b/setup/src/Magento/Setup/Model/Patch/DataPatchInterface.php @@ -0,0 +1,14 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Setup\Model\Patch; + +/** + * This interface describe script, that atomic operations with data (DML, DQL) in SQL database + * This is wrapper for @see PatchInterface in order to define what kind of patch we have + */ +interface DataPatchInterface extends PatchInterface +{ +} diff --git a/setup/src/Magento/Setup/Model/Patch/DependentPatchInterface.php b/setup/src/Magento/Setup/Model/Patch/DependentPatchInterface.php new file mode 100644 index 0000000000000..f0c20cbad466e --- /dev/null +++ b/setup/src/Magento/Setup/Model/Patch/DependentPatchInterface.php @@ -0,0 +1,33 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Setup\Model\Patch; + +/** + * Each patch can have dependecies, that should be applied before such patch + * + * / Patch2 --- Patch3 + * / + * / + * Patch1 + * + * Here you see dependency of Patch1 to Patch2 + */ +interface DependentPatchInterface +{ + /** + * Get array of patches that have to be executed prior to this. + * + * example of implementation: + * + * [ + * \Vendor_Name\Module_Name\Setup\Patch\Patch1::class, + * \Vendor_Name\Module_Name\Setup\Patch\Patch2::class + * ] + * + * @return string[] + */ + public static function getDependencies(); +} diff --git a/setup/src/Magento/Setup/Model/Patch/NonTransactionableInterface.php b/setup/src/Magento/Setup/Model/Patch/NonTransactionableInterface.php new file mode 100644 index 0000000000000..3b06f21de5c6e --- /dev/null +++ b/setup/src/Magento/Setup/Model/Patch/NonTransactionableInterface.php @@ -0,0 +1,13 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Setup\Model\Patch; + +/** + * Means that patch can`t be run in transaction + */ +interface NonTransactionableInterface +{ +} diff --git a/setup/src/Magento/Setup/Model/Patch/PatchApplier.php b/setup/src/Magento/Setup/Model/Patch/PatchApplier.php new file mode 100644 index 0000000000000..14ebd79add776 --- /dev/null +++ b/setup/src/Magento/Setup/Model/Patch/PatchApplier.php @@ -0,0 +1,269 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Setup\Model\Patch; + +use Magento\Framework\App\ResourceConnection; +use Magento\Framework\Module\ModuleResource; +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\Setup\ModuleDataSetupInterface; +use Magento\Setup\Exception; + +/** + * Apply patches per specific module + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class PatchApplier +{ + /** + * @var PatchRegistryFactory + */ + private $patchRegistryFactory; + + /** + * @var PatchReader + */ + private $dataPatchReader; + + /** + * @var PatchReader + */ + private $schemaPatchReader; + + /** + * @var ResourceConnection + */ + private $resourceConnection; + + /** + * @var ModuleResource + */ + private $moduleResource; + + /** + * @var PatchHistory + */ + private $patchHistory; + + /** + * @var PatchFactory + */ + private $patchFactory; + + /** + * @var \Magento\Framework\Setup\SetupInterface + */ + private $schemaSetup; + + /** + * @var ModuleDataSetupInterface + */ + private $moduleDataSetup; + + /** + * @var ObjectManagerInterface + */ + private $objectManager; + + /** + * PatchApplier constructor. + * @param PatchReader $dataPatchReader + * @param PatchReader $schemaPatchReader + * @param PatchRegistryFactory $patchRegistryFactory + * @param ResourceConnection $resourceConnection + * @param ModuleResource $moduleResource + * @param PatchHistory $patchHistory + * @param PatchFactory $patchFactory + * @param ObjectManagerInterface $objectManager + * @param \Magento\Framework\Setup\SchemaSetupInterface $schemaSetup + * @param ModuleDataSetupInterface $moduleDataSetup + * @SuppressWarnings(PHPMD.ExcessiveParameterList) + */ + public function __construct( + PatchReader $dataPatchReader, + PatchReader $schemaPatchReader, + PatchRegistryFactory $patchRegistryFactory, + ResourceConnection $resourceConnection, + ModuleResource $moduleResource, + PatchHistory $patchHistory, + PatchFactory $patchFactory, + ObjectManagerInterface $objectManager, + \Magento\Framework\Setup\SchemaSetupInterface $schemaSetup, + \Magento\Framework\Setup\ModuleDataSetupInterface $moduleDataSetup + ) { + $this->patchRegistryFactory = $patchRegistryFactory; + $this->dataPatchReader = $dataPatchReader; + $this->schemaPatchReader = $schemaPatchReader; + $this->resourceConnection = $resourceConnection; + $this->moduleResource = $moduleResource; + $this->patchHistory = $patchHistory; + $this->patchFactory = $patchFactory; + $this->schemaSetup = $schemaSetup; + $this->moduleDataSetup = $moduleDataSetup; + $this->objectManager = $objectManager; + } + + /** + * Check is patch skipable by data setup version in DB + * + * @param string $patchClassName + * @param string $moduleName + * @return bool + */ + private function isSkipableByDataSetupVersion(string $patchClassName, $moduleName) + { + $dbVersion = $this->moduleResource->getDataVersion($moduleName); + return in_array(PatchVersionInterface::class, class_implements($patchClassName)) && + version_compare(call_user_func([$patchClassName, 'getVersion']), $dbVersion) <= 0; + } + + /** + * Check is patch skipable by schema setup version in DB + * + * @param string $patchClassName + * @param string $moduleName + * @return bool + */ + private function isSkipableBySchemaSetupVersion(string $patchClassName, $moduleName) + { + $dbVersion = $this->moduleResource->getDbVersion($moduleName); + return in_array(PatchVersionInterface::class, class_implements($patchClassName)) && + version_compare(call_user_func([$patchClassName, 'getVersion']), $dbVersion) <= 0; + } + + /** + * Apply all patches for one module + * + * @param null | string $moduleName + * @throws Exception + */ + public function applyDataPatch($moduleName = null) + { + $dataPatches = $this->dataPatchReader->read($moduleName); + $registry = $this->prepareRegistry($dataPatches); + foreach ($registry as $dataPatch) { + /** + * Due to bacward compatabilities reasons some patches should be skipped + */ + if ($this->isSkipableByDataSetupVersion($dataPatch, $moduleName)) { + $this->patchHistory->fixPatch($dataPatch); + continue; + } + + $dataPatch = $this->objectManager->create( + '\\' . $dataPatch, + ['moduleDataSetup' => $this->moduleDataSetup] + ); + if (!$dataPatch instanceof DataPatchInterface) { + throw new Exception( + sprintf("Patch %s should implement DataPatchInterface", get_class($dataPatch)) + ); + } + if ($dataPatch instanceof NonTransactionableInterface) { + $dataPatch->apply(); + $this->patchHistory->fixPatch(get_class($dataPatch)); + } else { + try { + $this->moduleDataSetup->getConnection()->beginTransaction(); + $dataPatch->apply(); + $this->patchHistory->fixPatch(get_class($dataPatch)); + $this->moduleDataSetup->getConnection()->commit(); + } catch (\Exception $e) { + $this->moduleDataSetup->getConnection()->rollBack(); + throw new Exception($e->getMessage()); + } finally { + unset($dataPatch); + } + } + } + } + + /** + * Register all patches in registry in order to manipulate chains and dependencies of patches + * of patches + * + * @param array $patchNames + * @return PatchRegistry + */ + private function prepareRegistry(array $patchNames) + { + $registry = $this->patchRegistryFactory->create(); + + foreach ($patchNames as $patchName) { + $registry->registerPatch($patchName); + } + + return $registry; + } + + /** + * Apply all patches for one module + * + * @param null | string $moduleName + * @throws Exception + */ + public function applySchemaPatch($moduleName = null) + { + $schemaPatches = $this->schemaPatchReader->read($moduleName); + $registry = $this->prepareRegistry($schemaPatches); + + foreach ($registry as $schemaPatch) { + try { + /** + * Skip patches that were applied in old style + */ + if ($this->isSkipableBySchemaSetupVersion($schemaPatch, $moduleName)) { + $this->patchHistory->fixPatch($schemaPatch); + continue; + } + /** + * @var SchemaPatchInterface $schemaPatch + */ + $schemaPatch = $this->patchFactory->create($schemaPatch, ['schemaSetup' => $this->schemaSetup]); + $schemaPatch->apply(); + $this->patchHistory->fixPatch(get_class($schemaPatch)); + } catch (\Exception $e) { + throw new Exception($e->getMessage()); + } finally { + unset($schemaPatch); + } + } + } + + /** + * Revert data patches for specific module + * + * @param null | string $moduleName + * @throws Exception + */ + public function revertDataPatches($moduleName = null) + { + $dataPatches = $this->dataPatchReader->read($moduleName); + $registry = $this->prepareRegistry($dataPatches); + $adapter = $this->moduleDataSetup->getConnection(); + + foreach ($registry->getReverseIterator() as $dataPatch) { + $dataPatch = $this->objectManager->create( + '\\' . $dataPatch, + ['moduleDataSetup' => $this->moduleDataSetup] + ); + if ($dataPatch instanceof PatchRevertableInterface) { + try { + $adapter->beginTransaction(); + /** @var PatchRevertableInterface|DataPatchInterface $dataPatch */ + $dataPatch->revert(); + $this->patchHistory->revertPatchFromHistory(get_class($dataPatch)); + $adapter->commit(); + } catch (\Exception $e) { + $adapter->rollBack(); + throw new Exception($e->getMessage()); + } finally { + unset($dataPatch); + } + } + } + } +} diff --git a/setup/src/Magento/Setup/Model/Patch/PatchApplierFactory.php b/setup/src/Magento/Setup/Model/Patch/PatchApplierFactory.php new file mode 100644 index 0000000000000..69878e214fcd8 --- /dev/null +++ b/setup/src/Magento/Setup/Model/Patch/PatchApplierFactory.php @@ -0,0 +1,39 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Setup\Model\Patch; + +use Magento\Framework\ObjectManagerInterface; + +/** + * This factory allows to create data patches applier + */ +class PatchApplierFactory +{ + /** + * @var ObjectManagerInterface + */ + private $objectManager; + + /** + * @param ObjectManagerInterface $objectManager + */ + public function __construct(ObjectManagerInterface $objectManager) + { + $this->objectManager = $objectManager; + } + + /** + * Create new instance of patch applier + * + * @param array $arguments + * @return PatchInterface + */ + public function create($arguments = []) + { + return $this->objectManager->create(\Magento\Setup\Model\Patch\PatchApplier::class, $arguments); + } +} diff --git a/setup/src/Magento/Setup/Model/Patch/PatchFactory.php b/setup/src/Magento/Setup/Model/Patch/PatchFactory.php new file mode 100644 index 0000000000000..aec8dfbd52b5f --- /dev/null +++ b/setup/src/Magento/Setup/Model/Patch/PatchFactory.php @@ -0,0 +1,52 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Setup\Model\Patch; + +use Magento\Framework\ObjectManagerInterface; + +/** + * This factory allows to create data patches: + * @see PatchInterface + */ +class PatchFactory +{ + /** + * @var ObjectManagerInterface + */ + private $objectManager; + + /** + * @param ObjectManagerInterface $objectManager + */ + public function __construct(ObjectManagerInterface $objectManager) + { + $this->objectManager = $objectManager; + } + + /** + * Create new instance of patch + * + * @param string $instanceName + * @param array $arguments + * @return PatchInterface + */ + public function create($instanceName, $arguments = []) + { + $patchInstance = $this->objectManager->create('\\' . $instanceName, $arguments); + if (!$patchInstance instanceof PatchInterface) { + throw new \InvalidArgumentException( + sprintf( + "%s should implement %s interface", + $instanceName, + PatchInterface::class + ) + ); + } + + return $patchInstance; + } +} diff --git a/setup/src/Magento/Setup/Model/Patch/PatchHistory.php b/setup/src/Magento/Setup/Model/Patch/PatchHistory.php new file mode 100644 index 0000000000000..e05792eff9f9f --- /dev/null +++ b/setup/src/Magento/Setup/Model/Patch/PatchHistory.php @@ -0,0 +1,123 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Setup\Model\Patch; + +use Magento\Framework\App\ResourceConnection; + +/** + * This is registry of all patches, that are already applied on database + */ +class PatchHistory +{ + /** + * Table name where patche names will be persisted + */ + const TABLE_NAME = 'patch_list'; + + /** + * Name of a patch + */ + const CLASS_NAME = "patch_name"; + + /** + * Patch type for schema patches + */ + const SCHEMA_PATCH_TYPE = 'schema'; + + /** + * Patch type for data patches + */ + const DATA_PATCH_TYPE = 'data'; + + /** + * @var array + */ + private $patchesRegistry = null; + + /** + * @var ResourceConnection + */ + private $resourceConnection; + + /** + * PatchHistory constructor. + * @param ResourceConnection $resourceConnection + */ + public function __construct(ResourceConnection $resourceConnection) + { + $this->resourceConnection = $resourceConnection; + } + + /** + * Read and cache data patches from db + * + * All patches are store in patch_list table + * @see self::TABLE_NAME + * + * @return array + */ + private function getAppliedPatches() + { + if ($this->patchesRegistry === null) { + $adapter = $this->resourceConnection->getConnection(); + $filterSelect = $adapter + ->select() + ->from($this->resourceConnection->getTableName(self::TABLE_NAME), self::CLASS_NAME); + $this->patchesRegistry = $adapter->fetchCol($filterSelect); + } + + return $this->patchesRegistry; + } + + /** + * Fix patch in patch table in order to avoid reapplying of patch + * + * @param string $patchName + * @return void + */ + public function fixPatch($patchName) + { + if ($this->isApplied($patchName)) { + throw new \LogicException(sprintf("Patch %s cannot be applied twice", $patchName)); + } + + $adapter = $this->resourceConnection->getConnection(); + $adapter->insert($this->resourceConnection->getTableName(self::TABLE_NAME), [self::CLASS_NAME => $patchName]); + } + + /** + * Revert patch from history + * + * @param $patchName + * @return void + */ + public function revertPatchFromHistory($patchName) + { + if (!$this->isApplied($patchName)) { + throw new \LogicException( + sprintf("Patch %s should be applied, before you can revert it", $patchName) + ); + } + + $adapter = $this->resourceConnection->getConnection(); + $adapter->delete( + $this->resourceConnection->getTableName(self::TABLE_NAME), + [self::CLASS_NAME . "= ?" => $patchName] + ); + } + + /** + * Check whether patch was applied on the system or not + * + * @param string $patchName + * @return bool + */ + public function isApplied($patchName) + { + return in_array($patchName, $this->getAppliedPatches()); + } +} diff --git a/setup/src/Magento/Setup/Model/Patch/PatchInterface.php b/setup/src/Magento/Setup/Model/Patch/PatchInterface.php new file mode 100644 index 0000000000000..ecf1892878d87 --- /dev/null +++ b/setup/src/Magento/Setup/Model/Patch/PatchInterface.php @@ -0,0 +1,30 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Setup\Model\Patch; + +/** + * This interface describe script, that is presented by atomic operations for data and schema + */ +interface PatchInterface extends DependentPatchInterface +{ + /** + * Get aliases (previous names) for the patch. + * + * @return string[] + */ + public function getAliases(); + + /** + * Run code inside patch + * If code fails, patch must be reverted, in case when we are speaking about schema - than under revert + * means run PatchInterface::revert() + * + * If we speak about data, under revert means: $transaction->rollback() + * + * @return $this + */ + public function apply(); +} diff --git a/setup/src/Magento/Setup/Model/Patch/PatchReader.php b/setup/src/Magento/Setup/Model/Patch/PatchReader.php new file mode 100644 index 0000000000000..670828c171b66 --- /dev/null +++ b/setup/src/Magento/Setup/Model/Patch/PatchReader.php @@ -0,0 +1,122 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Setup\Model\Patch; + +use Magento\Framework\Component\ComponentRegistrar; +use Magento\Framework\Config\ReaderInterface; +use Magento\Framework\Filesystem\Glob; +use Magento\Framework\Module\Dir; + +/** + * Allows to read all patches through the whole system + */ +class PatchReader implements ReaderInterface +{ + /** + * Folder name, where patches are + */ + const SETUP_PATCH_FOLDER = 'Patch'; + + /** + * @var ComponentRegistrar + */ + private $componentRegistrar; + + /** + * @var string + */ + private $type; + + /** + * @param ComponentRegistrar $componentRegistrar + * @param string $type + */ + public function __construct( + ComponentRegistrar $componentRegistrar, + $type + ) { + $this->componentRegistrar = $componentRegistrar; + $this->type = $type; + } + + /** + * Retrieve absolute path to modules patch folder + * + * @param string $modulePath + * @return string + */ + private function getPatchFolder($modulePath) + { + return $modulePath . DIRECTORY_SEPARATOR . Dir::MODULE_SETUP_DIR . + DIRECTORY_SEPARATOR . self::SETUP_PATCH_FOLDER; + } + + /** + * Retrieve module name prepared to usage in namespaces + * + * @param string $moduleName + * @return string + */ + private function getModuleNameForNamespace($moduleName) + { + return str_replace('_', '\\', $moduleName); + } + + /** + * Depends on type we want to handle schema and data patches in different folders + * + * @return string + */ + private function getTypeFolder() + { + return ucfirst($this->type); + } + + /** + * Create array of class patch names from module name + * + * @param string $moduleName + * @param string $modulePath + * @return array + */ + private function getPatchClassesPerModule($moduleName, $modulePath) + { + $patchClasses = []; + $patchesPath = $this->getPatchFolder($modulePath); + $specificPatchPath = $patchesPath . DIRECTORY_SEPARATOR . $this->getTypeFolder(); + $patchesMask = $specificPatchPath . DIRECTORY_SEPARATOR . '*.php'; + + foreach (Glob::glob($patchesMask) as $patchPath) { + $moduleName = $this->getModuleNameForNamespace($moduleName); + $patchClasses[] = $moduleName . '\\Setup\\' . + self::SETUP_PATCH_FOLDER . '\\' . + $this->getTypeFolder() . '\\' . + basename($patchPath, '.php'); + } + + return $patchClasses; + } + + /** + * @param null $moduleName + * @return array + */ + public function read($moduleName = null) + { + $patches = []; + if ($moduleName === null) { + foreach ($this->componentRegistrar->getPaths(ComponentRegistrar::MODULE) as $moduleName => $modulePath) { + $patches += $this->getPatchClassesPerModule($moduleName, $modulePath); + } + } else { + $modulePath = $this->componentRegistrar->getPath(ComponentRegistrar::MODULE, $moduleName); + $patches = $this->getPatchClassesPerModule($moduleName, $modulePath); + } + + return $patches; + } +} diff --git a/setup/src/Magento/Setup/Model/Patch/PatchRegistry.php b/setup/src/Magento/Setup/Model/Patch/PatchRegistry.php new file mode 100644 index 0000000000000..a988b2a6ec6c6 --- /dev/null +++ b/setup/src/Magento/Setup/Model/Patch/PatchRegistry.php @@ -0,0 +1,223 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Setup\Model\Patch; + +/** + * Allows to read all patches through the whole system + */ +class PatchRegistry implements \IteratorAggregate +{ + /** + * + * @var array + */ + private $dependents = []; + + /** + * @var string[] + */ + private $patches = []; + + /** + * @var PatchFactory + */ + private $patchFactory; + + /** + * This classes need to do revert + * + * @var string[] + */ + private $appliedPatches = []; + + /** + * @var PatchHistory + */ + private $patchHistory; + + /** + * @var \Iterator + */ + private $iterator = null; + + /** + * @var \Iterator + */ + private $reverseIterator = null; + + /** + * @var array + */ + private $cyclomaticStack = []; + + /** + * PatchRegistry constructor. + * @param PatchFactory $patchFactory + * @param PatchHistory $patchHistory + */ + public function __construct(PatchFactory $patchFactory, PatchHistory $patchHistory) + { + $this->patchFactory = $patchFactory; + $this->patchHistory = $patchHistory; + } + + /** + * Register all dependents to patch + * + * @param string | DependentPatchInterface $patchName + */ + private function registerDependents(string $patchName) + { + $dependencies = $patchName::getDependencies(); + + foreach ($dependencies as $dependency) { + $this->dependents[$dependency][] = $patchName; + } + } + + /** + * Register patch and create chain of patches + * + * @param string $patchName + * @return PatchInterface | bool + */ + public function registerPatch(string $patchName) + { + if ($this->patchHistory->isApplied($patchName)) { + $this->appliedPatches[$patchName] = $patchName; + $this->registerDependents($patchName); + return false; + } + + if (isset($this->patches[$patchName])) { + return $this->patches[$patchName]; + } + + $patch = $patchName; + $this->patches[$patchName] = $patch; + return $patch; + } + + /** + * Retrieve all patches, that depends on current one + * + * @param string $patch + * @return string[] + */ + private function getDependentPatches(string $patch) + { + $patches = []; + $patchName = $patch; + + /** + * Let`s check if patch is dependency for other patches + */ + if (isset($this->dependents[$patchName])) { + foreach ($this->dependents[$patchName] as $dependent) { + if (isset($this->appliedPatches[$dependent])) { + $dependent = $this->appliedPatches[$dependent]; + $patches = array_replace($patches, $this->getDependentPatches($dependent)); + $patches[$dependent] = $dependent; + unset($this->appliedPatches[$dependent]); + } + } + } + + return $patches; + } + + /** + * @param string $patch + * @return string[] + */ + private function getDependencies(string $patch) + { + $depInstances = []; + $deps = call_user_func([$patch, 'getDependencies']); + $this->cyclomaticStack[$patch] = true; + + foreach ($deps as $dep) { + if (isset($this->cyclomaticStack[$dep])) { + throw new \LogicException("Cyclomatic dependency during patch installation"); + } + + $depInstance = $this->registerPatch($dep); + /** + * If a patch already have applied dependency - than we definently know + * that all other dependencies in dependency chain are applied too, so we can skip this dep + */ + if (!$depInstance) { + continue; + } + + $depInstances = array_replace($depInstances, $this->getDependencies($this->patches[$dep])); + $depInstances[$depInstance] = $depInstance; + } + + unset($this->cyclomaticStack[$patch]); + return $depInstances; + } + + /** + * If you want to uninstall system, there you will run all patches in reverse order + * + * But note, that patches also have dependencies, and if patch is dependency to any other patch + * you will to revert it dependencies first and only then patch + * + * @return \ArrayIterator + */ + public function getReverseIterator() + { + if ($this->reverseIterator === null) { + $reversePatches = []; + + while (!empty($this->appliedPatches)) { + $patch = array_pop($this->appliedPatches); + $reversePatches = array_replace($reversePatches, $this->getDependentPatches($patch)); + $reversePatches[$patch] = $patch; + } + + $this->reverseIterator = new \ArrayIterator($reversePatches); + } + + return $this->reverseIterator; + } + + /** + * Retrieve iterator of all patch instances + * + * If patch have dependencies, than first of all dependencies should be installed and only then desired patch + * + * @return \ArrayIterator + */ + public function getIterator() + { + if ($this->iterator === null) { + $installPatches = []; + $patchInstances = $this->patches; + + while (!empty($patchInstances)) { + $firstPatch = array_shift($patchInstances); + $deps = $this->getDependencies($firstPatch); + + /** + * Remove deps from patchInstances + */ + foreach ($deps as $dep) { + unset($patchInstances[$dep]); + } + + $installPatches = array_replace($installPatches, $deps); + $installPatches[$firstPatch] = $firstPatch; + } + + $this->iterator = new \ArrayIterator($installPatches); + } + + return $this->iterator; + } +} diff --git a/setup/src/Magento/Setup/Model/Patch/PatchRegistryFactory.php b/setup/src/Magento/Setup/Model/Patch/PatchRegistryFactory.php new file mode 100644 index 0000000000000..0f00f4607acf3 --- /dev/null +++ b/setup/src/Magento/Setup/Model/Patch/PatchRegistryFactory.php @@ -0,0 +1,46 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Setup\Model\Patch; + +use Magento\Framework\ObjectManagerInterface; + +/** + * Create instance of patch registry + */ +class PatchRegistryFactory +{ + /** + * @var ObjectManagerInterface + */ + private $objectManager; + + /** + * @var string + */ + private $instanceName; + + /** + * @param ObjectManagerInterface $objectManager + * @param string $instanceName + */ + public function __construct( + ObjectManagerInterface $objectManager, + $instanceName = PatchRegistry::class + ) { + + $this->objectManager = $objectManager; + $this->instanceName = $instanceName; + } + + /** + * @return PatchRegistry + */ + public function create() + { + return $this->objectManager->create($this->instanceName); + } +} diff --git a/setup/src/Magento/Setup/Model/Patch/PatchRevertableInterface.php b/setup/src/Magento/Setup/Model/Patch/PatchRevertableInterface.php new file mode 100644 index 0000000000000..be368e889cd8e --- /dev/null +++ b/setup/src/Magento/Setup/Model/Patch/PatchRevertableInterface.php @@ -0,0 +1,25 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Setup\Model\Patch; + +/** + * Revertable means, that patch can be reverted + * + * All patches (@see PatchInterface) that implement this interfaces should have next values: + * - do not use application layer: like Serilizer, Collections, etc + * - use only some DML operations: INSERT, UPDATE + * - DELETE DML operation is prohibited, because it can cause triggering foreign keys constraints + * - all schema patches are not revertable + */ +interface PatchRevertableInterface +{ + /** + * Rollback all changes, done by this patch + * + * @return void + */ + public function revert(); +} diff --git a/setup/src/Magento/Setup/Model/Patch/PatchVersionInterface.php b/setup/src/Magento/Setup/Model/Patch/PatchVersionInterface.php new file mode 100644 index 0000000000000..689bad9cf0d4e --- /dev/null +++ b/setup/src/Magento/Setup/Model/Patch/PatchVersionInterface.php @@ -0,0 +1,26 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Setup\Model\Patch; + +/** + * For backward compatibility with versioned style module installation. Deprecated since creation. + * + * @deprecated + */ +interface PatchVersionInterface +{ + /** + * This version associate patch with Magento setup version. + * For example, if Magento current setup version is 2.0.3 and patch version is 2.0.2 than + * this patch will be added to registry, but will not be applied, because it is already applied + * by old mechanism of UpgradeData.php script + * + * + * @return string + * @deprecated since appearance, required for backward compatibility + */ + public static function getVersion(); +} diff --git a/setup/src/Magento/Setup/Model/Patch/SchemaPatchInterface.php b/setup/src/Magento/Setup/Model/Patch/SchemaPatchInterface.php new file mode 100644 index 0000000000000..d8845e06edd28 --- /dev/null +++ b/setup/src/Magento/Setup/Model/Patch/SchemaPatchInterface.php @@ -0,0 +1,14 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Setup\Model\Patch; + +/** + * This interface describe script, that atomic operations with schema (DDL) in SQL database + * This is wrapper for @see PatchInterface in order to define what kind of patch we have + */ +interface SchemaPatchInterface extends PatchInterface +{ +} diff --git a/setup/src/Magento/Setup/Module/Di/Code/Reader/ClassesScanner.php b/setup/src/Magento/Setup/Module/Di/Code/Reader/ClassesScanner.php index 5cd9c6ad3f719..7759eb51a52ad 100644 --- a/setup/src/Magento/Setup/Module/Di/Code/Reader/ClassesScanner.php +++ b/setup/src/Magento/Setup/Module/Di/Code/Reader/ClassesScanner.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Setup\Module\Di\Code\Reader; use Magento\Framework\App\Filesystem\DirectoryList; @@ -69,7 +70,9 @@ public function getList($path) return $this->fileResults[$realPath]; } if (!(bool)$realPath) { - throw new FileSystemException(new \Magento\Framework\Phrase('Invalid path: %1', [$path])); + throw new FileSystemException( + new \Magento\Framework\Phrase('The "%1" path is invalid. Verify the path and try again.', [$path]) + ); } $recursiveIterator = new \RecursiveIteratorIterator( new \RecursiveDirectoryIterator($realPath, \FilesystemIterator::FOLLOW_SYMLINKS), diff --git a/setup/src/Magento/Setup/Test/Unit/Console/Command/AdminUserCreateCommandTest.php b/setup/src/Magento/Setup/Test/Unit/Console/Command/AdminUserCreateCommandTest.php index d244f48d4e1ea..a80302b40a617 100644 --- a/setup/src/Magento/Setup/Test/Unit/Console/Command/AdminUserCreateCommandTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Console/Command/AdminUserCreateCommandTest.php @@ -158,10 +158,13 @@ public function testValidate(array $options, array $errors) public function validateDataProvider() { return [ - [[null, 'Doe', 'admin', 'test@test.com', '123123q', '123123q'], ['First Name is a required field.']], + [ + [null, 'Doe', 'admin', 'test@test.com', '123123q', '123123q'], + ['"First Name" is required. Enter and try again.'] + ], [ ['John', null, null, 'test@test.com', '123123q', '123123q'], - ['User Name is a required field.', 'Last Name is a required field.'], + ['"User Name" is required. Enter and try again.', '"Last Name" is required. Enter and try again.'], ], [['John', 'Doe', 'admin', null, '123123q', '123123q'], ['Please enter a valid email.']], [ diff --git a/setup/src/Magento/Setup/Test/Unit/Console/Command/MaintenanceAllowIpsCommandTest.php b/setup/src/Magento/Setup/Test/Unit/Console/Command/MaintenanceAllowIpsCommandTest.php index 88038c2e817c1..cce7a2e39adfc 100644 --- a/setup/src/Magento/Setup/Test/Unit/Console/Command/MaintenanceAllowIpsCommandTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Console/Command/MaintenanceAllowIpsCommandTest.php @@ -66,6 +66,33 @@ public function testExecute(array $input, array $validatorMessages, $expectedMes $this->assertEquals($expectedMessage, $tester->getDisplay()); } + /** + * @param array $addressInfo + * @param array $input + * @param array $validatorMessages + * @param string $expectedMessage + * @dataProvider executeWithAddDataProvider + */ + public function testExecuteWithAdd(array $addressInfo, array $input, array $validatorMessages, $expectedMessage) + { + $newAddressInfo = array_unique(array_merge($addressInfo, $input['ip'])); + + $this->ipValidator->expects($this->once())->method('validateIps')->willReturn($validatorMessages); + $this->maintenanceMode + ->expects($this->once()) + ->method('setAddresses') + ->with(implode(',', $newAddressInfo)); + + $this->maintenanceMode + ->expects($this->exactly(2)) + ->method('getAddressInfo') + ->willReturnOnConsecutiveCalls($addressInfo, $newAddressInfo); + + $tester = new CommandTester($this->command); + $tester->execute($input); + $this->assertEquals($expectedMessage, $tester->getDisplay()); + } + /** * return array */ @@ -75,7 +102,7 @@ public function executeDataProvider() [ ['ip' => ['127.0.0.1', '127.0.0.2'], '--none' => false], [], - 'Set exempt IP-addresses: 127.0.0.1, 127.0.0.2' . PHP_EOL + 'Set exempt IP-addresses: 127.0.0.1 127.0.0.2' . PHP_EOL ], [ ['--none' => true], @@ -99,4 +126,31 @@ public function executeDataProvider() ] ]; } + + /** + * return array + */ + public function executeWithAddDataProvider() + { + return [ + [ + [], + ['ip' => ['127.0.0.1'], '--add' => true], + [], + 'Set exempt IP-addresses: 127.0.0.1' . PHP_EOL, + ], + [ + ['127.0.0.1'], + ['ip' => ['127.0.0.1'], '--add' => true], + [], + 'Set exempt IP-addresses: 127.0.0.1' . PHP_EOL, + ], + [ + ['127.0.0.1'], + ['ip' => ['127.0.0.2'], '--add' => true], + [], + 'Set exempt IP-addresses: 127.0.0.1 127.0.0.2' . PHP_EOL, + ], + ]; + } } diff --git a/setup/src/Magento/Setup/Test/Unit/Console/Command/MaintenanceStatusCommandTest.php b/setup/src/Magento/Setup/Test/Unit/Console/Command/MaintenanceStatusCommandTest.php index 07f9990a0bb6f..0b36c86cf8ada 100644 --- a/setup/src/Magento/Setup/Test/Unit/Console/Command/MaintenanceStatusCommandTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Console/Command/MaintenanceStatusCommandTest.php @@ -50,7 +50,7 @@ public function executeDataProvider() [ [true, ['127.0.0.1', '127.0.0.2']], 'Status: maintenance mode is active' . PHP_EOL . - 'List of exempt IP-addresses: 127.0.0.1, 127.0.0.2' . PHP_EOL + 'List of exempt IP-addresses: 127.0.0.1 127.0.0.2' . PHP_EOL ], [ [true, []], @@ -63,7 +63,7 @@ public function executeDataProvider() [ [false, ['127.0.0.1', '127.0.0.2']], 'Status: maintenance mode is not active' . PHP_EOL . - 'List of exempt IP-addresses: 127.0.0.1, 127.0.0.2' . PHP_EOL + 'List of exempt IP-addresses: 127.0.0.1 127.0.0.2' . PHP_EOL ], ]; } diff --git a/setup/src/Magento/Setup/Test/Unit/Console/Command/ModuleUninstallCommandTest.php b/setup/src/Magento/Setup/Test/Unit/Console/Command/ModuleUninstallCommandTest.php index b6674c9aac986..d779867e2ca86 100644 --- a/setup/src/Magento/Setup/Test/Unit/Console/Command/ModuleUninstallCommandTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Console/Command/ModuleUninstallCommandTest.php @@ -8,6 +8,7 @@ use Magento\Framework\App\Console\MaintenanceModeEnabler; use Magento\Setup\Console\Command\ModuleUninstallCommand; use Magento\Setup\Model\ModuleUninstaller; +use Magento\Setup\Model\Patch\PatchApplier; use Symfony\Component\Console\Tester\CommandTester; /** @@ -96,6 +97,11 @@ class ModuleUninstallCommandTest extends \PHPUnit\Framework\TestCase */ private $tester; + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + private $patchApplierMock; + /** * @SuppressWarnings(PHPMD.UnusedLocalVariable) */ @@ -130,6 +136,9 @@ public function setUp() '', false ); + $this->patchApplierMock = $this->getMockBuilder(PatchApplier::class) + ->disableOriginalConstructor() + ->getMock(); $configLoader->expects($this->any())->method('load')->willReturn([]); $objectManager->expects($this->any()) ->method('get') @@ -143,6 +152,7 @@ public function setUp() $this->createMock(\Magento\Framework\App\State::class) ], [\Magento\Framework\Setup\BackupRollbackFactory::class, $this->backupRollbackFactory], + [PatchApplier::class, $this->patchApplierMock], [\Magento\Framework\ObjectManager\ConfigLoaderInterface::class, $configLoader], ])); $composer = $this->createMock(\Magento\Framework\Composer\ComposerInformation::class); @@ -437,6 +447,18 @@ public function testExecuteRemoveData() $this->tester->execute($input); } + public function testExecuteNonComposerModules() + { + $this->deploymentConfig->expects(self::once()) + ->method('isAvailable') + ->willReturn(true); + $input = ['module' => ['Magento_A'], '-c' => true, '-r' => true, '--non-composer' => true]; + $this->patchApplierMock->expects(self::once()) + ->method('revertDataPatches') + ->with('Magento_A'); + self::assertEquals(0, $this->tester->execute($input)); + } + public function testExecuteAll() { $input = ['module' => ['Magento_A', 'Magento_B'], '-c' => true, '-r' => true]; diff --git a/setup/src/Magento/Setup/Test/Unit/Console/Command/UpgradeCommandTest.php b/setup/src/Magento/Setup/Test/Unit/Console/Command/UpgradeCommandTest.php index 4058eefe0f8c1..0abeb7b32894f 100644 --- a/setup/src/Magento/Setup/Test/Unit/Console/Command/UpgradeCommandTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Console/Command/UpgradeCommandTest.php @@ -104,7 +104,7 @@ public function executeDataProvider() [ 'options' => [ '--magento-init-params' => '', - '--convert_old_scripts' => false + '--convert_old_scripts' => false, ], 'deployMode' => \Magento\Framework\App\State::MODE_PRODUCTION, 'expectedString' => 'Please re-run Magento compile command. Use the command "setup:di:compile"' @@ -113,13 +113,15 @@ public function executeDataProvider() 'keep-generated' => false, 'convert_old_scripts' => false, 'magento-init-params' => '', + 'safe-mode' => false, + 'data-restore' => false ] ], [ 'options' => [ '--magento-init-params' => '', '--convert_old_scripts' => false, - '--keep-generated' => true + '--keep-generated' => true, ], 'deployMode' => \Magento\Framework\App\State::MODE_PRODUCTION, 'expectedString' => '', @@ -127,6 +129,8 @@ public function executeDataProvider() 'keep-generated' => true, 'convert_old_scripts' => false, 'magento-init-params' => '', + 'safe-mode' => false, + 'data-restore' => false ] ], [ @@ -137,6 +141,8 @@ public function executeDataProvider() 'keep-generated' => false, 'convert_old_scripts' => false, 'magento-init-params' => '', + 'safe-mode' => false, + 'data-restore' => false ] ], [ @@ -147,6 +153,8 @@ public function executeDataProvider() 'keep-generated' => false, 'convert_old_scripts' => false, 'magento-init-params' => '', + 'safe-mode' => false, + 'data-restore' => false ] ], ]; diff --git a/setup/src/Magento/Setup/Test/Unit/Console/Style/MagentoStyleTest.php b/setup/src/Magento/Setup/Test/Unit/Console/Style/MagentoStyleTest.php new file mode 100755 index 0000000000000..92aa43251ba26 --- /dev/null +++ b/setup/src/Magento/Setup/Test/Unit/Console/Style/MagentoStyleTest.php @@ -0,0 +1,287 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Setup\Test\Unit\Console\Style; + +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Setup\Console\Style\MagentoStyle; +use PHPUnit\Framework\TestCase; +use Symfony\Component\Console\Formatter\OutputFormatter; +use Symfony\Component\Console\Helper\SymfonyQuestionHelper; +use Symfony\Component\Console\Helper\TableCell; +use Symfony\Component\Console\Input\ArrayInput; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputDefinition; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * Provide tests for MagentoStyle output decorator. + */ +class MagentoStyleTest extends TestCase +{ + /** + * Test subject. + * + * @var MagentoStyle + */ + private $magentoStyle; + + /** + * Auxiliary class replacing console output. + * + * @var TestOutput + */ + private $testOutput; + + /** + * @inheritdoc + */ + protected function setUp() + { + $input = new ArrayInput(['name' => 'foo'], new InputDefinition([new InputArgument('name')])); + $this->testOutput = new TestOutput(); + $this->magentoStyle = new MagentoStyle($input, $this->testOutput); + } + + /** + * Test style decorator will output block with correct style. + * + * @return void + */ + public function testBlockStyle() + { + $this->magentoStyle->block( + ['test first message', 'test second message'], + 'testBlockType', + 'testBlockStyle', + 'testBlockPrefix' + ); + // @codingStandardsIgnoreStart + $expected = PHP_EOL . PHP_EOL . PHP_EOL . + '\<testBlockStyle\>testBlockPrefix\[testBlockType\] test first message\s+' + . PHP_EOL . '\<testBlockStyle\>testBlockPrefix\s+' + . PHP_EOL . '\<testBlockStyle\>testBlockPrefix \s+ test second message\s+' + . PHP_EOL . PHP_EOL; + // @codingStandardsIgnoreEnd + $this->assertRegExp('/' . $expected . '/', $this->testOutput->output, 'Block does not match output'); + } + + /** + * Test style decorator will add title with correct style. + * + * @return void + */ + public function testTitleStyle() + { + $this->magentoStyle->title('My Title'); + $expected = PHP_EOL . PHP_EOL . PHP_EOL . ' My Title' . PHP_EOL . ' ========' . PHP_EOL . PHP_EOL; + $this->assertEquals($expected, $this->testOutput->output, 'Title does not match output'); + } + + /** + * Test style decorator will output section with correct style. + * + * @return void + */ + public function testSectionStyle() + { + $this->magentoStyle->section('My Section'); + $expected = PHP_EOL . PHP_EOL . PHP_EOL . ' My Section' . PHP_EOL . ' ----------' . PHP_EOL . PHP_EOL; + $this->assertEquals($expected, $this->testOutput->output, 'Section does not match output'); + } + + /** + * Test style decorator will output listing with proper style. + * + * @return void + */ + public function testListingStyle() + { + $this->magentoStyle->listing(['test first element', 'test second element']); + $expected = PHP_EOL . ' * test first element' . PHP_EOL . ' * test second element' . PHP_EOL . PHP_EOL; + $this->assertEquals($expected, $this->testOutput->output, 'Listing does not match output'); + } + + /** + * Test style decorator will output text with proper style. + * + * @return void + */ + public function testTextStyle() + { + $this->magentoStyle->text('test message'); + $expected = PHP_EOL . ' test message' . PHP_EOL; + + $this->assertEquals($expected, $this->testOutput->output, 'Text does not match output'); + } + + /** + * Test style decorator will output comment with proper style. + * + * @return void + */ + public function testCommentStyle() + { + $this->magentoStyle->comment('test comment'); + $expected = PHP_EOL . PHP_EOL . PHP_EOL . '\s+test comment\s+' . PHP_EOL . PHP_EOL; + $this->assertRegExp('/' . $expected . '/', $this->testOutput->output, 'Comment does not match output'); + } + + /** + * Test style decorator will output success message with proper style. + * + * @return void + */ + public function testSuccessStyle() + { + $this->magentoStyle->success('test success message'); + $expected = PHP_EOL . PHP_EOL . PHP_EOL . ' \[SUCCESS\] test success message\s+' . PHP_EOL . PHP_EOL; + $this->assertRegExp('/' . $expected . '/', $this->testOutput->output, 'Success message does not match output'); + } + + /** + * Test style decorator will output error message with proper style. + * + * @return void + */ + public function testErrorStyle() + { + $this->magentoStyle->error('test error message'); + $expected = PHP_EOL . PHP_EOL . PHP_EOL . '\s+\[ERROR\] test error message\s+' . PHP_EOL . PHP_EOL; + $this->assertRegExp('/' . $expected . '/', $this->testOutput->output, 'Error message does not match output'); + } + + /** + * Test style decorator will output warning message with proper style. + * + * @return void + */ + public function testWarningStyle() + { + $this->magentoStyle->warning('test warning message'); + $expected = PHP_EOL . PHP_EOL . PHP_EOL . '\s+\[WARNING\] test warning message\s+' . PHP_EOL . PHP_EOL; + $this->assertRegExp('/' . $expected . '/', $this->testOutput->output, 'Warning message does not match output'); + } + + /** + * Test style decorator will output note message with proper style. + * + * @return void + */ + public function testNoteStyle() + { + $this->magentoStyle->note('test note message'); + $expected = PHP_EOL . PHP_EOL . PHP_EOL . '\s+\[NOTE\] test note message\s+' . PHP_EOL . PHP_EOL; + $this->assertRegExp('/' . $expected . '/', $this->testOutput->output, 'Note message does not match output'); + } + + /** + * Test style decorator will output caution message with proper style. + * + * @return void + */ + public function testCautionStyle() + { + $this->magentoStyle->caution('test caution message'); + $expected = PHP_EOL . PHP_EOL . PHP_EOL . '\s+! \[CAUTION\] test caution message\s+' . PHP_EOL . PHP_EOL; + $this->assertRegExp('/' . $expected . '/', $this->testOutput->output, 'Caution message does not match output'); + } + + /** + * Test style decorator will output table with proper style. + * + * @return void + */ + public function testTableStyle() + { + $headers = [ + [new TableCell('Main table title', ['colspan' => 2])], + ['testHeader1', 'testHeader2', 'testHeader3'], + ]; + $rows = [ + [ + 'testValue1', + 'testValue2', + new TableCell('testValue3', ['rowspan' => 2]), + ], + ['testValue4', 'testValue5'], + ]; + $this->magentoStyle->table($headers, $rows); + $expected = ' ------------- ------------- ------------- ' . PHP_EOL . + ' Main table title ' . PHP_EOL . + ' ------------- ------------- ------------- ' . PHP_EOL . + ' testHeader1 testHeader2 testHeader3 ' . PHP_EOL . + ' ------------- ------------- ------------- ' . PHP_EOL . + ' testValue1 testValue2 testValue3 ' . PHP_EOL . + ' testValue4 testValue5 ' . PHP_EOL . + ' ------------- ------------- ------------- ' . PHP_EOL . PHP_EOL; + + $this->assertEquals($expected, $this->testOutput->output, 'Table does not match output'); + } + + /** + * @return void + */ + public function testAsk() + { + $objectManager = new ObjectManager($this); + $formatter = $this->getMockBuilder(OutputFormatter::class) + ->disableOriginalConstructor() + ->getMock(); + $input = $this->getMockBuilder(InputInterface::class) + ->setMethods(['isInteractive']) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + $input->expects($this->exactly(2)) + ->method('isInteractive') + ->willReturn(false); + $output = $this->getMockBuilder(OutputInterface::class) + ->setMethods(['getVerbosity', 'getFormatter']) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + $output->expects($this->once()) + ->method('getVerbosity') + ->willReturn(32); + $output->expects($this->once()) + ->method('getFormatter') + ->willReturn($formatter); + $magentoStyle = $objectManager->getObject( + MagentoStyle::class, + [ + 'input' => $input, + 'output' => $output, + ] + ); + $questionHelper = $this->getMockBuilder(SymfonyQuestionHelper::class) + ->disableOriginalConstructor() + ->getMock(); + $questionHelper->expects($this->once()) + ->method('ask') + ->willReturn('test Answer'); + $objectManager->setBackwardCompatibleProperty($magentoStyle, 'questionHelper', $questionHelper); + + $this->assertEquals( + 'test Answer', + $magentoStyle->ask('test question?', 'test default') + ); + } + + /** + * Test style decorator will output progress with proper style. + * + * @return void + */ + public function testProgress() + { + $this->magentoStyle->progressStart(2); + $this->magentoStyle->progressAdvance(3); + $this->magentoStyle->progressFinish(); + $expected = ' 0/2 [> ] 0%' . PHP_EOL . + ' 3/3 [============================] 100%' . PHP_EOL . PHP_EOL; + $this->assertEquals($expected, $this->testOutput->output, 'Progress does not match output'); + } +} diff --git a/setup/src/Magento/Setup/Test/Unit/Console/Style/TestOutput.php b/setup/src/Magento/Setup/Test/Unit/Console/Style/TestOutput.php new file mode 100644 index 0000000000000..1407e5ed183e4 --- /dev/null +++ b/setup/src/Magento/Setup/Test/Unit/Console/Style/TestOutput.php @@ -0,0 +1,27 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Setup\Test\Unit\Console\Style; + +use Symfony\Component\Console\Output\Output; + +/** + * Auxiliary class for MagentoStyleTest. + */ +class TestOutput extends Output +{ + public $output = ''; + + public function clear() + { + $this->output = ''; + } + + protected function doWrite($message, $newline) + { + $this->output .= $message . ($newline ? "\n" : ''); + } +} diff --git a/setup/src/Magento/Setup/Test/Unit/Model/AdminAccountTest.php b/setup/src/Magento/Setup/Test/Unit/Model/AdminAccountTest.php index e7b1c5ade1bcf..cf8a578fdb579 100644 --- a/setup/src/Magento/Setup/Test/Unit/Model/AdminAccountTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Model/AdminAccountTest.php @@ -365,7 +365,7 @@ public function testSaveExceptionSpecialAdminRoleNotFound() /** * @expectedException \Exception - * @expectedExceptionMessage Password is a required field + * @expectedExceptionMessage "Password" is required. Enter and try again. */ public function testSaveExceptionPasswordEmpty() { diff --git a/setup/src/Magento/Setup/Test/Unit/Model/ConfigOptionsList/SessionTest.php b/setup/src/Magento/Setup/Test/Unit/Model/ConfigOptionsList/SessionTest.php index d37c07e715482..3b1d3e29e4e56 100644 --- a/setup/src/Magento/Setup/Test/Unit/Model/ConfigOptionsList/SessionTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Model/ConfigOptionsList/SessionTest.php @@ -32,7 +32,7 @@ protected function setUp() public function testGetOptions() { $options = $this->configList->getOptions(); - $this->assertCount(19, $options); + $this->assertCount(23, $options); $this->assertArrayHasKey(0, $options); $this->assertInstanceOf(SelectConfigOption::class, $options[0]); @@ -156,7 +156,11 @@ public function testCreateConfigWithSessionSaveRedis() 'bot_lifetime' => '', 'disable_locking' => '', 'min_lifetime' => '', - 'max_lifetime' => '' + 'max_lifetime' => '', + 'sentinel_master' => '', + 'sentinel_servers' => '', + 'sentinel_connect_retries' => '', + 'sentinel_verify_master' => '', ] ] @@ -209,7 +213,11 @@ public function testCreateConfigWithRedisInput() 'bot_lifetime' => '', 'disable_locking' => '', 'min_lifetime' => '60', - 'max_lifetime' => '3600' + 'max_lifetime' => '3600', + 'sentinel_master' => '', + 'sentinel_servers' => '', + 'sentinel_connect_retries' => '', + 'sentinel_verify_master' => '', ] ], diff --git a/setup/src/Magento/Setup/Test/Unit/Model/Declaration/Schema/Dto/Factories/TableTest.php b/setup/src/Magento/Setup/Test/Unit/Model/Declaration/Schema/Dto/Factories/TableTest.php new file mode 100644 index 0000000000000..cda2dafd3957a --- /dev/null +++ b/setup/src/Magento/Setup/Test/Unit/Model/Declaration/Schema/Dto/Factories/TableTest.php @@ -0,0 +1,84 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Setup\Test\Unit\Model\Declaration\Schema\Dto\Factories; + +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +use Magento\Setup\Model\Declaration\Schema\Dto\Table; + +class TableTest extends \PHPUnit\Framework\TestCase +{ + /** @var \Magento\Setup\Model\Declaration\Schema\Dto\Factories\Table */ + protected $model; + + /** @var ObjectManagerHelper */ + protected $objectManagerHelper; + + /** @var \Magento\Framework\ObjectManagerInterface|\PHPUnit_Framework_MockObject_MockObject */ + protected $objectManagerMock; + + /** @var \Magento\Framework\App\ResourceConnection|\PHPUnit_Framework_MockObject_MockObject */ + protected $resourceConnectionMock; + + protected function setUp() + { + $this->objectManagerMock = $this->getMockBuilder(\Magento\Framework\ObjectManagerInterface::class) + ->disableOriginalConstructor() + ->getMock(); + $this->resourceConnectionMock = $this->getMockBuilder(\Magento\Framework\App\ResourceConnection::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->objectManagerHelper = new ObjectManagerHelper($this); + $this->model = $this->objectManagerHelper->getObject( + \Magento\Setup\Model\Declaration\Schema\Dto\Factories\Table::class, + [ + 'objectManager' => $this->objectManagerMock, + 'resourceConnection' => $this->resourceConnectionMock + ] + ); + } + + public function testCreate() + { + $this->resourceConnectionMock->expects(self::once()) + ->method('getTablePrefix') + ->willReturn('pf_'); + $data = [ + 'name' => 'some_table', + 'engine' => null, + ]; + $expectedData = [ + 'name' => 'pf_some_table', + 'engine' => 'innodb', + 'nameWithoutPrefix' => 'some_table' + ]; + $this->objectManagerMock->expects(self::once()) + ->method('create') + ->with(Table::class, $expectedData); + $this->model->create($data); + } + + public function testCreateWithPrefix() + { + $this->resourceConnectionMock->expects(self::once()) + ->method('getTablePrefix') + ->willReturn('pf_'); + $data = [ + 'name' => 'pf_some_table', + 'engine' => 'memory', + 'nameWithoutPrefix' => 'some_table' + ]; + $expectedData = [ + 'name' => 'pf_some_table', + 'engine' => 'memory', + 'nameWithoutPrefix' => 'some_table' + ]; + $this->objectManagerMock->expects(self::once()) + ->method('create') + ->with(Table::class, $expectedData); + $this->model->create($data); + } +} diff --git a/setup/src/Magento/Setup/Test/Unit/Model/Declaration/Schema/OperationsExecutorTest.php b/setup/src/Magento/Setup/Test/Unit/Model/Declaration/Schema/OperationsExecutorTest.php index f14413ab169dc..101cc805fbdf9 100644 --- a/setup/src/Magento/Setup/Test/Unit/Model/Declaration/Schema/OperationsExecutorTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Model/Declaration/Schema/OperationsExecutorTest.php @@ -108,6 +108,7 @@ protected function setUp() 'create_table' => $this->createTableOperation, 'drop_element' => $this->dropElement ], + 'dataSaviorsCollection' => [], 'sharding' => $this->shardingMock, 'resourceConnection' => $this->resourceConnectionMock, 'statementFactory' => $this->statementFactoryMock, @@ -178,6 +179,6 @@ public function testExecute() ->willReturn($tablesHistories); $this->dropElement->expects(self::at(0)) ->method('doOperation'); - $this->model->execute($diff); + $this->model->execute($diff, []); } } diff --git a/setup/src/Magento/Setup/Test/Unit/Model/InstallerTest.php b/setup/src/Magento/Setup/Test/Unit/Model/InstallerTest.php index dd5918b477eef..e2cf02b623296 100644 --- a/setup/src/Magento/Setup/Test/Unit/Model/InstallerTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Model/InstallerTest.php @@ -15,6 +15,8 @@ use Magento\Framework\Filesystem\DriverPool; use Magento\Framework\Config\File\ConfigFilePool; use Magento\Framework\App\State\CleanupFiles; +use Magento\Setup\Model\Patch\PatchApplier; +use Magento\Setup\Model\Patch\PatchApplierFactory; use Magento\Setup\Validator\DbValidator; /** @@ -167,6 +169,16 @@ class InstallerTest extends \PHPUnit\Framework\TestCase */ private $contextMock; + /** + * @var PatchApplier|\PHPUnit_Framework_MockObject_MockObject + */ + private $patchApplierMock; + + /** + * @var PatchApplierFactory|\PHPUnit_Framework_MockObject_MockObject + */ + private $patchApplierFactoryMock; + protected function setUp() { $this->filePermissions = $this->createMock(\Magento\Framework\Setup\FilePermissions::class); @@ -204,6 +216,9 @@ protected function setUp() $this->phpReadinessCheck = $this->createMock(\Magento\Setup\Model\PhpReadinessCheck::class); $this->declarationInstallerMock = $this->createMock(DeclarationInstaller::class); $this->schemaListenerMock = $this->createMock(SchemaListener::class); + $this->patchApplierFactoryMock = $this->createMock(PatchApplierFactory::class); + $this->patchApplierMock = $this->createMock(PatchApplier::class); + $this->patchApplierFactoryMock->expects($this->any())->method('create')->willReturn($this->patchApplierMock); $this->object = $this->createObject(); } @@ -308,7 +323,24 @@ public function testInstall() ->will($this->returnValueMap([ [\Magento\Framework\App\Cache\Manager::class, [], $cacheManager], [\Magento\Framework\App\State::class, [], $appState], + [ + PatchApplierFactory::class, + ['objectManager' => $this->objectManager], + $this->patchApplierFactoryMock + ], ])); + $this->patchApplierMock->expects($this->exactly(2))->method('applySchemaPatch')->willReturnMap( + [ + ['Bar_Two'], + ['Foo_One'], + ] + ); + $this->patchApplierMock->expects($this->exactly(2))->method('applyDataPatch')->willReturnMap( + [ + ['Bar_Two'], + ['Foo_One'], + ] + ); $this->objectManager->expects($this->any()) ->method('get') ->will($this->returnValueMap([ diff --git a/setup/src/Magento/Setup/Test/Unit/Model/ModuleUninstallerTest.php b/setup/src/Magento/Setup/Test/Unit/Model/ModuleUninstallerTest.php index 89f7956332aac..bed65553b9428 100644 --- a/setup/src/Magento/Setup/Test/Unit/Model/ModuleUninstallerTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Model/ModuleUninstallerTest.php @@ -6,6 +6,7 @@ namespace Magento\Setup\Test\Unit\Model; use Magento\Setup\Model\ModuleUninstaller; +use Magento\Setup\Model\Patch\PatchApplier; /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) @@ -47,6 +48,11 @@ class ModuleUninstallerTest extends \PHPUnit\Framework\TestCase */ private $moduleRegistryUninstaller; + /** + * @var PatchApplier|\PHPUnit_Framework_MockObject_MockObject + */ + private $patchApplierMock; + public function setUp() { $this->moduleRegistryUninstaller = $this->createMock(\Magento\Setup\Model\ModuleRegistryUninstaller::class); @@ -63,6 +69,7 @@ public function setUp() $this->collector = $this->createMock(\Magento\Setup\Model\UninstallCollector::class); $this->setup = $this->createMock(\Magento\Setup\Module\Setup::class); + $this->patchApplierMock = $this->createMock(PatchApplier::class); $setupFactory = $this->createMock(\Magento\Setup\Module\SetupFactory::class); $setupFactory->expects($this->any())->method('create')->willReturn($this->setup); @@ -93,10 +100,20 @@ public function testUninstallRemoveData() $this->output->expects($this->atLeastOnce())->method('writeln'); - $this->objectManager->expects($this->once()) + $this->objectManager->expects($this->any()) ->method('get') - ->with(\Magento\Framework\Module\ModuleResource::class) - ->willReturn($resource); + ->willReturnMap( + [ + [\Magento\Framework\Module\ModuleResource::class, $resource], + [PatchApplier::class, $this->patchApplierMock] + ] + ); + $this->patchApplierMock->expects($this->exactly(2))->method('revertDataPatches')->willReturnMap( + [ + ['moduleA'], + ['moduleB'] + ] + ); $this->uninstaller->uninstallData($this->output, ['moduleA', 'moduleB']); } diff --git a/setup/src/Magento/Setup/Test/Unit/Model/Patch/PatchApplierTest.php b/setup/src/Magento/Setup/Test/Unit/Model/Patch/PatchApplierTest.php new file mode 100644 index 0000000000000..e7b5971375049 --- /dev/null +++ b/setup/src/Magento/Setup/Test/Unit/Model/Patch/PatchApplierTest.php @@ -0,0 +1,547 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Setup\Test\Unit\Model\Patch; + +use Magento\Framework\App\ResourceConnection; +use Magento\Framework\DB\Adapter\AdapterInterface; +use Magento\Framework\Module\ModuleResource; +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\Setup\ModuleDataSetupInterface; +use Magento\Framework\Setup\SchemaSetupInterface; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Setup\Model\Patch\PatchApplier; +use Magento\Setup\Model\Patch\PatchFactory; +use Magento\Setup\Model\Patch\PatchHistory; +use Magento\Setup\Model\Patch\PatchReader; +use Magento\Setup\Model\Patch\PatchRegistry; +use Magento\Setup\Model\Patch\PatchRegistryFactory; + +/** + * Class PatchApplierTest + * @package Magento\Setup\Test\Unit\Model\Patch + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class PatchApplierTest extends \PHPUnit\Framework\TestCase +{ + /** + * @var PatchRegistryFactory|\PHPUnit_Framework_MockObject_MockObject + */ + private $patchRegistryFactoryMock; + + /** + * @var PatchReader|\PHPUnit_Framework_MockObject_MockObject + */ + private $dataPatchReaderMock; + + /** + * @var PatchReader|\PHPUnit_Framework_MockObject_MockObject + */ + private $schemaPatchReaderMock; + + /** + * @var ResourceConnection|\PHPUnit_Framework_MockObject_MockObject + */ + private $resourceConnectionMock; + + /** + * @var ModuleResource|\PHPUnit_Framework_MockObject_MockObject + */ + private $moduleResourceMock; + + /** + * @var PatchHistory|\PHPUnit_Framework_MockObject_MockObject + */ + private $patchHistoryMock; + + /** + * @var PatchFactory|\PHPUnit_Framework_MockObject_MockObject + */ + private $patchFactoryMock; + + /** + * @var \Magento\Framework\Setup\SetupInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $schemaSetupMock; + + /** + * @var ModuleDataSetupInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $moduleDataSetupMock; + + /** + * @var ObjectManagerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $objectManagerMock; + + /** + * @var PatchApplier + */ + private $patchApllier; + + /** + * @var AdapterInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $connectionMock; + + protected function setUp() + { + $this->patchRegistryFactoryMock = $this->createMock(PatchRegistryFactory::class); + $this->dataPatchReaderMock = $this->createMock(PatchReader::class); + $this->schemaPatchReaderMock = $this->createMock(PatchReader::class); + $this->resourceConnectionMock = $this->createMock(ResourceConnection::class); + $this->moduleResourceMock = $this->createMock(ModuleResource::class); + $this->patchHistoryMock = $this->createMock(PatchHistory::class); + $this->patchFactoryMock = $this->createMock(PatchFactory::class); + $this->schemaSetupMock = $this->createMock(SchemaSetupInterface::class); + $this->moduleDataSetupMock = $this->createMock(ModuleDataSetupInterface::class); + $this->objectManagerMock = $this->createMock(ObjectManagerInterface::class); + $this->connectionMock = $this->createMock(AdapterInterface::class); + $this->moduleDataSetupMock->expects($this->any())->method('getConnection')->willReturn($this->connectionMock); + + $objectManager = new ObjectManager($this); + $this->patchApllier = $objectManager->getObject( + PatchApplier::class, + [ + 'patchRegistryFactory' => $this->patchRegistryFactoryMock, + 'dataPatchReader' => $this->dataPatchReaderMock, + 'schemaPatchReader' => $this->schemaPatchReaderMock, + 'resourceConnection' => $this->resourceConnectionMock, + 'moduleResource' => $this->moduleResourceMock, + 'patchHistory' => $this->patchHistoryMock, + 'patchFactory' => $this->patchFactoryMock, + 'objectManager' => $this->objectManagerMock, + 'schemaSetup' => $this->schemaSetupMock, + 'moduleDataSetup' => $this->moduleDataSetupMock, + ] + ); + require_once __DIR__ . '/../_files/data_patch_classes.php'; + require_once __DIR__ . '/../_files/schema_patch_classes.php'; + } + + /** + * @param $moduleName + * @param $dataPatches + * @param $moduleVersionInDb + * + * @dataProvider applyDataPatchDataNewModuleProvider() + */ + public function testApplyDataPatchForNewlyInstalledModule($moduleName, $dataPatches, $moduleVersionInDb) + { + $this->dataPatchReaderMock->expects($this->once()) + ->method('read') + ->with($moduleName) + ->willReturn($dataPatches); + + $this->moduleResourceMock->expects($this->any())->method('getDataVersion')->willReturnMap( + [ + [$moduleName, $moduleVersionInDb] + ] + ); + + $patches = [ + \SomeDataPatch::class, + \OtherDataPatch::class + ]; + $patchRegistryMock = $this->createAggregateIteratorMock(PatchRegistry::class, $patches, ['registerPatch']); + $patchRegistryMock->expects($this->exactly(2)) + ->method('registerPatch'); + + $this->patchRegistryFactoryMock->expects($this->any()) + ->method('create') + ->willReturn($patchRegistryMock); + + $patch1 = $this->createMock(\SomeDataPatch::class); + $patch1->expects($this->once())->method('apply'); + $patch2 = $this->createMock(\OtherDataPatch::class); + $patch2->expects($this->once())->method('apply'); + $this->objectManagerMock->expects($this->any())->method('create')->willReturnMap( + [ + ['\\' . \SomeDataPatch::class, ['moduleDataSetup' => $this->moduleDataSetupMock], $patch1], + ['\\' . \OtherDataPatch::class, ['moduleDataSetup' => $this->moduleDataSetupMock], $patch2], + ] + ); + $this->connectionMock->expects($this->exactly(2))->method('beginTransaction'); + $this->connectionMock->expects($this->exactly(2))->method('commit'); + $this->patchHistoryMock->expects($this->any())->method('fixPatch')->willReturnMap( + [ + [get_class($patch1)], + [get_class($patch2)], + ] + ); + $this->patchApllier->applyDataPatch($moduleName); + } + + /** + * @return array + */ + public function applyDataPatchDataNewModuleProvider() + { + return [ + 'newly installed module' => [ + 'moduleName' => 'Module1', + 'dataPatches' => [ + \SomeDataPatch::class, + \OtherDataPatch::class + ], + 'moduleVersionInDb' => null, + ], + ]; + } + + /** + * @param $moduleName + * @param $dataPatches + * @param $moduleVersionInDb + * + * @dataProvider applyDataPatchDataInstalledModuleProvider() + */ + public function testApplyDataPatchForInstalledModule($moduleName, $dataPatches, $moduleVersionInDb) + { + $this->dataPatchReaderMock->expects($this->once()) + ->method('read') + ->with($moduleName) + ->willReturn($dataPatches); + + $this->moduleResourceMock->expects($this->any())->method('getDataVersion')->willReturnMap( + [ + [$moduleName, $moduleVersionInDb] + ] + ); + + $patches = [ + \SomeDataPatch::class, + \OtherDataPatch::class + ]; + $patchRegistryMock = $this->createAggregateIteratorMock(PatchRegistry::class, $patches, ['registerPatch']); + $patchRegistryMock->expects($this->exactly(2)) + ->method('registerPatch'); + + $this->patchRegistryFactoryMock->expects($this->any()) + ->method('create') + ->willReturn($patchRegistryMock); + + $patch1 = $this->createMock(\SomeDataPatch::class); + $patch1->expects($this->never())->method('apply'); + $patch2 = $this->createMock(\OtherDataPatch::class); + $patch2->expects($this->once())->method('apply'); + $this->objectManagerMock->expects($this->any())->method('create')->willReturnMap( + [ + ['\\' . \SomeDataPatch::class, ['moduleDataSetup' => $this->moduleDataSetupMock], $patch1], + ['\\' . \OtherDataPatch::class, ['moduleDataSetup' => $this->moduleDataSetupMock], $patch2], + ] + ); + $this->connectionMock->expects($this->exactly(1))->method('beginTransaction'); + $this->connectionMock->expects($this->exactly(1))->method('commit'); + $this->patchHistoryMock->expects($this->exactly(2))->method('fixPatch'); + $this->patchApllier->applyDataPatch($moduleName); + } + + public function applyDataPatchDataInstalledModuleProvider() + { + return [ + 'upgrade module iwth only OtherDataPatch' => [ + 'moduleName' => 'Module1', + 'dataPatches' => [ + \SomeDataPatch::class, + \OtherDataPatch::class + ], + 'moduleVersionInDb' => '2.0.0', + ] + ]; + } + + /** + * @param $moduleName + * @param $dataPatches + * @param $moduleVersionInDb + * + * @expectedException \Magento\Setup\Exception + * @expectedExceptionMessage Patch Apply Error + * + * @dataProvider applyDataPatchDataInstalledModuleProvider() + */ + public function testApplyDataPatchRollback($moduleName, $dataPatches, $moduleVersionInDb) + { + $this->dataPatchReaderMock->expects($this->once()) + ->method('read') + ->with($moduleName) + ->willReturn($dataPatches); + + $this->moduleResourceMock->expects($this->any())->method('getDataVersion')->willReturnMap( + [ + [$moduleName, $moduleVersionInDb] + ] + ); + + $patches = [ + \SomeDataPatch::class, + \OtherDataPatch::class + ]; + $patchRegistryMock = $this->createAggregateIteratorMock(PatchRegistry::class, $patches, ['registerPatch']); + $patchRegistryMock->expects($this->exactly(2)) + ->method('registerPatch'); + + $this->patchRegistryFactoryMock->expects($this->any()) + ->method('create') + ->willReturn($patchRegistryMock); + + $patch1 = $this->createMock(\SomeDataPatch::class); + $patch1->expects($this->never())->method('apply'); + $patch2 = $this->createMock(\OtherDataPatch::class); + $exception = new \Exception('Patch Apply Error'); + $patch2->expects($this->once())->method('apply')->willThrowException($exception); + $this->objectManagerMock->expects($this->any())->method('create')->willReturnMap( + [ + ['\\' . \SomeDataPatch::class, ['moduleDataSetup' => $this->moduleDataSetupMock], $patch1], + ['\\' . \OtherDataPatch::class, ['moduleDataSetup' => $this->moduleDataSetupMock], $patch2], + ] + ); + $this->connectionMock->expects($this->exactly(1))->method('beginTransaction'); + $this->connectionMock->expects($this->never())->method('commit'); + $this->connectionMock->expects($this->exactly(1))->method('rollback'); + $this->patchHistoryMock->expects($this->exactly(1))->method('fixPatch'); + $this->patchApllier->applyDataPatch($moduleName); + } + + /** + * @expectedException \Magento\Setup\Exception + * @expectedExceptionMessageRegExp "Patch [a-zA-Z0-9\_]+ should implement DataPatchInterface" + */ + public function testNonDataPatchApply() + { + $this->dataPatchReaderMock->expects($this->once()) + ->method('read') + ->with('module1') + ->willReturn([\stdClass::class]); + $patchRegistryMock = $this->createAggregateIteratorMock( + PatchRegistry::class, + [\stdClass::class], + ['registerPatch'] + ); + $patchRegistryMock->expects($this->exactly(1)) + ->method('registerPatch'); + + $this->patchRegistryFactoryMock->expects($this->any()) + ->method('create') + ->willReturn($patchRegistryMock); + + $this->objectManagerMock->expects($this->any())->method('create')->willReturnMap( + [ + [ + '\\' . \stdClass::class, + ['moduleDataSetup' => $this->moduleDataSetupMock], + $this->createMock(\stdClass::class) + ], + ] + ); + + $this->patchApllier->applyDataPatch('module1'); + } + + public function testNonTransactionablePatch() + { + $patches = [\NonTransactionableDataPatch::class]; + $this->dataPatchReaderMock->expects($this->once()) + ->method('read') + ->with('module1') + ->willReturn($patches); + $patchRegistryMock = $this->createAggregateIteratorMock( + PatchRegistry::class, + $patches, + ['registerPatch'] + ); + $patchRegistryMock->expects($this->exactly(1)) + ->method('registerPatch'); + + $this->patchRegistryFactoryMock->expects($this->any()) + ->method('create') + ->willReturn($patchRegistryMock); + + $patch1 = $this->createMock($patches[0]); + $patch1->expects($this->exactly(1))->method('apply'); + $this->connectionMock->expects($this->never())->method('beginTransaction'); + $this->connectionMock->expects($this->never())->method('commit'); + $this->connectionMock->expects($this->never())->method('rollback'); + $this->patchHistoryMock->expects($this->once())->method('fixPatch')->with(get_class($patch1)); + $this->objectManagerMock->expects($this->any())->method('create')->willReturnMap( + [ + [ + '\\' . $patches[0], + ['moduleDataSetup' => $this->moduleDataSetupMock], + $patch1 + ], + ] + ); + + $this->patchApllier->applyDataPatch('module1'); + } + + /** + * @param $moduleName + * @param $schemaPatches + * @param $moduleVersionInDb + * + * @dataProvider schemaPatchDataProvider() + */ + public function testSchemaPatchAplly($moduleName, $schemaPatches, $moduleVersionInDb) + { + $this->schemaPatchReaderMock->expects($this->once()) + ->method('read') + ->with($moduleName) + ->willReturn($schemaPatches); + + $this->moduleResourceMock->expects($this->any())->method('getDbVersion')->willReturnMap( + [ + [$moduleName, $moduleVersionInDb] + ] + ); + + $patches = [ + \SomeSchemaPatch::class, + \OtherSchemaPatch::class + ]; + $patchRegistryMock = $this->createAggregateIteratorMock(PatchRegistry::class, $patches, ['registerPatch']); + $patchRegistryMock->expects($this->exactly(2)) + ->method('registerPatch'); + + $this->patchRegistryFactoryMock->expects($this->any()) + ->method('create') + ->willReturn($patchRegistryMock); + + $patch1 = $this->createMock(\SomeSchemaPatch::class); + $patch1->expects($this->never())->method('apply'); + $patch2 = $this->createMock(\OtherSchemaPatch::class); + $patch2->expects($this->once())->method('apply'); + $this->patchFactoryMock->expects($this->any())->method('create')->willReturnMap( + [ + [\SomeSchemaPatch::class, ['schemaSetup' => $this->schemaSetupMock], $patch1], + [\OtherSchemaPatch::class, ['schemaSetup' => $this->schemaSetupMock], $patch2], + ] + ); + $this->connectionMock->expects($this->never())->method('beginTransaction'); + $this->connectionMock->expects($this->never())->method('commit'); + $this->patchHistoryMock->expects($this->exactly(2))->method('fixPatch'); + $this->patchApllier->applySchemaPatch($moduleName); + } + + public function testRevertDataPatches() + { + $patches = [\RevertableDataPatch::class]; + $this->dataPatchReaderMock->expects($this->once()) + ->method('read') + ->with('module1') + ->willReturn($patches); + $patchRegistryMock = $this->createAggregateIteratorMock( + PatchRegistry::class, + $patches, + ['registerPatch', 'getReverseIterator'] + ); + $patchRegistryMock->expects($this->exactly(1)) + ->method('registerPatch'); + $patchRegistryMock->expects($this->once())->method('getReverseIterator') + ->willReturn(array_reverse($patches)); + + $this->patchRegistryFactoryMock->expects($this->any()) + ->method('create') + ->willReturn($patchRegistryMock); + + $patch1 = $this->createMock($patches[0]); + $patch1->expects($this->exactly(1))->method('revert'); + $this->connectionMock->expects($this->once())->method('beginTransaction'); + $this->connectionMock->expects($this->once())->method('commit'); + $this->connectionMock->expects($this->never())->method('rollback'); + $this->patchHistoryMock->expects($this->once())->method('revertPatchFromHistory')->with(get_class($patch1)); + $this->objectManagerMock->expects($this->any())->method('create')->willReturnMap( + [ + [ + '\\' . $patches[0], + ['moduleDataSetup' => $this->moduleDataSetupMock], + $patch1 + ], + ] + ); + + $this->patchApllier->revertDataPatches('module1'); + } + + /** + * @return array + */ + public function schemaPatchDataProvider() + { + return [ + 'upgrade module iwth only OtherSchemaPatch' => [ + 'moduleName' => 'Module1', + 'schemaPatches' => [ + \SomeSchemaPatch::class, + \OtherSchemaPatch::class + ], + 'moduleVersionInDb' => '2.0.0', + ] + ]; + } + /** + * Create mock of class that implements IteratorAggregate + * + * @param string $className + * @param array $items + * @param array $methods + * @return \PHPUnit_Framework_MockObject_MockObject|\IteratorAggregate + * @throws \Exception + */ + private function createAggregateIteratorMock($className, array $items = [], array $methods = []) + { + if (!in_array(ltrim(\IteratorAggregate::class, '\\'), class_implements($className))) { + throw new \Exception('Mock possible only for classes that implement IteratorAggregate interface.'); + } + /** + * PHPUnit_Framework_MockObject_MockObject + */ + $someIterator = $this->createMock(\ArrayIterator::class); + + $mockIteratorAggregate = $this->getMockBuilder($className) + ->disableOriginalConstructor() + ->setMethods(array_merge($methods, ['getIterator'])) + ->getMock(); + + $mockIteratorAggregate->expects($this->any())->method('getIterator')->willReturn($someIterator); + + $iterator = new \ArrayIterator($items); + + $someIterator->expects($this->any()) + ->method('rewind') + ->willReturnCallback(function () use ($iterator) { + $iterator->rewind(); + }); + + $someIterator->expects($this->any()) + ->method('current') + ->willReturnCallback(function () use ($iterator) { + return $iterator->current(); + }); + + $someIterator->expects($this->any()) + ->method('key') + ->willReturnCallback(function () use ($iterator) { + return $iterator->key(); + }); + + $someIterator->expects($this->any()) + ->method('next') + ->willReturnCallback(function () use ($iterator) { + $iterator->next(); + }); + + $someIterator->expects($this->any()) + ->method('valid') + ->willReturnCallback(function () use ($iterator) { + return $iterator->valid(); + }); + + return $mockIteratorAggregate; + } +} diff --git a/setup/src/Magento/Setup/Test/Unit/Model/Patch/PatchFactoryTest.php b/setup/src/Magento/Setup/Test/Unit/Model/Patch/PatchFactoryTest.php new file mode 100644 index 0000000000000..2b6b26d307128 --- /dev/null +++ b/setup/src/Magento/Setup/Test/Unit/Model/Patch/PatchFactoryTest.php @@ -0,0 +1,59 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Setup\Test\Unit\Model\Patch; + +use Magento\Framework\App\ResourceConnection; +use Magento\Framework\DB\Adapter\AdapterInterface; +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Setup\Model\Patch\PatchFactory; +use Magento\Setup\Model\Patch\PatchHistory; +use Magento\Setup\Model\Patch\PatchInterface; + +/** + * Class PatchFactoryTest + * @package Magento\Setup\Test\Unit\Model\Patch + */ +class PatchFactoryTest extends \PHPUnit\Framework\TestCase +{ + /** + * @var PatchFactory + */ + private $patchFactory; + + /** + * @var ObjectManagerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $objectManagerMock; + + protected function setUp() + { + $objectManager = new ObjectManager($this); + $this->objectManagerMock = $this->createMock(ObjectManagerInterface::class); + $this->patchFactory = $objectManager->getObject( + PatchFactory::class, + [ + 'objectManager' => $this->objectManagerMock, + ] + ); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage stdClass should implement Magento\Setup\Model\Patch\PatchInterface interface + */ + public function testCreateNonPatchInterface() + { + $patchNonPatchInterface = $this->createMock(\stdClass::class); + $this->objectManagerMock->expects($this->any()) + ->method('create') + ->with('\\stdClass') + ->willReturn($patchNonPatchInterface); + + $this->patchFactory->create(\stdClass::class); + } +} diff --git a/setup/src/Magento/Setup/Test/Unit/Model/Patch/PatchHistoryTest.php b/setup/src/Magento/Setup/Test/Unit/Model/Patch/PatchHistoryTest.php new file mode 100644 index 0000000000000..0918909681739 --- /dev/null +++ b/setup/src/Magento/Setup/Test/Unit/Model/Patch/PatchHistoryTest.php @@ -0,0 +1,86 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Setup\Test\Unit\Model\Patch; + +use Magento\Framework\App\ResourceConnection; +use Magento\Framework\DB\Adapter\AdapterInterface; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Setup\Model\Patch\PatchHistory; +use Magento\Setup\Model\Patch\PatchInterface; + +/** + * Class PatchHistoryTest + * @package Magento\Setup\Test\Unit\Model\Patch + */ +class PatchHistoryTest extends \PHPUnit\Framework\TestCase +{ + /** + * @var PatchHistory + */ + private $patchHistory; + + /** + * @var ResourceConnection|\PHPUnit_Framework_MockObject_MockObject + */ + private $resourceConnectionMock; + + protected function setUp() + { + $objectManager = new ObjectManager($this); + $this->resourceConnectionMock = $this->createMock(ResourceConnection::class); + $this->patchHistory = $objectManager->getObject( + PatchHistory::class, + [ + 'resourceConnection' => $this->resourceConnectionMock, + ] + ); + } + + /** + * Test fix non-applied patch + */ + public function testFixPatch() + { + /** @var PatchInterface|\PHPUnit_Framework_MockObject_MockObject $patch1 */ + $patch1 = $this->createMock(PatchInterface::class); + /** @var AdapterInterface|\PHPUnit_Framework_MockObject_MockObject $adapterMock */ + $adapterMock = $this->createMock(AdapterInterface::class); + $this->resourceConnectionMock->expects($this->any())->method('getConnection')->willReturn($adapterMock); + $selectMock = $this->createMock(\Magento\Framework\DB\Select::class); + $selectMock->expects($this->once())->method('from'); + $adapterMock->expects($this->any())->method('select')->willReturn($selectMock); + $adapterMock->expects($this->once())->method('fetchCol')->willReturn([]); + $this->resourceConnectionMock->expects($this->any()) + ->method('getTableName') + ->willReturn(PatchHistory::TABLE_NAME); + $adapterMock->expects($this->once())->method('insert') + ->with(PatchHistory::TABLE_NAME, [PatchHistory::CLASS_NAME => get_class($patch1)]); + $this->patchHistory->fixPatch(get_class($patch1)); + } + + /** + * @expectedException \LogicException + * @expectedExceptionMessageRegExp "Patch [a-zA-Z0-9\_]+ cannot be applied twice" + */ + public function testFixAppliedPatch() + { + /** @var PatchInterface|\PHPUnit_Framework_MockObject_MockObject $patch1 */ + $patch1 = $this->createMock(PatchInterface::class); + /** @var AdapterInterface|\PHPUnit_Framework_MockObject_MockObject $adapterMock */ + $adapterMock = $this->createMock(AdapterInterface::class); + $this->resourceConnectionMock->expects($this->any())->method('getConnection')->willReturn($adapterMock); + $selectMock = $this->createMock(\Magento\Framework\DB\Select::class); + $selectMock->expects($this->once())->method('from'); + $adapterMock->expects($this->any())->method('select')->willReturn($selectMock); + $adapterMock->expects($this->once())->method('fetchCol')->willReturn([get_class($patch1)]); + $this->resourceConnectionMock->expects($this->any()) + ->method('getTableName') + ->willReturn(PatchHistory::TABLE_NAME); + $adapterMock->expects($this->never())->method('insert'); + $this->patchHistory->fixPatch(get_class($patch1)); + } +} diff --git a/setup/src/Magento/Setup/Test/Unit/Model/Patch/PatchRegirtryTest.php b/setup/src/Magento/Setup/Test/Unit/Model/Patch/PatchRegirtryTest.php new file mode 100644 index 0000000000000..7957f9a192213 --- /dev/null +++ b/setup/src/Magento/Setup/Test/Unit/Model/Patch/PatchRegirtryTest.php @@ -0,0 +1,100 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Setup\Test\Unit\Model\Patch; + +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Setup\Model\Patch\PatchFactory; +use Magento\Setup\Model\Patch\PatchHistory; +use Magento\Setup\Model\Patch\PatchRegistry; + +/** + * Class PatchRegirtryTest + * @package Magento\Setup\Test\Unit\Model\Patch + */ +class PatchRegirtryTest extends \PHPUnit\Framework\TestCase +{ + /** + * @var PatchRegistry + */ + private $patchRegistry; + + /** + * @var PatchFactory|\PHPUnit_Framework_MockObject_MockObject + */ + private $patchFactoryMock; + + /** + * @var PatchHistory|\PHPUnit_Framework_MockObject_MockObject + */ + private $patchHistoryMock; + + protected function setUp() + { + $objectManager = new ObjectManager($this); + $this->patchFactoryMock = $this->getMockBuilder(PatchFactory::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->patchHistoryMock = $this->getMockBuilder(PatchHistory::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->patchRegistry = $objectManager->getObject( + PatchRegistry::class, + [ + 'patchHistory' => $this->patchHistoryMock, + 'patchFactory' => $this->patchFactoryMock, + ] + ); + require_once __DIR__ . '/../_files/data_patch_classes.php'; + } + + public function testRegisterAppliedPatch() + { + $this->patchHistoryMock->expects($this->once()) + ->method('isApplied') + ->with(\SomeDataPatch::class) + ->willReturn(false); + + $this->assertEquals(\SomeDataPatch::class, $this->patchRegistry->registerPatch(\SomeDataPatch::class)); + } + + public function testRegisterNonAplliedPatch() + { + $this->patchHistoryMock->expects($this->once()) + ->method('isApplied') + ->with(\SomeDataPatch::class) + ->willReturn(true); + + $this->assertEquals(false, $this->patchRegistry->registerPatch(\SomeDataPatch::class)); + } + + public function testGetIterator() + { + $this->patchHistoryMock->expects($this->any()) + ->method('isApplied') + ->willReturnMap( + [ + [\SomeDataPatch::class, false], + [\OtherDataPatch::class, false] + ] + ); + + $this->assertEquals(\SomeDataPatch::class, $this->patchRegistry->registerPatch(\SomeDataPatch::class)); + + $actualPatches = []; + foreach ($this->patchRegistry->getIterator() as $patch) { + $actualPatches[] = $patch; + } + // assert that all dependencies are present and placed in valid sequence + $this->assertEquals( + [\OtherDataPatch::class, \SomeDataPatch::class], + $actualPatches, + 'Failed to assert that actual non-apllied patches sequence is valid.' + ); + } +} diff --git a/setup/src/Magento/Setup/Test/Unit/Model/_files/data_patch_classes.php b/setup/src/Magento/Setup/Test/Unit/Model/_files/data_patch_classes.php new file mode 100644 index 0000000000000..e334400ce9244 --- /dev/null +++ b/setup/src/Magento/Setup/Test/Unit/Model/_files/data_patch_classes.php @@ -0,0 +1,136 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +// @codingStandardsIgnoreFile - as of namespace absence + +class OtherDataPatch implements \Magento\Setup\Model\Patch\DataPatchInterface +{ + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return []; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + } +} + +class SomeDataPatch implements + \Magento\Setup\Model\Patch\DataPatchInterface, + \Magento\Setup\Model\Patch\PatchVersionInterface +{ + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return [ + OtherDataPatch::class, + ]; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + return $this; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.0'; + } +} + +class NonTransactionableDataPatch implements + \Magento\Setup\Model\Patch\DataPatchInterface, + \Magento\Setup\Model\Patch\NonTransactionableInterface +{ + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return []; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + } +} + +class RevertableDataPatch implements + \Magento\Setup\Model\Patch\DataPatchInterface, + \Magento\Setup\Model\Patch\PatchRevertableInterface +{ + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return []; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + } + + /** + * {@inheritdoc} + */ + public function revert() + { + } +} diff --git a/setup/src/Magento/Setup/Test/Unit/Model/_files/schema_patch_classes.php b/setup/src/Magento/Setup/Test/Unit/Model/_files/schema_patch_classes.php new file mode 100644 index 0000000000000..9245380dbfdca --- /dev/null +++ b/setup/src/Magento/Setup/Test/Unit/Model/_files/schema_patch_classes.php @@ -0,0 +1,72 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +// @codingStandardsIgnoreFile - as of namespace absence + +class OtherSchemaPatch implements \Magento\Setup\Model\Patch\SchemaPatchInterface +{ + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return []; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + } +} + +class SomeSchemaPatch implements + \Magento\Setup\Model\Patch\SchemaPatchInterface, + \Magento\Setup\Model\Patch\PatchVersionInterface +{ + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return [ + OtherDataPatch::class, + ]; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + return $this; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '2.0.0'; + } +}