Skip to content

Commit 360ef42

Browse files
committed
Merge branch '2.2-develop' into 2.2-develop-pr10
2 parents 2281c89 + 4381a6b commit 360ef42

File tree

82 files changed

+4466
-584
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

82 files changed

+4466
-584
lines changed

app/code/Magento/Catalog/Model/Product/Option/Repository.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,9 @@ public function save(\Magento\Catalog\Api\Data\ProductCustomOptionInterface $opt
172172
$originalValues = $persistedOption->getValues();
173173
$newValues = $option->getData('values');
174174
if ($newValues) {
175-
$newValues = $this->markRemovedValues($newValues, $originalValues);
175+
if (isset($originalValues)) {
176+
$newValues = $this->markRemovedValues($newValues, $originalValues);
177+
}
176178
$option->setData('values', $newValues);
177179
}
178180
}

app/code/Magento/Catalog/Test/Unit/Model/Product/Option/RepositoryTest.php

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,4 +267,29 @@ public function testSave()
267267
]);
268268
$this->assertEquals($this->optionMock, $this->optionRepository->save($this->optionMock));
269269
}
270+
271+
public function testSaveWhenOptionTypeWasChanged()
272+
{
273+
$productSku = 'simple_product';
274+
$optionId = 1;
275+
$this->optionMock->expects($this->once())->method('getProductSku')->willReturn($productSku);
276+
$this->productRepositoryMock
277+
->expects($this->once())
278+
->method('get')
279+
->with($productSku)
280+
->willReturn($this->productMock);
281+
$this->optionMock->expects($this->any())->method('getOptionId')->willReturn($optionId);
282+
$this->productMock->expects($this->once())->method('getOptions')->willReturn([]);
283+
$this->optionMock->expects($this->once())->method('getData')->with('values')->willReturn([
284+
['option_type_id' => 4],
285+
['option_type_id' => 5]
286+
]);
287+
$optionCollection = $this->getMockBuilder(\Magento\Catalog\Model\ResourceModel\Product\Option\Collection::class)
288+
->disableOriginalConstructor()
289+
->getMock();
290+
$optionCollection->expects($this->once())->method('getProductOptions')->willReturn([$this->optionMock]);
291+
$this->optionCollectionFactory->expects($this->once())->method('create')->willReturn($optionCollection);
292+
$this->optionMock->expects($this->once())->method('getValues')->willReturn(null);
293+
$this->assertEquals($this->optionMock, $this->optionRepository->save($this->optionMock));
294+
}
270295
}

app/code/Magento/CatalogUrlRewrite/Model/ProductScopeRewriteGenerator.php

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,18 @@
55
*/
66
namespace Magento\CatalogUrlRewrite\Model;
77

8+
use Magento\Catalog\Api\CategoryRepositoryInterface;
89
use Magento\Catalog\Model\Category;
910
use Magento\Catalog\Model\Product;
11+
use Magento\CatalogUrlRewrite\Model\Product\AnchorUrlRewriteGenerator;
1012
use Magento\CatalogUrlRewrite\Model\Product\CanonicalUrlRewriteGenerator;
1113
use Magento\CatalogUrlRewrite\Model\Product\CategoriesUrlRewriteGenerator;
1214
use Magento\CatalogUrlRewrite\Model\Product\CurrentUrlRewritesRegenerator;
13-
use Magento\CatalogUrlRewrite\Model\Product\AnchorUrlRewriteGenerator;
1415
use Magento\CatalogUrlRewrite\Service\V1\StoreViewService;
16+
use Magento\Framework\App\ObjectManager;
1517
use Magento\Store\Model\Store;
1618
use Magento\Store\Model\StoreManagerInterface;
1719
use Magento\UrlRewrite\Model\MergeDataProviderFactory;
18-
use Magento\Framework\App\ObjectManager;
1920

2021
/**
2122
* Class ProductScopeRewriteGenerator
@@ -63,6 +64,11 @@ class ProductScopeRewriteGenerator
6364
*/
6465
private $mergeDataProviderPrototype;
6566

