Skip to content

Commit fe16964

Browse files
author
Alexander Akimov
authored
Merge pull request #2286 from magento-tsg/2.2.4-develop-pr23
[TSG] Backporting for 2.2 (pr23) (2.2.4)
2 parents db679be + bc92edc commit fe16964

File tree

6 files changed

+199
-16
lines changed

6 files changed

+199
-16
lines changed

app/code/Magento/Sales/CustomerData/LastOrderedItems.php

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,15 @@
77

88
use Magento\Customer\CustomerData\SectionSourceInterface;
99
use Magento\Catalog\Api\ProductRepositoryInterface;
10+
use Magento\Framework\Exception\NoSuchEntityException;
11+
use Psr\Log\LoggerInterface;
12+
use Magento\Framework\App\ObjectManager;
1013

1114
/**
1215
* Returns information for "Recently Ordered" widget.
1316
* It contains list of 5 salable products from the last placed order.
1417
* Qty of products to display is limited by LastOrderedItems::SIDEBAR_ORDER_LIMIT constant.
18+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
1519
*/
1620
class LastOrderedItems implements SectionSourceInterface
1721
{
@@ -60,28 +64,36 @@ class LastOrderedItems implements SectionSourceInterface
6064
*/
6165
private $productRepository;
6266

67+
/**
68+
* @var LoggerInterface
69+
*/
70+
private $logger;
71+
6372
/**
6473
* @param \Magento\Sales\Model\ResourceModel\Order\CollectionFactory $orderCollectionFactory
6574
* @param \Magento\Sales\Model\Order\Config $orderConfig
6675
* @param \Magento\Customer\Model\Session $customerSession
6776
* @param \Magento\CatalogInventory\Api\StockRegistryInterface $stockRegistry
6877
* @param \Magento\Store\Model\StoreManagerInterface $storeManager
6978
* @param ProductRepositoryInterface $productRepository
79+
* @param LoggerInterface|null $logger
7080
*/
7181
public function __construct(
7282
\Magento\Sales\Model\ResourceModel\Order\CollectionFactory $orderCollectionFactory,
7383
\Magento\Sales\Model\Order\Config $orderConfig,
7484
\Magento\Customer\Model\Session $customerSession,
7585
\Magento\CatalogInventory\Api\StockRegistryInterface $stockRegistry,
7686
\Magento\Store\Model\StoreManagerInterface $storeManager,
77-
ProductRepositoryInterface $productRepository
87+
ProductRepositoryInterface $productRepository,
88+
LoggerInterface $logger = null
7889
) {
7990
$this->_orderCollectionFactory = $orderCollectionFactory;
8091
$this->_orderConfig = $orderConfig;
8192
$this->_customerSession = $customerSession;
8293
$this->stockRegistry = $stockRegistry;
8394
$this->_storeManager = $storeManager;
8495
$this->productRepository = $productRepository;
96+
$this->logger = $logger ?? ObjectManager::getInstance()->get(LoggerInterface::class);
8597
}
8698

8799
/**
@@ -118,12 +130,17 @@ protected function getItems()
118130
/** @var \Magento\Sales\Model\Order\Item $item */
119131
foreach ($order->getParentItemsRandomCollection($limit) as $item) {
120132
/** @var \Magento\Catalog\Model\Product $product */
121-
$product = $this->productRepository->getById(
122-
$item->getProductId(),
123-
false,
124-
$this->_storeManager->getStore()->getId()
125-
);
126-
if ($product && in_array($website, $product->getWebsiteIds())) {
133+
try {
134+
$product = $this->productRepository->getById(
135+
$item->getProductId(),
136+
false,
137+
$this->_storeManager->getStore()->getId()
138+
);
139+
} catch (NoSuchEntityException $noEntityException) {
140+
$this->logger->critical($noEntityException);
141+
continue;
142+
}
143+
if (isset($product) && in_array($website, $product->getWebsiteIds())) {
127144
$url = $product->isVisibleInSiteVisibility() ? $product->getProductUrl() : null;
128145
$items[] = [
129146
'id' => $item->getId(),
@@ -152,7 +169,7 @@ protected function isItemAvailableForReorder(\Magento\Sales\Model\Order\Item $or
152169
$orderItem->getStore()->getWebsiteId()
153170
);
154171
return $stockItem->getIsInStock();
155-
} catch (\Magento\Framework\Exception\NoSuchEntityException $noEntityException) {
172+
} catch (NoSuchEntityException $noEntityException) {
156173
return false;
157174
}
158175
}

app/code/Magento/Sales/Test/Unit/CustomerData/LastOrderedItemsTest.php

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,11 @@ class LastOrderedItemsTest extends \PHPUnit\Framework\TestCase
5858
*/
5959
private $section;
6060

61+
/**
62+
* @var \Psr\Log\LoggerInterface|\PHPUnit_Framework_MockObject_MockObject
63+
*/
64+
private $loggerMock;
65+
6166
protected function setUp()
6267
{
6368
$this->objectManagerHelper = new ObjectManagerHelper($this);
@@ -81,13 +86,16 @@ protected function setUp()
8186
->getMock();
8287
$this->productRepository = $this->getMockBuilder(\Magento\Catalog\Api\ProductRepositoryInterface::class)
8388
->getMockForAbstractClass();
89+
$this->loggerMock = $this->getMockBuilder(\Psr\Log\LoggerInterface::class)
90+
->getMockForAbstractClass();
8491
$this->section = new \Magento\Sales\CustomerData\LastOrderedItems(
8592
$this->orderCollectionFactoryMock,
8693
$this->orderConfigMock,
8794
$this->customerSessionMock,
8895
$this->stockRegistryMock,
8996
$this->storeManagerMock,
90-
$this->productRepository
97+
$this->productRepository,
98+
$this->loggerMock
9199
);
92100
}
93101

@@ -196,4 +204,34 @@ private function getLastOrderMock()
196204
->willReturnSelf();
197205
return $this->orderMock;
198206
}
207+
208+
public function testGetSectionDataWithNotExistingProduct()
209+
{
210+
$storeId = 1;
211+
$websiteId = 4;
212+
$productId = 1;
213+
$exception = new \Magento\Framework\Exception\NoSuchEntityException(__("Product doesn't exist"));
214+
$orderItemMock = $this->getMockBuilder(\Magento\Sales\Model\Order\Item::class)
215+
->disableOriginalConstructor()
216+
->setMethods(['getProductId'])
217+
->getMock();
218+
$storeMock = $this->getMockBuilder(\Magento\Store\Api\Data\StoreInterface::class)->getMockForAbstractClass();
219+
220+
$this->getLastOrderMock();
221+
$this->storeManagerMock->expects($this->exactly(2))->method('getStore')->willReturn($storeMock);
222+
$storeMock->expects($this->once())->method('getWebsiteId')->willReturn($websiteId);
223+
$storeMock->expects($this->once())->method('getId')->willReturn($storeId);
224+
$this->orderMock->expects($this->once())
225+
->method('getParentItemsRandomCollection')
226+
->with(\Magento\Sales\CustomerData\LastOrderedItems::SIDEBAR_ORDER_LIMIT)
227+
->willReturn([$orderItemMock]);
228+
$orderItemMock->expects($this->once())->method('getProductId')->willReturn($productId);
229+
$this->productRepository->expects($this->once())
230+
->method('getById')
231+
->with($productId, false, $storeId)
232+
->willThrowException($exception);
233+
$this->loggerMock->expects($this->once())->method('critical')->with($exception);
234+
235+
$this->assertEquals(['items' => []], $this->section->getSectionData());
236+
}
199237
}

app/code/Magento/Theme/Model/Design/Config/Validator.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ private function getTemplateText($templateId, DesignConfigInterface $designConfi
114114
if (is_numeric($templateId)) {
115115
$template->load($templateId);
116116
} else {
117+
$template->setForcedArea($templateId);
117118
$template->loadDefault($templateId);
118119
}
119120
$text = $template->getTemplateText();

app/code/Magento/Theme/Test/Unit/Model/Config/ValidatorTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ public function testValidateHasRecursiveReference()
7070
$designElementMock->expects($this->once())->method('getValue')->willReturn($fieldConfig['field']);
7171

7272
$templateMock = $this->getMockBuilder(\Magento\Email\Model\TemplateInterface::class)
73-
->setMethods(['getTemplateText', 'emulateDesign', 'loadDefault', 'revertDesign'])
73+
->setMethods(['getTemplateText', 'emulateDesign', 'loadDefault', 'revertDesign', 'setForcedArea'])
7474
->getMock();
7575

7676
$this->templateFactoryMock->expects($this->once())->method('create')->willReturn($templateMock);
@@ -110,7 +110,7 @@ public function testValidateNoRecursiveReference()
110110
$designElementMock->expects($this->once())->method('getValue')->willReturn($fieldConfig['field']);
111111

112112
$templateMock = $this->getMockBuilder(\Magento\Email\Model\TemplateInterface::class)
113-
->setMethods(['getTemplateText', 'emulateDesign', 'loadDefault', 'revertDesign'])
113+
->setMethods(['getTemplateText', 'emulateDesign', 'loadDefault', 'revertDesign', 'setForcedArea'])
114114
->getMock();
115115

116116
$this->templateFactoryMock->expects($this->once())->method('create')->willReturn($templateMock);
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\Theme\Test\Unit\Model\Design\Config;
8+
9+
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
10+
use Magento\Theme\Model\Design\Config\Validator;
11+
12+
/**
13+
* Unit tests for Magento\Theme\Test\Unit\Model\Design\Config\Validator.
14+
*/
15+
class ValidatorTest extends \PHPUnit\Framework\TestCase
16+
{
17+
/**
18+
* @var \Magento\Framework\Mail\TemplateInterfaceFactory|\PHPUnit_Framework_MockObject_MockObject
19+
*/
20+
private $templateFactory;
21+
22+
/**
23+
* @var \Magento\Framework\Mail\TemplateInterface|\PHPUnit_Framework_MockObject_MockObject
24+
*/
25+
private $template;
26+
27+
/**
28+
* @var \Magento\Theme\Api\Data\DesignConfigInterface|\PHPUnit_Framework_MockObject_MockObject
29+
*/
30+
private $designConfig;
31+
32+
/**
33+
* @var ObjectManager
34+
*/
35+
private $objectManager;
36+
37+
/**
38+
* @inheritdoc
39+
*/
40+
public function setUp()
41+
{
42+
$this->objectManager = new ObjectManager($this);
43+
$this->templateFactory = $this->getMockBuilder(\Magento\Framework\Mail\TemplateInterfaceFactory::class)
44+
->disableOriginalConstructor()
45+
->setMethods(['create'])
46+
->getMockForAbstractClass();
47+
$this->template = $this->getMockBuilder(\Magento\Framework\Mail\TemplateInterface::class)
48+
->disableOriginalConstructor()
49+
->setMethods(
50+
[
51+
'emulateDesign',
52+
'setForcedArea',
53+
'loadDefault',
54+
'getTemplateText',
55+
'revertDesign',
56+
]
57+
)
58+
->getMockForAbstractClass();
59+
$this->templateFactory->expects($this->any())->method('create')->willReturn($this->template);
60+
$this->designConfig = $this->getMockBuilder(\Magento\Theme\Api\Data\DesignConfigInterface::class)
61+
->disableOriginalConstructor()
62+
->setMethods(['getExtensionAttributes'])
63+
->getMockForAbstractClass();
64+
}
65+
66+
/**
67+
* @return void
68+
*/
69+
public function testGetDefaultTemplateTextDefaultScope()
70+
{
71+
$templateId = 'email_template';
72+
$designData = [
73+
'field_config' => ['field' => 'fieldValue'],
74+
'value' => $templateId,
75+
];
76+
77+
$this->templateFactory->expects($this->once())->method('create');
78+
$this->designConfig->expects($this->any())->method('getScope')->willReturn('default');
79+
$this->template->expects($this->once())->method('emulateDesign');
80+
$this->template->expects($this->once())->method('setForcedArea')->with($templateId);
81+
$this->template->expects($this->once())->method('loadDefault')->with($templateId);
82+
$this->template->expects($this->once())->method('getTemplateText');
83+
$this->template->expects($this->once())->method('revertDesign');
84+
85+
$extensionAttributes = $this->getMockBuilder(\Magento\Theme\Api\Data\DesignConfigExtensionInterface::class)
86+
->disableOriginalConstructor()
87+
->setMethods(['getDesignConfigData'])
88+
->getMockForAbstractClass();
89+
90+
$extensionAttributes->expects($this->any())->method('getDesignConfigData')->willReturn(
91+
[
92+
$this->getDesignConfigData($designData),
93+
]
94+
);
95+
96+
$this->designConfig->expects($this->any())->method('getExtensionAttributes')->willReturn($extensionAttributes);
97+
98+
/** @var Validator $validator */
99+
$validator = $this->objectManager->getObject(
100+
Validator::class,
101+
[
102+
'templateFactory' => $this->templateFactory,
103+
'fields' => ['field' => 'fieldValue'],
104+
]
105+
);
106+
$validator->validate($this->designConfig);
107+
}
108+
109+
/**
110+
* Returns design config data object.
111+
*
112+
* @param array $data
113+
* @return \Magento\Theme\Model\Data\Design\Config\Data
114+
*/
115+
private function getDesignConfigData(array $data = [])
116+
{
117+
return $this->objectManager->getObject(
118+
\Magento\Theme\Model\Data\Design\Config\Data::class,
119+
[
120+
'data' => $data,
121+
]
122+
);
123+
}
124+
}

lib/web/mage/adminhtml/form.js

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -456,12 +456,15 @@ define([
456456
} else {
457457
values = valuesFrom[idFrom].values;
458458
fromId = $(idFrom + values[0]);
459-
radioFrom = fromId ? $$('[name="' + fromId.name + '"]:checked') : [];
460-
isInArray = radioFrom.length > 0 && values.indexOf(radioFrom[0].value) !== -1;
461-
isNegative = valuesFrom[idFrom].negative;
462459

463-
if (!radioFrom || isInArray && isNegative || !isInArray && !isNegative) {
464-
shouldShowUp = false;
460+
if (fromId) {
461+
radioFrom = $$('[name="' + fromId.name + '"]:checked');
462+
isInArray = radioFrom.length > 0 && values.indexOf(radioFrom[0].value) !== -1;
463+
isNegative = valuesFrom[idFrom].negative;
464+
465+
if (!radioFrom || isInArray && isNegative || !isInArray && !isNegative) {
466+
shouldShowUp = false;
467+
}
465468
}
466469
}
467470
}

0 commit comments

Comments
 (0)