Skip to content

Commit 2b7beca

Browse files
authored
Merge pull request #2660 from magento-honey-badgers/MAGETWO-91437-Category-Product-Indexer
[honey] MAGETWO-91437: Catalog_category_product_index table doesn't update after deleting category
2 parents 4688217 + 90e95ff commit 2b7beca

File tree

8 files changed

+201
-0
lines changed

8 files changed

+201
-0
lines changed

app/code/Magento/Catalog/Model/ResourceModel/Category.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
*/
1212
namespace Magento\Catalog\Model\ResourceModel;
1313

14+
use Magento\Catalog\Model\Indexer\Category\Product\Processor;
15+
use Magento\Framework\DataObject;
1416
use Magento\Framework\EntityManager\EntityManager;
1517

1618
/**
@@ -82,6 +84,11 @@ class Category extends AbstractResource
8284
*/
8385
protected $aggregateCount;
8486

87+
/**
88+
* @var Processor
89+
*/
90+
private $indexerProcessor;
91+
8592
/**
8693
* Category constructor.
8794
* @param \Magento\Eav\Model\Entity\Context $context
@@ -90,6 +97,7 @@ class Category extends AbstractResource
9097
* @param \Magento\Framework\Event\ManagerInterface $eventManager
9198
* @param Category\TreeFactory $categoryTreeFactory
9299
* @param Category\CollectionFactory $categoryCollectionFactory
100+
* @param Processor $indexerProcessor
93101
* @param array $data
94102
* @param \Magento\Framework\Serialize\Serializer\Json|null $serializer
95103
*/
@@ -100,6 +108,7 @@ public function __construct(
100108
\Magento\Framework\Event\ManagerInterface $eventManager,
101109
\Magento\Catalog\Model\ResourceModel\Category\TreeFactory $categoryTreeFactory,
102110
\Magento\Catalog\Model\ResourceModel\Category\CollectionFactory $categoryCollectionFactory,
111+
Processor $indexerProcessor,
103112
$data = [],
104113
\Magento\Framework\Serialize\Serializer\Json $serializer = null
105114
) {
@@ -113,6 +122,7 @@ public function __construct(
113122
$this->_categoryCollectionFactory = $categoryCollectionFactory;
114123
$this->_eventManager = $eventManager;
115124
$this->connectionName = 'catalog';
125+
$this->indexerProcessor = $indexerProcessor;
116126
$this->serializer = $serializer ?: \Magento\Framework\App\ObjectManager::getInstance()
117127
->get(\Magento\Framework\Serialize\Serializer\Json::class);
118128
}
@@ -197,6 +207,18 @@ protected function _beforeDelete(\Magento\Framework\DataObject $object)
197207
$this->deleteChildren($object);
198208
}
199209

210+
/**
211+
* Mark Category indexer as invalid to be picked up by cron.
212+
*
213+
* @param DataObject $object
214+
* @return $this
215+
*/
216+
protected function _afterDelete(DataObject $object)
217+
{
218+
$this->indexerProcessor->markIndexerAsInvalid();
219+
return parent::_afterDelete($object);
220+
}
221+
200222
/**
201223
* Delete children categories of specific category
202224
*

app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/CategoryTest.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
namespace Magento\Catalog\Test\Unit\Model\ResourceModel;
88

99
use Magento\Catalog\Model\Factory;
10+
use Magento\Catalog\Model\Indexer\Category\Product\Processor;
1011
use Magento\Catalog\Model\ResourceModel\Category;
1112
use Magento\Catalog\Model\ResourceModel\Category\CollectionFactory;
1213
use Magento\Eav\Model\Config;
@@ -91,6 +92,11 @@ class CategoryTest extends \PHPUnit\Framework\TestCase
9192
*/
9293
private $serializerMock;
9394

95+
/**
96+
* @var Processor|\PHPUnit_Framework_MockObject_MockObject
97+
*/
98+
private $indexerProcessorMock;
99+
94100
/**
95101
* {@inheritDoc}
96102
*/
@@ -121,6 +127,9 @@ protected function setUp()
121127
$this->collectionFactoryMock = $this->getMockBuilder(CollectionFactory::class)
122128
->disableOriginalConstructor()
123129
->getMock();
130+
$this->indexerProcessorMock = $this->getMockBuilder(Processor::class)
131+
->disableOriginalConstructor()
132+
->getMock();
124133

125134
$this->serializerMock = $this->getMockBuilder(Json::class)->getMock();
126135

@@ -131,6 +140,7 @@ protected function setUp()
131140
$this->managerMock,
132141
$this->treeFactoryMock,
133142
$this->collectionFactoryMock,
143+
$this->indexerProcessorMock,
134144
[],
135145
$this->serializerMock
136146
);
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
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\CatalogSearch\Model\Indexer\Fulltext\Model\Plugin;
9+
10+
use Magento\Catalog\Model\ResourceModel\Category as Resource;
11+
use Magento\CatalogSearch\Model\Indexer\Fulltext\Processor;
12+
13+
/**
14+
* Perform indexer invalidation after a category delete.
15+
*/
16+
class Category
17+
{
18+
/**
19+
* @var Processor
20+
*/
21+
private $fulltextIndexerProcessor;
22+
23+
/**
24+
* @param Processor $fulltextIndexerProcessor
25+
*/
26+
public function __construct(Processor $fulltextIndexerProcessor)
27+
{
28+
$this->fulltextIndexerProcessor = $fulltextIndexerProcessor;
29+
}
30+
31+
/**
32+
* Mark fulltext indexer as invalid post-deletion of category.
33+
*
34+
* @param Resource $subjectCategory
35+
* @param Resource $resultCategory
36+
* @return Resource
37+
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
38+
*/
39+
public function afterDelete(Resource $subjectCategory, Resource $resultCategory) : Resource
40+
{
41+
$this->fulltextIndexerProcessor->markIndexerAsInvalid();
42+
43+
return $resultCategory;
44+
}
45+
}

