From ff86fb9ef0dfdd5bac9716695be872e086ab1add Mon Sep 17 00:00:00 2001
From: Roman Ganin <rganin@ebay.com>
Date: Sun, 15 Mar 2015 15:00:36 +0200
Subject: [PATCH] MAGETWO-33690: Category page displays outdated prices after
 catalog price rule is deleted

---
 app/code/Magento/Catalog/etc/di.xml           |   3 -
 .../Model/Indexer/AbstractIndexer.php         |  28 +++-
 app/code/Magento/CatalogRule/Model/Rule.php   |  34 +++++
 .../Model/Indexer/AbstractIndexerTest.php     |  17 ++-
 .../CatalogRule/Test/Unit/Model/RuleTest.php  |  65 +++++++++-
 .../Model/Indexer/CatalogRulePlugin.php       |  74 -----------
 .../Model/Indexer/CatalogRulePluginTest.php   | 121 ------------------
 7 files changed, 140 insertions(+), 202 deletions(-)
 delete mode 100644 app/code/Magento/PageCache/Model/Indexer/CatalogRulePlugin.php
 delete mode 100644 app/code/Magento/PageCache/Test/Unit/Model/Indexer/CatalogRulePluginTest.php

diff --git a/app/code/Magento/Catalog/etc/di.xml b/app/code/Magento/Catalog/etc/di.xml
index c60e7710f85..971bebcac32 100644
--- a/app/code/Magento/Catalog/etc/di.xml
+++ b/app/code/Magento/Catalog/etc/di.xml
@@ -171,9 +171,6 @@
         <plugin name="catalogProductFlatIndexerStoreGroup" type="Magento\Catalog\Model\Indexer\Product\Flat\Plugin\StoreGroup" />
         <plugin name="categoryStoreGroupAroundSave" type="Magento\Catalog\Model\Indexer\Category\Product\Plugin\StoreGroup"/>
     </type>
-    <type name="Magento\CatalogRule\Model\Indexer\AbstractIndexer">
-        <plugin name="abstractIndexerAroundSave" type="Magento\PageCache\Model\Indexer\CatalogRulePlugin"/>
-    </type>
     <type name="Magento\Customer\Api\GroupRepositoryInterface">
         <plugin name="invalidatePriceIndexerOnCustomerGroup" type="Magento\Catalog\Model\Indexer\Product\Price\Plugin\CustomerGroup"/>
     </type>
diff --git a/app/code/Magento/CatalogRule/Model/Indexer/AbstractIndexer.php b/app/code/Magento/CatalogRule/Model/Indexer/AbstractIndexer.php
index cf52ebbe066..170053df37c 100644
--- a/app/code/Magento/CatalogRule/Model/Indexer/AbstractIndexer.php
+++ b/app/code/Magento/CatalogRule/Model/Indexer/AbstractIndexer.php
@@ -16,12 +16,22 @@ abstract class AbstractIndexer implements IndexerActionInterface, MviewActionInt
      */
     protected $indexBuilder;
 
+    /**
+     * Application Event Dispatcher
+     *
+     * @var \Magento\Framework\Event\ManagerInterface
+     */
+    protected $_eventManager;
+
     /**
      * @param IndexBuilder $indexBuilder
      */
