Skip to content

Commit a716c96

Browse files
author
Sergii Kovalenko
authored
Merge pull request #1401 from magento-tsg/2.2-develop-pr8
Fixed issues: - MAGETWO-70663 Impossible to assign products to category using Match products by rule with price attribute - MAGETWO-67283 quote_address.free_shipping is different depending on whether Magento was upgraded vs installed - MAGETWO-70642 Magento broken after changing transactional email
2 parents 99686e2 + 3868c1e commit a716c96

File tree

10 files changed

+375
-13
lines changed

10 files changed

+375
-13
lines changed

app/code/Magento/CatalogUrlRewrite/Observer/UrlRewriteHandler.php

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -110,19 +110,29 @@ public function generateProductUrlRewrites(\Magento\Catalog\Model\Category $cate
110110
$storeId = $category->getStoreId();
111111
if ($category->getAffectedProductIds()) {
112112
$this->isSkippedProduct[$category->getEntityId()] = $category->getAffectedProductIds();
113+
/* @var \Magento\Catalog\Model\ResourceModel\Product\Collection $collection */
113114
$collection = $this->productCollectionFactory->create()
114115
->setStoreId($storeId)
115116
->addIdFilter($category->getAffectedProductIds())
116117
->addAttributeToSelect('visibility')
117118
->addAttributeToSelect('name')
118119
->addAttributeToSelect('url_key')
119120
->addAttributeToSelect('url_path');
120-
foreach ($collection as $product) {
121-
$product->setStoreId($storeId);
122-
$product->setData('save_rewrites_history', $saveRewriteHistory);
123-
$mergeDataProvider->merge(
124-
$this->productUrlRewriteGenerator->generate($product, $category->getEntityId())
125-
);
121+
122+
$collection->setPageSize(1000);
123+
$pageCount = $collection->getLastPageNumber();
124+
$currentPage = 1;
125+
while ($currentPage <= $pageCount) {
126+
$collection->setCurPage($currentPage);
127+
foreach ($collection as $product) {
128+
$product->setStoreId($storeId);
129+
$product->setData('save_rewrites_history', $saveRewriteHistory);
130+
$mergeDataProvider->merge(
131+
$this->productUrlRewriteGenerator->generate($product, $category->getEntityId())
132+
);
133+
}
134+
$collection->clear();
135+
$currentPage++;
126136
}
127137
} else {
128138
$mergeDataProvider->merge(

app/code/Magento/CatalogUrlRewrite/Test/Unit/Observer/UrlRewriteHandlerTest.php

Lines changed: 78 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@
55
*/
66
namespace Magento\CatalogUrlRewrite\Test\Unit\Observer;
77

8+
use Magento\Catalog\Model\ResourceModel\Product\Collection;
89
use Magento\CatalogUrlRewrite\Observer\UrlRewriteHandler;
910
use Magento\CatalogUrlRewrite\Model\Category\ChildrenCategoriesProvider;
11+
use Magento\CatalogUrlRewrite\Model\CategoryBasedProductRewriteGenerator;
1012
use Magento\CatalogUrlRewrite\Model\CategoryUrlRewriteGenerator;
1113
use Magento\CatalogUrlRewrite\Model\ProductUrlRewriteGenerator;
1214
use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory;
@@ -16,6 +18,9 @@
1618
use Magento\UrlRewrite\Model\MergeDataProvider;
1719
use Magento\CatalogUrlRewrite\Model\CategoryProductUrlPathGenerator;
1820

21+
/**
22+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
23+
*/
1924
class UrlRewriteHandlerTest extends \PHPUnit\Framework\TestCase
2025
{
2126
/**
@@ -58,6 +63,11 @@ class UrlRewriteHandlerTest extends \PHPUnit\Framework\TestCase
5863
*/
5964
private $mergeDataProviderFactoryMock;
6065

66+
/**
67+
* @var MergeDataProvider|\PHPUnit_Framework_MockObject_MockObject
68+
*/
69+
private $mergeDataProviderMock;
70+
6171
/**
6272
* @var Json|\PHPUnit_Framework_MockObject_MockObject
6373
*/
@@ -85,16 +95,15 @@ protected function setUp()
8595
->setMethods(['create'])
8696
->disableOriginalConstructor()
8797
->getMock();
88-
$mergeDataProviderMock = $this->getMockBuilder(MergeDataProvider::class)
98+
$this->mergeDataProviderMock = $this->getMockBuilder(MergeDataProvider::class)
8999
->disableOriginalConstructor()
90100
->getMock();
91101
$this->categoryBasedProductRewriteGeneratorMock = $this->getMockBuilder(CategoryProductUrlPathGenerator::class)
92102
->disableOriginalConstructor()
93103
->getMock();
94104
$this->mergeDataProviderFactoryMock->expects($this->any())
95105
->method('create')
96-
->willReturn($mergeDataProviderMock);
97-
106+
->willReturn($this->mergeDataProviderMock);
98107
$this->serializerMock = $this->getMockBuilder(Json::class)
99108
->disableOriginalConstructor()
100109
->getMock();
@@ -111,6 +120,72 @@ protected function setUp()
111120
);
112121
}
113122

123+
/**
124+
* @test
125+
*/
126+
public function testGenerateProductUrlRewrites()
127+
{
128+
/* @var \Magento\Catalog\Model\Category|\PHPUnit_Framework_MockObject_MockObject $category */
129+
$category = $this->getMockBuilder(\Magento\Catalog\Model\Category::class)
130+
->setMethods(['getEntityId', 'getStoreId', 'getData', 'getAffectedProductIds'])
131+
->disableOriginalConstructor()
132+
->getMock();
133+
$category->expects($this->any())
134+
->method('getEntityId')
135+
->willReturn(2);
136+
$category->expects($this->any())
137+
->method('getStoreId')
138+
->willReturn(1);
139+
$category->expects($this->any())
140+
->method('getData')
141+
->with('save_rewrites_history')
142+
->willReturn(true);
143+
144+
/* @var \Magento\Catalog\Model\Category|\PHPUnit_Framework_MockObject_MockObject $childCategory1 */
145+
$childCategory1 = $this->getMockBuilder(\Magento\Catalog\Model\Category::class)
146+
->setMethods(['getEntityId'])
147+
->disableOriginalConstructor()
148+
->getMock();
149+
$childCategory1->expects($this->any())
150+
->method('getEntityId')
151+
->willReturn(100);
152+
153+
/* @var \Magento\Catalog\Model\Category|\PHPUnit_Framework_MockObject_MockObject $childCategory1 */
154+
$childCategory2 = $this->getMockBuilder(\Magento\Catalog\Model\Category::class)
155+
->setMethods(['getEntityId'])
156+
->disableOriginalConstructor()
157+
->getMock();
158+
$childCategory1->expects($this->any())
159+
->method('getEntityId')
160+
->willReturn(200);
161+
162+
$this->childrenCategoriesProviderMock->expects($this->once())
163+
->method('getChildren')
164+
->with($category, true)
165+
->willReturn([$childCategory1, $childCategory2]);
166+
167+
/** @var Collection|\PHPUnit_Framework_MockObject_MockObject $productCollection */
168+
$productCollection = $this->getMockBuilder(\Magento\Catalog\Model\ResourceModel\Product\Collection::class)
169+
->disableOriginalConstructor()
170+
->getMock();
171+
$productCollection->expects($this->any())
172+
->method('addCategoriesFilter')
173+
->willReturnSelf();
174+
$productCollection->expects($this->any())
175+
->method('addIdFilter')
176+
->willReturnSelf();
177+
$productCollection->expects($this->any())->method('setStoreId')->willReturnSelf();
178+
$productCollection->expects($this->any())->method('addAttributeToSelect')->willReturnSelf();
179+
$iterator = new \ArrayIterator([]);
180+
$productCollection->expects($this->any())->method('getIterator')->will($this->returnValue($iterator));
181+
182+
$this->collectionFactoryMock->expects($this->any())->method('create')->willReturn($productCollection);
183+
184+
$this->mergeDataProviderMock->expects($this->any())->method('getData')->willReturn([1, 2]);
185+
186+
$this->urlRewriteHandler->generateProductUrlRewrites($category);
187+
}
188+
114189
public function testDeleteCategoryRewritesForChildren()
115190
{
116191
$category = $this->getMockBuilder(\Magento\Catalog\Model\Category::class)
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\OfflineShipping\Setup;
8+
9+
use Magento\Framework\Setup\ModuleContextInterface;
10+
use Magento\Framework\Setup\ModuleDataSetupInterface;
11+
use Magento\Framework\Setup\UpgradeDataInterface;
12+
13+
/**
14+
* Upgrade Data script.
15+
*/
16+
class UpgradeData implements UpgradeDataInterface
17+
{
18+
/**
19+
* @var string
20+
*/
21+
private $quoteConnectionName = 'checkout';
22+
23+
/**
24+
* @var string
25+
*/
26+
private $salesConnectionName = 'sales';
27+
28+
/**
29+
* {@inheritdoc}
30+
*/
31+
public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
32+
{
33+
$setup->startSetup();
34+
if ($context->getVersion() && version_compare($context->getVersion(), '2.0.1') < 0) {
35+
$this->updateQuoteShippingAddresses($setup);
36+
}
37+
$setup->endSetup();
38+
}
39+
40+
/**
41+
* Replace Null with '0' for 'free_shipping' and 'simple_free_shipping' accordingly to upgraded schema.
42+
*
43+
* @param ModuleDataSetupInterface $setup
44+
* @return void
45+
*/
46+
private function updateQuoteShippingAddresses(ModuleDataSetupInterface $setup)
47+
{
48+
$setup->getConnection()->update(
49+
$setup->getTable('salesrule'),
50+
['simple_free_shipping' => 0],
51+
[new \Zend_Db_Expr('simple_free_shipping IS NULL')]
52+
);
53+
$setup->getConnection($this->salesConnectionName)->update(
54+
$setup->getTable('sales_order_item'),
55+
['free_shipping' => 0],
56+
[new \Zend_Db_Expr('free_shipping IS NULL')]
57+
);
58+
$setup->getConnection($this->quoteConnectionName)->update(
59+
$setup->getTable('quote_address'),
60+
['free_shipping' => 0],
61+
[new \Zend_Db_Expr('free_shipping IS NULL')]
62+
);
63+
$setup->getConnection($this->quoteConnectionName)->update(
64+
$setup->getTable('quote_item'),
65+
['free_shipping' => 0],
66+
[new \Zend_Db_Expr('free_shipping IS NULL')]
67+
);
68+
}
69+
}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\OfflineShipping\Setup;
8+
9+
use Magento\Framework\Setup\ModuleContextInterface;
10+
use Magento\Framework\Setup\SchemaSetupInterface;
11+
use Magento\Framework\Setup\UpgradeSchemaInterface;
12+
13+
/**
14+
* Upgrade schema DB for OfflineShipping module.
15+
*/
16+
class UpgradeSchema implements UpgradeSchemaInterface
17+
{
18+
/**
19+
* @var string
20+
*/
21+
private $quoteConnectionName = 'checkout';
22+
23+
/**
24+
* @var string
25+
*/
26+
private $salesConnectionName = 'sales';
27+
28+
/**
29+
* @inheritdoc
30+
*/
31+
public function upgrade(SchemaSetupInterface $setup, ModuleContextInterface $context)
32+
{
33+
$setup->startSetup();
34+
35+
if (version_compare($context->getVersion(), '2.0.1', '<')) {
36+
$this->updateFreeShippingColumns($setup);
37+
}
38+
39+
$setup->endSetup();
40+
}
41+
42+
/**
43+
* Modify 'free_shipping' and 'simple_free_shipping' columns added incorrectly in InstallSchema.
44+
*
45+
* @param SchemaSetupInterface $setup
46+
* @return void
47+
*/
48+
private function updateFreeShippingColumns(SchemaSetupInterface $setup)
49+
{
50+
$setup->getConnection()->modifyColumn(
51+
$setup->getTable('salesrule'),
52+
'simple_free_shipping',
53+
[
54+
'type' => \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT,
55+
'unsigned' => true,
56+
'nullable' => false,
57+
'default' => '0',
58+
'comment' => 'Simple Free Shipping',
59+
]
60+
);
61+
$setup->getConnection($this->salesConnectionName)->modifyColumn(
62+
$setup->getTable('sales_order_item', $this->salesConnectionName),
63+
'free_shipping',
64+
[
65+
'type' => \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT,
66+
'unsigned' => true,
67+
'nullable' => false,
68+
'default' => '0',
69+
'comment' => 'Free Shipping',
70+
]
71+
);
72+
$setup->getConnection($this->quoteConnectionName)->modifyColumn(
73+
$setup->getTable('quote_address', $this->quoteConnectionName),
74+
'free_shipping',
75+
[
76+
'type' => \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT,
77+
'unsigned' => true,
78+
'nullable' => false,
79+
'default' => '0',
80+
'comment' => 'Free Shipping',
81+
]
82+
);
83+
$setup->getConnection($this->quoteConnectionName)->modifyColumn(
84+
$setup->getTable('quote_item', $this->quoteConnectionName),
85+
'free_shipping',
86+
[
87+
'type' => \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT,
88+
'unsigned' => true,
89+
'nullable' => false,
90+
'default' => '0',
91+
'comment' => 'Free Shipping',
92+
]
93+
);
94+
$setup->getConnection($this->quoteConnectionName)->modifyColumn(
95+
$setup->getTable('quote_address_item', $this->quoteConnectionName),
96+
'free_shipping',
97+
[
98+
'type' => \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER,
99+
'unsigned' => true,
100+
'comment' => 'Free Shipping',
101+
]
102+
);
103+
}
104+
}

app/code/Magento/OfflineShipping/composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@
88
"magento/module-backend": "100.2.*",
99
"magento/module-shipping": "100.2.*",
1010
"magento/module-catalog": "101.1.*",
11+
"magento/module-sales": "100.2.*",
1112
"magento/module-sales-rule": "100.2.*",
1213
"magento/module-directory": "100.2.*",
1314
"magento/module-quote": "100.2.*",
1415
"magento/framework": "100.2.*"
1516
},
1617
"suggest": {
1718
"magento/module-checkout": "100.2.*",
18-
"magento/module-sales": "100.2.*",
1919
"magento/module-offline-shipping-sample-data": "Sample Data version:100.2.*"
2020
},
2121
"type": "magento2-module",

app/code/Magento/OfflineShipping/etc/module.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
*/
77
-->
88
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
9-
<module name="Magento_OfflineShipping" setup_version="2.0.0">
9+
<module name="Magento_OfflineShipping" setup_version="2.0.1">
1010
<sequence>
1111
<module name="Magento_Store"/>
1212
<module name="Magento_Sales"/>

app/code/Magento/Sales/Model/AdminOrder/Create.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1568,7 +1568,7 @@ public function applyCoupon($code)
15681568
$this->getQuote()->getShippingAddress()->setCollectShippingRates(true);
15691569

15701570
if (empty($code)) {
1571-
$this->getQuote()->getShippingAddress()->setFreeShipping(null);
1571+
$this->getQuote()->getShippingAddress()->setFreeShipping(0);
15721572
}
15731573
$this->getQuote()->setCouponCode($code);
15741574
$this->setRecollect(true);

app/code/Magento/Sales/Test/Unit/Model/AdminOrder/CreateTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ public function testApplyCoupon()
329329
$quoteMock->expects($this->once())->method('setCouponCode')->with($couponCode)->willReturnSelf();
330330

331331
$addressMock->expects($this->once())->method('setCollectShippingRates')->with(true)->willReturnSelf();
332-
$addressMock->expects($this->once())->method('setFreeShipping')->with(null)->willReturnSelf();
332+
$addressMock->expects($this->once())->method('setFreeShipping')->with(0)->willReturnSelf();
333333

334334
$object = $this->adminOrderCreate->applyCoupon($couponCode);
335335
$this->assertEquals($this->adminOrderCreate, $object);

app/code/Magento/Theme/Controller/Adminhtml/Design/Config/Save.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,15 @@ protected function getRequestData()
115115
$data = array_filter($data, function ($param) {
116116
return isset($param['error']) && $param['error'] > 0 ? false : true;
117117
});
118+
119+
/**
120+
* Set null to theme id in case it's empty string,
121+
* in order to delete value from db config but not set empty string,
122+
* which may cause an error in Magento/Theme/Model/ResourceModel/Theme/Collection::getThemeByFullPath().
123+
*/
124+
if (isset($data['theme_theme_id']) && $data['theme_theme_id'] === '') {
125+
$data['theme_theme_id'] = null;
126+
}
118127
return $data;
119128
}
120129
}

0 commit comments

Comments
 (0)