diff --git a/app/code/Magento/AdminNotification/Controller/Adminhtml/Notification/AjaxMarkAsRead.php b/app/code/Magento/AdminNotification/Controller/Adminhtml/Notification/AjaxMarkAsRead.php index 31a129d57ab90..da797fe12e75a 100644 --- a/app/code/Magento/AdminNotification/Controller/Adminhtml/Notification/AjaxMarkAsRead.php +++ b/app/code/Magento/AdminNotification/Controller/Adminhtml/Notification/AjaxMarkAsRead.php @@ -6,12 +6,35 @@ */ namespace Magento\AdminNotification\Controller\Adminhtml\Notification; +use Magento\Backend\App\Action; +use Magento\Framework\Controller\ResultFactory; + class AjaxMarkAsRead extends \Magento\AdminNotification\Controller\Adminhtml\Notification { + /** + * @var \Magento\AdminNotification\Model\NotificationService + */ + private $notificationService; + + /** + * @param Action\Context $context + * @param \Magento\AdminNotification\Model\NotificationService|null $notificationService + * @throws \RuntimeException + */ + public function __construct( + Action\Context $context, + \Magento\AdminNotification\Model\NotificationService $notificationService = null + ) { + parent::__construct($context); + $this->notificationService = $notificationService?: \Magento\Framework\App\ObjectManager::getInstance() + ->get(\Magento\AdminNotification\Model\NotificationService::class); + } + /** * Mark notification as read (AJAX action) * - * @return void + * @return \Magento\Framework\Controller\Result\Json|void + * @throws \InvalidArgumentException */ public function execute() { @@ -21,17 +44,15 @@ public function execute() $notificationId = (int)$this->getRequest()->getPost('id'); $responseData = []; try { - $this->_objectManager->create( - \Magento\AdminNotification\Model\NotificationService::class - )->markAsRead( - $notificationId - ); + $this->notificationService->markAsRead($notificationId); $responseData['success'] = true; } catch (\Exception $e) { $responseData['success'] = false; } - $this->getResponse()->representJson( - $this->_objectManager->create(\Magento\Framework\Json\Helper\Data::class)->jsonEncode($responseData) - ); + + /** @var \Magento\Framework\Controller\Result\Json $resultJson */ + $resultJson = $this->resultFactory->create(ResultFactory::TYPE_JSON); + $resultJson->setData($responseData); + return $resultJson; } } diff --git a/app/code/Magento/AdminNotification/composer.json b/app/code/Magento/AdminNotification/composer.json index afb820a2e6c93..227837558a8b3 100644 --- a/app/code/Magento/AdminNotification/composer.json +++ b/app/code/Magento/AdminNotification/composer.json @@ -3,15 +3,15 @@ "description": "N/A", "require": { "php": "7.0.2|7.0.4|~7.0.6|~7.1.0", - "magento/module-store": "100.2.*", - "magento/module-backend": "100.2.*", - "magento/module-media-storage": "100.2.*", - "magento/framework": "100.2.*", - "magento/module-ui": "100.2.*", + "magento/module-store": "100.3.*", + "magento/module-backend": "100.3.*", + "magento/module-media-storage": "100.3.*", + "magento/framework": "100.3.*", + "magento/module-ui": "100.3.*", "lib-libxml": "*" }, "type": "magento2-module", - "version": "100.2.0-dev", + "version": "100.3.0-dev", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/AdminNotification/i18n/en_US.csv b/app/code/Magento/AdminNotification/i18n/en_US.csv index 1afb8104bfef6..16c5abb9db0d2 100644 --- a/app/code/Magento/AdminNotification/i18n/en_US.csv +++ b/app/code/Magento/AdminNotification/i18n/en_US.csv @@ -1,13 +1,13 @@ "Read Details","Read Details" "Mark as Read","Mark as Read" "Are you sure?","Are you sure?" -"Remove","Remove" +Remove,Remove "Messages Inbox","Messages Inbox" "You have %1 new system messages","You have %1 new system messages" "You have %1 new system message","You have %1 new system message" "Incoming Message","Incoming Message" -"close","close" -"Notifications","Notifications" +close,close +Notifications,Notifications "The message has been marked as Read.","The message has been marked as Read." "We couldn't mark the notification as Read because of an error.","We couldn't mark the notification as Read because of an error." "Please select messages.","Please select messages." @@ -20,10 +20,10 @@ "6 Hours","6 Hours" "12 Hours","12 Hours" "24 Hours","24 Hours" -"critical","critical" -"major","major" -"minor","minor" -"notice","notice" +critical,critical +major,major +minor,minor +notice,notice "Wrong message type","Wrong message type" "Wrong notification ID specified.","Wrong notification ID specified." "{{base_url}} is not recommended to use in a production environment to declare the Base Unsecure URL / Base Secure URL. We highly recommend changing this value in your Magento configuration.","{{base_url}} is not recommended to use in a production environment to declare the Base Unsecure URL / Base Secure URL. We highly recommend changing this value in your Magento configuration." @@ -32,12 +32,11 @@ "We were unable to synchronize one or more media files. Please refer to the log file for details.","We were unable to synchronize one or more media files. Please refer to the log file for details." "Synchronization of media storages has been completed.","Synchronization of media storages has been completed." "Your web server is set up incorrectly and allows unauthorized access to sensitive files. Please contact your hosting provider.","Your web server is set up incorrectly and allows unauthorized access to sensitive files. Please contact your hosting provider." -"Close popup","Close popup" -"Close","Close" "System Messages:","System Messages:" "Critical System Messages","Critical System Messages" "Major System Messages","Major System Messages" "System messages","System messages" +Close,Close "See All (","See All (" " unread)"," unread)" "Show Toolbar","Show Toolbar" @@ -45,7 +44,7 @@ "Use HTTPS to Get Feed","Use HTTPS to Get Feed" "Update Frequency","Update Frequency" "Last Update","Last Update" -"Severity","Severity" +Severity,Severity "Date Added","Date Added" -"Message","Message" -"Actions","Actions" +Message,Message +Actions,Actions diff --git a/app/code/Magento/AdvancedPricingImportExport/composer.json b/app/code/Magento/AdvancedPricingImportExport/composer.json index 228464ecd6304..acc3e3ead715a 100644 --- a/app/code/Magento/AdvancedPricingImportExport/composer.json +++ b/app/code/Magento/AdvancedPricingImportExport/composer.json @@ -3,17 +3,17 @@ "description": "N/A", "require": { "php": "7.0.2|7.0.4|~7.0.6|~7.1.0", - "magento/module-catalog": "101.1.*", - "magento/module-catalog-inventory": "100.2.*", - "magento/module-eav": "100.2.*", - "magento/module-import-export": "100.2.*", - "magento/module-catalog-import-export": "100.2.*", - "magento/module-customer": "100.2.*", - "magento/module-store": "100.2.*", - "magento/framework": "100.2.*" + "magento/module-catalog": "101.2.*", + "magento/module-catalog-inventory": "100.3.*", + "magento/module-eav": "100.3.*", + "magento/module-import-export": "100.3.*", + "magento/module-catalog-import-export": "100.3.*", + "magento/module-customer": "100.3.*", + "magento/module-store": "100.3.*", + "magento/framework": "100.3.*" }, "type": "magento2-module", - "version": "100.2.0-dev", + "version": "100.3.0-dev", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/AdvancedPricingImportExport/i18n/en_US.csv b/app/code/Magento/AdvancedPricingImportExport/i18n/en_US.csv index 56b3d249c4123..54afa107ef377 100644 --- a/app/code/Magento/AdvancedPricingImportExport/i18n/en_US.csv +++ b/app/code/Magento/AdvancedPricingImportExport/i18n/en_US.csv @@ -1,4 +1,4 @@ "Please correct the data sent.","Please correct the data sent." -"Entity type model \'%1\' is not found","Entity type model \'%1\' is not found" +"Entity type model '%1' is not found","Entity type model '%1' is not found" "Entity type model must be an instance of \Magento\CatalogImportExport\Model\Export\Product\Type\AbstractType","Entity type model must be an instance of \Magento\CatalogImportExport\Model\Export\Product\Type\AbstractType" "There are no product types available for export","There are no product types available for export" diff --git a/app/code/Magento/Analytics/Controller/Adminhtml/Reports/Show.php b/app/code/Magento/Analytics/Controller/Adminhtml/Reports/Show.php index 7f0aade798e18..1b0e5c92420de 100644 --- a/app/code/Magento/Analytics/Controller/Adminhtml/Reports/Show.php +++ b/app/code/Magento/Analytics/Controller/Adminhtml/Reports/Show.php @@ -5,6 +5,7 @@ */ namespace Magento\Analytics\Controller\Adminhtml\Reports; +use Magento\Analytics\Model\Exception\State\SubscriptionUpdateException; use Magento\Analytics\Model\ReportUrlProvider; use Magento\Backend\App\Action; use Magento\Backend\App\Action\Context; @@ -55,6 +56,9 @@ public function execute() $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT); try { $resultRedirect->setUrl($this->reportUrlProvider->getUrl()); + } catch (SubscriptionUpdateException $e) { + $this->getMessageManager()->addNoticeMessage($e->getMessage()); + $resultRedirect->setPath('adminhtml'); } catch (LocalizedException $e) { $this->getMessageManager()->addExceptionMessage($e, $e->getMessage()); $resultRedirect->setPath('adminhtml'); diff --git a/app/code/Magento/Analytics/Cron/Update.php b/app/code/Magento/Analytics/Cron/Update.php index 36e6c3e59e5c7..9062a7bac7551 100644 --- a/app/code/Magento/Analytics/Cron/Update.php +++ b/app/code/Magento/Analytics/Cron/Update.php @@ -5,14 +5,14 @@ */ namespace Magento\Analytics\Cron; +use Magento\Analytics\Model\AnalyticsToken; +use Magento\Analytics\Model\Config\Backend\Baseurl\SubscriptionUpdateHandler; use Magento\Analytics\Model\Connector; -use Magento\Analytics\Model\Plugin\BaseUrlConfigPlugin; use Magento\Framework\FlagManager; use Magento\Framework\App\Config\ReinitableConfigInterface; use Magento\Framework\App\Config\Storage\WriterInterface; /** - * Class Update * Executes by cron schedule in case base url was changed */ class Update @@ -28,8 +28,6 @@ class Update private $configWriter; /** - * Reinitable Config Model. - * * @var ReinitableConfigInterface */ private $reinitableConfig; @@ -40,22 +38,29 @@ class Update private $flagManager; /** - * Update constructor. + * @var AnalyticsToken + */ + private $analyticsToken; + + /** * @param Connector $connector * @param WriterInterface $configWriter * @param ReinitableConfigInterface $reinitableConfig * @param FlagManager $flagManager + * @param AnalyticsToken $analyticsToken */ public function __construct( Connector $connector, WriterInterface $configWriter, ReinitableConfigInterface $reinitableConfig, - FlagManager $flagManager + FlagManager $flagManager, + AnalyticsToken $analyticsToken ) { $this->connector = $connector; $this->configWriter = $configWriter; $this->reinitableConfig = $reinitableConfig; $this->flagManager = $flagManager; + $this->analyticsToken = $analyticsToken; } /** @@ -65,13 +70,23 @@ public function __construct( */ public function execute() { - $updateResult = $this->connector->execute('update'); - if ($updateResult === false) { - return false; + $result = false; + $attemptsCount = $this->flagManager + ->getFlagData(SubscriptionUpdateHandler::SUBSCRIPTION_UPDATE_REVERSE_COUNTER_FLAG_CODE); + + if ($attemptsCount) { + $attemptsCount -= 1; + $result = $this->connector->execute('update'); + } + + if ($result || ($attemptsCount <= 0) || (!$this->analyticsToken->isTokenExist())) { + $this->flagManager + ->deleteFlag(SubscriptionUpdateHandler::SUBSCRIPTION_UPDATE_REVERSE_COUNTER_FLAG_CODE); + $this->flagManager->deleteFlag(SubscriptionUpdateHandler::PREVIOUS_BASE_URL_FLAG_CODE); + $this->configWriter->delete(SubscriptionUpdateHandler::UPDATE_CRON_STRING_PATH); + $this->reinitableConfig->reinit(); } - $this->configWriter->delete(BaseUrlConfigPlugin::UPDATE_CRON_STRING_PATH); - $this->flagManager->deleteFlag(BaseUrlConfigPlugin::OLD_BASE_URL_FLAG_CODE); - $this->reinitableConfig->reinit(); - return true; + + return $result; } } diff --git a/app/code/Magento/Analytics/Model/Config/Backend/Baseurl/SubscriptionUpdateHandler.php b/app/code/Magento/Analytics/Model/Config/Backend/Baseurl/SubscriptionUpdateHandler.php new file mode 100644 index 0000000000000..6e6f008d49f7e --- /dev/null +++ b/app/code/Magento/Analytics/Model/Config/Backend/Baseurl/SubscriptionUpdateHandler.php @@ -0,0 +1,107 @@ +analyticsToken = $analyticsToken; + $this->flagManager = $flagManager; + $this->reinitableConfig = $reinitableConfig; + $this->configWriter = $configWriter; + } + + /** + * Activate process of subscription update handling. + * + * @param string $url + * @return bool + */ + public function processUrlUpdate(string $url) + { + if ($this->analyticsToken->isTokenExist()) { + if (!$this->flagManager->getFlagData(self::PREVIOUS_BASE_URL_FLAG_CODE)) { + $this->flagManager->saveFlag(self::PREVIOUS_BASE_URL_FLAG_CODE, $url); + } + + $this->flagManager + ->saveFlag(self::SUBSCRIPTION_UPDATE_REVERSE_COUNTER_FLAG_CODE, $this->attemptsInitValue); + $this->configWriter->save(self::UPDATE_CRON_STRING_PATH, $this->cronExpression); + $this->reinitableConfig->reinit(); + } + + return true; + } +} diff --git a/app/code/Magento/Analytics/Model/Connector/NotifyDataChangedCommand.php b/app/code/Magento/Analytics/Model/Connector/NotifyDataChangedCommand.php index 177ee64c82c5b..f1a8ea6460f9d 100644 --- a/app/code/Magento/Analytics/Model/Connector/NotifyDataChangedCommand.php +++ b/app/code/Magento/Analytics/Model/Connector/NotifyDataChangedCommand.php @@ -6,8 +6,8 @@ namespace Magento\Analytics\Model\Connector; use Magento\Analytics\Model\AnalyticsToken; +use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\HTTP\ZendClient; -use Magento\Config\Model\Config; use Psr\Log\LoggerInterface; use Magento\Store\Model\Store; use Magento\Analytics\Model\Connector\Http\ResponseResolver; @@ -33,7 +33,7 @@ class NotifyDataChangedCommand implements CommandInterface private $httpClient; /** - * @var Config + * @var ScopeConfigInterface */ private $config; @@ -51,14 +51,14 @@ class NotifyDataChangedCommand implements CommandInterface * NotifyDataChangedCommand constructor. * @param AnalyticsToken $analyticsToken * @param Http\ClientInterface $httpClient - * @param Config $config + * @param ScopeConfigInterface $config * @param ResponseResolver $responseResolver * @param LoggerInterface $logger */ public function __construct( AnalyticsToken $analyticsToken, Http\ClientInterface $httpClient, - Config $config, + ScopeConfigInterface $config, ResponseResolver $responseResolver, LoggerInterface $logger ) { @@ -80,16 +80,14 @@ public function execute() if ($this->analyticsToken->isTokenExist()) { $response = $this->httpClient->request( ZendClient::POST, - $this->config->getConfigDataValue($this->notifyDataChangedUrlPath), + $this->config->getValue($this->notifyDataChangedUrlPath), [ "access-token" => $this->analyticsToken->getToken(), - "url" => $this->config->getConfigDataValue( - Store::XML_PATH_SECURE_BASE_URL - ), + "url" => $this->config->getValue(Store::XML_PATH_SECURE_BASE_URL), ] ); $result = $this->responseResolver->getResult($response); } - return $result; + return (bool)$result; } } diff --git a/app/code/Magento/Analytics/Model/Connector/SignUpCommand.php b/app/code/Magento/Analytics/Model/Connector/SignUpCommand.php index 367b46de17c4b..a1f23637e04b1 100644 --- a/app/code/Magento/Analytics/Model/Connector/SignUpCommand.php +++ b/app/code/Magento/Analytics/Model/Connector/SignUpCommand.php @@ -8,7 +8,7 @@ use Magento\Analytics\Model\AnalyticsToken; use Magento\Analytics\Model\Connector\Http\ResponseResolver; use Magento\Analytics\Model\IntegrationManager; -use Magento\Config\Model\Config; +use Magento\Framework\App\Config\ScopeConfigInterface; use Psr\Log\LoggerInterface; use Magento\Framework\HTTP\ZendClient; use Magento\Store\Model\Store; @@ -36,7 +36,7 @@ class SignUpCommand implements CommandInterface private $integrationManager; /** - * @var Config + * @var ScopeConfigInterface */ private $config; @@ -60,7 +60,7 @@ class SignUpCommand implements CommandInterface * * @param AnalyticsToken $analyticsToken * @param IntegrationManager $integrationManager - * @param Config $config + * @param ScopeConfigInterface $config * @param Http\ClientInterface $httpClient * @param LoggerInterface $logger * @param ResponseResolver $responseResolver @@ -68,7 +68,7 @@ class SignUpCommand implements CommandInterface public function __construct( AnalyticsToken $analyticsToken, IntegrationManager $integrationManager, - Config $config, + ScopeConfigInterface $config, Http\ClientInterface $httpClient, LoggerInterface $logger, ResponseResolver $responseResolver @@ -101,12 +101,10 @@ public function execute() $this->integrationManager->activateIntegration(); $response = $this->httpClient->request( ZendClient::POST, - $this->config->getConfigDataValue($this->signUpUrlPath), + $this->config->getValue($this->signUpUrlPath), [ "token" => $integrationToken->getData('token'), - "url" => $this->config->getConfigDataValue( - Store::XML_PATH_SECURE_BASE_URL - ) + "url" => $this->config->getValue(Store::XML_PATH_SECURE_BASE_URL), ] ); @@ -121,6 +119,6 @@ public function execute() } } - return $result; + return (bool)$result; } } diff --git a/app/code/Magento/Analytics/Model/Connector/UpdateCommand.php b/app/code/Magento/Analytics/Model/Connector/UpdateCommand.php index a2d64a98e0409..8f05f1107e87e 100644 --- a/app/code/Magento/Analytics/Model/Connector/UpdateCommand.php +++ b/app/code/Magento/Analytics/Model/Connector/UpdateCommand.php @@ -6,9 +6,9 @@ namespace Magento\Analytics\Model\Connector; use Magento\Analytics\Model\AnalyticsToken; +use Magento\Analytics\Model\Config\Backend\Baseurl\SubscriptionUpdateHandler; use Magento\Analytics\Model\Connector\Http\ResponseResolver; -use Magento\Analytics\Model\Plugin\BaseUrlConfigPlugin; -use Magento\Config\Model\Config; +use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\FlagManager; use Magento\Framework\HTTP\ZendClient; use Magento\Store\Model\Store; @@ -36,7 +36,7 @@ class UpdateCommand implements CommandInterface private $httpClient; /** - * @var Config + * @var ScopeConfigInterface */ private $config; @@ -58,7 +58,7 @@ class UpdateCommand implements CommandInterface /** * @param AnalyticsToken $analyticsToken * @param Http\ClientInterface $httpClient - * @param Config $config + * @param ScopeConfigInterface $config * @param LoggerInterface $logger * @param FlagManager $flagManager * @param ResponseResolver $responseResolver @@ -66,7 +66,7 @@ class UpdateCommand implements CommandInterface public function __construct( AnalyticsToken $analyticsToken, Http\ClientInterface $httpClient, - Config $config, + ScopeConfigInterface $config, LoggerInterface $logger, FlagManager $flagManager, ResponseResolver $responseResolver @@ -90,12 +90,11 @@ public function execute() if ($this->analyticsToken->isTokenExist()) { $response = $this->httpClient->request( ZendClient::PUT, - $this->config->getConfigDataValue($this->updateUrlPath), + $this->config->getValue($this->updateUrlPath), [ - "url" => $this->flagManager->getFlagData(BaseUrlConfigPlugin::OLD_BASE_URL_FLAG_CODE), - "new-url" => $this->config->getConfigDataValue( - Store::XML_PATH_SECURE_BASE_URL - ), + "url" => $this->flagManager + ->getFlagData(SubscriptionUpdateHandler::PREVIOUS_BASE_URL_FLAG_CODE), + "new-url" => $this->config->getValue(Store::XML_PATH_SECURE_BASE_URL), "access-token" => $this->analyticsToken->getToken(), ] ); @@ -110,6 +109,6 @@ public function execute() } } - return $result; + return (bool)$result; } } diff --git a/app/code/Magento/Analytics/Model/Exception/State/SubscriptionUpdateException.php b/app/code/Magento/Analytics/Model/Exception/State/SubscriptionUpdateException.php new file mode 100644 index 0000000000000..5d127037afea9 --- /dev/null +++ b/app/code/Magento/Analytics/Model/Exception/State/SubscriptionUpdateException.php @@ -0,0 +1,17 @@ +flagManager = $flagManager; - $this->subscriptionStatusProvider = $subscriptionStatusProvider; - $this->configWriter = $configWriter; + $this->subscriptionUpdateHandler = $subscriptionUpdateHandler; } /** - * Sets update analytics cron job if base url was changed. + * Add additional handling after config value was saved. * - * @param \Magento\Config\Model\Config\Backend\Baseurl $subject - * @param \Magento\Config\Model\Config\Backend\Baseurl $result - * @return \Magento\Config\Model\Config\Backend\Baseurl + * @param Value $subject + * @param Value $result + * @return Value * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function afterAfterSave( - \Magento\Config\Model\Config\Backend\Baseurl $subject, - \Magento\Config\Model\Config\Backend\Baseurl $result + Value $subject, + Value $result ) { - if (!$result->isValueChanged()) { - return $result; - } - if ($this->isPluginApplicable($result)) { - $this->flagManager->saveFlag(static::OLD_BASE_URL_FLAG_CODE, $result->getOldValue()); - $this->configWriter->save(self::UPDATE_CRON_STRING_PATH, $this->cronExpression); + $this->subscriptionUpdateHandler->processUrlUpdate($result->getOldValue()); } return $result; } /** - * @param \Magento\Config\Model\Config\Backend\Baseurl $result - * + * @param Value $result * @return bool */ - private function isPluginApplicable(\Magento\Config\Model\Config\Backend\Baseurl $result) + private function isPluginApplicable(Value $result) { - return $result->getData('path') === \Magento\Store\Model\Store::XML_PATH_SECURE_BASE_URL - && $this->subscriptionStatusProvider->getStatus() === SubscriptionStatusProvider::ENABLED; + return $result->isValueChanged() + && ($result->getPath() === Store::XML_PATH_SECURE_BASE_URL) + && ($result->getScope() === ScopeConfigInterface::SCOPE_TYPE_DEFAULT); } } diff --git a/app/code/Magento/Analytics/Model/ReportUrlProvider.php b/app/code/Magento/Analytics/Model/ReportUrlProvider.php index b72374f4d9f62..e7fdf6f9e8132 100644 --- a/app/code/Magento/Analytics/Model/ReportUrlProvider.php +++ b/app/code/Magento/Analytics/Model/ReportUrlProvider.php @@ -5,8 +5,11 @@ */ namespace Magento\Analytics\Model; +use Magento\Analytics\Model\Config\Backend\Baseurl\SubscriptionUpdateHandler; use Magento\Analytics\Model\Connector\OTPRequest; +use Magento\Analytics\Model\Exception\State\SubscriptionUpdateException; use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Framework\FlagManager; /** * Provide URL on resource with reports. @@ -32,6 +35,11 @@ class ReportUrlProvider */ private $config; + /** + * @var FlagManager + */ + private $flagManager; + /** * Path to config value with URL which provide reports. * @@ -43,24 +51,35 @@ class ReportUrlProvider * @param AnalyticsToken $analyticsToken * @param OTPRequest $otpRequest * @param ScopeConfigInterface $config + * @param FlagManager $flagManager */ public function __construct( AnalyticsToken $analyticsToken, OTPRequest $otpRequest, - ScopeConfigInterface $config + ScopeConfigInterface $config, + FlagManager $flagManager ) { $this->analyticsToken = $analyticsToken; $this->otpRequest = $otpRequest; $this->config = $config; + $this->flagManager = $flagManager; } /** * Provide URL on resource with reports. * * @return string + * @throws SubscriptionUpdateException */ public function getUrl() { + if ($this->flagManager->getFlagData(SubscriptionUpdateHandler::PREVIOUS_BASE_URL_FLAG_CODE)) { + throw new SubscriptionUpdateException(__( + 'Your Base URL has been changed and your reports are being updated. ' + . 'Advanced Reporting will be available once this change has been processed. Please try again later.' + )); + } + $url = $this->config->getValue($this->urlReportConfigPath); if ($this->analyticsToken->isTokenExist()) { $otp = $this->otpRequest->call(); diff --git a/app/code/Magento/Analytics/Model/SubscriptionStatusProvider.php b/app/code/Magento/Analytics/Model/SubscriptionStatusProvider.php index 8fe548013c206..1dd831a672faa 100644 --- a/app/code/Magento/Analytics/Model/SubscriptionStatusProvider.php +++ b/app/code/Magento/Analytics/Model/SubscriptionStatusProvider.php @@ -5,6 +5,7 @@ */ namespace Magento\Analytics\Model; +use Magento\Analytics\Model\Config\Backend\Baseurl\SubscriptionUpdateHandler; use Magento\Analytics\Model\Config\Backend\Enabled\SubscriptionHandler; use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\FlagManager; @@ -93,6 +94,10 @@ public function getStatus() public function getStatusForEnabledSubscription() { $status = static::ENABLED; + if ($this->flagManager->getFlagData(SubscriptionUpdateHandler::PREVIOUS_BASE_URL_FLAG_CODE)) { + $status = self::PENDING; + } + if (!$this->analyticsToken->isTokenExist()) { $status = static::PENDING; if ($this->flagManager->getFlagData(SubscriptionHandler::ATTEMPTS_REVERSE_COUNTER_FLAG_CODE) === null) { diff --git a/app/code/Magento/Analytics/Test/Unit/Controller/Adminhtml/Reports/ShowTest.php b/app/code/Magento/Analytics/Test/Unit/Controller/Adminhtml/Reports/ShowTest.php index eaab952178daa..99de92cc63905 100644 --- a/app/code/Magento/Analytics/Test/Unit/Controller/Adminhtml/Reports/ShowTest.php +++ b/app/code/Magento/Analytics/Test/Unit/Controller/Adminhtml/Reports/ShowTest.php @@ -6,6 +6,7 @@ namespace Magento\Analytics\Test\Unit\Controller\Adminhtml\Reports; use Magento\Analytics\Controller\Adminhtml\Reports\Show; +use Magento\Analytics\Model\Exception\State\SubscriptionUpdateException; use Magento\Analytics\Model\ReportUrlProvider; use Magento\Framework\Controller\Result\Redirect; use Magento\Framework\Controller\ResultFactory; @@ -152,4 +153,33 @@ public function executeWithExceptionDataProvider() 'ExecuteWithException' => [new \Exception('TestMessage')], ]; } + + /** + * @return void + */ + public function testExecuteWithSubscriptionUpdateException() + { + $exception = new SubscriptionUpdateException(__('TestMessage')); + $this->resultFactoryMock + ->expects($this->once()) + ->method('create') + ->with(ResultFactory::TYPE_REDIRECT) + ->willReturn($this->redirectMock); + $this->reportUrlProviderMock + ->expects($this->once()) + ->method('getUrl') + ->with() + ->willThrowException($exception); + $this->messageManagerMock + ->expects($this->once()) + ->method('addNoticeMessage') + ->with($exception->getMessage()) + ->willReturnSelf(); + $this->redirectMock + ->expects($this->once()) + ->method('setPath') + ->with('adminhtml') + ->willReturnSelf(); + $this->assertSame($this->redirectMock, $this->showController->execute()); + } } diff --git a/app/code/Magento/Analytics/Test/Unit/Cron/UpdateTest.php b/app/code/Magento/Analytics/Test/Unit/Cron/UpdateTest.php index 9a5355de62a5c..23ba59a90ce7b 100644 --- a/app/code/Magento/Analytics/Test/Unit/Cron/UpdateTest.php +++ b/app/code/Magento/Analytics/Test/Unit/Cron/UpdateTest.php @@ -6,8 +6,9 @@ namespace Magento\Analytics\Test\Unit\Cron; use Magento\Analytics\Cron\Update; +use Magento\Analytics\Model\AnalyticsToken; +use Magento\Analytics\Model\Config\Backend\Baseurl\SubscriptionUpdateHandler; use Magento\Analytics\Model\Connector; -use Magento\Analytics\Model\Plugin\BaseUrlConfigPlugin; use Magento\Framework\App\Config\ReinitableConfigInterface; use Magento\Framework\App\Config\Storage\WriterInterface; use Magento\Framework\FlagManager; @@ -37,6 +38,11 @@ class UpdateTest extends \PHPUnit_Framework_TestCase */ private $reinitableConfigMock; + /** + * @var AnalyticsToken|\PHPUnit_Framework_MockObject_MockObject + */ + private $analyticsTokenMock; + /** * @var Update */ @@ -56,38 +62,153 @@ protected function setUp() $this->reinitableConfigMock = $this->getMockBuilder(ReinitableConfigInterface::class) ->disableOriginalConstructor() ->getMock(); + $this->analyticsTokenMock = $this->getMockBuilder(AnalyticsToken::class) + ->disableOriginalConstructor() + ->getMock(); $this->update = new Update( $this->connectorMock, $this->configWriterMock, $this->reinitableConfigMock, - $this->flagManagerMock + $this->flagManagerMock, + $this->analyticsTokenMock ); } - public function testExecute() + /** + * @return void + */ + public function testExecuteWithoutToken() { - $this->connectorMock->expects($this->once()) + $this->flagManagerMock + ->method('getFlagData') + ->with(SubscriptionUpdateHandler::SUBSCRIPTION_UPDATE_REVERSE_COUNTER_FLAG_CODE) + ->willReturn(10); + $this->connectorMock + ->expects($this->once()) ->method('execute') ->with('update') - ->willReturn(true); - $this->configWriterMock->expects($this->once()) - ->method('delete') - ->with(BaseUrlConfigPlugin::UPDATE_CRON_STRING_PATH); - $this->flagManagerMock->expects($this->once()) + ->willReturn(false); + $this->analyticsTokenMock + ->expects($this->once()) + ->method('isTokenExist') + ->willReturn(false); + $this->addFinalOutputAsserts(); + $this->assertFalse($this->update->execute()); + } + + /** + * @param bool $isExecuted + */ + private function addFinalOutputAsserts(bool $isExecuted = true) + { + $this->flagManagerMock + ->expects($this->exactly(2 * $isExecuted)) ->method('deleteFlag') - ->with(BaseUrlConfigPlugin::OLD_BASE_URL_FLAG_CODE); - $this->reinitableConfigMock->expects($this->once()) - ->method('reinit'); - $this->assertTrue($this->update->execute()); + ->withConsecutive( + [SubscriptionUpdateHandler::SUBSCRIPTION_UPDATE_REVERSE_COUNTER_FLAG_CODE], + [SubscriptionUpdateHandler::PREVIOUS_BASE_URL_FLAG_CODE] + ); + $this->configWriterMock + ->expects($this->exactly((int)$isExecuted)) + ->method('delete') + ->with(SubscriptionUpdateHandler::UPDATE_CRON_STRING_PATH); + $this->reinitableConfigMock + ->expects($this->exactly((int)$isExecuted)) + ->method('reinit') + ->with(); } - public function testExecuteUnsuccess() + /** + * @param $counterData + * @return void + * @dataProvider executeWithEmptyReverseCounterDataProvider + */ + public function testExecuteWithEmptyReverseCounter($counterData) { - $this->connectorMock->expects($this->once()) + $this->flagManagerMock + ->method('getFlagData') + ->with(SubscriptionUpdateHandler::SUBSCRIPTION_UPDATE_REVERSE_COUNTER_FLAG_CODE) + ->willReturn($counterData); + $this->connectorMock + ->expects($this->never()) ->method('execute') ->with('update') ->willReturn(false); + $this->analyticsTokenMock + ->method('isTokenExist') + ->willReturn(true); + $this->addFinalOutputAsserts(); $this->assertFalse($this->update->execute()); } + + /** + * Provides empty states of the reverse counter. + * + * @return array + */ + public function executeWithEmptyReverseCounterDataProvider() + { + return [ + [null], + [0] + ]; + } + + /** + * @param int $reverseCount + * @param bool $commandResult + * @param bool $finalConditionsIsExpected + * @param bool $functionResult + * @return void + * @dataProvider executeRegularScenarioDataProvider + */ + public function testExecuteRegularScenario( + int $reverseCount, + bool $commandResult, + bool $finalConditionsIsExpected, + bool $functionResult + ) { + $this->flagManagerMock + ->method('getFlagData') + ->with(SubscriptionUpdateHandler::SUBSCRIPTION_UPDATE_REVERSE_COUNTER_FLAG_CODE) + ->willReturn($reverseCount); + $this->connectorMock + ->expects($this->once()) + ->method('execute') + ->with('update') + ->willReturn($commandResult); + $this->analyticsTokenMock + ->method('isTokenExist') + ->willReturn(true); + $this->addFinalOutputAsserts($finalConditionsIsExpected); + $this->assertSame($functionResult, $this->update->execute()); + } + + /** + * @return array + */ + public function executeRegularScenarioDataProvider() + { + return [ + 'The last attempt with command execution result False' => [ + 'Reverse count' => 1, + 'Command result' => false, + 'Executed final output conditions' => true, + 'Function result' => false, + ], + 'Not the last attempt with command execution result False' => [ + 'Reverse count' => 10, + 'Command result' => false, + 'Executed final output conditions' => false, + 'Function result' => false, + ], + 'Command execution result True' => [ + 'Reverse count' => 10, + 'Command result' => true, + 'Executed final output conditions' => true, + 'Function result' => true, + ], + ]; + } } diff --git a/app/code/Magento/Analytics/Test/Unit/Model/Config/Backend/Baseurl/SubscriptionUpdateHandlerTest.php b/app/code/Magento/Analytics/Test/Unit/Model/Config/Backend/Baseurl/SubscriptionUpdateHandlerTest.php new file mode 100644 index 0000000000000..865ad236fc057 --- /dev/null +++ b/app/code/Magento/Analytics/Test/Unit/Model/Config/Backend/Baseurl/SubscriptionUpdateHandlerTest.php @@ -0,0 +1,178 @@ +reinitableConfigMock = $this->getMockBuilder(ReinitableConfigInterface::class) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + + $this->analyticsTokenMock = $this->getMockBuilder(AnalyticsToken::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->flagManagerMock = $this->getMockBuilder(FlagManager::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->configWriterMock = $this->getMockBuilder(WriterInterface::class) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + + $this->objectManagerHelper = new ObjectManagerHelper($this); + + $this->subscriptionUpdateHandler = $this->objectManagerHelper->getObject( + SubscriptionUpdateHandler::class, + [ + 'reinitableConfig' => $this->reinitableConfigMock, + 'analyticsToken' => $this->analyticsTokenMock, + 'flagManager' => $this->flagManagerMock, + 'configWriter' => $this->configWriterMock, + ] + ); + } + + /** + * @return void + */ + public function testTokenDoesNotExist() + { + $this->analyticsTokenMock + ->expects($this->once()) + ->method('isTokenExist') + ->with() + ->willReturn(false); + $this->flagManagerMock + ->expects($this->never()) + ->method('saveFlag'); + $this->configWriterMock + ->expects($this->never()) + ->method('save'); + $this->assertTrue($this->subscriptionUpdateHandler->processUrlUpdate('http://store.com')); + } + + /** + * @return void + */ + public function testTokenAndPreviousBaseUrlExist() + { + $url = 'https://store.com'; + $this->analyticsTokenMock + ->expects($this->once()) + ->method('isTokenExist') + ->with() + ->willReturn(true); + $this->flagManagerMock + ->expects($this->once()) + ->method('getFlagData') + ->with(SubscriptionUpdateHandler::PREVIOUS_BASE_URL_FLAG_CODE) + ->willReturn(true); + $this->flagManagerMock + ->expects($this->once()) + ->method('saveFlag') + ->withConsecutive( + [SubscriptionUpdateHandler::SUBSCRIPTION_UPDATE_REVERSE_COUNTER_FLAG_CODE, $this->attemptsInitValue], + [SubscriptionUpdateHandler::PREVIOUS_BASE_URL_FLAG_CODE, $url] + ); + $this->configWriterMock + ->expects($this->once()) + ->method('save') + ->with(SubscriptionUpdateHandler::UPDATE_CRON_STRING_PATH, $this->cronExpression); + $this->reinitableConfigMock + ->expects($this->once()) + ->method('reinit') + ->with(); + $this->assertTrue($this->subscriptionUpdateHandler->processUrlUpdate($url)); + } + + /** + * @return void + */ + public function testTokenExistAndWithoutPreviousBaseUrl() + { + $url = 'https://store.com'; + $this->analyticsTokenMock + ->expects($this->once()) + ->method('isTokenExist') + ->with() + ->willReturn(true); + $this->flagManagerMock + ->expects($this->once()) + ->method('getFlagData') + ->with(SubscriptionUpdateHandler::PREVIOUS_BASE_URL_FLAG_CODE) + ->willReturn(false); + $this->flagManagerMock + ->expects($this->exactly(2)) + ->method('saveFlag') + ->withConsecutive( + [SubscriptionUpdateHandler::PREVIOUS_BASE_URL_FLAG_CODE, $url], + [SubscriptionUpdateHandler::SUBSCRIPTION_UPDATE_REVERSE_COUNTER_FLAG_CODE, $this->attemptsInitValue] + ); + $this->configWriterMock + ->expects($this->once()) + ->method('save') + ->with(SubscriptionUpdateHandler::UPDATE_CRON_STRING_PATH, $this->cronExpression); + $this->reinitableConfigMock + ->expects($this->once()) + ->method('reinit') + ->with(); + $this->assertTrue($this->subscriptionUpdateHandler->processUrlUpdate($url)); + } +} diff --git a/app/code/Magento/Analytics/Test/Unit/Model/Connector/NotifyDataChangedCommandTest.php b/app/code/Magento/Analytics/Test/Unit/Model/Connector/NotifyDataChangedCommandTest.php index a30211c7f3475..5b86dd6557d69 100644 --- a/app/code/Magento/Analytics/Test/Unit/Model/Connector/NotifyDataChangedCommandTest.php +++ b/app/code/Magento/Analytics/Test/Unit/Model/Connector/NotifyDataChangedCommandTest.php @@ -8,8 +8,8 @@ use Magento\Analytics\Model\AnalyticsToken; use Magento\Analytics\Model\Connector\Http\JsonConverter; use Magento\Analytics\Model\Connector\Http\ResponseResolver; +use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\HTTP\ZendClient; -use Magento\Config\Model\Config; use Psr\Log\LoggerInterface; use Magento\Analytics\Model\Connector\NotifyDataChangedCommand; use Magento\Analytics\Model\Connector\Http\ClientInterface; @@ -32,7 +32,7 @@ class NotifyDataChangedCommandTest extends \PHPUnit_Framework_TestCase private $httpClientMock; /** - * @var Config|\PHPUnit_Framework_MockObject_MockObject + * @var ScopeConfigInterface|\PHPUnit_Framework_MockObject_MockObject */ public $configMock; @@ -51,7 +51,7 @@ protected function setUp() ->disableOriginalConstructor() ->getMock(); - $this->configMock = $this->getMockBuilder(Config::class) + $this->configMock = $this->getMockBuilder(ScopeConfigInterface::class) ->disableOriginalConstructor() ->getMock(); @@ -80,7 +80,7 @@ public function testExecuteSuccess() ->method('isTokenExist') ->willReturn(true); $this->configMock->expects($this->any()) - ->method('getConfigDataValue') + ->method('getValue') ->willReturn($configVal); $this->analyticsTokenMock->expects($this->once()) ->method('getToken') diff --git a/app/code/Magento/Analytics/Test/Unit/Model/Connector/SignUpCommandTest.php b/app/code/Magento/Analytics/Test/Unit/Model/Connector/SignUpCommandTest.php index 624728f3440c9..cc9eba99b3d48 100644 --- a/app/code/Magento/Analytics/Test/Unit/Model/Connector/SignUpCommandTest.php +++ b/app/code/Magento/Analytics/Test/Unit/Model/Connector/SignUpCommandTest.php @@ -11,7 +11,7 @@ use Magento\Analytics\Model\Connector\SignUpCommand; use Magento\Analytics\Model\AnalyticsToken; use Magento\Analytics\Model\IntegrationManager; -use Magento\Config\Model\Config; +use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Integration\Model\Oauth\Token as IntegrationToken; use Psr\Log\LoggerInterface; @@ -41,7 +41,7 @@ class SignUpCommandTest extends \PHPUnit_Framework_TestCase private $integrationToken; /** - * @var Config|\PHPUnit_Framework_MockObject_MockObject + * @var ScopeConfigInterface|\PHPUnit_Framework_MockObject_MockObject */ private $configMock; @@ -71,7 +71,7 @@ protected function setUp() $this->integrationToken = $this->getMockBuilder(IntegrationToken::class) ->disableOriginalConstructor() ->getMock(); - $this->configMock = $this->getMockBuilder(Config::class) + $this->configMock = $this->getMockBuilder(ScopeConfigInterface::class) ->disableOriginalConstructor() ->getMock(); $this->httpClientMock = $this->getMockBuilder(ClientInterface::class) @@ -105,7 +105,7 @@ public function testExecuteSuccess() $data = $this->getTestData(); $this->configMock->expects($this->any()) - ->method('getConfigDataValue') + ->method('getValue') ->willReturn($data['url']); $this->integrationToken->expects($this->any()) ->method('getData') diff --git a/app/code/Magento/Analytics/Test/Unit/Model/Connector/UpdateCommandTest.php b/app/code/Magento/Analytics/Test/Unit/Model/Connector/UpdateCommandTest.php index c5f96a96b4432..eb22461d789c8 100644 --- a/app/code/Magento/Analytics/Test/Unit/Model/Connector/UpdateCommandTest.php +++ b/app/code/Magento/Analytics/Test/Unit/Model/Connector/UpdateCommandTest.php @@ -6,12 +6,12 @@ namespace Magento\Analytics\Test\Unit\Model\Connector; use Magento\Analytics\Model\AnalyticsToken; +use Magento\Analytics\Model\Config\Backend\Baseurl\SubscriptionUpdateHandler; use Magento\Analytics\Model\Connector\Http\ResponseResolver; +use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\FlagManager; use Magento\Framework\HTTP\ZendClient; -use Magento\Config\Model\Config; use Psr\Log\LoggerInterface; -use Magento\Analytics\Model\Plugin\BaseUrlConfigPlugin; use Magento\Analytics\Model\Connector\UpdateCommand; use Magento\Analytics\Model\Connector\Http\ClientInterface; @@ -36,7 +36,7 @@ class UpdateCommandTest extends \PHPUnit_Framework_TestCase private $httpClientMock; /** - * @var Config|\PHPUnit_Framework_MockObject_MockObject + * @var ScopeConfigInterface|\PHPUnit_Framework_MockObject_MockObject */ public $configMock; @@ -65,7 +65,7 @@ protected function setUp() ->disableOriginalConstructor() ->getMock(); - $this->configMock = $this->getMockBuilder(Config::class) + $this->configMock = $this->getMockBuilder(ScopeConfigInterface::class) ->disableOriginalConstructor() ->getMock(); @@ -101,12 +101,12 @@ public function testExecuteSuccess() ->willReturn(true); $this->configMock->expects($this->any()) - ->method('getConfigDataValue') + ->method('getValue') ->willReturn($configVal); $this->flagManagerMock->expects($this->once()) ->method('getFlagData') - ->with(BaseUrlConfigPlugin::OLD_BASE_URL_FLAG_CODE) + ->with(SubscriptionUpdateHandler::PREVIOUS_BASE_URL_FLAG_CODE) ->willReturn($url); $this->analyticsTokenMock->expects($this->once()) diff --git a/app/code/Magento/Analytics/Test/Unit/Model/Plugin/BaseUrlConfigPluginTest.php b/app/code/Magento/Analytics/Test/Unit/Model/Plugin/BaseUrlConfigPluginTest.php index caf81b77fbdf9..38d073a4b4550 100644 --- a/app/code/Magento/Analytics/Test/Unit/Model/Plugin/BaseUrlConfigPluginTest.php +++ b/app/code/Magento/Analytics/Test/Unit/Model/Plugin/BaseUrlConfigPluginTest.php @@ -5,12 +5,13 @@ */ namespace Magento\Analytics\Test\Unit\Model\Plugin; +use Magento\Analytics\Model\Config\Backend\Baseurl\SubscriptionUpdateHandler; use Magento\Analytics\Model\Plugin\BaseUrlConfigPlugin; use Magento\Analytics\Model\SubscriptionStatusProvider; -use Magento\Config\Model\Config\Backend\Baseurl; -use Magento\Framework\FlagManager; -use Magento\Framework\App\Config\Storage\WriterInterface; +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Framework\App\Config\Value; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +use Magento\Store\Model\ScopeInterface; use Magento\Store\Model\Store; /** @@ -19,25 +20,15 @@ class BaseUrlConfigPluginTest extends \PHPUnit_Framework_TestCase { /** - * @var FlagManager | \PHPUnit_Framework_MockObject_MockObject + * @var SubscriptionUpdateHandler | \PHPUnit_Framework_MockObject_MockObject */ - private $flagManagerMock; + private $subscriptionUpdateHandlerMock; /** - * @var BaseUrl | \PHPUnit_Framework_MockObject_MockObject + * @var Value | \PHPUnit_Framework_MockObject_MockObject */ private $configValueMock; - /** - * @var SubscriptionStatusProvider | \PHPUnit_Framework_MockObject_MockObject - */ - private $subscriptionStatusProvider; - - /** - * @var WriterInterface | \PHPUnit_Framework_MockObject_MockObject - */ - private $configWriterMock; - /** * @var ObjectManagerHelper */ @@ -53,70 +44,42 @@ class BaseUrlConfigPluginTest extends \PHPUnit_Framework_TestCase */ protected function setUp() { - $this->flagManagerMock = $this->getMockBuilder(FlagManager::class) - ->disableOriginalConstructor() - ->getMock(); - $this->configValueMock = $this->getMockBuilder(Baseurl::class) + $this->subscriptionUpdateHandlerMock = $this->getMockBuilder(SubscriptionUpdateHandler::class) ->disableOriginalConstructor() ->getMock(); - $this->subscriptionStatusProvider = $this->getMockBuilder(SubscriptionStatusProvider::class) + $this->configValueMock = $this->getMockBuilder(Value::class) ->disableOriginalConstructor() + ->setMethods(['isValueChanged', 'getPath', 'getScope', 'getOldValue']) ->getMock(); - $this->configWriterMock = $this->getMockBuilder(WriterInterface::class) - ->disableOriginalConstructor() - ->getMockForAbstractClass(); $this->objectManagerHelper = new ObjectManagerHelper($this); $this->plugin = $this->objectManagerHelper->getObject( BaseUrlConfigPlugin::class, [ - 'flagManager' => $this->flagManagerMock, - 'subscriptionStatusProvider' => $this->subscriptionStatusProvider, - 'configWriter' => $this->configWriterMock + 'subscriptionUpdateHandler' => $this->subscriptionUpdateHandlerMock, ] ); } /** - * @param array $testData - * @param \PHPUnit_Framework_MockObject_Matcher_InvokedCount $saveConfigInvokeMatcher - * @param \PHPUnit_Framework_MockObject_Matcher_InvokedCount $oldValueInvokeMatcher - * @param \PHPUnit_Framework_MockObject_Matcher_InvokedCount $saveFlagInvokeMatcher - * @param \PHPUnit_Framework_MockObject_Matcher_InvokedCount $configValueGetPathMatcher - * + * @param array $configValueData * @return void - * @dataProvider pluginDataProvider + * @dataProvider afterSavePluginIsNotApplicableDataProvider */ - public function testPluginForAfterSave( - array $testData, - \PHPUnit_Framework_MockObject_Matcher_InvokedCount $saveConfigInvokeMatcher, - \PHPUnit_Framework_MockObject_Matcher_InvokedCount $oldValueInvokeMatcher, - \PHPUnit_Framework_MockObject_Matcher_InvokedCount $saveFlagInvokeMatcher, - \PHPUnit_Framework_MockObject_Matcher_InvokedCount $configValueGetPathMatcher + public function testAfterSavePluginIsNotApplicable( + array $configValueData ) { - $this->configValueMock->expects($this->once()) + $this->configValueMock ->method('isValueChanged') - ->willReturn($testData['isValueChanged']); - - $this->configValueMock->expects($configValueGetPathMatcher) - ->method('getData') - ->with('path') - ->willReturn($testData['path']); - $this->subscriptionStatusProvider->expects($this->any())->method('getStatus') - ->willReturn($testData['subscriptionStatus']); - - $oldUrl = 'mage.dev'; - $this->configValueMock->expects($oldValueInvokeMatcher) - ->method('getOldValue') - ->willReturn($oldUrl); - $this->flagManagerMock->expects($saveFlagInvokeMatcher) - ->method('saveFlag') - ->with(BaseUrlConfigPlugin::OLD_BASE_URL_FLAG_CODE, $oldUrl); - - $this->configWriterMock->expects($saveConfigInvokeMatcher)->method('save') - ->with( - BaseUrlConfigPlugin::UPDATE_CRON_STRING_PATH, - '0 * * * *' - ); + ->willReturn($configValueData['isValueChanged']); + $this->configValueMock + ->method('getPath') + ->willReturn($configValueData['path']); + $this->configValueMock + ->method('getScope') + ->willReturn($configValueData['scope']); + $this->subscriptionUpdateHandlerMock + ->expects($this->never()) + ->method('processUrlUpdate'); $this->assertEquals( $this->configValueMock, @@ -127,64 +90,58 @@ public function testPluginForAfterSave( /** * @return array */ - public function pluginDataProvider() + public function afterSavePluginIsNotApplicableDataProvider() { return [ - 'setup_subscription_update_cron_job' => [ - 'testData' => [ - 'isValueChanged' => true, - 'subscriptionStatus' => SubscriptionStatusProvider::ENABLED, - 'path' => Store::XML_PATH_SECURE_BASE_URL - ], - 'saveConfigInvokeMatcher' => $this->once(), - 'oldValueInvokeMatcher' => $this->once(), - 'saveFlagInvokeMatcher' => $this->once(), - 'configValueGetPathMatcher' => $this->once(), - ], - 'base_url_not_changed' => [ - 'testData' => [ + 'Value has not been changed' => [ + 'Config Value Data' => [ 'isValueChanged' => false, - 'subscriptionStatus' => SubscriptionStatusProvider::ENABLED, - 'path' => Store::XML_PATH_SECURE_BASE_URL + 'path' => Store::XML_PATH_SECURE_BASE_URL, + 'scope' => ScopeConfigInterface::SCOPE_TYPE_DEFAULT ], - 'saveConfigInvokeMatcher' => $this->never(), - 'oldValueInvokeMatcher' => $this->never(), - 'saveFlagInvokeMatcher' => $this->never(), - 'configValueGetPathMatcher' => $this->never(), ], - 'analytics_disabled' => [ - 'testData' => [ + 'Unsecure URL has been changed' => [ + 'Config Value Data' => [ 'isValueChanged' => true, - 'subscriptionStatus' => SubscriptionStatusProvider::DISABLED, - 'path' => Store::XML_PATH_SECURE_BASE_URL + 'path' => Store::XML_PATH_UNSECURE_BASE_URL, + 'scope' => ScopeConfigInterface::SCOPE_TYPE_DEFAULT ], - 'saveConfigInvokeMatcher' => $this->never(), - 'oldValueInvokeMatcher' => $this->never(), - 'saveFlagInvokeMatcher' => $this->never(), - 'configValueGetPathMatcher' => $this->once(), ], - 'analytics_pending' => [ - 'testData' => [ + 'Secure URL has been changed not in the Default scope' => [ + 'Config Value Data' => [ 'isValueChanged' => true, - 'subscriptionStatus' => SubscriptionStatusProvider::PENDING, - 'path' => Store::XML_PATH_SECURE_BASE_URL + 'path' => Store::XML_PATH_SECURE_BASE_URL, + 'scope' => ScopeInterface::SCOPE_STORES ], - 'saveConfigInvokeMatcher' => $this->never(), - 'oldValueInvokeMatcher' => $this->never(), - 'saveFlagInvokeMatcher' => $this->never(), - 'configValueGetPathMatcher' => $this->once(), ], - 'unsecure_url_changed' => [ - 'testData' => [ - 'isValueChanged' => true, - 'subscriptionStatus' => SubscriptionStatusProvider::PENDING, - 'path' => Store::XML_PATH_UNSECURE_BASE_URL - ], - 'saveConfigInvokeMatcher' => $this->never(), - 'oldValueInvokeMatcher' => $this->never(), - 'saveFlagInvokeMatcher' => $this->never(), - 'configValueGetPathMatcher' => $this->once(), - ] ]; } + + /** + * @return void + */ + public function testAfterSavePluginIsApplicable() + { + $this->configValueMock + ->method('isValueChanged') + ->willReturn(true); + $this->configValueMock + ->method('getPath') + ->willReturn(Store::XML_PATH_SECURE_BASE_URL); + $this->configValueMock + ->method('getScope') + ->willReturn(ScopeConfigInterface::SCOPE_TYPE_DEFAULT); + $this->configValueMock + ->method('getOldValue') + ->willReturn('http://store.com'); + $this->subscriptionUpdateHandlerMock + ->expects($this->once()) + ->method('processUrlUpdate') + ->with('http://store.com'); + + $this->assertEquals( + $this->configValueMock, + $this->plugin->afterAfterSave($this->configValueMock, $this->configValueMock) + ); + } } diff --git a/app/code/Magento/Analytics/Test/Unit/Model/ReportUrlProviderTest.php b/app/code/Magento/Analytics/Test/Unit/Model/ReportUrlProviderTest.php index 1be0524d72b7f..ee507d88c68db 100644 --- a/app/code/Magento/Analytics/Test/Unit/Model/ReportUrlProviderTest.php +++ b/app/code/Magento/Analytics/Test/Unit/Model/ReportUrlProviderTest.php @@ -6,9 +6,12 @@ namespace Magento\Analytics\Test\Unit\Model; use Magento\Analytics\Model\AnalyticsToken; +use Magento\Analytics\Model\Config\Backend\Baseurl\SubscriptionUpdateHandler; use Magento\Analytics\Model\Connector\OTPRequest; +use Magento\Analytics\Model\Exception\State\SubscriptionUpdateException; use Magento\Analytics\Model\ReportUrlProvider; use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Framework\FlagManager; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; /** @@ -31,6 +34,11 @@ class ReportUrlProviderTest extends \PHPUnit_Framework_TestCase */ private $otpRequestMock; + /** + * @var FlagManager|\PHPUnit_Framework_MockObject_MockObject + */ + private $flagManagerMock; + /** * @var ObjectManagerHelper */ @@ -63,6 +71,10 @@ protected function setUp() ->disableOriginalConstructor() ->getMock(); + $this->flagManagerMock = $this->getMockBuilder(FlagManager::class) + ->disableOriginalConstructor() + ->getMock(); + $this->objectManagerHelper = new ObjectManagerHelper($this); $this->reportUrlProvider = $this->objectManagerHelper->getObject( @@ -71,6 +83,7 @@ protected function setUp() 'config' => $this->configMock, 'analyticsToken' => $this->analyticsTokenMock, 'otpRequest' => $this->otpRequestMock, + 'flagManager' => $this->flagManagerMock, 'urlReportConfigPath' => $this->urlReportConfigPath, ] ); @@ -119,4 +132,22 @@ public function getUrlDataProvider() 'TokenExistAndOtpValid' => [true, '249e6b658877bde2a77bc4ab'], ]; } + + /** + * @return void + */ + public function testGetUrlWhenSubscriptionUpdateRunning() + { + $this->flagManagerMock + ->expects($this->once()) + ->method('getFlagData') + ->with(SubscriptionUpdateHandler::PREVIOUS_BASE_URL_FLAG_CODE) + ->willReturn('http://store.com'); + $this->setExpectedException( + SubscriptionUpdateException::class, + 'Your Base URL has been changed and your reports are being updated. ' + . 'Advanced Reporting will be available once this change has been processed. Please try again later.' + ); + $this->reportUrlProvider->getUrl(); + } } diff --git a/app/code/Magento/Analytics/Test/Unit/Model/SubscriptionStatusProviderTest.php b/app/code/Magento/Analytics/Test/Unit/Model/SubscriptionStatusProviderTest.php index 90707b2db7e1a..2e52a13f90bbf 100644 --- a/app/code/Magento/Analytics/Test/Unit/Model/SubscriptionStatusProviderTest.php +++ b/app/code/Magento/Analytics/Test/Unit/Model/SubscriptionStatusProviderTest.php @@ -6,6 +6,7 @@ namespace Magento\Analytics\Test\Unit\Model; use Magento\Analytics\Model\AnalyticsToken; +use Magento\Analytics\Model\Config\Backend\Baseurl\SubscriptionUpdateHandler; use Magento\Analytics\Model\Config\Backend\Enabled\SubscriptionHandler; use Magento\Analytics\Model\SubscriptionStatusProvider; use Magento\Framework\App\Config\ScopeConfigInterface; @@ -70,7 +71,11 @@ protected function setUp() ); } - public function testGetStatusShouldBeFailed() + /** + * @param array $flagManagerData + * @dataProvider getStatusShouldBeFailedDataProvider + */ + public function testGetStatusShouldBeFailed(array $flagManagerData) { $this->analyticsTokenMock->expects($this->once()) ->method('isTokenExist') @@ -80,26 +85,86 @@ public function testGetStatusShouldBeFailed() ->with('analytics/subscription/enabled') ->willReturn(true); - $this->expectFlagCounterReturn(null); + $this->expectFlagManagerReturn($flagManagerData); $this->assertEquals(SubscriptionStatusProvider::FAILED, $this->statusProvider->getStatus()); } - public function testGetStatusShouldBePending() + /** + * @return array + */ + public function getStatusShouldBeFailedDataProvider() + { + return [ + 'Subscription update doesn\'t active' => [ + 'Flag Manager data mapping' => [ + [SubscriptionUpdateHandler::PREVIOUS_BASE_URL_FLAG_CODE, null], + [SubscriptionHandler::ATTEMPTS_REVERSE_COUNTER_FLAG_CODE, null] + ], + ], + 'Subscription update is active' => [ + 'Flag Manager data mapping' => [ + [SubscriptionUpdateHandler::PREVIOUS_BASE_URL_FLAG_CODE, 'http://store.com'], + [SubscriptionHandler::ATTEMPTS_REVERSE_COUNTER_FLAG_CODE, null] + ], + ], + ]; + } + + /** + * @param array $flagManagerData + * @param bool $isTokenExist + * @dataProvider getStatusShouldBePendingDataProvider + */ + public function testGetStatusShouldBePending(array $flagManagerData, bool $isTokenExist) { $this->analyticsTokenMock->expects($this->once()) ->method('isTokenExist') - ->willReturn(false); + ->willReturn($isTokenExist); $this->scopeConfigMock->expects($this->once()) ->method('getValue') ->with('analytics/subscription/enabled') ->willReturn(true); - $this->expectFlagCounterReturn(45); + $this->expectFlagManagerReturn($flagManagerData); $this->assertEquals(SubscriptionStatusProvider::PENDING, $this->statusProvider->getStatus()); } + /** + * @return array + */ + public function getStatusShouldBePendingDataProvider() + { + return [ + 'Subscription update doesn\'t active and the token does not exist' => [ + 'Flag Manager data mapping' => [ + [SubscriptionUpdateHandler::PREVIOUS_BASE_URL_FLAG_CODE, null], + [SubscriptionHandler::ATTEMPTS_REVERSE_COUNTER_FLAG_CODE, 45] + ], + 'isTokenExist' => false, + ], + 'Subscription update is active and the token does not exist' => [ + 'Flag Manager data mapping' => [ + [SubscriptionUpdateHandler::PREVIOUS_BASE_URL_FLAG_CODE, 'http://store.com'], + [SubscriptionHandler::ATTEMPTS_REVERSE_COUNTER_FLAG_CODE, 45] + ], + 'isTokenExist' => false, + ], + 'Subscription update is active and token exist' => [ + 'Flag Manager data mapping' => [ + [SubscriptionUpdateHandler::PREVIOUS_BASE_URL_FLAG_CODE, 'http://store.com'], + [SubscriptionHandler::ATTEMPTS_REVERSE_COUNTER_FLAG_CODE, null] + ], + 'isTokenExist' => true, + ], + ]; + } + public function testGetStatusShouldBeEnabled() { + $this->flagManagerMock + ->method('getFlagData') + ->with(SubscriptionUpdateHandler::PREVIOUS_BASE_URL_FLAG_CODE) + ->willReturn(null); $this->analyticsTokenMock->expects($this->once()) ->method('isTokenExist') ->willReturn(true); @@ -120,15 +185,12 @@ public function testGetStatusShouldBeDisabled() } /** - * @param null|int $value + * @param array $mapping */ - private function expectFlagCounterReturn($value) + private function expectFlagManagerReturn(array $mapping) { - $this->flagManagerMock->expects($this->once())->method('getFlagData') - ->willReturnMap( - [ - [SubscriptionHandler::ATTEMPTS_REVERSE_COUNTER_FLAG_CODE, $value], - ] - ); + $this->flagManagerMock + ->method('getFlagData') + ->willReturnMap($mapping); } } diff --git a/app/code/Magento/Analytics/composer.json b/app/code/Magento/Analytics/composer.json index edc3443e487b6..bdea53c445a34 100644 --- a/app/code/Magento/Analytics/composer.json +++ b/app/code/Magento/Analytics/composer.json @@ -3,14 +3,14 @@ "description": "N/A", "require": { "php": "7.0.2|7.0.4|~7.0.6|~7.1.0", - "magento/module-backend": "100.2.*", - "magento/module-config": "100.2.*", - "magento/module-integration": "100.2.*", - "magento/module-store": "100.2.*", - "magento/framework": "100.2.*" + "magento/module-backend": "100.3.*", + "magento/module-config": "100.3.*", + "magento/module-integration": "100.3.*", + "magento/module-store": "100.3.*", + "magento/framework": "100.3.*" }, "type": "magento2-module", - "version": "100.2.0-dev", + "version": "100.3.0-dev", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Analytics/etc/di.xml b/app/code/Magento/Analytics/etc/di.xml index 4b4cef4c1a80e..09efd7c36ad83 100644 --- a/app/code/Magento/Analytics/etc/di.xml +++ b/app/code/Magento/Analytics/etc/di.xml @@ -181,28 +181,28 @@ - Apps and Games - Athletic/Sporting Goods - Art and Design - Auto Parts - Baby/Children’s Apparel, Gear and Toys - Beauty and Cosmetics - Books, Music and Magazines - Crafts and Stationery - Consumer Electronics - Deal Site - Fashion Apparel and Accessories - Food, Beverage and Grocery - Home Goods and Furniture - Home Improvement - Jewelry and Watches - Mass Merchant - Office Supplies - Outdoor and Camping Gear - Pet Goods - Pharma and Medical Devices - Technology B2B - Other + Apps and Games + Athletic/Sporting Goods + Art and Design + Auto Parts + Baby/Children’s Apparel, Gear and Toys + Beauty and Cosmetics + Books, Music and Magazines + Crafts and Stationery + Consumer Electronics + Deal Site + Fashion Apparel and Accessories + Food, Beverage and Grocery + Home Goods and Furniture + Home Improvement + Jewelry and Watches + Mass Merchant + Office Supplies + Outdoor and Camping Gear + Pet Goods + Pharma and Medical Devices + Technology B2B + Other diff --git a/app/code/Magento/Analytics/i18n/en_US.csv b/app/code/Magento/Analytics/i18n/en_US.csv new file mode 100644 index 0000000000000..090534923e450 --- /dev/null +++ b/app/code/Magento/Analytics/i18n/en_US.csv @@ -0,0 +1,103 @@ +"Subscription status","Subscription status" +"Sorry, there has been an error processing your request. Please try again later.","Sorry, there has been an error processing your request. Please try again later." +"Sorry, there was an error processing your registration request to Magento Analytics. Please try again later.","Sorry, there was an error processing your registration request to Magento Analytics. Please try again later." +"Error occurred during postponement notification","Error occurred during postponement notification" +"Time value has an unsupported format","Time value has an unsupported format" +"Cron settings can't be saved","Cron settings can't be saved" +"There was an error save new configuration value.","There was an error save new configuration value." +"Please select a vertical.","Please select a vertical." +"--Please Select--","--Please Select--" +"Command was not found.","Command was not found." +"Input data must be string or convertible into string.","Input data must be string or convertible into string." +"Input data must be non-empty string.","Input data must be non-empty string." +"Not valid cipher method.","Not valid cipher method." +"Encryption key can't be empty.","Encryption key can't be empty." +"Source ""%1"" is not exist","Source ""%1"" is not exist" +"These arguments can't be empty ""%1""","These arguments can't be empty ""%1""" +"Cannot find predefined integration user!","Cannot find predefined integration user!" +"File is not ready yet.","File is not ready yet." +"Your Base URL has been changed and your reports are being updated. Advanced Reporting will be available once this change has been processed. Please try again later.","Your Base URL has been changed and your reports are being updated. Advanced Reporting will be available once this change has been processed. Please try again later." +"Failed to synchronize data to the Magento Business Intelligence service. ","Failed to synchronize data to the Magento Business Intelligence service. " +"Retry Synchronization","Retry Synchronization" +TestMessage,TestMessage +"Error message","Error message" +"Apps and Games","Apps and Games" +"Athletic/Sporting Goods","Athletic/Sporting Goods" +"Art and Design","Art and Design" +"Advanced Reporting","Advanced Reporting" +"Gain new insights and take command of your business' performance, using our dynamic product, order, and customer reports tailored to your customer data.","Gain new insights and take command of your business' performance, using our dynamic product, order, and customer reports tailored to your customer data." +"View details","View details" +"Go to Advanced Reporting","Go to Advanced Reporting" +"An error occurred while subscription process.","An error occurred while subscription process." +Analytics,Analytics +API,API +Configuration,Configuration +"Business Intelligence","Business Intelligence" +"BI Essentials","BI Essentials" +"This service provides a suite of dynamic reports based on your product, order and + customer data. All reports are accessed securely on a personalized dashboard dedicated to your reports - + separate from your Admin Panel.
For more information, view details or see our + terms and conditions.","This service provides a suite of dynamic reports based on your product, order and + customer data. All reports are accessed securely on a personalized dashboard dedicated to your reports - + separate from your Admin Panel.
For more information, view details or see our + terms and conditions." +"Advanced Reporting Service","Advanced Reporting Service" +Industry,Industry +"Time of day to send data","Time of day to send data" +"Get more insights from Magento Business Intelligence","Get more insights from Magento Business Intelligence" +"Magento Business Intelligence provides you with a simple and clear path to + becoming more data driven.
Learn more about BI Essentials tier.","Magento Business Intelligence provides you with a simple and clear path to + becoming more data driven.
Learn more about BI Essentials tier." +"Auto Parts","Auto Parts" +"Baby/Children’s Apparel, Gear and Toys","Baby/Children’s Apparel, Gear and Toys" +"Beauty and Cosmetics","Beauty and Cosmetics" +"Books, Music and Magazines","Books, Music and Magazines" +"Crafts and Stationery","Crafts and Stationery" +"Consumer Electronics","Consumer Electronics" +"Deal Site","Deal Site" +"Fashion Apparel and Accessories","Fashion Apparel and Accessories" +"Food, Beverage and Grocery","Food, Beverage and Grocery" +"Home Goods and Furniture","Home Goods and Furniture" +"Home Improvement","Home Improvement" +"Jewelry and Watches","Jewelry and Watches" +"Mass Merchant","Mass Merchant" +"Office Supplies","Office Supplies" +"Outdoor and Camping Gear","Outdoor and Camping Gear" +"Pet Goods","Pet Goods" +"Pharma and Medical Devices","Pharma and Medical Devices" +"Technology B2B","Technology B2B" +"Analytics Subscription","Analytics Subscription" +"powered by Magento Business Intelligence","powered by Magento Business Intelligence" +"

When you turn on Advanced + Reporting, you'll have access to a suite of dynamic reports tailored to your business. Example + of the new data and trend reports, listed by category, include:

A + personalized dashboard includes all reports - separate from your Admin Panel, yet still at your + fingertips.

We're excited to offer these valuable tools that can help your business become + more data-driven. For more information, view details or see our + terms and conditions.

+ ","

When you turn on Advanced + Reporting, you'll have access to a suite of dynamic reports tailored to your business. Example + of the new data and trend reports, listed by category, include:

A + personalized dashboard includes all reports - separate from your Admin Panel, yet still at your + fingertips.

We're excited to offer these valuable tools that can help your business become + more data-driven. For more information, view details or see our + terms and conditions.

+ " +"Are you sure you want to opt out?","Are you sure you want to opt out?" +Cancel,Cancel +"Opt out","Opt out" +"

Advanced Reporting in included, + free of charge, in your Magento software. When you opt out, we collect no product, order, and + customer data to generate our dynamic reports.

To opt in later: You can always turn on Advanced + Reporting in you Admin Panel.

","

Advanced Reporting in included, + free of charge, in your Magento software. When you opt out, we collect no product, order, and + customer data to generate our dynamic reports.

To opt in later: You can always turn on Advanced + Reporting in you Admin Panel.

" diff --git a/app/code/Magento/Authorization/composer.json b/app/code/Magento/Authorization/composer.json index a894193888100..5e80365847ce5 100644 --- a/app/code/Magento/Authorization/composer.json +++ b/app/code/Magento/Authorization/composer.json @@ -3,11 +3,11 @@ "description": "Authorization module provides access to Magento ACL functionality.", "require": { "php": "7.0.2|7.0.4|~7.0.6|~7.1.0", - "magento/module-backend": "100.2.*", - "magento/framework": "100.2.*" + "magento/module-backend": "100.3.*", + "magento/framework": "100.3.*" }, "type": "magento2-module", - "version": "100.2.0-dev", + "version": "100.3.0-dev", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Authorization/i18n/en_US.csv b/app/code/Magento/Authorization/i18n/en_US.csv index 2bb5f767fa5f9..c2d0eaa1df978 100644 --- a/app/code/Magento/Authorization/i18n/en_US.csv +++ b/app/code/Magento/Authorization/i18n/en_US.csv @@ -1,2 +1,2 @@ -"We can\'t find the role for the user you wanted.","We can\'t find the role for the user you wanted." +"We can't find the role for the user you wanted.","We can't find the role for the user you wanted." "Something went wrong while compiling a list of allowed resources. You can find out more in the exceptions log.","Something went wrong while compiling a list of allowed resources. You can find out more in the exceptions log." diff --git a/app/code/Magento/Authorizenet/composer.json b/app/code/Magento/Authorizenet/composer.json index 2abfebc3c1cb7..be581500c4020 100644 --- a/app/code/Magento/Authorizenet/composer.json +++ b/app/code/Magento/Authorizenet/composer.json @@ -3,20 +3,20 @@ "description": "N/A", "require": { "php": "7.0.2|7.0.4|~7.0.6|~7.1.0", - "magento/module-sales": "100.2.*", - "magento/module-store": "100.2.*", - "magento/module-quote": "100.2.*", - "magento/module-checkout": "100.2.*", - "magento/module-backend": "100.2.*", - "magento/module-payment": "100.2.*", - "magento/module-catalog": "101.1.*", - "magento/framework": "100.2.*" + "magento/module-sales": "100.3.*", + "magento/module-store": "100.3.*", + "magento/module-quote": "100.3.*", + "magento/module-checkout": "100.3.*", + "magento/module-backend": "100.3.*", + "magento/module-payment": "100.3.*", + "magento/module-catalog": "101.2.*", + "magento/framework": "100.3.*" }, "suggest": { - "magento/module-config": "100.2.*" + "magento/module-config": "100.3.*" }, "type": "magento2-module", - "version": "100.2.0-dev", + "version": "100.3.0-dev", "license": [ "proprietary" ], diff --git a/app/code/Magento/Authorizenet/i18n/en_US.csv b/app/code/Magento/Authorizenet/i18n/en_US.csv index 45025304c4e44..bb59afffff2c6 100644 --- a/app/code/Magento/Authorizenet/i18n/en_US.csv +++ b/app/code/Magento/Authorizenet/i18n/en_US.csv @@ -1,7 +1,7 @@ "You created the order.","You created the order." "Order saving error: %1","Order saving error: %1" "Please choose a payment method.","Please choose a payment method." -"We can\'t process your order right now. Please try again later.","We can\'t process your order right now. Please try again later." +"We can't process your order right now. Please try again later.","We can't process your order right now. Please try again later." "An error occurred on the server. Please try to place the order again.","An error occurred on the server. Please try to place the order again." "Credit Card: xxxx-%1","Credit Card: xxxx-%1" "amount %1","amount %1" @@ -22,16 +22,18 @@ void,void "Invalid amount for refund.","Invalid amount for refund." "Payment refunding error.","Payment refunding error." "The transaction was declined because the response hash validation failed.","The transaction was declined because the response hash validation failed." -"This payment didn\'t work out because we can\'t find this order.","This payment didn\'t work out because we can\'t find this order." +"This payment didn't work out because we can't find this order.","This payment didn't work out because we can't find this order." "There was a payment authorization error.","There was a payment authorization error." "Please enter a transaction ID to authorize this payment.","Please enter a transaction ID to authorize this payment." -"Something went wrong: the paid amount doesn\'t match the order amount. Please correct this and try again.","Something went wrong: the paid amount doesn\'t match the order amount. Please correct this and try again." +"Something went wrong: the paid amount doesn't match the order amount. Please correct this and try again.","Something went wrong: the paid amount doesn't match the order amount. Please correct this and try again." "Transaction %1 has been approved. Amount %2. Transaction status is ""%3""","Transaction %1 has been approved. Amount %2. Transaction status is ""%3""" "Transaction %1 has been voided/declined. Transaction status is ""%2"". Amount %3.","Transaction %1 has been voided/declined. Transaction status is ""%2"". Amount %3." "Authorize Only","Authorize Only" "Authorize and Capture","Authorize and Capture" "Unable to get transaction details. Try again later.","Unable to get transaction details. Try again later." +"Electronic payments save the trees.","Electronic payments save the trees." "Credit Card Type","Credit Card Type" +"Please Select","Please Select" "Credit Card Number","Credit Card Number" "Expiration Date","Expiration Date" "Card Verification Number","Card Verification Number" @@ -42,6 +44,7 @@ void,void "CAVV Response","CAVV Response" "Fraud Filters","Fraud Filters" "Place Order","Place Order" +"Sorry, but something went wrong. Please contact the seller.","Sorry, but something went wrong. Please contact the seller." "Authorize.net Direct Post","Authorize.net Direct Post" Enabled,Enabled "Payment Action","Payment Action" @@ -64,4 +67,3 @@ Debug,Debug "Minimum Order Total","Minimum Order Total" "Maximum Order Total","Maximum Order Total" "Sort Order","Sort Order" -"Sorry, but something went wrong. Please contact the seller.","Sorry, but something went wrong. Please contact the seller." diff --git a/app/code/Magento/Backend/Test/Unit/Controller/Adminhtml/Cache/CleanMediaTest.php b/app/code/Magento/Backend/Test/Unit/Controller/Adminhtml/Cache/CleanMediaTest.php index ecc47b229b2e0..5ec23d9792f19 100644 --- a/app/code/Magento/Backend/Test/Unit/Controller/Adminhtml/Cache/CleanMediaTest.php +++ b/app/code/Magento/Backend/Test/Unit/Controller/Adminhtml/Cache/CleanMediaTest.php @@ -26,11 +26,26 @@ public function testExecute() ['setIsUrlNotice'], $helper->getConstructArguments(\Magento\Backend\Model\Session::class) ); + + $exceptionMessageFactory = $this->getMockBuilder( + \Magento\Framework\Message\ExceptionMessageLookupFactory::class + ) + ->disableOriginalConstructor() + ->setMethods( + ['getMessageGenerator'] + ) + ->getMock(); + + $messageManagerParams = $helper->getConstructArguments(\Magento\Framework\Message\Manager::class); + + $messageManagerParams['exceptionMessageFactory'] = $exceptionMessageFactory; + $messageManager = $this->getMock( \Magento\Framework\Message\Manager::class, ['addSuccess'], - $helper->getConstructArguments(\Magento\Framework\Message\Manager::class) + $messageManagerParams ); + $context = $this->getMock( \Magento\Backend\App\Action\Context::class, ['getRequest', 'getResponse', 'getMessageManager', 'getSession', 'getResultFactory'], diff --git a/app/code/Magento/Backend/composer.json b/app/code/Magento/Backend/composer.json index d3c94c1e286e0..0b141226f7574 100644 --- a/app/code/Magento/Backend/composer.json +++ b/app/code/Magento/Backend/composer.json @@ -3,28 +3,28 @@ "description": "N/A", "require": { "php": "7.0.2|7.0.4|~7.0.6|~7.1.0", - "magento/module-store": "100.2.*", - "magento/module-directory": "100.2.*", - "magento/module-developer": "100.2.*", - "magento/module-eav": "100.2.*", - "magento/module-reports": "100.2.*", - "magento/module-sales": "100.2.*", - "magento/module-quote": "100.2.*", - "magento/module-catalog": "101.1.*", - "magento/module-user": "100.2.*", - "magento/module-security": "100.2.*", - "magento/module-backup": "100.2.*", - "magento/module-customer": "100.2.*", - "magento/module-translation": "100.2.*", - "magento/module-require-js": "100.2.*", - "magento/module-config": "100.2.*", - "magento/framework": "100.2.*" + "magento/module-store": "100.3.*", + "magento/module-directory": "100.3.*", + "magento/module-developer": "100.3.*", + "magento/module-eav": "100.3.*", + "magento/module-reports": "100.3.*", + "magento/module-sales": "100.3.*", + "magento/module-quote": "100.3.*", + "magento/module-catalog": "101.2.*", + "magento/module-user": "100.3.*", + "magento/module-security": "100.3.*", + "magento/module-backup": "100.3.*", + "magento/module-customer": "100.3.*", + "magento/module-translation": "100.3.*", + "magento/module-require-js": "100.3.*", + "magento/module-config": "100.3.*", + "magento/framework": "100.3.*" }, "suggest": { - "magento/module-theme": "100.2.*" + "magento/module-theme": "100.3.*" }, "type": "magento2-module", - "version": "100.2.0-dev", + "version": "100.3.0-dev", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Backend/i18n/en_US.csv b/app/code/Magento/Backend/i18n/en_US.csv index 17df68ab5eb9f..2730d4d92835b 100644 --- a/app/code/Magento/Backend/i18n/en_US.csv +++ b/app/code/Magento/Backend/i18n/en_US.csv @@ -98,10 +98,10 @@ No,No "Store Information","Store Information" "Web Site","Web Site" Name,Name +Code,Code "Root Category","Root Category" "Default Store View","Default Store View" "Store View Information","Store View Information" -Code,Code Status,Status Disabled,Disabled Enabled,Enabled @@ -128,7 +128,7 @@ To,To "[ deleted ]","[ deleted ]" "Select All","Select All" " [deleted]"," [deleted]" -"We couldn\'t find any records.","We couldn\'t find any records." +"We couldn't find any records.","We couldn't find any records." "Add New","Add New" "Invalid export type supplied for grid export block","Invalid export type supplied for grid export block" Export,Export @@ -139,7 +139,7 @@ Submit,Submit "Please correct the tab configuration and try again. Tab Id should be not empty","Please correct the tab configuration and try again. Tab Id should be not empty" "Please correct the tab configuration and try again.","Please correct the tab configuration and try again." "You have logged out.","You have logged out." -"Specified cache type(s) don\'t exist: %1","Specified cache type(s) don\'t exist: %1" +"Specified cache type(s) don't exist: %1","Specified cache type(s) don't exist: %1" "The image cache was cleaned.","The image cache was cleaned." "An error occurred while clearing the image cache.","An error occurred while clearing the image cache." "The JavaScript/CSS cache has been cleaned.","The JavaScript/CSS cache has been cleaned." @@ -148,6 +148,7 @@ Submit,Submit "You flushed the cache storage.","You flushed the cache storage." "The Magento cache storage has been flushed.","The Magento cache storage has been flushed." "Cache Management","Cache Management" +"You can't change status of cache type(s) in production mode","You can't change status of cache type(s) in production mode" "%1 cache type(s) disabled.","%1 cache type(s) disabled." "An error occurred while disabling cache.","An error occurred while disabling cache." "%1 cache type(s) enabled.","%1 cache type(s) enabled." @@ -156,7 +157,7 @@ Submit,Submit "An error occurred while refreshing cache.","An error occurred while refreshing cache." Dashboard,Dashboard "We updated lifetime statistic.","We updated lifetime statistic." -"We can\'t refresh lifetime statistics.","We can\'t refresh lifetime statistics." +"We can't refresh lifetime statistics.","We can't refresh lifetime statistics." "invalid request","invalid request" "see error log for details","see error log for details" "Service unavailable: %1","Service unavailable: %1" @@ -175,7 +176,7 @@ Error,Error System,System "Manage Stores","Manage Stores" "The database was backed up.","The database was backed up." -"We can\'t create a backup right now. Please try again later.","We can\'t create a backup right now. Please try again later." +"We can't create a backup right now. Please try again later.","We can't create a backup right now. Please try again later." "Deleting a %1 will not delete the information associated with the %1 (e.g. categories, products, etc.), but the %1 will not be able to be restored. It is suggested that you create a database backup before deleting the %1.","Deleting a %1 will not delete the information associated with the %1 (e.g. categories, products, etc.), but the %1 will not be able to be restored. It is suggested that you create a database backup before deleting the %1." "Something went wrong. Please try again.","Something went wrong. Please try again." "This store cannot be deleted.","This store cannot be deleted." @@ -194,9 +195,12 @@ System,System "Store view doesn't exist","Store view doesn't exist" "Before modifying the store view code please make sure it is not used in index.php.","Before modifying the store view code please make sure it is not used in index.php." "New ","New " +"All Stores","All Stores" "You saved the website.","You saved the website." -"You saved the store.","You saved the store." +"The default store cannot be disabled","The default store cannot be disabled" "You saved the store view.","You saved the store view." +"An inactive store view cannot be saved as default store view","An inactive store view cannot be saved as default store view" +"You saved the store.","You saved the store." "Something went wrong while saving. Please review the error log.","Something went wrong while saving. Please review the error log." "Last 24 Hours","Last 24 Hours" "Last 7 Days","Last 7 Days" @@ -232,7 +236,7 @@ password,password "Reload Data","Reload Data" "Browse Files...","Browse Files..." Magento,Magento -"Copyright© %1 Magento Commerce Inc. All rights reserved.","Copyright© %1 Magento Commerce Inc. All rights reserved." +"Copyright © %1 Magento Commerce Inc. All rights reserved.","Copyright © %1 Magento Commerce Inc. All rights reserved." "ver. %1","ver. %1" "Magento Admin Panel","Magento Admin Panel" "Account Setting","Account Setting" @@ -253,7 +257,7 @@ Minute,Minute "Report an Issue","Report an Issue" "Store View:","Store View:" "Stores Configuration","Stores Configuration" -"Please confirm scope switching. All data that hasn\'t been saved will be lost.","Please confirm scope switching. All data that hasn\'t been saved will be lost." +"Please confirm scope switching. All data that hasn't been saved will be lost.","Please confirm scope switching. All data that hasn't been saved will be lost." "Additional Cache Management","Additional Cache Management" "Flush Catalog Images Cache","Flush Catalog Images Cache" "Pregenerated product images files","Pregenerated product images files" @@ -286,7 +290,7 @@ Actions,Actions "The information in this tab has been changed.","The information in this tab has been changed." Loading...,Loading... "We could not detect a size.","We could not detect a size." -"We don\'t recognize or support this file extension type.","We don\'t recognize or support this file extension type." +"We don't recognize or support this file extension type.","We don't recognize or support this file extension type." "Allow everything","Allow everything" "Magento Admin","Magento Admin" "Global Search","Global Search" @@ -298,7 +302,6 @@ Elements,Elements Design,Design Schedule,Schedule Settings,Settings -"All Stores","All Stores" Attributes,Attributes "Other Settings","Other Settings" "Data Transfer","Data Transfer" @@ -441,19 +444,17 @@ Tags,Tags "

404 Error

Page not found.

","

404 Error

Page not found.

" "Community Edition","Community Edition" "Default Theme","Default Theme" -"Applied Theme","Applied Theme" "If no value is specified, the system default is used. The system default may be modified by third party extensions.","If no value is specified, the system default is used. The system default may be modified by third party extensions." +"Applied Theme","Applied Theme" "Design Rule","Design Rule" "User Agent Rules","User Agent Rules" -Magento_Ui/js/dynamic-rows/record,Magento_Ui/js/dynamic-rows/record Pagination,Pagination -"Pagination Frame","Pagination Frame" "How many links to display at once.","How many links to display at once." -"Pagination Frame Skip","Pagination Frame Skip" +"Pagination Frame","Pagination Frame" "If current frame position does not cover utmost pages, it renders the link to current position plus/minus this value.","If current frame position does not cover utmost pages, it renders the link to current position plus/minus this value." -"Anchor Text for Previous","Anchor Text for Previous" +"Pagination Frame Skip","Pagination Frame Skip" "Alternative text for the previous pages link in the pagination menu. If empty, the default arrow image is used.","Alternative text for the previous pages link in the pagination menu. If empty, the default arrow image is used." -"Anchor Text for Next","Anchor Text for Next" +"Anchor Text for Previous","Anchor Text for Previous" "Alternative text for the next pages link in the pagination menu. If empty, default arrow image is used.","Alternative text for the next pages link in the pagination menu. If empty, default arrow image is used." +"Anchor Text for Next","Anchor Text for Next" "Theme Name","Theme Name" -"Deployment config file %1 is not writable.","Deployment config file %1 is not writable." diff --git a/app/code/Magento/Backup/composer.json b/app/code/Magento/Backup/composer.json index cc1b13f773480..dc3914a2185a2 100644 --- a/app/code/Magento/Backup/composer.json +++ b/app/code/Magento/Backup/composer.json @@ -3,13 +3,13 @@ "description": "N/A", "require": { "php": "7.0.2|7.0.4|~7.0.6|~7.1.0", - "magento/module-store": "100.2.*", - "magento/module-backend": "100.2.*", - "magento/module-cron": "100.2.*", - "magento/framework": "100.2.*" + "magento/module-store": "100.3.*", + "magento/module-backend": "100.3.*", + "magento/module-cron": "100.3.*", + "magento/framework": "100.3.*" }, "type": "magento2-module", - "version": "100.2.0-dev", + "version": "100.3.0-dev", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Backup/i18n/en_US.csv b/app/code/Magento/Backup/i18n/en_US.csv index 9aee00c33c393..b8438172e3b6a 100644 --- a/app/code/Magento/Backup/i18n/en_US.csv +++ b/app/code/Magento/Backup/i18n/en_US.csv @@ -7,20 +7,20 @@ "Something went wrong while putting your store into maintenance mode.","Something went wrong while putting your store into maintenance mode." "You need more free space to create a backup.","You need more free space to create a backup." "You need more permissions to create a backup.","You need more permissions to create a backup." -"We can\'t create the backup right now.","We can\'t create the backup right now." +"We can't create the backup right now.","We can't create the backup right now." Backups,Backups System,System Tools,Tools Backup,Backup -"We can\'t delete one or more backups.","We can\'t delete one or more backups." +"We can't delete one or more backups.","We can't delete one or more backups." failed,failed successful,successful "You deleted the selected backup(s).","You deleted the selected backup(s)." -"Can\'t load snapshot archive","Can\'t load snapshot archive" +"Can't load snapshot archive","Can't load snapshot archive" "Please correct the password.","Please correct the password." "To complete the rollback, please deselect ""Put store into maintenance mode"" or update your permissions.","To complete the rollback, please deselect ""Put store into maintenance mode"" or update your permissions." -"We can\'t find the backup file.","We can\'t find the backup file." -"We can\'t connect to the FTP right now.","We can\'t connect to the FTP right now." +"We can't find the backup file.","We can't find the backup file." +"We can't connect to the FTP right now.","We can't connect to the FTP right now." "Failed to validate FTP.","Failed to validate FTP." "You need more permissions to perform a rollback.","You need more permissions to perform a rollback." "Failed to rollback.","Failed to rollback." @@ -38,7 +38,7 @@ Database,Database "Sorry, but we cannot read from or write to backup file ""%1"".","Sorry, but we cannot read from or write to backup file ""%1""." "The backup file handler was unspecified.","The backup file handler was unspecified." "Something went wrong while writing to the backup file ""%1"".","Something went wrong while writing to the backup file ""%1""." -"We can\'t save the Cron expression.","We can\'t save the Cron expression." +"We can't save the Cron expression.","We can't save the Cron expression." "You will lose any data created since the backup was made, including admin users, customers and orders.","You will lose any data created since the backup was made, including admin users, customers and orders." "Are you sure you want to continue?","Are you sure you want to continue?" "This may take a few moments.","This may take a few moments." diff --git a/app/code/Magento/Braintree/composer.json b/app/code/Magento/Braintree/composer.json index 67f80ff8dd79a..3e2c9e9c005e6 100644 --- a/app/code/Magento/Braintree/composer.json +++ b/app/code/Magento/Braintree/composer.json @@ -3,28 +3,28 @@ "description": "N/A", "require": { "php": "7.0.2|7.0.4|~7.0.6|~7.1.0", - "magento/framework": "100.2.*", + "magento/framework": "100.3.*", "magento/magento-composer-installer": "*", - "magento/module-config": "100.2.*", - "magento/module-directory": "100.2.*", - "magento/module-payment": "100.2.*", - "magento/module-checkout": "100.2.*", - "magento/module-sales": "100.2.*", - "magento/module-backend": "100.2.*", - "magento/module-vault": "100.2.*", - "magento/module-customer": "100.2.*", - "magento/module-catalog": "101.1.*", - "magento/module-quote": "100.2.*", - "magento/module-paypal": "100.2.*", - "magento/module-ui": "100.2.*", + "magento/module-config": "100.3.*", + "magento/module-directory": "100.3.*", + "magento/module-payment": "100.3.*", + "magento/module-checkout": "100.3.*", + "magento/module-sales": "100.3.*", + "magento/module-backend": "100.3.*", + "magento/module-vault": "100.3.*", + "magento/module-customer": "100.3.*", + "magento/module-catalog": "101.2.*", + "magento/module-quote": "100.3.*", + "magento/module-paypal": "100.3.*", + "magento/module-ui": "100.3.*", "braintree/braintree_php": "3.22.0" }, "suggest": { - "magento/module-checkout-agreements": "100.2.*", - "magento/module-theme": "100.2.*" + "magento/module-checkout-agreements": "100.3.*", + "magento/module-theme": "100.3.*" }, "type": "magento2-module", - "version": "100.2.0-dev", + "version": "100.3.0-dev", "license": [ "proprietary" ], diff --git a/app/code/Magento/Braintree/i18n/en_US.csv b/app/code/Magento/Braintree/i18n/en_US.csv index f5e2d36e1e9bb..116f459a1c1c8 100644 --- a/app/code/Magento/Braintree/i18n/en_US.csv +++ b/app/code/Magento/Braintree/i18n/en_US.csv @@ -1,120 +1,98 @@ +cc_type,"Credit Card Type" +cc_number,"Credit Card Number" +avsPostalCodeResponseCode,"AVS Postal Code Response Code" +avsStreetAddressResponseCode,"AVS Street Address Response Code" +cvvResponseCode,"CVV Response Code" +processorAuthorizationCode,"Processor Authorization Code" +processorResponseCode,"Processor Response Code" +processorResponseText,"Processor Response Text" +braintree,Braintree +liabilityShifted,"Liability Shifted" +liabilityShiftPossible,"Liability Shift Possible" +riskDataId,"Risk ID" +riskDataDecision,"Risk Decision" +paymentId,"Payment Id" +payerEmail,"Payer Email" +sale,Sale +credit,Credit +authorization_expired,"Authorization expired" +authorizing,Authorizing +authorized,Authorized +gateway_rejected,"Gateway rejected" +failed,Failed +processor_declined,"Processor declined" +settled,Settled +settling,Settling +submitted_for_settlement,"Submitted for settlement" +voided,Voided +unrecognized,Unrecognized +settlement_declined,"Settlement declined" +settlement_pending,"Settlement pending" +settlement_confirmed,"Settlement confirmed" +paypal_account,"Paypal account" +coinbase_account,"Coinbase account" +europe_bank_accout,"Europe bank account" +credit_card,"Credit card" +apple_pay_card,"Apple pay card" +android_pay_card,"Android pay card" Country,Country "Allowed Credit Card Types","Allowed Credit Card Types" "Add Rule","Add Rule" -Month,Month -Year,Year -"Stored Card","Stored Card" -"Credit Card Type","Credit Card Type" -"Credit Card Number","Credit Card Number" -"Credit card successfully added","Credit card successfully added" -"Something went wrong while saving the card.","Something went wrong while saving the card." -"Credit card does not exist","Credit card does not exist" -"Delete Credit Card","Delete Credit Card" -"There was error deleting the credit card","There was error deleting the credit card" -"Credit card successfully deleted","Credit card successfully deleted" -"Edit Credit Card","Edit Credit Card" -"My Credit Cards","My Credit Cards" -"New Credit Card","New Credit Card" -"There was error during saving card data","There was error during saving card data" -"We can\'t initialize checkout.","We can\'t initialize checkout." -"Please agree to all the terms and conditions before placing the order.","Please agree to all the terms and conditions before placing the order." -"We can\'t place the order.","We can\'t place the order." -"Incorrect payment method.","Incorrect payment method." -"We can\'t initialize checkout review.","We can\'t initialize checkout review." -"We can\'t update shipping method.","We can\'t update shipping method." -"The processor declined your transaction, please re-enter your payment information","The processor declined your transaction, please re-enter your payment information" -"Transaction declined by gateway: Check card details or try another card","Transaction declined by gateway: Check card details or try another card" -"Transaction declined: ","Transaction declined: " -.,. -"The processor responded with an unknown error","The processor responded with an unknown error" -"Credit card type is not allowed for your country.","Credit card type is not allowed for your country." -"Credit card type is not allowed for this payment method.","Credit card type is not allowed for this payment method." -"Selected payment type is not allowed for billing country.","Selected payment type is not allowed for billing country." -"Incomplete payment information.","Incomplete payment information." -"Please try again later","Please try again later" -"Can not find original authorization transaction for partial capture","Can not find original authorization transaction for partial capture" -"There was an error capturing the transaction: %1.","There was an error capturing the transaction: %1." -"This refund is for a partial amount but the Transaction has not settled.","This refund is for a partial amount but the Transaction has not settled." -"Please wait 24 hours before trying to issue a partial refund.","Please wait 24 hours before trying to issue a partial refund." -"There was an error refunding the transaction: %1.","There was an error refunding the transaction: %1." -"Some transactions are already settled or voided and cannot be voided.","Some transactions are already settled or voided and cannot be voided." -"Voided capture.","Voided capture." -"There was an error voiding the transaction: %1.","There was an error voiding the transaction: %1." -Invoice,Invoice -Shipment,Shipment +"Braintree Settlement Report","Braintree Settlement Report" +"Sorry, but something went wrong","Sorry, but something went wrong" +"We can't initialize checkout.","We can't initialize checkout." +"No authorization transaction to proceed capture.","No authorization transaction to proceed capture." +"Braintree error response.","Braintree error response." +"Payment method nonce can't be retrieved.","Payment method nonce can't be retrieved." +"Wrong transaction status","Wrong transaction status" Authorize,Authorize "Authorize and Capture","Authorize and Capture" "--Please Select--","--Please Select--" -"Invalid Customer ID provided","Invalid Customer ID provided" -"some error","some error" -"a,b,c","a,b,c" -"Something went wrong while processing.","Something went wrong while processing." -error,error -exception,exception -"Payment Information","Payment Information" -"Add new card","Add new card" -"Please Select","Please Select" +"Please agree to all the terms and conditions before placing the order.","Please agree to all the terms and conditions before placing the order." +"Credit Card Type","Credit Card Type" +"Credit Card Number","Credit Card Number" +"Please, enter valid Credit Card Number","Please, enter valid Credit Card Number" "Expiration Date","Expiration Date" +"Please, enter valid Expiration Date","Please, enter valid Expiration Date" "Card Verification Number","Card Verification Number" -"Save this card for future use","Save this card for future use" -or,or -"Please confirm that you want to delete this credit card","Please confirm that you want to delete this credit card" -"Cardholder Name","Cardholder Name" +"Please, enter valid Card Verification Number","Please, enter valid Card Verification Number" +ending,ending +expires,expires +"Are you sure you want to delete this PayPal account","Are you sure you want to delete this PayPal account" +"PayPal Account","PayPal Account" +"PayPal Logo","PayPal Logo" +Actions,Actions Delete,Delete -Back,Back -"* Required Fields","* Required Fields" -"Credit Card","Credit Card" -CVV,CVV -"Card Verification Number Visual Reference","Card Verification Number Visual Reference" +"Credit Card Information","Credit Card Information" "What is this?","What is this?" -"Make Default","Make Default" -"Billing Address","Billing Address" -"First Name","First Name" -"Last Name","Last Name" -Company,Company -Address,Address -City,City -State/Province,State/Province -"Please select region, state or province","Please select region, state or province" -"Zip/Postal Code","Zip/Postal Code" -Submit,Submit -"Add Credit Card","Add Credit Card" -Type,Type -"Card Number","Card Number" -"Is Default","Is Default" -Actions,Actions -Yes,Yes -No,No -Edit,Edit +"Save for later use.","Save for later use." "Place Order","Place Order" -"Credit Card Information","Credit Card Information" -"An error occured with payment processing.","An error occured with payment processing." -"Can not initialize PayPal (Braintree)","Can not initialize PayPal (Braintree)" +"This payment is not available","This payment is not available" +MM,MM +YY,YY "Please try again with another form of payment.","Please try again with another form of payment." +"Sorry, but something went wrong.","Sorry, but something went wrong." +"Payment ","Payment " Braintree,Braintree - ,  +"Accept credit/debit cards and PayPal in your Magento store.
No setup or monthly fees and your customers never leave your store to complete the purchase.","Accept credit/debit cards and PayPal in your Magento store.
No setup or monthly fees and your customers never leave your store to complete the purchase." "Enable this Solution","Enable this Solution" "Enable PayPal through Braintree","Enable PayPal through Braintree" +"Vault Enabled","Vault Enabled" "Basic Braintree Settings","Basic Braintree Settings" Title,Title Environment,Environment "Payment Action","Payment Action" -"Merchant Account ID","Merchant Account ID" "Merchant ID","Merchant ID" "Public Key","Public Key" "Private Key","Private Key" "Advanced Braintree Settings","Advanced Braintree Settings" +"Vault Title","Vault Title" +"Merchant Account ID","Merchant Account ID" +"Advanced Fraud Protection","Advanced Fraud Protection" +"Kount Merchant ID","Kount Merchant ID" Debug,Debug -"Capture Action","Capture Action" -"New Order Status","New Order Status" -"Use Vault","Use Vault" -"Allow Duplicate Cards","Allow Duplicate Cards" "CVV Verification","CVV Verification" "Credit Card Types","Credit Card Types" -"Enable Credit Card auto-detection on Storefront","Enable Credit Card auto-detection on Storefront" -"Advanced Fraud Protection","Advanced Fraud Protection" -"Your Kount ID","Your Kount ID" -"Use Cache","Use Cache" "Sort Order","Sort Order" "Country Specific Settings","Country Specific Settings" "Payment from Applicable Countries","Payment from Applicable Countries" @@ -122,47 +100,32 @@ Debug,Debug "Country Specific Credit Card Types","Country Specific Credit Card Types" "PayPal through Braintree","PayPal through Braintree" "Override Merchant Name","Override Merchant Name" -"Display on Shopping Cart","Display on Shopping Cart" "Require Customer's Billing Address","Require Customer's Billing Address" "Allow to Edit Shipping Address Entered During Checkout on PayPal Side","Allow to Edit Shipping Address Entered During Checkout on PayPal Side" +"Display on Shopping Cart","Display on Shopping Cart" +"Skip Order Review","Skip Order Review" "3D Secure Verification Settings","3D Secure Verification Settings" "3D Secure Verification","3D Secure Verification" -"Edit My Credit Cards","Edit My Credit Cards" -"cc_type","Credit Card Type" -"cc_number","Credit Card Number" -"avsPostalCodeResponseCode","AVS Postal Code Response Code" -"avsStreetAddressResponseCode","AVS Street Address Response Code" -"cvvResponseCode","CVV Response Code" -"processorAuthorizationCode","Processor Authorization Code" -"processorResponseCode","Processor Response Code" -"processorResponseText","Processor Response Text" -"braintree", "Braintree" -"liabilityShifted", "Liability Shifted" -"liabilityShiftPossible", "Liability Shift Possible" -"riskDataId", "Risk ID" -"riskDataDecision", "Risk Decision" -"paymentId", "Payment Id" -"payerEmail", "Payer Email" -"sale","Sale" -"credit","Credit" -"authorization_expired","Authorization expired" -"authorizing","Authorizing" -"authorized","Authorized" -"gateway_rejected","Gateway rejected" -"failed","Failed" -"processor_declined","Processor declined" -"settled","Settled" -"settling","Settling" -"submitted_for_settlement","Submitted for settlement" -"voided","Voided" -"unrecognized","Unrecognized" -"settlement_declined","Settlement declined" -"settlement_pending","Settlement pending" -"settlement_confirmed","Settlement confirmed" -"paypal_account","Paypal account" -"coinbase_account","Coinbase account" -"europe_bank_accout","Europe bank account" -"credit_card","Credit card" -"apple_pay_card","Apple pay card" -"android_pay_card","Android pay card" -"Accept credit/debit cards and PayPal in your Magento store.
No setup or monthly fees and your customers never leave your store to complete the purchase.","Accept credit/debit cards and PayPal in your Magento store.
No setup or monthly fees and your customers never leave your store to complete the purchase." \ No newline at end of file +"Threshold Amount","Threshold Amount" +"Verify for Applicable Countries","Verify for Applicable Countries" +"Verify for Specific Countries","Verify for Specific Countries" +"Dynamic Descriptors","Dynamic Descriptors" +Name,Name +Phone,Phone +URL,URL +"Apply filters in order to get results. Only first 100 records will be displayed in the grid, you will be able to download full version of the report in .csv format.","Apply filters in order to get results. Only first 100 records will be displayed in the grid, you will be able to download full version of the report in .csv format." +Select...,Select... +Status,Status +"Transaction Type","Transaction Type" +"Payment Type","Payment Type" +"PayPal Payment ID","PayPal Payment ID" +"Created At","Created At" +"Transaction ID","Transaction ID" +"Order ID","Order ID" +Type,Type +Amount,Amount +"Settlement Code","Settlement Code" +"Settlement Response Text","Settlement Response Text" +"Refund Ids","Refund Ids" +"Settlement Batch ID","Settlement Batch ID" +Currency,Currency diff --git a/app/code/Magento/Bundle/composer.json b/app/code/Magento/Bundle/composer.json index a839c110402d5..2b12028882cfd 100644 --- a/app/code/Magento/Bundle/composer.json +++ b/app/code/Magento/Bundle/composer.json @@ -3,29 +3,29 @@ "description": "N/A", "require": { "php": "7.0.2|7.0.4|~7.0.6|~7.1.0", - "magento/module-store": "100.2.*", - "magento/module-catalog": "101.1.*", - "magento/module-tax": "100.2.*", - "magento/module-backend": "100.2.*", - "magento/module-sales": "100.2.*", - "magento/module-checkout": "100.2.*", - "magento/module-catalog-inventory": "100.2.*", - "magento/module-customer": "100.2.*", - "magento/module-catalog-rule": "100.2.*", - "magento/module-eav": "100.2.*", - "magento/module-config": "100.2.*", - "magento/module-gift-message": "100.2.*", - "magento/framework": "100.2.*", - "magento/module-quote": "100.2.*", - "magento/module-media-storage": "100.2.*", - "magento/module-ui": "100.2.*" + "magento/module-store": "100.3.*", + "magento/module-catalog": "101.2.*", + "magento/module-tax": "100.3.*", + "magento/module-backend": "100.3.*", + "magento/module-sales": "100.3.*", + "magento/module-checkout": "100.3.*", + "magento/module-catalog-inventory": "100.3.*", + "magento/module-customer": "100.3.*", + "magento/module-catalog-rule": "100.3.*", + "magento/module-eav": "100.3.*", + "magento/module-config": "100.3.*", + "magento/module-gift-message": "100.3.*", + "magento/framework": "100.3.*", + "magento/module-quote": "100.3.*", + "magento/module-media-storage": "100.3.*", + "magento/module-ui": "100.3.*" }, "suggest": { - "magento/module-webapi": "100.2.*", - "magento/module-bundle-sample-data": "Sample Data version:100.2.*" + "magento/module-webapi": "100.3.*", + "magento/module-bundle-sample-data": "Sample Data version:100.3.*" }, "type": "magento2-module", - "version": "100.2.0-dev", + "version": "100.3.0-dev", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Bundle/i18n/en_US.csv b/app/code/Magento/Bundle/i18n/en_US.csv index e6ecf7d43df4a..ad9fad974e38f 100644 --- a/app/code/Magento/Bundle/i18n/en_US.csv +++ b/app/code/Magento/Bundle/i18n/en_US.csv @@ -24,8 +24,9 @@ Delete,Delete "Product with specified sku: ""%1"" does not contain option: ""%2""","Product with specified sku: ""%1"" does not contain option: ""%2""" "Child with specified sku: ""%1"" already assigned to product: ""%2""","Child with specified sku: ""%1"" already assigned to product: ""%2""" "Product with specified sku: %1 is not a bundle product","Product with specified sku: %1 is not a bundle product" -"Requested bundle option product doesn\'t exist","Requested bundle option product doesn\'t exist" -"Requested option doesn\'t exist","Requested option doesn\'t exist" +"Requested bundle option product doesn't exist","Requested bundle option product doesn't exist" +"%fieldName is a required field.","%fieldName is a required field." +"Requested option doesn't exist","Requested option doesn't exist" "Cannot delete option with id %1","Cannot delete option with id %1" "Could not save option","Could not save option" "Price Range","Price Range" @@ -36,37 +37,35 @@ Separately,Separately "The options you selected are not available.","The options you selected are not available." "The required options you selected are not available.","The required options you selected are not available." "Please select all required options.","Please select all required options." -"We can\'t add this item to your shopping cart right now.","We can\'t add this item to your shopping cart right now." +"We can't add this item to your shopping cart right now.","We can't add this item to your shopping cart right now." N/A,N/A Percent,Percent -"Ship Bundle Items","Ship Bundle Items" -"We can\'t save custom-defined options for bundles with dynamic pricing.","We can\'t save custom-defined options for bundles with dynamic pricing." +"We can't save custom-defined options for bundles with dynamic pricing.","We can't save custom-defined options for bundles with dynamic pricing." Cancel,Cancel "Add Selected Products","Add Selected Products" -[GLOBAL],[GLOBAL] "Add Option","Add Option" "New Option","New Option" "Option Title","Option Title" +"Default Title","Default Title" +"Store View Title","Store View Title" "Input Type","Input Type" Drop-down,Drop-down "Radio Buttons","Radio Buttons" Checkbox,Checkbox "Multiple Select","Multiple Select" Required,Required -Default,Default +"Is Default","Is Default" Name,Name "Default Quantity","Default Quantity" "User Defined","User Defined" "Price Type","Price Type" -"Dynamic Price","Dynamic Price" -"Dynamic SKU","Dynamic SKU" -"Dynamic Weight","Dynamic Weight" None,None Quantity:,Quantity: "Choose a selection...","Choose a selection..." -"Store View Title","Store View Title" +"Ship Bundle Items","Ship Bundle Items" Position,Position "There are no products in this option.","There are no products in this option." +Default,Default Ordered,Ordered Invoiced,Invoiced Shipped,Shipped diff --git a/app/code/Magento/Bundle/view/frontend/layout/checkout_onepage_review_item_renderers.xml b/app/code/Magento/Bundle/view/frontend/layout/checkout_onepage_review_item_renderers.xml index dce5945e3221d..686e12da7de21 100644 --- a/app/code/Magento/Bundle/view/frontend/layout/checkout_onepage_review_item_renderers.xml +++ b/app/code/Magento/Bundle/view/frontend/layout/checkout_onepage_review_item_renderers.xml @@ -8,7 +8,7 @@ - + diff --git a/app/code/Magento/Bundle/view/frontend/layout/sales_email_order_creditmemo_renderers.xml b/app/code/Magento/Bundle/view/frontend/layout/sales_email_order_creditmemo_renderers.xml index 97f07511d2fda..f92a04de2b57c 100644 --- a/app/code/Magento/Bundle/view/frontend/layout/sales_email_order_creditmemo_renderers.xml +++ b/app/code/Magento/Bundle/view/frontend/layout/sales_email_order_creditmemo_renderers.xml @@ -8,7 +8,7 @@ - + diff --git a/app/code/Magento/Bundle/view/frontend/layout/sales_email_order_invoice_renderers.xml b/app/code/Magento/Bundle/view/frontend/layout/sales_email_order_invoice_renderers.xml index 1041965f2c77b..051365f99021f 100644 --- a/app/code/Magento/Bundle/view/frontend/layout/sales_email_order_invoice_renderers.xml +++ b/app/code/Magento/Bundle/view/frontend/layout/sales_email_order_invoice_renderers.xml @@ -8,7 +8,7 @@ - + diff --git a/app/code/Magento/Bundle/view/frontend/layout/sales_email_order_renderers.xml b/app/code/Magento/Bundle/view/frontend/layout/sales_email_order_renderers.xml index f46300afd518c..b48e196c52866 100644 --- a/app/code/Magento/Bundle/view/frontend/layout/sales_email_order_renderers.xml +++ b/app/code/Magento/Bundle/view/frontend/layout/sales_email_order_renderers.xml @@ -8,7 +8,7 @@ - + diff --git a/app/code/Magento/Bundle/view/frontend/layout/sales_email_order_shipment_renderers.xml b/app/code/Magento/Bundle/view/frontend/layout/sales_email_order_shipment_renderers.xml index d6e8812b02165..c2c80e0ba6763 100644 --- a/app/code/Magento/Bundle/view/frontend/layout/sales_email_order_shipment_renderers.xml +++ b/app/code/Magento/Bundle/view/frontend/layout/sales_email_order_shipment_renderers.xml @@ -8,7 +8,7 @@ - + diff --git a/app/code/Magento/Bundle/view/frontend/layout/sales_order_creditmemo_renderers.xml b/app/code/Magento/Bundle/view/frontend/layout/sales_order_creditmemo_renderers.xml index da9b7fa494ed4..deb7334b726b3 100644 --- a/app/code/Magento/Bundle/view/frontend/layout/sales_order_creditmemo_renderers.xml +++ b/app/code/Magento/Bundle/view/frontend/layout/sales_order_creditmemo_renderers.xml @@ -8,7 +8,7 @@ - + diff --git a/app/code/Magento/Bundle/view/frontend/layout/sales_order_invoice_renderers.xml b/app/code/Magento/Bundle/view/frontend/layout/sales_order_invoice_renderers.xml index a1c1d23ad4788..c4865e22ad9be 100644 --- a/app/code/Magento/Bundle/view/frontend/layout/sales_order_invoice_renderers.xml +++ b/app/code/Magento/Bundle/view/frontend/layout/sales_order_invoice_renderers.xml @@ -8,7 +8,7 @@ - + diff --git a/app/code/Magento/Bundle/view/frontend/layout/sales_order_item_renderers.xml b/app/code/Magento/Bundle/view/frontend/layout/sales_order_item_renderers.xml index c02075bee5e59..86cfb1c0f7ade 100644 --- a/app/code/Magento/Bundle/view/frontend/layout/sales_order_item_renderers.xml +++ b/app/code/Magento/Bundle/view/frontend/layout/sales_order_item_renderers.xml @@ -8,7 +8,7 @@ - + diff --git a/app/code/Magento/Bundle/view/frontend/layout/sales_order_print_creditmemo_renderers.xml b/app/code/Magento/Bundle/view/frontend/layout/sales_order_print_creditmemo_renderers.xml index 2f16633a2bcca..bd1310acbcdee 100644 --- a/app/code/Magento/Bundle/view/frontend/layout/sales_order_print_creditmemo_renderers.xml +++ b/app/code/Magento/Bundle/view/frontend/layout/sales_order_print_creditmemo_renderers.xml @@ -8,7 +8,7 @@ - + diff --git a/app/code/Magento/Bundle/view/frontend/layout/sales_order_print_invoice_renderers.xml b/app/code/Magento/Bundle/view/frontend/layout/sales_order_print_invoice_renderers.xml index f143da9b57dfe..5bea1dd1c672e 100644 --- a/app/code/Magento/Bundle/view/frontend/layout/sales_order_print_invoice_renderers.xml +++ b/app/code/Magento/Bundle/view/frontend/layout/sales_order_print_invoice_renderers.xml @@ -8,7 +8,7 @@ - + diff --git a/app/code/Magento/Bundle/view/frontend/layout/sales_order_print_renderers.xml b/app/code/Magento/Bundle/view/frontend/layout/sales_order_print_renderers.xml index 384a0665a80f7..27c7aabfeb195 100644 --- a/app/code/Magento/Bundle/view/frontend/layout/sales_order_print_renderers.xml +++ b/app/code/Magento/Bundle/view/frontend/layout/sales_order_print_renderers.xml @@ -8,7 +8,7 @@ - + diff --git a/app/code/Magento/Bundle/view/frontend/layout/sales_order_print_shipment_renderers.xml b/app/code/Magento/Bundle/view/frontend/layout/sales_order_print_shipment_renderers.xml index bfa85a0a9c9d8..481d72ae10bdb 100644 --- a/app/code/Magento/Bundle/view/frontend/layout/sales_order_print_shipment_renderers.xml +++ b/app/code/Magento/Bundle/view/frontend/layout/sales_order_print_shipment_renderers.xml @@ -8,7 +8,7 @@ - + diff --git a/app/code/Magento/Bundle/view/frontend/layout/sales_order_shipment_renderers.xml b/app/code/Magento/Bundle/view/frontend/layout/sales_order_shipment_renderers.xml index e1b6ba0e86130..99124dfeeef93 100644 --- a/app/code/Magento/Bundle/view/frontend/layout/sales_order_shipment_renderers.xml +++ b/app/code/Magento/Bundle/view/frontend/layout/sales_order_shipment_renderers.xml @@ -8,7 +8,7 @@ - + diff --git a/app/code/Magento/BundleImportExport/Model/Import/Product/Type/Bundle.php b/app/code/Magento/BundleImportExport/Model/Import/Product/Type/Bundle.php index 35c7405501b1e..b4435acca8d0d 100644 --- a/app/code/Magento/BundleImportExport/Model/Import/Product/Type/Bundle.php +++ b/app/code/Magento/BundleImportExport/Model/Import/Product/Type/Bundle.php @@ -11,6 +11,7 @@ use \Magento\Framework\App\ObjectManager; use \Magento\Bundle\Model\Product\Price as BundlePrice; use \Magento\Catalog\Model\Product\Type\AbstractType; +use Magento\CatalogImportExport\Model\Import\Product; /** * Class Bundle @@ -177,7 +178,7 @@ protected function parseSelections($rowData, $entityId) $rowData['bundle_values'] ); $selections = explode( - \Magento\CatalogImportExport\Model\Import\Product::PSEUDO_MULTI_LINE_SEPARATOR, + Product::PSEUDO_MULTI_LINE_SEPARATOR, $rowData['bundle_values'] ); foreach ($selections as $selection) { @@ -347,7 +348,7 @@ public function saveData() $newSku = $this->_entityModel->getNewSku(); while ($bunch = $this->_entityModel->getNextBunch()) { foreach ($bunch as $rowNum => $rowData) { - $productData = $newSku[$rowData[\Magento\CatalogImportExport\Model\Import\Product::COL_SKU]]; + $productData = $newSku[strtolower($rowData[Product::COL_SKU])]; $productIds[] = $productData[$this->getProductEntityLinkField()]; } $this->deleteOptionsAndSelections($productIds); @@ -359,7 +360,7 @@ public function saveData() if (!$this->_entityModel->isRowAllowedToImport($rowData, $rowNum)) { continue; } - $productData = $newSku[$rowData[\Magento\CatalogImportExport\Model\Import\Product::COL_SKU]]; + $productData = $newSku[strtolower($rowData[Product::COL_SKU])]; if ($this->_type != $productData['type_id']) { continue; } diff --git a/app/code/Magento/BundleImportExport/Test/Unit/Model/Import/Product/Type/BundleTest.php b/app/code/Magento/BundleImportExport/Test/Unit/Model/Import/Product/Type/BundleTest.php index 6412ec9d7a86c..3fba6d9309361 100644 --- a/app/code/Magento/BundleImportExport/Test/Unit/Model/Import/Product/Type/BundleTest.php +++ b/app/code/Magento/BundleImportExport/Test/Unit/Model/Import/Product/Type/BundleTest.php @@ -299,6 +299,11 @@ public function testSaveDataProvider() 'bunch' => ['bundle_values' => 'value1', 'sku' => 'sku', 'name' => 'name'], 'allowImport' => true ], + [ + 'skus' => ['newSku' => ['sku' => ['sku' => 'SKU', 'entity_id' => 3, 'type_id' => 'bundle']]], + 'bunch' => ['bundle_values' => 'value1', 'sku' => 'SKU', 'name' => 'name'], + 'allowImport' => true + ], [ 'skus' => ['newSku' => ['sku' => ['sku' => 'sku', 'entity_id' => 3, 'type_id' => 'simple']]], 'bunch' => ['bundle_values' => 'value1', 'sku' => 'sku', 'name' => 'name'], diff --git a/app/code/Magento/BundleImportExport/composer.json b/app/code/Magento/BundleImportExport/composer.json index 8c45c565785b7..c0193b9eb365f 100644 --- a/app/code/Magento/BundleImportExport/composer.json +++ b/app/code/Magento/BundleImportExport/composer.json @@ -3,15 +3,15 @@ "description": "N/A", "require": { "php": "7.0.2|7.0.4|~7.0.6|~7.1.0", - "magento/module-catalog": "101.1.*", - "magento/module-import-export": "100.2.*", - "magento/module-catalog-import-export": "100.2.*", - "magento/module-bundle": "100.2.*", - "magento/module-eav": "100.2.*", - "magento/framework": "100.2.*" + "magento/module-catalog": "101.2.*", + "magento/module-import-export": "100.3.*", + "magento/module-catalog-import-export": "100.3.*", + "magento/module-bundle": "100.3.*", + "magento/module-eav": "100.3.*", + "magento/framework": "100.3.*" }, "type": "magento2-module", - "version": "100.2.0-dev", + "version": "100.3.0-dev", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/CacheInvalidate/composer.json b/app/code/Magento/CacheInvalidate/composer.json index feb0466a3744b..c11e55bd448d9 100644 --- a/app/code/Magento/CacheInvalidate/composer.json +++ b/app/code/Magento/CacheInvalidate/composer.json @@ -3,11 +3,11 @@ "description": "N/A", "require": { "php": "7.0.2|7.0.4|~7.0.6|~7.1.0", - "magento/module-page-cache": "100.2.*", - "magento/framework": "100.2.*" + "magento/module-page-cache": "100.3.*", + "magento/framework": "100.3.*" }, "type": "magento2-module", - "version": "100.2.0-dev", + "version": "100.3.0-dev", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Captcha/composer.json b/app/code/Magento/Captcha/composer.json index 08f49a584fbe7..db5ed92fab74b 100644 --- a/app/code/Magento/Captcha/composer.json +++ b/app/code/Magento/Captcha/composer.json @@ -3,17 +3,17 @@ "description": "N/A", "require": { "php": "7.0.2|7.0.4|~7.0.6|~7.1.0", - "magento/module-store": "100.2.*", - "magento/module-customer": "100.2.*", - "magento/module-checkout": "100.2.*", - "magento/module-backend": "100.2.*", - "magento/framework": "100.2.*", + "magento/module-store": "100.3.*", + "magento/module-customer": "100.3.*", + "magento/module-checkout": "100.3.*", + "magento/module-backend": "100.3.*", + "magento/framework": "100.3.*", "zendframework/zend-db": "^2.8.2", "zendframework/zend-captcha": "^2.7.1", "zendframework/zend-session": "^2.7.3" }, "type": "magento2-module", - "version": "100.2.0-dev", + "version": "100.3.0-dev", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Catalog/Api/Data/EavAttributeInterface.php b/app/code/Magento/Catalog/Api/Data/EavAttributeInterface.php index 263dbdf5164cc..5d5a57a670f22 100644 --- a/app/code/Magento/Catalog/Api/Data/EavAttributeInterface.php +++ b/app/code/Magento/Catalog/Api/Data/EavAttributeInterface.php @@ -139,6 +139,30 @@ public function getIsVisibleInGrid(); */ public function getIsFilterableInGrid(); + /** + * Set is attribute used in grid + * + * @param bool|null $isUsedInGrid + * @return $this + */ + public function setIsUsedInGrid($isUsedInGrid); + + /** + * Set is attribute visible in grid + * + * @param bool|null $isVisibleInGrid + * @return $this + */ + public function setIsVisibleInGrid($isVisibleInGrid); + + /** + * Set is attribute filterable in grid + * + * @param bool|null $isFilterableInGrid + * @return $this + */ + public function setIsFilterableInGrid($isFilterableInGrid); + /** * Set whether it is used in search results layered navigation * diff --git a/app/code/Magento/Catalog/Block/Product/Context.php b/app/code/Magento/Catalog/Block/Product/Context.php index 7b4afffc3cf27..8c15075747ed1 100644 --- a/app/code/Magento/Catalog/Block/Product/Context.php +++ b/app/code/Magento/Catalog/Block/Product/Context.php @@ -16,7 +16,7 @@ * As Magento moves from inheritance-based APIs all such classes will be deprecated together with * the classes they were introduced for. * - * @deprecated + * @deprecated * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class Context extends \Magento\Framework\View\Element\Template\Context diff --git a/app/code/Magento/Catalog/Block/Product/View/Gallery.php b/app/code/Magento/Catalog/Block/Product/View/Gallery.php index 35b2d487623fb..0a9589182d659 100644 --- a/app/code/Magento/Catalog/Block/Product/View/Gallery.php +++ b/app/code/Magento/Catalog/Block/Product/View/Gallery.php @@ -128,9 +128,14 @@ public function getGalleryImagesJson() /** @var DataObject $image */ foreach ($this->getGalleryImages() as $image) { $imageItem = new DataObject([ + 'thumb' => $image->getData('small_image_url'), + 'img' => $image->getData('medium_image_url'), + 'full' => $image->getData('large_image_url'), 'caption' => $image->getData('label'), 'position' => $image->getData('position'), 'isMain' => $this->isMainImage($image), + 'type' => str_replace('external-', '', $image->getMediaType()), + 'videoUrl' => $image->getVideoUrl(), ]); foreach ($this->getGalleryImagesConfig()->getItems() as $imageConfig) { $imageItem->setData( @@ -148,6 +153,8 @@ public function getGalleryImagesJson() 'caption' => '', 'position' => '0', 'isMain' => true, + 'type' => 'image', + 'videoUrl' => null, ]; } return json_encode($imagesItems); diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Category/Move.php b/app/code/Magento/Catalog/Controller/Adminhtml/Category/Move.php index 704054dc22e5b..df2c80eda141c 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Category/Move.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Category/Move.php @@ -27,7 +27,7 @@ class Move extends \Magento\Catalog\Controller\Adminhtml\Category * @param \Magento\Backend\App\Action\Context $context * @param \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory * @param \Magento\Framework\View\LayoutFactory $layoutFactory, - * @param \Psr\Log\LoggerInterface $logger, + * @param \Psr\Log\LoggerInterface $logger */ public function __construct( \Magento\Backend\App\Action\Context $context, @@ -67,20 +67,17 @@ public function execute() throw new \Exception(__('Category is not available for requested store.')); } $category->move($parentNodeId, $prevNodeId); - } catch (\Magento\Framework\Exception\AlreadyExistsException $e) { - $error = true; - $this->messageManager->addError(__('There was a category move error. %1', $e->getMessage())); } catch (\Magento\Framework\Exception\LocalizedException $e) { $error = true; - $this->messageManager->addError($e->getMessage()); + $this->messageManager->addExceptionMessage($e); } catch (\Exception $e) { $error = true; - $this->messageManager->addError(__('There was a category move error.')); + $this->messageManager->addErrorMessage(__('There was a category move error.')); $this->logger->critical($e); } if (!$error) { - $this->messageManager->addSuccess(__('You moved the category.')); + $this->messageManager->addSuccessMessage(__('You moved the category.')); } $block->setMessages($this->messageManager->getMessages(true)); diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Category/Save.php b/app/code/Magento/Catalog/Controller/Adminhtml/Category/Save.php index 5319862e29fcb..3422d414566c2 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Category/Save.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Category/Save.php @@ -211,17 +211,13 @@ public function execute() $category->unsetData('use_post_data_config'); $category->save(); - $this->messageManager->addSuccess(__('You saved the category.')); - } catch (\Magento\Framework\Exception\AlreadyExistsException $e) { - $this->messageManager->addError($e->getMessage()); - $this->_objectManager->get(\Psr\Log\LoggerInterface::class)->critical($e); - $this->_getSession()->setCategoryData($categoryPostData); + $this->messageManager->addSuccessMessage(__('You saved the category.')); } catch (\Magento\Framework\Exception\LocalizedException $e) { - $this->messageManager->addError($e->getMessage()); + $this->messageManager->addExceptionMessage($e); $this->_objectManager->get(\Psr\Log\LoggerInterface::class)->critical($e); $this->_getSession()->setCategoryData($categoryPostData); } catch (\Exception $e) { - $this->messageManager->addError(__('Something went wrong while saving the category.')); + $this->messageManager->addErrorMessage(__('Something went wrong while saving the category.')); $this->_objectManager->get(\Psr\Log\LoggerInterface::class)->critical($e); $this->_getSession()->setCategoryData($categoryPostData); } 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 f14cb709c9ebb..4dd406a5d14db 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Validate.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Validate.php @@ -104,10 +104,13 @@ public function execute() $multipleOption = null == $multipleOption ? 'select' : $multipleOption; if (isset($this->multipleAttributeList[$multipleOption]) && !(null == ($multipleOption))) { + $options = $this->getRequest()->getParam($this->multipleAttributeList[$multipleOption]); $this->checkUniqueOption( $response, - $this->getRequest()->getParam($this->multipleAttributeList[$multipleOption]) + $options ); + $valueOptions = (isset($options['value']) && is_array($options['value'])) ? $options['value'] : []; + $this->checkEmptyOption($response, $valueOptions); } return $this->resultJsonFactory->create()->setJsonData($response->toJson()); @@ -155,19 +158,37 @@ private function setMessageToResponse($response, $messages) private function checkUniqueOption(DataObject $response, array $options = null) { if (is_array($options) + && isset($options['value']) + && isset($options['delete']) && !empty($options['value']) && !empty($options['delete']) ) { $duplicates = $this->isUniqueAdminValues($options['value'], $options['delete']); - if ($duplicates) { + if (!empty($duplicates)) { $this->setMessageToResponse( $response, [__('The value of Admin must be unique. (%1)', implode(', ', $duplicates))] ); - $response->setError(true); } } return $this; } + + /** + * Check that admin does not try to create option with empty admin scope option. + * + * @param DataObject $response + * @param array $optionsForCheck + * @return void + */ + private function checkEmptyOption(DataObject $response, array $optionsForCheck = null) + { + foreach ($optionsForCheck as $optionValues) { + if (isset($optionValues[0]) && $optionValues[0] == '') { + $this->setMessageToResponse($response, [__("The value of Admin scope can't be empty.")]); + $response->setError(true); + } + } + } } diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper.php index 9228b9687b82a..1f534ff2833bd 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper.php @@ -8,6 +8,7 @@ use Magento\Catalog\Api\Data\ProductCustomOptionInterfaceFactory as CustomOptionFactory; use Magento\Catalog\Api\Data\ProductLinkInterfaceFactory as ProductLinkFactory; use Magento\Catalog\Api\ProductRepositoryInterface\Proxy as ProductRepository; +use Magento\Catalog\Model\Product; use Magento\Catalog\Model\Product\Initialization\Helper\ProductLinks; use Magento\Catalog\Model\Product\Link\Resolver as LinkResolver; use Magento\Framework\App\ObjectManager; @@ -203,34 +204,7 @@ public function initializeFromData(\Magento\Catalog\Model\Product $product, arra } $product = $this->setProductLinks($product); - - /** - * Initialize product options - */ - if ($productOptions && !$product->getOptionsReadonly()) { - // mark custom options that should to fall back to default value - $options = $this->mergeProductOptions( - $productOptions, - $this->request->getPost('options_use_default') - ); - $customOptions = []; - foreach ($options as $customOptionData) { - if (empty($customOptionData['is_delete'])) { - if (empty($customOptionData['option_id'])) { - $customOptionData['option_id'] = null; - } - if (isset($customOptionData['values'])) { - $customOptionData['values'] = array_filter($customOptionData['values'], function ($valueData) { - return empty($valueData['is_delete']); - }); - } - $customOption = $this->customOptionFactory->create(['data' => $customOptionData]); - $customOption->setProductSku($product->getSku()); - $customOptions[] = $customOption; - } - } - $product->setOptions($customOptions); - } + $product = $this->fillProductOptions($product, $productOptions); $product->setCanSaveCustomOptions( !empty($productData['affect_product_custom_options']) && !$product->getOptionsReadonly() @@ -427,4 +401,50 @@ private function filterWebsiteIds($websiteIds) return $websiteIds; } + + /** + * Fills $product with options from $productOptions array + * + * @param Product $product + * @param array $productOptions + * @return Product + */ + private function fillProductOptions(Product $product, array $productOptions) + { + if ($product->getOptionsReadonly()) { + return $product; + } + + if (empty($productOptions)) { + return $product->setOptions([]); + } + + // mark custom options that should to fall back to default value + $options = $this->mergeProductOptions( + $productOptions, + $this->request->getPost('options_use_default') + ); + $customOptions = []; + foreach ($options as $customOptionData) { + if (!empty($customOptionData['is_delete'])) { + continue; + } + + if (empty($customOptionData['option_id'])) { + $customOptionData['option_id'] = null; + } + + if (isset($customOptionData['values'])) { + $customOptionData['values'] = array_filter($customOptionData['values'], function ($valueData) { + return empty($valueData['is_delete']); + }); + } + + $customOption = $this->customOptionFactory->create(['data' => $customOptionData]); + $customOption->setProductSku($product->getSku()); + $customOptions[] = $customOption; + } + + return $product->setOptions($customOptions); + } } diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Save.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Save.php index 5a83fa3e34fa8..42d830e92669d 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Save.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Save.php @@ -119,10 +119,10 @@ public function execute() $this->copyToStores($data, $productId); - $this->messageManager->addSuccess(__('You saved the product.')); + $this->messageManager->addSuccessMessage(__('You saved the product.')); $this->getDataPersistor()->clear('catalog_product'); if ($product->getSku() != $originalSku) { - $this->messageManager->addNotice( + $this->messageManager->addNoticeMessage( __( 'SKU for product %1 has been changed to %2.', $this->_objectManager->get( @@ -141,22 +141,22 @@ public function execute() if ($redirectBack === 'duplicate') { $newProduct = $this->productCopier->copy($product); - $this->messageManager->addSuccess(__('You duplicated the product.')); + $this->messageManager->addSuccessMessage(__('You duplicated the product.')); } } catch (\Magento\Framework\Exception\LocalizedException $e) { $this->_objectManager->get(\Psr\Log\LoggerInterface::class)->critical($e); - $this->messageManager->addError($e->getMessage()); + $this->messageManager->addExceptionMessage($e); $this->getDataPersistor()->set('catalog_product', $data); $redirectBack = $productId ? true : 'new'; } catch (\Exception $e) { $this->_objectManager->get(\Psr\Log\LoggerInterface::class)->critical($e); - $this->messageManager->addError($e->getMessage()); + $this->messageManager->addErrorMessage($e->getMessage()); $this->getDataPersistor()->set('catalog_product', $data); $redirectBack = $productId ? true : 'new'; } } else { $resultRedirect->setPath('catalog/*/', ['store' => $storeId]); - $this->messageManager->addError('No data to save'); + $this->messageManager->addErrorMessage('No data to save'); return $resultRedirect; } @@ -202,7 +202,7 @@ private function handleImageRemoveError($postData, $productId) $expectedImagesAmount = count($postData['product']['media_gallery']['images']) - $removedImagesAmount; $product = $this->productRepository->getById($productId); if ($expectedImagesAmount != count($product->getMediaGallery('images'))) { - $this->messageManager->addNotice( + $this->messageManager->addNoticeMessage( __('The image cannot be removed as it has been assigned to the other image role') ); } diff --git a/app/code/Magento/Catalog/Model/Category/Attribute.php b/app/code/Magento/Catalog/Model/Category/Attribute.php index a191ab3113b5b..968db224c01f5 100644 --- a/app/code/Magento/Catalog/Model/Category/Attribute.php +++ b/app/code/Magento/Catalog/Model/Category/Attribute.php @@ -361,4 +361,31 @@ public function setScope($scope) return $this; } } + + /** + * @inheritdoc + */ + public function setIsUsedInGrid($isUsedInGrid) + { + $this->setData(self::IS_USED_IN_GRID, $isUsedInGrid); + return $this; + } + + /** + * @inheritdoc + */ + public function setIsVisibleInGrid($isVisibleInGrid) + { + $this->setData(self::IS_VISIBLE_IN_GRID, $isVisibleInGrid); + return $this; + } + + /** + * @inheritdoc + */ + public function setIsFilterableInGrid($isFilterableInGrid) + { + $this->setData(self::IS_FILTERABLE_IN_GRID, $isFilterableInGrid); + return $this; + } } diff --git a/app/code/Magento/Catalog/Model/Entity/Product/Attribute/Design/Options/Container.php b/app/code/Magento/Catalog/Model/Entity/Product/Attribute/Design/Options/Container.php index 011cfdcb6860d..22cb3c3264df5 100644 --- a/app/code/Magento/Catalog/Model/Entity/Product/Attribute/Design/Options/Container.php +++ b/app/code/Magento/Catalog/Model/Entity/Product/Attribute/Design/Options/Container.php @@ -24,7 +24,7 @@ public function getOptionText($value) if (sizeof($options) > 0) { foreach ($options as $option) { if (isset($option['value']) && $option['value'] == $value) { - return $option['label']; + return __($option['label']); } } } diff --git a/app/code/Magento/Catalog/Model/Product/Attribute/DataProvider.php b/app/code/Magento/Catalog/Model/Product/Attribute/DataProvider.php index 989c886f64a05..2bb10d3b31a24 100644 --- a/app/code/Magento/Catalog/Model/Product/Attribute/DataProvider.php +++ b/app/code/Magento/Catalog/Model/Product/Attribute/DataProvider.php @@ -5,15 +5,14 @@ */ namespace Magento\Catalog\Model\Product\Attribute; -use Magento\Catalog\Model\Category; use Magento\Framework\Stdlib\ArrayManager; use Magento\Store\Api\StoreRepositoryInterface; use Magento\Catalog\Model\ResourceModel\Product\Attribute\CollectionFactory; use Magento\Eav\Model\Entity\Attribute as EavAttribute; -use Magento\Ui\Component\Form; use Magento\Ui\Component\Form\Element\Input; use Magento\Ui\Component\Form\Field; use Magento\Ui\Component\Form\Element\DataType\Text; +use Magento\Store\Model\Store; /** * Data provider for the form of adding new product attribute. @@ -149,40 +148,36 @@ private function customizeOptions($meta) $sortOrder = 1; foreach ($this->storeRepository->getList() as $store) { $storeId = $store->getId(); - + $storeLabelConfiguration = [ + 'dataType' => 'text', + 'formElement' => 'input', + 'component' => 'Magento_Catalog/js/form/element/input', + 'template' => 'Magento_Catalog/form/element/input', + 'prefixName' => 'option.value', + 'prefixElementName' => 'option_', + 'suffixName' => (string)$storeId, + 'label' => $store->getName(), + 'sortOrder' => $sortOrder, + 'componentType' => Field::NAME, + ]; + // JS code can't understand 'required-entry' => false|null, we have to avoid even empty property. + if ($store->getCode() == Store::ADMIN_CODE) { + $storeLabelConfiguration['validation'] = [ + 'required-entry' => true, + ]; + } $meta['attribute_options_select_container']['children']['attribute_options_select']['children'] ['record']['children']['value_option_' . $storeId] = $this->arrayManager->set( 'arguments/data/config', [], - [ - 'dataType' => 'text', - 'formElement' => 'input', - 'component' => 'Magento_Catalog/js/form/element/input', - 'template' => 'Magento_Catalog/form/element/input', - 'prefixName' => 'option.value', - 'prefixElementName' => 'option_', - 'suffixName' => (string)$storeId, - 'label' => $store->getName(), - 'sortOrder' => $sortOrder, - 'componentType' => Field::NAME, - ] + $storeLabelConfiguration ); + $meta['attribute_options_multiselect_container']['children']['attribute_options_multiselect']['children'] ['record']['children']['value_option_' . $storeId] = $this->arrayManager->set( 'arguments/data/config', [], - [ - 'dataType' => 'text', - 'formElement' => 'input', - 'component' => 'Magento_Catalog/js/form/element/input', - 'template' => 'Magento_Catalog/form/element/input', - 'prefixName' => 'option.value', - 'prefixElementName' => 'option_', - 'suffixName' => (string)$storeId, - 'label' => $store->getName(), - 'sortOrder' => $sortOrder, - 'componentType' => Field::NAME, - ] + $storeLabelConfiguration ); ++$sortOrder; } diff --git a/app/code/Magento/Catalog/Model/ProductVisibilityCondition.php b/app/code/Magento/Catalog/Model/ProductVisibilityCondition.php index cdaa8da793b87..08475ec3d052f 100644 --- a/app/code/Magento/Catalog/Model/ProductVisibilityCondition.php +++ b/app/code/Magento/Catalog/Model/ProductVisibilityCondition.php @@ -1,6 +1,6 @@ _productFlatIndexerHelper = $objectManager->get(\Magento\Catalog\Helper\Product\Flat\Indexer::class); $this->attrLockValidator = $objectManager->get(LockValidatorInterface::class); } + + /** + * @inheritdoc + */ + public function setIsUsedInGrid($isUsedInGrid) + { + $this->setData(self::IS_USED_IN_GRID, $isUsedInGrid); + return $this; + } + + /** + * @inheritdoc + */ + public function setIsVisibleInGrid($isVisibleInGrid) + { + $this->setData(self::IS_VISIBLE_IN_GRID, $isVisibleInGrid); + return $this; + } + + /** + * @inheritdoc + */ + public function setIsFilterableInGrid($isFilterableInGrid) + { + $this->setData(self::IS_FILTERABLE_IN_GRID, $isFilterableInGrid); + return $this; + } } diff --git a/app/code/Magento/Catalog/Model/Widget/RecentlyComparedStorageConfiguration.php b/app/code/Magento/Catalog/Model/Widget/RecentlyComparedStorageConfiguration.php index befd4306787d0..ff5765f3e3795 100644 --- a/app/code/Magento/Catalog/Model/Widget/RecentlyComparedStorageConfiguration.php +++ b/app/code/Magento/Catalog/Model/Widget/RecentlyComparedStorageConfiguration.php @@ -32,7 +32,7 @@ public function __construct(ScopeConfigInterface $scopeConfig) /** * Parse lifetime of recently compared products in widget - * + * * @inheritdoc */ public function get() diff --git a/app/code/Magento/Catalog/Model/Widget/RecentlyViewedStorageConfiguration.php b/app/code/Magento/Catalog/Model/Widget/RecentlyViewedStorageConfiguration.php index 54ddc66e634e1..a1cdaf64425d4 100644 --- a/app/code/Magento/Catalog/Model/Widget/RecentlyViewedStorageConfiguration.php +++ b/app/code/Magento/Catalog/Model/Widget/RecentlyViewedStorageConfiguration.php @@ -1,6 +1,6 @@ messageManager->expects($this->once()) - ->method('addError') + ->method('addErrorMessage') ->with(__('There was a category move error.')); $this->messageManager->expects($this->once()) ->method('getMessages') @@ -211,8 +211,7 @@ public function testExecuteWithLocaliedException() ->withConsecutive([Registry::class], [Registry::class], [\Magento\Cms\Model\Wysiwyg\Config::class]) ->willReturnMap([[Registry::class, $registry], [\Magento\Cms\Model\Wysiwyg\Config::class, $wysiwigConfig]]); $this->messageManager->expects($this->once()) - ->method('addError') - ->with($exceptionMessage); + ->method('addExceptionMessage'); $this->messageManager->expects($this->once()) ->method('getMessages') ->with(true) @@ -306,7 +305,7 @@ public function testSuccessfullCategorySave() ) ->willReturn(true); $this->messageManager->expects($this->once()) - ->method('addSuccess') + ->method('addSuccessMessage') ->with(__('You moved the category.')); $categoryMock->expects($this->once()) ->method('move') diff --git a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Attribute/ValidateTest.php b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Attribute/ValidateTest.php index f5a6cee9c526a..6373712066695 100644 --- a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Attribute/ValidateTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Attribute/ValidateTest.php @@ -251,4 +251,77 @@ public function provideUniqueData() ], ]; } + + /** + * Check that empty admin scope labels will trigger error. + * + * @dataProvider provideEmptyOption + * @param array $options + * @throws \Magento\Framework\Exception\NotFoundException + */ + public function testEmptyOption(array $options, $result) + { + $this->requestMock->expects($this->any()) + ->method('getParam') + ->willReturnMap([ + ['frontend_label', null, null], + ['frontend_input', 'select', 'multipleselect'], + ['attribute_code', null, "test_attribute_code"], + ['new_attribute_set_name', null, 'test_attribute_set_name'], + ['option', null, $options], + ['message_key', Validate::DEFAULT_MESSAGE_KEY, 'message'], + ]); + + $this->objectManagerMock->expects($this->once()) + ->method('create') + ->willReturn($this->attributeMock); + + $this->attributeMock->expects($this->once()) + ->method('loadByCode') + ->willReturnSelf(); + + $this->resultJsonFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($this->resultJson); + + $this->resultJson->expects($this->once()) + ->method('setJsonData') + ->willReturnArgument(0); + + $response = $this->getModel()->execute(); + $responseObject = json_decode($response); + $this->assertEquals($responseObject, $result); + } + + /** + * Dataprovider for testEmptyOption. + * + * @return array + */ + public function provideEmptyOption() + { + return [ + 'empty admin scope options' => [ + [ + 'value' => [ + "option_0" => [''], + ], + ], + (object) [ + 'error' => true, + 'message' => 'The value of Admin scope can\'t be empty.', + ] + ], + 'not empty admin scope options' => [ + [ + 'value' => [ + "option_0" => ['asdads'], + ], + ], + (object) [ + 'error' => false, + ] + ] + ]; + } } diff --git a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/SaveTest.php b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/SaveTest.php index c51e875d95171..04d0e20c365e6 100644 --- a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/SaveTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/SaveTest.php @@ -17,25 +17,28 @@ class SaveTest extends \Magento\Catalog\Test\Unit\Controller\Adminhtml\ProductTe protected $action; /** @var \Magento\Backend\Model\View\Result\Page|\PHPUnit_Framework_MockObject_MockObject */ - protected $resultPage; + private $resultPage; /** @var \Magento\Backend\Model\View\Result\Forward|\PHPUnit_Framework_MockObject_MockObject */ - protected $resultForward; + private $resultForward; /** @var \Magento\Catalog\Controller\Adminhtml\Product\Builder|\PHPUnit_Framework_MockObject_MockObject */ - protected $productBuilder; + private $productBuilder; /** @var \Magento\Catalog\Model\Product|\PHPUnit_Framework_MockObject_MockObject */ - protected $product; + private $product; /** @var \Magento\Backend\Model\View\Result\RedirectFactory|\PHPUnit_Framework_MockObject_MockObject */ - protected $resultRedirectFactory; + private $resultRedirectFactory; /** @var \Magento\Backend\Model\View\Result\Redirect|\PHPUnit_Framework_MockObject_MockObject */ - protected $resultRedirect; + private $resultRedirect; /** @var Helper|\PHPUnit_Framework_MockObject_MockObject */ - protected $initializationHelper; + private $initializationHelper; + + /** @var \Magento\Framework\Message\ManagerInterface|\PHPUnit_Framework_MockObject_MockObject */ + private $messageManagerMock; /** * @return void @@ -55,6 +58,10 @@ protected function setUp() $this->product->expects($this->any())->method('getStoreId')->will($this->returnValue('1')); $this->productBuilder->expects($this->any())->method('build')->will($this->returnValue($this->product)); + $this->messageManagerMock = $this->getMockForAbstractClass( + \Magento\Framework\Message\ManagerInterface::class + ); + $this->resultPage = $this->getMockBuilder(\Magento\Backend\Model\View\Result\Page::class) ->disableOriginalConstructor() ->getMock(); @@ -120,21 +127,24 @@ protected function setUp() \Magento\Catalog\Controller\Adminhtml\Product\Save::class, [ 'context' => $this->initContext($additionalParams), + 'resultRedirectFactory' => $this->resultRedirectFactory, 'productBuilder' => $this->productBuilder, 'resultPageFactory' => $resultPageFactory, 'resultForwardFactory' => $resultForwardFactory, 'initializationHelper' => $this->initializationHelper, 'storeManager' => $storeManagerInterfaceMock, + 'messageManager' => $this->messageManagerMock ] ); } /** * @param string $exceptionType + * @param string $methodExpected * @return void * @dataProvider exceptionTypeDataProvider */ - public function testExecuteSetsProductDataToSessionAndRedirectsToNewActionOnError($exceptionType) + public function testExecuteSetsProductDataToSessionAndRedirectsToNewActionOnError($exceptionType, $methodExpected) { $productData = ['product' => ['name' => 'test-name']]; @@ -145,6 +155,9 @@ public function testExecuteSetsProductDataToSessionAndRedirectsToNewActionOnErro $this->resultRedirect->expects($this->once())->method('setPath')->with('catalog/*/new'); + $this->messageManagerMock->expects($this->once()) + ->method($methodExpected); + $this->action->execute(); } @@ -153,6 +166,9 @@ public function testExecuteSetsProductDataToSessionAndRedirectsToNewActionOnErro */ public function exceptionTypeDataProvider() { - return [[\Magento\Framework\Exception\LocalizedException::class], ['Exception']]; + return [ + [\Magento\Framework\Exception\LocalizedException::class, 'addExceptionMessage'], + ['Exception', 'addErrorMessage'] + ]; } } diff --git a/app/code/Magento/Catalog/Test/Unit/Model/FrontendStorageConfigurationPoolTest.php b/app/code/Magento/Catalog/Test/Unit/Model/FrontendStorageConfigurationPoolTest.php index e217b11fe4382..22865358c8b2e 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/FrontendStorageConfigurationPoolTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/FrontendStorageConfigurationPoolTest.php @@ -1,6 +1,6 @@ - [ - 1 => \Magento\Catalog\Model\Product\Type::TYPE_SIMPLE - ], - 'sku_2' => - [ - 2 => \Magento\Catalog\Model\Product\Type::TYPE_VIRTUAL - ] + 'sku_1' => [ + 1 => \Magento\Catalog\Model\Product\Type::TYPE_SIMPLE + ], + 'sku_2' => [ + 2 => \Magento\Catalog\Model\Product\Type::TYPE_VIRTUAL + ] ]; $select = $this->getMockBuilder(\Magento\Framework\DB\Select::class) ->disableOriginalConstructor()->getMock(); @@ -228,14 +226,12 @@ public function testDelete() $attributeId = 5; $skus = ['sku_1', 'sku_2']; $idsBySku = [ - 'sku_1' => - [ - 1 => \Magento\Catalog\Model\Product\Type::TYPE_SIMPLE - ], - 'sku_2' => - [ - 2 => \Magento\Catalog\Model\Product\Type::TYPE_VIRTUAL - ] + 'sku_1' => [ + 1 => \Magento\Catalog\Model\Product\Type::TYPE_SIMPLE + ], + 'sku_2' => [ + 2 => \Magento\Catalog\Model\Product\Type::TYPE_VIRTUAL + ] ]; $this->productIdLocator ->expects($this->once()) @@ -278,14 +274,12 @@ public function testDeleteWithException() $attributeId = 5; $skus = ['sku_1', 'sku_2']; $idsBySku = [ - 'sku_1' => - [ - 1 => \Magento\Catalog\Model\Product\Type::TYPE_SIMPLE - ], - 'sku_2' => - [ - 2 => \Magento\Catalog\Model\Product\Type::TYPE_VIRTUAL - ] + 'sku_1' => [ + 1 => \Magento\Catalog\Model\Product\Type::TYPE_SIMPLE + ], + 'sku_2' => [ + 2 => \Magento\Catalog\Model\Product\Type::TYPE_VIRTUAL + ] ]; $this->productIdLocator ->expects($this->once()) diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ProductRenderListTest.php b/app/code/Magento/Catalog/Test/Unit/Model/ProductRenderListTest.php index b50297101d687..f407ccf33ab63 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/ProductRenderListTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/ProductRenderListTest.php @@ -1,6 +1,6 @@ - Small + Small small_image - Main + Main image - Thumbnail + Thumbnail thumbnail - Custom image + Custom image custom_image @@ -51,6 +51,7 @@ option + option diff --git a/app/code/Magento/Catalog/etc/di.xml b/app/code/Magento/Catalog/etc/di.xml index 1d41d0b7b49d2..4f9b5b6fbead3 100644 --- a/app/code/Magento/Catalog/etc/di.xml +++ b/app/code/Magento/Catalog/etc/di.xml @@ -145,11 +145,11 @@ container1 - Product Info Column + Product Info Column container2 - Block after Info Column + Block after Info Column diff --git a/app/code/Magento/Catalog/i18n/en_US.csv b/app/code/Magento/Catalog/i18n/en_US.csv index 145ead923d61e..f7b31bb8a5e90 100644 --- a/app/code/Magento/Catalog/i18n/en_US.csv +++ b/app/code/Magento/Catalog/i18n/en_US.csv @@ -23,16 +23,17 @@ Year,Year label,label "Product Attributes","Product Attributes" "Add New Attribute","Add New Attribute" +Cancel,Cancel +"Save Attribute","Save Attribute" "Save in New Attribute Set","Save in New Attribute Set" "Enter Name for New Attribute Set","Enter Name for New Attribute Set" "Save and Continue Edit","Save and Continue Edit" -"Save Attribute","Save Attribute" "Delete Attribute","Delete Attribute" "Edit Product Attribute ""%1""","Edit Product Attribute ""%1""" "New Product Attribute","New Product Attribute" "Advanced Attribute Properties","Advanced Attribute Properties" "Attribute Code","Attribute Code" -"This is used internally. Make sure you don\'t use spaces or more than %1 symbols.","This is used internally. Make sure you don\'t use spaces or more than %1 symbols." +"This is used internally. Make sure you don't use spaces or more than %1 symbols.","This is used internally. Make sure you don't use spaces or more than %1 symbols." "Default Value","Default Value" "Unique Value","Unique Value" "Unique Value (not shared with other products)","Unique Value (not shared with other products)" @@ -75,7 +76,7 @@ Integer,Integer Properties,Properties "Manage Labels","Manage Labels" Visible,Visible -"Website","Website" +"Web Site","Web Site" Searchable,Searchable Comparable,Comparable "Delete Selected Group","Delete Selected Group" @@ -175,14 +176,14 @@ None,None "Price: %1","Price: %1" "Special Price: %1","Special Price: %1" "Special Products","Special Products" +"Manage Catalog Categories","Manage Catalog Categories" +"Manage Categories","Manage Categories" "You deleted the category.","You deleted the category." "Something went wrong while trying to delete the category.","Something went wrong while trying to delete the category." Categories,Categories -"Manage Catalog Categories","Manage Catalog Categories" -"Manage Categories","Manage Categories" "Category is not available for requested store.","Category is not available for requested store." -"There was a category move error.","There was a category move error." "There was a category move error. %1","There was a category move error. %1" +"There was a category move error.","There was a category move error." "You moved the category.","You moved the category." "Attribute ""%1"" is required.","Attribute ""%1"" is required." "You saved the category.","You saved the category." @@ -191,24 +192,28 @@ Categories,Categories "Please make sure to define SKU values for all processed products.","Please make sure to define SKU values for all processed products." "A total of %1 record(s) were updated.","A total of %1 record(s) were updated." "Something went wrong while updating the product(s) attributes.","Something went wrong while updating the product(s) attributes." +"Unable to add attribute","Unable to add attribute" "Please, specify attributes","Please, specify attributes" Catalog,Catalog "Manage Product Attributes","Manage Product Attributes" -"We can\'t delete the attribute.","We can\'t delete the attribute." +"We can't delete the attribute.","We can't delete the attribute." "You deleted the product attribute.","You deleted the product attribute." -"We can\'t find an attribute to delete.","We can\'t find an attribute to delete." +"We can't find an attribute to delete.","We can't find an attribute to delete." "This attribute no longer exists.","This attribute no longer exists." "This attribute cannot be edited.","This attribute cannot be edited." "Edit Product Attribute","Edit Product Attribute" -"An attribute set named \'%1\' already exists.","An attribute set named \'%1\' already exists." +"An attribute set named '%1' already exists.","An attribute set named '%1' already exists." "Something went wrong while saving the attribute.","Something went wrong while saving the attribute." "Attribute code ""%1"" is invalid. Please use only letters (a-z), numbers (0-9) or underscore(_) in this field, first character should be a letter.","Attribute code ""%1"" is invalid. Please use only letters (a-z), numbers (0-9) or underscore(_) in this field, first character should be a letter." -"We can\'t update the attribute.","We can\'t update the attribute." +"We can't update the attribute.","We can't update the attribute." "You saved the product attribute.","You saved the product attribute." "An attribute with this code already exists.","An attribute with this code already exists." "An attribute with the same code (%1) already exists.","An attribute with the same code (%1) already exists." +"The value of Admin must be unique.","The value of Admin must be unique." +"The value of Admin scope can't be empty.","The value of Admin scope can't be empty." "You duplicated the product.","You duplicated the product." -"This product no longer exists.","This product no longer exists." +"This product doesn't exist.","This product doesn't exist." +"Invalid product id. Should be numeric value greater than 0","Invalid product id. Should be numeric value greater than 0" Products,Products "A group with the same name already exists.","A group with the same name already exists." "Something went wrong while saving this group.","Something went wrong while saving this group." @@ -221,7 +226,7 @@ Products,Products "The image cannot be removed as it has been assigned to the other image role","The image cannot be removed as it has been assigned to the other image role" "New Attribute Set","New Attribute Set" "The attribute set has been removed.","The attribute set has been removed." -"We can\'t delete this set right now.","We can\'t delete this set right now." +"We can't delete this set right now.","We can't delete this set right now." "New Set","New Set" "Manage Product Sets","Manage Product Sets" "Manage Attribute Sets","Manage Attribute Sets" @@ -234,6 +239,8 @@ Products,Products "You removed product %1 from the comparison list.","You removed product %1 from the comparison list." "1 item","1 item" "%1 items","%1 items" +"Are you sure you want to remove this item from your Compare Products list?","Are you sure you want to remove this item from your Compare Products list?" +"Are you sure you want to remove all items from your Compare Products list?","Are you sure you want to remove all items from your Compare Products list?" "Invalid attribute %1","Invalid attribute %1" Grid,Grid List,List @@ -241,10 +248,11 @@ All,All "Bad controller interface for showing product","Bad controller interface for showing product" "Product is not loaded","Product is not loaded" "Make sure the To Date is later than or the same as the From Date.","Make sure the To Date is later than or the same as the From Date." -"Sorry, but we can\'t find the new parent category you selected.","Sorry, but we can\'t find the new parent category you selected." -"Sorry, but we can\'t find the new category you selected.","Sorry, but we can\'t find the new category you selected." -"We can\'t move the category because the parent category name matches the child category name.","We can\'t move the category because the parent category name matches the child category name." -"Can\'t delete root category.","Can\'t delete root category." +"Sorry, but we can't find the new parent category you selected.","Sorry, but we can't find the new parent category you selected." +"Sorry, but we can't find the new category you selected.","Sorry, but we can't find the new category you selected." +"We can't move the category because the parent category name matches the child category name.","We can't move the category because the parent category name matches the child category name." +"Something went wrong while getting the image url.","Something went wrong while getting the image url." +"Can't delete root category.","Can't delete root category." "The value of attribute ""%1"" must be unique.","The value of attribute ""%1"" must be unique." "Default Product Listing Sort by does not exist in Available Product Listing Sort By.","Default Product Listing Sort by does not exist in Available Product Listing Sort By." "No layout updates","No layout updates" @@ -270,6 +278,7 @@ frontend_label,frontend_label Manual,Manual Fixed,Fixed Percent,Percent +Discount,Discount "-- Please select --","-- Please select --" "Product Thumbnail Itself","Product Thumbnail Itself" "Parent Product Thumbnail","Parent Product Thumbnail" @@ -282,11 +291,11 @@ Top/Right,Top/Right Bottom/Left,Bottom/Left Bottom/Right,Bottom/Right Center,Center -"%1 doesn\'t extends \Magento\Framework\Model\AbstractModel","%1 doesn\'t extends \Magento\Framework\Model\AbstractModel" +"%1 doesn't extends \Magento\Framework\Model\AbstractModel","%1 doesn't extends \Magento\Framework\Model\AbstractModel" "Something went wrong while saving the file(s).","Something went wrong while saving the file(s)." "File can not be saved to the destination folder.","File can not be saved to the destination folder." "Unknown EAV indexer type ""%1"".","Unknown EAV indexer type ""%1""." -"We can\'t rebuild the index for an undefined product.","We can\'t rebuild the index for an undefined product." +"We can't rebuild the index for an undefined product.","We can't rebuild the index for an undefined product." "Bad value was supplied.","Bad value was supplied." "The Flat Catalog module has a limit of %2$d filterable and/or sortable attributes.Currently there are %1$d of them.Please reduce the number of filterable/sortable attributes in order to use this module","The Flat Catalog module has a limit of %2$d filterable and/or sortable attributes.Currently there are %1$d of them.Please reduce the number of filterable/sortable attributes in order to use this module" "Unsupported product type ""%1"".","Unsupported product type ""%1""." @@ -296,12 +305,14 @@ Center,Center Category,Category "%1 - %2","%1 - %2" "%1 was not found in algorithms","%1 was not found in algorithms" -"%1 doesn\'t extend \Magento\Catalog\Model\Layer\Filter\Dynamic\AlgorithmInterface","%1 doesn\'t extend \Magento\Catalog\Model\Layer\Filter\Dynamic\AlgorithmInterface" -"%1 doesn\'t extends \Magento\Catalog\Model\Layer\Filter\AbstractFilter","%1 doesn\'t extends \Magento\Catalog\Model\Layer\Filter\AbstractFilter" +"%1 doesn't extend \Magento\Catalog\Model\Layer\Filter\Dynamic\AlgorithmInterface","%1 doesn't extend \Magento\Catalog\Model\Layer\Filter\Dynamic\AlgorithmInterface" +"%1 doesn't extends \Magento\Catalog\Model\Layer\Filter\AbstractFilter","%1 doesn't extends \Magento\Catalog\Model\Layer\Filter\AbstractFilter" "The filter must be an object. Please set the correct filter.","The filter must be an object. Please set the correct filter." "Clear Price","Clear Price" "%1 and above","%1 and above" "The filters must be an array.","The filters must be an array." +"Product was not registered","Product was not registered" +"Store was not registered","Store was not registered" "Group price must be a number greater than 0.","Group price must be a number greater than 0." "Media Gallery converter should be an instance of EntryConverterInterface.","Media Gallery converter should be an instance of EntryConverterInterface." "There is no MediaGalleryEntryConverter for given type","There is no MediaGalleryEntryConverter for given type" @@ -310,6 +321,7 @@ Category,Category "SKU length should be %1 characters maximum.","SKU length should be %1 characters maximum." "Please enter a valid number in this field.","Please enter a valid number in this field." "We found a duplicate website, tier price, customer group and quantity.","We found a duplicate website, tier price, customer group and quantity." +"Percentage value must be a number between 0 and 100.","Percentage value must be a number between 0 and 100." "Invalid option id %1","Invalid option id %1" "Can not create attribute set based on non product attribute set.","Can not create attribute set based on non product attribute set." "Can not create attribute set based on not existing attribute set","Can not create attribute set based on not existing attribute set" @@ -318,30 +330,30 @@ Category,Category Enabled,Enabled Disabled,Disabled "Attribute Set already exists.","Attribute Set already exists." -"We couldn\'t copy file %1. Please delete media with non-existing images and try again.","We couldn\'t copy file %1. Please delete media with non-existing images and try again." +"We couldn't copy file %1. Please delete media with non-existing images and try again.","We couldn't copy file %1. Please delete media with non-existing images and try again." "The image content is not valid.","The image content is not valid." "Cannot save product.","Cannot save product." "Failed to save new media gallery entry.","Failed to save new media gallery entry." "There is no image with provided ID.","There is no image with provided ID." -"Such product doesn\'t exist","Such product doesn\'t exist" -"Such image doesn\'t exist","Such image doesn\'t exist" +"Such product doesn't exist","Such product doesn't exist" +"Such image doesn't exist","Such image doesn't exist" "The image does not exist.","The image does not exist." "Please correct the image file type.","Please correct the image file type." -"We couldn\'t move this file: %1.","We couldn\'t move this file: %1." -"We can\'t find the image file.","We can\'t find the image file." +"We couldn't move this file: %1.","We couldn't move this file: %1." "The option type to get group instance is incorrect.","The option type to get group instance is incorrect." "Select type options required values rows.","Select type options required values rows." +"ProductSku should be specified","ProductSku should be specified" "Could not remove custom option","Could not remove custom option" "Please specify date required option(s).","Please specify date required option(s)." "Please specify time required option(s).","Please specify time required option(s)." -"Please specify product\'s required option(s).","Please specify product\'s required option(s)." +"Please specify product's required option(s).","Please specify product's required option(s)." "The option instance type in options group is incorrect.","The option instance type in options group is incorrect." "The product instance type in options group is incorrect.","The product instance type in options group is incorrect." "The configuration item option instance in options group is incorrect.","The configuration item option instance in options group is incorrect." "The configuration item instance in options group is incorrect.","The configuration item instance in options group is incorrect." "The BuyRequest instance in options group is incorrect.","The BuyRequest instance in options group is incorrect." -"We can\'t add the product to the cart because of an option validation issue.","We can\'t add the product to the cart because of an option validation issue." -"%1 doesn\'t extends \Magento\Catalog\Model\Product\Option\Type\DefaultType","%1 doesn\'t extends \Magento\Catalog\Model\Product\Option\Type\DefaultType" +"We can't add the product to the cart because of an option validation issue.","We can't add the product to the cart because of an option validation issue." +"%1 doesn't extends \Magento\Catalog\Model\Product\Option\Type\DefaultType","%1 doesn't extends \Magento\Catalog\Model\Product\Option\Type\DefaultType" "The file options format is not valid.","The file options format is not valid." px.,px. "The file '%1' for '%2' has an invalid extension.","The file '%1' for '%2' has an invalid extension." @@ -349,25 +361,44 @@ px.,px. "The file '%1' you uploaded is larger than the %2 megabytes allowed by our server.","The file '%1' you uploaded is larger than the %2 megabytes allowed by our server." "The file '%1' is empty. Please choose another one","The file '%1' is empty. Please choose another one" "The file '%1' is invalid. Please choose another one","The file '%1' is invalid. Please choose another one" -"File \'%1\' is not an image.","File \'%1\' is not an image." +"File '%1' is not an image.","File '%1' is not an image." "Validation failed. Required options were not filled or the file was not uploaded.","Validation failed. Required options were not filled or the file was not uploaded." "The file you uploaded is larger than %1 Megabytes allowed by server","The file you uploaded is larger than %1 Megabytes allowed by server" "Option required.","Option required." "The file is empty. Please choose another one","The file is empty. Please choose another one" "Some of the selected item options are not currently available.","Some of the selected item options are not currently available." "The text is too long.","The text is too long." -"This product doesn\'t have tier price","This product doesn\'t have tier price" -"Product hasn\'t group price with such data: customerGroupId = \'%1\', website = %2, qty = %3","Product hasn\'t group price with such data: customerGroupId = \'%1\', website = %2, qty = %3" +"Invalid attribute %fieldName = %fieldValue.","Invalid attribute %fieldName = %fieldValue." +"Requested store is not found. Row ID: SKU = %SKU, Store ID: %storeId.","Requested store is not found. Row ID: SKU = %SKU, Store ID: %storeId." +"Invalid attribute Cost = %cost. Row ID: SKU = %SKU, Store ID: %storeId.","Invalid attribute Cost = %cost. Row ID: SKU = %SKU, Store ID: %storeId." +"Could not save Prices.","Could not save Prices." +"Could not delete Prices","Could not delete Prices" +"Requested product doesn't exist. Row ID: SKU = %SKU, Store ID: %storeId, Price From: %priceFrom, Price To: %priceTo.","Requested product doesn't exist. Row ID: SKU = %SKU, Store ID: %storeId, Price From: %priceFrom, Price To: %priceTo." +"Requested store is not found. Row ID: SKU = %SKU, Store ID: %storeId, Price From: %priceFrom, Price To: %priceTo.","Requested store is not found. Row ID: SKU = %SKU, Store ID: %storeId, Price From: %priceFrom, Price To: %priceTo." +"Invalid attribute %label = %priceTo. Row ID: SKU = %SKU, Store ID: %storeId, Price From: %priceFrom, Price To: %priceTo.","Invalid attribute %label = %priceTo. Row ID: SKU = %SKU, Store ID: %storeId, Price From: %priceFrom, Price To: %priceTo." +"Invalid attribute Price = %price. Row ID: SKU = %SKU, Store ID: %storeId, Price From: %priceFrom, Price To: %priceTo.","Invalid attribute Price = %price. Row ID: SKU = %SKU, Store ID: %storeId, Price From: %priceFrom, Price To: %priceTo." +"Could not save Tier Prices","Could not save Tier Prices" +"Could not replace Tier Prices","Could not replace Tier Prices" +"Could not delete Tier Prices","Could not delete Tier Prices" +"Invalid attribute SKU = %SKU. Row ID: SKU = %SKU, Website ID: %websiteId, Customer Group: %customerGroup, Quantity: %qty.","Invalid attribute SKU = %SKU. Row ID: SKU = %SKU, Website ID: %websiteId, Customer Group: %customerGroup, Quantity: %qty." +"Invalid attribute Price = %price. Row ID: SKU = %SKU, Website ID: %websiteId, Customer Group: %customerGroup, Quantity: %qty.","Invalid attribute Price = %price. Row ID: SKU = %SKU, Website ID: %websiteId, Customer Group: %customerGroup, Quantity: %qty." +"Invalid attribute Price Type = %priceType. Row ID: SKU = %SKU, Website ID: %websiteId, Customer Group: %customerGroup, Quantity: %qty.","Invalid attribute Price Type = %priceType. Row ID: SKU = %SKU, Website ID: %websiteId, Customer Group: %customerGroup, Quantity: %qty." +"Invalid attribute Quantity = %qty. Row ID: SKU = %SKU, Website ID: %websiteId, Customer Group: %customerGroup, Quantity: %qty.","Invalid attribute Quantity = %qty. Row ID: SKU = %SKU, Website ID: %websiteId, Customer Group: %customerGroup, Quantity: %qty." +"Invalid attribute Website ID = %websiteId. Row ID: SKU = %SKU, Website ID: %websiteId, Customer Group: %customerGroup, Quantity: %qty.","Invalid attribute Website ID = %websiteId. Row ID: SKU = %SKU, Website ID: %websiteId, Customer Group: %customerGroup, Quantity: %qty." +"We found a duplicate website, tier price, customer group and quantity: Customer Group = %customerGroup, Website ID = %websiteId, Quantity = %qty. Row ID: SKU = %SKU, Website ID: %websiteId, Customer Group: %customerGroup, Quantity: %qty.","We found a duplicate website, tier price, customer group and quantity: Customer Group = %customerGroup, Website ID = %websiteId, Quantity = %qty. Row ID: SKU = %SKU, Website ID: %websiteId, Customer Group: %customerGroup, Quantity: %qty." +"No such entity with Customer Group = %customerGroup. Row ID: SKU = %SKU, Website ID: %websiteId, Customer Group: %customerGroup, Quantity: %qty.","No such entity with Customer Group = %customerGroup. Row ID: SKU = %SKU, Website ID: %websiteId, Customer Group: %customerGroup, Quantity: %qty." +"This product doesn't have tier price","This product doesn't have tier price" +"Product hasn't group price with such data: customerGroupId = '%1', website = %2, qty = %3","Product hasn't group price with such data: customerGroupId = '%1', website = %2, qty = %3" "Invalid data provided for tier_price","Invalid data provided for tier_price" +"Could not save group price","Could not save group price" "Please provide valid data","Please provide valid data" "Values of following attributes are invalid: %1","Values of following attributes are invalid: %1" -"Could not save group price","Could not save group price" -"We can\'t create writeable directory ""%1"".","We can\'t create writeable directory ""%1""." +"We can't create writeable directory ""%1"".","We can't create writeable directory ""%1""." "The file upload failed.","The file upload failed." "The product has required options.","The product has required options." "Something went wrong while processing the request.","Something went wrong while processing the request." -"%1 doesn\'t extends \Magento\Catalog\Model\Product\Type\AbstractType","%1 doesn\'t extends \Magento\Catalog\Model\Product\Type\AbstractType" -"%1 doesn\'t extends \Magento\Catalog\Model\Product\Type\Price","%1 doesn\'t extends \Magento\Catalog\Model\Product\Type\Price" +"%1 doesn't extends \Magento\Catalog\Model\Product\Type\AbstractType","%1 doesn't extends \Magento\Catalog\Model\Product\Type\AbstractType" +"%1 doesn't extends \Magento\Catalog\Model\Product\Type\Price","%1 doesn't extends \Magento\Catalog\Model\Product\Type\Price" "Not Visible Individually","Not Visible Individually" Search,Search "Catalog, Search","Catalog, Search" @@ -379,39 +410,48 @@ Search,Search "Unknown link type: %1","Unknown link type: %1" "Provided link type ""%1"" does not exist","Provided link type ""%1"" does not exist" "Invalid data provided for linked products","Invalid data provided for linked products" -"Product with SKU %1 is not linked to product with SKU %2","Product with SKU %1 is not linked to product with SKU %2" -"Product %1 doesn\'t have linked %2 as %3","Product %1 doesn\'t have linked %2 as %3" -"Requested product doesn\'t exist","Requested product doesn\'t exist" +"Product with SKU '%1' is not linked to product with SKU '%2'","Product with SKU '%1' is not linked to product with SKU '%2'" +"Product %1 doesn't have linked %2 as %3","Product %1 doesn't have linked %2 as %3" +"Requested product doesn't exist","Requested product doesn't exist" "Requested product does not support images.","Requested product does not support images." "Product with SKU ""%1"" does not exist","Product with SKU ""%1"" does not exist" "Invalid product data: %1","Invalid product data: %1" +"Database connection error","Database connection error" +"Database deadlock found when trying to get lock","Database deadlock found when trying to get lock" +"Database lock wait timeout exceeded","Database lock wait timeout exceeded" "Unable to remove product %1","Unable to remove product %1" "There are not websites for assign to product","There are not websites for assign to product" "Could not assign product ""%1"" to websites ""%2""","Could not assign product ""%1"" to websites ""%2""" "Could not save product ""%1"" with websites %2","Could not save product ""%1"" with websites %2" "We cannot determine the field name.","We cannot determine the field name." -"Attribute \'%1\' is locked. %2","Attribute \'%1\' is locked. %2" +"Attribute '%1' is locked. %2","Attribute '%1' is locked. %2" "Do not change the scope. %1","Do not change the scope. %1" +"Processor %1 doesn't implement BaseSelectProcessorInterface","Processor %1 doesn't implement BaseSelectProcessorInterface" "A product type is not defined for the indexer.","A product type is not defined for the indexer." -"%1 doesn\'t extend \Magento\Catalog\Model\ResourceModel\Product\Indexer\Price\DefaultPrice","%1 doesn\'t extend \Magento\Catalog\Model\ResourceModel\Product\Indexer\Price\DefaultPrice" +"%1 doesn't extend \Magento\Catalog\Model\ResourceModel\Product\Indexer\Price\DefaultPrice","%1 doesn't extend \Magento\Catalog\Model\ResourceModel\Product\Indexer\Price\DefaultPrice" +"Product with SKU %1 is not linked to product with SKU %2","Product with SKU %1 is not linked to product with SKU %2" "Multiple Select","Multiple Select" Dropdown,Dropdown -"%1 doesn\'t extend \Magento\Framework\Filter\Template","%1 doesn\'t extend \Magento\Framework\Filter\Template" +"%1 doesn't extend \Magento\Framework\Filter\Template","%1 doesn't extend \Magento\Framework\Filter\Template" "As low as","As low as" +test,test +"Could not get extension attributes","Could not get extension attributes" message,message +"Some exception","Some exception" fl,fl +"Lock wait timeout","Lock wait timeout" 123,123 Images,Images Select...,Select... "Advanced Pricing","Advanced Pricing" -"Tier Price","Tier Price" "Customer Group Price","Customer Group Price" "Customer Group","Customer Group" "Special Price From","Special Price From" To,To -Cancel,Cancel Done,Done "Add Selected","Add Selected" +"Select Attribute","Select Attribute" +"Create New Attribute","Create New Attribute" "Customizable Options","Customizable Options" "Custom options let customers choose the product variations they want.","Custom options let customers choose the product variations they want." "Add Option","Add Option" @@ -446,14 +486,14 @@ Thumbnail,Thumbnail Actions,Actions "Schedule Update From","Schedule Update From" "Product in Websites","Product in Websites" -"If your Magento site has multiple views, you can set the scope to apply to a specific view.","If your Magento site has multiple views, you can set the scope to apply to a specific view." +"If your Magento installation has multiple websites, you can edit the scope to use the product on specific sites.","If your Magento installation has multiple websites, you can edit the scope to use the product on specific sites." name,name "Copy Data from","Copy Data from" "If there are no custom parent categories, please use the default parent category. You can reassign the category at any time in Products > Categories.","If there are no custom parent categories, please use the default parent category. You can reassign the category at any time in Products > Categories." "This operation can take a long time","This operation can take a long time" "Collapse All","Collapse All" "Expand All","Expand All" -"Please confirm site switching. All data that hasn\'t been saved will be lost.","Please confirm site switching. All data that hasn\'t been saved will be lost." +"Please confirm site switching. All data that hasn't been saved will be lost.","Please confirm site switching. All data that hasn't been saved will be lost." "Use Default Value","Use Default Value" "Manage Titles (Size, Color, etc.)","Manage Titles (Size, Color, etc.)" "Manage Options (Values of Your Attribute)","Manage Options (Values of Your Attribute)" @@ -464,13 +504,14 @@ Groups,Groups "Unassigned Attributes","Unassigned Attributes" "A name is required.","A name is required." "This group contains system attributes. Please move system attributes to another group and try again.","This group contains system attributes. Please move system attributes to another group and try again." +"Please select a node.","Please select a node." "Please enter a new group name.","Please enter a new group name." -"An attribute group named ""/name/"" already exists"".","An attribute group named ""/name/"" already exists""." -"Sorry, we\'re unable to complete this request.","Sorry, we\'re unable to complete this request." -"You can\'t remove attributes from this attribute set.","You can\'t remove attributes from this attribute set." +"An attribute group named ""/name/"" already exists.","An attribute group named ""/name/"" already exists." +"Sorry, we're unable to complete this request.","Sorry, we're unable to complete this request." +"You can't remove attributes from this attribute set.","You can't remove attributes from this attribute set." "Custom Options","Custom Options" "This is a required option.","This is a required option." -"The field isn\'t complete.","The field isn\'t complete." +"The field isn't complete.","The field isn't complete." "Compatible file extensions to upload","Compatible file extensions to upload" "Maximum image width","Maximum image width" "Maximum image height","Maximum image height" @@ -495,7 +536,7 @@ Backorders,Backorders "Add Product To Websites","Add Product To Websites" "Remove Product From Websites","Remove Product From Websites" "To hide an item in catalog or search results, set the status to ""Disabled"".","To hide an item in catalog or search results, set the status to ""Disabled""." -"We can\'t save custom-defined options for bundles with dynamic pricing.","We can\'t save custom-defined options for bundles with dynamic pricing." +"We can't save custom-defined options for bundles with dynamic pricing.","We can't save custom-defined options for bundles with dynamic pricing." "Delete Custom Option","Delete Custom Option" "Sort Custom Options","Sort Custom Options" "Input Type","Input Type" @@ -549,9 +590,9 @@ Compare,Compare "Clear All","Clear All" Prev,Prev Next,Next -"We can\'t find products matching the selection.","We can\'t find products matching the selection." -"Add to Compare","Add to Compare" +"We can't find products matching the selection.","We can't find products matching the selection." "Learn More","Learn More" +"Add to Compare","Add to Compare" "We found other products you might like!","We found other products you might like!" "More Choices:","More Choices:" "Check items to add to the cart or","Check items to add to the cart or" @@ -571,9 +612,10 @@ Loading...,Loading... Availability,Availability "Warning message","Warning message" Submit,Submit -"We don\'t recognize or support this file extension type.","We don\'t recognize or support this file extension type." +"We don't recognize or support this file extension type.","We don't recognize or support this file extension type." "Configure Product","Configure Product" OK,OK +"This value does not follow the specified format (for example, 200X300).","This value does not follow the specified format (for example, 200X300)." "Select type of option.","Select type of option." "Please add rows to option.","Please add rows to option." "Please select items.","Please select items." @@ -581,9 +623,13 @@ OK,OK "Image Detail","Image Detail" Adding...,Adding... Added,Added +"does not implement Storage Interface","does not implement Storage Interface" "unselect all","unselect all" Inventory,Inventory "Catalog Section","Catalog Section" +Small,Small +Main,Main +"Custom image","Custom image" "Product Fields Auto-Generation","Product Fields Auto-Generation" "Mask for SKU","Mask for SKU" "Use {{name}} as Product Name placeholder","Use {{name}} as Product Name placeholder" @@ -592,6 +638,10 @@ Inventory,Inventory "Use {{name}} as Product Name or {{sku}} as Product SKU placeholders","Use {{name}} as Product Name or {{sku}} as Product SKU placeholders" "Mask for Meta Description","Mask for Meta Description" "Use {{name}} and {{description}} as Product Name and Product Description placeholders","Use {{name}} and {{description}} as Product Name and Product Description placeholders" +"Recently Viewed/Compared Products","Recently Viewed/Compared Products" +"Lifetime of products in Recently Viewed Widget","Lifetime of products in Recently Viewed Widget" +"Lifetime of products in Recently Compared Widget","Lifetime of products in Recently Compared Widget" +"Synchronize widget products with backend storage","Synchronize widget products with backend storage" Storefront,Storefront "List Mode","List Mode" "Products per Page on Grid Allowed Values","Products per Page on Grid Allowed Values" @@ -625,6 +675,8 @@ Comma-separated.,Comma-separated. "Use Static URLs for Media Content in WYSIWYG for Catalog","Use Static URLs for Media Content in WYSIWYG for Catalog" "This applies only to catalog products and categories. Media content will be inserted into the editor as a static URL. Media content is not updated if the system configuration base URL changes.","This applies only to catalog products and categories. Media content will be inserted into the editor as a static URL. Media content is not updated if the system configuration base URL changes." "Top Level Category","Top Level Category" +"Product Info Column","Product Info Column" +"Block after Info Column","Block after Info Column" "Product Flat Data","Product Flat Data" "Reorganize EAV product structure to flat structure","Reorganize EAV product structure to flat structure" "Category Flat Data","Category Flat Data" @@ -668,18 +720,36 @@ Template,Template "If empty, we'll use the category name here.","If empty, we'll use the category name here." "Category Link Block Template","Category Link Block Template" "Category Link Inline Template","Category Link Inline Template" +"Recently Viewed Products","Recently Viewed Products" +"List of Products Recently Viewed by Visitor","List of Products Recently Viewed by Visitor" +"UI Component","UI Component" +"Number of Products to display","Number of Products to display" +"Product attributes to show","Product attributes to show" +Image,Image +"Learn More Link","Learn More Link" +"Buttons to show","Buttons to show" +"Add to Wishlist","Add to Wishlist" +"Viewed Products Grid Template","Viewed Products Grid Template" +"Viewed Products List Template","Viewed Products List Template" +"Viewed Products Sidebar Template","Viewed Products Sidebar Template" +"Recently Compared Products","Recently Compared Products" +"List of Products Recently Compared by Visitor","List of Products Recently Compared by Visitor" +"Compared Products Grid Template","Compared Products Grid Template" +"Compared Products List Template","Compared Products List Template" Set,Set "Category Information","Category Information" "Enable Category","Enable Category" "Include in Menu","Include in Menu" Content,Content "Category Image","Category Image" +Description,Description "Add CMS Block","Add CMS Block" "Display Settings","Display Settings" +"Display Mode","Display Mode" Anchor,Anchor -"Sort Products By","Sort Products By" +"Available Product Listing Sort By","Available Product Listing Sort By" "Use All","Use All" -"Default Product Sorting","Default Product Sorting" +"Default Product Listing Sort By","Default Product Listing Sort By" "Layered Navigation Price Step","Layered Navigation Price Step" "URL Key","URL Key" "Meta Title","Meta Title" @@ -687,7 +757,6 @@ Anchor,Anchor "Meta Description","Meta Description" "Products in Category","Products in Category" Design,Design -"Use Parent Category Settings","Use Parent Category Settings" Theme,Theme Layout,Layout "Layout Update XML","Layout Update XML" @@ -697,24 +766,34 @@ AttributeSetText,AttributeSetText StatusText,StatusText "Product Image Watermarks","Product Image Watermarks" Base,Base -Image,Image "Allowed file types: jpeg, gif, png.","Allowed file types: jpeg, gif, png." +Image,Image "Image Opacity","Image Opacity" "Example format: 200x300.","Example format: 200x300." -"This value does not follow the specified format (for example, 200X300).","This value does not follow the specified format (for example, 200X300)." "Image Position","Image Position" Small,Small +"Attribute Properties","Attribute Properties" "Attribute Label","Attribute Label" +"Catalog Input Type for Store Owner","Catalog Input Type for Store Owner" +Values,Values +"Add this attribute to the list of column options in the product grid.","Add this attribute to the list of column options in the product grid." +"Add this attribute to the list of filter options in the product grid.","Add this attribute to the list of filter options in the product grid." System,System "All Store Views","All Store Views" -"Delete items","Delete items" "Delete selected items?","Delete selected items?" +"Delete items","Delete items" "Change status","Change status" Enable,Enable Disable,Disable "Update attributes","Update attributes" -none,none Overview,Overview +"Skip to the end of the images gallery","Skip to the end of the images gallery" +"Skip to the beginning of the images gallery","Skip to the beginning of the images gallery" Details,Details +"Recently Compared","Recently Compared" +"Add To Cart","Add To Cart" +"Add To Compare","Add To Compare" +"Learn more","Learn more" +"Recently Viewed","Recently Viewed" "The value of Admin must be unique.", "The value of Admin must be unique." "The value of Admin must be unique. (%1)", "The value of Admin must be unique. (%1)" diff --git a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/wysiwyg/js.phtml b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/wysiwyg/js.phtml index 1dac30a083a7c..9c568cab16d84 100644 --- a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/wysiwyg/js.phtml +++ b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/wysiwyg/js.phtml @@ -69,17 +69,21 @@ var catalogWysiwygEditor = { $(elementId + '_editor').value = $(elementId).value; }, okDialogWindow : function(dialogWindow) { - if (dialogWindow.options.firedElementId) { - wysiwygObj = eval('wysiwyg'+dialogWindow.options.firedElementId+'_editor'); + var $firedElement = jQuery('#' + dialogWindow.options.firedElementId), + $editorElement = jQuery('#' + dialogWindow.options.firedElementId + '_editor'), + firedElementId = $firedElement.attr('id'), + wysiwygObj = window['wysiwyg' + firedElementId + '_editor']; + + if ($firedElement.length) { wysiwygObj.turnOff(); if (tinyMCE.get(wysiwygObj.id)) { - $(dialogWindow.options.firedElementId).value = tinyMCE.get(wysiwygObj.id).getContent(); + $firedElement.val(tinyMCE.get(wysiwygObj.id).getContent()).change(); } else { - if ($(dialogWindow.options.firedElementId+'_editor')) { - $(dialogWindow.options.firedElementId).value = $(dialogWindow.options.firedElementId+'_editor').value; - } + $firedElement.val($editorElement.val()).change(); + } + if (tinyMCE.get(firedElementId)) { + tinyMCE.get(firedElementId).load(); } - tinyMCE.editors[dialogWindow.options.firedElementId].load(); if (typeof varienGlobalEvents != undefined) { varienGlobalEvents.fireEvent('tinymceChange'); } diff --git a/app/code/Magento/Catalog/view/adminhtml/web/js/components/dynamic-rows-import-custom-options.js b/app/code/Magento/Catalog/view/adminhtml/web/js/components/dynamic-rows-import-custom-options.js index 09fd015d2114d..bcc5ad451a533 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/js/components/dynamic-rows-import-custom-options.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/js/components/dynamic-rows-import-custom-options.js @@ -10,20 +10,6 @@ define([ ], function (DynamicRows, _, utils) { 'use strict'; - var maxId = 0, - - /** - * Stores max option_id value of the options from recordData once on initialization - * @param {Array} data - array with records data - */ - initMaxId = function (data) { - if (data && data.length) { - maxId = ~~_.max(data, function (record) { - return ~~record['option_id']; - })['option_id']; - } - }; - return DynamicRows.extend({ defaults: { mappingSettings: { @@ -38,18 +24,11 @@ define([ identificationDRProperty: 'option_id' }, - /** @inheritdoc */ - initialize: function () { - this._super(); - initMaxId(this.recordData()); - - return this; - }, - /** @inheritdoc */ processingInsertData: function (data) { var options = [], - currentOption; + currentOption, + generalContext = this; if (!data) { return; @@ -70,10 +49,7 @@ define([ } if (currentOption.values.length > 0) { - _.each(currentOption.values, function (optionValue) { - delete optionValue['option_id']; - delete optionValue['option_type_id']; - }); + generalContext.removeOptionsIds(currentOption.values); } options.push(currentOption); }); @@ -91,17 +67,20 @@ define([ }, /** - * Set empty array to dataProvider + * Removes option_id and option_type_id from every option + * + * @param {Array} options */ - clearDataProvider: function () { - this.source.set(this.dataProvider, []); + removeOptionsIds: function (options) { + _.each(options, function (optionValue) { + delete optionValue['option_id']; + delete optionValue['option_type_id']; + }); }, /** @inheritdoc */ processingAddChild: function (ctx, index, prop) { - if (ctx && !_.isNumber(ctx['option_id'])) { - ctx['option_id'] = ++maxId; - } else if (!ctx) { + if (!ctx) { this.showSpinner(true); this.addChild(ctx, index, prop); @@ -111,6 +90,13 @@ define([ this._super(ctx, index, prop); }, + /** + * Set empty array to dataProvider + */ + clearDataProvider: function () { + this.source.set(this.dataProvider, []); + }, + /** * Mutes parent method */ diff --git a/app/code/Magento/Catalog/view/adminhtml/web/template/form/element/input.html b/app/code/Magento/Catalog/view/adminhtml/web/template/form/element/input.html index a3aad4284d8d8..f13f431c95944 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/template/form/element/input.html +++ b/app/code/Magento/Catalog/view/adminhtml/web/template/form/element/input.html @@ -17,3 +17,4 @@ id: uid, disabled: disabled }"/> +