app/code/Magento/CatalogSearch/etc/adminhtml/di.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,7 @@
3131
<argument name="filter" xsi:type="object">Magento\CatalogSearch\Ui\DataProvider\Product\AddFulltextFilterToCollection</argument>
3232
</arguments>
3333
</type>
34+
<type name="Magento\Catalog\Model\ResourceModel\Category">
35+
<plugin name="fulltext_search_indexer" type="Magento\CatalogSearch\Model\Indexer\Fulltext\Model\Plugin\Category"/>
36+
</type>
3437
</config>
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?xml version="1.0"?>
2+
<!--
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
-->
8+
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
9+
<type name="Magento\Catalog\Model\ResourceModel\Category">
10+
<plugin name="fulltext_search_indexer" type="Magento\CatalogSearch\Model\Indexer\Fulltext\Model\Plugin\Category"/>
11+
</type>
12+
</config>
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?xml version="1.0"?>
2+
<!--
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
-->
8+
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
9+
<type name="Magento\Catalog\Model\ResourceModel\Category">
10+
<plugin name="fulltext_search_indexer" type="Magento\CatalogSearch\Model\Indexer\Fulltext\Model\Plugin\Category"/>
11+
</type>
12+
</config>

dev/tests/integration/testsuite/Magento/Catalog/Model/Indexer/Category/ProductTest.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@ class ProductTest extends \PHPUnit\Framework\TestCase
2727
*/
2828
protected $productResource;
2929

30+
/**
31+
* @var \Magento\Catalog\Api\CategoryRepositoryInterface
32+
*/
33+
private $categoryRepository;
34+
3035
protected function setUp()
3136
{
3237
/** @var \Magento\Framework\Indexer\IndexerInterface indexer */
@@ -39,6 +44,10 @@ protected function setUp()
3944
$this->productResource = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(
4045
\Magento\Catalog\Model\ResourceModel\Product::class
4146
);
47+
48+
$this->categoryRepository = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(
49+
\Magento\Catalog\Api\CategoryRepositoryInterface::class
50+
);
4251
}
4352

4453
/**
@@ -200,6 +209,25 @@ public function testCategoryCreate()
200209
}
201210
}
202211

212+
/**
213+
* @magentoAppArea adminhtml
214+
* @depends testReindexAll
215+
*/
216+
public function testCatalogCategoryProductIndexInvalidateAfterDelete()
217+
{
218+
$indexerShouldBeValid = (bool)$this->indexer->isInvalid();
219+
220+
$categories = $this->getCategories(1);
221+
$this->categoryRepository->delete(array_pop($categories));
222+
223+
$state = $this->indexer->getState();
224+
$state->loadByIndexer($this->indexer->getId());
225+
$status = $state->getStatus();
226+
227+
$this->assertFalse($indexerShouldBeValid);
228+
$this->assertEquals(\Magento\Framework\Indexer\StateInterface::STATUS_INVALID, $status);
229+
}
230+
203231
/**
204232
* @param int $count
205233
* @return Category[]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
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\CatalogSearch\Model\Indexer\Fulltext\Model\Plugin;
9+
10+
use Magento\Catalog\Api\CategoryRepositoryInterface;
11+
use Magento\Catalog\Model\Category;
12+
use Magento\CatalogSearch\Model\Indexer\Fulltext\Processor;
13+
use Magento\TestFramework\Helper\Bootstrap;
14+
15+
class CategoryTest extends \PHPUnit\Framework\TestCase
16+
{
17+
/**
18+
* @var Processor
19+
*/
20+
private $indexerProcessor;
21+
22+
/**
23+
* @var CategoryRepositoryInterface
24+
*/
25+
private $categoryRepository;
26+
27+
protected function setUp()
28+
{
29+
$this->indexerProcessor = Bootstrap::getObjectManager()->create(Processor::class);
30+
$this->categoryRepository = Bootstrap::getObjectManager()->create(CategoryRepositoryInterface::class);
31+
}
32+
33+
/**
34+
* @magentoDataFixture Magento/Catalog/_files/indexer_catalog_category.php
35+
* @magentoAppArea adminhtml
36+
*/
37+
public function testIndexerInvalidatedAfterCategoryDelete()
38+
{
39+
$this->indexerProcessor->reindexAll();
40+
$isIndexerValid = (bool)$this->indexerProcessor->getIndexer()->isValid();
41+
42+
$category = $this->getCategories(1);
43+
$this->categoryRepository->delete(array_pop($category));
44+
45+
$state = $this->indexerProcessor->getIndexer()->getState();
46+
$state->loadByIndexer($this->indexerProcessor->getIndexerId());
47+
$status = $state->getStatus();
48+
49+
$this->assertTrue($isIndexerValid);
50+
$this->assertEquals(\Magento\Framework\Indexer\StateInterface::STATUS_INVALID, $status);
51+
}
52+
53+
/**
54+
* @param int $count
55+
* @return Category[]
56+
*/
57+
private function getCategories($count)
58+
{
59+
/** @var Category $category */
60+
$category = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(
61+
\Magento\Catalog\Model\Category::class
62+
);
63+
64+
$result = $category->getCollection()->addAttributeToSelect('name')->getItems();
65+
$result = array_slice($result, 2);
66+
67+
return array_slice($result, 0, $count);
68+
}
69+
}

0 commit comments

Comments
 (0)