From b271dd889363992514d1555ab9bd21ddfdb7b41d Mon Sep 17 00:00:00 2001 From: Rik Willems Date: Wed, 21 Nov 2018 16:28:44 +0100 Subject: [PATCH 01/65] CLA force push commit --- app/code/Magento/Sales/Setup/UpgradeData.php | 125 ++++++++++++------- 1 file changed, 81 insertions(+), 44 deletions(-) diff --git a/app/code/Magento/Sales/Setup/UpgradeData.php b/app/code/Magento/Sales/Setup/UpgradeData.php index 77b96791e8cea..83f239546960e 100644 --- a/app/code/Magento/Sales/Setup/UpgradeData.php +++ b/app/code/Magento/Sales/Setup/UpgradeData.php @@ -14,9 +14,7 @@ use Magento\Framework\Setup\ModuleContextInterface; use Magento\Framework\Setup\ModuleDataSetupInterface; use Magento\Framework\Setup\UpgradeDataInterface; -use Magento\Quote\Model\QuoteFactory; -use Magento\Sales\Model\OrderFactory; -use Magento\Sales\Model\ResourceModel\Order\Address\CollectionFactory as AddressCollectionFactory; +use Magento\Sales\Model\Order\Address; /** * Data upgrade script @@ -42,21 +40,6 @@ class UpgradeData implements UpgradeDataInterface */ private $aggregatedFieldConverter; - /** - * @var AddressCollectionFactory - */ - private $addressCollectionFactory; - - /** - * @var OrderFactory - */ - private $orderFactory; - - /** - * @var QuoteFactory - */ - private $quoteFactory; - /** * @var State */ @@ -66,26 +49,17 @@ class UpgradeData implements UpgradeDataInterface * @param SalesSetupFactory $salesSetupFactory * @param Config $eavConfig * @param AggregatedFieldDataConverter $aggregatedFieldConverter - * @param AddressCollectionFactory $addressCollFactory - * @param OrderFactory $orderFactory - * @param QuoteFactory $quoteFactory * @param State $state */ public function __construct( SalesSetupFactory $salesSetupFactory, Config $eavConfig, AggregatedFieldDataConverter $aggregatedFieldConverter, - AddressCollectionFactory $addressCollFactory, - OrderFactory $orderFactory, - QuoteFactory $quoteFactory, State $state ) { $this->salesSetupFactory = $salesSetupFactory; $this->eavConfig = $eavConfig; $this->aggregatedFieldConverter = $aggregatedFieldConverter; - $this->addressCollectionFactory = $addressCollFactory; - $this->orderFactory = $orderFactory; - $this->quoteFactory = $quoteFactory; $this->state = $state; } @@ -125,6 +99,7 @@ public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface * @param string $setupVersion * @param SalesSetup $salesSetup * @return void + * @throws \Magento\Framework\DB\FieldDataConversionException */ private function convertSerializedDataToJson($setupVersion, SalesSetup $salesSetup) { @@ -173,32 +148,94 @@ private function convertSerializedDataToJson($setupVersion, SalesSetup $salesSet /** * Fill quote_address_id in table sales_order_address if it is empty. - * * @param ModuleDataSetupInterface $setup */ public function fillQuoteAddressIdInSalesOrderAddress(ModuleDataSetupInterface $setup) { - $addressTable = $setup->getTable('sales_order_address'); - $updateOrderAddress = $setup->getConnection() + $this->fillQuoteAddressIdInSalesOrderAddressByType($setup, Address::TYPE_SHIPPING); + $this->fillQuoteAddressIdInSalesOrderAddressByType($setup, Address::TYPE_BILLING); + } + + /** + * @param ModuleDataSetupInterface $setup + * @param string $addressType + */ + public function fillQuoteAddressIdInSalesOrderAddressByType(ModuleDataSetupInterface $setup, $addressType) + { + $salesConnection = $setup->getConnection('sales'); + + $orderTable = $setup->getTable('sales_order', 'sales'); + $orderAddressTable = $setup->getTable('sales_order_address', 'sales'); + + $query = $salesConnection ->select() + ->from( + ['sales_order_address' => $orderAddressTable], + ['entity_id', 'address_type'] + ) ->joinInner( - ['sales_order' => $setup->getTable('sales_order')], - $addressTable . '.parent_id = sales_order.entity_id', - ['quote_address_id' => 'quote_address.address_id'] + ['sales_order' => $orderTable], + 'sales_order_address.parent_id = sales_order.entity_id', + ['quote_id' => 'sales_order.quote_id'] + ) + ->where('sales_order_address.quote_address_id IS NULL') + ->where('sales_order_address.address_type = ?', $addressType) + ->order('sales_order_address.entity_id'); + + $batchSize = 5000; + $result = $salesConnection->query($query); + $count = $result->rowCount(); + $batches = ceil($count / $batchSize); + + for ($batch = $batches; $batch > 0; $batch--) { + $query->limitPage($batch, $batchSize); + $result = $salesConnection->fetchAssoc($query); + + $this->fillQuoteAddressIdInSalesOrderAddressProcessBatch($setup, $result, $addressType); + } + } + /** + * @param ModuleDataSetupInterface $setup + * @param array $orderAddresses + * @param string $addressType + */ + public function fillQuoteAddressIdInSalesOrderAddressProcessBatch( + ModuleDataSetupInterface $setup, + array $orderAddresses, + $addressType + ) { + $salesConnection = $setup->getConnection('sales'); + $quoteConnection = $setup->getConnection('checkout'); + + $quoteAddressTable = $setup->getTable('quote_address', 'checkout'); + $quoteTable = $setup->getTable('quote', 'checkout'); + $salesOrderAddressTable = $setup->getTable('sales_order_address', 'sales'); + + $query = $quoteConnection + ->select() + ->from( + ['quote_address' => $quoteAddressTable], + ['quote_id', 'address_id'] ) ->joinInner( - ['quote_address' => $setup->getTable('quote_address')], - 'sales_order.quote_id = quote_address.quote_id - AND ' . $addressTable . '.address_type = quote_address.address_type', + ['quote' => $quoteTable], + 'quote_address.quote_id = quote.entity_id', [] ) - ->where( - $addressTable . '.quote_address_id IS NULL' - ); - $updateOrderAddress = $setup->getConnection()->updateFromSelect( - $updateOrderAddress, - $addressTable - ); - $setup->getConnection()->query($updateOrderAddress); + ->where('quote.entity_id in (?)', array_column($orderAddresses, 'quote_id')) + ->where('address_type = ?', $addressType); + + $quoteAddresses = $quoteConnection->fetchAssoc($query); + + foreach ($orderAddresses as $orderAddress) { + $bind = [ + 'quote_address_id' => $quoteAddresses[$orderAddress['quote_id']]['address_id'] ?? null, + ]; + $where = [ + 'orderAddressId' => $orderAddress['entity_id'] + ]; + + $salesConnection->update($salesOrderAddressTable, $bind, $where); + } } } From f0a92f2a2ad7e6a8f6c03b7bded7b2092561f07b Mon Sep 17 00:00:00 2001 From: Suneet Date: Tue, 4 Dec 2018 22:52:34 +0530 Subject: [PATCH 02/65] Resolved upgrade issue if manufacturer attribute missing --- .../ConfigurableProduct/Setup/InstallData.php | 24 ++++++++++--------- .../ConfigurableProduct/Setup/UpgradeData.php | 23 +++++++++++------- 2 files changed, 27 insertions(+), 20 deletions(-) diff --git a/app/code/Magento/ConfigurableProduct/Setup/InstallData.php b/app/code/Magento/ConfigurableProduct/Setup/InstallData.php index 1c26f159405dd..f9c94cc684b0d 100644 --- a/app/code/Magento/ConfigurableProduct/Setup/InstallData.php +++ b/app/code/Magento/ConfigurableProduct/Setup/InstallData.php @@ -57,18 +57,20 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface 'color' ]; foreach ($attributes as $attributeCode) { - $relatedProductTypes = explode( - ',', - $eavSetup->getAttribute(\Magento\Catalog\Model\Product::ENTITY, $attributeCode, 'apply_to') - ); - if (!in_array(Configurable::TYPE_CODE, $relatedProductTypes)) { - $relatedProductTypes[] = Configurable::TYPE_CODE; - $eavSetup->updateAttribute( - \Magento\Catalog\Model\Product::ENTITY, - $attributeCode, - 'apply_to', - implode(',', $relatedProductTypes) + if ($attribute = $eavSetup->getAttribute(\Magento\Catalog\Model\Product::ENTITY, $attributeCode, 'apply_to')) { + $relatedProductTypes = explode( + ',', + $attribute ); + if (!in_array(Configurable::TYPE_CODE, $relatedProductTypes)) { + $relatedProductTypes[] = Configurable::TYPE_CODE; + $eavSetup->updateAttribute( + \Magento\Catalog\Model\Product::ENTITY, + $attributeCode, + 'apply_to', + implode(',', $relatedProductTypes) + ); + } } } } diff --git a/app/code/Magento/ConfigurableProduct/Setup/UpgradeData.php b/app/code/Magento/ConfigurableProduct/Setup/UpgradeData.php index 1ff78a632c3bb..c71bb95a584c5 100644 --- a/app/code/Magento/ConfigurableProduct/Setup/UpgradeData.php +++ b/app/code/Magento/ConfigurableProduct/Setup/UpgradeData.php @@ -47,16 +47,18 @@ public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface if (version_compare($context->getVersion(), '2.2.0') < 0) { $relatedProductTypes = $this->getRelatedProductTypes('tier_price', $eavSetup); - $key = array_search(Configurable::TYPE_CODE, $relatedProductTypes); - if ($key !== false) { - unset($relatedProductTypes[$key]); - $this->updateRelatedProductTypes('tier_price', $relatedProductTypes, $eavSetup); + if (!empty($relatedProductTypes)) { + $key = array_search(Configurable::TYPE_CODE, $relatedProductTypes); + if ($key !== false) { + unset($relatedProductTypes[$key]); + $this->updateRelatedProductTypes('tier_price', $relatedProductTypes, $eavSetup); + } } } if (version_compare($context->getVersion(), '2.2.1') < 0) { $relatedProductTypes = $this->getRelatedProductTypes('manufacturer', $eavSetup); - if (!in_array(Configurable::TYPE_CODE, $relatedProductTypes)) { + if (!empty($relatedProductTypes) && !in_array(Configurable::TYPE_CODE, $relatedProductTypes)) { $relatedProductTypes[] = Configurable::TYPE_CODE; $this->updateRelatedProductTypes('manufacturer', $relatedProductTypes, $eavSetup); } @@ -78,10 +80,13 @@ public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface */ private function getRelatedProductTypes(string $attributeId, EavSetup $eavSetup) { - return explode( - ',', - $eavSetup->getAttribute(Product::ENTITY, $attributeId, 'apply_to') - ); + if($attribute = $eavSetup->getAttribute(Product::ENTITY, $attributeId, 'apply_to')) { + return explode( + ',', + $attribute + ); + } + return []; } /** From dbf5293d42f7f88eae47913b746278cf16045914 Mon Sep 17 00:00:00 2001 From: Suneet Date: Tue, 4 Dec 2018 23:35:35 +0530 Subject: [PATCH 03/65] Fixed code style as per the review --- app/code/Magento/ConfigurableProduct/Setup/InstallData.php | 5 ++++- app/code/Magento/ConfigurableProduct/Setup/UpgradeData.php | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/ConfigurableProduct/Setup/InstallData.php b/app/code/Magento/ConfigurableProduct/Setup/InstallData.php index f9c94cc684b0d..2d6f6579059bc 100644 --- a/app/code/Magento/ConfigurableProduct/Setup/InstallData.php +++ b/app/code/Magento/ConfigurableProduct/Setup/InstallData.php @@ -57,7 +57,10 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface 'color' ]; foreach ($attributes as $attributeCode) { - if ($attribute = $eavSetup->getAttribute(\Magento\Catalog\Model\Product::ENTITY, $attributeCode, 'apply_to')) { + if ($attribute = $eavSetup->getAttribute( + \Magento\Catalog\Model\Product::ENTITY, + $attributeCode, 'apply_to' + )) { $relatedProductTypes = explode( ',', $attribute diff --git a/app/code/Magento/ConfigurableProduct/Setup/UpgradeData.php b/app/code/Magento/ConfigurableProduct/Setup/UpgradeData.php index c71bb95a584c5..8724e244a1fd0 100644 --- a/app/code/Magento/ConfigurableProduct/Setup/UpgradeData.php +++ b/app/code/Magento/ConfigurableProduct/Setup/UpgradeData.php @@ -80,7 +80,10 @@ public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface */ private function getRelatedProductTypes(string $attributeId, EavSetup $eavSetup) { - if($attribute = $eavSetup->getAttribute(Product::ENTITY, $attributeId, 'apply_to')) { + if ($attribute = $eavSetup->getAttribute( + Product::ENTITY, + $attributeId, 'apply_to' + )) { return explode( ',', $attribute From 94a3402605fa3d8fc74b025095d292616002b33d Mon Sep 17 00:00:00 2001 From: Stjepan Udovicic Date: Tue, 4 Dec 2018 19:24:45 +0100 Subject: [PATCH 04/65] Fix typo in SQL join --- .../Model/ResourceModel/Product/Indexer/Price/DefaultPrice.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Price/DefaultPrice.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Price/DefaultPrice.php index 7ea85cd3f6f10..8fdeaf00b804f 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Price/DefaultPrice.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Price/DefaultPrice.php @@ -604,7 +604,7 @@ protected function _applyCustomOption() [] )->joinLeft( ['otps' => $this->getTable('catalog_product_option_type_price')], - 'otps.option_type_id = otpd.option_type_id AND otpd.store_id = cs.store_id', + 'otps.option_type_id = otpd.option_type_id AND otps.store_id = cs.store_id', [] )->group( ['i.entity_id', 'i.customer_group_id', 'i.website_id', 'o.option_id'] From 4567a1a95fdd8a4089c808cfd12895de4db1d0e5 Mon Sep 17 00:00:00 2001 From: Suneet Date: Wed, 5 Dec 2018 10:01:14 +0530 Subject: [PATCH 05/65] Fixed code style --- app/code/Magento/ConfigurableProduct/Setup/InstallData.php | 3 ++- app/code/Magento/ConfigurableProduct/Setup/UpgradeData.php | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/ConfigurableProduct/Setup/InstallData.php b/app/code/Magento/ConfigurableProduct/Setup/InstallData.php index 2d6f6579059bc..57cc287aa24aa 100644 --- a/app/code/Magento/ConfigurableProduct/Setup/InstallData.php +++ b/app/code/Magento/ConfigurableProduct/Setup/InstallData.php @@ -59,7 +59,8 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface foreach ($attributes as $attributeCode) { if ($attribute = $eavSetup->getAttribute( \Magento\Catalog\Model\Product::ENTITY, - $attributeCode, 'apply_to' + $attributeCode, + 'apply_to' )) { $relatedProductTypes = explode( ',', diff --git a/app/code/Magento/ConfigurableProduct/Setup/UpgradeData.php b/app/code/Magento/ConfigurableProduct/Setup/UpgradeData.php index 8724e244a1fd0..113839e57791d 100644 --- a/app/code/Magento/ConfigurableProduct/Setup/UpgradeData.php +++ b/app/code/Magento/ConfigurableProduct/Setup/UpgradeData.php @@ -82,7 +82,8 @@ private function getRelatedProductTypes(string $attributeId, EavSetup $eavSetup) { if ($attribute = $eavSetup->getAttribute( Product::ENTITY, - $attributeId, 'apply_to' + $attributeId, + 'apply_to' )) { return explode( ',', From 0935782d1e27027299446103e819edbf76db5259 Mon Sep 17 00:00:00 2001 From: Stjepan Udovicic Date: Sun, 16 Dec 2018 00:07:48 +0100 Subject: [PATCH 06/65] Fix typo in SQL for CustomOptionPriceModifier --- .../Product/Indexer/Price/CustomOptionPriceModifier.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Price/CustomOptionPriceModifier.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Price/CustomOptionPriceModifier.php index 646cd0d4c1a4c..0ca13855cf896 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Price/CustomOptionPriceModifier.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Price/CustomOptionPriceModifier.php @@ -211,7 +211,7 @@ private function getSelectForOptionsWithMultipleValues(string $sourceTable): Sel } else { $select->joinLeft( ['otps' => $this->getTable('catalog_product_option_type_price')], - 'otps.option_type_id = otpd.option_type_id AND otpd.store_id = cwd.default_store_id', + 'otps.option_type_id = otpd.option_type_id AND otps.store_id = cwd.default_store_id', [] ); From 0b0dcfb9c7a943045d7724ee1832da2cbd3e04ff Mon Sep 17 00:00:00 2001 From: Ihor Sviziev Date: Tue, 22 Jan 2019 16:25:51 +0200 Subject: [PATCH 07/65] magento/magento2#19098 2.2.6 Use batches and direct queries to fix sales address upgrade Revert not needed changes --- app/code/Magento/Sales/Setup/UpgradeData.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/app/code/Magento/Sales/Setup/UpgradeData.php b/app/code/Magento/Sales/Setup/UpgradeData.php index 83f239546960e..b35632d6e12d2 100644 --- a/app/code/Magento/Sales/Setup/UpgradeData.php +++ b/app/code/Magento/Sales/Setup/UpgradeData.php @@ -14,7 +14,10 @@ use Magento\Framework\Setup\ModuleContextInterface; use Magento\Framework\Setup\ModuleDataSetupInterface; use Magento\Framework\Setup\UpgradeDataInterface; +use Magento\Quote\Model\QuoteFactory; use Magento\Sales\Model\Order\Address; +use Magento\Sales\Model\OrderFactory; +use Magento\Sales\Model\ResourceModel\Order\Address\CollectionFactory as AddressCollectionFactory; /** * Data upgrade script @@ -49,12 +52,18 @@ class UpgradeData implements UpgradeDataInterface * @param SalesSetupFactory $salesSetupFactory * @param Config $eavConfig * @param AggregatedFieldDataConverter $aggregatedFieldConverter + * @param AddressCollectionFactory $addressCollFactory + * @param OrderFactory $orderFactory + * @param QuoteFactory $quoteFactory * @param State $state */ public function __construct( SalesSetupFactory $salesSetupFactory, Config $eavConfig, AggregatedFieldDataConverter $aggregatedFieldConverter, + AddressCollectionFactory $addressCollFactory, + OrderFactory $orderFactory, + QuoteFactory $quoteFactory, State $state ) { $this->salesSetupFactory = $salesSetupFactory; From 4a9a98a9b6548cecb4c479e7cfb567faa51825d7 Mon Sep 17 00:00:00 2001 From: Ihor Sviziev Date: Wed, 30 Jan 2019 08:30:56 +0200 Subject: [PATCH 08/65] magento/magento2#19098 2.2.6 Use batches and direct queries to fix sales address upgrade Fix static test failures --- app/code/Magento/Sales/Setup/UpgradeData.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/code/Magento/Sales/Setup/UpgradeData.php b/app/code/Magento/Sales/Setup/UpgradeData.php index b35632d6e12d2..0b69458b7656c 100644 --- a/app/code/Magento/Sales/Setup/UpgradeData.php +++ b/app/code/Magento/Sales/Setup/UpgradeData.php @@ -49,6 +49,8 @@ class UpgradeData implements UpgradeDataInterface private $state; /** + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + * * @param SalesSetupFactory $salesSetupFactory * @param Config $eavConfig * @param AggregatedFieldDataConverter $aggregatedFieldConverter From 7c6026e2f62e5edd35b0f75877b556b07801e598 Mon Sep 17 00:00:00 2001 From: Ihor Sviziev Date: Wed, 30 Jan 2019 09:13:37 +0200 Subject: [PATCH 09/65] magento/magento2#19098 2.2.6 Use batches and direct queries to fix sales address upgrade Fix statis test failures --- app/code/Magento/Sales/Setup/UpgradeData.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Sales/Setup/UpgradeData.php b/app/code/Magento/Sales/Setup/UpgradeData.php index 0b69458b7656c..56cbf31c3d695 100644 --- a/app/code/Magento/Sales/Setup/UpgradeData.php +++ b/app/code/Magento/Sales/Setup/UpgradeData.php @@ -171,7 +171,7 @@ public function fillQuoteAddressIdInSalesOrderAddress(ModuleDataSetupInterface $ * @param ModuleDataSetupInterface $setup * @param string $addressType */ - public function fillQuoteAddressIdInSalesOrderAddressByType(ModuleDataSetupInterface $setup, $addressType) + private function fillQuoteAddressIdInSalesOrderAddressByType(ModuleDataSetupInterface $setup, $addressType) { $salesConnection = $setup->getConnection('sales'); @@ -205,12 +205,13 @@ public function fillQuoteAddressIdInSalesOrderAddressByType(ModuleDataSetupInter $this->fillQuoteAddressIdInSalesOrderAddressProcessBatch($setup, $result, $addressType); } } + /** * @param ModuleDataSetupInterface $setup * @param array $orderAddresses * @param string $addressType */ - public function fillQuoteAddressIdInSalesOrderAddressProcessBatch( + private function fillQuoteAddressIdInSalesOrderAddressProcessBatch( ModuleDataSetupInterface $setup, array $orderAddresses, $addressType From c60d395347569dd4feb3be07dab5b8a5738b6e85 Mon Sep 17 00:00:00 2001 From: Ihor Sviziev Date: Fri, 1 Feb 2019 09:22:04 +0200 Subject: [PATCH 10/65] magento/magento2#19098 2.2.6 Use batches and direct queries to fix sales address upgrade Fix static test failure --- app/code/Magento/Sales/Setup/UpgradeData.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Sales/Setup/UpgradeData.php b/app/code/Magento/Sales/Setup/UpgradeData.php index 56cbf31c3d695..0f9833ed8f7f2 100644 --- a/app/code/Magento/Sales/Setup/UpgradeData.php +++ b/app/code/Magento/Sales/Setup/UpgradeData.php @@ -50,7 +50,7 @@ class UpgradeData implements UpgradeDataInterface /** * @SuppressWarnings(PHPMD.UnusedFormalParameter) - * + * * @param SalesSetupFactory $salesSetupFactory * @param Config $eavConfig * @param AggregatedFieldDataConverter $aggregatedFieldConverter From 115b1bcbd38495e269ada16e0515b883104a7f7f Mon Sep 17 00:00:00 2001 From: Myroslav Dobra Date: Tue, 12 Feb 2019 15:38:52 +0200 Subject: [PATCH 11/65] MAGETWO-96636: MFTF test fix --- ...efrontBraintreeFillCardDataActionGroup.xml | 32 +++++++++++++++++++ .../Test/Mftf/Data/BraintreeData.xml | 3 +- ...ntBraintreePaymentConfigurationSection.xml | 24 ++++++++++++++ .../Data/ProductConfigurableAttributeData.xml | 2 +- .../AdminCreditMemoActionGroup.xml | 27 ++++++++++++++++ .../Section/AdminCreditMemoTotalSection.xml | 4 ++- .../AdminOrderDetailsMainActionsSection.xml | 2 +- .../Section/AdminOrderViewTabsSection.xml | 1 + 8 files changed, 90 insertions(+), 5 deletions(-) create mode 100644 app/code/Magento/Braintree/Test/Mftf/ActionGroup/StorefrontBraintreeFillCardDataActionGroup.xml create mode 100644 app/code/Magento/Braintree/Test/Mftf/Section/StorefrontBraintreePaymentConfigurationSection.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminCreditMemoActionGroup.xml diff --git a/app/code/Magento/Braintree/Test/Mftf/ActionGroup/StorefrontBraintreeFillCardDataActionGroup.xml b/app/code/Magento/Braintree/Test/Mftf/ActionGroup/StorefrontBraintreeFillCardDataActionGroup.xml new file mode 100644 index 0000000000000..561d660a1bb75 --- /dev/null +++ b/app/code/Magento/Braintree/Test/Mftf/ActionGroup/StorefrontBraintreeFillCardDataActionGroup.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/code/Magento/Braintree/Test/Mftf/Data/BraintreeData.xml b/app/code/Magento/Braintree/Test/Mftf/Data/BraintreeData.xml index 0c57147ca950e..4e8526a2b0e2b 100644 --- a/app/code/Magento/Braintree/Test/Mftf/Data/BraintreeData.xml +++ b/app/code/Magento/Braintree/Test/Mftf/Data/BraintreeData.xml @@ -7,7 +7,7 @@ --> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd"> SampleTitle SamplePaymentAction @@ -113,5 +113,4 @@ 20 113 - diff --git a/app/code/Magento/Braintree/Test/Mftf/Section/StorefrontBraintreePaymentConfigurationSection.xml b/app/code/Magento/Braintree/Test/Mftf/Section/StorefrontBraintreePaymentConfigurationSection.xml new file mode 100644 index 0000000000000..d4cc3fe0f113d --- /dev/null +++ b/app/code/Magento/Braintree/Test/Mftf/Section/StorefrontBraintreePaymentConfigurationSection.xml @@ -0,0 +1,24 @@ + + + + +
+ + + + + + + + + + + +
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/ProductConfigurableAttributeData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/ProductConfigurableAttributeData.xml index 0446a9db14f1a..8d588a192ed90 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Data/ProductConfigurableAttributeData.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Data/ProductConfigurableAttributeData.xml @@ -7,7 +7,7 @@ --> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd"> Color 1 diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminCreditMemoActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminCreditMemoActionGroup.xml new file mode 100644 index 0000000000000..7197afb4a20df --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminCreditMemoActionGroup.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminCreditMemoTotalSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminCreditMemoTotalSection.xml index 648f519455b56..73ea29836e242 100644 --- a/app/code/Magento/Sales/Test/Mftf/Section/AdminCreditMemoTotalSection.xml +++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminCreditMemoTotalSection.xml @@ -13,6 +13,8 @@ - + + + diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderDetailsMainActionsSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderDetailsMainActionsSection.xml index eac238584b030..3794def0ac77a 100644 --- a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderDetailsMainActionsSection.xml +++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderDetailsMainActionsSection.xml @@ -7,7 +7,7 @@ --> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd">
diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderViewTabsSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderViewTabsSection.xml index 78d0a45bce460..0037c482fcd72 100644 --- a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderViewTabsSection.xml +++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderViewTabsSection.xml @@ -12,5 +12,6 @@ +
From 30e61f499761ba83ace058d230e91807dbd45803 Mon Sep 17 00:00:00 2001 From: Serhii Voloshkov Date: Wed, 13 Feb 2019 08:38:22 +0200 Subject: [PATCH 12/65] MAGETWO-94421: Default addresses not selected when checking out from cart --- .../Customer/Test/Mftf/Data/CustomerData.xml | 10 +++++ .../ActionGroup/AdminOrderActionGroup.xml | 45 +++++++++++++++++++ .../AdminOrderFormShippingAddressSection.xml | 23 ++++++++++ 3 files changed, 78 insertions(+) create mode 100644 app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormShippingAddressSection.xml diff --git a/app/code/Magento/Customer/Test/Mftf/Data/CustomerData.xml b/app/code/Magento/Customer/Test/Mftf/Data/CustomerData.xml index a8b8cece39fad..7082a799ed748 100644 --- a/app/code/Magento/Customer/Test/Mftf/Data/CustomerData.xml +++ b/app/code/Magento/Customer/Test/Mftf/Data/CustomerData.xml @@ -44,6 +44,16 @@ 0 US_Address_TX
+ + 1 + John.Doe@example.com + John + Doe + John Doe + pwdTest123! + 0 + 0 + Jane diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOrderActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOrderActionGroup.xml index bb3bfdc03d340..2f7bd98572f8b 100644 --- a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOrderActionGroup.xml +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOrderActionGroup.xml @@ -174,6 +174,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormShippingAddressSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormShippingAddressSection.xml new file mode 100644 index 0000000000000..aae90589a390f --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormShippingAddressSection.xml @@ -0,0 +1,23 @@ + + + + +
+ + + + + + + + + + +
+
From ef8e4f5a7d779278010a5d0b261759c75889ed53 Mon Sep 17 00:00:00 2001 From: Serhii Voloshkov Date: Wed, 13 Feb 2019 08:46:01 +0200 Subject: [PATCH 13/65] MAGETWO-94421: Default addresses not selected when checking out from cart --- app/code/Magento/Sales/Test/Mftf/Page/AdminOrderCreatePage.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Sales/Test/Mftf/Page/AdminOrderCreatePage.xml b/app/code/Magento/Sales/Test/Mftf/Page/AdminOrderCreatePage.xml index e67a2c3b961d9..ca4239bb060ca 100644 --- a/app/code/Magento/Sales/Test/Mftf/Page/AdminOrderCreatePage.xml +++ b/app/code/Magento/Sales/Test/Mftf/Page/AdminOrderCreatePage.xml @@ -7,12 +7,13 @@ --> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/PageObject.xsd">
+
From 934b6e2cfa898d628c88e09fc88406e36b716e78 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra Date: Wed, 13 Feb 2019 12:20:47 +0200 Subject: [PATCH 14/65] MAGETWO-96636: MFTF test fix --- .../StorefrontBraintreeFillCardDataActionGroup.xml | 9 +++++++-- .../Braintree/Test/Mftf/Page/CheckoutPage.xml | 14 ++++++++++++++ ...refrontBraintreePaymentConfigurationSection.xml | 6 ++---- 3 files changed, 23 insertions(+), 6 deletions(-) create mode 100644 app/code/Magento/Braintree/Test/Mftf/Page/CheckoutPage.xml diff --git a/app/code/Magento/Braintree/Test/Mftf/ActionGroup/StorefrontBraintreeFillCardDataActionGroup.xml b/app/code/Magento/Braintree/Test/Mftf/ActionGroup/StorefrontBraintreeFillCardDataActionGroup.xml index 561d660a1bb75..93f239b5c38a1 100644 --- a/app/code/Magento/Braintree/Test/Mftf/ActionGroup/StorefrontBraintreeFillCardDataActionGroup.xml +++ b/app/code/Magento/Braintree/Test/Mftf/ActionGroup/StorefrontBraintreeFillCardDataActionGroup.xml @@ -7,13 +7,18 @@ --> + + + + + - - + + diff --git a/app/code/Magento/Braintree/Test/Mftf/Page/CheckoutPage.xml b/app/code/Magento/Braintree/Test/Mftf/Page/CheckoutPage.xml new file mode 100644 index 0000000000000..bc23a1e1fe3f7 --- /dev/null +++ b/app/code/Magento/Braintree/Test/Mftf/Page/CheckoutPage.xml @@ -0,0 +1,14 @@ + + + + + +
+ + diff --git a/app/code/Magento/Braintree/Test/Mftf/Section/StorefrontBraintreePaymentConfigurationSection.xml b/app/code/Magento/Braintree/Test/Mftf/Section/StorefrontBraintreePaymentConfigurationSection.xml index d4cc3fe0f113d..f72eed9179764 100644 --- a/app/code/Magento/Braintree/Test/Mftf/Section/StorefrontBraintreePaymentConfigurationSection.xml +++ b/app/code/Magento/Braintree/Test/Mftf/Section/StorefrontBraintreePaymentConfigurationSection.xml @@ -9,14 +9,12 @@
- - - + - + From 69972709ad74896c4d3d5ce28020e07571aeb8fa Mon Sep 17 00:00:00 2001 From: Myroslav Dobra Date: Thu, 14 Feb 2019 17:51:06 +0200 Subject: [PATCH 15/65] MAGETWO-96636: MFTF test fix --- .../Test/Mftf/ActionGroup/AdminCreditMemoActionGroup.xml | 3 ++- .../Test/Mftf/Section/AdminCreditMemoItemsSection.xml | 2 +- .../Test/Mftf/Section/AdminCreditMemoTotalSection.xml | 6 ++---- .../Test/AdminAbleToShipPartiallyInvoicedItemsTest.xml | 2 +- .../Test/Mftf/Test/AdminCheckingCreditMemoTotalsTest.xml | 9 ++------- 5 files changed, 8 insertions(+), 14 deletions(-) diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminCreditMemoActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminCreditMemoActionGroup.xml index 7197afb4a20df..de1ed79db81ad 100644 --- a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminCreditMemoActionGroup.xml +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminCreditMemoActionGroup.xml @@ -12,12 +12,13 @@ + - + diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminCreditMemoItemsSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminCreditMemoItemsSection.xml index 496fae2b548a7..15d4df39416f2 100644 --- a/app/code/Magento/Sales/Test/Mftf/Section/AdminCreditMemoItemsSection.xml +++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminCreditMemoItemsSection.xml @@ -10,6 +10,6 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd">
- +
diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminCreditMemoTotalSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminCreditMemoTotalSection.xml index 73ea29836e242..e087873fe62c2 100644 --- a/app/code/Magento/Sales/Test/Mftf/Section/AdminCreditMemoTotalSection.xml +++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminCreditMemoTotalSection.xml @@ -11,10 +11,8 @@
- - - + + -
diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminAbleToShipPartiallyInvoicedItemsTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminAbleToShipPartiallyInvoicedItemsTest.xml index cb761dc358abb..1abb23ebddba0 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminAbleToShipPartiallyInvoicedItemsTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminAbleToShipPartiallyInvoicedItemsTest.xml @@ -119,7 +119,7 @@ - + + - - - + From be57683357f8a6819a575f051d0ea96bcdfc1548 Mon Sep 17 00:00:00 2001 From: Stjepan Udovicic Date: Mon, 18 Feb 2019 08:07:09 +0100 Subject: [PATCH 16/65] Backport ENGCOM-3616: Static test fix --- .../Indexer/Price/CustomOptionPriceModifier.php | 10 ++++++++++ .../Product/Indexer/Price/DefaultPrice.php | 14 ++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Price/CustomOptionPriceModifier.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Price/CustomOptionPriceModifier.php index 646cd0d4c1a4c..ce0b7a4111d2c 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Price/CustomOptionPriceModifier.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Price/CustomOptionPriceModifier.php @@ -127,6 +127,8 @@ public function modifyPrice(IndexTableStructure $priceTable, array $entityIds = } /** + * Check if custom options exist. + * * @param IndexTableStructure $priceTable * @return bool * @throws \Exception @@ -154,6 +156,8 @@ private function checkIfCustomOptionsExist(IndexTableStructure $priceTable): boo } /** + * Get connection. + * * @return \Magento\Framework\DB\Adapter\AdapterInterface */ private function getConnection() @@ -373,6 +377,8 @@ private function getSelectAggregated(string $sourceTable): Select } /** + * Get select for update. + * * @param string $sourceTable * @return \Magento\Framework\DB\Select */ @@ -402,6 +408,8 @@ private function getSelectForUpdate(string $sourceTable): Select } /** + * Get table name. + * * @param string $tableName * @return string */ @@ -411,6 +419,8 @@ private function getTable(string $tableName): string } /** + * Is price scope global. + * * @return bool */ private function isPriceGlobal(): bool diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Price/DefaultPrice.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Price/DefaultPrice.php index 8fdeaf00b804f..aab4577de3770 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Price/DefaultPrice.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Price/DefaultPrice.php @@ -10,6 +10,7 @@ /** * Default Product Type Price Indexer Resource model + * * For correctly work need define product type id * * @api @@ -208,6 +209,8 @@ public function reindexEntity($entityIds) } /** + * Reindex prices. + * * @param null|int|array $entityIds * @return \Magento\Catalog\Model\ResourceModel\Product\Indexer\Price\DefaultPrice */ @@ -802,6 +805,8 @@ public function getIdxTable($table = null) } /** + * Check if product exists. + * * @return bool */ protected function hasEntity() @@ -823,6 +828,8 @@ protected function hasEntity() } /** + * Get total tier price expression. + * * @param \Zend_Db_Expr $priceExpression * @return \Zend_Db_Expr */ @@ -862,6 +869,13 @@ private function getTotalTierPriceExpression(\Zend_Db_Expr $priceExpression) ); } + /** + * Get tier price expression for table. + * + * @param string $tableAlias + * @param \Zend_Db_Expr $priceExpression + * @return \Zend_Db_Expr + */ private function getTierPriceExpressionForTable($tableAlias, \Zend_Db_Expr $priceExpression) { return $this->getConnection()->getCheckSql( From b16221b1b76dd18bb1fbebbe4b26ed394e4e3657 Mon Sep 17 00:00:00 2001 From: Viktor Petryk Date: Mon, 18 Feb 2019 20:54:51 +0200 Subject: [PATCH 17/65] MAGETWO-94190: [Magento Cloud] Error when saving Bundle product --- .../Bundle/Model/Product/SaveHandler.php | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/app/code/Magento/Bundle/Model/Product/SaveHandler.php b/app/code/Magento/Bundle/Model/Product/SaveHandler.php index 09fce9222e63d..dbd07f188f90b 100644 --- a/app/code/Magento/Bundle/Model/Product/SaveHandler.php +++ b/app/code/Magento/Bundle/Model/Product/SaveHandler.php @@ -7,6 +7,7 @@ use Magento\Bundle\Api\ProductOptionRepositoryInterface as OptionRepository; use Magento\Bundle\Api\ProductLinkManagementInterface; +use Magento\Catalog\Api\Data\ProductInterface; use Magento\Framework\App\ObjectManager; use Magento\Framework\EntityManager\MetadataPool; use Magento\Framework\EntityManager\Operation\ExtensionInterface; @@ -49,12 +50,11 @@ public function __construct( } /** + * Perform action on Bundle product relation/extension attribute. + * * @param object $entity * @param array $arguments - * @return \Magento\Catalog\Api\Data\ProductInterface|object - * @throws \Magento\Framework\Exception\NoSuchEntityException - * @throws \Magento\Framework\Exception\InputException - * @throws \Magento\Framework\Exception\CouldNotSaveException + * @return ProductInterface|object * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function execute($entity, $arguments = []) @@ -78,7 +78,7 @@ public function execute($entity, $arguments = []) $options = $bundleProductOptions ?: []; if (!$entity->getCopyFromView()) { - $this->processRemovedOptions($entity->getSku(), $existingOptionsIds, $optionIds); + $this->processRemovedOptions($entity, $existingOptionsIds, $optionIds); $newOptionsIds = array_diff($optionIds, $existingOptionsIds); $this->saveOptions($entity, $options, $newOptionsIds); @@ -92,10 +92,10 @@ public function execute($entity, $arguments = []) } /** + * Remove option product links. + * * @param string $entitySku * @param \Magento\Bundle\Api\Data\OptionInterface $option - * @throws \Magento\Framework\Exception\NoSuchEntityException - * @throws \Magento\Framework\Exception\InputException * @return void */ protected function removeOptionLinks($entitySku, $option) @@ -152,21 +152,21 @@ private function getOptionIds(array $options) } /** - * Removes old options that no longer exists + * Removes old options that no longer exists. * - * @param string $entitySku + * @param ProductInterface $entity * @param array $existingOptionsIds * @param array $optionIds - * @throws \Magento\Framework\Exception\NoSuchEntityException - * @throws \Magento\Framework\Exception\InputException - * @throws \Magento\Framework\Exception\CouldNotSaveException * @return void */ - private function processRemovedOptions($entitySku, array $existingOptionsIds, array $optionIds) + private function processRemovedOptions(ProductInterface $entity, array $existingOptionsIds, array $optionIds) { + $metadata = $this->metadataPool->getMetadata(ProductInterface::class); + $parentId = $entity->getData($metadata->getLinkField()); foreach (array_diff($existingOptionsIds, $optionIds) as $optionId) { - $option = $this->optionRepository->get($entitySku, $optionId); - $this->removeOptionLinks($entitySku, $option); + $option = $this->optionRepository->get($entity->getSku(), $optionId); + $option->setParentId($parentId); + $this->removeOptionLinks($entity->getSku(), $option); $this->optionRepository->delete($option); } } From 7a2b275c22324e9b2684698167372dc10a196dbe Mon Sep 17 00:00:00 2001 From: Serhii Voloshkov Date: Tue, 19 Feb 2019 16:59:11 +0200 Subject: [PATCH 18/65] MAGETWO-95904: Header Minicart, Shopping cart page and Checkout page show incorrect product name --- .../Magento/Checkout/Block/Cart/Sidebar.php | 5 +- .../Magento/Checkout/CustomerData/Cart.php | 3 +- .../StorefrontMiniCartActionGroup.xml | 2 +- .../CheckoutShippingGuestInfoSection.xml | 4 +- ...tOnCheckoutPageDifferentStoreViewsTest.xml | 87 +++++++++++++++++++ .../Test/Unit/Block/Cart/SidebarTest.php | 14 ++- .../Test/Unit/CustomerData/CartTest.php | 13 ++- .../view/frontend/web/js/view/minicart.js | 7 +- .../Block/Adminhtml/Edit/Tab/View/Cart.php | 2 +- app/code/Magento/Quote/Model/Quote.php | 6 +- .../Quote/Plugin/UpdateQuoteItemStore.php | 73 ++++++++++++++++ app/code/Magento/Quote/etc/frontend/di.xml | 3 + 12 files changed, 204 insertions(+), 15 deletions(-) create mode 100644 app/code/Magento/Checkout/Test/Mftf/Test/StorefrontProductNameMinicartOnCheckoutPageDifferentStoreViewsTest.xml create mode 100644 app/code/Magento/Quote/Plugin/UpdateQuoteItemStore.php diff --git a/app/code/Magento/Checkout/Block/Cart/Sidebar.php b/app/code/Magento/Checkout/Block/Cart/Sidebar.php index 5c237eecf0a9f..7453d3c62e862 100644 --- a/app/code/Magento/Checkout/Block/Cart/Sidebar.php +++ b/app/code/Magento/Checkout/Block/Cart/Sidebar.php @@ -67,7 +67,7 @@ public function __construct( } /** - * Returns minicart config + * Returns minicart config. * * @return array */ @@ -82,7 +82,8 @@ public function getConfig() 'baseUrl' => $this->getBaseUrl(), 'minicartMaxItemsVisible' => $this->getMiniCartMaxItemsCount(), 'websiteId' => $this->_storeManager->getStore()->getWebsiteId(), - 'maxItemsToDisplay' => $this->getMaxItemsToDisplay() + 'maxItemsToDisplay' => $this->getMaxItemsToDisplay(), + 'storeId' => $this->_storeManager->getStore()->getId(), ]; } diff --git a/app/code/Magento/Checkout/CustomerData/Cart.php b/app/code/Magento/Checkout/CustomerData/Cart.php index 01e91d75c02d9..9154e9c99478e 100644 --- a/app/code/Magento/Checkout/CustomerData/Cart.php +++ b/app/code/Magento/Checkout/CustomerData/Cart.php @@ -98,7 +98,8 @@ public function getSectionData() 'items' => $this->getRecentItems(), 'extra_actions' => $this->layout->createBlock(\Magento\Catalog\Block\ShortcutButtons::class)->toHtml(), 'isGuestCheckoutAllowed' => $this->isGuestCheckoutAllowed(), - 'website_id' => $this->getQuote()->getStore()->getWebsiteId() + 'website_id' => $this->getQuote()->getStore()->getWebsiteId(), + 'storeId' => $this->getQuote()->getStore()->getStoreId(), ]; } diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontMiniCartActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontMiniCartActionGroup.xml index 7a5c5e1d15872..3390dc588b69b 100644 --- a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontMiniCartActionGroup.xml +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontMiniCartActionGroup.xml @@ -15,7 +15,7 @@ - + diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingGuestInfoSection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingGuestInfoSection.xml index 8e043f85a0b95..0a243d54cedef 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingGuestInfoSection.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingGuestInfoSection.xml @@ -7,7 +7,7 @@ --> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd">
@@ -17,5 +17,7 @@ + +
diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontProductNameMinicartOnCheckoutPageDifferentStoreViewsTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontProductNameMinicartOnCheckoutPageDifferentStoreViewsTest.xml new file mode 100644 index 0000000000000..a810aa7107ff1 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontProductNameMinicartOnCheckoutPageDifferentStoreViewsTest.xml @@ -0,0 +1,87 @@ + + + + + + + + <description value="Checking Product name in Minicart and on Checkout page with custom store views"/> + <stories value="Verify product name with custom store view"/> + <severity value="MAJOR"/> + <testCaseId value="MC-14944"/> + <features value="Checkout"/> + <group value="checkout"/> + </annotations> + <before> + <!--Login as Admin--> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + <!--Create a product--> + <createData entity="SimpleSubCategory" stepKey="createCategory"/> + <createData entity="SimpleProduct" stepKey="createProduct"> + <requiredEntity createDataKey="createCategory"/> + </createData> + <!-- Create store view --> + <actionGroup ref="AdminCreateStoreViewActionGroup" stepKey="createStoreView"> + <argument name="customStore" value="customStore"/> + </actionGroup> + </before> + <after> + <!--Delete product--> + <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> + <!--Delete store view--> + <actionGroup ref="AdminDeleteStoreViewActionGroup" stepKey="deleteStoreView"> + <argument name="customStore" value="customStore"/> + </actionGroup> + <!--Logout from admin--> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <!--Go to created product page--> + <amOnPage url="{{AdminProductEditPage.url($$createProduct.id$$)}}" stepKey="goToEditPage"/> + + <!--Switch to second store view and change the product name--> + <actionGroup ref="SwitchToTheNewStoreView" stepKey="switchToCustomStoreView"> + <argument name="storeViewName" value="customStore"/> + </actionGroup> + <click selector="{{AdminProductFormSection.productNameUseDefault}}" stepKey="uncheckUseDefault"/> + <fillField selector="{{AdminProductFormSection.productName}}" userInput="$$createProduct.name$$-new" stepKey="fillProductName"/> + <click selector="{{AdminProductFormActionSection.saveButton}}" stepKey="saveProduct"/> + + <!--Add product to cart--> + <amOnPage url="{{StorefrontProductPage.url($$createProduct.name$$)}}" stepKey="amOnProductPage"/> + <actionGroup ref="addToCartFromStorefrontProductPage" stepKey="addToCartFromStorefrontProductPage"> + <argument name="productName" value="$createProduct.name$$"/> + </actionGroup> + + <!--Check simple product in minicart--> + <actionGroup ref="assertOneProductNameInMiniCart" stepKey="assertProductNameInMiniCart1"> + <argument name="productName" value="$$createProduct.name$$"/> + </actionGroup> + + <!--Switch to second store view--> + <actionGroup ref="StorefrontSwitchStoreViewActionGroup" stepKey="switchStoreView"> + <argument name="storeView" value="customStore"/> + </actionGroup> + + <!--Check simple product in minicart--> + <actionGroup ref="assertOneProductNameInMiniCart" stepKey="assertProductNameInMiniCart2"> + <argument name="productName" value="$$createProduct.name$$-new"/> + </actionGroup> + + <!--Go to Shopping Cart--> + <actionGroup ref="clickViewAndEditCartFromMiniCart" stepKey="goToCheckoutFromMinicart"/> + <seeElement selector="{{CheckoutCartProductSection.productLinkByName($$createProduct.name$$-new)}}" stepKey="assertProductName"/> + + <!--Proceed to checkout--> + <actionGroup ref="GoToCheckoutFromMinicartActionGroup" stepKey="goToCheckoutPage"/> + <conditionalClick selector="{{CheckoutShippingGuestInfoSection.itemInCart}}" dependentSelector="{{CheckoutShippingGuestInfoSection.itemInCart}}" visible="true" stepKey="clickItemsInCart"/> + <see selector="{{CheckoutShippingGuestInfoSection.productName}}" userInput="$$createProduct.name$$-new" stepKey="seeProductNameAtCheckout"/> + </test> +</tests> diff --git a/app/code/Magento/Checkout/Test/Unit/Block/Cart/SidebarTest.php b/app/code/Magento/Checkout/Test/Unit/Block/Cart/SidebarTest.php index 88751b899d7c9..015d8ccbe928f 100644 --- a/app/code/Magento/Checkout/Test/Unit/Block/Cart/SidebarTest.php +++ b/app/code/Magento/Checkout/Test/Unit/Block/Cart/SidebarTest.php @@ -6,6 +6,8 @@ namespace Magento\Checkout\Test\Unit\Block\Cart; /** + * Unit tests for Magento\Checkout\Block\Cart\Sidebar. + * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class SidebarTest extends \PHPUnit\Framework\TestCase @@ -123,6 +125,11 @@ public function testGetTotalsHtml() $this->assertEquals($totalsHtml, $this->model->getTotalsHtml()); } + /** + * Unit test for getConfig method. + * + * @return void + */ public function testGetConfig() { $websiteId = 100; @@ -144,14 +151,15 @@ public function testGetConfig() 'baseUrl' => $baseUrl, 'minicartMaxItemsVisible' => 3, 'websiteId' => 100, - 'maxItemsToDisplay' => 8 + 'maxItemsToDisplay' => 8, + 'storeId' => null, ]; $valueMap = [ ['checkout/cart', [], $shoppingCartUrl], ['checkout', [], $checkoutUrl], ['checkout/sidebar/updateItemQty', ['_secure' => false], $updateItemQtyUrl], - ['checkout/sidebar/removeItem', ['_secure' => false], $removeItemUrl] + ['checkout/sidebar/removeItem', ['_secure' => false], $removeItemUrl], ]; $this->requestMock->expects($this->any()) @@ -161,7 +169,7 @@ public function testGetConfig() $this->urlBuilderMock->expects($this->exactly(4)) ->method('getUrl') ->willReturnMap($valueMap); - $this->storeManagerMock->expects($this->exactly(2))->method('getStore')->willReturn($storeMock); + $this->storeManagerMock->expects($this->atLeastOnce())->method('getStore')->willReturn($storeMock); $storeMock->expects($this->once())->method('getBaseUrl')->willReturn($baseUrl); $this->imageHelper->expects($this->once())->method('getFrame')->willReturn(false); diff --git a/app/code/Magento/Checkout/Test/Unit/CustomerData/CartTest.php b/app/code/Magento/Checkout/Test/Unit/CustomerData/CartTest.php index 75e181cbabd08..9f718f00b4b9d 100644 --- a/app/code/Magento/Checkout/Test/Unit/CustomerData/CartTest.php +++ b/app/code/Magento/Checkout/Test/Unit/CustomerData/CartTest.php @@ -7,6 +7,8 @@ namespace Magento\Checkout\Test\Unit\CustomerData; /** + * Unit tests for Magento\Checkout\CustomerData\Cart. + * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class CartTest extends \PHPUnit\Framework\TestCase @@ -78,6 +80,11 @@ public function testIsGuestCheckoutAllowed() $this->assertTrue($this->model->isGuestCheckoutAllowed()); } + /** + * Unit test for getSectionData method. + * + * @return void + */ public function testGetSectionData() { $summaryQty = 100; @@ -113,7 +120,7 @@ public function testGetSectionData() $storeMock = $this->createPartialMock(\Magento\Store\Model\System\Store::class, ['getWebsiteId']); $storeMock->expects($this->once())->method('getWebsiteId')->willReturn($websiteId); - $quoteMock->expects($this->once())->method('getStore')->willReturn($storeMock); + $quoteMock->expects($this->atLeastOnce())->method('getStore')->willReturn($storeMock); $productMock = $this->createPartialMock( \Magento\Catalog\Model\Product::class, @@ -162,6 +169,7 @@ public function testGetSectionData() 'isGuestCheckoutAllowed' => 1, 'website_id' => $websiteId, 'subtotalAmount' => 200, + 'storeId' => null, ]; $this->assertEquals($expectedResult, $this->model->getSectionData()); } @@ -199,7 +207,7 @@ public function testGetSectionDataWithCompositeProduct() $storeMock = $this->createPartialMock(\Magento\Store\Model\System\Store::class, ['getWebsiteId']); $storeMock->expects($this->once())->method('getWebsiteId')->willReturn($websiteId); - $quoteMock->expects($this->once())->method('getStore')->willReturn($storeMock); + $quoteMock->expects($this->atLeastOnce())->method('getStore')->willReturn($storeMock); $this->checkoutCartMock->expects($this->once())->method('getSummaryQty')->willReturn($summaryQty); $this->checkoutHelperMock->expects($this->once()) @@ -265,6 +273,7 @@ public function testGetSectionDataWithCompositeProduct() 'isGuestCheckoutAllowed' => 1, 'website_id' => $websiteId, 'subtotalAmount' => 200, + 'storeId' => null, ]; $this->assertEquals($expectedResult, $this->model->getSectionData()); } diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/minicart.js b/app/code/Magento/Checkout/view/frontend/web/js/view/minicart.js index a2f8c8c56ff33..5e29fa209a641 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/view/minicart.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/view/minicart.js @@ -81,6 +81,7 @@ define([ maxItemsToDisplay: window.checkout.maxItemsToDisplay, cart: {}, + // jscs:disable requireCamelCaseOrUpperCaseIdentifiers /** * @override */ @@ -101,12 +102,16 @@ define([ self.isLoading(true); }); - if (cartData()['website_id'] !== window.checkout.websiteId) { + if (cartData().website_id !== window.checkout.websiteId || + cartData().store_id !== window.checkout.storeId + ) { customerData.reload(['cart'], false); } return this._super(); }, + //jscs:enable requireCamelCaseOrUpperCaseIdentifiers + isLoading: ko.observable(false), initSidebar: initSidebar, diff --git a/app/code/Magento/Customer/Block/Adminhtml/Edit/Tab/View/Cart.php b/app/code/Magento/Customer/Block/Adminhtml/Edit/Tab/View/Cart.php index 3f2c7cda7608d..d0973d3baf383 100644 --- a/app/code/Magento/Customer/Block/Adminhtml/Edit/Tab/View/Cart.php +++ b/app/code/Magento/Customer/Block/Adminhtml/Edit/Tab/View/Cart.php @@ -94,7 +94,7 @@ protected function _prepareCollection() $quote = $this->getQuote(); if ($quote) { - $collection = $quote->getItemsCollection(false); + $collection = $quote->getItemsCollection(true); } else { $collection = $this->_dataCollectionFactory->create(); } diff --git a/app/code/Magento/Quote/Model/Quote.php b/app/code/Magento/Quote/Model/Quote.php index a3f5d1aaa6a6a..6ea70e63fdbf6 100644 --- a/app/code/Magento/Quote/Model/Quote.php +++ b/app/code/Magento/Quote/Model/Quote.php @@ -1354,7 +1354,7 @@ public function addShippingAddress(\Magento\Quote\Api\Data\AddressInterface $add } /** - * Retrieve quote items collection + * Retrieve quote items collection. * * @param bool $useCache * @return \Magento\Eav\Model\Entity\Collection\AbstractCollection @@ -1362,10 +1362,10 @@ public function addShippingAddress(\Magento\Quote\Api\Data\AddressInterface $add */ public function getItemsCollection($useCache = true) { - if ($this->hasItemsCollection()) { + if ($this->hasItemsCollection() && $useCache) { return $this->getData('items_collection'); } - if (null === $this->_items) { + if (null === $this->_items || !$useCache) { $this->_items = $this->_quoteItemCollectionFactory->create(); $this->extensionAttributesJoinProcessor->process($this->_items); $this->_items->setQuote($this); diff --git a/app/code/Magento/Quote/Plugin/UpdateQuoteItemStore.php b/app/code/Magento/Quote/Plugin/UpdateQuoteItemStore.php new file mode 100644 index 0000000000000..4d3e2dff70f9b --- /dev/null +++ b/app/code/Magento/Quote/Plugin/UpdateQuoteItemStore.php @@ -0,0 +1,73 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Quote\Plugin; + +use Magento\Checkout\Model\Session; +use Magento\Quote\Model\QuoteRepository; +use Magento\Store\Api\Data\StoreInterface; +use Magento\Store\Model\StoreSwitcherInterface; + +/** + * Updates quote items store id. + * + * @SuppressWarnings(PHPMD.CookieAndSessionMisuse) + */ +class UpdateQuoteItemStore +{ + /** + * @var QuoteRepository + */ + private $quoteRepository; + + /** + * @var Session + */ + private $checkoutSession; + + /** + * @param QuoteRepository $quoteRepository + * @param Session $checkoutSession + */ + public function __construct( + QuoteRepository $quoteRepository, + Session $checkoutSession + ) { + $this->quoteRepository = $quoteRepository; + $this->checkoutSession = $checkoutSession; + } + + /** + * Update store id in active quote after store view switching. + * + * @param StoreSwitcherInterface $subject + * @param string $result + * @param StoreInterface $fromStore store where we came from + * @param StoreInterface $targetStore store where to go to + * @param string $redirectUrl original url requested for redirect after switching + * @return string url to be redirected after switching + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function afterSwitch( + StoreSwitcherInterface $subject, + string $result, + StoreInterface $fromStore, + StoreInterface $targetStore, + string $redirectUrl + ): string { + $quote = $this->checkoutSession->getQuote(); + if ($quote->getIsActive()) { + $quote->setStoreId( + $targetStore->getId() + ); + $quote->getItemsCollection(false); + $this->quoteRepository->save($quote); + } + + return $result; + } +} diff --git a/app/code/Magento/Quote/etc/frontend/di.xml b/app/code/Magento/Quote/etc/frontend/di.xml index 25acd6763ba56..91f4cfbf60aba 100644 --- a/app/code/Magento/Quote/etc/frontend/di.xml +++ b/app/code/Magento/Quote/etc/frontend/di.xml @@ -12,6 +12,9 @@ <argument name="checkoutSession" xsi:type="object">Magento\Checkout\Model\Session\Proxy</argument> </arguments> </type> + <type name="Magento\Store\Model\StoreSwitcherInterface"> + <plugin name="update_quote_item_store_after_switch_store_view" type="Magento\Quote\Plugin\UpdateQuoteItemStore"/> + </type> <type name="Magento\Store\Api\StoreCookieManagerInterface"> <plugin name="update_quote_store_after_switch_store_view" type="Magento\Quote\Plugin\UpdateQuoteStore"/> </type> From d78ccf6cec8e3f2dee6d47afe49545967fe3a2b3 Mon Sep 17 00:00:00 2001 From: Serhii Voloshkov <serhii.voloshkov@transoftgroup.com> Date: Wed, 20 Feb 2019 10:08:30 +0200 Subject: [PATCH 19/65] MAGETWO-95904: Header Minicart, Shopping cart page and Checkout page show incorrect product name --- app/code/Magento/Checkout/Block/Cart/Sidebar.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/code/Magento/Checkout/Block/Cart/Sidebar.php b/app/code/Magento/Checkout/Block/Cart/Sidebar.php index 7453d3c62e862..5e3234e9f4cc8 100644 --- a/app/code/Magento/Checkout/Block/Cart/Sidebar.php +++ b/app/code/Magento/Checkout/Block/Cart/Sidebar.php @@ -133,6 +133,7 @@ public function getShoppingCartUrl() * * @return string * @codeCoverageIgnore + * @SuppressWarnings(PHPMD.RequestAwareBlockMethod) */ public function getUpdateItemQtyUrl() { @@ -144,6 +145,7 @@ public function getUpdateItemQtyUrl() * * @return string * @codeCoverageIgnore + * @SuppressWarnings(PHPMD.RequestAwareBlockMethod) */ public function getRemoveItemUrl() { From 102d5972b4c69f5efb6e7ee5100120d06716ecb4 Mon Sep 17 00:00:00 2001 From: Serhii Voloshkov <serhii.voloshkov@transoftgroup.com> Date: Mon, 25 Feb 2019 14:44:29 +0200 Subject: [PATCH 20/65] MAGETWO-94421: Default addresses not selected when checking out from cart --- .../Sales/Test/Mftf/ActionGroup/AdminOrderActionGroup.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOrderActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOrderActionGroup.xml index 4af8128d7ac14..eabe51776894e 100644 --- a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOrderActionGroup.xml +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOrderActionGroup.xml @@ -181,7 +181,7 @@ <fillField selector="{{AdminOrderFormBillingAddressSection.phone}}" userInput="{{address.telephone}}" stepKey="fillPhone"/> </actionGroup> <!--Check customer billing address fields--> - <actionGroup name="checkOrderCustomerBillingInformation"> + <actionGroup name="CheckOrderCustomerBillingInformation"> <arguments> <argument name="customer"/> <argument name="address"/> @@ -196,7 +196,7 @@ <seeInField selector="{{AdminOrderFormBillingAddressSection.phone}}" userInput="{{address.telephone}}" stepKey="checkTelephone"/> </actionGroup> <!--Fill customer shipping address--> - <actionGroup name="fillOrderCustomerShippingInformation"> + <actionGroup name="FillOrderCustomerShippingInformation"> <arguments> <argument name="customer"/> <argument name="address"/> @@ -211,7 +211,7 @@ <fillField selector="{{AdminOrderFormShippingAddressSection.phone}}" userInput="{{address.telephone}}" stepKey="fillPhone"/> </actionGroup> <!--Check customer shipping address fields--> - <actionGroup name="checkOrderCustomerShippingInformation"> + <actionGroup name="CheckOrderCustomerShippingInformation"> <arguments> <argument name="customer"/> <argument name="address"/> From 6c09eca826e4ad3b4215748ae52054383b6163da Mon Sep 17 00:00:00 2001 From: Serhii Voloshkov <serhii.voloshkov@transoftgroup.com> Date: Tue, 26 Feb 2019 12:37:48 +0200 Subject: [PATCH 21/65] MAGETWO-95904: Header Minicart, Shopping cart page and Checkout page show incorrect product name --- .../Magento/Checkout/Block/Cart/Sidebar.php | 2 + .../CheckoutShippingGuestInfoSection.xml | 2 - ...tOnCheckoutPageDifferentStoreViewsTest.xml | 19 ++- .../view/frontend/web/js/view/minicart.js | 4 +- .../Quote/Plugin/UpdateQuoteItemStore.php | 4 +- .../Unit/Plugin/UpdateQuoteItemStoreTest.php | 143 ++++++++++++++++++ 6 files changed, 159 insertions(+), 15 deletions(-) create mode 100644 app/code/Magento/Quote/Test/Unit/Plugin/UpdateQuoteItemStoreTest.php diff --git a/app/code/Magento/Checkout/Block/Cart/Sidebar.php b/app/code/Magento/Checkout/Block/Cart/Sidebar.php index 7453d3c62e862..5e3234e9f4cc8 100644 --- a/app/code/Magento/Checkout/Block/Cart/Sidebar.php +++ b/app/code/Magento/Checkout/Block/Cart/Sidebar.php @@ -133,6 +133,7 @@ public function getShoppingCartUrl() * * @return string * @codeCoverageIgnore + * @SuppressWarnings(PHPMD.RequestAwareBlockMethod) */ public function getUpdateItemQtyUrl() { @@ -144,6 +145,7 @@ public function getUpdateItemQtyUrl() * * @return string * @codeCoverageIgnore + * @SuppressWarnings(PHPMD.RequestAwareBlockMethod) */ public function getRemoveItemUrl() { diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingGuestInfoSection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingGuestInfoSection.xml index 0a243d54cedef..115eb92c48268 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingGuestInfoSection.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingGuestInfoSection.xml @@ -17,7 +17,5 @@ <element name="region" type="select" selector="select[name=region_id]"/> <element name="postcode" type="input" selector="input[name=postcode]"/> <element name="telephone" type="input" selector="input[name=telephone]"/> - <element name="itemInCart" type="button" selector="div.items-in-cart div.title"/> - <element name="productName" type="text" selector="div.items-in-cart strong.product-item-name"/> </section> </sections> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontProductNameMinicartOnCheckoutPageDifferentStoreViewsTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontProductNameMinicartOnCheckoutPageDifferentStoreViewsTest.xml index a810aa7107ff1..4622a6bd1ebf6 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontProductNameMinicartOnCheckoutPageDifferentStoreViewsTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontProductNameMinicartOnCheckoutPageDifferentStoreViewsTest.xml @@ -10,22 +10,23 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="StorefrontProductNameMinicartOnCheckoutPageDifferentStoreViewsTest"> <annotations> + <features value="Checkout"/> <title value="Checking Product name with custom store views"/> <description value="Checking Product name in Minicart and on Checkout page with custom store views"/> - <stories value="Verify product name with custom store view"/> + <stories value="Checkout via Guest Checkout"/> <severity value="MAJOR"/> <testCaseId value="MC-14944"/> - <features value="Checkout"/> + <useCaseId value="MAGETWO-95904"/> <group value="checkout"/> </annotations> <before> - <!--Login as Admin--> - <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> <!--Create a product--> <createData entity="SimpleSubCategory" stepKey="createCategory"/> <createData entity="SimpleProduct" stepKey="createProduct"> <requiredEntity createDataKey="createCategory"/> </createData> + <!--Login as Admin--> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> <!-- Create store view --> <actionGroup ref="AdminCreateStoreViewActionGroup" stepKey="createStoreView"> <argument name="customStore" value="customStore"/> @@ -39,6 +40,7 @@ <actionGroup ref="AdminDeleteStoreViewActionGroup" stepKey="deleteStoreView"> <argument name="customStore" value="customStore"/> </actionGroup> + <actionGroup ref="clearFiltersAdminDataGrid" stepKey="clearGridFilter"/> <!--Logout from admin--> <actionGroup ref="logout" stepKey="logout"/> </after> @@ -55,7 +57,7 @@ <click selector="{{AdminProductFormActionSection.saveButton}}" stepKey="saveProduct"/> <!--Add product to cart--> - <amOnPage url="{{StorefrontProductPage.url($$createProduct.name$$)}}" stepKey="amOnProductPage"/> + <amOnPage url="{{StorefrontProductPage.url($$createProduct.sku$$)}}" stepKey="amOnProductPage"/> <actionGroup ref="addToCartFromStorefrontProductPage" stepKey="addToCartFromStorefrontProductPage"> <argument name="productName" value="$createProduct.name$$"/> </actionGroup> @@ -76,12 +78,13 @@ </actionGroup> <!--Go to Shopping Cart--> - <actionGroup ref="clickViewAndEditCartFromMiniCart" stepKey="goToCheckoutFromMinicart"/> + <actionGroup ref="clickViewAndEditCartFromMiniCart" stepKey="goToShoppingCartFromMinicart"/> <seeElement selector="{{CheckoutCartProductSection.productLinkByName($$createProduct.name$$-new)}}" stepKey="assertProductName"/> <!--Proceed to checkout--> <actionGroup ref="GoToCheckoutFromMinicartActionGroup" stepKey="goToCheckoutPage"/> - <conditionalClick selector="{{CheckoutShippingGuestInfoSection.itemInCart}}" dependentSelector="{{CheckoutShippingGuestInfoSection.itemInCart}}" visible="true" stepKey="clickItemsInCart"/> - <see selector="{{CheckoutShippingGuestInfoSection.productName}}" userInput="$$createProduct.name$$-new" stepKey="seeProductNameAtCheckout"/> + <conditionalClick selector="{{CheckoutOrderSummarySection.miniCartTab}}" dependentSelector="{{CheckoutOrderSummarySection.miniCartTab}}" visible="true" stepKey="clickItemsInCart"/> + <waitForElementVisible selector="{{CheckoutOrderSummarySection.productItemName}}" stepKey="waitForProduct"/> + <see selector="{{CheckoutOrderSummarySection.productItemName}}" userInput="$$createProduct.name$$-new" stepKey="seeProductNameAtCheckout"/> </test> </tests> diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/minicart.js b/app/code/Magento/Checkout/view/frontend/web/js/view/minicart.js index 5e29fa209a641..da1b1a41e2fa9 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/view/minicart.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/view/minicart.js @@ -102,8 +102,8 @@ define([ self.isLoading(true); }); - if (cartData().website_id !== window.checkout.websiteId || - cartData().store_id !== window.checkout.storeId + if (cartData().website_id !== window.checkout.websiteId + || cartData().store_id !== window.checkout.storeId ) { customerData.reload(['cart'], false); } diff --git a/app/code/Magento/Quote/Plugin/UpdateQuoteItemStore.php b/app/code/Magento/Quote/Plugin/UpdateQuoteItemStore.php index 4d3e2dff70f9b..0ac589b11b53b 100644 --- a/app/code/Magento/Quote/Plugin/UpdateQuoteItemStore.php +++ b/app/code/Magento/Quote/Plugin/UpdateQuoteItemStore.php @@ -61,9 +61,7 @@ public function afterSwitch( ): string { $quote = $this->checkoutSession->getQuote(); if ($quote->getIsActive()) { - $quote->setStoreId( - $targetStore->getId() - ); + $quote->setStoreId($targetStore->getId()); $quote->getItemsCollection(false); $this->quoteRepository->save($quote); } diff --git a/app/code/Magento/Quote/Test/Unit/Plugin/UpdateQuoteItemStoreTest.php b/app/code/Magento/Quote/Test/Unit/Plugin/UpdateQuoteItemStoreTest.php new file mode 100644 index 0000000000000..f6146c824aabc --- /dev/null +++ b/app/code/Magento/Quote/Test/Unit/Plugin/UpdateQuoteItemStoreTest.php @@ -0,0 +1,143 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Quote\Test\Unit\Plugin; + +use Magento\Quote\Model\ResourceModel\Quote\Item; +use Magento\Store\Model\StoreSwitcherInterface; +use Magento\Quote\Plugin\UpdateQuoteItemStore; +use Magento\Quote\Model\QuoteRepository; +use Magento\Checkout\Model\Session; +use Magento\Store\Model\Store; +use Magento\Quote\Model\Quote; + +/** + * Unit test for Magento\Quote\Plugin\UpdateQuoteItemStore. + */ +class UpdateQuoteItemStoreTest extends \PHPUnit\Framework\TestCase +{ + /** + * @var UpdateQuoteItemStore + */ + private $model; + + /** + * @var StoreSwitcherInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $subjectMock; + + /** + * @var QuoteRepository|\PHPUnit_Framework_MockObject_MockObject + */ + private $quoteRepositoryMock; + + /** + * @var Quote|\PHPUnit_Framework_MockObject_MockObject + */ + private $quoteMock; + + /** + * @var Session|\PHPUnit_Framework_MockObject_MockObject + */ + private $checkoutSessionMock; + + /** + * @var Store|\PHPUnit_Framework_MockObject_MockObject + */ + private $storeMock; + + /** + * @inheritdoc + */ + protected function setUp() + { + $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $this->checkoutSessionMock = $this->createPartialMock( + Session::class, + ['getQuote'] + ); + $this->quoteMock = $this->createPartialMock( + Quote::class, + ['getIsActive', 'setStoreId', 'getItemsCollection'] + ); + $this->storeMock = $this->createPartialMock( + Store::class, + ['getId'] + ); + $this->quoteRepositoryMock = $this->createPartialMock( + QuoteRepository::class, + ['save'] + ); + $this->subjectMock = $this->createMock(StoreSwitcherInterface::class); + + $this->checkoutSessionMock->expects($this->once())->method('getQuote')->willReturn($this->quoteMock); + + $this->model = $objectManager->getObject( + UpdateQuoteItemStore::class, + [ + 'quoteRepository' => $this->quoteRepositoryMock, + 'checkoutSession' => $this->checkoutSessionMock, + ] + ); + } + + /** + * Unit test for afterSwitch method with active quote. + * + * @return void + */ + public function testWithActiveQuote() + { + $storeId = 1; + $this->quoteMock->expects($this->once())->method('getIsActive')->willReturn(true); + $this->storeMock->expects($this->once())->method('getId')->willReturn($storeId); + $this->quoteMock->expects($this->once())->method('setStoreId')->with($storeId)->willReturnSelf(); + $quoteItem = $this->createMock(Item::class); + $this->quoteMock->expects($this->once())->method('getItemsCollection')->willReturnSelf($quoteItem); + + $this->model->afterSwitch( + $this->subjectMock, + 'magento2.loc', + $this->storeMock, + $this->storeMock, + 'magento2.loc' + ); + } + + /** + * Unit test for afterSwitch method without active quote. + * + * @dataProvider getIsActive + * @param bool|null $isActive + * @return void + */ + public function testWithoutActiveQuote($isActive) + { + $this->quoteMock->expects($this->once())->method('getIsActive')->willReturn($isActive); + $this->quoteRepositoryMock->expects($this->never())->method('save'); + + $this->model->afterSwitch( + $this->subjectMock, + 'magento2.loc', + $this->storeMock, + $this->storeMock, + 'magento2.loc' + ); + } + + /** + * Data provider for method testWithoutActiveQuote. + * @return array + */ + public function getIsActive() + { + return [ + [false], + [null], + ]; + } +} From 835cdbeb44c27fa67b1d933dceee33ad4261f0a2 Mon Sep 17 00:00:00 2001 From: Serhii Voloshkov <serhii.voloshkov@transoftgroup.com> Date: Tue, 26 Feb 2019 14:13:15 +0200 Subject: [PATCH 22/65] MAGETWO-95904: Header Minicart, Shopping cart page and Checkout page show incorrect product name --- .../Magento/Checkout/view/frontend/web/js/view/minicart.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/minicart.js b/app/code/Magento/Checkout/view/frontend/web/js/view/minicart.js index da1b1a41e2fa9..5e29fa209a641 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/view/minicart.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/view/minicart.js @@ -102,8 +102,8 @@ define([ self.isLoading(true); }); - if (cartData().website_id !== window.checkout.websiteId - || cartData().store_id !== window.checkout.storeId + if (cartData().website_id !== window.checkout.websiteId || + cartData().store_id !== window.checkout.storeId ) { customerData.reload(['cart'], false); } From 3a68a8de9749280fcc48f10daa85238217fb0bf0 Mon Sep 17 00:00:00 2001 From: Serhii Voloshkov <serhii.voloshkov@transoftgroup.com> Date: Tue, 26 Feb 2019 15:23:04 +0200 Subject: [PATCH 23/65] MAGETWO-94421: Default addresses not selected when checking out from cart --- .../Sales/Test/Mftf/ActionGroup/AdminOrderActionGroup.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOrderActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOrderActionGroup.xml index eabe51776894e..479b631db0b71 100644 --- a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOrderActionGroup.xml +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOrderActionGroup.xml @@ -296,4 +296,10 @@ <waitForElementVisible selector="{{AdminOrderFormPaymentSection.paymentBlock}}" stepKey="waitForPaymentOptions"/> <conditionalClick selector="{{AdminOrderFormPaymentSection.checkMoneyOption}}" dependentSelector="{{AdminOrderFormPaymentSection.checkMoneyOption}}" visible="true" stepKey="checkCheckMoneyOption"/> </actionGroup> + <!--Submit order--> + <actionGroup name="SubmitOrderActionGroup"> + <click selector="{{AdminOrderFormActionSection.submitOrder}}" stepKey="clickSubmitOrder"/> + <waitForElementVisible selector="{{AdminMessagesSection.success}}" stepKey="waitForSuccessMessage"/> + <see selector="{{AdminMessagesSection.success}}" userInput="You created the order." stepKey="seeOrderSuccessMessage"/> + </actionGroup> </actionGroups> From dd8202e943c112b716b80c99a2596b16545b9a00 Mon Sep 17 00:00:00 2001 From: Serhii Voloshkov <serhii.voloshkov@transoftgroup.com> Date: Tue, 26 Feb 2019 17:00:34 +0200 Subject: [PATCH 24/65] MAGETWO-95904: Header Minicart, Shopping cart page and Checkout page show incorrect product name --- ...ProductNameMinicartOnCheckoutPageDifferentStoreViewsTest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontProductNameMinicartOnCheckoutPageDifferentStoreViewsTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontProductNameMinicartOnCheckoutPageDifferentStoreViewsTest.xml index 4622a6bd1ebf6..9fee0302345d5 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontProductNameMinicartOnCheckoutPageDifferentStoreViewsTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontProductNameMinicartOnCheckoutPageDifferentStoreViewsTest.xml @@ -57,7 +57,7 @@ <click selector="{{AdminProductFormActionSection.saveButton}}" stepKey="saveProduct"/> <!--Add product to cart--> - <amOnPage url="{{StorefrontProductPage.url($$createProduct.sku$$)}}" stepKey="amOnProductPage"/> + <amOnPage url="{{StorefrontProductPage.url($$createProduct.custom_attributes[url_key]$$)}}" stepKey="amOnProductPage"/> <actionGroup ref="addToCartFromStorefrontProductPage" stepKey="addToCartFromStorefrontProductPage"> <argument name="productName" value="$createProduct.name$$"/> </actionGroup> From ca2d3bd42541d2b61616f81a69f004a1a07aa483 Mon Sep 17 00:00:00 2001 From: Viktor Sevch <svitja@ukr.net> Date: Wed, 27 Feb 2019 13:00:17 +0200 Subject: [PATCH 25/65] MAGETWO-92495: [Magento Cloud] - Wrong color image when filtering by color filter --- .../Product/Renderer/Listing/Configurable.php | 36 +++++-- app/code/Magento/Swatches/Helper/Data.php | 13 +-- .../Renderer/Listing/ConfigurableTest.php | 100 +++++++++++++++++- .../Swatches/Test/Unit/Helper/DataTest.php | 2 + 4 files changed, 134 insertions(+), 17 deletions(-) diff --git a/app/code/Magento/Swatches/Block/Product/Renderer/Listing/Configurable.php b/app/code/Magento/Swatches/Block/Product/Renderer/Listing/Configurable.php index 85633475205ed..3df47ee749587 100644 --- a/app/code/Magento/Swatches/Block/Product/Renderer/Listing/Configurable.php +++ b/app/code/Magento/Swatches/Block/Product/Renderer/Listing/Configurable.php @@ -8,6 +8,8 @@ use Magento\Catalog\Block\Product\Context; use Magento\Catalog\Helper\Product as CatalogProduct; use Magento\Catalog\Model\Product; +use Magento\Catalog\Model\Layer\Resolver; +use Magento\Catalog\Model\Layer\Category as CategoryLayer; use Magento\ConfigurableProduct\Helper\Data; use Magento\ConfigurableProduct\Model\ConfigurableAttributeData; use Magento\Customer\Helper\Session\CurrentCustomer; @@ -39,6 +41,12 @@ class Configurable extends \Magento\Swatches\Block\Product\Renderer\Configurable private $variationPrices; /** + * @var \Magento\Catalog\Model\Layer\Resolver + */ + private $layerResolver; + + /** + * @SuppressWarnings(PHPMD.ExcessiveParameterList) * @param Context $context * @param ArrayUtils $arrayUtils * @param EncoderInterface $jsonEncoder @@ -49,11 +57,11 @@ class Configurable extends \Magento\Swatches\Block\Product\Renderer\Configurable * @param ConfigurableAttributeData $configurableAttributeData * @param SwatchData $swatchHelper * @param Media $swatchMediaHelper - * @param array $data other data - * @param SwatchAttributesProvider $swatchAttributesProvider + * @param array $data + * @param SwatchAttributesProvider|null $swatchAttributesProvider * @param \Magento\Framework\Locale\Format|null $localeFormat * @param \Magento\ConfigurableProduct\Model\Product\Type\Configurable\Variations\Prices|null $variationPrices - * @SuppressWarnings(PHPMD.ExcessiveParameterList) + * @param Resolver $layerResolver */ public function __construct( Context $context, @@ -69,7 +77,8 @@ public function __construct( array $data = [], SwatchAttributesProvider $swatchAttributesProvider = null, \Magento\Framework\Locale\Format $localeFormat = null, - \Magento\ConfigurableProduct\Model\Product\Type\Configurable\Variations\Prices $variationPrices = null + \Magento\ConfigurableProduct\Model\Product\Type\Configurable\Variations\Prices $variationPrices = null, + Resolver $layerResolver = null ) { parent::__construct( $context, @@ -91,10 +100,11 @@ public function __construct( $this->variationPrices = $variationPrices ?: ObjectManager::getInstance()->get( \Magento\ConfigurableProduct\Model\Product\Type\Configurable\Variations\Prices::class ); + $this->layerResolver = $layerResolver ?: ObjectManager::getInstance()->get(Resolver::class); } /** - * @return string + * @inheritdoc */ protected function getRendererTemplate() { @@ -120,7 +130,7 @@ protected function _toHtml() } /** - * @return array + * @inheritdoc */ protected function getSwatchAttributesData() { @@ -182,6 +192,7 @@ protected function getOptionImages() * Add images to result json config in case of Layered Navigation is used * * @return array + * @SuppressWarnings(PHPMD.RequestAwareBlockMethod) * @since 100.2.0 */ protected function _getAdditionalConfig() @@ -246,4 +257,17 @@ private function getLayeredAttributesIfExists(Product $configurableProduct, arra return $layeredAttributes; } + + /** + * @inheritdoc + */ + public function getCacheKeyInfo() + { + $cacheKeyInfo = parent::getCacheKeyInfo(); + /** @var CategoryLayer $catalogLayer */ + $catalogLayer = $this->layerResolver->get(); + $cacheKeyInfo[] = $catalogLayer->getStateKey(); + + return $cacheKeyInfo; + } } diff --git a/app/code/Magento/Swatches/Helper/Data.php b/app/code/Magento/Swatches/Helper/Data.php index ae35f5203dd73..2c00224083bfc 100644 --- a/app/code/Magento/Swatches/Helper/Data.php +++ b/app/code/Magento/Swatches/Helper/Data.php @@ -249,18 +249,15 @@ public function loadVariationByFallback(Product $parentProduct, array $attribute $this->addFilterByParent($productCollection, $parentId); $configurableAttributes = $this->getAttributesFromConfigurable($parentProduct); - $allAttributesArray = []; + + $resultAttributesToFilter = []; foreach ($configurableAttributes as $attribute) { - if (!empty($attribute['default_value'])) { - $allAttributesArray[$attribute['attribute_code']] = $attribute['default_value']; + $attributeCode = $attribute->getData('attribute_code'); + if (array_key_exists($attributeCode, $attributes)) { + $resultAttributesToFilter[$attributeCode] = $attributes[$attributeCode]; } } - $resultAttributesToFilter = array_merge( - $attributes, - array_diff_key($allAttributesArray, $attributes) - ); - $this->addFilterByAttributes($productCollection, $resultAttributesToFilter); $variationProduct = $productCollection->getFirstItem(); diff --git a/app/code/Magento/Swatches/Test/Unit/Block/Product/Renderer/Listing/ConfigurableTest.php b/app/code/Magento/Swatches/Test/Unit/Block/Product/Renderer/Listing/ConfigurableTest.php index 6b72422d05014..adcdcad25e337 100644 --- a/app/code/Magento/Swatches/Test/Unit/Block/Product/Renderer/Listing/ConfigurableTest.php +++ b/app/code/Magento/Swatches/Test/Unit/Block/Product/Renderer/Listing/ConfigurableTest.php @@ -61,6 +61,18 @@ class ConfigurableTest extends \PHPUnit\Framework\TestCase /** @var \PHPUnit_Framework_MockObject_MockObject */ private $variationPricesMock; + /** @var \PHPUnit_Framework_MockObject_MockObject */ + private $layerResolverMock; + + /** @var ObjectManagerHelper */ + private $objectManagerHelper; + + /** @var \Magento\Store\Model\StoreManagerInterface|\PHPUnit_Framework_MockObject_MockObject */ + private $storeManagerMock; + + /** @var \Magento\Customer\Model\Session|\PHPUnit_Framework_MockObject_MockObject */ + private $customerSessionMock; + public function setUp() { $this->arrayUtils = $this->createMock(\Magento\Framework\Stdlib\ArrayUtils::class); @@ -82,9 +94,35 @@ public function setUp() $this->variationPricesMock = $this->createMock( \Magento\ConfigurableProduct\Model\Product\Type\Configurable\Variations\Prices::class ); + $this->layerResolverMock = $this->createMock(\Magento\Catalog\Model\Layer\Resolver::class); + + $this->storeManagerMock = $this->getMockBuilder(\Magento\Store\Model\StoreManagerInterface::class) + ->setMethods(['getStore']) + ->getMockForAbstractClass(); + $this->customerSessionMock = $this->getMockBuilder(\Magento\Customer\Model\Session::class) + ->disableOriginalConstructor() + ->setMethods(['getCustomerGroupId']) + ->getMock(); + + $this->objectManagerHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $this->prepareObjectManager([ + [ + \Magento\Framework\Locale\Format::class, + $this->createMock(\Magento\Framework\Locale\Format::class), + ], + [ + \Magento\ConfigurableProduct\Model\Product\Type\Configurable\Variations\Prices::class, + $this->createMock( + \Magento\ConfigurableProduct\Model\Product\Type\Configurable\Variations\Prices::class + ), + ], + [ + \Magento\Customer\Model\Session::class, + $this->customerSessionMock, + ], + ]); - $objectManagerHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); - $this->configurable = $objectManagerHelper->getObject( + $this->configurable = $this->objectManagerHelper->getObject( \Magento\Swatches\Block\Product\Renderer\Listing\Configurable::class, [ 'scopeConfig' => $this->scopeConfig, @@ -100,9 +138,15 @@ public function setUp() 'priceCurrency' => $this->priceCurrency, 'configurableAttributeData' => $this->configurableAttributeData, 'data' => [], - 'variationPrices' => $this->variationPricesMock + 'variationPrices' => $this->variationPricesMock, + 'layerResolver' => $this->layerResolverMock, ] ); + $this->objectManagerHelper->setBackwardCompatibleProperty( + $this->configurable, + '_storeManager', + $this->storeManagerMock + ); } /** @@ -235,4 +279,54 @@ public function testGetPricesJson() $this->jsonEncoder->expects($this->once())->method('encode')->with($expectedPrices); $this->configurable->getPricesJson(); } + + /** + * @param $map + */ + private function prepareObjectManager($map) + { + $objectManagerMock = $this->getMockBuilder(\Magento\Framework\ObjectManagerInterface::class) + ->setMethods(['getInstance']) + ->getMockForAbstractClass(); + $objectManagerMock->expects($this->any())->method('getInstance')->willReturnSelf(); + $objectManagerMock->expects($this->any()) + ->method('get') + ->will($this->returnValueMap($map)); + $reflectionClass = new \ReflectionClass(\Magento\Framework\App\ObjectManager::class); + $reflectionProperty = $reflectionClass->getProperty('_instance'); + $reflectionProperty->setAccessible(true); + $reflectionProperty->setValue($objectManagerMock); + } + + /** + * Test receiving cache key info. + */ + public function testGetCacheKeyInfo() + { + $expected = [ + 0 => 'BLOCK_TPL', + 1 => 'default', + 2 => NULL, + 'base_url' => NULL, + 'template' => NULL, + 3 => 'USD', + 4 => NULL, + 5 => 'STORE_1_CAT_25_CUSTGROUP_0_color_53', + ]; + $stateKey = 'STORE_1_CAT_25_CUSTGROUP_0_color_53'; + + $storeMock = $this->getMockBuilder(\Magento\Store\Api\Data\StoreInterface::class)->getMockForAbstractClass(); + $storeMock->expects($this->any())->method('getCode')->willReturn('default'); + $this->storeManagerMock->expects($this->any())->method('getStore')->willReturn($storeMock); + $currency = $this->getMockBuilder(\Magento\Directory\Model\Currency::class) + ->disableOriginalConstructor() + ->getMock(); + $this->priceCurrency->expects($this->once())->method('getCurrency')->willReturn($currency); + $currency->expects($this->once())->method('getCode')->willReturn('USD'); + $layer = $this->createMock(\Magento\Catalog\Model\Layer::class); + $this->layerResolverMock->expects($this->once())->method('get')->willReturn($layer); + $layer->expects($this->once())->method('getStateKey')->willReturn($stateKey); + + $this->assertEquals($this->configurable->getCacheKeyInfo(), $expected); + } } diff --git a/app/code/Magento/Swatches/Test/Unit/Helper/DataTest.php b/app/code/Magento/Swatches/Test/Unit/Helper/DataTest.php index 5732018f7615f..58f9ea821f0b4 100644 --- a/app/code/Magento/Swatches/Test/Unit/Helper/DataTest.php +++ b/app/code/Magento/Swatches/Test/Unit/Helper/DataTest.php @@ -278,6 +278,8 @@ public function testLoadVariationByFallback($product) $metadataMock = $this->createMock(\Magento\Framework\EntityManager\EntityMetadataInterface::class); $this->metaDataPoolMock->expects($this->once())->method('getMetadata')->willReturn($metadataMock); $metadataMock->expects($this->once())->method('getLinkField')->willReturn('id'); + $this->productMock->expects($this->once())->method('getTypeInstance')->willReturn($this->configurableMock); + $this->attributeMock->method('getData')->with('attribute_code')->willReturn('color'); $this->getSwatchAttributes($product); From e5145576095fe77d839e138f68fbf9e4f49c21fc Mon Sep 17 00:00:00 2001 From: Viktor Sevch <svitja@ukr.net> Date: Wed, 27 Feb 2019 14:28:00 +0200 Subject: [PATCH 26/65] MAGETWO-92495: [Magento Cloud] - Wrong color image when filtering by color filter --- .../Block/Product/Renderer/Listing/ConfigurableTest.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Swatches/Test/Unit/Block/Product/Renderer/Listing/ConfigurableTest.php b/app/code/Magento/Swatches/Test/Unit/Block/Product/Renderer/Listing/ConfigurableTest.php index adcdcad25e337..fce0f6609ad73 100644 --- a/app/code/Magento/Swatches/Test/Unit/Block/Product/Renderer/Listing/ConfigurableTest.php +++ b/app/code/Magento/Swatches/Test/Unit/Block/Product/Renderer/Listing/ConfigurableTest.php @@ -306,11 +306,11 @@ public function testGetCacheKeyInfo() $expected = [ 0 => 'BLOCK_TPL', 1 => 'default', - 2 => NULL, - 'base_url' => NULL, - 'template' => NULL, + 2 => null, + 'base_url' => null, + 'template' => null, 3 => 'USD', - 4 => NULL, + 4 => null, 5 => 'STORE_1_CAT_25_CUSTGROUP_0_color_53', ]; $stateKey = 'STORE_1_CAT_25_CUSTGROUP_0_color_53'; From 77391fca341d90c63a1d04e66bc7c4c434bd6a71 Mon Sep 17 00:00:00 2001 From: Viktor Sevch <svitja@ukr.net> Date: Thu, 28 Feb 2019 13:37:07 +0200 Subject: [PATCH 27/65] MAGETWO-92495: [Magento Cloud] - Wrong color image when filtering by color filter --- .../Unit/Block/Product/Renderer/Listing/ConfigurableTest.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/code/Magento/Swatches/Test/Unit/Block/Product/Renderer/Listing/ConfigurableTest.php b/app/code/Magento/Swatches/Test/Unit/Block/Product/Renderer/Listing/ConfigurableTest.php index fce0f6609ad73..a876a4dcc85c1 100644 --- a/app/code/Magento/Swatches/Test/Unit/Block/Product/Renderer/Listing/ConfigurableTest.php +++ b/app/code/Magento/Swatches/Test/Unit/Block/Product/Renderer/Listing/ConfigurableTest.php @@ -73,6 +73,9 @@ class ConfigurableTest extends \PHPUnit\Framework\TestCase /** @var \Magento\Customer\Model\Session|\PHPUnit_Framework_MockObject_MockObject */ private $customerSessionMock; + /** + * @inheritdoc + */ public function setUp() { $this->arrayUtils = $this->createMock(\Magento\Framework\Stdlib\ArrayUtils::class); From eaad776629a933b944663ef35c4bac08143d0592 Mon Sep 17 00:00:00 2001 From: Jitheesh <jitheeshvo@gmail.com> Date: Fri, 22 Feb 2019 10:01:45 +0530 Subject: [PATCH 28/65] As low as displays incorrect pricing on category page, tax appears to be added twice #21383 - excluded tax from min price --- .../Catalog/Pricing/Price/MinimalTierPriceCalculator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Pricing/Price/MinimalTierPriceCalculator.php b/app/code/Magento/Catalog/Pricing/Price/MinimalTierPriceCalculator.php index 387ef9416ef68..af81e67e86fce 100644 --- a/app/code/Magento/Catalog/Pricing/Price/MinimalTierPriceCalculator.php +++ b/app/code/Magento/Catalog/Pricing/Price/MinimalTierPriceCalculator.php @@ -58,6 +58,6 @@ public function getAmount(SaleableInterface $saleableItem) return $value === null ? null - : $this->calculator->getAmount($value, $saleableItem); + : $this->calculator->getAmount($value, $saleableItem, 'tax'); } } From aa7fee51fb66d75800c7c454da013b75d565ebe4 Mon Sep 17 00:00:00 2001 From: nmalevanec <mikola.malevanec@transoftgroup.com> Date: Tue, 26 Feb 2019 11:57:48 +0200 Subject: [PATCH 29/65] Fix static tests. --- .../Pricing/Price/MinimalTierPriceCalculator.php | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Catalog/Pricing/Price/MinimalTierPriceCalculator.php b/app/code/Magento/Catalog/Pricing/Price/MinimalTierPriceCalculator.php index af81e67e86fce..a5e573caa381e 100644 --- a/app/code/Magento/Catalog/Pricing/Price/MinimalTierPriceCalculator.php +++ b/app/code/Magento/Catalog/Pricing/Price/MinimalTierPriceCalculator.php @@ -29,8 +29,10 @@ public function __construct(CalculatorInterface $calculator) } /** - * Get raw value of "as low as" as a minimal among tier prices - * {@inheritdoc} + * Get raw value of "as low as" as a minimal among tier prices{@inheritdoc} + * + * @param SaleableInterface $saleableItem + * @return float|null */ public function getValue(SaleableInterface $saleableItem) { @@ -49,8 +51,10 @@ public function getValue(SaleableInterface $saleableItem) } /** - * Return calculated amount object that keeps "as low as" value - * {@inheritdoc} + * Return calculated amount object that keeps "as low as" value{@inheritdoc} + * + * @param SaleableInterface $saleableItem + * @return AmountInterface|null */ public function getAmount(SaleableInterface $saleableItem) { From 7bb5dd47e92e4d20da612e62bae7822de48d1bee Mon Sep 17 00:00:00 2001 From: Wojtek Naruniec <wojtek@mediotype.com> Date: Mon, 18 Feb 2019 13:16:20 +0100 Subject: [PATCH 30/65] Skip cart validation if empty cart action is executed --- .../view/frontend/web/js/action/update-shopping-cart.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/code/Magento/Checkout/view/frontend/web/js/action/update-shopping-cart.js b/app/code/Magento/Checkout/view/frontend/web/js/action/update-shopping-cart.js index ce1527b3d72d6..9d79e34b10f17 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/action/update-shopping-cart.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/action/update-shopping-cart.js @@ -35,6 +35,11 @@ define([ return true; } + var action = this.element.find('#update_cart_action_container').val(); + if (action === 'empty_cart') { + return true; + } + if (this.isValid()) { event.preventDefault(); this.validateItems(this.options.validationURL, this.element.serialize()); From 847115efd5068b40a4d274702d6086f0d6549adc Mon Sep 17 00:00:00 2001 From: Wojtek Naruniec <wojtek@mediotype.com> Date: Fri, 22 Feb 2019 10:17:42 +0100 Subject: [PATCH 31/65] Move element id to component parameters, fix JS coding style --- .../Checkout/view/frontend/templates/cart/form.phtml | 3 ++- .../view/frontend/web/js/action/update-shopping-cart.js | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Checkout/view/frontend/templates/cart/form.phtml b/app/code/Magento/Checkout/view/frontend/templates/cart/form.phtml index 1005c11e44d95..84ab9b13d8f3a 100644 --- a/app/code/Magento/Checkout/view/frontend/templates/cart/form.phtml +++ b/app/code/Magento/Checkout/view/frontend/templates/cart/form.phtml @@ -14,7 +14,8 @@ method="post" id="form-validate" data-mage-init='{"Magento_Checkout/js/action/update-shopping-cart": - {"validationURL" : "/checkout/cart/updateItemQty"} + {"validationURL" : "/checkout/cart/updateItemQty", + "updateCartActionContainer": "#update_cart_action_container"} }' class="form form-cart"> <?= $block->getBlockHtml('formkey') ?> diff --git a/app/code/Magento/Checkout/view/frontend/web/js/action/update-shopping-cart.js b/app/code/Magento/Checkout/view/frontend/web/js/action/update-shopping-cart.js index 9d79e34b10f17..7686dcad6e050 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/action/update-shopping-cart.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/action/update-shopping-cart.js @@ -14,7 +14,8 @@ define([ $.widget('mage.updateShoppingCart', { options: { validationURL: '', - eventName: 'updateCartItemQty' + eventName: 'updateCartItemQty', + updateCartActionContainer: '' }, /** @inheritdoc */ @@ -31,11 +32,12 @@ define([ * @return {Boolean} */ onSubmit: function (event) { + var action = this.element.find(this.options.updateCartActionContainer).val(); + if (!this.options.validationURL) { return true; } - var action = this.element.find('#update_cart_action_container').val(); if (action === 'empty_cart') { return true; } From 42b03bb7cd92320bb6b689b82101ac4eb91b1b93 Mon Sep 17 00:00:00 2001 From: Oleksandr Kravchuk <swnsma@gmail.com> Date: Fri, 22 Feb 2019 13:46:04 +0200 Subject: [PATCH 32/65] Simplify. --- .../view/frontend/web/js/action/update-shopping-cart.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/app/code/Magento/Checkout/view/frontend/web/js/action/update-shopping-cart.js b/app/code/Magento/Checkout/view/frontend/web/js/action/update-shopping-cart.js index 7686dcad6e050..1920bc4d7ac41 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/action/update-shopping-cart.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/action/update-shopping-cart.js @@ -34,11 +34,7 @@ define([ onSubmit: function (event) { var action = this.element.find(this.options.updateCartActionContainer).val(); - if (!this.options.validationURL) { - return true; - } - - if (action === 'empty_cart') { + if (!this.options.validationURL || action === 'empty_cart') { return true; } From 13c6edd690905c704cb69ff245d5ce7faff0aefe Mon Sep 17 00:00:00 2001 From: Ilan Parmentier <ilan.parmentier@artbambou.com> Date: Thu, 31 Jan 2019 14:44:29 +0100 Subject: [PATCH 33/65] Update details.phtml Good afternoon, I just encountered a problem with product's tabs in product info. I realized when description or other custom tabs have links, when you click on it, nothing happen. It caused by the script mage/tabs.js in details.phtml. The current link to trigger the tab is declared with data-role="switch" instead of a data-role="trigger". https://github.com/magento/magento2/blob/4f232511ceba6f1f7bf6f73b3b5609bd087f8c74/app/code/Magento/Catalog/view/frontend/templates/product/view/details.phtml#L24-L37 When not even the trigger and the header is declared respectively by data-role="heading" and data-role="trigger", the script based it search on the current collapsible panel declared by data-role="collapsible". https://github.com/magento/magento2/blob/4f232511ceba6f1f7bf6f73b3b5609bd087f8c74/lib/web/mage/tabs.js#L99-L124 You can simply try by adding a link in the product description. Tell me if I am wrong. Cheers, Ilan PARMENTIER --- .../Catalog/view/frontend/templates/product/view/details.phtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/view/frontend/templates/product/view/details.phtml b/app/code/Magento/Catalog/view/frontend/templates/product/view/details.phtml index 038bea86e7d4e..bbbc950e6712e 100644 --- a/app/code/Magento/Catalog/view/frontend/templates/product/view/details.phtml +++ b/app/code/Magento/Catalog/view/frontend/templates/product/view/details.phtml @@ -25,7 +25,7 @@ data-role="collapsible" id="tab-label-<?= /* @escapeNotVerified */ $alias ?>"> <a class="data switch" tabindex="-1" - data-toggle="switch" + data-toggle="trigger" href="#<?= /* @escapeNotVerified */ $alias ?>" id="tab-label-<?= /* @escapeNotVerified */ $alias ?>-title"> <?= /* @escapeNotVerified */ $label ?> From e5676cfb72590fff072c8dfff931740587ff2213 Mon Sep 17 00:00:00 2001 From: Ilan Parmentier <ilan.parmentier@artbambou.com> Date: Mon, 18 Feb 2019 15:37:52 +0100 Subject: [PATCH 34/65] Misconfigured aria-labelledby for product tabs Good afternoon, I find out attribute aria-labelledby is misconfigured. It must be declared for the content of the tab and not the title, in particular, for a parent tag. Ilan PARMENTIER Source : https://www.w3.org/TR/wai-aria-practices/examples/tabs/tabs-1/tabs.html#sc1_label --- .../view/frontend/templates/product/view/details.phtml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Catalog/view/frontend/templates/product/view/details.phtml b/app/code/Magento/Catalog/view/frontend/templates/product/view/details.phtml index 038bea86e7d4e..19a058006b18c 100644 --- a/app/code/Magento/Catalog/view/frontend/templates/product/view/details.phtml +++ b/app/code/Magento/Catalog/view/frontend/templates/product/view/details.phtml @@ -21,7 +21,6 @@ $label = $block->getChildData($alias, 'title'); ?> <div class="data item title" - aria-labelledby="tab-label-<?= /* @escapeNotVerified */ $alias ?>-title" data-role="collapsible" id="tab-label-<?= /* @escapeNotVerified */ $alias ?>"> <a class="data switch" tabindex="-1" @@ -31,7 +30,8 @@ <?= /* @escapeNotVerified */ $label ?> </a> </div> - <div class="data item content" id="<?= /* @escapeNotVerified */ $alias ?>" data-role="content"> + <div class="data item content" + aria-labelledby="tab-label-<?= /* @escapeNotVerified */ $alias ?>-title" id="<?= /* @escapeNotVerified */ $alias ?>" data-role="content"> <?= /* @escapeNotVerified */ $html ?> </div> <?php endforeach;?> From 42d7504d1def753cf8bedfdac9b1b4a7d165aab8 Mon Sep 17 00:00:00 2001 From: Viktor Petryk <victor.petryk@transoftgroup.com> Date: Mon, 4 Mar 2019 10:11:49 +0200 Subject: [PATCH 35/65] MAGETWO-94190: [Magento Cloud] Error when saving Bundle product --- .../Unit/Model/Product/SaveHandlerTest.php | 275 ++++++++++++++++++ 1 file changed, 275 insertions(+) create mode 100644 app/code/Magento/Bundle/Test/Unit/Model/Product/SaveHandlerTest.php diff --git a/app/code/Magento/Bundle/Test/Unit/Model/Product/SaveHandlerTest.php b/app/code/Magento/Bundle/Test/Unit/Model/Product/SaveHandlerTest.php new file mode 100644 index 0000000000000..94e5b72b10e3c --- /dev/null +++ b/app/code/Magento/Bundle/Test/Unit/Model/Product/SaveHandlerTest.php @@ -0,0 +1,275 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Bundle\Test\Unit\Model\Product; + +use Magento\Bundle\Api\Data\LinkInterface; +use Magento\Bundle\Api\Data\OptionInterface; +use Magento\Bundle\Api\ProductLinkManagementInterface; +use Magento\Bundle\Api\ProductOptionRepositoryInterface; +use Magento\Bundle\Model\Product\SaveHandler; +use Magento\Catalog\Api\Data\ProductExtensionInterface; +use Magento\Catalog\Api\Data\ProductInterface; +use Magento\Framework\EntityManager\EntityMetadataInterface; +use Magento\Framework\EntityManager\MetadataPool; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use PHPUnit_Framework_MockObject_MockObject as MockObject; + +class SaveHandlerTest extends \PHPUnit\Framework\TestCase +{ + /** + * @var ObjectManager + */ + private $objectManager; + /** + * @var ProductInterface|MockObject + */ + private $productMock; + + /** + * @var ProductExtensionInterface|MockObject + */ + private $productExtensionMock; + + /** + * @var OptionInterface|MockObject + */ + private $optionMock; + + /** + * @var ProductOptionRepositoryInterface|MockObject + */ + private $optionRepositoryMock; + + /** + * @var ProductLinkManagementInterface|MockObject + */ + private $productLinkManagementMock; + + /** + * @var LinkInterface|MockObject + */ + private $linkMock; + + /** + * @var MetadataPool|MockObject + */ + private $metadataPoolMock; + + /** + * @var EntityMetadataInterface|MockObject + */ + private $metadataMock; + + /** + * @var SaveHandler + */ + private $saveHandler; + + /** + * @inheritdoc + */ + protected function setUp() + { + $this->objectManager = new ObjectManager($this); + + $this->productMock = $this->getMockBuilder(ProductInterface::class) + ->setMethods( + [ + 'getExtensionAttributes', + 'getCopyFromView', + 'getData', + 'getTypeId', + 'getSku', + ] + ) + ->getMockForAbstractClass(); + $this->productExtensionMock = $this->getMockBuilder(ProductExtensionInterface::class) + ->setMethods(['getBundleProductOptions']) + ->getMockForAbstractClass(); + $this->optionMock = $this->getMockBuilder(OptionInterface::class) + ->setMethods( + [ + 'setParentId', + 'getId', + 'getOptionId', + ] + ) + ->getMockForAbstractClass(); + $this->optionRepositoryMock = $this->createMock(ProductOptionRepositoryInterface::class); + $this->productLinkManagementMock = $this->createMock(ProductLinkManagementInterface::class); + $this->linkMock = $this->createMock(LinkInterface::class); + $this->metadataPoolMock = $this->createMock(MetadataPool::class); + $this->metadataMock = $this->createMock(EntityMetadataInterface::class); + $this->metadataPoolMock->expects($this->any()) + ->method('getMetadata') + ->willReturn($this->metadataMock); + + $this->saveHandler = $this->objectManager->getObject( + SaveHandler::class, + [ + 'optionRepository' => $this->optionRepositoryMock, + 'productLinkManagement' => $this->productLinkManagementMock, + 'metadataPool' => $this->metadataPoolMock, + ] + ); + } + + /** + * @return void + */ + public function testExecuteWithInvalidProductType() + { + $productType = 'simple'; + + $this->productMock->expects($this->once()) + ->method('getExtensionAttributes') + ->willReturn($this->productExtensionMock); + $this->productExtensionMock->expects($this->once()) + ->method('getBundleProductOptions') + ->willReturn([]); + $this->productMock->expects($this->once()) + ->method('getTypeId') + ->willReturn($productType); + + $entity = $this->saveHandler->execute($this->productMock); + $this->assertSame($this->productMock, $entity); + } + + /** + * @return void + */ + public function testExecuteWithoutExistingOption() + { + $productType = 'bundle'; + $productSku = 'product-sku'; + $optionId = ''; + + $this->productMock->expects($this->once()) + ->method('getExtensionAttributes') + ->willReturn($this->productExtensionMock); + $this->productExtensionMock->expects($this->once()) + ->method('getBundleProductOptions') + ->willReturn([$this->optionMock]); + + $this->productMock->expects($this->once()) + ->method('getTypeId') + ->willReturn($productType); + + $this->productMock->expects($this->once()) + ->method('getSku') + ->willReturn($productSku); + $this->optionRepositoryMock->expects($this->once()) + ->method('getList') + ->with($productSku) + ->willReturn([]); + + $this->optionMock->expects($this->any()) + ->method('getOptionId') + ->willReturn($optionId); + + $this->productMock->expects($this->once()) + ->method('getCopyFromView') + ->willReturn(false); + + $this->optionMock->expects($this->never())->method('setOptionId'); + $this->optionRepositoryMock->expects($this->once()) + ->method('save') + ->with($this->productMock, $this->optionMock) + ->willReturn($optionId); + + $this->saveHandler->execute($this->productMock); + } + + /** + * @return void + */ + public function testExecuteWithExistingOption() + { + $productType = 'bundle'; + $productSku = 'product-sku'; + $productLinkSku = 'product-link-sku'; + $linkField = 'entity_id'; + $parentId = 1; + $existingOptionId = 1; + $optionId = 2; + + /** @var OptionInterface|MockObject $existingOptionMock */ + $existingOptionMock = $this->getMockBuilder(OptionInterface::class) + ->setMethods(['getOptionId']) + ->getMockForAbstractClass(); + + $this->productMock->expects($this->once()) + ->method('getExtensionAttributes') + ->willReturn($this->productExtensionMock); + $this->productExtensionMock->expects($this->once()) + ->method('getBundleProductOptions') + ->willReturn([$this->optionMock]); + $this->productMock->expects($this->once()) + ->method('getTypeId') + ->willReturn($productType); + + $this->productMock->expects($this->exactly(3)) + ->method('getSku') + ->willReturn($productSku); + $this->optionRepositoryMock->expects($this->once()) + ->method('getList') + ->with($productSku) + ->willReturn([$existingOptionMock]); + + $existingOptionMock->expects($this->any()) + ->method('getOptionId') + ->willReturn($existingOptionId); + $this->optionMock->expects($this->any()) + ->method('getOptionId') + ->willReturn($optionId); + + $this->productMock->expects($this->once()) + ->method('getCopyFromView') + ->willReturn(false); + $this->metadataMock->expects($this->once()) + ->method('getLinkField') + ->willReturn($linkField); + $this->productMock->expects($this->once()) + ->method('getData') + ->with($linkField) + ->willReturn($parentId); + + $this->optionRepositoryMock->expects($this->once()) + ->method('get') + ->with($productSku, $existingOptionId) + ->willReturn($this->optionMock); + $this->optionMock->expects($this->once()) + ->method('setParentId') + ->with($parentId) + ->willReturnSelf(); + $this->optionMock->expects($this->once()) + ->method('getProductLinks') + ->willReturn([$this->linkMock]); + $this->linkMock->expects($this->once()) + ->method('getSku') + ->willReturn($productLinkSku); + + $this->optionMock->expects($this->any()) + ->method('getId') + ->willReturn($existingOptionId); + $this->productLinkManagementMock->expects($this->once()) + ->method('removeChild') + ->with($productSku, $existingOptionId, $productLinkSku) + ->willReturn(true); + $this->optionRepositoryMock->expects($this->once()) + ->method('delete') + ->with($this->optionMock) + ->willReturn(true); + + $this->optionRepositoryMock->expects($this->once()) + ->method('save') + ->with($this->productMock, $this->optionMock) + ->willReturn($optionId); + + $this->saveHandler->execute($this->productMock); + } +} From 41e694f19ab1c66019abad1910bb9fe8fb0d9a3a Mon Sep 17 00:00:00 2001 From: Viktor Petryk <victor.petryk@transoftgroup.com> Date: Mon, 4 Mar 2019 17:14:45 +0200 Subject: [PATCH 36/65] MAGETWO-94190: [Magento Cloud] Error when saving Bundle product --- .../Bundle/Test/Unit/Model/Product/SaveHandlerTest.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/code/Magento/Bundle/Test/Unit/Model/Product/SaveHandlerTest.php b/app/code/Magento/Bundle/Test/Unit/Model/Product/SaveHandlerTest.php index 94e5b72b10e3c..a5b9fb4e1b268 100644 --- a/app/code/Magento/Bundle/Test/Unit/Model/Product/SaveHandlerTest.php +++ b/app/code/Magento/Bundle/Test/Unit/Model/Product/SaveHandlerTest.php @@ -18,12 +18,16 @@ use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; use PHPUnit_Framework_MockObject_MockObject as MockObject; +/** + * Unit tests for \Magento\Bundle\Model\Product\SaveHandler class. + */ class SaveHandlerTest extends \PHPUnit\Framework\TestCase { /** * @var ObjectManager */ private $objectManager; + /** * @var ProductInterface|MockObject */ From 080743fba05fdcc4cfb98fd9bcdc15e39d7e02d9 Mon Sep 17 00:00:00 2001 From: Shikha Mishra <shikhamishra@cedcoss.com> Date: Mon, 25 Feb 2019 22:38:49 +0530 Subject: [PATCH 37/65] Fixed #21425 Date design change show not correctly value in backend --- .../Magento/Backend/Block/System/Design/Edit/Tab/General.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Backend/Block/System/Design/Edit/Tab/General.php b/app/code/Magento/Backend/Block/System/Design/Edit/Tab/General.php index 5a09e1f17f617..3fe187e6e7694 100644 --- a/app/code/Magento/Backend/Block/System/Design/Edit/Tab/General.php +++ b/app/code/Magento/Backend/Block/System/Design/Edit/Tab/General.php @@ -90,7 +90,7 @@ protected function _prepareForm() ] ); - $dateFormat = $this->_localeDate->getDateFormat(\IntlDateFormatter::SHORT); + $dateFormat = $this->_localeDate->getDateFormatWithLongYear(); $fieldset->addField( 'date_from', 'date', From 2b41017794d74966ed2df9932d7d1d33518475f1 Mon Sep 17 00:00:00 2001 From: nmalevanec <mikola.malevanec@transoftgroup.com> Date: Thu, 28 Feb 2019 10:36:58 +0200 Subject: [PATCH 38/65] Fix static tests. --- .../Magento/Backend/Block/System/Design/Edit/Tab/General.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/code/Magento/Backend/Block/System/Design/Edit/Tab/General.php b/app/code/Magento/Backend/Block/System/Design/Edit/Tab/General.php index 3fe187e6e7694..6004d08b4b738 100644 --- a/app/code/Magento/Backend/Block/System/Design/Edit/Tab/General.php +++ b/app/code/Magento/Backend/Block/System/Design/Edit/Tab/General.php @@ -6,6 +6,9 @@ namespace Magento\Backend\Block\System\Design\Edit\Tab; +/** + * General system tab block. + */ class General extends \Magento\Backend\Block\Widget\Form\Generic { /** From b169fe3f94c7107bb9f88380b530d00a812f765a Mon Sep 17 00:00:00 2001 From: Jitheesh <jitheeshvo@gmail.com> Date: Wed, 20 Feb 2019 16:14:06 +0530 Subject: [PATCH 39/65] Checkout Page Cancel button is not working #21327 - hide cancel button if billing address is not available on current quote --- .../Checkout/view/frontend/web/js/view/billing-address.js | 6 ++++++ .../view/frontend/web/template/billing-address.html | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/billing-address.js b/app/code/Magento/Checkout/view/frontend/web/js/view/billing-address.js index 6f9a1a46826da..121a94a14852f 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/view/billing-address.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/view/billing-address.js @@ -201,6 +201,12 @@ function ( this.isAddressDetailsVisible(true); } }, + /** + * Manage cancel button visibility + */ + canUseCancelBillingAddress: ko.computed(function () { + return quote.billingAddress() || lastSelectedBillingAddress; + }), /** * Restore billing address diff --git a/app/code/Magento/Checkout/view/frontend/web/template/billing-address.html b/app/code/Magento/Checkout/view/frontend/web/template/billing-address.html index 5f735fbb4daa9..63edb5057b933 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/billing-address.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/billing-address.html @@ -22,7 +22,7 @@ <button class="action action-update" type="button" data-bind="click: updateAddress"> <span data-bind="i18n: 'Update'"></span> </button> - <button class="action action-cancel" type="button" data-bind="click: cancelAddressEdit"> + <button class="action action-cancel" type="button" data-bind="click: cancelAddressEdit, visible: canUseCancelBillingAddress()"> <span data-bind="i18n: 'Cancel'"></span> </button> </div> From b2d04ca9882e660cf60de599b1446620f5f5ae91 Mon Sep 17 00:00:00 2001 From: Jitheesh <jitheeshvo@gmail.com> Date: Thu, 21 Feb 2019 10:28:32 +0530 Subject: [PATCH 40/65] Checkout Page Cancel button is not working #21327 - CR fix --- .../Checkout/view/frontend/web/js/view/billing-address.js | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/billing-address.js b/app/code/Magento/Checkout/view/frontend/web/js/view/billing-address.js index 121a94a14852f..4ea6fb5e5df75 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/view/billing-address.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/view/billing-address.js @@ -201,6 +201,7 @@ function ( this.isAddressDetailsVisible(true); } }, + /** * Manage cancel button visibility */ From b4af1319de272df127c3a4c0945e871f258f91ab Mon Sep 17 00:00:00 2001 From: Jitheesh <jitheeshvo@gmail.com> Date: Fri, 22 Feb 2019 11:21:44 +0530 Subject: [PATCH 41/65] Checkout Page Cancel button is not working - Code style issues fixed --- .../Checkout/view/frontend/web/js/view/billing-address.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/billing-address.js b/app/code/Magento/Checkout/view/frontend/web/js/view/billing-address.js index 4ea6fb5e5df75..d68b0682eb511 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/view/billing-address.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/view/billing-address.js @@ -201,7 +201,7 @@ function ( this.isAddressDetailsVisible(true); } }, - + /** * Manage cancel button visibility */ From ce1c1a2e8f2342efb287934066e70587fe16c30d Mon Sep 17 00:00:00 2001 From: Nick de Kleijn <nick.dekleijn@gmail.com> Date: Tue, 15 Jan 2019 16:39:08 +0100 Subject: [PATCH 42/65] #20310 change product_price_value based on tax setting --- .../Magento/Tax/Plugin/Checkout/CustomerData/Cart.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/app/code/Magento/Tax/Plugin/Checkout/CustomerData/Cart.php b/app/code/Magento/Tax/Plugin/Checkout/CustomerData/Cart.php index 87f65ef311ac2..c1b495d4ecf98 100644 --- a/app/code/Magento/Tax/Plugin/Checkout/CustomerData/Cart.php +++ b/app/code/Magento/Tax/Plugin/Checkout/CustomerData/Cart.php @@ -68,6 +68,14 @@ public function afterGetSectionData(\Magento\Checkout\CustomerData\Cart $subject $this->itemPriceRenderer->setItem($item); $this->itemPriceRenderer->setTemplate('checkout/cart/item/price/sidebar.phtml'); $result['items'][$key]['product_price']=$this->itemPriceRenderer->toHtml(); + if($this->itemPriceRenderer->displayPriceExclTax()) { + $result['items'][$key]['product_price_value'] = $item->getCalculationPrice(); + } elseif ($this->itemPriceRenderer->displayPriceInclTax()) { + $result['items'][$key]['product_price_value'] = $item->getPriceInclTax(); + } elseif ($this->itemPriceRenderer->displayBothPrices()) { + $result['items'][$key]['product_price_value']['incl_tax'] = $item->getPriceInclTax(); + $result['items'][$key]['product_price_value']['excl_tax'] = $item->getCalculationPrice(); + } } } } From c821730fa110d93f92a87feb3e1bc8253c6ba820 Mon Sep 17 00:00:00 2001 From: nmalevanec <mikola.malevanec@transoftgroup.com> Date: Tue, 26 Feb 2019 14:23:30 +0200 Subject: [PATCH 43/65] Fix static and functional tests. --- .../Magento/Tax/Plugin/Checkout/CustomerData/Cart.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Tax/Plugin/Checkout/CustomerData/Cart.php b/app/code/Magento/Tax/Plugin/Checkout/CustomerData/Cart.php index c1b495d4ecf98..208833733ae3f 100644 --- a/app/code/Magento/Tax/Plugin/Checkout/CustomerData/Cart.php +++ b/app/code/Magento/Tax/Plugin/Checkout/CustomerData/Cart.php @@ -6,6 +6,10 @@ namespace Magento\Tax\Plugin\Checkout\CustomerData; +/** + * Process quote items price, considering tax configuration. + * @SuppressWarnings(PHPMD.CookieAndSessionMisuse) + */ class Cart { /** @@ -68,11 +72,13 @@ public function afterGetSectionData(\Magento\Checkout\CustomerData\Cart $subject $this->itemPriceRenderer->setItem($item); $this->itemPriceRenderer->setTemplate('checkout/cart/item/price/sidebar.phtml'); $result['items'][$key]['product_price']=$this->itemPriceRenderer->toHtml(); - if($this->itemPriceRenderer->displayPriceExclTax()) { + if ($this->itemPriceRenderer->displayPriceExclTax()) { $result['items'][$key]['product_price_value'] = $item->getCalculationPrice(); } elseif ($this->itemPriceRenderer->displayPriceInclTax()) { $result['items'][$key]['product_price_value'] = $item->getPriceInclTax(); } elseif ($this->itemPriceRenderer->displayBothPrices()) { + //unset product price value in case price already has been set as scalar value. + unset($result['items'][$key]['product_price_value']); $result['items'][$key]['product_price_value']['incl_tax'] = $item->getPriceInclTax(); $result['items'][$key]['product_price_value']['excl_tax'] = $item->getCalculationPrice(); } From eea46883e0941bec6bc71350338160dbe68877da Mon Sep 17 00:00:00 2001 From: Viktor Petryk <victor.petryk@transoftgroup.com> Date: Tue, 5 Mar 2019 10:55:53 +0200 Subject: [PATCH 44/65] MAGETWO-94190: [Magento Cloud] Error when saving Bundle product --- .../Magento/Bundle/Test/Unit/Model/Product/SaveHandlerTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Bundle/Test/Unit/Model/Product/SaveHandlerTest.php b/app/code/Magento/Bundle/Test/Unit/Model/Product/SaveHandlerTest.php index a5b9fb4e1b268..41e6c2c160e0a 100644 --- a/app/code/Magento/Bundle/Test/Unit/Model/Product/SaveHandlerTest.php +++ b/app/code/Magento/Bundle/Test/Unit/Model/Product/SaveHandlerTest.php @@ -150,7 +150,7 @@ public function testExecuteWithoutExistingOption() { $productType = 'bundle'; $productSku = 'product-sku'; - $optionId = ''; + $optionId = null; $this->productMock->expects($this->once()) ->method('getExtensionAttributes') From ab2de1505b5b98d746c3623269e19fdb283676b5 Mon Sep 17 00:00:00 2001 From: Prakash <prakash@2jcommerce.in> Date: Fri, 8 Feb 2019 19:34:23 +0530 Subject: [PATCH 45/65] Fixes for product tabbing issue --- lib/web/mage/tabs.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/web/mage/tabs.js b/lib/web/mage/tabs.js index b441477ab8d8a..e4d196fcbbca8 100644 --- a/lib/web/mage/tabs.js +++ b/lib/web/mage/tabs.js @@ -71,6 +71,9 @@ define([ anchorId = anchor.replace('#', ''); if (anchor && isValid) { + if(anchorId == 'review-form'){ + anchorId = anchorId.replace('-form', 's'); + } $.each(self.contents, function (i) { if ($(this).attr('id') === anchorId) { self.collapsibles.not(self.collapsibles.eq(i)).collapsible('forceDeactivate'); From c6c6ead1aaaa5e45b992aff7d564a44c2276e083 Mon Sep 17 00:00:00 2001 From: Prakash <prakash@2jcommerce.in> Date: Wed, 13 Feb 2019 11:59:25 +0530 Subject: [PATCH 46/65] Fixes for tabbing issue on product --- lib/web/mage/tabs.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/lib/web/mage/tabs.js b/lib/web/mage/tabs.js index e4d196fcbbca8..ee3119e90d3a8 100644 --- a/lib/web/mage/tabs.js +++ b/lib/web/mage/tabs.js @@ -70,12 +70,9 @@ define([ isValid = $.mage.isValidSelector(anchor), anchorId = anchor.replace('#', ''); - if (anchor && isValid) { - if(anchorId == 'review-form'){ - anchorId = anchorId.replace('-form', 's'); - } + if (anchor && isValid) { $.each(self.contents, function (i) { - if ($(this).attr('id') === anchorId) { + if ($(this).attr('id') === anchorId || $(this).find('#' + anchorId).length) { self.collapsibles.not(self.collapsibles.eq(i)).collapsible('forceDeactivate'); return false; From 905085d16039d44c5a1159d2fc68a68062291f37 Mon Sep 17 00:00:00 2001 From: Volodymyr Zaets <vzaets@magento.com> Date: Wed, 13 Feb 2019 17:58:30 +0200 Subject: [PATCH 47/65] Remove spaces --- lib/web/mage/tabs.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/web/mage/tabs.js b/lib/web/mage/tabs.js index ee3119e90d3a8..65c452d33bf12 100644 --- a/lib/web/mage/tabs.js +++ b/lib/web/mage/tabs.js @@ -70,7 +70,7 @@ define([ isValid = $.mage.isValidSelector(anchor), anchorId = anchor.replace('#', ''); - if (anchor && isValid) { + if (anchor && isValid) { $.each(self.contents, function (i) { if ($(this).attr('id') === anchorId || $(this).find('#' + anchorId).length) { self.collapsibles.not(self.collapsibles.eq(i)).collapsible('forceDeactivate'); From 1c45357d60ef44975e12bad55fa7f2ef9107cad9 Mon Sep 17 00:00:00 2001 From: LisovyiEvhenii <lisovyievhenii@gmail.com> Date: Fri, 25 Jan 2019 13:14:09 +0200 Subject: [PATCH 48/65] #14882: product_types.xml doesn't allow numbers in modelInstance. Fix module and models name pattern for product_types_base.xsd, product_options.xsd, import.xsd, export.xsd. Adjust unit tests, related to these files --- .../Config/_files/invalidProductOptionsXmlArray.php | 8 ++++---- .../Config/_files/invalidProductTypesXmlArray.php | 8 ++++---- .../Config/_files/valid_product_types_merged.xml | 9 +++++++++ app/code/Magento/Catalog/etc/product_options.xsd | 4 ++-- app/code/Magento/Catalog/etc/product_types_base.xsd | 4 ++-- .../Export/Config/_files/invalidExportXmlArray.php | 10 +++++----- .../Config/_files/invalidImportMergedXmlArray.php | 10 +++++----- .../Import/Config/_files/invalidImportXmlArray.php | 12 ++++++------ app/code/Magento/ImportExport/etc/export.xsd | 4 ++-- app/code/Magento/ImportExport/etc/import.xsd | 4 ++-- 10 files changed, 41 insertions(+), 32 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ProductOptions/Config/_files/invalidProductOptionsXmlArray.php b/app/code/Magento/Catalog/Test/Unit/Model/ProductOptions/Config/_files/invalidProductOptionsXmlArray.php index 034b04b6a757d..31f3ec07bf063 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/ProductOptions/Config/_files/invalidProductOptionsXmlArray.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/ProductOptions/Config/_files/invalidProductOptionsXmlArray.php @@ -29,12 +29,12 @@ ], ], 'renderer_attribute_with_invalid_value' => [ - '<?xml version="1.0"?><config><option name="name_one" renderer="true12"><inputType name="name_one"/>' . + '<?xml version="1.0"?><config><option name="name_one" renderer="123true"><inputType name="name_one"/>' . '</option></config>', [ - "Element 'option', attribute 'renderer': [facet 'pattern'] The value 'true12' is not accepted by the " . - "pattern '[a-zA-Z_\\\\]+'.\nLine: 1\n", - "Element 'option', attribute 'renderer': 'true12' is not a valid value of the atomic" . + "Element 'option', attribute 'renderer': [facet 'pattern'] The value '123true' is not accepted by the " . + "pattern '[a-zA-Z_\\\\]+[a-zA-Z0-9_\\\\]+'.\nLine: 1\n", + "Element 'option', attribute 'renderer': '123true' is not a valid value of the atomic" . " type 'modelName'.\nLine: 1\n" ], ], diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ProductTypes/Config/_files/invalidProductTypesXmlArray.php b/app/code/Magento/Catalog/Test/Unit/Model/ProductTypes/Config/_files/invalidProductTypesXmlArray.php index e1847bea53fcb..1850ff476a809 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/ProductTypes/Config/_files/invalidProductTypesXmlArray.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/ProductTypes/Config/_files/invalidProductTypesXmlArray.php @@ -23,7 +23,7 @@ '<?xml version="1.0"?><config><type name="some_name" modelInstance="123" /></config>', [ "Element 'type', attribute 'modelInstance': [facet 'pattern'] The value '123' is not accepted by the" . - " pattern '[a-zA-Z_\\\\]+'.\nLine: 1\n", + " pattern '[a-zA-Z_\\\\]+[a-zA-Z0-9_\\\\]+'.\nLine: 1\n", "Element 'type', attribute 'modelInstance': '123' is not a valid value of the atomic type" . " 'modelName'.\nLine: 1\n" ], @@ -57,7 +57,7 @@ '<?xml version="1.0"?><config><type name="some_name"><priceModel instance="123123" /></type></config>', [ "Element 'priceModel', attribute 'instance': [facet 'pattern'] The value '123123' is not accepted " . - "by the pattern '[a-zA-Z_\\\\]+'.\nLine: 1\n", + "by the pattern '[a-zA-Z_\\\\]+[a-zA-Z0-9_\\\\]+'.\nLine: 1\n", "Element 'priceModel', attribute 'instance': '123123' is not a valid value of the atomic type" . " 'modelName'.\nLine: 1\n" ], @@ -66,7 +66,7 @@ '<?xml version="1.0"?><config><type name="some_name"><indexerModel instance="123" /></type></config>', [ "Element 'indexerModel', attribute 'instance': [facet 'pattern'] The value '123' is not accepted by " . - "the pattern '[a-zA-Z_\\\\]+'.\nLine: 1\n", + "the pattern '[a-zA-Z_\\\\]+[a-zA-Z0-9_\\\\]+'.\nLine: 1\n", "Element 'indexerModel', attribute 'instance': '123' is not a valid value of the atomic type" . " 'modelName'.\nLine: 1\n" ], @@ -83,7 +83,7 @@ '<?xml version="1.0"?><config><type name="some_name"><stockIndexerModel instance="1234"/></type></config>', [ "Element 'stockIndexerModel', attribute 'instance': [facet 'pattern'] The value '1234' is not " . - "accepted by the pattern '[a-zA-Z_\\\\]+'.\nLine: 1\n", + "accepted by the pattern '[a-zA-Z_\\\\]+[a-zA-Z0-9_\\\\]+'.\nLine: 1\n", "Element 'stockIndexerModel', attribute 'instance': '1234' is not a valid value of the atomic " . "type 'modelName'.\nLine: 1\n" ], diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ProductTypes/Config/_files/valid_product_types_merged.xml b/app/code/Magento/Catalog/Test/Unit/Model/ProductTypes/Config/_files/valid_product_types_merged.xml index 7edbc399a9476..701338774baa5 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/ProductTypes/Config/_files/valid_product_types_merged.xml +++ b/app/code/Magento/Catalog/Test/Unit/Model/ProductTypes/Config/_files/valid_product_types_merged.xml @@ -15,6 +15,14 @@ <stockIndexerModel instance="instance_name"/> </type> <type label="some_label" name="some_name2" modelInstance="model_name"> + <allowedSelectionTypes> + <type name="some_name" /> + </allowedSelectionTypes> + <priceModel instance="instance_name_with_digits_123" /> + <indexerModel instance="instance_name_with_digits_123" /> + <stockIndexerModel instance="instance_name_with_digits_123"/> + </type> + <type label="some_label" name="some_name3" modelInstance="model_name"> <allowedSelectionTypes> <type name="some_name" /> </allowedSelectionTypes> @@ -25,5 +33,6 @@ <composableTypes> <type name="some_name"/> <type name="some_name2"/> + <type name="some_name3"/> </composableTypes> </config> diff --git a/app/code/Magento/Catalog/etc/product_options.xsd b/app/code/Magento/Catalog/etc/product_options.xsd index 3bc24a9099262..e57eb4e715918 100644 --- a/app/code/Magento/Catalog/etc/product_options.xsd +++ b/app/code/Magento/Catalog/etc/product_options.xsd @@ -61,11 +61,11 @@ <xs:simpleType name="modelName"> <xs:annotation> <xs:documentation> - Model name can contain only [a-zA-Z_\\]. + Model name can contain only [a-zA-Z_\\]+[a-zA-Z0-9_\\]+. </xs:documentation> </xs:annotation> <xs:restriction base="xs:string"> - <xs:pattern value="[a-zA-Z_\\]+" /> + <xs:pattern value="[a-zA-Z_\\]+[a-zA-Z0-9_\\]+" /> </xs:restriction> </xs:simpleType> </xs:schema> diff --git a/app/code/Magento/Catalog/etc/product_types_base.xsd b/app/code/Magento/Catalog/etc/product_types_base.xsd index 6cc35fd7bee37..fdefc95c277b1 100644 --- a/app/code/Magento/Catalog/etc/product_types_base.xsd +++ b/app/code/Magento/Catalog/etc/product_types_base.xsd @@ -92,11 +92,11 @@ <xs:simpleType name="modelName"> <xs:annotation> <xs:documentation> - Model name can contain only [a-zA-Z_\\]. + Model name can contain only [a-zA-Z_\\]+[a-zA-Z0-9_\\]+. </xs:documentation> </xs:annotation> <xs:restriction base="xs:string"> - <xs:pattern value="[a-zA-Z_\\]+" /> + <xs:pattern value="[a-zA-Z_\\]+[a-zA-Z0-9_\\]+" /> </xs:restriction> </xs:simpleType> </xs:schema> diff --git a/app/code/Magento/ImportExport/Test/Unit/Model/Export/Config/_files/invalidExportXmlArray.php b/app/code/Magento/ImportExport/Test/Unit/Model/Export/Config/_files/invalidExportXmlArray.php index 288a99770974a..251ccae6d7a8a 100644 --- a/app/code/Magento/ImportExport/Test/Unit/Model/Export/Config/_files/invalidExportXmlArray.php +++ b/app/code/Magento/ImportExport/Test/Unit/Model/Export/Config/_files/invalidExportXmlArray.php @@ -22,15 +22,15 @@ 'attributes_with_type_modelName_and_invalid_value' => [ '<?xml version="1.0"?><config><entity name="Name/one" model="model_one" ' . 'entityAttributeFilterType="model_one"/><entityType entity="Name/one" name="name_one" model="1"/>' - . ' <fileFormat name="name_one" model="model1"/></config>', + . ' <fileFormat name="name_one" model="1model"/></config>', [ "Element 'entityType', attribute 'model': [facet 'pattern'] The value '1' is not accepted by the " . - "pattern '[A-Za-z_\\\\]+'.\nLine: 1\n", + "pattern '[a-zA-Z_\\\\]+[a-zA-Z0-9_\\\\]+'.\nLine: 1\n", "Element 'entityType', attribute 'model': '1' is not a valid value of the atomic type" . " 'modelName'.\nLine: 1\n", - "Element 'fileFormat', attribute 'model': [facet 'pattern'] The value 'model1' is not " . - "accepted by the pattern '[A-Za-z_\\\\]+'.\nLine: 1\n", - "Element 'fileFormat', attribute 'model': 'model1' is not a valid " . + "Element 'fileFormat', attribute 'model': [facet 'pattern'] The value '1model' is not " . + "accepted by the pattern '[a-zA-Z_\\\\]+[a-zA-Z0-9_\\\\]+'.\nLine: 1\n", + "Element 'fileFormat', attribute 'model': '1model' is not a valid " . "value of the atomic type 'modelName'.\nLine: 1\n" ], ], diff --git a/app/code/Magento/ImportExport/Test/Unit/Model/Import/Config/_files/invalidImportMergedXmlArray.php b/app/code/Magento/ImportExport/Test/Unit/Model/Import/Config/_files/invalidImportMergedXmlArray.php index 357b35e8a313c..e51d46536abc0 100644 --- a/app/code/Magento/ImportExport/Test/Unit/Model/Import/Config/_files/invalidImportMergedXmlArray.php +++ b/app/code/Magento/ImportExport/Test/Unit/Model/Import/Config/_files/invalidImportMergedXmlArray.php @@ -26,12 +26,12 @@ ["Element 'entity', attribute 'notallowed': The attribute 'notallowed' is not allowed.\nLine: 1\n"], ], 'entity_model_with_invalid_value' => [ - '<?xml version="1.0"?><config><entity name="test_name" label="test_label" model="afwer34" ' . + '<?xml version="1.0"?><config><entity name="test_name" label="test_label" model="34afwer" ' . 'behaviorModel="test" /></config>', [ - "Element 'entity', attribute 'model': [facet 'pattern'] The value 'afwer34' is not " . - "accepted by the pattern '[A-Za-z_\\\\]+'.\nLine: 1\n", - "Element 'entity', attribute 'model': 'afwer34' is not a valid value of the atomic type" . + "Element 'entity', attribute 'model': [facet 'pattern'] The value '34afwer' is not " . + "accepted by the pattern '[a-zA-Z_\\\\]+[a-zA-Z0-9_\\\\]+'.\nLine: 1\n", + "Element 'entity', attribute 'model': '34afwer' is not a valid value of the atomic type" . " 'modelName'.\nLine: 1\n" ], ], @@ -40,7 +40,7 @@ '</config>', [ "Element 'entity', attribute 'behaviorModel': [facet 'pattern'] The value '666' is not accepted by " . - "the pattern '[A-Za-z_\\\\]+'.\nLine: 1\n", + "the pattern '[a-zA-Z_\\\\]+[a-zA-Z0-9_\\\\]+'.\nLine: 1\n", "Element 'entity', attribute 'behaviorModel': '666' is not a valid value of the atomic type" . " 'modelName'.\nLine: 1\n" ], diff --git a/app/code/Magento/ImportExport/Test/Unit/Model/Import/Config/_files/invalidImportXmlArray.php b/app/code/Magento/ImportExport/Test/Unit/Model/Import/Config/_files/invalidImportXmlArray.php index c913b53e8b531..4b9d8e1c32f6d 100644 --- a/app/code/Magento/ImportExport/Test/Unit/Model/Import/Config/_files/invalidImportXmlArray.php +++ b/app/code/Magento/ImportExport/Test/Unit/Model/Import/Config/_files/invalidImportXmlArray.php @@ -19,7 +19,7 @@ '<?xml version="1.0"?><config><entity name="some_name" model="12345"/></config>', [ "Element 'entity', attribute 'model': [facet 'pattern'] The value '12345' is not accepted by " . - "the pattern '[A-Za-z_\\\\]+'.\nLine: 1\n", + "the pattern '[a-zA-Z_\\\\]+[a-zA-Z0-9_\\\\]+'.\nLine: 1\n", "Element 'entity', attribute 'model': '12345' is not a valid value of the atomic type" . " 'modelName'.\nLine: 1\n" ], @@ -28,7 +28,7 @@ '<?xml version="1.0"?><config><entity name="some_name" behaviorModel="=--09"/></config>', [ "Element 'entity', attribute 'behaviorModel': [facet 'pattern'] The value '=--09' is not " . - "accepted by the pattern '[A-Za-z_\\\\]+'.\nLine: 1\n", + "accepted by the pattern '[a-zA-Z_\\\\]+[a-zA-Z0-9_\\\\]+'.\nLine: 1\n", "Element 'entity', attribute 'behaviorModel': '=--09' is not a valid value of the atomic type" . " 'modelName'.\nLine: 1\n" ], @@ -46,11 +46,11 @@ ["Element 'entityType': The attribute 'model' is required but missing.\nLine: 1\n"], ], 'entitytype_with_invalid_model_attribute_value' => [ - '<?xml version="1.0"?><config><entityType entity="entity_name" name="some_name" model="test1"/></config>', + '<?xml version="1.0"?><config><entityType entity="entity_name" name="some_name" model="1test"/></config>', [ - "Element 'entityType', attribute 'model': [facet 'pattern'] The value 'test1' is not " . - "accepted by the pattern '[A-Za-z_\\\\]+'.\nLine: 1\n", - "Element 'entityType', attribute 'model': 'test1' is not a valid value of the atomic type" . + "Element 'entityType', attribute 'model': [facet 'pattern'] The value '1test' is not " . + "accepted by the pattern '[a-zA-Z_\\\\]+[a-zA-Z0-9_\\\\]+'.\nLine: 1\n", + "Element 'entityType', attribute 'model': '1test' is not a valid value of the atomic type" . " 'modelName'.\nLine: 1\n" ], ], diff --git a/app/code/Magento/ImportExport/etc/export.xsd b/app/code/Magento/ImportExport/etc/export.xsd index 65728a9be5c62..b196ae0cb6f11 100644 --- a/app/code/Magento/ImportExport/etc/export.xsd +++ b/app/code/Magento/ImportExport/etc/export.xsd @@ -71,11 +71,11 @@ <xs:simpleType name="modelName"> <xs:annotation> <xs:documentation> - Model name can contain only [A-Za-z_\\]. + Model name can contain only [a-zA-Z_\\]+[a-zA-Z0-9_\\]+. </xs:documentation> </xs:annotation> <xs:restriction base="xs:string"> - <xs:pattern value="[A-Za-z_\\]+" /> + <xs:pattern value="[a-zA-Z_\\]+[a-zA-Z0-9_\\]+" /> </xs:restriction> </xs:simpleType> </xs:schema> diff --git a/app/code/Magento/ImportExport/etc/import.xsd b/app/code/Magento/ImportExport/etc/import.xsd index aefa6541d7e13..42bd365878eb2 100644 --- a/app/code/Magento/ImportExport/etc/import.xsd +++ b/app/code/Magento/ImportExport/etc/import.xsd @@ -61,11 +61,11 @@ <xs:simpleType name="modelName"> <xs:annotation> <xs:documentation> - Model name can contain only [A-Za-z_\\]. + Model name can contain only [a-zA-Z_\\]+[a-zA-Z0-9_\\]+. </xs:documentation> </xs:annotation> <xs:restriction base="xs:string"> - <xs:pattern value="[A-Za-z_\\]+" /> + <xs:pattern value="[a-zA-Z_\\]+[a-zA-Z0-9_\\]+" /> </xs:restriction> </xs:simpleType> </xs:schema> From ab8d312286fa448f408727ea6fff9e790424cb34 Mon Sep 17 00:00:00 2001 From: LisovyiEvhenii <lisovyievhenii@gmail.com> Date: Tue, 29 Jan 2019 15:50:21 +0200 Subject: [PATCH 49/65] #14882: improve regular expression --- .../Config/_files/invalidProductOptionsXmlArray.php | 2 +- .../Config/_files/invalidProductTypesXmlArray.php | 8 ++++---- app/code/Magento/Catalog/etc/product_options.xsd | 4 ++-- app/code/Magento/Catalog/etc/product_types_base.xsd | 4 ++-- .../Model/Export/Config/_files/invalidExportXmlArray.php | 4 ++-- .../Import/Config/_files/invalidImportMergedXmlArray.php | 4 ++-- .../Model/Import/Config/_files/invalidImportXmlArray.php | 6 +++--- app/code/Magento/ImportExport/etc/export.xsd | 4 ++-- app/code/Magento/ImportExport/etc/import.xsd | 4 ++-- 9 files changed, 20 insertions(+), 20 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ProductOptions/Config/_files/invalidProductOptionsXmlArray.php b/app/code/Magento/Catalog/Test/Unit/Model/ProductOptions/Config/_files/invalidProductOptionsXmlArray.php index 31f3ec07bf063..cfb54c3aefd0f 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/ProductOptions/Config/_files/invalidProductOptionsXmlArray.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/ProductOptions/Config/_files/invalidProductOptionsXmlArray.php @@ -33,7 +33,7 @@ '</option></config>', [ "Element 'option', attribute 'renderer': [facet 'pattern'] The value '123true' is not accepted by the " . - "pattern '[a-zA-Z_\\\\]+[a-zA-Z0-9_\\\\]+'.\nLine: 1\n", + "pattern '([\\\\]?[a-zA-Z_][a-zA-Z0-9_]*)+'.\nLine: 1\n", "Element 'option', attribute 'renderer': '123true' is not a valid value of the atomic" . " type 'modelName'.\nLine: 1\n" ], diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ProductTypes/Config/_files/invalidProductTypesXmlArray.php b/app/code/Magento/Catalog/Test/Unit/Model/ProductTypes/Config/_files/invalidProductTypesXmlArray.php index 1850ff476a809..868252da8190c 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/ProductTypes/Config/_files/invalidProductTypesXmlArray.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/ProductTypes/Config/_files/invalidProductTypesXmlArray.php @@ -23,7 +23,7 @@ '<?xml version="1.0"?><config><type name="some_name" modelInstance="123" /></config>', [ "Element 'type', attribute 'modelInstance': [facet 'pattern'] The value '123' is not accepted by the" . - " pattern '[a-zA-Z_\\\\]+[a-zA-Z0-9_\\\\]+'.\nLine: 1\n", + " pattern '([\\\\]?[a-zA-Z_][a-zA-Z0-9_]*)+'.\nLine: 1\n", "Element 'type', attribute 'modelInstance': '123' is not a valid value of the atomic type" . " 'modelName'.\nLine: 1\n" ], @@ -57,7 +57,7 @@ '<?xml version="1.0"?><config><type name="some_name"><priceModel instance="123123" /></type></config>', [ "Element 'priceModel', attribute 'instance': [facet 'pattern'] The value '123123' is not accepted " . - "by the pattern '[a-zA-Z_\\\\]+[a-zA-Z0-9_\\\\]+'.\nLine: 1\n", + "by the pattern '([\\\\]?[a-zA-Z_][a-zA-Z0-9_]*)+'.\nLine: 1\n", "Element 'priceModel', attribute 'instance': '123123' is not a valid value of the atomic type" . " 'modelName'.\nLine: 1\n" ], @@ -66,7 +66,7 @@ '<?xml version="1.0"?><config><type name="some_name"><indexerModel instance="123" /></type></config>', [ "Element 'indexerModel', attribute 'instance': [facet 'pattern'] The value '123' is not accepted by " . - "the pattern '[a-zA-Z_\\\\]+[a-zA-Z0-9_\\\\]+'.\nLine: 1\n", + "the pattern '([\\\\]?[a-zA-Z_][a-zA-Z0-9_]*)+'.\nLine: 1\n", "Element 'indexerModel', attribute 'instance': '123' is not a valid value of the atomic type" . " 'modelName'.\nLine: 1\n" ], @@ -83,7 +83,7 @@ '<?xml version="1.0"?><config><type name="some_name"><stockIndexerModel instance="1234"/></type></config>', [ "Element 'stockIndexerModel', attribute 'instance': [facet 'pattern'] The value '1234' is not " . - "accepted by the pattern '[a-zA-Z_\\\\]+[a-zA-Z0-9_\\\\]+'.\nLine: 1\n", + "accepted by the pattern '([\\\\]?[a-zA-Z_][a-zA-Z0-9_]*)+'.\nLine: 1\n", "Element 'stockIndexerModel', attribute 'instance': '1234' is not a valid value of the atomic " . "type 'modelName'.\nLine: 1\n" ], diff --git a/app/code/Magento/Catalog/etc/product_options.xsd b/app/code/Magento/Catalog/etc/product_options.xsd index e57eb4e715918..734c8f378d5d7 100644 --- a/app/code/Magento/Catalog/etc/product_options.xsd +++ b/app/code/Magento/Catalog/etc/product_options.xsd @@ -61,11 +61,11 @@ <xs:simpleType name="modelName"> <xs:annotation> <xs:documentation> - Model name can contain only [a-zA-Z_\\]+[a-zA-Z0-9_\\]+. + Model name can contain only ([\\]?[a-zA-Z_][a-zA-Z0-9_]*)+. </xs:documentation> </xs:annotation> <xs:restriction base="xs:string"> - <xs:pattern value="[a-zA-Z_\\]+[a-zA-Z0-9_\\]+" /> + <xs:pattern value="([\\]?[a-zA-Z_][a-zA-Z0-9_]*)+" /> </xs:restriction> </xs:simpleType> </xs:schema> diff --git a/app/code/Magento/Catalog/etc/product_types_base.xsd b/app/code/Magento/Catalog/etc/product_types_base.xsd index fdefc95c277b1..dec952bcf492e 100644 --- a/app/code/Magento/Catalog/etc/product_types_base.xsd +++ b/app/code/Magento/Catalog/etc/product_types_base.xsd @@ -92,11 +92,11 @@ <xs:simpleType name="modelName"> <xs:annotation> <xs:documentation> - Model name can contain only [a-zA-Z_\\]+[a-zA-Z0-9_\\]+. + Model name can contain only ([\\]?[a-zA-Z_][a-zA-Z0-9_]*)+. </xs:documentation> </xs:annotation> <xs:restriction base="xs:string"> - <xs:pattern value="[a-zA-Z_\\]+[a-zA-Z0-9_\\]+" /> + <xs:pattern value="([\\]?[a-zA-Z_][a-zA-Z0-9_]*)+" /> </xs:restriction> </xs:simpleType> </xs:schema> diff --git a/app/code/Magento/ImportExport/Test/Unit/Model/Export/Config/_files/invalidExportXmlArray.php b/app/code/Magento/ImportExport/Test/Unit/Model/Export/Config/_files/invalidExportXmlArray.php index 251ccae6d7a8a..179f3f3cadab0 100644 --- a/app/code/Magento/ImportExport/Test/Unit/Model/Export/Config/_files/invalidExportXmlArray.php +++ b/app/code/Magento/ImportExport/Test/Unit/Model/Export/Config/_files/invalidExportXmlArray.php @@ -25,11 +25,11 @@ . ' <fileFormat name="name_one" model="1model"/></config>', [ "Element 'entityType', attribute 'model': [facet 'pattern'] The value '1' is not accepted by the " . - "pattern '[a-zA-Z_\\\\]+[a-zA-Z0-9_\\\\]+'.\nLine: 1\n", + "pattern '([\\\\]?[a-zA-Z_][a-zA-Z0-9_]*)+'.\nLine: 1\n", "Element 'entityType', attribute 'model': '1' is not a valid value of the atomic type" . " 'modelName'.\nLine: 1\n", "Element 'fileFormat', attribute 'model': [facet 'pattern'] The value '1model' is not " . - "accepted by the pattern '[a-zA-Z_\\\\]+[a-zA-Z0-9_\\\\]+'.\nLine: 1\n", + "accepted by the pattern '([\\\\]?[a-zA-Z_][a-zA-Z0-9_]*)+'.\nLine: 1\n", "Element 'fileFormat', attribute 'model': '1model' is not a valid " . "value of the atomic type 'modelName'.\nLine: 1\n" ], diff --git a/app/code/Magento/ImportExport/Test/Unit/Model/Import/Config/_files/invalidImportMergedXmlArray.php b/app/code/Magento/ImportExport/Test/Unit/Model/Import/Config/_files/invalidImportMergedXmlArray.php index e51d46536abc0..409c1af9cb38a 100644 --- a/app/code/Magento/ImportExport/Test/Unit/Model/Import/Config/_files/invalidImportMergedXmlArray.php +++ b/app/code/Magento/ImportExport/Test/Unit/Model/Import/Config/_files/invalidImportMergedXmlArray.php @@ -30,7 +30,7 @@ 'behaviorModel="test" /></config>', [ "Element 'entity', attribute 'model': [facet 'pattern'] The value '34afwer' is not " . - "accepted by the pattern '[a-zA-Z_\\\\]+[a-zA-Z0-9_\\\\]+'.\nLine: 1\n", + "accepted by the pattern '([\\\\]?[a-zA-Z_][a-zA-Z0-9_]*)+'.\nLine: 1\n", "Element 'entity', attribute 'model': '34afwer' is not a valid value of the atomic type" . " 'modelName'.\nLine: 1\n" ], @@ -40,7 +40,7 @@ '</config>', [ "Element 'entity', attribute 'behaviorModel': [facet 'pattern'] The value '666' is not accepted by " . - "the pattern '[a-zA-Z_\\\\]+[a-zA-Z0-9_\\\\]+'.\nLine: 1\n", + "the pattern '([\\\\]?[a-zA-Z_][a-zA-Z0-9_]*)+'.\nLine: 1\n", "Element 'entity', attribute 'behaviorModel': '666' is not a valid value of the atomic type" . " 'modelName'.\nLine: 1\n" ], diff --git a/app/code/Magento/ImportExport/Test/Unit/Model/Import/Config/_files/invalidImportXmlArray.php b/app/code/Magento/ImportExport/Test/Unit/Model/Import/Config/_files/invalidImportXmlArray.php index 4b9d8e1c32f6d..c7b06a8731f02 100644 --- a/app/code/Magento/ImportExport/Test/Unit/Model/Import/Config/_files/invalidImportXmlArray.php +++ b/app/code/Magento/ImportExport/Test/Unit/Model/Import/Config/_files/invalidImportXmlArray.php @@ -19,7 +19,7 @@ '<?xml version="1.0"?><config><entity name="some_name" model="12345"/></config>', [ "Element 'entity', attribute 'model': [facet 'pattern'] The value '12345' is not accepted by " . - "the pattern '[a-zA-Z_\\\\]+[a-zA-Z0-9_\\\\]+'.\nLine: 1\n", + "the pattern '([\\\\]?[a-zA-Z_][a-zA-Z0-9_]*)+'.\nLine: 1\n", "Element 'entity', attribute 'model': '12345' is not a valid value of the atomic type" . " 'modelName'.\nLine: 1\n" ], @@ -28,7 +28,7 @@ '<?xml version="1.0"?><config><entity name="some_name" behaviorModel="=--09"/></config>', [ "Element 'entity', attribute 'behaviorModel': [facet 'pattern'] The value '=--09' is not " . - "accepted by the pattern '[a-zA-Z_\\\\]+[a-zA-Z0-9_\\\\]+'.\nLine: 1\n", + "accepted by the pattern '([\\\\]?[a-zA-Z_][a-zA-Z0-9_]*)+'.\nLine: 1\n", "Element 'entity', attribute 'behaviorModel': '=--09' is not a valid value of the atomic type" . " 'modelName'.\nLine: 1\n" ], @@ -49,7 +49,7 @@ '<?xml version="1.0"?><config><entityType entity="entity_name" name="some_name" model="1test"/></config>', [ "Element 'entityType', attribute 'model': [facet 'pattern'] The value '1test' is not " . - "accepted by the pattern '[a-zA-Z_\\\\]+[a-zA-Z0-9_\\\\]+'.\nLine: 1\n", + "accepted by the pattern '([\\\\]?[a-zA-Z_][a-zA-Z0-9_]*)+'.\nLine: 1\n", "Element 'entityType', attribute 'model': '1test' is not a valid value of the atomic type" . " 'modelName'.\nLine: 1\n" ], diff --git a/app/code/Magento/ImportExport/etc/export.xsd b/app/code/Magento/ImportExport/etc/export.xsd index b196ae0cb6f11..f62dbc891ef0f 100644 --- a/app/code/Magento/ImportExport/etc/export.xsd +++ b/app/code/Magento/ImportExport/etc/export.xsd @@ -71,11 +71,11 @@ <xs:simpleType name="modelName"> <xs:annotation> <xs:documentation> - Model name can contain only [a-zA-Z_\\]+[a-zA-Z0-9_\\]+. + Model name can contain only ([\\]?[a-zA-Z_][a-zA-Z0-9_]*)+. </xs:documentation> </xs:annotation> <xs:restriction base="xs:string"> - <xs:pattern value="[a-zA-Z_\\]+[a-zA-Z0-9_\\]+" /> + <xs:pattern value="([\\]?[a-zA-Z_][a-zA-Z0-9_]*)+" /> </xs:restriction> </xs:simpleType> </xs:schema> diff --git a/app/code/Magento/ImportExport/etc/import.xsd b/app/code/Magento/ImportExport/etc/import.xsd index 42bd365878eb2..e73038ebc0710 100644 --- a/app/code/Magento/ImportExport/etc/import.xsd +++ b/app/code/Magento/ImportExport/etc/import.xsd @@ -61,11 +61,11 @@ <xs:simpleType name="modelName"> <xs:annotation> <xs:documentation> - Model name can contain only [a-zA-Z_\\]+[a-zA-Z0-9_\\]+. + Model name can contain only ([\\]?[a-zA-Z_][a-zA-Z0-9_]*)+. </xs:documentation> </xs:annotation> <xs:restriction base="xs:string"> - <xs:pattern value="[a-zA-Z_\\]+[a-zA-Z0-9_\\]+" /> + <xs:pattern value="([\\]?[a-zA-Z_][a-zA-Z0-9_]*)+" /> </xs:restriction> </xs:simpleType> </xs:schema> From 290b998c6309d52e77c0c226e5317643ce915677 Mon Sep 17 00:00:00 2001 From: Oleksandr Iegorov <oiegorov@magento.com> Date: Wed, 6 Mar 2019 10:00:23 -0600 Subject: [PATCH 50/65] MAGETWO-98208: URLs not using SEO friendly format if you assign to website --- .../ProductToWebsiteChangeObserver.php | 9 +- .../ProductToWebsiteChangeObserverTest.php | 193 ++++++++++++++++++ 2 files changed, 201 insertions(+), 1 deletion(-) create mode 100644 app/code/Magento/CatalogUrlRewrite/Test/Unit/Observer/ProductToWebsiteChangeObserverTest.php diff --git a/app/code/Magento/CatalogUrlRewrite/Observer/ProductToWebsiteChangeObserver.php b/app/code/Magento/CatalogUrlRewrite/Observer/ProductToWebsiteChangeObserver.php index 94798753ca63f..12334a2a773cb 100644 --- a/app/code/Magento/CatalogUrlRewrite/Observer/ProductToWebsiteChangeObserver.php +++ b/app/code/Magento/CatalogUrlRewrite/Observer/ProductToWebsiteChangeObserver.php @@ -13,6 +13,8 @@ use Magento\Store\Model\Store; use Magento\UrlRewrite\Model\UrlPersistInterface; use Magento\UrlRewrite\Service\V1\Data\UrlRewrite; +use Magento\Framework\Exception\NoSuchEntityException; +use Magento\UrlRewrite\Model\Exception\UrlAlreadyExistsException; /** * Observer to assign the products to website. @@ -61,21 +63,26 @@ public function __construct( * Generate urls for UrlRewrite and save it in storage * * @param \Magento\Framework\Event\Observer $observer + * @throws NoSuchEntityException + * @throws UrlAlreadyExistsException * @return void */ public function execute(\Magento\Framework\Event\Observer $observer) { foreach ($observer->getEvent()->getProducts() as $productId) { + $storeId = $this->request->getParam('store_id', Store::DEFAULT_STORE_ID); + $product = $this->productRepository->getById( $productId, false, - $this->request->getParam('store_id', Store::DEFAULT_STORE_ID) + $storeId ); if (!empty($this->productUrlRewriteGenerator->generate($product))) { $this->urlPersist->deleteByData([ UrlRewrite::ENTITY_ID => $product->getId(), UrlRewrite::ENTITY_TYPE => ProductUrlRewriteGenerator::ENTITY_TYPE, + UrlRewrite::STORE_ID => $storeId, ]); if ($product->getVisibility() != Visibility::VISIBILITY_NOT_VISIBLE) { $this->urlPersist->replace($this->productUrlRewriteGenerator->generate($product)); diff --git a/app/code/Magento/CatalogUrlRewrite/Test/Unit/Observer/ProductToWebsiteChangeObserverTest.php b/app/code/Magento/CatalogUrlRewrite/Test/Unit/Observer/ProductToWebsiteChangeObserverTest.php new file mode 100644 index 0000000000000..f383c949b4295 --- /dev/null +++ b/app/code/Magento/CatalogUrlRewrite/Test/Unit/Observer/ProductToWebsiteChangeObserverTest.php @@ -0,0 +1,193 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +declare(strict_types=1); + +namespace Magento\CatalogUrlRewrite\Test\Unit\Observer; + +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Framework\App\RequestInterface; +use Magento\Framework\Event; +use Magento\Framework\Event\Observer; +use Magento\Catalog\Model\Product; +use Magento\Catalog\Model\Product\Visibility; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\CatalogUrlRewrite\Observer\ProductToWebsiteChangeObserver; +use Magento\CatalogUrlRewrite\Model\ProductUrlRewriteGenerator; +use Magento\UrlRewrite\Model\UrlPersistInterface; +use Magento\UrlRewrite\Service\V1\Data\UrlRewrite; +use Magento\Store\Model\Store; + +/** + * Test for ProductToWebsiteChangeObserver + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class ProductToWebsiteChangeObserverTest extends \PHPUnit\Framework\TestCase +{ + /** + * @var ProductRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $productRepository; + + /** + * @var ProductUrlRewriteGenerator|\PHPUnit_Framework_MockObject_MockObject + */ + private $productUrlRewriteGenerator; + + /** + * @var UrlPersistInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $urlPersist; + + /** + * @var Event|\PHPUnit_Framework_MockObject_MockObject + */ + private $event; + + /** + * @var Observer|\PHPUnit_Framework_MockObject_MockObject + */ + private $observer; + + /** + * @var Product|\PHPUnit_Framework_MockObject_MockObject + */ + private $product; + + /** + * @var RequestInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $request; + + /** + * @var ObjectManager + */ + private $objectManager; + + /** + * @var ProductToWebsiteChangeObserver + */ + private $model; + + /** + * @var int + */ + private $productId; + + /** + * @inheritDoc + */ + protected function setUp() + { + $this->productId = 3; + + $this->urlPersist = $this->getMockBuilder(UrlPersistInterface::class) + ->setMethods(['deleteByData', 'replace']) + ->getMockForAbstractClass(); + $this->productRepository = $this->getMockBuilder(ProductRepositoryInterface::class) + ->setMethods(['getById']) + ->getMockForAbstractClass(); + $this->product = $this->getMockBuilder(Product::class) + ->disableOriginalConstructor() + ->setMethods(['getId', 'getVisibility']) + ->getMock(); + $this->product->expects($this->any()) + ->method('getId') + ->willReturn($this->productId); + $this->productRepository->expects($this->any()) + ->method('getById') + ->with($this->productId, false, Store::DEFAULT_STORE_ID) + ->willReturn($this->product); + $this->productUrlRewriteGenerator = $this->getMockBuilder(ProductUrlRewriteGenerator::class) + ->disableOriginalConstructor() + ->setMethods(['generate']) + ->getMock(); + $this->event = $this->getMockBuilder(Event::class) + ->disableOriginalConstructor() + ->setMethods(['getProducts']) + ->getMock(); + $this->event->expects($this->any()) + ->method('getProducts') + ->willReturn([$this->productId]); + $this->observer = $this->getMockBuilder(Observer::class) + ->disableOriginalConstructor() + ->setMethods(['getEvent']) + ->getMock(); + $this->observer->expects($this->any()) + ->method('getEvent') + ->willReturn($this->event); + $this->request = $this->getMockBuilder(RequestInterface::class) + ->setMethods(['getParam']) + ->getMockForAbstractClass(); + $this->request->expects($this->any()) + ->method('getParam') + ->with('store_id', Store::DEFAULT_STORE_ID) + ->willReturn(Store::DEFAULT_STORE_ID); + + $this->objectManager = new ObjectManager($this); + $this->model = $this->objectManager->getObject( + ProductToWebsiteChangeObserver::class, + [ + 'productUrlRewriteGenerator' => $this->productUrlRewriteGenerator, + 'urlPersist' => $this->urlPersist, + 'productRepository' => $this->productRepository, + 'request' => $this->request + ] + ); + } + + /** + * @param array $urlRewriteGeneratorResult + * @param int $numberDeleteByData + * @param int $productVisibility + * @param int $numberReplace + * @throws \Magento\Framework\Exception\NoSuchEntityException + * @throws \Magento\UrlRewrite\Model\Exception\UrlAlreadyExistsException + * @dataProvider executeDataProvider + */ + public function testExecute( + array $urlRewriteGeneratorResult, + int $numberDeleteByData, + int $productVisibility, + int $numberReplace + ) { + $this->productUrlRewriteGenerator->expects($this->any()) + ->method('generate') + ->willReturn($urlRewriteGeneratorResult); + $this->urlPersist->expects($this->exactly($numberDeleteByData)) + ->method('deleteByData') + ->with( + [ + UrlRewrite::ENTITY_ID => $this->productId, + UrlRewrite::ENTITY_TYPE => ProductUrlRewriteGenerator::ENTITY_TYPE, + UrlRewrite::STORE_ID => Store::DEFAULT_STORE_ID + ] + ); + $this->product->expects($this->any()) + ->method('getVisibility') + ->willReturn($productVisibility); + $this->urlPersist->expects($this->exactly($numberReplace)) + ->method('replace') + ->with($urlRewriteGeneratorResult); + + $this->model->execute($this->observer); + } + + /** + * Data provider for testExecute + * + * @return array + */ + public function executeDataProvider(): array + { + return [ + [[], 0, Visibility::VISIBILITY_NOT_VISIBLE, 0], + [['someRewrite'], 1, Visibility::VISIBILITY_NOT_VISIBLE, 0], + [['someRewrite'], 1, Visibility::VISIBILITY_BOTH, 1], + ]; + } +} From 715bd00fa49db50bdff175d8918e006120bcf2b9 Mon Sep 17 00:00:00 2001 From: Andrey Nikolaev <tonikolaev@gmail.com> Date: Wed, 13 Feb 2019 00:58:25 +0300 Subject: [PATCH 51/65] Fix issue with custom option file uploading --- lib/internal/Magento/Framework/Filesystem/DirectoryList.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/internal/Magento/Framework/Filesystem/DirectoryList.php b/lib/internal/Magento/Framework/Filesystem/DirectoryList.php index f07932d45ecb6..96818e4ff3b70 100644 --- a/lib/internal/Magento/Framework/Filesystem/DirectoryList.php +++ b/lib/internal/Magento/Framework/Filesystem/DirectoryList.php @@ -97,6 +97,10 @@ public function __construct($root, array $config = []) $this->root = $this->normalizePath($root); $this->directories = static::getDefaultConfig(); $this->directories[self::SYS_TMP] = [self::PATH => realpath(sys_get_temp_dir())]; + $uploadTmpDir = ini_get('upload_tmp_dir'); + if ($uploadTmpDir) { + $this->directories[self::SYS_TMP] = [self::PATH => realpath($uploadTmpDir)]; + } // inject custom values from constructor foreach ($this->directories as $code => $dir) { From 63e268c1332f8040cdb8b5c4583125b6e9e25dd4 Mon Sep 17 00:00:00 2001 From: Andrey Nikolaev <tonikolaev@gmail.com> Date: Wed, 13 Feb 2019 20:29:51 +0300 Subject: [PATCH 52/65] Simplify code by using ternary operator. --- .../Magento/Framework/Filesystem/DirectoryList.php | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/lib/internal/Magento/Framework/Filesystem/DirectoryList.php b/lib/internal/Magento/Framework/Filesystem/DirectoryList.php index 96818e4ff3b70..1d73b79398d27 100644 --- a/lib/internal/Magento/Framework/Filesystem/DirectoryList.php +++ b/lib/internal/Magento/Framework/Filesystem/DirectoryList.php @@ -96,11 +96,8 @@ public function __construct($root, array $config = []) static::validate($config); $this->root = $this->normalizePath($root); $this->directories = static::getDefaultConfig(); - $this->directories[self::SYS_TMP] = [self::PATH => realpath(sys_get_temp_dir())]; - $uploadTmpDir = ini_get('upload_tmp_dir'); - if ($uploadTmpDir) { - $this->directories[self::SYS_TMP] = [self::PATH => realpath($uploadTmpDir)]; - } + $sysTmpPath = ini_get('upload_tmp_dir') ? ini_get('upload_tmp_dir') : sys_get_temp_dir(); + $this->directories[self::SYS_TMP] = [self::PATH => realpath($sysTmpPath)]; // inject custom values from constructor foreach ($this->directories as $code => $dir) { From 4b3127e50242bea2e2e6bf6ea2b137470b219684 Mon Sep 17 00:00:00 2001 From: nmalevanec <mikola.malevanec@transoftgroup.com> Date: Mon, 4 Mar 2019 17:02:18 +0200 Subject: [PATCH 53/65] Fix static tests. --- lib/internal/Magento/Framework/Filesystem/DirectoryList.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/Filesystem/DirectoryList.php b/lib/internal/Magento/Framework/Filesystem/DirectoryList.php index 1d73b79398d27..ef27cc19c4697 100644 --- a/lib/internal/Magento/Framework/Filesystem/DirectoryList.php +++ b/lib/internal/Magento/Framework/Filesystem/DirectoryList.php @@ -8,6 +8,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\Filesystem; /** @@ -96,7 +97,7 @@ public function __construct($root, array $config = []) static::validate($config); $this->root = $this->normalizePath($root); $this->directories = static::getDefaultConfig(); - $sysTmpPath = ini_get('upload_tmp_dir') ? ini_get('upload_tmp_dir') : sys_get_temp_dir(); + $sysTmpPath = get_cfg_var('upload_tmp_dir') ?: sys_get_temp_dir(); $this->directories[self::SYS_TMP] = [self::PATH => realpath($sysTmpPath)]; // inject custom values from constructor From adf4425136c276f0e482f154198c4f39cc15d00d Mon Sep 17 00:00:00 2001 From: eduard13 <e.chitoraga@atwix.com> Date: Mon, 11 Mar 2019 16:40:15 +0200 Subject: [PATCH 54/65] Made configurable product variations table cell label hidden --- .../Form/Modifier/ConfigurablePanel.php | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/app/code/Magento/ConfigurableProduct/Ui/DataProvider/Product/Form/Modifier/ConfigurablePanel.php b/app/code/Magento/ConfigurableProduct/Ui/DataProvider/Product/Form/Modifier/ConfigurablePanel.php index 9fd225e8acaab..dcdffddbeeec0 100644 --- a/app/code/Magento/ConfigurableProduct/Ui/DataProvider/Product/Form/Modifier/ConfigurablePanel.php +++ b/app/code/Magento/ConfigurableProduct/Ui/DataProvider/Product/Form/Modifier/ConfigurablePanel.php @@ -5,14 +5,14 @@ */ namespace Magento\ConfigurableProduct\Ui\DataProvider\Product\Form\Modifier; +use Magento\Catalog\Model\Locator\LocatorInterface; use Magento\Catalog\Model\Product\Attribute\Backend\Sku; use Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\AbstractModifier; +use Magento\Framework\UrlInterface; use Magento\Ui\Component\Container; -use Magento\Ui\Component\Form; use Magento\Ui\Component\DynamicRows; +use Magento\Ui\Component\Form; use Magento\Ui\Component\Modal; -use Magento\Framework\UrlInterface; -use Magento\Catalog\Model\Locator\LocatorInterface; /** * Data provider for Configurable panel @@ -90,7 +90,7 @@ public function __construct( } /** - * {@inheritdoc} + * @inheritdoc */ public function modifyData(array $data) { @@ -98,7 +98,7 @@ public function modifyData(array $data) } /** - * {@inheritdoc} + * @inheritdoc * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ public function modifyMeta(array $meta) @@ -197,7 +197,7 @@ public function modifyMeta(array $meta) 'autoRender' => false, 'componentType' => 'insertListing', 'component' => 'Magento_ConfigurableProduct/js' - .'/components/associated-product-insert-listing', + . '/components/associated-product-insert-listing', 'dataScope' => $this->associatedListingPrefix . static::ASSOCIATED_PRODUCT_LISTING, 'externalProvider' => $this->associatedListingPrefix @@ -328,14 +328,12 @@ protected function getButtonSet() 'component' => 'Magento_Ui/js/form/components/button', 'actions' => [ [ - 'targetName' => - $this->dataScopeName . '.configurableModal', + 'targetName' => $this->dataScopeName . '.configurableModal', 'actionName' => 'trigger', 'params' => ['active', true], ], [ - 'targetName' => - $this->dataScopeName . '.configurableModal', + 'targetName' => $this->dataScopeName . '.configurableModal', 'actionName' => 'openModal', ], ], @@ -574,6 +572,7 @@ protected function getColumn( 'dataType' => Form\Element\DataType\Text::NAME, 'dataScope' => $name, 'visibleIfCanEdit' => false, + 'labelVisible' => false, 'imports' => [ 'visible' => '!${$.provider}:${$.parentScope}.canEdit' ], @@ -592,6 +591,7 @@ protected function getColumn( 'component' => 'Magento_Ui/js/form/components/group', 'label' => $label, 'dataScope' => '', + 'showLabel' => false ]; $container['children'] = [ $name . '_edit' => $fieldEdit, From b4283aa17b03927d8f2b0983b9b519b684610b5e Mon Sep 17 00:00:00 2001 From: Jitheesh <jitheeshvo@gmail.com> Date: Thu, 28 Feb 2019 15:04:11 +0530 Subject: [PATCH 55/65] Setting default sorting #21493 - Fixed default sort direction --- app/code/Magento/Customer/Block/Adminhtml/Edit/Tab/Orders.php | 3 ++- .../Magento/Customer/Block/Adminhtml/Edit/Tab/View/Cart.php | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Customer/Block/Adminhtml/Edit/Tab/Orders.php b/app/code/Magento/Customer/Block/Adminhtml/Edit/Tab/Orders.php index bb190260e4776..c1266febff99d 100644 --- a/app/code/Magento/Customer/Block/Adminhtml/Edit/Tab/Orders.php +++ b/app/code/Magento/Customer/Block/Adminhtml/Edit/Tab/Orders.php @@ -63,7 +63,8 @@ protected function _construct() { parent::_construct(); $this->setId('customer_orders_grid'); - $this->setDefaultSort('created_at', 'desc'); + $this->setDefaultSort('created_at'); + $this->setDefaultDir('desc'); $this->setUseAjax(true); } diff --git a/app/code/Magento/Customer/Block/Adminhtml/Edit/Tab/View/Cart.php b/app/code/Magento/Customer/Block/Adminhtml/Edit/Tab/View/Cart.php index d0973d3baf383..988a157805b36 100644 --- a/app/code/Magento/Customer/Block/Adminhtml/Edit/Tab/View/Cart.php +++ b/app/code/Magento/Customer/Block/Adminhtml/Edit/Tab/View/Cart.php @@ -77,7 +77,8 @@ protected function _construct() { parent::_construct(); $this->setId('customer_view_cart_grid'); - $this->setDefaultSort('added_at', 'desc'); + $this->setDefaultSort('added_at'); + $this->setDefaultDir('desc'); $this->setSortable(false); $this->setPagerVisibility(false); $this->setFilterVisibility(false); From a4a487829684c76c3b5dfd7e5786a9352dfb915f Mon Sep 17 00:00:00 2001 From: Sarfaraz Bheda <sarfaraz.bheda@krishtechnolabs.com> Date: Sat, 24 Nov 2018 16:16:25 +0530 Subject: [PATCH 56/65] 19276 - Fixed price renderer issue --- .../Swatches/view/frontend/web/js/swatch-renderer.js | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/Swatches/view/frontend/web/js/swatch-renderer.js b/app/code/Magento/Swatches/view/frontend/web/js/swatch-renderer.js index 3e28982ad44d3..2cb8bd1c25d46 100644 --- a/app/code/Magento/Swatches/view/frontend/web/js/swatch-renderer.js +++ b/app/code/Magento/Swatches/view/frontend/web/js/swatch-renderer.js @@ -918,7 +918,8 @@ define([ $productPrice = $product.find(this.options.selectorProductPrice), options = _.object(_.keys($widget.optionsMap), {}), result, - tierPriceHtml; + tierPriceHtml, + isShow; $widget.element.find('.' + $widget.options.classes.attributeClass + '[option-selected]').each(function () { var attributeId = $(this).attr('attribute-id'); @@ -935,11 +936,9 @@ define([ } ); - if (typeof result != 'undefined' && result.oldPrice.amount !== result.finalPrice.amount) { - $(this.options.slyOldPriceSelector).show(); - } else { - $(this.options.slyOldPriceSelector).hide(); - } + isShow = typeof result != 'undefined' && result.oldPrice.amount !== result.finalPrice.amount; + + $product.find(this.options.slyOldPriceSelector)[isShow ? 'show' : 'hide'](); if (typeof result != 'undefined' && result.tierPrices.length) { if (this.options.tierPriceTemplate) { From 9a839d176f1d8d1ec46d5ce47f7a8ba6cea76067 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20F=C3=BChr?= <d.fuehr@techdivision.com> Date: Tue, 22 Jan 2019 11:43:21 +0100 Subject: [PATCH 57/65] 19117: fix performance leak in salesrule collection Github Issue: https://github.com/magento/magento2/issues/19117 Refactored sql query that created a huge temporary table for each request, when a greater amount of salesrules and coupon codes exists in database. The sorting of this table took a lot of cpu time. The statement now consists of two subselects that drill down the remaining lines as far as possible, so that the remaining temporary table is minimal and easily sorted. example: for 2,000 salesrules and 3,000,000 coupon codes the original query took about 2.4 seconds (mbp, server, aws). the optimized query takes about 5ms (about 100ms on aws). --- .../Model/ResourceModel/Rule/Collection.php | 185 ++++++++++-------- 1 file changed, 101 insertions(+), 84 deletions(-) diff --git a/app/code/Magento/SalesRule/Model/ResourceModel/Rule/Collection.php b/app/code/Magento/SalesRule/Model/ResourceModel/Rule/Collection.php index 5e6f3847c8e31..352b5d4c809c9 100644 --- a/app/code/Magento/SalesRule/Model/ResourceModel/Rule/Collection.php +++ b/app/code/Magento/SalesRule/Model/ResourceModel/Rule/Collection.php @@ -107,12 +107,15 @@ protected function mapAssociatedEntities($entityType, $objectField) $associatedEntities = $this->getConnection()->fetchAll($select); - array_map(function ($associatedEntity) use ($entityInfo, $ruleIdField, $objectField) { - $item = $this->getItemByColumnValue($ruleIdField, $associatedEntity[$ruleIdField]); - $itemAssociatedValue = $item->getData($objectField) === null ? [] : $item->getData($objectField); - $itemAssociatedValue[] = $associatedEntity[$entityInfo['entity_id_field']]; - $item->setData($objectField, $itemAssociatedValue); - }, $associatedEntities); + array_map( + function ($associatedEntity) use ($entityInfo, $ruleIdField, $objectField) { + $item = $this->getItemByColumnValue($ruleIdField, $associatedEntity[$ruleIdField]); + $itemAssociatedValue = $item->getData($objectField) === null ? [] : $item->getData($objectField); + $itemAssociatedValue[] = $associatedEntity[$entityInfo['entity_id_field']]; + $item->setData($objectField, $itemAssociatedValue); + }, + $associatedEntities + ); } /** @@ -144,6 +147,7 @@ protected function _afterLoad() * @use $this->addWebsiteGroupDateFilter() * @SuppressWarnings(PHPMD.UnusedFormalParameter) * @return $this + * @throws \Zend_Db_Select_Exception */ public function setValidationFilter( $websiteId, @@ -153,32 +157,21 @@ public function setValidationFilter( Address $address = null ) { if (!$this->getFlag('validation_filter')) { - /* We need to overwrite joinLeft if coupon is applied */ - $this->getSelect()->reset(); - parent::_initSelect(); - $this->addWebsiteGroupDateFilter($websiteId, $customerGroupId, $now); - $select = $this->getSelect(); + $this->prepareSelect($websiteId, $customerGroupId, $now); - $connection = $this->getConnection(); - if (strlen($couponCode)) { - $noCouponWhereCondition = $connection->quoteInto( - 'main_table.coupon_type = ?', - \Magento\SalesRule\Model\Rule::COUPON_TYPE_NO_COUPON - ); - $relatedRulesIds = $this->getCouponRelatedRuleIds($couponCode); - - $select->where( - $noCouponWhereCondition . ' OR main_table.rule_id IN (?)', - $relatedRulesIds, - Select::TYPE_CONDITION - ); + $noCouponRules = $this->getNoCouponCodeSelect(); + + if ($couponCode) { + $couponRules = $this->getCouponCodeSelect($couponCode); + $allAllowedRules = $this->getConnection()->select(); + $allAllowedRules->union([$noCouponRules, $couponRules], \Zend_Db_Select::SQL_UNION_ALL); + + $this->_select = $allAllowedRules; } else { - $this->addFieldToFilter( - 'main_table.coupon_type', - \Magento\SalesRule\Model\Rule::COUPON_TYPE_NO_COUPON - ); + $this->_select = $noCouponRules; } + $this->setOrder('sort_order', self::SORT_ORDER_ASC); $this->setFlag('validation_filter', true); } @@ -187,72 +180,96 @@ public function setValidationFilter( } /** - * Get rules ids related to coupon code + * Recreate the default select object for specific needs of salesrule evaluation with coupon codes. * - * @param string $couponCode - * @return array + * @param $websiteId + * @param $customerGroupId + * @param $now */ - private function getCouponRelatedRuleIds(string $couponCode): array + private function prepareSelect($websiteId, $customerGroupId, $now) { - $connection = $this->getConnection(); - $select = $connection->select()->from( - ['main_table' => $this->getTable('salesrule')], - 'rule_id' + $this->getSelect()->reset(); + parent::_initSelect(); + + $this->addWebsiteGroupDateFilter($websiteId, $customerGroupId, $now); + } + + /** + * Return select object to determine all active rules not needing a coupon code. + * + * @return Select + */ + private function getNoCouponCodeSelect() + { + $noCouponSelect = clone $this->getSelect(); + + $noCouponSelect->where( + 'main_table.coupon_type = ?', + Rule::COUPON_TYPE_NO_COUPON ); - $select->joinLeft( - ['rule_coupons' => $this->getTable('salesrule_coupon')], - $connection->quoteInto( - 'main_table.rule_id = rule_coupons.rule_id AND main_table.coupon_type != ?', - \Magento\SalesRule\Model\Rule::COUPON_TYPE_NO_COUPON, - null - ) + + $noCouponSelect->columns([Coupon::KEY_CODE => new \Zend_Db_Expr('NULL')]); + + return $noCouponSelect; + } + + /** + * Determine all active rules that are valid for the given coupon code. + * + * @param $couponCode + * @return Select + */ + private function getCouponCodeSelect($couponCode) + { + $couponSelect = clone $this->getSelect(); + + $this->joinCouponTable($couponCode, $couponSelect); + + $notExpired = $this->getConnection()->quoteInto( + '(rule_coupons.expiration_date IS NULL OR rule_coupons.expiration_date >= ?)', + $this->_date->date()->format('Y-m-d') ); - $autoGeneratedCouponCondition = [ - $connection->quoteInto( - "main_table.coupon_type = ?", - \Magento\SalesRule\Model\Rule::COUPON_TYPE_AUTO - ), - $connection->quoteInto( - "rule_coupons.type = ?", - \Magento\SalesRule\Api\Data\CouponInterface::TYPE_GENERATED - ), - ]; - - $orWhereConditions = [ - "(" . implode($autoGeneratedCouponCondition, " AND ") . ")", - $connection->quoteInto( - '(main_table.coupon_type = ? AND main_table.use_auto_generation = 1 AND rule_coupons.type = 1)', - \Magento\SalesRule\Model\Rule::COUPON_TYPE_SPECIFIC - ), - $connection->quoteInto( - '(main_table.coupon_type = ? AND main_table.use_auto_generation = 0 AND rule_coupons.type = 0)', - \Magento\SalesRule\Model\Rule::COUPON_TYPE_SPECIFIC - ), - ]; - - $andWhereConditions = [ - $connection->quoteInto( - 'rule_coupons.code = ?', - $couponCode - ), - $connection->quoteInto( - '(rule_coupons.expiration_date IS NULL OR rule_coupons.expiration_date >= ?)', - $this->_date->date()->format('Y-m-d') - ), - ]; - - $orWhereCondition = implode(' OR ', $orWhereConditions); - $andWhereCondition = implode(' AND ', $andWhereConditions); - - $select->where( - '(' . $orWhereCondition . ') AND ' . $andWhereCondition, + $isAutogeneratedCoupon = + $this->getConnection()->quoteInto('main_table.coupon_type = ?', Rule::COUPON_TYPE_AUTO) + . ' AND ' . + $this->getConnection()->quoteInto('rule_coupons.type = ?', CouponInterface::TYPE_GENERATED); + + $isValidSpecificCoupon = + $this->getConnection()->quoteInto('(main_table.coupon_type = ?)', Rule::COUPON_TYPE_SPECIFIC) + . ' AND (' . + '(main_table.use_auto_generation = 1 AND rule_coupons.type = 1)' + . ' OR ' . + '(main_table.use_auto_generation = 0 AND rule_coupons.type = 0)' + . ')'; + + $couponSelect->where( + "$notExpired AND ($isAutogeneratedCoupon OR $isValidSpecificCoupon)", null, Select::TYPE_CONDITION ); - $select->group('main_table.rule_id'); - return $connection->fetchCol($select); + return $couponSelect; + } + + /** + * @param $couponCode + * @param Select $couponSelect + */ + private function joinCouponTable($couponCode, Select $couponSelect) + { + $couponJoinCondition = + 'main_table.rule_id = rule_coupons.rule_id' + . ' AND ' . + $this->getConnection()->quoteInto('main_table.coupon_type <> ?', Rule::COUPON_TYPE_NO_COUPON) + . ' AND ' . + $this->getConnection()->quoteInto('rule_coupons.code = ?', $couponCode); + + $couponSelect->joinInner( + ['rule_coupons' => $this->getTable('salesrule_coupon')], + $couponJoinCondition, + [Coupon::KEY_CODE] + ); } /** From 8e7ddbf4656b15fd37b1321cadabed9d9175ea6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20F=C3=BChr?= <d.fuehr@techdivision.com> Date: Tue, 22 Jan 2019 20:56:31 +0100 Subject: [PATCH 58/65] Fix integration error preventing coupon codes to be applied. --- .../SalesRule/Model/ResourceModel/Rule/Collection.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/SalesRule/Model/ResourceModel/Rule/Collection.php b/app/code/Magento/SalesRule/Model/ResourceModel/Rule/Collection.php index 352b5d4c809c9..2a6bf17342504 100644 --- a/app/code/Magento/SalesRule/Model/ResourceModel/Rule/Collection.php +++ b/app/code/Magento/SalesRule/Model/ResourceModel/Rule/Collection.php @@ -167,7 +167,10 @@ public function setValidationFilter( $allAllowedRules = $this->getConnection()->select(); $allAllowedRules->union([$noCouponRules, $couponRules], \Zend_Db_Select::SQL_UNION_ALL); - $this->_select = $allAllowedRules; + $wrapper = $this->getConnection()->select(); + $wrapper->from($allAllowedRules); + + $this->_select = $wrapper; } else { $this->_select = $noCouponRules; } From a3e87bdfbefe486eb5217b8dbdded50fffde1236 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20F=C3=BChr?= <d.fuehr@techdivision.com> Date: Wed, 23 Jan 2019 09:32:43 +0100 Subject: [PATCH 59/65] Rename variable to comply to codestyle standards --- .../SalesRule/Model/ResourceModel/Rule/Collection.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/SalesRule/Model/ResourceModel/Rule/Collection.php b/app/code/Magento/SalesRule/Model/ResourceModel/Rule/Collection.php index 2a6bf17342504..04c54bf5b7e01 100644 --- a/app/code/Magento/SalesRule/Model/ResourceModel/Rule/Collection.php +++ b/app/code/Magento/SalesRule/Model/ResourceModel/Rule/Collection.php @@ -233,12 +233,12 @@ private function getCouponCodeSelect($couponCode) $this->_date->date()->format('Y-m-d') ); - $isAutogeneratedCoupon = + $isAutogenerated = $this->getConnection()->quoteInto('main_table.coupon_type = ?', Rule::COUPON_TYPE_AUTO) . ' AND ' . $this->getConnection()->quoteInto('rule_coupons.type = ?', CouponInterface::TYPE_GENERATED); - $isValidSpecificCoupon = + $isValidSpecific = $this->getConnection()->quoteInto('(main_table.coupon_type = ?)', Rule::COUPON_TYPE_SPECIFIC) . ' AND (' . '(main_table.use_auto_generation = 1 AND rule_coupons.type = 1)' @@ -247,7 +247,7 @@ private function getCouponCodeSelect($couponCode) . ')'; $couponSelect->where( - "$notExpired AND ($isAutogeneratedCoupon OR $isValidSpecificCoupon)", + "$notExpired AND ($isAutogenerated OR $isValidSpecific)", null, Select::TYPE_CONDITION ); From bfd1d4f7c38c0fe3c8e17449b621bbc5c996d59b Mon Sep 17 00:00:00 2001 From: nmalevanec <mikola.malevanec@transoftgroup.com> Date: Fri, 1 Mar 2019 15:09:21 +0200 Subject: [PATCH 60/65] Fix static tests. --- .../Model/ResourceModel/Rule/Collection.php | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/app/code/Magento/SalesRule/Model/ResourceModel/Rule/Collection.php b/app/code/Magento/SalesRule/Model/ResourceModel/Rule/Collection.php index 04c54bf5b7e01..9446a053f6d0e 100644 --- a/app/code/Magento/SalesRule/Model/ResourceModel/Rule/Collection.php +++ b/app/code/Magento/SalesRule/Model/ResourceModel/Rule/Collection.php @@ -157,7 +157,6 @@ public function setValidationFilter( Address $address = null ) { if (!$this->getFlag('validation_filter')) { - $this->prepareSelect($websiteId, $customerGroupId, $now); $noCouponRules = $this->getNoCouponCodeSelect(); @@ -165,7 +164,7 @@ public function setValidationFilter( if ($couponCode) { $couponRules = $this->getCouponCodeSelect($couponCode); $allAllowedRules = $this->getConnection()->select(); - $allAllowedRules->union([$noCouponRules, $couponRules], \Zend_Db_Select::SQL_UNION_ALL); + $allAllowedRules->union([$noCouponRules, $couponRules], Select::SQL_UNION_ALL); $wrapper = $this->getConnection()->select(); $wrapper->from($allAllowedRules); @@ -185,9 +184,9 @@ public function setValidationFilter( /** * Recreate the default select object for specific needs of salesrule evaluation with coupon codes. * - * @param $websiteId - * @param $customerGroupId - * @param $now + * @param int $websiteId + * @param int $customerGroupId + * @param string $now */ private function prepareSelect($websiteId, $customerGroupId, $now) { @@ -219,7 +218,7 @@ private function getNoCouponCodeSelect() /** * Determine all active rules that are valid for the given coupon code. * - * @param $couponCode + * @param string $couponCode * @return Select */ private function getCouponCodeSelect($couponCode) @@ -256,7 +255,9 @@ private function getCouponCodeSelect($couponCode) } /** - * @param $couponCode + * Join coupon table to select. + * + * @param string $couponCode * @param Select $couponSelect */ private function joinCouponTable($couponCode, Select $couponSelect) From 8b8a46c4beb8cf3c4c0d881660f442d4df545782 Mon Sep 17 00:00:00 2001 From: Ihor Sviziev <ihor-sviziev@users.noreply.github.com> Date: Tue, 12 Mar 2019 11:41:14 +0200 Subject: [PATCH 61/65] magento/magento2#19098 2.2.6 Use batches and direct queries to fix sales address upgrade Fix field name --- app/code/Magento/Sales/Setup/UpgradeData.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Sales/Setup/UpgradeData.php b/app/code/Magento/Sales/Setup/UpgradeData.php index 0f9833ed8f7f2..ee60eef03726d 100644 --- a/app/code/Magento/Sales/Setup/UpgradeData.php +++ b/app/code/Magento/Sales/Setup/UpgradeData.php @@ -244,7 +244,7 @@ private function fillQuoteAddressIdInSalesOrderAddressProcessBatch( 'quote_address_id' => $quoteAddresses[$orderAddress['quote_id']]['address_id'] ?? null, ]; $where = [ - 'orderAddressId' => $orderAddress['entity_id'] + 'entity_id' => $orderAddress['entity_id'] ]; $salesConnection->update($salesOrderAddressTable, $bind, $where); From 571cf9bfd6ba69ef2c8f4f7a6f1dacb17452a495 Mon Sep 17 00:00:00 2001 From: Ihor Sviziev <ihor-sviziev@users.noreply.github.com> Date: Tue, 12 Mar 2019 11:55:18 +0200 Subject: [PATCH 62/65] magento/magento2#21699 Backport Fix performance leak in salesrule collection Unify PRs to be the same --- .../Magento/SalesRule/Model/ResourceModel/Rule/Collection.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/SalesRule/Model/ResourceModel/Rule/Collection.php b/app/code/Magento/SalesRule/Model/ResourceModel/Rule/Collection.php index 9446a053f6d0e..105bbeaa11d1b 100644 --- a/app/code/Magento/SalesRule/Model/ResourceModel/Rule/Collection.php +++ b/app/code/Magento/SalesRule/Model/ResourceModel/Rule/Collection.php @@ -163,6 +163,7 @@ public function setValidationFilter( if ($couponCode) { $couponRules = $this->getCouponCodeSelect($couponCode); + $allAllowedRules = $this->getConnection()->select(); $allAllowedRules->union([$noCouponRules, $couponRules], Select::SQL_UNION_ALL); From ea34b66bd90957d7495428f3adff94f83c92dbb5 Mon Sep 17 00:00:00 2001 From: Ihor Sviziev <ihor-sviziev@users.noreply.github.com> Date: Tue, 12 Mar 2019 11:58:07 +0200 Subject: [PATCH 63/65] magento/magento2#21699 Backport Fix performance leak in salesrule collection Unify PRs to be the same --- .../Magento/SalesRule/Model/ResourceModel/Rule/Collection.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/code/Magento/SalesRule/Model/ResourceModel/Rule/Collection.php b/app/code/Magento/SalesRule/Model/ResourceModel/Rule/Collection.php index 105bbeaa11d1b..c45400f65047f 100644 --- a/app/code/Magento/SalesRule/Model/ResourceModel/Rule/Collection.php +++ b/app/code/Magento/SalesRule/Model/ResourceModel/Rule/Collection.php @@ -9,6 +9,9 @@ use Magento\Framework\DB\Select; use Magento\Framework\Serialize\Serializer\Json; use Magento\Quote\Model\Quote\Address; +use Magento\SalesRule\Api\Data\CouponInterface; +use Magento\SalesRule\Model\Coupon; +use Magento\SalesRule\Model\Rule; /** * Sales Rules resource collection model. From dbf671438ef01bf9cc8882c7a36bb28bea280434 Mon Sep 17 00:00:00 2001 From: Ihor Sviziev <ihor-sviziev@users.noreply.github.com> Date: Tue, 12 Mar 2019 12:00:20 +0200 Subject: [PATCH 64/65] magento/magento2#21699 Backport Fix performance leak in salesrule collection Unify PRs to be the same --- .../Magento/SalesRule/Model/ResourceModel/Rule/Collection.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/SalesRule/Model/ResourceModel/Rule/Collection.php b/app/code/Magento/SalesRule/Model/ResourceModel/Rule/Collection.php index c45400f65047f..423cd1543117b 100644 --- a/app/code/Magento/SalesRule/Model/ResourceModel/Rule/Collection.php +++ b/app/code/Magento/SalesRule/Model/ResourceModel/Rule/Collection.php @@ -147,10 +147,10 @@ protected function _afterLoad() * @param string $couponCode * @param string|null $now * @param Address $address allow extensions to further filter out rules based on quote address + * @throws \Zend_Db_Select_Exception * @use $this->addWebsiteGroupDateFilter() * @SuppressWarnings(PHPMD.UnusedFormalParameter) * @return $this - * @throws \Zend_Db_Select_Exception */ public function setValidationFilter( $websiteId, From df364432458bc551964a14cc1c1aaa50110c72e3 Mon Sep 17 00:00:00 2001 From: Ihor Sviziev <ihor-sviziev@users.noreply.github.com> Date: Tue, 12 Mar 2019 20:08:59 +0200 Subject: [PATCH 65/65] magento/magento2#19098 Use batches and direct queries to fix sales address upgrade --- app/code/Magento/Sales/Setup/UpgradeData.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Sales/Setup/UpgradeData.php b/app/code/Magento/Sales/Setup/UpgradeData.php index ee60eef03726d..2e5a454e62fdd 100644 --- a/app/code/Magento/Sales/Setup/UpgradeData.php +++ b/app/code/Magento/Sales/Setup/UpgradeData.php @@ -244,7 +244,7 @@ private function fillQuoteAddressIdInSalesOrderAddressProcessBatch( 'quote_address_id' => $quoteAddresses[$orderAddress['quote_id']]['address_id'] ?? null, ]; $where = [ - 'entity_id' => $orderAddress['entity_id'] + 'entity_id = ?' => $orderAddress['entity_id'] ]; $salesConnection->update($salesOrderAddressTable, $bind, $where);