Skip to content

Commit f83266d

Browse files
committed
Merge remote-tracking branch 'l3/ACP2E-2595' into Tier4-PR-Delivery-11-18-23
2 parents c6f24d4 + 5dcb5c1 commit f83266d

File tree

2 files changed

+291
-9
lines changed

2 files changed

+291
-9
lines changed

app/code/Magento/Customer/Controller/Account/EditPost.php

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use Magento\Customer\Model\AuthenticationInterface;
1717
use Magento\Customer\Model\Customer\Mapper;
1818
use Magento\Customer\Model\EmailNotificationInterface;
19+
use Magento\Customer\Model\Metadata\Form\File;
1920
use Magento\Framework\App\CsrfAwareActionInterface;
2021
use Magento\Framework\App\ObjectManager;
2122
use Magento\Framework\App\Request\InvalidRequestException;
@@ -136,6 +137,7 @@ class EditPost extends AbstractAccount implements CsrfAwareActionInterface, Http
136137
* @param SessionCleanerInterface|null $sessionCleaner
137138
* @param AccountConfirmation|null $accountConfirmation
138139
* @param Url|null $customerUrl
140+
* @param Mapper|null $customerMapper
139141
*/
140142
public function __construct(
141143
Context $context,
@@ -149,7 +151,8 @@ public function __construct(
149151
?Filesystem $filesystem = null,
150152
?SessionCleanerInterface $sessionCleaner = null,
151153
?AccountConfirmation $accountConfirmation = null,
152-
?Url $customerUrl = null
154+
?Url $customerUrl = null,
155+
?Mapper $customerMapper = null
153156
) {
154157
parent::__construct($context);
155158
$this->session = $customerSession;
@@ -164,6 +167,7 @@ public function __construct(
164167
$this->accountConfirmation = $accountConfirmation ?: ObjectManager::getInstance()
165168
->get(AccountConfirmation::class);
166169
$this->customerUrl = $customerUrl ?: ObjectManager::getInstance()->get(Url::class);
170+
$this->customerMapper = $customerMapper ?: ObjectManager::getInstance()->get(Mapper::class);
167171
}
168172

169173
/**
@@ -233,9 +237,15 @@ public function execute()
233237
$customer = $this->getCustomerDataObject($this->session->getCustomerId());
234238
$customerCandidate = $this->populateNewCustomerDataObject($this->_request, $customer);
235239

236-
$attributeToDelete = $this->_request->getParam('delete_attribute_value');
237-
if ($attributeToDelete !== null) {
238-
$this->deleteCustomerFileAttribute($customerCandidate, $attributeToDelete);
240+
$attributeToDelete = (string)$this->_request->getParam('delete_attribute_value');
241+
if ($attributeToDelete !== "") {
242+
$attributesToDelete = $this->prepareAttributesToDelete($attributeToDelete);
243+
foreach ($attributesToDelete as $attribute) {
244+
$uploadedValue = $this->_request->getParam($attribute . File::UPLOADED_FILE_SUFFIX);
245+
if ((string)$uploadedValue === "") {
246+
$this->deleteCustomerFileAttribute($customerCandidate, $attribute);
247+
}
248+
}
239249
}
240250

241251
try {
@@ -300,6 +310,26 @@ public function execute()
300310
return $resultRedirect;
301311
}
302312

313+
/**
314+
* Convert comma-separated list of attributes to delete into array
315+
*
316+
* @param string $attribute
317+
* @return array
318+
*/
319+
private function prepareAttributesToDelete(string $attribute) : array
320+
{
321+
$result = [];
322+
if ($attribute !== "") {
323+
if (str_contains($attribute, ',')) {
324+
$result = explode(',', $attribute);
325+
} else {
326+
$result[] = $attribute;
327+
}
328+
$result = array_unique($result);
329+
}
330+
return $result;
331+
}
332+
303333
/**
304334
* Adds a complex success message if email confirmation is required
305335
*
@@ -468,11 +498,7 @@ private function deleteCustomerFileAttribute(
468498
string $attributeToDelete
469499
) : void {
470500
if ($attributeToDelete !== '') {
471-
if (strpos($attributeToDelete, ',') !== false) {
472-
$attributes = explode(',', $attributeToDelete);
473-
} else {
474-
$attributes[] = $attributeToDelete;
475-
}
501+
$attributes = $this->prepareAttributesToDelete($attributeToDelete);
476502
foreach ($attributes as $attr) {
477503
$attributeValue = $customerCandidateDataObject->getCustomAttribute($attr);
478504
if ($attributeValue!== null) {
Lines changed: 256 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,256 @@
1+
<?php
2+
/**
3+
* Copyright 2023 Adobe
4+
* All Rights Reserved.
5+
*
6+
* NOTICE: All information contained herein is, and remains
7+
* the property of Adobe and its suppliers, if any. The intellectual
8+
* and technical concepts contained herein are proprietary to Adobe
9+
* and its suppliers and are protected by all applicable intellectual
10+
* property laws, including trade secret and copyright laws.
11+
* Dissemination of this information or reproduction of this material
12+
* is strictly forbidden unless prior written permission is obtained
13+
* from Adobe.
14+
*/
15+
declare(strict_types=1);
16+
17+
namespace Magento\Customer\Test\Unit\Controller\Account;
18+
19+
use Magento\Customer\Api\SessionCleanerInterface;
20+
use Magento\Customer\Api\AccountManagementInterface;
21+
use Magento\Customer\Api\CustomerRepositoryInterface;
22+
use Magento\Customer\Api\Data\CustomerInterface;
23+
use Magento\Customer\Controller\Account\EditPost;
24+
use Magento\Customer\Model\Metadata\Form\File;
25+
use Magento\Customer\Model\Session;
26+
use Magento\Customer\Model\AddressRegistry;
27+
use Magento\Customer\Model\CustomerExtractor;
28+
use Magento\Customer\Model\AccountConfirmation;
29+
use Magento\Customer\Model\Url;
30+
use Magento\Customer\Model\Customer\Mapper;
31+
use Magento\Framework\Escaper;
32+
use Magento\Framework\Exception\SessionException;
33+
use Magento\Framework\Filesystem;
34+
use Magento\Framework\App\RequestInterface;
35+
use Magento\Framework\App\Action\Context;
36+
use Magento\Framework\Controller\Result\RedirectFactory;
37+
use Magento\Framework\Controller\Result\Redirect;
38+
use Magento\Framework\Data\Form\FormKey\Validator;
39+
use Magento\Framework\Event\ManagerInterface as EventManagerInterface;
40+
use Magento\Framework\Message\ManagerInterface as MessageManagerInterface;
41+
use PHPUnit\Framework\MockObject\MockObject;
42+
use PHPUnit\Framework\TestCase;
43+
44+
/**
45+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
46+
*/
47+
class EditPostTest extends TestCase
48+
{
49+
/**
50+
* @var EditPost
51+
*/
52+
private $editPost;
53+
54+
/**
55+
* @var Context|MockObject
56+
*/
57+
private $context;
58+
59+
/**
60+
* @var Session|MockObject
61+
*/
62+
private $customerSession;
63+
64+
/**
65+
* @var AccountManagementInterface|MockObject
66+
*/
67+
private $accountManagement;
68+
69+
/**
70+
* @var CustomerRepositoryInterface|MockObject
71+
*/
72+
private $customerRepository;
73+
74+
/**
75+
* @var Validator|MockObject
76+
*/
77+
private $formKeyValidator;
78+
79+
/**
80+
* @var CustomerExtractor|MockObject
81+
*/
82+
private $customerExtractor;
83+
84+
/**
85+
* @var Escaper|MockObject
86+
*/
87+
private $escaper;
88+
89+
/**
90+
* @var AddressRegistry|MockObject
91+
*/
92+
private $addressRegistry;
93+
94+
/**
95+
* @var Filesystem|MockObject
96+
*/
97+
private $filesystem;
98+
99+
/**
100+
* @var SessionCleanerInterface|MockObject
101+
*/
102+
private $sessionCleaner;
103+
104+
/**
105+
* @var AccountConfirmation|MockObject
106+
*/
107+
private $accountConfirmation;
108+
109+
/**
110+
* @var Url|MockObject
111+
*/
112+
private $customerUrl;
113+
114+
/**
115+
* @var RequestInterface|MockObject
116+
*/
117+
private $request;
118+
119+
/**
120+
* @var Mapper|MockObject
121+
*/
122+
private $customerMapper;
123+
124+
protected function setUp(): void
125+
{
126+
$this->context = $this->getMockBuilder(Context::class)
127+
->disableOriginalConstructor()
128+
->getMock();
129+
$this->customerSession = $this->getMockBuilder(Session::class)
130+
->disableOriginalConstructor()
131+
->getMock();
132+
$this->accountManagement = $this->getMockBuilder(AccountManagementInterface::class)
133+
->getMockForAbstractClass();
134+
$this->customerRepository = $this->getMockBuilder(CustomerRepositoryInterface::class)
135+
->getMockForAbstractClass();
136+
$this->formKeyValidator = $this->getMockBuilder(Validator::class)
137+
->disableOriginalConstructor()
138+
->getMock();
139+
$this->customerExtractor = $this->getMockBuilder(CustomerExtractor::class)
140+
->disableOriginalConstructor()
141+
->getMock();
142+
$this->escaper = $this->getMockBuilder(Escaper::class)
143+
->disableOriginalConstructor()
144+
->getMock();
145+
$this->addressRegistry = $this->getMockBuilder(AddressRegistry::class)
146+
->disableOriginalConstructor()
147+
->getMock();
148+
$this->filesystem = $this->getMockBuilder(Filesystem::class)
149+
->disableOriginalConstructor()
150+
->getMock();
151+
$this->sessionCleaner = $this->getMockBuilder(SessionCleanerInterface::class)
152+
->getMockForAbstractClass();
153+
$this->accountConfirmation = $this->getMockBuilder(AccountConfirmation::class)
154+
->disableOriginalConstructor()
155+
->getMock();
156+
$this->customerUrl = $this->getMockBuilder(Url::class)
157+
->disableOriginalConstructor()
158+
->getMock();
159+
$this->customerMapper = $this->getMockBuilder(Mapper::class)
160+
->disableOriginalConstructor()
161+
->getMock();
162+
163+
$this->request = $this->getMockBuilder(RequestInterface::class)
164+
->addMethods(['isPost', 'getPostValue'])
165+
->getMockForAbstractClass();
166+
$this->context->expects($this->any())
167+
->method('getRequest')
168+
->willReturn($this->request);
169+
$resultRedirectFactory = $this->getMockBuilder(RedirectFactory::class)
170+
->disableOriginalConstructor()
171+
->getMock();
172+
$this->context->expects($this->any())
173+
->method('getResultRedirectFactory')
174+
->willReturn($resultRedirectFactory);
175+
$redirect = $this->getMockBuilder(Redirect::class)
176+
->disableOriginalConstructor()
177+
->getMock();
178+
$resultRedirectFactory->expects($this->any())
179+
->method('create')
180+
->willReturn($redirect);
181+
182+
$eventManager = $this->getMockBuilder(EventManagerInterface::class)
183+
->getMockForAbstractClass();
184+
$this->context->expects($this->any())
185+
->method('getEventManager')
186+
->willReturn($eventManager);
187+
188+
$messageManager = $this->getMockBuilder(MessageManagerInterface::class)
189+
->getMockForAbstractClass();
190+
$this->context->expects($this->any())
191+
->method('getMessageManager')
192+
->willReturn($messageManager);
193+
194+
$this->editPost = new EditPost(
195+
$this->context,
196+
$this->customerSession,
197+
$this->accountManagement,
198+
$this->customerRepository,
199+
$this->formKeyValidator,
200+
$this->customerExtractor,
201+
$this->escaper,
202+
$this->addressRegistry,
203+
$this->filesystem,
204+
$this->sessionCleaner,
205+
$this->accountConfirmation,
206+
$this->customerUrl,
207+
$this->customerMapper
208+
);
209+
}
210+
211+
/**
212+
* @return void
213+
* @throws SessionException
214+
*/
215+
public function testExecute()
216+
{
217+
$this->formKeyValidator->expects($this->once())
218+
->method('validate')
219+
->with($this->request)
220+
->willReturn(true);
221+
$this->request->expects($this->once())
222+
->method('isPost')
223+
->willReturn(true);
224+
225+
$customer = $this->getMockBuilder(CustomerInterface::class)
226+
->getMockForAbstractClass();
227+
$customer->expects($this->any())
228+
->method('getAddresses')
229+
->willReturn([]);
230+
$this->customerRepository->expects($this->any())
231+
->method('getById')
232+
->willReturn($customer);
233+
234+
$this->customerMapper->expects($this->once())
235+
->method('toFlatArray')
236+
->willReturn([]);
237+
$this->customerExtractor->expects($this->once())
238+
->method('extract')
239+
->willReturn($customer);
240+
241+
$attr = 'attr1';
242+
$this->request->expects($this->exactly(5))
243+
->method('getParam')
244+
->withConsecutive(
245+
['change_email'],
246+
[ 'delete_attribute_value'],
247+
[$attr . File::UPLOADED_FILE_SUFFIX]
248+
)->willReturnOnConsecutiveCalls(
249+
false,
250+
$attr,
251+
'uploadedFileName'
252+
);
253+
254+
$this->editPost->execute();
255+
}
256+
}

0 commit comments

Comments
 (0)