-    public function __construct(IndexBuilder $indexBuilder)
-    {
+    public function __construct(
+        IndexBuilder $indexBuilder,
+        \Magento\Framework\Event\ManagerInterface $eventManager
+    ) {
         $this->indexBuilder = $indexBuilder;
+        $this->_eventManager = $eventManager;
     }
 
     /**
@@ -43,6 +53,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 61eac7c2b59..bcb85979fc7 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
      * @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,30 @@ class Rule extends \Magento\Rule\Model\AbstractModel
         }
         return $this;
     }
+
+    /**
+     * {@inheritdoc}
+     *
+     * @return $this
+     */
+    public function afterSave()
+    {
+        if ($this->isObjectNew()) {
+            $this->_ruleProductProcessor->reindexList($this->getMatchingProductIds());
+        } 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 526ea778641..6c2fd2056d7 100644
--- a/app/code/Magento/CatalogRule/Test/Unit/Model/Indexer/AbstractIndexerTest.php
+++ b/app/code/Magento/CatalogRule/Test/Unit/Model/Indexer/AbstractIndexerTest.php
@@ -18,13 +18,22 @@ class AbstractIndexerTest extends \PHPUnit_Framework_TestCase
      */
     protected $indexer;
 
+    /**
+     * @var \Magento\Framework\Event\ManagerInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $_eventManagerMock;
+
     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
+            ]
         );
     }
 
@@ -39,6 +48,12 @@ class AbstractIndexerTest extends \PHPUnit_Framework_TestCase
     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();
     }
diff --git a/app/code/Magento/CatalogRule/Test/Unit/Model/RuleTest.php b/app/code/Magento/CatalogRule/Test/Unit/Model/RuleTest.php
index 095ca9891a7..de720aa681a 100644
--- a/app/code/Magento/CatalogRule/Test/Unit/Model/RuleTest.php
+++ b/app/code/Magento/CatalogRule/Test/Unit/Model/RuleTest.php
@@ -31,6 +31,26 @@ 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;
+
     protected function setUp()
     {
         $this->storeManager = $this->getMock('Magento\Store\Model\StoreManagerInterface');
@@ -74,13 +94,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,
             ]
         );
     }
@@ -141,4 +187,21 @@ class RuleTest extends \PHPUnit_Framework_TestCase
             [true],
         ];
     }
+
+    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();
+    }
+
+    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();
+    }
 }
diff --git a/app/code/Magento/PageCache/Model/Indexer/CatalogRulePlugin.php b/app/code/Magento/PageCache/Model/Indexer/CatalogRulePlugin.php
deleted file mode 100644
index e0088a87904..00000000000
--- a/app/code/Magento/PageCache/Model/Indexer/CatalogRulePlugin.php
+++ /dev/null
@@ -1,74 +0,0 @@
-<?php
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-namespace Magento\PageCache\Model\Indexer;
-
-/**
- * Class CatalogRulePlugin
- * @package Magento\PageCache\Model\Indexer
- */
-class CatalogRulePlugin
-{
-    /**
-     * @var \Magento\PageCache\Model\Config
-     */
-    protected $config;
-
-    /**
-     * @var \Magento\Framework\App\CacheInterface
-     */
-    protected $cache;
-
-    /**
-     * @var \Magento\Framework\App\Cache\Type\FrontendPool
-     */
-    protected $pool;
-
-    /**
-     * @param \Magento\PageCache\Model\Config $config
-     * @param \Magento\Framework\App\Cache\TypeListInterface $typeList
-     * @param \Magento\Framework\App\Cache\Type\FrontendPool $pool
-     */
-    public function __construct(
-        \Magento\PageCache\Model\Config $config,
-        \Magento\Framework\App\CacheInterface $cache,
-        \Magento\Framework\App\Cache\Type\FrontendPool $pool
-    ) {
-        $this->config = $config;
-        $this->cache = $cache;
-        $this->pool = $pool;
-    }
-
-    /**
-     * @param \Magento\CatalogRule\Model\Indexer\AbstractIndexer $subject
-     *
-     * @return \Magento\CatalogRule\Model\Indexer\AbstractIndexer
-     */
-    public function afterExecuteFull(
-        \Magento\CatalogRule\Model\Indexer\AbstractIndexer $subject
-    ) {
-        if ($this->config->isEnabled()) {
-            $this->pool->get(
-                \Magento\PageCache\Model\Cache\Type::TYPE_IDENTIFIER
-            )->clean(
-                \Zend_Cache::CLEANING_MODE_ALL,
-                [
-                    \Magento\Catalog\Model\Category::CACHE_TAG,
-                    \Magento\Catalog\Model\Product::CACHE_TAG
-                ]
-            );
-
-            $this->cache->clean(
-                [
-                    \Magento\Catalog\Model\Category::CACHE_TAG,
-                    \Magento\Catalog\Model\Product::CACHE_TAG,
-                    \Magento\Catalog\Model\Product\Compare\Item::CACHE_TAG,
-                    \Magento\Wishlist\Model\Wishlist::CACHE_TAG
-                ]
-            );
-        }
-        return $subject;
-    }
-}
diff --git a/app/code/Magento/PageCache/Test/Unit/Model/Indexer/CatalogRulePluginTest.php b/app/code/Magento/PageCache/Test/Unit/Model/Indexer/CatalogRulePluginTest.php
deleted file mode 100644
index 0e64779bebc..00000000000
--- a/app/code/Magento/PageCache/Test/Unit/Model/Indexer/CatalogRulePluginTest.php
+++ /dev/null
@@ -1,121 +0,0 @@
-<?php
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-namespace Magento\PageCache\Test\Unit\Model\Indexer;
-
-/**
- * Class CatalogRulePluginTest
- * @package Magento\PageCache\Test\Unit\Model\Indexer
- */
-class CatalogRulePluginTest extends \PHPUnit_Framework_TestCase
-{
-    /**
-     * @var \PHPUnit_Framework_MockObject_MockObject
-     */
-    protected $configMock;
-
-    /**
-     * @var \PHPUnit_Framework_MockObject_MockObject
-     */
-    protected $cacheMock;
-
-    /**
-     * @var \PHPUnit_Framework_MockObject_MockObject
-     */
-    protected $poolMock;
-
-    /**
-     * @var \PHPUnit_Framework_MockObject_MockObject
-     */
-    protected $frontCache;
-
-    /**
-     * @var \Magento\PageCache\Model\Indexer\CatalogRulePlugin
-     */
-    protected $model;
-
-    protected function setUp()
-    {
-        $this->configMock = $this->getMock(
-            '\Magento\PageCache\Model\Config',
-            ['isEnabled'],
-            [],
-            '',
-            false
-        );
-
-        $this->cacheMock = $this->getMockForAbstractClass(
-            '\Magento\Framework\App\CacheInterface',
-            [],
-            '',
-            false,
-            true,
-            true,
-            ['clean']
-        );
-
-        $this->frontCache = $this->getMockForAbstractClass(
-            '\Magento\Framework\Cache\FrontendInterface',
-            [],
-            '',
-            false,
-            true,
-            true,
-            ['clean']
-        );
-
-        $this->poolMock = $this->getMock(
-            '\Magento\Framework\App\Cache\Type\FrontendPool',
-            ['get'],
-            ['clean'],
-            '',
-            false
-        );
-
-        $this->model = new \Magento\PageCache\Model\Indexer\CatalogRulePlugin(
-            $this->configMock,
-            $this->cacheMock,
-            $this->poolMock
-        );
-    }
-
-    public function testAfterExecuteFull()
-    {
-        $this->configMock->expects($this->once())
-            ->method('isEnabled')
-            ->willReturn(true);
-        $this->poolMock->expects($this->once())
-            ->method('get')
-            ->with(\Magento\PageCache\Model\Cache\Type::TYPE_IDENTIFIER)
-            ->willReturn($this->frontCache);
-        $this->frontCache->expects($this->once())->method('clean')
-            ->with(
-                \Zend_Cache::CLEANING_MODE_ALL,
-                [
-                    \Magento\Catalog\Model\Category::CACHE_TAG,
-                    \Magento\Catalog\Model\Product::CACHE_TAG
-                ]
-            );
-        $this->cacheMock->expects($this->once())
-            ->method('clean')
-            ->with(
-                [
-                    \Magento\Catalog\Model\Category::CACHE_TAG,
-                    \Magento\Catalog\Model\Product::CACHE_TAG,
-                    \Magento\Catalog\Model\Product\Compare\Item::CACHE_TAG,
-                    \Magento\Wishlist\Model\Wishlist::CACHE_TAG
-                ]
-            );
-
-        $this->model->afterExecuteFull(
-            $this->getMockForAbstractClass(
-                '\Magento\CatalogRule\Model\Indexer\AbstractIndexer',
-                [],
-                '',
-                false
-            )
-        );
-    }
-}
-- 
GitLab