Skip to content

Commit e092d78

Browse files
authored
ENGCOM-6490: Add mass action to invalidate indexes via admin #25860
2 parents 9805fbd + a590e96 commit e092d78

File tree

9 files changed

+370
-0
lines changed

9 files changed

+370
-0
lines changed

app/code/Magento/Indexer/Controller/Adminhtml/Indexer.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
*/
66
namespace Magento\Indexer\Controller\Adminhtml;
77

8+
/**
9+
* Abstract class used as part of inheritance tree for Indexer controllers
10+
*/
811
abstract class Indexer extends \Magento\Backend\App\Action
912
{
1013
/**
@@ -20,6 +23,8 @@ protected function _isAllowed()
2023
case 'massOnTheFly':
2124
case 'massChangelog':
2225
return $this->_authorization->isAllowed('Magento_Indexer::changeMode');
26+
case 'massInvalidate':
27+
return $this->_authorization->isAllowed('Magento_Indexer::invalidate');
2328
}
2429
return false;
2530
}

app/code/Magento/Indexer/Controller/Adminhtml/Indexer/ListAction.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88

99
use Magento\Framework\App\Action\HttpGetActionInterface as HttpGetActionInterface;
1010

11+
/**
12+
* Controller for indexer grid
13+
*/
1114
class ListAction extends \Magento\Indexer\Controller\Adminhtml\Indexer implements HttpGetActionInterface
1215
{
1316
/**

app/code/Magento/Indexer/Controller/Adminhtml/Indexer/MassChangelog.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88

99
use Magento\Framework\App\Action\HttpPostActionInterface as HttpPostActionInterface;
1010

11+
/**
12+
* Controller endpoint for mass action: set index mode as 'Update by Schedule'
13+
*/
1114
class MassChangelog extends \Magento\Indexer\Controller\Adminhtml\Indexer implements HttpPostActionInterface
1215
{
1316
/**
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento\Indexer\Controller\Adminhtml\Indexer;
7+
8+
use Magento\Backend\App\Action\Context;
9+
use Magento\Framework\App\Action\HttpPostActionInterface as HttpPostActionInterface;
10+
use Magento\Framework\Indexer\IndexerRegistry;
11+
12+
/**
13+
* Controller endpoint for mass action: invalidate index
14+
*/
15+
class MassInvalidate extends \Magento\Indexer\Controller\Adminhtml\Indexer implements HttpPostActionInterface
16+
{
17+
/**
18+
* @var IndexerRegistry $indexerRegistry
19+
*/
20+
private $indexerRegistry;
21+
22+
/**
23+
* @param Context $context
24+
* @param IndexerRegistry $indexerRegistry
25+
*/
26+
public function __construct(
27+
Context $context,
28+
IndexerRegistry $indexerRegistry
29+
) {
30+
parent::__construct($context);
31+
$this->indexerRegistry = $indexerRegistry;
32+
}
33+
34+
/**
35+
* Turn mview on for the given indexers
36+
*
37+
* @return void
38+
*/
39+
public function execute()
40+
{
41+
$indexerIds = $this->getRequest()->getParam('indexer_ids');
42+
if (!is_array($indexerIds)) {
43+
$this->messageManager->addError(__('Please select indexers.'));
44+
} else {
45+
try {
46+
foreach ($indexerIds as $indexerId) {
47+
/** @var \Magento\Framework\Indexer\IndexerInterface $model */
48+
$model = $this->indexerRegistry->get($indexerId);
49+
$model->invalidate();
50+
}
51+
$this->messageManager->addSuccess(
52+
__('%1 indexer(s) were invalidated.', count($indexerIds))
53+
);
54+
} catch (\Magento\Framework\Exception\LocalizedException $e) {
55+
$this->messageManager->addError($e->getMessage());
56+
} catch (\Exception $e) {
57+
$this->messageManager->addException(
58+
$e,
59+
__("We couldn't invalidate indexer(s) because of an error.")
60+
);
61+
}
62+
}
63+
return $this->resultRedirectFactory->create()->setPath('*/*/list');
64+
}
65+
}

app/code/Magento/Indexer/Controller/Adminhtml/Indexer/MassOnTheFly.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88

99
use Magento\Framework\App\Action\HttpPostActionInterface as HttpPostActionInterface;
1010

11+
/**
12+
* Controller endpoint for mass action: set index mode as 'Update on Save'
13+
*/
1114
class MassOnTheFly extends \Magento\Indexer\Controller\Adminhtml\Indexer implements HttpPostActionInterface
1215
{
1316
/**
Lines changed: 281 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,281 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento\Indexer\Test\Unit\Controller\Adminhtml\Indexer;
7+
8+
/**
9+
* Test for Mass invalidate action
10+
*
11+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
12+
*/
13+
class MassInvalidateTest extends \PHPUnit\Framework\TestCase
14+
{
15+
/**
16+
* @var \Magento\Indexer\Controller\Adminhtml\Indexer\MassInvalidate
17+
*/
18+
protected $controller;
19+
20+
/**
21+
* @var \Magento\Backend\App\Action\Context
22+
*/
23+
protected $contextMock;
24+
25+
/**
26+
* @var \Magento\Framework\App\ViewInterface
27+
*/
28+
protected $view;
29+
30+
/**
31+
* @var \Magento\Framework\View\Result\Page
32+
*/
33+
protected $page;
34+
35+
/**
36+
* @var \Magento\Framework\View\Page\Config
37+
*/
38+
protected $config;
39+
40+
/**
41+
* @var \Magento\Framework\View\Page\Title
42+
*/
43+
protected $title;
44+
45+
/**
46+
* @var \Magento\Framework\App\RequestInterface
47+
*/
48+
protected $request;
49+
50+
/**
51+
* @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager
52+
*/
53+
protected $objectManager;
54+
55+
/**
56+
* @var \Magento\Framework\Message\ManagerInterface
57+
*/
58+
protected $messageManager;
59+
60+
/**
61+
* @var \Magento\Framework\Indexer\IndexerRegistry
62+
*/
63+
protected $indexReg;
64+
65+
/**
66+
* @var \Magento\Framework\App\ResponseInterface
67+
*/
68+
protected $response;
69+
70+
/**
71+
* @var \Magento\Framework\App\ActionFlag
72+
*/
73+
protected $actionFlag;
74+
75+
/**
76+
* @var \Magento\Backend\Helper\Data
77+
*/
78+
protected $helper;
79+
80+
/**
81+
* @var \Magento\Backend\Model\Session
82+
*/
83+
protected $session;
84+
85+
/**
86+
* @var \Magento\Framework\Controller\Result\Redirect
87+
*/
88+
protected $resultRedirect;
89+
90+
/**
91+
* Set up test
92+
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
93+
*/
94+
protected function setUp()
95+
{
96+
$this->contextMock = $this->createPartialMock(
97+
\Magento\Backend\App\Action\Context::class,
98+
[
99+
'getAuthorization',
100+
'getSession',
101+
'getActionFlag',
102+
'getAuth',
103+
'getView',
104+
'getHelper',
105+
'getBackendUrl',
106+
'getFormKeyValidator',
107+
'getLocaleResolver',
108+
'getCanUseBaseUrl',
109+
'getRequest',
110+
'getResponse',
111+
'getObjectManager',
112+
'getMessageManager',
113+
'getResultRedirectFactory',
114+
]
115+
);
116+
117+
$this->response = $this->createPartialMock(
118+
\Magento\Framework\App\ResponseInterface::class,
119+
['setRedirect', 'sendResponse']
120+
);
121+
122+
$this->view = $this->createPartialMock(
123+
\Magento\Framework\App\ViewInterface::class,
124+
[
125+
'loadLayout',
126+
'getPage',
127+
'getConfig',
128+
'getTitle',
129+
'renderLayout',
130+
'loadLayoutUpdates',
131+
'getDefaultLayoutHandle',
132+
'addPageLayoutHandles',
133+
'generateLayoutBlocks',
134+
'generateLayoutXml',
135+
'getLayout',
136+
'addActionLayoutHandles',
137+
'setIsLayoutLoaded',
138+
'isLayoutLoaded'
139+
]
140+
);
141+
142+
$this->session = $this->createPartialMock(\Magento\Backend\Model\Session::class, ['setIsUrlNotice']);
143+
$this->session->expects($this->any())->method('setIsUrlNotice')->willReturn($this->objectManager);
144+
$this->actionFlag = $this->createPartialMock(\Magento\Framework\App\ActionFlag::class, ['get']);
145+
$this->actionFlag->expects($this->any())->method("get")->willReturn($this->objectManager);
146+
$this->objectManager = $this->createPartialMock(
147+
\Magento\Framework\TestFramework\Unit\Helper\ObjectManager::class,
148+
['get']
149+
);
150+
$this->request = $this->getMockForAbstractClass(
151+
\Magento\Framework\App\RequestInterface::class,
152+
['getParam', 'getRequest'],
153+
'',
154+
false
155+
);
156+
157+
$resultRedirectFactory = $this->createPartialMock(
158+
\Magento\Backend\Model\View\Result\RedirectFactory::class,
159+
['create']
160+
);
161+
$this->resultRedirect = $this->createPartialMock(
162+
\Magento\Framework\Controller\Result\Redirect::class,
163+
['setPath']
164+
);
165+
$this->contextMock->expects($this->any())->method('getResultRedirectFactory')
166+
->willReturn($resultRedirectFactory);
167+
$resultRedirectFactory->expects($this->any())->method('create')
168+
->willReturn($this->resultRedirect);
169+
170+
$this->response->expects($this->any())->method("setRedirect")->willReturn(1);
171+
$this->page = $this->createMock(\Magento\Framework\View\Result\Page::class);
172+
$this->config = $this->createMock(\Magento\Framework\View\Result\Page::class);
173+
$this->title = $this->createMock(\Magento\Framework\View\Page\Title::class);
174+
$this->messageManager = $this->getMockForAbstractClass(
175+
\Magento\Framework\Message\ManagerInterface::class,
176+
['addError', 'addSuccess'],
177+
'',
178+
false
179+
);
180+
181+
$this->indexReg = $this->createPartialMock(
182+
\Magento\Framework\Indexer\IndexerRegistry::class,
183+
['get', 'setScheduled']
184+
);
185+
$this->helper = $this->createPartialMock(\Magento\Backend\Helper\Data::class, ['getUrl']);
186+
$this->contextMock->expects($this->any())->method("getObjectManager")->willReturn($this->objectManager);
187+
$this->contextMock->expects($this->any())->method("getRequest")->willReturn($this->request);
188+
$this->contextMock->expects($this->any())->method("getResponse")->willReturn($this->response);
189+
$this->contextMock->expects($this->any())->method("getMessageManager")->willReturn($this->messageManager);
190+
$this->contextMock->expects($this->any())->method("getSession")->willReturn($this->session);
191+
$this->contextMock->expects($this->any())->method("getActionFlag")->willReturn($this->actionFlag);
192+
$this->contextMock->expects($this->any())->method("getHelper")->willReturn($this->helper);
193+
}
194+
195+
/**
196+
* @param array $indexerIds
197+
* @param \Exception $exception
198+
* @dataProvider executeDataProvider
199+
*/
200+
public function testExecute($indexerIds, $exception)
201+
{
202+
$this->controller = new \Magento\Indexer\Controller\Adminhtml\Indexer\MassInvalidate(
203+
$this->contextMock,
204+
$this->indexReg
205+
);
206+
$this->request->expects($this->any())
207+
->method('getParam')->with('indexer_ids')
208+
->will($this->returnValue($indexerIds));
209+
210+
if (!is_array($indexerIds)) {
211+
$this->messageManager->expects($this->once())
212+
->method('addError')->with(__('Please select indexers.'))
213+
->will($this->returnValue(1));
214+
} else {
215+
$indexerInterface = $this->getMockForAbstractClass(
216+
\Magento\Framework\Indexer\IndexerInterface::class,
217+
['invalidate'],
218+
'',
219+
false
220+
);
221+
$this->indexReg->expects($this->any())
222+
->method('get')->with(1)
223+
->will($this->returnValue($indexerInterface));
224+
225+
$indexerInterface->expects($this->any())
226+
->method('invalidate')->with(true)
227+
->will($this->returnValue(1));
228+
229+
$this->messageManager->expects($this->any())
230+
->method('addSuccess')
231+
->will($this->returnValue(1));
232+
233+
if ($exception) {
234+
$this->indexReg->expects($this->any())
235+
->method('get')->with(2)
236+
->will($this->throwException($exception));
237+
238+
if ($exception instanceof \Magento\Framework\Exception\LocalizedException) {
239+
$this->messageManager->expects($this->once())
240+
->method('addError')
241+
->with($exception->getMessage());
242+
} else {
243+
$this->messageManager->expects($this->once())
244+
->method('addException')
245+
->with($exception, "We couldn't invalidate indexer(s) because of an error.");
246+
}
247+
}
248+
}
249+
250+
$this->helper->expects($this->any())->method("getUrl")->willReturn("magento.com");
251+
$this->response->expects($this->any())->method("setRedirect")->willReturn(1);
252+
$this->resultRedirect->expects($this->once())->method('setPath')->with('*/*/list');
253+
254+
$this->controller->execute();
255+
}
256+
257+
/**
258+
* @return array
259+
*/
260+
public function executeDataProvider()
261+
{
262+
return [
263+
'set1' => [
264+
'indexers' => 1,
265+
'exception' => null,
266+
],
267+
'set2' => [
268+
'indexers' => [1],
269+
'exception' => null,
270+
],
271+
'set3' => [
272+
'indexers' => [2],
273+
'exception' => new \Magento\Framework\Exception\LocalizedException(__('Test Phrase')),
274+
],
275+
'set4' => [
276+
'indexers' => [2],
277+
'exception' => new \Exception(),
278+
]
279+
];
280+
}
281+
}

0 commit comments

Comments
 (0)