Skip to content

Commit cf428c8

Browse files
ACP2E-403 Fixed Unable to save multiple email addresses
1 parent 1d1614b commit cf428c8

File tree

3 files changed

+193
-3
lines changed

3 files changed

+193
-3
lines changed

app/code/Magento/Directory/Model/Observer.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,9 +139,10 @@ public function scheduledUpdateCurrencyRates($schedule)
139139
self::XML_PATH_ERROR_RECIPIENT,
140140
\Magento\Store\Model\ScopeInterface::SCOPE_STORE
141141
);
142+
$errorRecipients = !empty($errorRecipient) ? explode(',', $errorRecipient) : [];
142143
if (count($importWarnings) == 0) {
143144
$this->_currencyFactory->create()->saveRates($rates);
144-
} elseif ($errorRecipient) {
145+
} elseif (count($errorRecipients) > 0) {
145146
//if $errorRecipient is not set, there is no sense send email to nobody
146147
$this->inlineTranslation->suspend();
147148

@@ -162,7 +163,7 @@ public function scheduledUpdateCurrencyRates($schedule)
162163
self::XML_PATH_ERROR_IDENTITY,
163164
\Magento\Store\Model\ScopeInterface::SCOPE_STORE
164165
)
165-
)->addTo($errorRecipient);
166+
)->addTo($errorRecipients);
166167
$transport = $this->_transportBuilder->getTransport();
167168
$transport->sendMessage();
168169

Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
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\Directory\Test\Unit\Model;
9+
10+
use Magento\Backend\App\Area\FrontNameResolver;
11+
use Magento\Directory\Model\Currency\Import\Factory;
12+
use Magento\Directory\Model\CurrencyFactory;
13+
use Magento\Framework\App\Config\ScopeConfigInterface;
14+
use Magento\Framework\Mail\Template\TransportBuilder;
15+
use Magento\Framework\Mail\TransportInterface;
16+
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
17+
use Magento\Framework\Translate\Inline\StateInterface;
18+
use Magento\Store\Model\ScopeInterface;
19+
use Magento\Store\Model\Store;
20+
use Magento\Store\Model\StoreManagerInterface;
21+
use Magento\Directory\Model\Observer;
22+
use Magento\Directory\Model\Currency\Import\ImportInterface;
23+
use PHPUnit\Framework\MockObject\MockObject;
24+
use PHPUnit\Framework\TestCase;
25+
26+
/**
27+
* Unit test for \Magento\Directory\Model\Observer
28+
*
29+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
30+
*/
31+
class ObserverTest extends TestCase
32+
{
33+
/**
34+
* @var string
35+
*/
36+
private const STUB_SENDER = 'Sender';
37+
38+
/**
39+
* @var string
40+
*/
41+
private const STUB_ERROR_TEMPLATE = 'currency_import_error_email_template';
42+
43+
/**
44+
* @var Factory|MockObject
45+
*/
46+
private $importFactoryMock;
47+
48+
/**
49+
* @var ScopeConfigInterface|MockObject
50+
*/
51+
private $scopeConfigMock;
52+
53+
/**
54+
* @var StoreManagerInterface|MockObject
55+
*/
56+
private $storeManagerMock;
57+
58+
/**
59+
* @var TransportBuilder|MockObject
60+
*/
61+
private $transportBuilderMock;
62+
63+
/**
64+
* @var CurrencyFactory|MockObject
65+
*/
66+
private $currencyFactoryMock;
67+
68+
/**
69+
* @var StateInterface|MockObject
70+
*/
71+
private $inlineTranslationMock;
72+
73+
/**
74+
* @var Observer
75+
*/
76+
private $model;
77+
78+
/**
79+
* @inheritdoc
80+
*/
81+
protected function setUp(): void
82+
{
83+
$this->importFactoryMock = $this->createMock(Factory::class);
84+
$this->scopeConfigMock = $this->getMockForAbstractClass(ScopeConfigInterface::class);
85+
$this->transportBuilderMock = $this->createMock(TransportBuilder::class);
86+
$this->storeManagerMock = $this->getMockForAbstractClass(StoreManagerInterface::class);
87+
$this->currencyFactoryMock = $this->createMock(CurrencyFactory::class);
88+
$this->inlineTranslationMock = $this->getMockForAbstractClass(StateInterface::class);
89+
$objectManager = new ObjectManager($this);
90+
$this->model = $objectManager->getObject(
91+
Observer::class,
92+
[
93+
'importFactory' => $this->importFactoryMock,
94+
'scopeConfig' => $this->scopeConfigMock,
95+
'transportBuilder' => $this->transportBuilderMock,
96+
'storeManager' => $this->storeManagerMock,
97+
'currencyFactory' => $this->currencyFactoryMock,
98+
'inlineTranslation' => $this->inlineTranslationMock
99+
]
100+
);
101+
}
102+
103+
/**
104+
* @return void
105+
*/
106+
public function testScheduledUpdateCurrencyRates(): void
107+
{
108+
$importWarnings = ['WARNING: error1', 'WARNING: error2'];
109+
$senderValues = ['name' => self::STUB_SENDER, 'email' => self::STUB_SENDER];
110+
$this->scopeConfigMock->expects($this->any())
111+
->method('getValue')
112+
->withConsecutive(
113+
[
114+
Observer::IMPORT_ENABLE,
115+
ScopeInterface::SCOPE_STORE
116+
],
117+
[
118+
Observer::CRON_STRING_PATH,
119+
ScopeInterface::SCOPE_STORE
120+
],
121+
[
122+
Observer::IMPORT_SERVICE,
123+
ScopeInterface::SCOPE_STORE
124+
],
125+
[
126+
Observer::XML_PATH_ERROR_RECIPIENT,
127+
ScopeInterface::SCOPE_STORE
128+
],
129+
[
130+
Observer::XML_PATH_ERROR_TEMPLATE,
131+
ScopeInterface::SCOPE_STORE
132+
],
133+
[
134+
Observer::XML_PATH_ERROR_IDENTITY,
135+
ScopeInterface::SCOPE_STORE
136+
]
137+
)->willReturnOnConsecutiveCalls(
138+
1,
139+
'* * * * *',
140+
'fixerio',
141+
'test1@email.com,test2@email.com',
142+
self::STUB_ERROR_TEMPLATE,
143+
self::STUB_SENDER
144+
145+
);
146+
$import = $this->getMockForAbstractClass(ImportInterface::class);
147+
$import->expects($this->once())->method('fetchRates')
148+
->willReturn([]);
149+
$import->expects($this->once())->method('getMessages')
150+
->willReturn(['error1', 'error2']);
151+
$this->importFactoryMock->expects($this->once())->method('create')
152+
->with('fixerio')
153+
->willReturn($import);
154+
$this->transportBuilderMock->expects($this->once())
155+
->method('setTemplateIdentifier')
156+
->with(self::STUB_ERROR_TEMPLATE)
157+
->willReturnSelf();
158+
$this->transportBuilderMock->expects($this->once())
159+
->method('setTemplateOptions')
160+
->with(['area' => FrontNameResolver::AREA_CODE, 'store' => Store::DEFAULT_STORE_ID])
161+
->willReturnSelf();
162+
$this->transportBuilderMock->expects($this->once())
163+
->method('setTemplateVars')
164+
->with(['warnings' => join("\n", $importWarnings)])
165+
->willReturnSelf();
166+
$this->transportBuilderMock->expects($this->once())
167+
->method('setFrom')
168+
->with(self::STUB_SENDER)
169+
->willReturnSelf();
170+
171+
$this->transportBuilderMock->expects($this->once())
172+
->method('addTo')
173+
->with(['test1@email.com', 'test2@email.com'])
174+
->willReturnSelf();
175+
$transport = $this->getMockForAbstractClass(TransportInterface::class);
176+
177+
$this->transportBuilderMock->expects($this->once())
178+
->method('getTransport')
179+
->willReturn($transport);
180+
181+
$transport->expects($this->once())
182+
->method('sendMessage')
183+
->willReturnSelf();
184+
$this->inlineTranslationMock->expects($this->once())->method('suspend')->willReturnSelf();
185+
$this->inlineTranslationMock->expects($this->once())->method('resume')->willReturnSelf();
186+
187+
$this->model->scheduledUpdateCurrencyRates([]);
188+
}
189+
}

app/code/Magento/Directory/etc/adminhtml/system.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@
6666
</field>
6767
<field id="error_email" translate="label" type="text" sortOrder="5" showInDefault="1" showInWebsite="1" showInStore="1">
6868
<label>Error Email Recipient</label>
69-
<validate>validate-email</validate>
69+
<validate>validate-emails</validate>
7070
<depends>
7171
<field id="enabled">1</field>
7272
</depends>

0 commit comments

Comments
 (0)