Skip to content

Commit 42673a9

Browse files
committed
Merge remote-tracking branch 'origin/ACP2E-403' into L3_Arrows_PR_20220217
2 parents 59be598 + cdc7702 commit 42673a9

File tree

3 files changed

+234
-44
lines changed

3 files changed

+234
-44
lines changed

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

Lines changed: 46 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -4,80 +4,81 @@
44
* See COPYING.txt for license details.
55
*/
66

7-
/**
8-
* Directory module observer
9-
*
10-
* @author Magento Core Team <core@magentocommerce.com>
11-
*/
12-
137
namespace Magento\Directory\Model;
148

9+
use Magento\Backend\App\Area\FrontNameResolver;
10+
use Magento\Directory\Model\Currency\Import\Factory;
11+
use Magento\Framework\App\Config\ScopeConfigInterface;
12+
use Magento\Framework\Mail\Template\TransportBuilder;
13+
use Magento\Framework\Translate\Inline\StateInterface;
14+
use Magento\Store\Model\ScopeInterface;
15+
use Magento\Store\Model\Store;
16+
use Magento\Store\Model\StoreManagerInterface;
17+
1518
/**
16-
* Class Observer
17-
*
18-
* @package Magento\Directory\Model
19+
* Import currency rates
1920
*/
2021
class Observer
2122
{
22-
const CRON_STRING_PATH = 'crontab/default/jobs/currency_rates_update/schedule/cron_expr';
23+
public const CRON_STRING_PATH = 'crontab/default/jobs/currency_rates_update/schedule/cron_expr';
2324

24-
const IMPORT_ENABLE = 'currency/import/enabled';
25+
public const IMPORT_ENABLE = 'currency/import/enabled';
2526

26-
const IMPORT_SERVICE = 'currency/import/service';
27+
public const IMPORT_SERVICE = 'currency/import/service';
2728

28-
const XML_PATH_ERROR_TEMPLATE = 'currency/import/error_email_template';
29+
public const XML_PATH_ERROR_TEMPLATE = 'currency/import/error_email_template';
2930

30-
const XML_PATH_ERROR_IDENTITY = 'currency/import/error_email_identity';
31+
public const XML_PATH_ERROR_IDENTITY = 'currency/import/error_email_identity';
3132

32-
const XML_PATH_ERROR_RECIPIENT = 'currency/import/error_email';
33+
public const XML_PATH_ERROR_RECIPIENT = 'currency/import/error_email';
3334

3435
/**
35-
* @var \Magento\Directory\Model\Currency\Import\Factory
36+
* @var Factory
3637
*/
3738
protected $_importFactory;
3839

3940
/**
4041
* Core store config
4142
*
42-
* @var \Magento\Framework\App\Config\ScopeConfigInterface
43+
* @var ScopeConfigInterface
4344
*/
4445
protected $_scopeConfig;
4546

4647
/**
47-
* @var \Magento\Framework\Mail\Template\TransportBuilder
48+
* @var TransportBuilder
4849
*/
4950
protected $_transportBuilder;
5051

5152
/**
52-
* @var \Magento\Store\Model\StoreManagerInterface
53+
* @var StoreManagerInterface
5354
*/
5455
protected $_storeManager;
5556

5657
/**
57-
* @var \Magento\Directory\Model\CurrencyFactory
58+
* @var CurrencyFactory
5859
*/
5960
protected $_currencyFactory;
6061

6162
/**
62-
* @var \Magento\Framework\Translate\Inline\StateInterface
63+
* @var StateInterface
6364
*/
6465
protected $inlineTranslation;
6566

6667
/**
67-
* @param \Magento\Directory\Model\Currency\Import\Factory $importFactory
68-
* @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
69-
* @param \Magento\Framework\Mail\Template\TransportBuilder $transportBuilder
70-
* @param \Magento\Store\Model\StoreManagerInterface $storeManager
71-
* @param \Magento\Directory\Model\CurrencyFactory $currencyFactory
72-
* @param \Magento\Framework\Translate\Inline\StateInterface $inlineTranslation
68+
* @param Factory $importFactory
69+
* @param ScopeConfigInterface $scopeConfig
70+
* @param TransportBuilder $transportBuilder
71+
* @param StoreManagerInterface $storeManager
72+
* @param CurrencyFactory $currencyFactory
73+
* @param StateInterface $inlineTranslation
7374
*/
7475
public function __construct(
75-
\Magento\Directory\Model\Currency\Import\Factory $importFactory,
76-
\Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
77-
\Magento\Framework\Mail\Template\TransportBuilder $transportBuilder,
78-
\Magento\Store\Model\StoreManagerInterface $storeManager,
79-
\Magento\Directory\Model\CurrencyFactory $currencyFactory,
80-
\Magento\Framework\Translate\Inline\StateInterface $inlineTranslation
76+
Factory $importFactory,
77+
ScopeConfigInterface $scopeConfig,
78+
TransportBuilder $transportBuilder,
79+
StoreManagerInterface $storeManager,
80+
CurrencyFactory $currencyFactory,
81+
StateInterface $inlineTranslation
8182
) {
8283
$this->_importFactory = $importFactory;
8384
$this->_scopeConfig = $scopeConfig;
@@ -94,16 +95,17 @@ public function __construct(
9495
* @return void
9596
* @throws \Exception
9697
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
98+
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
9799
*/
98100
public function scheduledUpdateCurrencyRates($schedule)
99101
{
100102
$importWarnings = [];
101103
if (!$this->_scopeConfig->getValue(
102104
self::IMPORT_ENABLE,
103-
\Magento\Store\Model\ScopeInterface::SCOPE_STORE
105+
ScopeInterface::SCOPE_STORE
104106
) || !$this->_scopeConfig->getValue(
105107
self::CRON_STRING_PATH,
106-
\Magento\Store\Model\ScopeInterface::SCOPE_STORE
108+
ScopeInterface::SCOPE_STORE
107109
)
108110
) {
109111
return;
@@ -113,7 +115,7 @@ public function scheduledUpdateCurrencyRates($schedule)
113115
$rates = [];
114116
$service = $this->_scopeConfig->getValue(
115117
self::IMPORT_SERVICE,
116-
\Magento\Store\Model\ScopeInterface::SCOPE_STORE
118+
ScopeInterface::SCOPE_STORE
117119
);
118120
if ($service) {
119121
try {
@@ -137,32 +139,33 @@ public function scheduledUpdateCurrencyRates($schedule)
137139

138140
$errorRecipient = $this->_scopeConfig->getValue(
139141
self::XML_PATH_ERROR_RECIPIENT,
140-
\Magento\Store\Model\ScopeInterface::SCOPE_STORE
142+
ScopeInterface::SCOPE_STORE
141143
);
144+
$errorRecipients = !empty($errorRecipient) ? explode(',', $errorRecipient) : [];
142145
if (count($importWarnings) == 0) {
143146
$this->_currencyFactory->create()->saveRates($rates);
144-
} elseif ($errorRecipient) {
147+
} elseif (count($errorRecipients) > 0) {
145148
//if $errorRecipient is not set, there is no sense send email to nobody
146149
$this->inlineTranslation->suspend();
147150

148151
$this->_transportBuilder->setTemplateIdentifier(
149152
$this->_scopeConfig->getValue(
150153
self::XML_PATH_ERROR_TEMPLATE,
151-
\Magento\Store\Model\ScopeInterface::SCOPE_STORE
154+
ScopeInterface::SCOPE_STORE
152155
)
153156
)->setTemplateOptions(
154157
[
155-
'area' => \Magento\Backend\App\Area\FrontNameResolver::AREA_CODE,
156-
'store' => \Magento\Store\Model\Store::DEFAULT_STORE_ID,
158+
'area' => FrontNameResolver::AREA_CODE,
159+
'store' => Store::DEFAULT_STORE_ID,
157160
]
158161
)->setTemplateVars(
159162
['warnings' => join("\n", $importWarnings)]
160163
)->setFrom(
161164
$this->_scopeConfig->getValue(
162165
self::XML_PATH_ERROR_IDENTITY,
163-
\Magento\Store\Model\ScopeInterface::SCOPE_STORE
166+
ScopeInterface::SCOPE_STORE
164167
)
165-
)->addTo($errorRecipient);
168+
)->addTo($errorRecipients);
166169
$transport = $this->_transportBuilder->getTransport();
167170
$transport->sendMessage();
168171

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
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+
$this->scopeConfigMock->expects($this->any())
110+
->method('getValue')
111+
->withConsecutive(
112+
[
113+
Observer::IMPORT_ENABLE,
114+
ScopeInterface::SCOPE_STORE
115+
],
116+
[
117+
Observer::CRON_STRING_PATH,
118+
ScopeInterface::SCOPE_STORE
119+
],
120+
[
121+
Observer::IMPORT_SERVICE,
122+
ScopeInterface::SCOPE_STORE
123+
],
124+
[
125+
Observer::XML_PATH_ERROR_RECIPIENT,
126+
ScopeInterface::SCOPE_STORE
127+
],
128+
[
129+
Observer::XML_PATH_ERROR_TEMPLATE,
130+
ScopeInterface::SCOPE_STORE
131+
],
132+
[
133+
Observer::XML_PATH_ERROR_IDENTITY,
134+
ScopeInterface::SCOPE_STORE
135+
]
136+
)->willReturnOnConsecutiveCalls(
137+
1,
138+
'* * * * *',
139+
'fixerio',
140+
'test1@email.com,test2@email.com',
141+
self::STUB_ERROR_TEMPLATE,
142+
self::STUB_SENDER
143+
);
144+
$import = $this->getMockForAbstractClass(ImportInterface::class);
145+
$import->expects($this->once())->method('fetchRates')
146+
->willReturn([]);
147+
$import->expects($this->once())->method('getMessages')
148+
->willReturn(['error1', 'error2']);
149+
$this->importFactoryMock->expects($this->once())->method('create')
150+
->with('fixerio')
151+
->willReturn($import);
152+
$this->transportBuilderMock->expects($this->once())
153+
->method('setTemplateIdentifier')
154+
->with(self::STUB_ERROR_TEMPLATE)
155+
->willReturnSelf();
156+
$this->transportBuilderMock->expects($this->once())
157+
->method('setTemplateOptions')
158+
->with(['area' => FrontNameResolver::AREA_CODE, 'store' => Store::DEFAULT_STORE_ID])
159+
->willReturnSelf();
160+
$this->transportBuilderMock->expects($this->once())
161+
->method('setTemplateVars')
162+
->with(['warnings' => join("\n", $importWarnings)])
163+
->willReturnSelf();
164+
$this->transportBuilderMock->expects($this->once())
165+
->method('setFrom')
166+
->with(self::STUB_SENDER)
167+
->willReturnSelf();
168+
169+
$this->transportBuilderMock->expects($this->once())
170+
->method('addTo')
171+
->with(['test1@email.com', 'test2@email.com'])
172+
->willReturnSelf();
173+
$transport = $this->getMockForAbstractClass(TransportInterface::class);
174+
175+
$this->transportBuilderMock->expects($this->once())
176+
->method('getTransport')
177+
->willReturn($transport);
178+
179+
$transport->expects($this->once())
180+
->method('sendMessage')
181+
->willReturnSelf();
182+
$this->inlineTranslationMock->expects($this->once())->method('suspend')->willReturnSelf();
183+
$this->inlineTranslationMock->expects($this->once())->method('resume')->willReturnSelf();
184+
185+
$this->model->scheduledUpdateCurrencyRates([]);
186+
}
187+
}

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)