Skip to content

Commit f63e109

Browse files
committed
ACP2E-3002: [CLOUD] Cannot Disable Send Emails from Admin UI as Dev Docs shows
1 parent 995a05c commit f63e109

File tree

5 files changed

+192
-8
lines changed

5 files changed

+192
-8
lines changed
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?php
2+
/************************************************************************
3+
*
4+
* Copyright 2024 Adobe
5+
* All Rights Reserved.
6+
*
7+
* NOTICE: All information contained herein is, and remains
8+
* the property of Adobe and its suppliers, if any. The intellectual
9+
* and technical concepts contained herein are proprietary to Adobe
10+
* and its suppliers and are protected by all applicable intellectual
11+
* property laws, including trade secret and copyright laws.
12+
* Dissemination of this information or reproduction of this material
13+
* is strictly forbidden unless prior written permission is obtained
14+
* from Adobe.
15+
* ************************************************************************
16+
*/
17+
declare(strict_types=1);
18+
19+
namespace Magento\Sales\Plugin;
20+
21+
use Magento\Framework\App\Config\ScopeConfigInterface;
22+
use Magento\Sales\Model\Order\Email\Container\IdentityInterface;
23+
use Magento\Store\Model\ScopeInterface;
24+
25+
class ApplyStoreEmailConfigToSalesEmail
26+
{
27+
private const XML_PATH_SYSTEM_SMTP_DISABLE = 'system/smtp/disable';
28+
29+
/**
30+
* @param ScopeConfigInterface $scopeConfig
31+
*/
32+
public function __construct(
33+
private readonly ScopeConfigInterface $scopeConfig
34+
) {
35+
}
36+
37+
/**
38+
* Disable email sending depending on the system configuration setting
39+
*
40+
* @param IdentityInterface $subject
41+
* @param bool $result
42+
* @return bool
43+
*/
44+
public function afterIsEnabled(
45+
IdentityInterface $subject,
46+
$result
47+
) {
48+
return $result && !$this->scopeConfig->isSetFlag(
49+
self::XML_PATH_SYSTEM_SMTP_DISABLE,
50+
ScopeInterface::SCOPE_STORE,
51+
$subject->getStore()->getStoreId()
52+
);
53+
}
54+
}

app/code/Magento/Sales/etc/di.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1038,4 +1038,8 @@
10381038
</argument>
10391039
</arguments>
10401040
</type>
1041+
<type name="Magento\Sales\Model\Order\Email\Container\IdentityInterface">
1042+
<plugin name="applyStoreEmailConfigToSalesEmail"
1043+
type="Magento\Sales\Plugin\ApplyStoreEmailConfigToSalesEmail"/>
1044+
</type>
10411045
</config>

dev/tests/integration/framework/Magento/TestFramework/Mail/Template/TransportBuilderMock.php

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
namespace Magento\TestFramework\Mail\Template;
88

99
/**
10-
* Class TransportBuilderMock
10+
* Mock of mail transport builder
1111
*/
1212
class TransportBuilderMock extends \Magento\Framework\Mail\Template\TransportBuilder
1313
{
@@ -16,6 +16,11 @@ class TransportBuilderMock extends \Magento\Framework\Mail\Template\TransportBui
1616
*/
1717
protected $_sentMessage;
1818

19+
/**
20+
* @var callable
21+
*/
22+
private $onMessageSentCallback;
23+
1924
/**
2025
* Reset object state
2126
*
@@ -24,7 +29,7 @@ class TransportBuilderMock extends \Magento\Framework\Mail\Template\TransportBui
2429
protected function reset()
2530
{
2631
$this->_sentMessage = $this->message;
27-
parent::reset();
32+
return parent::reset();
2833
}
2934

3035
/**
@@ -47,6 +52,31 @@ public function getTransport()
4752
{
4853
$this->prepareMessage();
4954
$this->reset();
50-
return new \Magento\TestFramework\Mail\TransportInterfaceMock($this->message);
55+
return $this->objectManager->create(
56+
\Magento\TestFramework\Mail\TransportInterfaceMock::class,
57+
[
58+
'message' => $this->message,
59+
'onMessageSentCallback' => $this->onMessageSentCallback
60+
]
61+
);
62+
}
63+
64+
/**
65+
* Set callback to be called when message is sent.
66+
*
67+
* @param callable $callback
68+
*/
69+
public function setOnMessageSentCallback(callable $callback): void
70+
{
71+
$this->onMessageSentCallback = $callback;
72+
}
73+
74+
/**
75+
* Clean previous test data.
76+
*/
77+
public function clean(): void
78+
{
79+
$this->_sentMessage = null;
80+
$this->onMessageSentCallback = null;
5181
}
5282
}

