Skip to content

Commit 83abd82

Browse files
committed
Merge remote-tracking branch 'origin/MAGETWO-95176' into 2.2-develop-pr72
2 parents 77c03d1 + c842cef commit 83abd82

File tree

9 files changed

+239
-18
lines changed

9 files changed

+239
-18
lines changed

app/code/Magento/CatalogInventory/Observer/CancelOrderItemObserver.php

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,21 @@
66

77
namespace Magento\CatalogInventory\Observer;
88

9-
use Magento\Framework\Event\ObserverInterface;
109
use Magento\CatalogInventory\Api\StockManagementInterface;
10+
use Magento\CatalogInventory\Model\Configuration;
1111
use Magento\Framework\Event\Observer as EventObserver;
12+
use Magento\Framework\Event\ObserverInterface;
1213

1314
/**
1415
* Catalog inventory module observer
1516
*/
1617
class CancelOrderItemObserver implements ObserverInterface
1718
{
19+
/**
20+
* @var \Magento\CatalogInventory\Model\Configuration
21+
*/
22+
protected $configuration;
23+
1824
/**
1925
* @var StockManagementInterface
2026
*/
@@ -26,13 +32,16 @@ class CancelOrderItemObserver implements ObserverInterface
2632
protected $priceIndexer;
2733

2834
/**
35+
* @param Configuration $configuration
2936
* @param StockManagementInterface $stockManagement
3037
* @param \Magento\Catalog\Model\Indexer\Product\Price\Processor $priceIndexer
3138
*/
3239
public function __construct(
40+
Configuration $configuration,
3341
StockManagementInterface $stockManagement,
3442
\Magento\Catalog\Model\Indexer\Product\Price\Processor $priceIndexer
3543
) {
44+
$this->configuration = $configuration;
3645
$this->stockManagement = $stockManagement;
3746
$this->priceIndexer = $priceIndexer;
3847
}
@@ -49,7 +58,8 @@ public function execute(EventObserver $observer)
4958
$item = $observer->getEvent()->getItem();
5059
$children = $item->getChildrenItems();
5160
$qty = $item->getQtyOrdered() - max($item->getQtyShipped(), $item->getQtyInvoiced()) - $item->getQtyCanceled();
52-
if ($item->getId() && $item->getProductId() && empty($children) && $qty) {
61+
if ($item->getId() && $item->getProductId() && empty($children) && $qty && $this->configuration
62+
->getCanBackInStock()) {
5363
$this->stockManagement->backItemQty($item->getProductId(), $qty, $item->getStore()->getWebsiteId());
5464
}
5565
$this->priceIndexer->reindexRow($item->getProductId());

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

Lines changed: 45 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -100,16 +100,19 @@ public function execute(\Magento\Framework\Event\Observer $observer)
100100
}
101101

102102
$mapsGenerated = false;
103-
if ($category->dataHasChangedFor('url_key')
104-
|| $category->dataHasChangedFor('is_anchor')
105-
|| $category->getChangedProductIds()
106-
) {
103+
if ($this->isCategoryHasChanged($category)) {
107104
if ($category->dataHasChangedFor('url_key')) {
108105
$categoryUrlRewriteResult = $this->categoryUrlRewriteGenerator->generate($category);
109106
$this->urlRewriteBunchReplacer->doBunchReplace($categoryUrlRewriteResult);
110107
}
111-
$productUrlRewriteResult = $this->urlRewriteHandler->generateProductUrlRewrites($category);
112-
$this->urlRewriteBunchReplacer->doBunchReplace($productUrlRewriteResult);
108+
if ($this->isChangedOnlyProduct($category)) {
109+
$productUrlRewriteResult =
110+
$this->urlRewriteHandler->updateProductUrlRewritesForChangedProduct($category);
111+
$this->urlRewriteBunchReplacer->doBunchReplace($productUrlRewriteResult);
112+
} else {
113+
$productUrlRewriteResult = $this->urlRewriteHandler->generateProductUrlRewrites($category);
114+
$this->urlRewriteBunchReplacer->doBunchReplace($productUrlRewriteResult);
115+
}
113116
$mapsGenerated = true;
114117
}
115118

@@ -120,8 +123,42 @@ public function execute(\Magento\Framework\Event\Observer $observer)
120123
}
121124

122125
/**
123-
* in case store_id is not set for category then we can assume that it was passed through product import.
124-
* store group must have only one root category, so receiving category's path and checking if one of it parts
126+
* Check is category changed changed.
127+
*
128+
* @param Category $category
129+
* @return bool
130+
*/
131+
private function isCategoryHasChanged(Category $category): bool
132+
{
133+
if ($category->dataHasChangedFor('url_key')
134+
|| $category->dataHasChangedFor('is_anchor')
135+
|| !empty($category->getChangedProductIds())) {
136+
return true;
137+
}
138+
139+
return false;
140+
}
141+
142+
/**
143+
* Check is only product changed.
144+
*
145+
* @param Category $category
146+
* @return bool
147+
*/
148+
private function isChangedOnlyProduct(Category $category): bool
149+
{
150+
if (!empty($category->getChangedProductIds())
151+
&& !$category->dataHasChangedFor('is_anchor')
152+
&& !$category->dataHasChangedFor('url_key')) {
153+
return true;
154+
}
155+
156+
return false;
157+
}
158+
159+
/**
160+
* In case store_id is not set for category then we can assume that it was passed through product import.
161+
* Store group must have only one root category, so receiving category's path and checking if one of it parts
125162
* is the root category for store group, we can set default_store_id value from it to category.
126163
* it prevents urls duplication for different stores
127164
* ("Default Category/category/sub" and "Default Category2/category/sub")

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

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
use Magento\UrlRewrite\Service\V1\Data\UrlRewrite;
2525

2626
/**
27+
* Class for management url rewrites.
28+
*
2729
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
2830
*/
2931
class UrlRewriteHandler
@@ -125,7 +127,7 @@ public function generateProductUrlRewrites(Category $category): array
125127
{
126128
$mergeDataProvider = clone $this->mergeDataProviderPrototype;
127129
$this->isSkippedProduct[$category->getEntityId()] = [];
128-
$saveRewriteHistory = $category->getData('save_rewrites_history');
130+
$saveRewriteHistory = (bool)$category->getData('save_rewrites_history');
129131
$storeId = (int)$category->getStoreId();
130132

131133
if ($category->getChangedProductIds()) {
@@ -156,6 +158,30 @@ public function generateProductUrlRewrites(Category $category): array
156158
}
157159

158160
/**
161+
* Update product url rewrites for changed product.
162+
*
163+
* @param Category $category
164+
* @return array
165+
*/
166+
public function updateProductUrlRewritesForChangedProduct(Category $category): array
167+
{
168+
$mergeDataProvider = clone $this->mergeDataProviderPrototype;
169+
$this->isSkippedProduct[$category->getEntityId()] = [];
170+
$saveRewriteHistory = (bool)$category->getData('save_rewrites_history');
171+
$storeIds = $this->getCategoryStoreIds($category);
172+
173+
if ($category->getChangedProductIds()) {
174+
foreach ($storeIds as $storeId) {
175+
$this->generateChangedProductUrls($mergeDataProvider, $category, (int)$storeId, $saveRewriteHistory);
176+
}
177+
}
178+
179+
return $mergeDataProvider->getData();
180+
}
181+
182+
/**
183+
* Delete category rewrites for children.
184+
*
159185
* @param Category $category
160186
* @return void
161187
*/
@@ -184,6 +210,8 @@ public function deleteCategoryRewritesForChildren(Category $category)
184210
}
185211

186212
/**
213+
* Get category products url rewrites.
214+
*
187215
* @param Category $category
188216
* @param int $storeId
189217
* @param bool $saveRewriteHistory
@@ -230,15 +258,15 @@ private function getCategoryProductsUrlRewrites(
230258
*
231259
* @param MergeDataProvider $mergeDataProvider
232260
* @param Category $category
233-
* @param Product $product
234261
* @param int $storeId
235-
* @param $saveRewriteHistory
262+
* @param bool $saveRewriteHistory
263+
* @return void
236264
*/
237265
private function generateChangedProductUrls(
238266
MergeDataProvider $mergeDataProvider,
239267
Category $category,
240268
int $storeId,
241-
$saveRewriteHistory
269+
bool $saveRewriteHistory
242270
) {
243271
$this->isSkippedProduct[$category->getEntityId()] = $category->getAffectedProductIds();
244272

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\CatalogUrlRewrite\Test\Unit\Observer;
9+
10+
use Magento\Catalog\Model\Category;
11+
use Magento\CatalogUrlRewrite\Model\CategoryUrlRewriteGenerator;
12+
use Magento\CatalogUrlRewrite\Model\Map\DatabaseMapPool;
13+
use Magento\CatalogUrlRewrite\Model\Map\DataCategoryUrlRewriteDatabaseMap;
14+
use Magento\CatalogUrlRewrite\Model\Map\DataProductUrlRewriteDatabaseMap;
15+
use Magento\CatalogUrlRewrite\Model\UrlRewriteBunchReplacer;
16+
use Magento\CatalogUrlRewrite\Observer\CategoryProcessUrlRewriteSavingObserver;
17+
use Magento\CatalogUrlRewrite\Observer\UrlRewriteHandler;
18+
use Magento\Framework\Event;
19+
use Magento\Framework\Event\Observer;
20+
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
21+
use Magento\Store\Model\ResourceModel\Group\CollectionFactory;
22+
23+
/**
24+
* Tests Magento\CatalogUrlRewrite\Observer\CategoryProcessUrlRewriteSavingObserver.
25+
*/
26+
class CategoryProcessUrlRewriteSavingObserverTest extends \PHPUnit\Framework\TestCase
27+
{
28+
/**
29+
* @var CategoryProcessUrlRewriteSavingObserver
30+
*/
31+
private $observer;
32+
33+
/**
34+
* @var CategoryUrlRewriteGenerator|\PHPUnit_Framework_MockObject_MockObject
35+
*/
36+
private $categoryUrlRewriteGeneratorMock;
37+
38+
/**
39+
* @var UrlRewriteHandler|\PHPUnit_Framework_MockObject_MockObject
40+
*/
41+
private $urlRewriteHandlerMock;
42+
43+
/**
44+
* @var UrlRewriteBunchReplacer|\PHPUnit_Framework_MockObject_MockObject $urlRewriteMock
45+
*/
46+
private $urlRewriteBunchReplacerMock;
47+
48+
/**
49+
* @var DatabaseMapPool|\PHPUnit_Framework_MockObject_MockObject
50+
*/
51+
private $databaseMapPoolMock;
52+
53+
/**
54+
* @inheritdoc
55+
*/
56+
protected function setUp()
57+
{
58+
$objectManager = new ObjectManager($this);
59+
$this->categoryUrlRewriteGeneratorMock = $this->createMock(CategoryUrlRewriteGenerator::class);
60+
$this->urlRewriteHandlerMock = $this->createMock(UrlRewriteHandler::class);
61+
$this->urlRewriteBunchReplacerMock = $this->createMock(UrlRewriteBunchReplacer::class);
62+
$this->databaseMapPoolMock = $this->createMock(DatabaseMapPool::class);
63+
/** @var CollectionFactory|\PHPUnit_Framework_MockObject_MockObject $storeGroupFactoryMock */
64+
$storeGroupCollectionFactoryMock = $this->createMock(CollectionFactory::class);
65+
66+
$this->observer = $objectManager->getObject(
67+
CategoryProcessUrlRewriteSavingObserver::class,
68+
[
69+
'categoryUrlRewriteGenerator' => $this->categoryUrlRewriteGeneratorMock,
70+
'urlRewriteHandler' => $this->urlRewriteHandlerMock,
71+
'urlRewriteBunchReplacer' => $this->urlRewriteBunchReplacerMock,
72+
'databaseMapPool' => $this->databaseMapPoolMock,
73+
'dataUrlRewriteClassNames' => [
74+
DataCategoryUrlRewriteDatabaseMap::class,
75+
DataProductUrlRewriteDatabaseMap::class
76+
],
77+
'storeGroupFactory' => $storeGroupCollectionFactoryMock,
78+
]
79+
);
80+
}
81+
82+
/**
83+
* Covers case when only associated products are changed for category.
84+
*
85+
* @return void
86+
*/
87+
public function testExecuteCategoryOnlyProductHasChanged()
88+
{
89+
$productId = 120;
90+
$productRewrites = ['product-url-rewrite'];
91+
92+
/** @var Observer|\PHPUnit_Framework_MockObject_MockObject $observerMock */
93+
$observerMock = $this->createMock(Observer::class);
94+
/** @var Event|\PHPUnit_Framework_MockObject_MockObject $eventMock */
95+
$eventMock = $this->createMock(Event::class);
96+
/** @var Category|\PHPUnit_Framework_MockObject_MockObject $categoryMock */
97+
$categoryMock = $this->createPartialMock(
98+
Category::class,
99+
[
100+
'hasData',
101+
'dataHasChangedFor',
102+
'getChangedProductIds',
103+
]
104+
);
105+
106+
$categoryMock->expects($this->once())->method('hasData')->with('store_id')->willReturn(true);
107+
$categoryMock->expects($this->exactly(2))->method('getChangedProductIds')->willReturn([$productId]);
108+
$categoryMock->expects($this->any())->method('dataHasChangedFor')
109+
->willReturnMap(
110+
[
111+
['url_key', false],
112+
['is_anchor', false],
113+
]
114+
);
115+
$eventMock->expects($this->once())->method('getData')->with('category')->willReturn($categoryMock);
116+
$observerMock->expects($this->once())->method('getEvent')->willReturn($eventMock);
117+
118+
$this->urlRewriteHandlerMock->expects($this->once())
119+
->method('updateProductUrlRewritesForChangedProduct')
120+
->with($categoryMock)
121+
->willReturn($productRewrites);
122+
123+
$this->urlRewriteBunchReplacerMock->expects($this->once())
124+
->method('doBunchReplace')
125+
->with($productRewrites, 10000);
126+
127+
$this->observer->execute($observerMock);
128+
}
129+
}

app/code/Magento/Quote/Model/Quote/Address/Total.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
namespace Magento\Quote\Model\Quote\Address;
77

88
/**
9+
* Class Total
10+
*
911
* @method string getCode()
1012
*
1113
* @api
@@ -54,6 +56,8 @@ public function __construct(
5456
*/
5557
public function setTotalAmount($code, $amount)
5658
{
59+
$amount = is_float($amount) ? round($amount, 4) : $amount;
60+
5761
$this->totalAmounts[$code] = $amount;
5862
if ($code != 'subtotal') {
5963
$code = $code . '_amount';
@@ -72,6 +76,8 @@ public function setTotalAmount($code, $amount)
7276
*/
7377
public function setBaseTotalAmount($code, $amount)
7478
{
79+
$amount = is_float($amount) ? round($amount, 4) : $amount;
80+
7581
$this->baseTotalAmounts[$code] = $amount;
7682
if ($code != 'subtotal') {
7783
$code = $code . '_amount';
@@ -167,6 +173,7 @@ public function getAllBaseTotalAmounts()
167173

168174
/**
169175
* Set the full info, which is used to capture tax related information.
176+
*
170177
* If a string is used, it is assumed to be serialized.
171178
*
172179
* @param array|string $info

app/code/Magento/Reports/Model/ResourceModel/Order/Collection.php

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
* Copyright © Magento, Inc. All rights reserved.
44
* See COPYING.txt for license details.
55
*/
6-
76
namespace Magento\Reports\Model\ResourceModel\Order;
87

98
use Magento\Framework\DB\Select;
@@ -81,7 +80,7 @@ class Collection extends \Magento\Sales\Model\ResourceModel\Order\Collection
8180
* @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate
8281
* @param \Magento\Sales\Model\Order\Config $orderConfig
8382
* @param \Magento\Sales\Model\ResourceModel\Report\OrderFactory $reportOrderFactory
84-
* @param null $connection
83+
* @param \Magento\Framework\DB\Adapter\AdapterInterface $connection
8584
* @param \Magento\Framework\Model\ResourceModel\Db\AbstractDb $resource
8685
*
8786
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
@@ -825,7 +824,7 @@ protected function getTotalsExpression(
825824
) {
826825
$template = ($storeId != 0)
827826
? '(main_table.base_subtotal - %2$s - %1$s - ABS(main_table.base_discount_amount) - %3$s)'
828-
: '((main_table.base_subtotal - %1$s - %2$s - ABS(main_table.base_discount_amount) - %3$s) '
827+
: '((main_table.base_subtotal - %1$s - %2$s - ABS(main_table.base_discount_amount) + %3$s) '
829828
. ' * main_table.base_to_global_rate)';
830829
return sprintf($template, $baseSubtotalRefunded, $baseSubtotalCanceled, $baseDiscountCanceled);
831830
}

0 commit comments

Comments
 (0)