From 1031b3bd268af411958399f3ebdf9bb57a4279c2 Mon Sep 17 00:00:00 2001 From: Ihor Sviziev Date: Thu, 12 Mar 2020 10:59:07 +0200 Subject: [PATCH 001/126] Clean expired quotes - Fix out of memory on huge quotes list --- .../Magento/Sales/Cron/CleanExpiredQuotes.php | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/Sales/Cron/CleanExpiredQuotes.php b/app/code/Magento/Sales/Cron/CleanExpiredQuotes.php index a3242228b28e0..a8e367487b983 100644 --- a/app/code/Magento/Sales/Cron/CleanExpiredQuotes.php +++ b/app/code/Magento/Sales/Cron/CleanExpiredQuotes.php @@ -5,12 +5,12 @@ */ namespace Magento\Sales\Cron; -use Magento\Quote\Model\ResourceModel\Quote\Collection; +use Magento\Quote\Model\ResourceModel\Quote\Collection as QuoteCollection; use Magento\Sales\Model\ResourceModel\Collection\ExpiredQuotesCollection; use Magento\Store\Model\StoreManagerInterface; /** - * Class CleanExpiredQuotes + * Cron job for cleaning expired Quotes */ class CleanExpiredQuotes { @@ -45,9 +45,20 @@ public function execute() { $stores = $this->storeManager->getStores(true); foreach ($stores as $store) { - /** @var $quotes Collection */ - $quotes = $this->expiredQuotesCollection->getExpiredQuotes($store); - $quotes->walk('delete'); + /** @var $quoteCollection QuoteCollection */ + $quoteCollection = $this->expiredQuotesCollection->getExpiredQuotes($store); + $quoteCollection->setPageSize(50); + + // Last page returns 1 even when we don't have any results + $lastPage = $quoteCollection->getSize() ? $quoteCollection->getLastPageNumber() : 0; + + for ($currentPage = 1; $currentPage <= $lastPage; $currentPage++) { + $quoteCollection->setCurPage($currentPage); + + $quoteCollection->walk('delete'); + + $quoteCollection->clear(); + } } } } From a18eecc0d0aa82d0976fda0dd5994e519d226c9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Tylek?= Date: Thu, 19 Mar 2020 13:50:19 +0100 Subject: [PATCH 002/126] Fix duplicates of footer and incorrect greeting in some Magento_Customer emails --- .../Magento/Customer/view/frontend/email/change_email.html | 7 +------ .../view/frontend/email/change_email_and_password.html | 7 +------ .../Customer/view/frontend/email/password_reset.html | 7 +------ 3 files changed, 3 insertions(+), 18 deletions(-) diff --git a/app/code/Magento/Customer/view/frontend/email/change_email.html b/app/code/Magento/Customer/view/frontend/email/change_email.html index 4853adf638066..890a1e22b833f 100644 --- a/app/code/Magento/Customer/view/frontend/email/change_email.html +++ b/app/code/Magento/Customer/view/frontend/email/change_email.html @@ -12,15 +12,10 @@ } @--> {{template config_path="design/email/header_template"}} -

{{trans "Hello,"}}

-
- +

{{trans "%name," name=$customer.name}}

{{trans "We have received a request to change the following information associated with your account at %store_name: email." store_name=$store.frontend_name}} {{trans 'If you have not authorized this action, please contact us immediately at %store_email' store_email=$store_email |raw}}{{depend store_phone}} {{trans 'or call us at %store_phone' store_phone=$store_phone |raw}}{{/depend}}.

-
- -

{{trans "Thanks,
%store_name" store_name=$store.frontend_name |raw}}

{{template config_path="design/email/footer_template"}} diff --git a/app/code/Magento/Customer/view/frontend/email/change_email_and_password.html b/app/code/Magento/Customer/view/frontend/email/change_email_and_password.html index 49867bdedc9e0..173223ced9029 100644 --- a/app/code/Magento/Customer/view/frontend/email/change_email_and_password.html +++ b/app/code/Magento/Customer/view/frontend/email/change_email_and_password.html @@ -12,15 +12,10 @@ } @--> {{template config_path="design/email/header_template"}} -

{{trans "Hello,"}}

-
- +

{{trans "%name," name=$customer.name}}

{{trans "We have received a request to change the following information associated with your account at %store_name: email, password." store_name=$store.frontend_name}} {{trans 'If you have not authorized this action, please contact us immediately at %store_email' store_email=$store_email |raw}}{{depend store_phone}} {{trans 'or call us at %store_phone' store_phone=$store_phone |raw}}{{/depend}}.

-
- -

{{trans "Thanks,
%store_name" store_name=$store.frontend_name |raw}}

{{template config_path="design/email/footer_template"}} diff --git a/app/code/Magento/Customer/view/frontend/email/password_reset.html b/app/code/Magento/Customer/view/frontend/email/password_reset.html index 79015117c2280..23307978e158c 100644 --- a/app/code/Magento/Customer/view/frontend/email/password_reset.html +++ b/app/code/Magento/Customer/view/frontend/email/password_reset.html @@ -13,15 +13,10 @@ } @--> {{template config_path="design/email/header_template"}} -

{{trans "Hello,"}}

-
- +

{{trans "%name," name=$customer.name}}

{{trans "We have received a request to change the following information associated with your account at %store_name: password." store_name=$store.frontend_name}} {{trans 'If you have not authorized this action, please contact us immediately at %store_email' store_email=$store_email |raw}}{{depend store_phone}} {{trans 'or call us at %store_phone' store_phone=$store_phone |raw}}{{/depend}}.

-
- -

{{trans "Thanks,
%store_name" store_name=$store.frontend_name |raw}}

{{template config_path="design/email/footer_template"}} From 7fa9dd709fbc015354042f5fd12bf2b34db05bf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Tylek?= Date: Thu, 19 Mar 2020 14:24:31 +0100 Subject: [PATCH 003/126] Add missing vars --- .../Magento/Customer/view/frontend/email/change_email.html | 3 ++- .../view/frontend/email/change_email_and_password.html | 3 ++- .../Magento/Customer/view/frontend/email/password_reset.html | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Customer/view/frontend/email/change_email.html b/app/code/Magento/Customer/view/frontend/email/change_email.html index 890a1e22b833f..5341a2dc67ad5 100644 --- a/app/code/Magento/Customer/view/frontend/email/change_email.html +++ b/app/code/Magento/Customer/view/frontend/email/change_email.html @@ -8,7 +8,8 @@ {{template config_path="design/email/header_template"}} diff --git a/app/code/Magento/Customer/view/frontend/email/change_email_and_password.html b/app/code/Magento/Customer/view/frontend/email/change_email_and_password.html index 173223ced9029..ed2af7ada669e 100644 --- a/app/code/Magento/Customer/view/frontend/email/change_email_and_password.html +++ b/app/code/Magento/Customer/view/frontend/email/change_email_and_password.html @@ -8,7 +8,8 @@ {{template config_path="design/email/header_template"}} diff --git a/app/code/Magento/Customer/view/frontend/email/password_reset.html b/app/code/Magento/Customer/view/frontend/email/password_reset.html index 23307978e158c..a6c54842a1573 100644 --- a/app/code/Magento/Customer/view/frontend/email/password_reset.html +++ b/app/code/Magento/Customer/view/frontend/email/password_reset.html @@ -9,7 +9,8 @@ "var customer.name":"Customer Name", "var store.frontend_name":"Store Name", "var store_email":"Store Email", -"var store_phone":"Store Phone" +"var store_phone":"Store Phone", +"var customer.name":"Customer Name" } @--> {{template config_path="design/email/header_template"}} From 414b897b8ef5e67d1fe4a9ed9789abfac12e466b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Tylek?= Date: Thu, 19 Mar 2020 14:27:43 +0100 Subject: [PATCH 004/126] Newsletter subscription emails should also use paragraph tags --- .../Magento/Newsletter/view/frontend/email/subscr_success.html | 2 +- .../Magento/Newsletter/view/frontend/email/unsub_success.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Newsletter/view/frontend/email/subscr_success.html b/app/code/Magento/Newsletter/view/frontend/email/subscr_success.html index d56163c10fdf3..996dff0c973e9 100644 --- a/app/code/Magento/Newsletter/view/frontend/email/subscr_success.html +++ b/app/code/Magento/Newsletter/view/frontend/email/subscr_success.html @@ -13,6 +13,6 @@ {{template config_path="design/email/header_template"}} -{{trans "You have been successfully subscribed to our newsletter."}} +

{{trans "You have been successfully subscribed to our newsletter."}}

{{template config_path="design/email/footer_template"}} diff --git a/app/code/Magento/Newsletter/view/frontend/email/unsub_success.html b/app/code/Magento/Newsletter/view/frontend/email/unsub_success.html index d39b5d8a8b8e9..1f222f85abac7 100644 --- a/app/code/Magento/Newsletter/view/frontend/email/unsub_success.html +++ b/app/code/Magento/Newsletter/view/frontend/email/unsub_success.html @@ -13,6 +13,6 @@ {{template config_path="design/email/header_template"}} -{{trans "You have been unsubscribed from the newsletter."}} +

{{trans "You have been unsubscribed from the newsletter."}}

{{template config_path="design/email/footer_template"}} From 4cd55f5aee91bbbeb4bc51274ec687fb30cb0ac1 Mon Sep 17 00:00:00 2001 From: Ihor Sviziev Date: Mon, 23 Mar 2020 18:17:53 +0200 Subject: [PATCH 005/126] Clean expired quotes - Fix out of memory on huge quotes list --- .../Magento/Sales/Cron/CleanExpiredQuotes.php | 46 +++++++++++++++++-- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Sales/Cron/CleanExpiredQuotes.php b/app/code/Magento/Sales/Cron/CleanExpiredQuotes.php index a8e367487b983..b420bdcde7040 100644 --- a/app/code/Magento/Sales/Cron/CleanExpiredQuotes.php +++ b/app/code/Magento/Sales/Cron/CleanExpiredQuotes.php @@ -5,9 +5,12 @@ */ namespace Magento\Sales\Cron; +use Exception; +use Magento\Quote\Model\QuoteRepository; use Magento\Quote\Model\ResourceModel\Quote\Collection as QuoteCollection; use Magento\Sales\Model\ResourceModel\Collection\ExpiredQuotesCollection; use Magento\Store\Model\StoreManagerInterface; +use Psr\Log\LoggerInterface; /** * Cron job for cleaning expired Quotes @@ -24,16 +27,32 @@ class CleanExpiredQuotes */ private $storeManager; + /** + * @var QuoteRepository + */ + private $quoteRepository; + + /** + * @var LoggerInterface + */ + private $logger; + /** * @param StoreManagerInterface $storeManager * @param ExpiredQuotesCollection $expiredQuotesCollection + * @param QuoteRepository $quoteRepository + * @param LoggerInterface $logger */ public function __construct( StoreManagerInterface $storeManager, - ExpiredQuotesCollection $expiredQuotesCollection + ExpiredQuotesCollection $expiredQuotesCollection, + QuoteRepository $quoteRepository, + LoggerInterface $logger ) { $this->storeManager = $storeManager; $this->expiredQuotesCollection = $expiredQuotesCollection; + $this->quoteRepository = $quoteRepository; + $this->logger = $logger; } /** @@ -52,13 +71,32 @@ public function execute() // Last page returns 1 even when we don't have any results $lastPage = $quoteCollection->getSize() ? $quoteCollection->getLastPageNumber() : 0; - for ($currentPage = 1; $currentPage <= $lastPage; $currentPage++) { + for ($currentPage = $lastPage; $currentPage >= 1; $currentPage--) { $quoteCollection->setCurPage($currentPage); - $quoteCollection->walk('delete'); + $this->deleteQuotes($quoteCollection); + } + } + } - $quoteCollection->clear(); + /** + * @param QuoteCollection $quoteCollection + */ + private function deleteQuotes(QuoteCollection $quoteCollection): void + { + foreach ($quoteCollection as $quote) { + try { + $this->quoteRepository->delete($quote); + } catch (Exception $e) { + $message = sprintf( + 'Unable to delete expired quote (ID: %s): %s', + $quote->getId(), + (string)$e + ); + $this->logger->error($message); } } + + $quoteCollection->clear(); } } From 76f3ed4b2308b9c746d0ce4f783a8caf1529830b Mon Sep 17 00:00:00 2001 From: Ihor Sviziev Date: Mon, 23 Mar 2020 18:35:30 +0200 Subject: [PATCH 006/126] Clean expired quotes - Fix out of memory on huge quotes list --- .../Sales/Cron/CleanExpiredQuotesTest.php | 27 ++++++++++++++ .../Sales/_files/quotes_big_amount.php | 37 +++++++++++++++++++ .../_files/quotes_big_amount_rollback.php | 34 +++++++++++++++++ 3 files changed, 98 insertions(+) create mode 100644 dev/tests/integration/testsuite/Magento/Sales/_files/quotes_big_amount.php create mode 100644 dev/tests/integration/testsuite/Magento/Sales/_files/quotes_big_amount_rollback.php diff --git a/dev/tests/integration/testsuite/Magento/Sales/Cron/CleanExpiredQuotesTest.php b/dev/tests/integration/testsuite/Magento/Sales/Cron/CleanExpiredQuotesTest.php index fc39972b5e9f7..63bf507652c6b 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/Cron/CleanExpiredQuotesTest.php +++ b/dev/tests/integration/testsuite/Magento/Sales/Cron/CleanExpiredQuotesTest.php @@ -9,6 +9,7 @@ use Magento\Framework\Api\SearchCriteriaBuilder; use Magento\Quote\Model\QuoteRepository; +use Magento\Quote\Model\ResourceModel\Quote\CollectionFactory as QuoteCollectionFactory; use Magento\TestFramework\Helper\Bootstrap; /** @@ -34,6 +35,11 @@ class CleanExpiredQuotesTest extends \PHPUnit\Framework\TestCase */ private $searchCriteriaBuilder; + /** + * @var QuoteCollectionFactory + */ + private $quoteCollectionFactory; + /** * @inheritdoc */ @@ -43,6 +49,7 @@ protected function setUp() $this->cleanExpiredQuotes = $objectManager->get(CleanExpiredQuotes::class); $this->quoteRepository = $objectManager->get(QuoteRepository::class); $this->searchCriteriaBuilder = $objectManager->get(SearchCriteriaBuilder::class); + $this->quoteCollectionFactory = $objectManager->get(QuoteCollectionFactory::class); } /** @@ -66,4 +73,24 @@ public function testExecute() $totalCount ); } + + /** + * Check if outdated quotes are deleted. + * + * @magentoConfigFixture default_store checkout/cart/delete_quote_after -365 + * @magentoDataFixture Magento/Sales/_files/quotes_big_amount.php + */ + public function testExecuteWithBigAmountOfQuotes() + { + //Initial count - should be equal to 1000 + //Use collection getSize in order to get quick result + $this->assertEquals(1000, $this->quoteCollectionFactory->create()->getSize()); + + //Deleting expired quotes + $this->cleanExpiredQuotes->execute(); + $totalCount = $this->quoteCollectionFactory->create()->getSize(); + + //There should be no quotes anymore + $this->assertEquals(0, $totalCount); + } } diff --git a/dev/tests/integration/testsuite/Magento/Sales/_files/quotes_big_amount.php b/dev/tests/integration/testsuite/Magento/Sales/_files/quotes_big_amount.php new file mode 100644 index 0000000000000..c666f938d9125 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Sales/_files/quotes_big_amount.php @@ -0,0 +1,37 @@ +get(QuoteFactory::class); +/** @var QuoteRepository $quoteRepository */ +$quoteRepository = $objectManager->get(QuoteRepository::class); +/** @var StoreRepository $storeRepository */ +$storeRepository = $objectManager->get(StoreRepository::class); +/** @var Config $appConfig */ +$appConfig = $objectManager->get(Config::class); +$appConfig->clean(); + +/** @var Store $defaultStore */ +$defaultStore = $storeRepository->getActiveStoreByCode('default'); + +for ($i = 0; $i < 1000; $i++) { + /** @var Quote $quote */ + $quote = $quoteFactory->create(); + $quote->setStoreId($defaultStore->getId()); + $quoteRepository->save($quote); +} diff --git a/dev/tests/integration/testsuite/Magento/Sales/_files/quotes_big_amount_rollback.php b/dev/tests/integration/testsuite/Magento/Sales/_files/quotes_big_amount_rollback.php new file mode 100644 index 0000000000000..24832a297949d --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Sales/_files/quotes_big_amount_rollback.php @@ -0,0 +1,34 @@ +get(Registry::class); +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); + +/** @var QuoteRepository $quoteRepository */ +$quoteRepository = $objectManager->get(QuoteRepository::class); +/** @var SearchCriteriaBuilder $searchCriteriaBuilder */ +$searchCriteriaBuilder = $objectManager->get(SearchCriteriaBuilder::class); +$searchCriteria = $searchCriteriaBuilder->create(); +$items = $quoteRepository->getList($searchCriteria) + ->getItems(); +foreach ($items as $item) { + $quoteRepository->delete($item); +} + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); From 7e9fd8048f7579be1418932637b948a6d0aabf9f Mon Sep 17 00:00:00 2001 From: Ihor Sviziev Date: Mon, 23 Mar 2020 21:15:18 +0200 Subject: [PATCH 007/126] Clean expired quotes - Fix out of memory on huge quotes list --- app/code/Magento/Sales/Cron/CleanExpiredQuotes.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/code/Magento/Sales/Cron/CleanExpiredQuotes.php b/app/code/Magento/Sales/Cron/CleanExpiredQuotes.php index b420bdcde7040..978aec1b79ec4 100644 --- a/app/code/Magento/Sales/Cron/CleanExpiredQuotes.php +++ b/app/code/Magento/Sales/Cron/CleanExpiredQuotes.php @@ -80,6 +80,8 @@ public function execute() } /** + * Deletes all quotes in collection + * * @param QuoteCollection $quoteCollection */ private function deleteQuotes(QuoteCollection $quoteCollection): void From 939e1de2b6f761e46c4481e3d4c75c051b1c9f37 Mon Sep 17 00:00:00 2001 From: Ihor Sviziev Date: Tue, 24 Mar 2020 12:18:55 +0200 Subject: [PATCH 008/126] Clean expired quotes - Fix out of memory on huge quotes list --- .../Sales/Cron/CleanExpiredQuotesTest.php | 40 ++++++++----------- 1 file changed, 17 insertions(+), 23 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Sales/Cron/CleanExpiredQuotesTest.php b/dev/tests/integration/testsuite/Magento/Sales/Cron/CleanExpiredQuotesTest.php index 63bf507652c6b..ce093974f968e 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/Cron/CleanExpiredQuotesTest.php +++ b/dev/tests/integration/testsuite/Magento/Sales/Cron/CleanExpiredQuotesTest.php @@ -25,16 +25,6 @@ class CleanExpiredQuotesTest extends \PHPUnit\Framework\TestCase */ private $cleanExpiredQuotes; - /** - * @var QuoteRepository - */ - private $quoteRepository; - - /** - * @var SearchCriteriaBuilder - */ - private $searchCriteriaBuilder; - /** * @var QuoteCollectionFactory */ @@ -47,8 +37,6 @@ protected function setUp() { $objectManager = Bootstrap::getObjectManager(); $this->cleanExpiredQuotes = $objectManager->get(CleanExpiredQuotes::class); - $this->quoteRepository = $objectManager->get(QuoteRepository::class); - $this->searchCriteriaBuilder = $objectManager->get(SearchCriteriaBuilder::class); $this->quoteCollectionFactory = $objectManager->get(QuoteCollectionFactory::class); } @@ -60,18 +48,14 @@ protected function setUp() */ public function testExecute() { - $searchCriteria = $this->searchCriteriaBuilder->create(); //Initial count - should be equal to stores number. - $this->assertEquals(2, $this->quoteRepository->getList($searchCriteria)->getTotalCount()); + $this->assertQuotesCount(2); //Deleting expired quotes $this->cleanExpiredQuotes->execute(); - $totalCount = $this->quoteRepository->getList($searchCriteria)->getTotalCount(); + //Only 1 will be deleted for the store that has all of them expired by config (default_store) - $this->assertEquals( - 1, - $totalCount - ); + $this->assertQuotesCount(1); } /** @@ -83,14 +67,24 @@ public function testExecute() public function testExecuteWithBigAmountOfQuotes() { //Initial count - should be equal to 1000 - //Use collection getSize in order to get quick result - $this->assertEquals(1000, $this->quoteCollectionFactory->create()->getSize()); + $this->assertQuotesCount(1000); //Deleting expired quotes $this->cleanExpiredQuotes->execute(); - $totalCount = $this->quoteCollectionFactory->create()->getSize(); //There should be no quotes anymore - $this->assertEquals(0, $totalCount); + $this->assertQuotesCount(0); + } + + /** + * Optimized assert quotes count + * Uses collection getSize in order to get quick result + * + * @param int $expected + */ + private function assertQuotesCount(int $expected): void + { + $totalCount = $this->quoteCollectionFactory->create()->getSize(); + $this->assertEquals($expected, $totalCount); } } From 2f0bbe93b187c050a5049be66cb0fcdf97827193 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Tylek?= Date: Fri, 27 Mar 2020 17:45:36 +0100 Subject: [PATCH 009/126] Fix integration tests --- .../Magento/Newsletter/Model/SubscriberTest.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Newsletter/Model/SubscriberTest.php b/dev/tests/integration/testsuite/Magento/Newsletter/Model/SubscriberTest.php index 06c8902f45897..d2248737679c0 100644 --- a/dev/tests/integration/testsuite/Magento/Newsletter/Model/SubscriberTest.php +++ b/dev/tests/integration/testsuite/Magento/Newsletter/Model/SubscriberTest.php @@ -88,7 +88,7 @@ public function testUnsubscribeSubscribe(): void $this->assertSame($subscriber, $subscriber->loadByCustomerId(1)); $this->assertEquals($subscriber, $subscriber->unsubscribe()); $this->assertContains( - 'You have been unsubscribed from the newsletter.', + '

You have been unsubscribed from the newsletter.

', $this->transportBuilder->getSentMessage()->getRawMessage() ); $this->assertEquals(Subscriber::STATUS_UNSUBSCRIBED, $subscriber->getSubscriberStatus()); @@ -96,7 +96,7 @@ public function testUnsubscribeSubscribe(): void $this->assertEquals(Subscriber::STATUS_SUBSCRIBED, $subscriber->subscribe('customer@example.com')); $this->assertEquals(Subscriber::STATUS_SUBSCRIBED, $subscriber->getSubscriberStatus()); $this->assertContains( - 'You have been successfully subscribed to our newsletter.', + '

You have been successfully subscribed to our newsletter.

', $this->transportBuilder->getSentMessage()->getRawMessage() ); } @@ -115,14 +115,14 @@ public function testUnsubscribeSubscribeByCustomerId(): void $this->assertSame($subscriber, $subscriber->unsubscribeCustomerById(1)); $this->assertEquals(Subscriber::STATUS_UNSUBSCRIBED, $subscriber->getSubscriberStatus()); $this->assertContains( - 'You have been unsubscribed from the newsletter.', + '

You have been unsubscribed from the newsletter.

', $this->transportBuilder->getSentMessage()->getRawMessage() ); // Subscribe and verify $this->assertSame($subscriber, $subscriber->subscribeCustomerById(1)); $this->assertEquals(Subscriber::STATUS_SUBSCRIBED, $subscriber->getSubscriberStatus()); $this->assertContains( - 'You have been successfully subscribed to our newsletter.', + '

You have been successfully subscribed to our newsletter.

', $this->transportBuilder->getSentMessage()->getRawMessage() ); } @@ -142,7 +142,7 @@ public function testConfirm(): void $subscriber->loadByEmail($customerEmail); $subscriber->confirm($subscriber->getSubscriberConfirmCode()); $this->assertContains( - 'You have been successfully subscribed to our newsletter.', + '

You have been successfully subscribed to our newsletter.

', $this->transportBuilder->getSentMessage()->getRawMessage() ); } From b0c3ead8ba269198d1967f936c59211d8ebbbc42 Mon Sep 17 00:00:00 2001 From: Andrii Beziazychnyi Date: Sat, 28 Mar 2020 10:52:12 +0200 Subject: [PATCH 010/126] Fixed issue #19481: Magento 2.3.0: After composer installation sampledata can't be installed from command line --- .../Command/SampleDataDeployCommand.php | 92 +++++++++---- .../Command/AbstractSampleDataCommandTest.php | 127 ++++++++++++------ .../Command/SampleDataDeployCommandTest.php | 126 +++++++++++++---- .../Command/SampleDataRemoveCommandTest.php | 82 ++++++++--- 4 files changed, 316 insertions(+), 111 deletions(-) diff --git a/app/code/Magento/SampleData/Console/Command/SampleDataDeployCommand.php b/app/code/Magento/SampleData/Console/Command/SampleDataDeployCommand.php index 57a61fecae5ca..a65d350d8faad 100644 --- a/app/code/Magento/SampleData/Console/Command/SampleDataDeployCommand.php +++ b/app/code/Magento/SampleData/Console/Command/SampleDataDeployCommand.php @@ -7,10 +7,17 @@ namespace Magento\SampleData\Console\Command; use Composer\Console\Application; +use Composer\Console\ApplicationFactory; +use Exception; use Magento\Framework\App\Filesystem\DirectoryList; +use Magento\Framework\Exception\FileSystemException; +use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\Filesystem; +use Magento\SampleData\Model\Dependency; use Magento\Setup\Model\PackagesAuth; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\ArrayInput; +use Symfony\Component\Console\Input\ArrayInputFactory; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; @@ -23,37 +30,37 @@ class SampleDataDeployCommand extends Command const OPTION_NO_UPDATE = 'no-update'; /** - * @var \Magento\Framework\Filesystem + * @var Filesystem */ private $filesystem; /** - * @var \Magento\SampleData\Model\Dependency + * @var Dependency */ private $sampleDataDependency; /** - * @var \Symfony\Component\Console\Input\ArrayInputFactory + * @var ArrayInputFactory * @deprecated 100.1.0 */ private $arrayInputFactory; /** - * @var \Composer\Console\ApplicationFactory + * @var ApplicationFactory */ private $applicationFactory; /** - * @param \Magento\Framework\Filesystem $filesystem - * @param \Magento\SampleData\Model\Dependency $sampleDataDependency - * @param \Symfony\Component\Console\Input\ArrayInputFactory $arrayInputFactory - * @param \Composer\Console\ApplicationFactory $applicationFactory + * @param Filesystem $filesystem + * @param Dependency $sampleDataDependency + * @param ArrayInputFactory $arrayInputFactory + * @param ApplicationFactory $applicationFactory */ public function __construct( - \Magento\Framework\Filesystem $filesystem, - \Magento\SampleData\Model\Dependency $sampleDataDependency, - \Symfony\Component\Console\Input\ArrayInputFactory $arrayInputFactory, - \Composer\Console\ApplicationFactory $applicationFactory + Filesystem $filesystem, + Dependency $sampleDataDependency, + ArrayInputFactory $arrayInputFactory, + ApplicationFactory $applicationFactory ) { $this->filesystem = $filesystem; $this->sampleDataDependency = $sampleDataDependency; @@ -63,7 +70,7 @@ public function __construct( } /** - * {@inheritdoc} + * @inheritdoc */ protected function configure() { @@ -79,15 +86,42 @@ protected function configure() } /** - * {@inheritdoc} + * @inheritdoc + * + * @param InputInterface $input + * @param OutputInterface $output + * @return int|void + * @throws FileSystemException + * @throws LocalizedException */ protected function execute(InputInterface $input, OutputInterface $output) { - $rootJson = json_decode($this->filesystem->getDirectoryRead(DirectoryList::ROOT)->readFile("composer.json")); + $rootJson = json_decode( + $this->filesystem->getDirectoryRead( + DirectoryList::ROOT + )->readFile("composer.json") + ); if (!isset($rootJson->version)) { - // @codingStandardsIgnoreLine - $output->writeln('' . 'Git installations must deploy sample data from GitHub; see https://devdocs.magento.com/guides/v2.3/install-gde/install/sample-data-after-clone.html for more information.' . ''); - return; + $magentoProductPackage = array_filter( + (array) $rootJson->require, + function ($package) { + return false !== strpos($package, 'magento/product-'); + }, + ARRAY_FILTER_USE_KEY + ); + $version = reset($magentoProductPackage); + $output->writeln( + '' . + // @codingStandardsIgnoreLine + 'We don\'t recommend to remove the "version" field from your composer.json; see https://getcomposer.org/doc/02-libraries.md#library-versioning for more information.' . + '' + ); + $restoreVersion = new ArrayInput([ + 'command' => 'config', + 'setting-key' => 'version', + 'setting-value' => [$version], + '--quiet' => 1 + ]); } $this->updateMemoryLimit(); $this->createAuthFile(); @@ -109,6 +143,12 @@ protected function execute(InputInterface $input, OutputInterface $output) /** @var Application $application */ $application = $this->applicationFactory->create(); $application->setAutoExit(false); + if (!empty($restoreVersion)) { + $result = $application->run($restoreVersion, clone $output); + if ($result === 0) { + $output->writeln('The field "version" has been restored.'); + } + } $result = $application->run($commandInput, $output); if ($result !== 0) { $output->writeln( @@ -128,7 +168,7 @@ protected function execute(InputInterface $input, OutputInterface $output) * We create auth.json with correct permissions instead of relying on Composer. * * @return void - * @throws \Exception + * @throws LocalizedException */ private function createAuthFile() { @@ -137,16 +177,18 @@ private function createAuthFile() if (!$directory->isExist(PackagesAuth::PATH_TO_AUTH_FILE)) { try { $directory->writeFile(PackagesAuth::PATH_TO_AUTH_FILE, '{}'); - } catch (\Exception $e) { - $message = 'Error in writing Auth file ' - . $directory->getAbsolutePath(PackagesAuth::PATH_TO_AUTH_FILE) - . '. Please check permissions for writing.'; - throw new \Exception($message); + } catch (Exception $e) { + throw new LocalizedException(__( + 'Error in writing Auth file %1. Please check permissions for writing.', + $directory->getAbsolutePath(PackagesAuth::PATH_TO_AUTH_FILE) + )); } } } /** + * Updates PHP memory limit + * * @return void */ private function updateMemoryLimit() @@ -161,6 +203,8 @@ private function updateMemoryLimit() } /** + * Retrieves the memory size in bytes + * * @param string $value * @return int */ diff --git a/app/code/Magento/SampleData/Test/Unit/Console/Command/AbstractSampleDataCommandTest.php b/app/code/Magento/SampleData/Test/Unit/Console/Command/AbstractSampleDataCommandTest.php index a5790d40f782c..10fe2f3c32fbd 100644 --- a/app/code/Magento/SampleData/Test/Unit/Console/Command/AbstractSampleDataCommandTest.php +++ b/app/code/Magento/SampleData/Test/Unit/Console/Command/AbstractSampleDataCommandTest.php @@ -3,6 +3,8 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\SampleData\Test\Unit\Console\Command; use Composer\Console\Application; @@ -12,54 +14,64 @@ use Magento\Framework\Filesystem\Directory\ReadInterface; use Magento\Framework\Filesystem\Directory\WriteInterface; use Magento\SampleData\Model\Dependency; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Input\ArrayInput; use Symfony\Component\Console\Input\ArrayInputFactory; /** + * Common class for tests + * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ abstract class AbstractSampleDataCommandTest extends TestCase { /** - * @var ReadInterface|\PHPUnit_Framework_MockObject_MockObject + * @var ReadInterface|MockObject */ protected $directoryReadMock; /** - * @var WriteInterface|\PHPUnit_Framework_MockObject_MockObject + * @var WriteInterface|MockObject */ protected $directoryWriteMock; /** - * @var Filesystem|\PHPUnit_Framework_MockObject_MockObject + * @var Filesystem|MockObject */ protected $filesystemMock; /** - * @var Dependency|\PHPUnit_Framework_MockObject_MockObject + * @var Dependency|MockObject */ protected $sampleDataDependencyMock; /** - * @var ArrayInputFactory|\PHPUnit_Framework_MockObject_MockObject + * @var ArrayInputFactory|MockObject */ protected $arrayInputFactoryMock; /** - * @var Application|\PHPUnit_Framework_MockObject_MockObject + * @var Application|MockObject */ protected $applicationMock; /** - * @var ApplicationFactory|\PHPUnit_Framework_MockObject_MockObject + * @var ApplicationFactory|MockObject */ protected $applicationFactoryMock; /** + * @var int + */ + private $appRunResult; + + /** + * Creates mocks + * * @return void */ - protected function setUp() + protected function setUp(): void { $this->directoryReadMock = $this->createMock(ReadInterface::class); $this->directoryWriteMock = $this->createMock(WriteInterface::class); @@ -71,47 +83,86 @@ protected function setUp() } /** - * @param array $sampleDataPackages Array in form [package_name => version_constraint] - * @param string $pathToComposerJson Fake path to composer.json - * @param int $appRunResult Composer exit code + * Sets mocks + * + * @param array $sampleDataPackages Array in form [package_name => version_constraint] + * @param string $pathToComposerJson Fake path to composer.json + * @param int $appRunResult Composer exit code + * @param array $composerJsonContent Content of the composer.json * @param array $additionalComposerArgs Additional arguments that composer expects */ protected function setupMocks( $sampleDataPackages, $pathToComposerJson, $appRunResult, + $composerJsonContent = [], $additionalComposerArgs = [] ) { - $this->directoryReadMock->expects($this->any())->method('getAbsolutePath')->willReturn($pathToComposerJson); - $this->directoryReadMock->expects($this->any())->method('readFile')->with('composer.json')->willReturn( - '{"version": "0.0.1"}' - ); - $this->filesystemMock->expects($this->any())->method('getDirectoryRead')->with(DirectoryList::ROOT)->willReturn( - $this->directoryReadMock - ); - $this->sampleDataDependencyMock->expects($this->any())->method('getSampleDataPackages')->willReturn( - $sampleDataPackages - ); + $this->appRunResult = $appRunResult; + $this->directoryReadMock->expects($this->any()) + ->method('getAbsolutePath') + ->willReturn($pathToComposerJson); + $this->directoryReadMock->expects($this->any()) + ->method('readFile') + ->with('composer.json') + ->willReturn(json_encode($composerJsonContent)); + $this->filesystemMock->expects($this->any()) + ->method('getDirectoryRead') + ->with(DirectoryList::ROOT) + ->willReturn($this->directoryReadMock); + $this->sampleDataDependencyMock->expects($this->any()) + ->method('getSampleDataPackages') + ->willReturn($sampleDataPackages); $this->arrayInputFactoryMock->expects($this->never())->method('create'); - $this->applicationMock->expects($this->any()) - ->method('run') - ->with( - new ArrayInput( - array_merge( - $this->expectedComposerArguments( - $sampleDataPackages, - $pathToComposerJson + if (!array_key_exists('version', $composerJsonContent)) { + $this->applicationMock->expects($this->any()) + ->method('run') + ->withConsecutive( + [ + 'input' => new ArrayInput( + $this->expectedComposerArgumentsCommandConfig() ), - $additionalComposerArgs - ) - ), - $this->anything() - ) - ->willReturn($appRunResult); + 'output' => $this->anything() + ], + [ + 'input' => new ArrayInput( + array_merge( + $this->expectedComposerArgumentsSampleDataCommands( + $sampleDataPackages, + $pathToComposerJson + ), + $additionalComposerArgs + ) + ), + 'output' => $this->anything() + ] + )->willReturnOnConsecutiveCalls( + $this->returnValue(0), + $this->returnValue($appRunResult) + ); + } else { + $this->applicationMock->expects($this->any()) + ->method('run') + ->with( + new ArrayInput( + array_merge( + $this->expectedComposerArgumentsSampleDataCommands( + $sampleDataPackages, + $pathToComposerJson + ), + $additionalComposerArgs + ) + ), + $this->anything() + ) + ->willReturn($appRunResult); + } if (($appRunResult !== 0) && !empty($sampleDataPackages)) { - $this->applicationMock->expects($this->once())->method('resetComposer')->willReturnSelf(); + $this->applicationMock->expects($this->any()) + ->method('resetComposer') + ->willReturnSelf(); } $this->applicationFactoryMock->expects($this->any()) @@ -120,13 +171,13 @@ protected function setupMocks( } /** - * Expected arguments for composer based on sample data packages and composer.json path + * Expected arguments for composer based on sample data command * * @param array $sampleDataPackages * @param string $pathToComposerJson * @return array */ - abstract protected function expectedComposerArguments( + abstract protected function expectedComposerArgumentsSampleDataCommands( array $sampleDataPackages, string $pathToComposerJson ) : array; diff --git a/app/code/Magento/SampleData/Test/Unit/Console/Command/SampleDataDeployCommandTest.php b/app/code/Magento/SampleData/Test/Unit/Console/Command/SampleDataDeployCommandTest.php index 7ca27a7d746c7..115dec67f9f73 100644 --- a/app/code/Magento/SampleData/Test/Unit/Console/Command/SampleDataDeployCommandTest.php +++ b/app/code/Magento/SampleData/Test/Unit/Console/Command/SampleDataDeployCommandTest.php @@ -3,28 +3,36 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\SampleData\Test\Unit\Console\Command; +use Exception; use Magento\Framework\App\Filesystem\DirectoryList; use Magento\SampleData\Console\Command\SampleDataDeployCommand; use Magento\Setup\Model\PackagesAuth; use Symfony\Component\Console\Tester\CommandTester; +/** + * Tests for command `sampledata:deploy` + */ class SampleDataDeployCommandTest extends AbstractSampleDataCommandTest { /** - * @param bool $authExist True to test with existing auth.json, false without + * Sets mocks for auth file + * + * @param bool $authExist True to test with existing auth.json, false without + * @return void */ - protected function setupMocksForAuthFile($authExist) + protected function setupMocksForAuthFile(bool $authExist): void { $this->directoryWriteMock->expects($this->once()) ->method('isExist') ->with(PackagesAuth::PATH_TO_AUTH_FILE) ->willReturn($authExist); - $this->directoryWriteMock->expects($authExist ? $this->never() : $this->once())->method('writeFile')->with( - PackagesAuth::PATH_TO_AUTH_FILE, - '{}' - ); + $this->directoryWriteMock->expects($authExist ? $this->never() : $this->once()) + ->method('writeFile') + ->with(PackagesAuth::PATH_TO_AUTH_FILE, '{}'); $this->filesystemMock->expects($this->once()) ->method('getDirectoryWrite') ->with(DirectoryList::COMPOSER_HOME) @@ -32,17 +40,28 @@ protected function setupMocksForAuthFile($authExist) } /** - * @param array $sampleDataPackages - * @param int $appRunResult - int 0 if everything went fine, or an error code - * @param string $expectedMsg - * @param bool $authExist - * @return void + * @param array $sampleDataPackages + * @param int $appRunResult - int 0 if everything went fine, or an error code + * @param array $composerJsonContent + * @param string $expectedMsg + * @param bool $authExist + * @return void * * @dataProvider processDataProvider */ - public function testExecute(array $sampleDataPackages, $appRunResult, $expectedMsg, $authExist) - { - $this->setupMocks($sampleDataPackages, '/path/to/composer.json', $appRunResult); + public function testExecute( + array $sampleDataPackages, + int $appRunResult, + array $composerJsonContent, + string $expectedMsg, + bool $authExist + ): void { + $this->setupMocks( + $sampleDataPackages, + '/path/to/composer.json', + $appRunResult, + $composerJsonContent + ); $this->setupMocksForAuthFile($authExist); $commandTester = $this->createCommandTester(); $commandTester->execute([]); @@ -51,20 +70,27 @@ public function testExecute(array $sampleDataPackages, $appRunResult, $expectedM } /** - * @param array $sampleDataPackages - * @param int $appRunResult - int 0 if everything went fine, or an error code - * @param string $expectedMsg - * @param bool $authExist - * @return void + * @param array $sampleDataPackages + * @param int $appRunResult - int 0 if everything went fine, or an error code + * @param array $composerJsonContent + * @param string $expectedMsg + * @param bool $authExist + * @return void * * @dataProvider processDataProvider */ - public function testExecuteWithNoUpdate(array $sampleDataPackages, $appRunResult, $expectedMsg, $authExist) - { + public function testExecuteWithNoUpdate( + array $sampleDataPackages, + int $appRunResult, + array $composerJsonContent, + string $expectedMsg, + bool $authExist + ): void { $this->setupMocks( $sampleDataPackages, '/path/to/composer.json', $appRunResult, + $composerJsonContent, ['--no-update' => 1] ); $this->setupMocksForAuthFile($authExist); @@ -77,6 +103,8 @@ public function testExecuteWithNoUpdate(array $sampleDataPackages, $appRunResult } /** + * Data provider + * * @return array */ public function processDataProvider() @@ -85,6 +113,10 @@ public function processDataProvider() 'No sample data found' => [ 'sampleDataPackages' => [], 'appRunResult' => 1, + 'composerJsonContent' => [ + 'require' => ["magento/product-community-edition" => "0.0.1"], + 'version' => '0.0.1' + ], 'expectedMsg' => 'There is no sample data for current set of modules.' . PHP_EOL, 'authExist' => true, ], @@ -93,15 +125,36 @@ public function processDataProvider() 'magento/module-cms-sample-data' => '1.0.0-beta', ], 'appRunResult' => 1, + 'composerJsonContent' => [ + 'require' => ["magento/product-community-edition" => "0.0.1"], + 'version' => '0.0.1' + ], 'expectedMsg' => 'There is an error during sample data deployment. Composer file will be reverted.' . PHP_EOL, 'authExist' => false, ], + 'Successful sample data installation without field "version"' => [ + 'sampleDataPackages' => [ + 'magento/module-cms-sample-data' => '1.0.0-beta', + ], + 'appRunResult' => 0, + 'composerJsonContent' => [ + 'require' => ["magento/product-community-edition" => "0.0.1"] + ], + // @codingStandardsIgnoreLine + 'expectedMsg' => 'We don\'t recommend to remove the "version" field from your composer.json; see https://getcomposer.org/doc/02-libraries.md#library-versioning for more information.' + . PHP_EOL . 'The field "version" has been restored.' . PHP_EOL, + 'authExist' => true, + ], 'Successful sample data installation' => [ 'sampleDataPackages' => [ 'magento/module-cms-sample-data' => '1.0.0-beta', ], 'appRunResult' => 0, + 'composerJsonContent' => [ + 'require' => ["magento/product-community-edition" => "0.0.1"], + 'version' => '0.0.1' + ], 'expectedMsg' => '', 'authExist' => true, ], @@ -109,7 +162,7 @@ public function processDataProvider() } /** - * @expectedException \Exception + * @expectedException Exception * @expectedExceptionMessage Error in writing Auth file path/to/auth.json. Please check permissions for writing. * @return void */ @@ -118,12 +171,11 @@ public function testExecuteWithException() $this->directoryReadMock->expects($this->once()) ->method('readFile') ->with('composer.json') - ->willReturn('{"version": "0.0.1"}'); + ->willReturn('{"require": {"magento/product-community-edition": "0.0.1"}, "version": "0.0.1"}'); $this->filesystemMock->expects($this->once()) ->method('getDirectoryRead') ->with(DirectoryList::ROOT) ->willReturn($this->directoryReadMock); - $this->directoryWriteMock->expects($this->once()) ->method('isExist') ->with(PackagesAuth::PATH_TO_AUTH_FILE) @@ -131,7 +183,7 @@ public function testExecuteWithException() $this->directoryWriteMock->expects($this->once()) ->method('writeFile') ->with(PackagesAuth::PATH_TO_AUTH_FILE, '{}') - ->willThrowException(new \Exception('Something went wrong...')); + ->willThrowException(new Exception('Something went wrong...')); $this->directoryWriteMock->expects($this->once()) ->method('getAbsolutePath') ->with(PackagesAuth::PATH_TO_AUTH_FILE) @@ -145,11 +197,13 @@ public function testExecuteWithException() } /** + * Creates command tester + * * @return CommandTester */ private function createCommandTester(): CommandTester { - $commandTester = new CommandTester( + return new CommandTester( new SampleDataDeployCommand( $this->filesystemMock, $this->sampleDataDependencyMock, @@ -157,15 +211,31 @@ private function createCommandTester(): CommandTester $this->applicationFactoryMock ) ); - return $commandTester; } /** + * Expected arguments for `composer config` to set missing field "version" + * + * @return array + */ + protected function expectedComposerArgumentsCommandConfig(): array + { + return [ + 'command' => 'config', + 'setting-key' => 'version', + 'setting-value' => ['0.0.1'], + '--quiet' => 1 + ]; + } + + /** + * Returns expected arguments for command `composer require` + * * @param $sampleDataPackages * @param $pathToComposerJson * @return array */ - protected function expectedComposerArguments( + protected function expectedComposerArgumentsSampleDataCommands( array $sampleDataPackages, string $pathToComposerJson ) : array { diff --git a/app/code/Magento/SampleData/Test/Unit/Console/Command/SampleDataRemoveCommandTest.php b/app/code/Magento/SampleData/Test/Unit/Console/Command/SampleDataRemoveCommandTest.php index 7fce70fd9c376..aa720f87a84e0 100644 --- a/app/code/Magento/SampleData/Test/Unit/Console/Command/SampleDataRemoveCommandTest.php +++ b/app/code/Magento/SampleData/Test/Unit/Console/Command/SampleDataRemoveCommandTest.php @@ -3,25 +3,39 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\SampleData\Test\Unit\Console\Command; use Magento\SampleData\Console\Command\SampleDataRemoveCommand; use Symfony\Component\Console\Tester\CommandTester; +/** + * Tests for command `sampledata:remove` + */ class SampleDataRemoveCommandTest extends AbstractSampleDataCommandTest { - /** - * @param array $sampleDataPackages - * @param int $appRunResult - int 0 if everything went fine, or an error code - * @param string $expectedMsg - * @return void + * @param array $sampleDataPackages + * @param int $appRunResult - int 0 if everything went fine, or an error code + * @param array $composerJsonContent + * @param string $expectedMsg + * @return void * * @dataProvider processDataProvider */ - public function testExecute(array $sampleDataPackages, $appRunResult, $expectedMsg) - { - $this->setupMocks($sampleDataPackages, '/path/to/composer.json', $appRunResult); + public function testExecute( + array $sampleDataPackages, + int $appRunResult, + array $composerJsonContent, + string $expectedMsg + ): void { + $this->setupMocks( + $sampleDataPackages, + '/path/to/composer.json', + $appRunResult, + $composerJsonContent + ); $commandTester = $this->createCommandTester(); $commandTester->execute([]); @@ -29,19 +43,25 @@ public function testExecute(array $sampleDataPackages, $appRunResult, $expectedM } /** - * @param array $sampleDataPackages - * @param int $appRunResult - int 0 if everything went fine, or an error code - * @param string $expectedMsg - * @return void + * @param array $sampleDataPackages + * @param int $appRunResult - int 0 if everything went fine, or an error code + * @param array $composerJsonContent + * @param string $expectedMsg + * @return void * * @dataProvider processDataProvider */ - public function testExecuteWithNoUpdate(array $sampleDataPackages, $appRunResult, $expectedMsg) - { + public function testExecuteWithNoUpdate( + array $sampleDataPackages, + int $appRunResult, + array $composerJsonContent, + string $expectedMsg + ): void { $this->setupMocks( $sampleDataPackages, '/path/to/composer.json', $appRunResult, + $composerJsonContent, ['--no-update' => 1] ); $commandInput = ['--no-update' => 1]; @@ -53,32 +73,51 @@ public function testExecuteWithNoUpdate(array $sampleDataPackages, $appRunResult } /** + * Data provider + * * @return array */ public function processDataProvider() { return [ - 'No sample data found' => [ - 'sampleDataPackages' => [], + 'No sample data found in require' => [ + 'sampleDataPackages' => [ + 'magento/module-cms-sample-data' => '1.0.0-beta', + ], 'appRunResult' => 1, - 'expectedMsg' => 'There is no sample data for current set of modules.' . PHP_EOL, + 'composerJsonContent' => [ + "require" => [ + "magento/product-community-edition" => "0.0.1", + ], + "version" => "0.0.1" + ], + 'expectedMsg' => 'There is an error during remove sample data.' . PHP_EOL, ], - 'Successful sample data installation' => [ + 'Successful sample data removing' => [ 'sampleDataPackages' => [ 'magento/module-cms-sample-data' => '1.0.0-beta', ], 'appRunResult' => 0, + 'composerJsonContent' => [ + "require" => [ + "magento/product-community-edition" => "0.0.1", + "magento/module-cms-sample-data" => "1.0.0-beta", + ], + "version" => "0.0.1" + ], 'expectedMsg' => '', ], ]; } /** + * Creates command tester + * * @return CommandTester */ private function createCommandTester(): CommandTester { - $commandTester = new CommandTester( + return new CommandTester( new SampleDataRemoveCommand( $this->filesystemMock, $this->sampleDataDependencyMock, @@ -86,15 +125,16 @@ private function createCommandTester(): CommandTester $this->applicationFactoryMock ) ); - return $commandTester; } /** + * Returns expected arguments for command `composer remove` + * * @param $sampleDataPackages * @param $pathToComposerJson * @return array */ - protected function expectedComposerArguments( + protected function expectedComposerArgumentsSampleDataCommands( array $sampleDataPackages, string $pathToComposerJson ) : array { From 7fec913c47d930c351ea52ac42df7f446e6f5adc Mon Sep 17 00:00:00 2001 From: Andrii Beziazychnyi Date: Sat, 28 Mar 2020 17:33:44 +0200 Subject: [PATCH 011/126] magento/issue#19481: minor and codestyle fixes --- .../Command/SampleDataDeployCommand.php | 48 +++++++++++++--- .../Command/AbstractSampleDataCommandTest.php | 12 +++- .../Command/SampleDataDeployCommandTest.php | 57 +++++++++++++------ .../Exception/InvalidArgumentException.php | 14 +++++ 4 files changed, 107 insertions(+), 24 deletions(-) create mode 100644 lib/internal/Magento/Framework/Exception/InvalidArgumentException.php diff --git a/app/code/Magento/SampleData/Console/Command/SampleDataDeployCommand.php b/app/code/Magento/SampleData/Console/Command/SampleDataDeployCommand.php index a65d350d8faad..d6c5901a25324 100644 --- a/app/code/Magento/SampleData/Console/Command/SampleDataDeployCommand.php +++ b/app/code/Magento/SampleData/Console/Command/SampleDataDeployCommand.php @@ -10,9 +10,12 @@ use Composer\Console\ApplicationFactory; use Exception; use Magento\Framework\App\Filesystem\DirectoryList; +use Magento\Framework\Console\Cli; use Magento\Framework\Exception\FileSystemException; +use Magento\Framework\Exception\InvalidArgumentException; use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Filesystem; +use Magento\Framework\Serialize\Serializer\Json; use Magento\SampleData\Model\Dependency; use Magento\Setup\Model\PackagesAuth; use Symfony\Component\Console\Command\Command; @@ -24,6 +27,8 @@ /** * Command for deployment of Sample Data + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class SampleDataDeployCommand extends Command { @@ -50,22 +55,30 @@ class SampleDataDeployCommand extends Command */ private $applicationFactory; + /** + * @var Json + */ + private $serializer; + /** * @param Filesystem $filesystem * @param Dependency $sampleDataDependency * @param ArrayInputFactory $arrayInputFactory * @param ApplicationFactory $applicationFactory + * @param Json $serializer */ public function __construct( Filesystem $filesystem, Dependency $sampleDataDependency, ArrayInputFactory $arrayInputFactory, - ApplicationFactory $applicationFactory + ApplicationFactory $applicationFactory, + Json $serializer ) { $this->filesystem = $filesystem; $this->sampleDataDependency = $sampleDataDependency; $this->arrayInputFactory = $arrayInputFactory; $this->applicationFactory = $applicationFactory; + $this->serializer = $serializer; parent::__construct(); } @@ -90,20 +103,20 @@ protected function configure() * * @param InputInterface $input * @param OutputInterface $output - * @return int|void + * @return int * @throws FileSystemException * @throws LocalizedException */ protected function execute(InputInterface $input, OutputInterface $output) { - $rootJson = json_decode( + $rootJson = $this->serializer->unserialize( $this->filesystem->getDirectoryRead( DirectoryList::ROOT )->readFile("composer.json") ); - if (!isset($rootJson->version)) { + if (!isset($rootJson['version'])) { $magentoProductPackage = array_filter( - (array) $rootJson->require, + $rootJson['require'], function ($package) { return false !== strpos($package, 'magento/product-'); }, @@ -156,9 +169,15 @@ function ($package) { . '' ); $application->resetComposer(); + + return Cli::RETURN_FAILURE; } + + return Cli::RETURN_SUCCESS; } else { $output->writeln('' . 'There is no sample data for current set of modules.' . ''); + + return Cli::RETURN_FAILURE; } } @@ -189,15 +208,30 @@ private function createAuthFile() /** * Updates PHP memory limit * + * @throws InvalidArgumentException * @return void */ private function updateMemoryLimit() { if (function_exists('ini_set')) { - @ini_set('display_errors', 1); + $result = ini_alter('display_errors', 1); + if ($result === false) { + $error = error_get_last(); + throw new InvalidArgumentException(__( + 'Failed to set ini option display_errors to value 1. %1', + $error['message'] + )); + } $memoryLimit = trim(ini_get('memory_limit')); if ($memoryLimit != -1 && $this->getMemoryInBytes($memoryLimit) < 756 * 1024 * 1024) { - @ini_set('memory_limit', '756M'); + $result = ini_alter('memory_limit', '756M'); + if ($result === false) { + $error = error_get_last(); + throw new InvalidArgumentException(__( + 'Failed to set ini option memory_limit to 756M. %1', + $error['message'] + )); + } } } } diff --git a/app/code/Magento/SampleData/Test/Unit/Console/Command/AbstractSampleDataCommandTest.php b/app/code/Magento/SampleData/Test/Unit/Console/Command/AbstractSampleDataCommandTest.php index 10fe2f3c32fbd..8259bc45cce2a 100644 --- a/app/code/Magento/SampleData/Test/Unit/Console/Command/AbstractSampleDataCommandTest.php +++ b/app/code/Magento/SampleData/Test/Unit/Console/Command/AbstractSampleDataCommandTest.php @@ -26,6 +26,16 @@ */ abstract class AbstractSampleDataCommandTest extends TestCase { + /* + * Expected arguments for `composer config` to set missing field "version" + */ + private const STUB_EXPECTED_COMPOSER_CONFIG = [ + 'command' => 'config', + 'setting-key' => 'version', + 'setting-value' => ['0.0.1'], + '--quiet' => 1 + ]; + /** * @var ReadInterface|MockObject */ @@ -121,7 +131,7 @@ protected function setupMocks( ->withConsecutive( [ 'input' => new ArrayInput( - $this->expectedComposerArgumentsCommandConfig() + self::STUB_EXPECTED_COMPOSER_CONFIG ), 'output' => $this->anything() ], diff --git a/app/code/Magento/SampleData/Test/Unit/Console/Command/SampleDataDeployCommandTest.php b/app/code/Magento/SampleData/Test/Unit/Console/Command/SampleDataDeployCommandTest.php index 115dec67f9f73..16364c95ac81a 100644 --- a/app/code/Magento/SampleData/Test/Unit/Console/Command/SampleDataDeployCommandTest.php +++ b/app/code/Magento/SampleData/Test/Unit/Console/Command/SampleDataDeployCommandTest.php @@ -9,8 +9,10 @@ use Exception; use Magento\Framework\App\Filesystem\DirectoryList; +use Magento\Framework\Serialize\Serializer\Json; use Magento\SampleData\Console\Command\SampleDataDeployCommand; use Magento\Setup\Model\PackagesAuth; +use PHPUnit\Framework\MockObject\MockObject; use Symfony\Component\Console\Tester\CommandTester; /** @@ -18,6 +20,35 @@ */ class SampleDataDeployCommandTest extends AbstractSampleDataCommandTest { + /** + * @var Json|MockObject + */ + private $serializerMock; + + /** + * Creates mocks + * + * @return void + */ + protected function setUp(): void + { + parent::setUp(); + + $this->serializerMock = $this->createMock(Json::class); + } + + /** + * Sets mock for unserialization composer content + * @param array $composerJsonContent + * @return void + */ + protected function setupMockForSerializer(array $composerJsonContent): void + { + $this->serializerMock->expects($this->any()) + ->method('unserialize') + ->will($this->returnValue($composerJsonContent)); + } + /** * Sets mocks for auth file * @@ -63,6 +94,7 @@ public function testExecute( $composerJsonContent ); $this->setupMocksForAuthFile($authExist); + $this->setupMockForSerializer($composerJsonContent); $commandTester = $this->createCommandTester(); $commandTester->execute([]); @@ -94,6 +126,7 @@ public function testExecuteWithNoUpdate( ['--no-update' => 1] ); $this->setupMocksForAuthFile($authExist); + $this->setupMockForSerializer($composerJsonContent); $commandInput = ['--no-update' => 1]; $commandTester = $this->createCommandTester(); @@ -172,6 +205,12 @@ public function testExecuteWithException() ->method('readFile') ->with('composer.json') ->willReturn('{"require": {"magento/product-community-edition": "0.0.1"}, "version": "0.0.1"}'); + $this->serializerMock->expects($this->any()) + ->method('unserialize') + ->will($this->returnValue([ + 'require' => ["magento/product-community-edition" => "0.0.1"], + 'version' => '0.0.1' + ])); $this->filesystemMock->expects($this->once()) ->method('getDirectoryRead') ->with(DirectoryList::ROOT) @@ -208,26 +247,12 @@ private function createCommandTester(): CommandTester $this->filesystemMock, $this->sampleDataDependencyMock, $this->arrayInputFactoryMock, - $this->applicationFactoryMock + $this->applicationFactoryMock, + $this->serializerMock ) ); } - /** - * Expected arguments for `composer config` to set missing field "version" - * - * @return array - */ - protected function expectedComposerArgumentsCommandConfig(): array - { - return [ - 'command' => 'config', - 'setting-key' => 'version', - 'setting-value' => ['0.0.1'], - '--quiet' => 1 - ]; - } - /** * Returns expected arguments for command `composer require` * diff --git a/lib/internal/Magento/Framework/Exception/InvalidArgumentException.php b/lib/internal/Magento/Framework/Exception/InvalidArgumentException.php new file mode 100644 index 0000000000000..a92308ec41bde --- /dev/null +++ b/lib/internal/Magento/Framework/Exception/InvalidArgumentException.php @@ -0,0 +1,14 @@ + Date: Sat, 4 Apr 2020 13:00:16 +0300 Subject: [PATCH 012/126] Revert from function alias to original function ini_set --- .../SampleData/Console/Command/SampleDataDeployCommand.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/SampleData/Console/Command/SampleDataDeployCommand.php b/app/code/Magento/SampleData/Console/Command/SampleDataDeployCommand.php index d6c5901a25324..76159dc8320e1 100644 --- a/app/code/Magento/SampleData/Console/Command/SampleDataDeployCommand.php +++ b/app/code/Magento/SampleData/Console/Command/SampleDataDeployCommand.php @@ -214,7 +214,8 @@ private function createAuthFile() private function updateMemoryLimit() { if (function_exists('ini_set')) { - $result = ini_alter('display_errors', 1); + // phpcs:ignore Magento2.Functions.DiscouragedFunction + $result = ini_set('display_errors', 1); if ($result === false) { $error = error_get_last(); throw new InvalidArgumentException(__( @@ -224,7 +225,8 @@ private function updateMemoryLimit() } $memoryLimit = trim(ini_get('memory_limit')); if ($memoryLimit != -1 && $this->getMemoryInBytes($memoryLimit) < 756 * 1024 * 1024) { - $result = ini_alter('memory_limit', '756M'); + // phpcs:ignore Magento2.Functions.DiscouragedFunction + $result = ini_set('memory_limit', '756M'); if ($result === false) { $error = error_get_last(); throw new InvalidArgumentException(__( From 179f02caceffba1d53c9419d901674d3ad993cd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Tylek?= Date: Sat, 4 Apr 2020 19:01:44 +0200 Subject: [PATCH 013/126] Revert changes to greeting, keep only changes regarding duplicated footer --- .../Magento/Customer/view/frontend/email/change_email.html | 7 ++++--- .../view/frontend/email/change_email_and_password.html | 7 ++++--- .../Customer/view/frontend/email/password_reset.html | 7 ++++--- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/app/code/Magento/Customer/view/frontend/email/change_email.html b/app/code/Magento/Customer/view/frontend/email/change_email.html index 5341a2dc67ad5..f91f40078447b 100644 --- a/app/code/Magento/Customer/view/frontend/email/change_email.html +++ b/app/code/Magento/Customer/view/frontend/email/change_email.html @@ -8,12 +8,13 @@ {{template config_path="design/email/header_template"}} -

{{trans "%name," name=$customer.name}}

+

{{trans "Hello,"}}

+
+

{{trans "We have received a request to change the following information associated with your account at %store_name: email." store_name=$store.frontend_name}} {{trans 'If you have not authorized this action, please contact us immediately at %store_email' store_email=$store_email |raw}}{{depend store_phone}} {{trans 'or call us at %store_phone' store_phone=$store_phone |raw}}{{/depend}}. diff --git a/app/code/Magento/Customer/view/frontend/email/change_email_and_password.html b/app/code/Magento/Customer/view/frontend/email/change_email_and_password.html index ed2af7ada669e..f957cbe5b59a0 100644 --- a/app/code/Magento/Customer/view/frontend/email/change_email_and_password.html +++ b/app/code/Magento/Customer/view/frontend/email/change_email_and_password.html @@ -8,12 +8,13 @@ {{template config_path="design/email/header_template"}} -

{{trans "%name," name=$customer.name}}

+

{{trans "Hello,"}}

+
+

{{trans "We have received a request to change the following information associated with your account at %store_name: email, password." store_name=$store.frontend_name}} {{trans 'If you have not authorized this action, please contact us immediately at %store_email' store_email=$store_email |raw}}{{depend store_phone}} {{trans 'or call us at %store_phone' store_phone=$store_phone |raw}}{{/depend}}. diff --git a/app/code/Magento/Customer/view/frontend/email/password_reset.html b/app/code/Magento/Customer/view/frontend/email/password_reset.html index a6c54842a1573..ce9cd02ba72ea 100644 --- a/app/code/Magento/Customer/view/frontend/email/password_reset.html +++ b/app/code/Magento/Customer/view/frontend/email/password_reset.html @@ -9,12 +9,13 @@ "var customer.name":"Customer Name", "var store.frontend_name":"Store Name", "var store_email":"Store Email", -"var store_phone":"Store Phone", -"var customer.name":"Customer Name" +"var store_phone":"Store Phone" } @--> {{template config_path="design/email/header_template"}} -

{{trans "%name," name=$customer.name}}

+

{{trans "Hello,"}}

+
+

{{trans "We have received a request to change the following information associated with your account at %store_name: password." store_name=$store.frontend_name}} {{trans 'If you have not authorized this action, please contact us immediately at %store_email' store_email=$store_email |raw}}{{depend store_phone}} {{trans 'or call us at %store_phone' store_phone=$store_phone |raw}}{{/depend}}. From a216e7fc93ee015a0128aadebbd1c7ee722a5299 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Tylek?= Date: Sat, 4 Apr 2020 19:08:12 +0200 Subject: [PATCH 014/126] Revert changes to test --- .../Magento/Newsletter/Model/SubscriberTest.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Newsletter/Model/SubscriberTest.php b/dev/tests/integration/testsuite/Magento/Newsletter/Model/SubscriberTest.php index d2248737679c0..06c8902f45897 100644 --- a/dev/tests/integration/testsuite/Magento/Newsletter/Model/SubscriberTest.php +++ b/dev/tests/integration/testsuite/Magento/Newsletter/Model/SubscriberTest.php @@ -88,7 +88,7 @@ public function testUnsubscribeSubscribe(): void $this->assertSame($subscriber, $subscriber->loadByCustomerId(1)); $this->assertEquals($subscriber, $subscriber->unsubscribe()); $this->assertContains( - '

You have been unsubscribed from the newsletter.

', + 'You have been unsubscribed from the newsletter.', $this->transportBuilder->getSentMessage()->getRawMessage() ); $this->assertEquals(Subscriber::STATUS_UNSUBSCRIBED, $subscriber->getSubscriberStatus()); @@ -96,7 +96,7 @@ public function testUnsubscribeSubscribe(): void $this->assertEquals(Subscriber::STATUS_SUBSCRIBED, $subscriber->subscribe('customer@example.com')); $this->assertEquals(Subscriber::STATUS_SUBSCRIBED, $subscriber->getSubscriberStatus()); $this->assertContains( - '

You have been successfully subscribed to our newsletter.

', + 'You have been successfully subscribed to our newsletter.', $this->transportBuilder->getSentMessage()->getRawMessage() ); } @@ -115,14 +115,14 @@ public function testUnsubscribeSubscribeByCustomerId(): void $this->assertSame($subscriber, $subscriber->unsubscribeCustomerById(1)); $this->assertEquals(Subscriber::STATUS_UNSUBSCRIBED, $subscriber->getSubscriberStatus()); $this->assertContains( - '

You have been unsubscribed from the newsletter.

', + 'You have been unsubscribed from the newsletter.', $this->transportBuilder->getSentMessage()->getRawMessage() ); // Subscribe and verify $this->assertSame($subscriber, $subscriber->subscribeCustomerById(1)); $this->assertEquals(Subscriber::STATUS_SUBSCRIBED, $subscriber->getSubscriberStatus()); $this->assertContains( - '

You have been successfully subscribed to our newsletter.

', + 'You have been successfully subscribed to our newsletter.', $this->transportBuilder->getSentMessage()->getRawMessage() ); } @@ -142,7 +142,7 @@ public function testConfirm(): void $subscriber->loadByEmail($customerEmail); $subscriber->confirm($subscriber->getSubscriberConfirmCode()); $this->assertContains( - '

You have been successfully subscribed to our newsletter.

', + 'You have been successfully subscribed to our newsletter.', $this->transportBuilder->getSentMessage()->getRawMessage() ); } From 2bfb191c91a0870c1756bc2c18c25a8af2f92c5f Mon Sep 17 00:00:00 2001 From: Andrii Beziazychnyi Date: Sat, 4 Apr 2020 20:43:53 +0300 Subject: [PATCH 015/126] Fixed tests according to request from issue-27500 --- .../Console/Command/SampleDataDeployCommandTest.php | 12 +++++++----- .../Console/Command/SampleDataRemoveCommandTest.php | 2 +- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/SampleData/Test/Unit/Console/Command/SampleDataDeployCommandTest.php b/app/code/Magento/SampleData/Test/Unit/Console/Command/SampleDataDeployCommandTest.php index 16364c95ac81a..971e1996e95c2 100644 --- a/app/code/Magento/SampleData/Test/Unit/Console/Command/SampleDataDeployCommandTest.php +++ b/app/code/Magento/SampleData/Test/Unit/Console/Command/SampleDataDeployCommandTest.php @@ -140,7 +140,7 @@ public function testExecuteWithNoUpdate( * * @return array */ - public function processDataProvider() + public function processDataProvider(): array { return [ 'No sample data found' => [ @@ -195,12 +195,14 @@ public function processDataProvider() } /** - * @expectedException Exception - * @expectedExceptionMessage Error in writing Auth file path/to/auth.json. Please check permissions for writing. * @return void */ - public function testExecuteWithException() + public function testExecuteWithException(): void { + $this->expectException(Exception::class); + $this->expectExceptionMessage( + 'Error in writing Auth file path/to/auth.json. Please check permissions for writing.' + ); $this->directoryReadMock->expects($this->once()) ->method('readFile') ->with('composer.json') @@ -263,7 +265,7 @@ private function createCommandTester(): CommandTester protected function expectedComposerArgumentsSampleDataCommands( array $sampleDataPackages, string $pathToComposerJson - ) : array { + ): array { return [ 'command' => 'require', '--working-dir' => $pathToComposerJson, diff --git a/app/code/Magento/SampleData/Test/Unit/Console/Command/SampleDataRemoveCommandTest.php b/app/code/Magento/SampleData/Test/Unit/Console/Command/SampleDataRemoveCommandTest.php index aa720f87a84e0..9883100ce5c49 100644 --- a/app/code/Magento/SampleData/Test/Unit/Console/Command/SampleDataRemoveCommandTest.php +++ b/app/code/Magento/SampleData/Test/Unit/Console/Command/SampleDataRemoveCommandTest.php @@ -77,7 +77,7 @@ public function testExecuteWithNoUpdate( * * @return array */ - public function processDataProvider() + public function processDataProvider(): array { return [ 'No sample data found in require' => [ From 2c1daf37da116b93f2453bb4167585c5c1423669 Mon Sep 17 00:00:00 2001 From: Mateusz Krzeszowiak Date: Sun, 5 Apr 2020 10:08:26 +0200 Subject: [PATCH 016/126] Load polyfills for browsers that don't support certain features --- .../Magento/Ui/view/base/requirejs-config.js | 25 +++++++++++++++++++ .../Ui/view/base/web/js/lib/core/events.js | 3 +-- .../js/lib/knockout/extender/bound-nodes.js | 3 +-- .../view/base/web/js/lib/registry/registry.js | 3 +-- .../web/js/lib/view/utils/dom-observer.js | 1 - .../Ui/view/base/web/js/lib/view/utils/raf.js | 4 +-- 6 files changed, 29 insertions(+), 10 deletions(-) diff --git a/app/code/Magento/Ui/view/base/requirejs-config.js b/app/code/Magento/Ui/view/base/requirejs-config.js index 5e76600673254..91acac0380d6b 100644 --- a/app/code/Magento/Ui/view/base/requirejs-config.js +++ b/app/code/Magento/Ui/view/base/requirejs-config.js @@ -4,6 +4,7 @@ */ var config = { + deps: [], shim: { 'chartjs/Chart.min': ['moment'], 'tiny_mce_4/tinymce.min': { @@ -30,3 +31,27 @@ var config = { } } }; + +/** + * Adds polyfills only for browser contexts which prevents bundlers from including them. + */ +if (typeof window !== "undefined" && window.document) { + /** + * Polyfill Map and WeakMap for older browsers that do not support them. + */ + if (typeof Map === 'undefined' || typeof WeakMap === 'undefined'){ + config.deps.push('es6-collections'); + } + /** + * Polyfill MutationObserver only for the browsers that do not support it. + */ + if (typeof MutationObserver === 'undefined') { + config.deps.push('MutationObserver'); + } + /** + * Polyfill FormData object for old browsers that don't have full support for it. + */ + if (typeof FormData === 'undefined' || typeof FormData.prototype.get === 'undefined') { + config.deps.push('FormData'); + } +} diff --git a/app/code/Magento/Ui/view/base/web/js/lib/core/events.js b/app/code/Magento/Ui/view/base/web/js/lib/core/events.js index fdb11cd89f361..15965fba1ad2d 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/core/events.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/core/events.js @@ -6,8 +6,7 @@ /* global WeakMap, Map*/ define([ 'ko', - 'underscore', - 'es6-collections' + 'underscore' ], function (ko, _) { 'use strict'; diff --git a/app/code/Magento/Ui/view/base/web/js/lib/knockout/extender/bound-nodes.js b/app/code/Magento/Ui/view/base/web/js/lib/knockout/extender/bound-nodes.js index 6b3c437b90508..0b80a75bf0c18 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/knockout/extender/bound-nodes.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/knockout/extender/bound-nodes.js @@ -8,8 +8,7 @@ define([ 'ko', 'underscore', 'mage/utils/wrapper', - 'uiEvents', - 'es6-collections' + 'uiEvents' ], function (ko, _, wrapper, Events) { 'use strict'; diff --git a/app/code/Magento/Ui/view/base/web/js/lib/registry/registry.js b/app/code/Magento/Ui/view/base/web/js/lib/registry/registry.js index 826e8ec8c33b4..18e05b8daac68 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/registry/registry.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/registry/registry.js @@ -9,8 +9,7 @@ /* global WeakMap */ define([ 'jquery', - 'underscore', - 'es6-collections' + 'underscore' ], function ($, _) { 'use strict'; diff --git a/app/code/Magento/Ui/view/base/web/js/lib/view/utils/dom-observer.js b/app/code/Magento/Ui/view/base/web/js/lib/view/utils/dom-observer.js index f8e752fb77af2..cb9f5b13de494 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/view/utils/dom-observer.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/view/utils/dom-observer.js @@ -5,7 +5,6 @@ define([ 'jquery', 'underscore', - 'MutationObserver', 'domReady!' ], function ($, _) { 'use strict'; diff --git a/app/code/Magento/Ui/view/base/web/js/lib/view/utils/raf.js b/app/code/Magento/Ui/view/base/web/js/lib/view/utils/raf.js index 3ec0996543c7d..bc8e3095b5cd2 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/view/utils/raf.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/view/utils/raf.js @@ -4,9 +4,7 @@ */ /* global WeakMap */ -define([ - 'es6-collections' -], function () { +define([], function () { 'use strict'; var processMap = new WeakMap(), From cba9d4637ab7200b2fa5ad690384b6ccbab1db37 Mon Sep 17 00:00:00 2001 From: Mateusz Krzeszowiak Date: Sun, 5 Apr 2020 10:31:37 +0200 Subject: [PATCH 017/126] Load storage polyfill conditionally --- .../Theme/view/base/requirejs-config.js | 35 ++++++++++++++----- .../frontend/layout/default_head_blocks.xml | 1 - 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/app/code/Magento/Theme/view/base/requirejs-config.js b/app/code/Magento/Theme/view/base/requirejs-config.js index f5580461f7d9e..7da527b691db5 100644 --- a/app/code/Magento/Theme/view/base/requirejs-config.js +++ b/app/code/Magento/Theme/view/base/requirejs-config.js @@ -4,8 +4,8 @@ */ var config = { - 'waitSeconds': 0, - 'map': { + waitSeconds: 0, + map: { '*': { 'ko': 'knockoutjs/knockout', 'knockout': 'knockoutjs/knockout', @@ -13,7 +13,7 @@ var config = { 'rjsResolver': 'mage/requirejs/resolver' } }, - 'shim': { + shim: { 'jquery/jquery-migrate': ['jquery'], 'jquery/jstree/jquery.hotkeys': ['jquery'], 'jquery/hover-intent': ['jquery'], @@ -28,7 +28,7 @@ var config = { }, 'magnifier/magnifier': ['jquery'] }, - 'paths': { + paths: { 'jquery/validate': 'jquery/jquery.validate', 'jquery/hover-intent': 'jquery/jquery.hoverIntent', 'jquery/file-uploader': 'jquery/fileUploader/jquery.fileupload-fp', @@ -40,11 +40,11 @@ var config = { 'tinycolor': 'jquery/spectrum/tinycolor', 'jquery-ui-modules': 'jquery/ui-modules' }, - 'deps': [ + deps: [ 'jquery/jquery-migrate' ], - 'config': { - 'mixins': { + config: { + mixins: { 'jquery/jstree/jquery.jstree': { 'mage/backend/jstree-mixin': true }, @@ -52,7 +52,7 @@ var config = { 'jquery/patches/jquery': true } }, - 'text': { + text: { 'headers': { 'X-Requested-With': 'XMLHttpRequest' } @@ -60,6 +60,25 @@ var config = { } }; +/** + * Adds polyfills only for browser contexts which prevents bundlers from including them. + */ +if (typeof window !== "undefined" && window.document) { + /** + * Polyfill localStorage and sessionStorage for browsers that do not support them. + */ + try { + if (!window.localStorage || !window.sessionStorage) { + throw new Error(); + } + + localStorage.setItem('storage_test', 1); + localStorage.removeItem('storage_test'); + } catch (e) { + config.deps.push('mage/polyfill'); + } +} + require(['jquery'], function ($) { 'use strict'; diff --git a/app/code/Magento/Theme/view/frontend/layout/default_head_blocks.xml b/app/code/Magento/Theme/view/frontend/layout/default_head_blocks.xml index a4a10ef3f6ee9..96f8fbed4c041 100644 --- a/app/code/Magento/Theme/view/frontend/layout/default_head_blocks.xml +++ b/app/code/Magento/Theme/view/frontend/layout/default_head_blocks.xml @@ -10,7 +10,6 @@