67+
/**
68+
* @var CategoryRepositoryInterface
69+
*/
70+
private $categoryRepository;
71+
6672
/**
6773
* @param StoreViewService $storeViewService
6874
* @param StoreManagerInterface $storeManager
@@ -72,6 +78,7 @@ class ProductScopeRewriteGenerator
7278
* @param CurrentUrlRewritesRegenerator $currentUrlRewritesRegenerator
7379
* @param AnchorUrlRewriteGenerator $anchorUrlRewriteGenerator
7480
* @param \Magento\UrlRewrite\Model\MergeDataProviderFactory|null $mergeDataProviderFactory
81+
* @param CategoryRepositoryInterface|null $categoryRepository
7582
*/
7683
public function __construct(
7784
StoreViewService $storeViewService,
@@ -81,7 +88,8 @@ public function __construct(
8188
CategoriesUrlRewriteGenerator $categoriesUrlRewriteGenerator,
8289
CurrentUrlRewritesRegenerator $currentUrlRewritesRegenerator,
8390
AnchorUrlRewriteGenerator $anchorUrlRewriteGenerator,
84-
MergeDataProviderFactory $mergeDataProviderFactory = null
91+
MergeDataProviderFactory $mergeDataProviderFactory = null,
92+
CategoryRepositoryInterface $categoryRepository = null
8593
) {
8694
$this->storeViewService = $storeViewService;
8795
$this->storeManager = $storeManager;
@@ -94,6 +102,8 @@ public function __construct(
94102
$mergeDataProviderFactory = ObjectManager::getInstance()->get(MergeDataProviderFactory::class);
95103
}
96104
$this->mergeDataProviderPrototype = $mergeDataProviderFactory->create();
105+
$this->categoryRepository = $categoryRepository ?:
106+
ObjectManager::getInstance()->get(CategoryRepositoryInterface::class);
97107
}
98108

99109
/**
@@ -150,10 +160,14 @@ public function generateForSpecificStoreView($storeId, $productCategories, Produ
150160
$mergeDataProvider = clone $this->mergeDataProviderPrototype;
151161
$categories = [];
152162
foreach ($productCategories as $category) {
153-
if ($this->isCategoryProperForGenerating($category, $storeId)) {
154-
$categories[] = $category;
163+
if (!$this->isCategoryProperForGenerating($category, $storeId)) {
164+
continue;
155165
}
166+
167+
// category should be loaded per appropriate store if category's URL key has been changed
168+
$categories[] = $this->getCategoryWithOverriddenUrlKey($storeId, $category);
156169
}
170+
157171
$productCategories = $this->objectRegistryFactory->create(['entities' => $categories]);
158172

159173
$mergeDataProvider->merge(
@@ -199,4 +213,26 @@ public function isCategoryProperForGenerating(Category $category, $storeId)
199213
}
200214
return false;
201215
}
216+
217+
/**
218+
* Checks if URL key has been changed for provided category and returns reloaded category,
219+
* in other case - returns provided category.
220+
*
221+
* @param $storeId
222+
* @param Category $category
223+
* @return Category
224+
*/
225+
private function getCategoryWithOverriddenUrlKey($storeId, Category $category)
226+
{
227+
$isUrlKeyOverridden = $this->storeViewService->doesEntityHaveOverriddenUrlKeyForStore(
228+
$storeId,
229+
$category->getEntityId(),
230+
Category::ENTITY
231+
);
232+
233+
if (!$isUrlKeyOverridden) {
234+
return $category;
235+
}
236+
return $this->categoryRepository->get($category->getEntityId(), $storeId);
237+
}
202238
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento\Email\Model\Mail;
7+
8+
use Magento\Framework\App\Config\ScopeConfigInterface;
9+
use Magento\Framework\Exception\MailException;
10+
use Magento\Framework\Mail\TransportInterface;
11+
use Magento\Store\Model\ScopeInterface;
12+
13+
/**
14+
* Plugin over \Magento\Framework\Mail\TransportInterface
15+
*
16+
* It disables email sending depending on the system configuration settings
17+
*/
18+
class TransportInterfacePlugin
19+
{
20+
/**
21+
* @var ScopeConfigInterface
22+
*/
23+
private $scopeConfig;
24+
25+
/**
26+
* @param ScopeConfigInterface $scopeConfig
27+
*/
28+
public function __construct(
29+
ScopeConfigInterface $scopeConfig
30+
) {
31+
$this->scopeConfig = $scopeConfig;
32+
}
33+
34+
/**
35+
* Omit email sending depending on the system configuration setting
36+
*
37+
* @param TransportInterface $subject
38+
* @param \Closure $proceed
39+
* @return void
40+
* @throws MailException
41+
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
42+
*/
43+
public function aroundSendMessage(
44+
TransportInterface $subject,
45+
\Closure $proceed
46+
) {
47+
if (!$this->scopeConfig->isSetFlag('system/smtp/disable', ScopeInterface::SCOPE_STORE)) {
48+
$proceed();
49+
}
50+
}
51+
}

app/code/Magento/Email/Model/Template.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@ class Template extends AbstractTemplate implements \Magento\Framework\Mail\Templ
5757
/**
5858
* Config path to mail sending setting that shows if email communications are disabled
5959
* @deprecated
60-
* @see \Magento\Email\Model\Transport::XML_PATH_SYSTEM_SMTP_DISABLE
6160
*/
6261
const XML_PATH_SYSTEM_SMTP_DISABLE = 'system/smtp/disable';
6362

app/code/Magento/Email/Model/Transport.php

Lines changed: 19 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,10 @@
1313

1414
/**
1515
* Class that responsible for filling some message data before transporting it.
16-
* This class checks whether this email should be sent in the first place, based on System Configurations.
1716
* @see Zend_Mail_Transport_Sendmail is used for transport
1817
*/
1918
class Transport implements TransportInterface
2019
{
21-
/**
22-
* Config path to mail sending setting that shows if email communications are disabled
23-
*/
24-
const XML_PATH_SYSTEM_SMTP_DISABLE = 'system/smtp/disable';
25-
2620
/**
2721
* Configuration path to source of Return-Path and whether it should be set at all
2822
* @see \Magento\Config\Model\Config\Source\Yesnocustom to possible values
@@ -85,29 +79,27 @@ public function __construct(
8579
public function sendMessage()
8680
{
8781
try {
88-
if (!$this->scopeConfig->isSetFlag(self::XML_PATH_SYSTEM_SMTP_DISABLE, ScopeInterface::SCOPE_STORE)) {
89-
/* configuration of whether return path should be set or no. Possible values are:
90-
* 0 - no
91-
* 1 - yes (set value as FROM address)
92-
* 2 - use custom value
93-
* @see Magento\Config\Model\Config\Source\Yesnocustom
94-
*/
95-
$isSetReturnPath = $this->scopeConfig->getValue(
96-
self::XML_PATH_SENDING_SET_RETURN_PATH,
97-
ScopeInterface::SCOPE_STORE
98-
);
99-
$returnPathValue = $this->scopeConfig->getValue(
100-
self::XML_PATH_SENDING_RETURN_PATH_EMAIL,
101-
ScopeInterface::SCOPE_STORE
102-
);
82+
/* configuration of whether return path should be set or no. Possible values are:
83+
* 0 - no
84+
* 1 - yes (set value as FROM address)
85+
* 2 - use custom value
86+
* @see Magento\Config\Model\Config\Source\Yesnocustom
87+
*/
88+
$isSetReturnPath = $this->scopeConfig->getValue(
89+
self::XML_PATH_SENDING_SET_RETURN_PATH,
90+
ScopeInterface::SCOPE_STORE
91+
);
92+
$returnPathValue = $this->scopeConfig->getValue(
93+
self::XML_PATH_SENDING_RETURN_PATH_EMAIL,
94+
ScopeInterface::SCOPE_STORE
95+
);
10396

104-
if ($isSetReturnPath == '1') {
105-
$this->message->setReturnPath($this->message->getFrom());
106-
} elseif ($isSetReturnPath == '2' && $returnPathValue !== null) {
107-
$this->message->setReturnPath($returnPathValue);
108-
}
109-
$this->transport->send($this->message);
97+
if ($isSetReturnPath == '1') {
98+
$this->message->setReturnPath($this->message->getFrom());
99+
} elseif ($isSetReturnPath == '2' && $returnPathValue !== null) {
100+
$this->message->setReturnPath($returnPathValue);
110101
}
102+
$this->transport->send($this->message);
111103
} catch (\Exception $e) {
112104
throw new MailException(__($e->getMessage()), $e);
113105
}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento\Email\Test\Unit\Model\Mail;
7+
8+
use Magento\Email\Model\Mail\TransportInterfacePlugin;
9+
use Magento\Framework\App\Config\ScopeConfigInterface;
10+
use Magento\Framework\Mail\TransportInterface;
11+
use Magento\Store\Model\ScopeInterface;
12+
13+
/**
14+
* Covers \Magento\Email\Model\Transport
15+
*/
16+
class TransportInterfacePluginTest extends \PHPUnit\Framework\TestCase
17+
{
18+
/**
19+
* @var TransportInterface|\PHPUnit_Framework_MockObject_MockObject
20+
*/
21+
private $transportMock;
22+
23+
/**
24+
* @var ScopeConfigInterface|\PHPUnit_Framework_MockObject_MockObject
25+
*/
26+
private $scopeConfigMock;
27+
28+
/**
29+
* @var \Callable|\PHPUnit_Framework_MockObject_MockObject
30+
*/
31+
private $proceedMock;
32+
33+
/**
34+
* @var bool
35+
*/
36+
private $isProceedMockCalled = false;
37+
38+
/**
39+
* @var TransportInterfacePlugin
40+
*/
41+
private $model;
42+
43+
protected function setUp()
44+
{
45+
$this->transportMock = $this->createMock(TransportInterface::class);
46+
$this->scopeConfigMock = $this->getMockForAbstractClass(ScopeConfigInterface::class);
47+
$this->proceedMock = function () {
48+
$this->isProceedMockCalled = true;
49+
};
50+
51+
$this->model = new TransportInterfacePlugin($this->scopeConfigMock);
52+
}
53+
54+
/**
55+
* @dataProvider sendMessageDataProvider
56+
* @param bool $isDisabled
57+
* @param bool $shouldProceedRun
58+
*/
59+
public function testAroundSendMessage(bool $isDisabled, bool $shouldProceedRun)
60+
{
61+
$this->isProceedMockCalled = false;
62+
63+
$this->scopeConfigMock->expects($this->once())
64+
->method('isSetFlag')
65+
->with('system/smtp/disable', ScopeInterface::SCOPE_STORE)
66+
->willReturn($isDisabled);
67+
$this->model->aroundSendMessage($this->transportMock, $this->proceedMock);
68+
$this->assertEquals($shouldProceedRun, $this->isProceedMockCalled);
69+
}
70+
71+
/**
72+
* Data provider for testAroundSendMessage
73+
* @return array
74+
*/
75+
public function sendMessageDataProvider()
76+
{
77+
return [
78+
[false, true],
79+
[true, false],
80+
];
81+
}
82+
}

app/code/Magento/Email/Test/Unit/Model/TransportTest.php

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -54,25 +54,11 @@ protected function setUp()
5454
public function testSendMessageException()
5555
{
5656
$this->scopeConfigMock->expects($this->once())
57-
->method('isSetFlag')
57+
->method('getValue')
5858
->willThrowException(new \Exception('some exception'));
5959
$this->model->sendMessage();
6060
}
6161

62-
/**
63-
* Tests that if sending emails is disabled in System Configuration, send nothing
64-
*/
65-
public function testSendMessageSmtpDisabled()
66-
{
67-
$this->scopeConfigMock->expects($this->once())
68-
->method('isSetFlag')
69-
->with(Transport::XML_PATH_SYSTEM_SMTP_DISABLE, ScopeInterface::SCOPE_STORE)
70-
->willReturn(true);
71-
$this->transportMock->expects($this->never())
72-
->method('send');
73-
$this->model->sendMessage();
74-
}
75-
7662
/**
7763
* Tests that if sending Return-Path was disabled or email was not provided, - this header won't be set
7864
*
@@ -154,11 +140,6 @@ public function testGetMessage()
154140
*/
155141
private function prepareSendingMessage($returnPathSet, $returnPathEmail)
156142
{
157-
$this->scopeConfigMock->expects($this->once())
158-
->method('isSetFlag')
159-
->with(Transport::XML_PATH_SYSTEM_SMTP_DISABLE, ScopeInterface::SCOPE_STORE)
160-
->willReturn(false);
161-
162143
$map = [
163144
[Transport::XML_PATH_SENDING_SET_RETURN_PATH, ScopeInterface::SCOPE_STORE, null, $returnPathSet],
164145
[Transport::XML_PATH_SENDING_RETURN_PATH_EMAIL, ScopeInterface::SCOPE_STORE, null, $returnPathEmail]

0 commit comments

Comments
 (0)