diff --git a/app/code/Magento/CatalogRule/Model/Indexer/AbstractIndexer.php b/app/code/Magento/CatalogRule/Model/Indexer/AbstractIndexer.php index cf52ebbe0669ae45c8ec130f440f557b22865427..a4d8b53934937cd2342f00bfd5505f6d59953ecc 100644 --- a/app/code/Magento/CatalogRule/Model/Indexer/AbstractIndexer.php +++ b/app/code/Magento/CatalogRule/Model/Indexer/AbstractIndexer.php @@ -16,12 +16,23 @@ abstract class AbstractIndexer implements IndexerActionInterface, MviewActionInt */ protected $indexBuilder; + /** + * Application Event Dispatcher + * + * @var \Magento\Framework\Event\ManagerInterface + */ + protected $_eventManager; + /** * @param IndexBuilder $indexBuilder + * @param \Magento\Framework\Event\ManagerInterface $eventManager */ - public function __construct(IndexBuilder $indexBuilder) - { + public function __construct( + IndexBuilder $indexBuilder, + \Magento\Framework\Event\ManagerInterface $eventManager + ) { $this->indexBuilder = $indexBuilder; + $this->_eventManager = $eventManager; } /** @@ -43,6 +54,20 @@ abstract class AbstractIndexer implements IndexerActionInterface, MviewActionInt public function executeFull() { $this->indexBuilder->reindexFull(); + $this->_eventManager->dispatch('clean_cache_by_tags', ['object' => $this]); + } + + /** + * Get affected cache tags + * + * @return array + */ + public function getIdentities() + { + return [ + \Magento\Catalog\Model\Category::CACHE_TAG, + \Magento\Catalog\Model\Product::CACHE_TAG + ]; } /** diff --git a/app/code/Magento/CatalogRule/Model/Rule.php b/app/code/Magento/CatalogRule/Model/Rule.php index 61eac7c2b59f204a98ee782994d04eed6e97bfbf..99eb4752f691cb88006c3cd108782aa53600e991 100644 --- a/app/code/Magento/CatalogRule/Model/Rule.php +++ b/app/code/Magento/CatalogRule/Model/Rule.php @@ -143,6 +143,11 @@ class Rule extends \Magento\Rule\Model\AbstractModel */ protected $dateTime; + /** + * @var \Magento\CatalogRule\Model\Indexer\Rule\RuleProductProcessor; + */ + protected $_ruleProductProcessor; + /** * @param \Magento\Framework\Model\Context $context * @param \Magento\Framework\Registry $registry @@ -158,6 +163,7 @@ class Rule extends \Magento\Rule\Model\AbstractModel * @param \Magento\CatalogRule\Helper\Data $catalogRuleData * @param \Magento\Framework\App\Cache\TypeListInterface $cacheTypesList * @param \Magento\Framework\Stdlib\DateTime $dateTime + * @param \Magento\CatalogRule\Model\Indexer\Rule\RuleProductProcessor $ruleProductProcessor * @param \Magento\Framework\Model\Resource\AbstractResource $resource * @param \Magento\Framework\Data\Collection\Db $resourceCollection * @param array $relatedCacheTypes @@ -179,6 +185,7 @@ class Rule extends \Magento\Rule\Model\AbstractModel \Magento\CatalogRule\Helper\Data $catalogRuleData, \Magento\Framework\App\Cache\TypeListInterface $cacheTypesList, \Magento\Framework\Stdlib\DateTime $dateTime, + \Magento\CatalogRule\Model\Indexer\Rule\RuleProductProcessor $ruleProductProcessor, \Magento\Framework\Model\Resource\AbstractResource $resource = null, \Magento\Framework\Data\Collection\Db $resourceCollection = null, array $relatedCacheTypes = [], @@ -195,6 +202,7 @@ class Rule extends \Magento\Rule\Model\AbstractModel $this->_cacheTypesList = $cacheTypesList; $this->_relatedCacheTypes = $relatedCacheTypes; $this->dateTime = $dateTime; + $this->_ruleProductProcessor = $ruleProductProcessor; parent::__construct($context, $registry, $formFactory, $localeDate, $resource, $resourceCollection, $data); } @@ -445,4 +453,33 @@ class Rule extends \Magento\Rule\Model\AbstractModel } return $this; } + + /** + * {@inheritdoc} + * + * @return $this + */ + public function afterSave() + { + if ($this->isObjectNew()) { + $this->getMatchingProductIds(); + if (!empty($this->_productIds) && is_array($this->_productIds)) { + $this->_ruleProductProcessor->reindexList($this->_productIds); + } + } else { + $this->_ruleProductProcessor->getIndexer()->invalidate(); + } + return parent::afterSave(); + } + + /** + * {@inheritdoc} + * + * @return $this + */ + public function afterDelete() + { + $this->_ruleProductProcessor->getIndexer()->invalidate(); + return parent::afterDelete(); + } } diff --git a/app/code/Magento/CatalogRule/Test/Unit/Model/Indexer/AbstractIndexerTest.php b/app/code/Magento/CatalogRule/Test/Unit/Model/Indexer/AbstractIndexerTest.php index 526ea7786417882ee711161a4021d27b66fcf7e7..b9a21020e4120a7218a7af66fc9ba0d833a2ebc8 100644 --- a/app/code/Magento/CatalogRule/Test/Unit/Model/Indexer/AbstractIndexerTest.php +++ b/app/code/Magento/CatalogRule/Test/Unit/Model/Indexer/AbstractIndexerTest.php @@ -18,16 +18,35 @@ class AbstractIndexerTest extends \PHPUnit_Framework_TestCase */ protected $indexer; + /** + * @var \Magento\Framework\Event\ManagerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $_eventManagerMock; + + /** + * Set up test + * + * @return void + */ protected function setUp() { + $this->_eventManagerMock = $this->getMock('\Magento\Framework\Event\ManagerInterface'); $this->indexBuilder = $this->getMock('Magento\CatalogRule\Model\Indexer\IndexBuilder', [], [], '', false); $this->indexer = $this->getMockForAbstractClass( 'Magento\CatalogRule\Model\Indexer\AbstractIndexer', - [$this->indexBuilder] + [ + $this->indexBuilder, + $this->_eventManagerMock + ] ); } + /** + * Test execute + * + * @return void + */ public function testExecute() { $ids = [1, 2, 5]; @@ -36,9 +55,20 @@ class AbstractIndexerTest extends \PHPUnit_Framework_TestCase $this->indexer->execute($ids); } + /** + * Test execute full reindex action + * + * @return void + */ public function testExecuteFull() { $this->indexBuilder->expects($this->once())->method('reindexFull'); + $this->_eventManagerMock->expects($this->once()) + ->method('dispatch') + ->with( + 'clean_cache_by_tags', + ['object' => $this->indexer] + ); $this->indexer->executeFull(); } @@ -46,12 +76,19 @@ class AbstractIndexerTest extends \PHPUnit_Framework_TestCase /** * @expectedException \Magento\CatalogRule\CatalogRuleException * @expectedExceptionMessage Could not rebuild index for empty products array + * + * @return void */ public function testExecuteListWithEmptyIds() { $this->indexer->executeList([]); } + /** + * @throws \Magento\CatalogRule\CatalogRuleException + * + * @return void + */ public function testExecuteList() { $ids = [1, 2, 5]; @@ -63,12 +100,19 @@ class AbstractIndexerTest extends \PHPUnit_Framework_TestCase /** * @expectedException \Magento\CatalogRule\CatalogRuleException * @expectedExceptionMessage Could not rebuild index for undefined product + * + * @return void */ public function testExecuteRowWithEmptyId() { $this->indexer->executeRow(null); } + /** + * @throws \Magento\CatalogRule\CatalogRuleException + * + * @return void + */ public function testExecuteRow() { $id = 5; diff --git a/app/code/Magento/CatalogRule/Test/Unit/Model/RuleTest.php b/app/code/Magento/CatalogRule/Test/Unit/Model/RuleTest.php index 095ca9891a7405407df9b759950721b4d2676d40..4b3d8d2edd1875f00b0244b31f82a2796e6bc60e 100644 --- a/app/code/Magento/CatalogRule/Test/Unit/Model/RuleTest.php +++ b/app/code/Magento/CatalogRule/Test/Unit/Model/RuleTest.php @@ -31,6 +31,31 @@ class RuleTest extends \PHPUnit_Framework_TestCase /** @var \Magento\Rule\Model\Condition\Combine|\PHPUnit_Framework_MockObject_MockObject */ protected $condition; + /** + * @var \Magento\CatalogRule\Model\Indexer\Rule\RuleProductProcessor|\PHPUnit_Framework_MockObject_MockObject + */ + protected $_ruleProductProcessor; + + /** + * @var \Magento\Catalog\Model\Resource\Product\CollectionFactory|\PHPUnit_Framework_MockObject_MockObject + */ + protected $_productCollectionFactory; + + /** + * @var \Magento\Framework\Model\Resource\Iterator|\PHPUnit_Framework_MockObject_MockObject + */ + protected $_resourceIterator; + + /** + * @var \Magento\Catalog\Model\Product|\PHPUnit_Framework_MockObject_MockObject + */ + protected $productModel; + + /** + * Set up before test + * + * @return void + */ protected function setUp() { $this->storeManager = $this->getMock('Magento\Store\Model\StoreManagerInterface'); @@ -74,13 +99,39 @@ class RuleTest extends \PHPUnit_Framework_TestCase '', false ); + $this->_ruleProductProcessor = $this->getMock( + '\Magento\CatalogRule\Model\Indexer\Rule\RuleProductProcessor', + [], + [], + '', + false + ); + + $this->_productCollectionFactory = $this->getMock( + '\Magento\Catalog\Model\Resource\Product\CollectionFactory', + ['create'], + [], + '', + false + ); + + $this->_resourceIterator = $this->getMock( + '\Magento\Framework\Model\Resource\Iterator', + ['walk'], + [], + '', + false + ); $this->objectManagerHelper = new ObjectManagerHelper($this); $this->rule = $this->objectManagerHelper->getObject( 'Magento\CatalogRule\Model\Rule', [ 'storeManager' => $this->storeManager, - 'combineFactory' => $this->combineFactory + 'combineFactory' => $this->combineFactory, + 'ruleProductProcessor' => $this->_ruleProductProcessor, + 'productCollectionFactory' => $this->_productCollectionFactory, + 'resourceIterator' => $this->_resourceIterator, ] ); } @@ -88,6 +139,8 @@ class RuleTest extends \PHPUnit_Framework_TestCase /** * @dataProvider dataProviderCallbackValidateProduct * @param bool $validate + * + * @return void */ public function testCallbackValidateProduct($validate) { @@ -134,6 +187,11 @@ class RuleTest extends \PHPUnit_Framework_TestCase } } + /** + * Data provider for callbackValidateProduct test + * + * @return array + */ public function dataProviderCallbackValidateProduct() { return [ @@ -141,4 +199,31 @@ class RuleTest extends \PHPUnit_Framework_TestCase [true], ]; } + + /** + * Test after delete action + * + * @return void + */ + public function testAfterDelete() + { + $indexer = $this->getMock('\Magento\Indexer\Model\IndexerInterface'); + $indexer->expects($this->once())->method('invalidate'); + $this->_ruleProductProcessor->expects($this->once())->method('getIndexer')->will($this->returnValue($indexer)); + $this->rule->afterDelete(); + } + + /** + * Test after update action + * + * @return void + */ + public function testAfterUpdate() + { + $this->rule->isObjectNew(false); + $indexer = $this->getMock('\Magento\Indexer\Model\IndexerInterface'); + $indexer->expects($this->once())->method('invalidate'); + $this->_ruleProductProcessor->expects($this->once())->method('getIndexer')->will($this->returnValue($indexer)); + $this->rule->afterSave(); + } }