dev/tests/integration/framework/Magento/TestFramework/Mail/TransportInterfaceMock.php

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
use Magento\Framework\Mail\EmailMessageInterface;
1010

1111
/**
12-
* Class TransportInterfaceMock
12+
* Mock of mail transport interface
1313
*/
1414
class TransportInterfaceMock implements \Magento\Framework\Mail\TransportInterface
1515
{
@@ -18,14 +18,23 @@ class TransportInterfaceMock implements \Magento\Framework\Mail\TransportInterfa
1818
*/
1919
private $message;
2020

21+
/**
22+
* @var null|callable
23+
*/
24+
private $onMessageSentCallback;
25+
2126
/**
2227
* TransportInterfaceMock constructor.
2328
*
2429
* @param null|EmailMessageInterface $message
30+
* @param null|callable $onMessageSentCallback
2531
*/
26-
public function __construct($message = null)
27-
{
32+
public function __construct(
33+
$message = null,
34+
?callable $onMessageSentCallback = null
35+
) {
2836
$this->message = $message;
37+
$this->onMessageSentCallback = $onMessageSentCallback;
2938
}
3039

3140
/**
@@ -35,8 +44,7 @@ public function __construct($message = null)
3544
*/
3645
public function sendMessage()
3746
{
38-
//phpcs:ignore Squiz.PHP.NonExecutableCode.ReturnNotRequired
39-
return;
47+
$this->onMessageSentCallback && call_user_func($this->onMessageSentCallback, $this->message);
4048
}
4149

4250
/**

dev/tests/integration/testsuite/Magento/Sales/Model/OrderTest.php

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,12 @@
1414
use Magento\Checkout\Test\Fixture\SetGuestEmail as SetGuestEmailFixture;
1515
use Magento\Checkout\Test\Fixture\SetPaymentMethod as SetPaymentMethodFixture;
1616
use Magento\Checkout\Test\Fixture\SetShippingAddress as SetShippingAddressFixture;
17+
use Magento\Framework\App\Config\MutableScopeConfigInterface;
1718
use Magento\Quote\Test\Fixture\AddProductToCart as AddProductToCartFixture;
1819
use Magento\Quote\Test\Fixture\GuestCart as GuestCartFixture;
20+
use Magento\Sales\Model\Order\Email\Container\OrderIdentity;
21+
use Magento\Sales\Model\Order\Email\Sender\OrderSender;
22+
use Magento\Sales\Model\ResourceModel\Order\CollectionFactory;
1923
use Magento\Sales\Test\Fixture\Creditmemo as CreditmemoFixture;
2024
use Magento\Sales\Test\Fixture\Invoice as InvoiceFixture;
2125
use Magento\SalesRule\Model\Rule;
@@ -25,21 +29,65 @@
2529
use Magento\TestFramework\Fixture\DataFixtureStorage;
2630
use Magento\TestFramework\Fixture\DataFixtureStorageManager;
2731
use Magento\TestFramework\Helper\Bootstrap;
32+
use Magento\TestFramework\Mail\Template\TransportBuilderMock;
2833
use PHPUnit\Framework\TestCase;
2934

35+
/**
36+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
37+
*/
3038
class OrderTest extends TestCase
3139
{
3240
/**
3341
* @var DataFixtureStorage
3442
*/
3543
private $fixtures;
3644

45+
/**
46+
* @var TransportBuilderMock
47+
*/
48+
private $transportBuilderMock;
49+
50+
/**
51+
* @var MutableScopeConfigInterface
52+
*/
53+
private $mutableScopeConfig;
54+
55+
/**
56+
* @var CollectionFactory
57+
*/
58+
private $collectionFactory;
59+
60+
/**
61+
* @var EmailSenderHandler
62+
*/
63+
private $emailSenderHandler;
64+
3765
/**
3866
* Set up
3967
*/
4068
protected function setUp(): void
4169
{
4270
$this->fixtures = Bootstrap::getObjectManager()->get(DataFixtureStorageManager::class)->getStorage();
71+
$objectManager = Bootstrap::getObjectManager();
72+
$this->collectionFactory = $objectManager->get(CollectionFactory::class);
73+
$this->transportBuilderMock = $objectManager->get(TransportBuilderMock::class);
74+
$this->mutableScopeConfig = $objectManager->get(MutableScopeConfigInterface::class);
75+
$this->emailSenderHandler = Bootstrap::getObjectManager()->create(
76+
EmailSenderHandler::class,
77+
[
78+
'emailSender' => $objectManager->get(OrderSender::class),
79+
'entityResource' => $objectManager->get(\Magento\Sales\Model\ResourceModel\Order::class),
80+
'entityCollection' => $this->collectionFactory->create(),
81+
'identityContainer' => $objectManager->create(OrderIdentity::class),
82+
]
83+
);
84+
$this->transportBuilderMock->clean();
85+
}
86+
87+
protected function tearDown(): void
88+
{
89+
$this->transportBuilderMock->clean();
90+
parent::tearDown();
4391
}
4492

4593
/**
@@ -90,4 +138,44 @@ public function testMultipleCreditmemosForZeroTotalOrder()
90138
'Should be possible to create second credit memo for zero total order if not all items are refunded yet'
91139
);
92140
}
141+
142+
#[
143+
Config('system/smtp/disable', '1', 'store', 'default'),
144+
Config('sales_email/general/async_sending', '1'),
145+
DataFixture(ProductFixture::class, as: 'product'),
146+
DataFixture(GuestCartFixture::class, as: 'cart'),
147+
DataFixture(
148+
AddProductToCartFixture::class,
149+
['cart_id' => '$cart.id$', 'product_id' => '$product.id$']
150+
),
151+
DataFixture(SetBillingAddressFixture::class, ['cart_id' => '$cart.id$']),
152+
DataFixture(SetShippingAddressFixture::class, ['cart_id' => '$cart.id$']),
153+
DataFixture(SetGuestEmailFixture::class, ['cart_id' => '$cart.id$']),
154+
DataFixture(SetDeliveryMethodFixture::class, ['cart_id' => '$cart.id$']),
155+
DataFixture(SetPaymentMethodFixture::class, ['cart_id' => '$cart.id$']),
156+
DataFixture(PlaceOrderFixture::class, ['cart_id' => '$cart.id$'], 'order')
157+
]
158+
public function testAsyncEmailForOrderCreatedWhenEmailSendingWasDisabled(): void
159+
{
160+
$isEmailSent = false;
161+
$this->transportBuilderMock->setOnMessageSentCallback(
162+
function () use (&$isEmailSent) {
163+
$isEmailSent = true;
164+
}
165+
);
166+
$order = $this->fixtures->get('order');
167+
$this->assertEquals(0, $order->getSendEmail());
168+
$this->assertNull($order->getEmailSent());
169+
$this->mutableScopeConfig->setValue('system/smtp/disable', 0, 'store', 'default');
170+
$this->emailSenderHandler->sendEmails();
171+
$this->assertFalse(
172+
$isEmailSent,
173+
'Email is not expected to be sent'
174+
);
175+
$collection = $this->collectionFactory->create();
176+
$collection->addFieldToFilter('entity_id', $order->getId());
177+
$order = $collection->getFirstItem();
178+
$this->assertEquals(0, $order->getSendEmail());
179+
$this->assertNull($order->getEmailSent());
180+
}
93181
}

0 commit comments

Comments
 (0)