diff --git a/app/code/Magento/Catalog/Model/Indexer/Product/Flat/Action/Row.php b/app/code/Magento/Catalog/Model/Indexer/Product/Flat/Action/Row.php index b5dbdb68606ff..709f27d031ebe 100644 --- a/app/code/Magento/Catalog/Model/Indexer/Product/Flat/Action/Row.php +++ b/app/code/Magento/Catalog/Model/Indexer/Product/Flat/Action/Row.php @@ -61,6 +61,7 @@ public function __construct( * @param int|null $id * @return \Magento\Catalog\Model\Indexer\Product\Flat\Action\Row * @throws \Magento\Framework\Exception\LocalizedException + * @throws \Zend_Db_Statement_Exception */ public function execute($id = null) { @@ -75,17 +76,43 @@ public function execute($id = null) if ($tableExists) { $this->flatItemEraser->removeDeletedProducts($ids, $store->getId()); } - if (isset($ids[0])) { - if (!$tableExists) { - $this->_flatTableBuilder->build( - $store->getId(), - [$ids[0]], - $this->_valueFieldSuffix, - $this->_tableDropSuffix, - false - ); + + /* @var $status \Magento\Eav\Model\Entity\Attribute */ + $status = $this->_productIndexerHelper->getAttribute('status'); + $statusTable = $status->getBackend()->getTable(); + $statusConditions = [ + 'store_id IN(0,' . (int)$store->getId() . ')', + 'attribute_id = ' . (int)$status->getId(), + 'entity_id = ' . (int)$id + ]; + $select = $this->_connection->select(); + $select->from( + $statusTable, + ['value'] + )->where( + implode(' AND ', $statusConditions) + )->order( + 'store_id DESC' + ); + $result = $this->_connection->query($select); + $status = $result->fetch(1); + + if ($status['value'] == \Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED) { + if (isset($ids[0])) { + if (!$tableExists) { + $this->_flatTableBuilder->build( + $store->getId(), + [$ids[0]], + $this->_valueFieldSuffix, + $this->_tableDropSuffix, + false + ); + } + $this->flatItemWriter->write($store->getId(), $ids[0], $this->_valueFieldSuffix); } - $this->flatItemWriter->write($store->getId(), $ids[0], $this->_valueFieldSuffix); + } + if ($status['value'] == \Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_DISABLED) { + $this->flatItemEraser->deleteProductsFromStore($id, $store->getId()); } } return $this; diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Flat/Action/RowTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Flat/Action/RowTest.php index 41b3d36227431..2572356cf855d 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Flat/Action/RowTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Flat/Action/RowTest.php @@ -10,6 +10,9 @@ use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +/** + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ class RowTest extends \PHPUnit\Framework\TestCase { /** @@ -61,6 +64,8 @@ protected function setUp() { $objectManager = new ObjectManager($this); + $attributeTable = 'catalog_product_entity_int'; + $statusId = 22; $this->connection = $this->createMock(\Magento\Framework\DB\Adapter\AdapterInterface::class); $this->resource = $this->createMock(\Magento\Framework\App\ResourceConnection::class); $this->resource->expects($this->any())->method('getConnection') @@ -70,10 +75,36 @@ protected function setUp() $this->store = $this->createMock(\Magento\Store\Model\Store::class); $this->store->expects($this->any())->method('getId')->will($this->returnValue('store_id_1')); $this->storeManager->expects($this->any())->method('getStores')->will($this->returnValue([$this->store])); - $this->productIndexerHelper = $this->createMock(\Magento\Catalog\Helper\Product\Flat\Indexer::class); $this->flatItemEraser = $this->createMock(\Magento\Catalog\Model\Indexer\Product\Flat\Action\Eraser::class); $this->flatItemWriter = $this->createMock(\Magento\Catalog\Model\Indexer\Product\Flat\Action\Indexer::class); $this->flatTableBuilder = $this->createMock(\Magento\Catalog\Model\Indexer\Product\Flat\FlatTableBuilder::class); + $this->productIndexerHelper = $this->createMock(\Magento\Catalog\Helper\Product\Flat\Indexer::class); + $statusAttributeMock = $this->getMockBuilder(\Magento\Eav\Model\Entity\Attribute::class) + ->disableOriginalConstructor() + ->getMock(); + $this->productIndexerHelper->expects($this->any())->method('getAttribute') + ->with('status') + ->willReturn($statusAttributeMock); + $backendMock = $this->getMockBuilder(\Magento\Eav\Model\Entity\Attribute\Backend\AbstractBackend::class) + ->disableOriginalConstructor() + ->getMock(); + $backendMock->expects($this->any())->method('getTable')->willReturn($attributeTable); + $statusAttributeMock->expects($this->any())->method('getBackend')->willReturn( + $backendMock + ); + $statusAttributeMock->expects($this->any())->method('getId')->willReturn($statusId); + $selectMock = $this->getMockBuilder(\Magento\Framework\DB\Select::class) + ->disableOriginalConstructor() + ->getMock(); + $this->connection->expects($this->any())->method('select')->willReturn($selectMock); + $selectMock->expects($this->any())->method('from')->with( + $attributeTable, + ['value'] + )->willReturnSelf(); + $selectMock->expects($this->any())->method('where')->willReturnSelf(); + $pdoMock = $this->createMock(\Zend_Db_Statement_Pdo::class); + $this->connection->expects($this->any())->method('query')->with($selectMock)->will($this->returnValue($pdoMock)); + $pdoMock->expects($this->any())->method('fetch')->will($this->returnValue(['value' => 1])); $this->model = $objectManager->getObject( \Magento\Catalog\Model\Indexer\Product\Flat\Action\Row::class, [ @@ -82,7 +113,7 @@ protected function setUp() 'productHelper' => $this->productIndexerHelper, 'flatItemEraser' => $this->flatItemEraser, 'flatItemWriter' => $this->flatItemWriter, - 'flatTableBuilder' => $this->flatTableBuilder + 'flatTableBuilder' => $this->flatTableBuilder, ]); }