![]() Server : Apache System : Linux server2.corals.io 4.18.0-348.2.1.el8_5.x86_64 #1 SMP Mon Nov 15 09:17:08 EST 2021 x86_64 User : corals ( 1002) PHP Version : 7.4.33 Disable Function : exec,passthru,shell_exec,system Directory : /home/corals/old/vendor/magento/module-catalog/Model/Indexer/Product/Flat/ |
<?php /** * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\Catalog\Model\Indexer\Product\Flat; use Magento\Catalog\Api\Data\ProductInterface; use Magento\Framework\App\ResourceConnection; use Magento\Framework\EntityManager\MetadataPool; /** * Abstract action reindex class * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ abstract class AbstractAction { /** * Suffix for value field on composite attributes * * @var string */ protected $_valueFieldSuffix = '_value'; /** * Suffix for drop table (uses on flat table rename) * * @var string */ protected $_tableDropSuffix = '_drop_indexer'; /** * @var \Magento\Store\Model\StoreManagerInterface */ protected $_storeManager; /** * @var \Magento\Catalog\Helper\Product\Flat\Indexer */ protected $_productIndexerHelper; /** * @var \Magento\Framework\DB\Adapter\AdapterInterface */ protected $_connection; /** * @var \Magento\Catalog\Model\Product\Type */ protected $_productType; /** * Existing flat tables flags pool * * @var array */ protected $_flatTablesExist = []; /** * List of product types available in installation * * @var array */ protected $_productTypes = []; /** * @var TableBuilder */ protected $_tableBuilder; /** * @var FlatTableBuilder */ protected $_flatTableBuilder; /** * @var MetadataPool */ private $metadataPool; /** * @param \Magento\Framework\App\ResourceConnection $resource * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\Catalog\Helper\Product\Flat\Indexer $productHelper * @param \Magento\Catalog\Model\Product\Type $productType * @param TableBuilder $tableBuilder * @param FlatTableBuilder $flatTableBuilder */ public function __construct( \Magento\Framework\App\ResourceConnection $resource, \Magento\Store\Model\StoreManagerInterface $storeManager, \Magento\Catalog\Helper\Product\Flat\Indexer $productHelper, \Magento\Catalog\Model\Product\Type $productType, TableBuilder $tableBuilder, FlatTableBuilder $flatTableBuilder ) { $this->_storeManager = $storeManager; $this->_productIndexerHelper = $productHelper; $this->_productType = $productType; $this->_connection = $resource->getConnection(); $this->_tableBuilder = $tableBuilder; $this->_flatTableBuilder = $flatTableBuilder; } /** * Execute action for given ids * * @param array|int $ids * @return \Magento\Catalog\Model\Indexer\Product\Flat\AbstractAction */ abstract public function execute($ids); /** * Return temporary table name by regular table name * * @param string $tableName * @return string */ protected function _getTemporaryTableName($tableName) { return sprintf('%s_tmp_indexer', $tableName); } /** * Drop temporary tables created by reindex process * * @param array $tablesList * @param int|string $storeId * @return void * @SuppressWarnings(PHPMD.UnusedLocalVariable) */ protected function _cleanOnFailure(array $tablesList, $storeId) { foreach ($tablesList as $table => $columns) { $this->_connection->dropTemporaryTable($table); } $tableName = $this->_getTemporaryTableName($this->_productIndexerHelper->getFlatTableName($storeId)); $this->_connection->dropTable($tableName); } /** * Rebuild catalog flat index from scratch * * @param int $storeId * @param array $changedIds * @return void * @throws \Exception */ protected function _reindex($storeId, array $changedIds = []) { try { $this->_tableBuilder->build($storeId, $changedIds, $this->_valueFieldSuffix); $this->_flatTableBuilder->build( $storeId, $changedIds, $this->_valueFieldSuffix, $this->_tableDropSuffix, true ); $this->_updateRelationProducts($storeId, $changedIds); $this->_cleanRelationProducts($storeId); } catch (\Exception $e) { $attributes = $this->_productIndexerHelper->getAttributes(); $eavAttributes = $this->_productIndexerHelper->getTablesStructure($attributes); $this->_cleanOnFailure($eavAttributes, $storeId); throw $e; } } /** * Retrieve Product Type Instances as key - type code, value - instance model * * @return array */ protected function _getProductTypeInstances() { if ($this->_productTypes === null) { $this->_productTypes = []; $productEmulator = new \Magento\Framework\DataObject(); foreach (array_keys($this->_productType->getTypes()) as $typeId) { $productEmulator->setTypeId($typeId); $this->_productTypes[$typeId] = $this->_productType->factory($productEmulator); } } return $this->_productTypes; } /** * Update relation products * * @param int $storeId * @param int|array $productIds Update child product(s) only * @return \Magento\Catalog\Model\Indexer\Product\Flat\AbstractAction * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ protected function _updateRelationProducts($storeId, $productIds = null) { if (!$this->_productIndexerHelper->isAddChildData() || !$this->_isFlatTableExists($storeId)) { return $this; } $metadata = $this->getMetadataPool()->getMetadata(ProductInterface::class); foreach ($this->_getProductTypeInstances() as $typeInstance) { /** @var $typeInstance \Magento\Catalog\Model\Product\Type\AbstractType */ if (!$typeInstance->isComposite(null)) { continue; } $relation = $typeInstance->getRelationInfo(); if ($relation && $relation->getTable() && $relation->getParentFieldName() && $relation->getChildFieldName() ) { $columns = $this->_productIndexerHelper->getFlatColumns(); $fieldList = array_keys($columns); unset( $columns['entity_id'], $columns['child_id'], $columns['is_child'] ); /** @var $select \Magento\Framework\DB\Select */ $select = $this->_connection->select()->from( ['t' => $this->_productIndexerHelper->getTable($relation->getTable())], ['entity_table.entity_id', $relation->getChildFieldName(), new \Zend_Db_Expr('1')] )->join( ['entity_table' => $this->_productIndexerHelper->getTable('catalog_product_entity')], "entity_table.{$metadata->getLinkField()} = t.{$relation->getParentFieldName()}", [] )->join( ['e' => $this->_productIndexerHelper->getFlatTableName($storeId)], "e.entity_id = t.{$relation->getChildFieldName()}", array_keys($columns) ); if ($relation->getWhere() !== null) { $select->where($relation->getWhere()); } if (!empty($productIds)) { $cond = [ $this->_connection->quoteInto("{$relation->getChildFieldName()} IN(?)", $productIds), $this->_connection->quoteInto('entity_table.entity_id IN(?)', $productIds), ]; $select->where(implode(' OR ', $cond)); } $sql = $select->insertFromSelect($this->_productIndexerHelper->getFlatTableName($storeId), $fieldList); $this->_connection->query($sql); } } return $this; } /** * Clean unused relation products * * @param int $storeId * @return \Magento\Catalog\Model\Indexer\Product\Flat\AbstractAction * * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ protected function _cleanRelationProducts($storeId) { if (!$this->_productIndexerHelper->isAddChildData() || !$this->_isFlatTableExists($storeId)) { return $this; } $metadata = $this->getMetadataPool()->getMetadata(ProductInterface::class); foreach ($this->_getProductTypeInstances() as $typeInstance) { /** @var $typeInstance \Magento\Catalog\Model\Product\Type\AbstractType */ if (!$typeInstance->isComposite(null)) { continue; } $relation = $typeInstance->getRelationInfo(); if ($relation && $relation->getTable() && $relation->getParentFieldName() && $relation->getChildFieldName() ) { $select = $this->_connection->select()->distinct( true )->from( $this->_productIndexerHelper->getTable($relation->getTable()), $relation->getParentFieldName() ); $joinLeftCond = [ "e.{$metadata->getLinkField()} = t.{$relation->getParentFieldName()}", "e.child_id = t.{$relation->getChildFieldName()}", ]; if ($relation->getWhere() !== null) { $select->where($relation->getWhere()); $joinLeftCond[] = $relation->getWhere(); } $entitySelect = new \Zend_Db_Expr($select->__toString()); /** @var $select \Magento\Framework\DB\Select */ $select = $this->_connection->select()->from( ['e' => $this->_productIndexerHelper->getFlatTableName($storeId)], null )->joinLeft( ['t' => $this->_productIndexerHelper->getTable($relation->getTable())], implode(' AND ', $joinLeftCond), [] )->where( 'e.is_child = ?', 1 )->where( "e.{$metadata->getLinkField()} IN(?)", $entitySelect )->where( "t.{$relation->getChildFieldName()} IS NULL" ); $sql = $select->deleteFromSelect('e'); $this->_connection->query($sql); } } return $this; } /** * Check is flat table for store exists * * @param int $storeId * @return bool */ protected function _isFlatTableExists($storeId) { if (!isset($this->_flatTablesExist[$storeId])) { $tableName = $this->_productIndexerHelper->getFlatTableName($storeId); $isTableExists = $this->_connection->isTableExists($tableName); $this->_flatTablesExist[$storeId] = $isTableExists ? true : false; } return $this->_flatTablesExist[$storeId]; } /** * Get Metadata Pool * * @return \Magento\Framework\EntityManager\MetadataPool */ private function getMetadataPool() { if (null === $this->metadataPool) { $this->metadataPool = \Magento\Framework\App\ObjectManager::getInstance() ->get(\Magento\Framework\EntityManager\MetadataPool::class); } return $this->metadataPool; } }