| Current Path : /var/www/www.indacotrentino.com/www/vendor/magento/module-catalog/Helper/Product/Flat/ |
| Current File : /var/www/www.indacotrentino.com/www/vendor/magento/module-catalog/Helper/Product/Flat/Indexer.php |
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\Catalog\Helper\Product\Flat;
use Magento\Framework\App\ResourceConnection;
use Magento\Framework\ObjectManager\ResetAfterRequestInterface;
/**
* Catalog Product Flat Indexer Helper
*
* @api
* @SuppressWarnings(PHPMD.TooManyFields)
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
* @since 100.0.2
*/
class Indexer extends \Magento\Framework\App\Helper\AbstractHelper implements ResetAfterRequestInterface
{
/**
* Path to list of attributes used for flat indexer
*/
public const XML_NODE_ATTRIBUTE_NODES = 'global/catalog/product/flat/attribute_groups';
/**
* Size of ids batch for reindex
*/
public const BATCH_SIZE = 500;
/**
* Resource instance
*
* @var \Magento\Framework\App\ResourceConnection
*/
protected $_resource;
/**
* @var array
*/
protected $_columns;
/**
* List of indexes uses in flat product table
*
* @var null|array
*/
protected $_indexes;
/**
* Retrieve catalog product flat columns array in old format (used before MMDB support)
*
* @var array
*/
protected $_attributes;
/**
* Required system attributes for preload
*
* @var array
*/
protected $_systemAttributes = ['status', 'required_options', 'tax_class_id', 'weight'];
/**
* EAV Config instance
*
* @var \Magento\Eav\Model\Config
*/
protected $_eavConfig;
/**
* @var \Magento\Catalog\Model\Attribute\Config
*/
protected $_attributeConfig;
/**
* @var array
*/
protected $_attributeCodes;
/**
* @var int
*/
protected $_entityTypeId;
/**
* @var \Magento\Catalog\Model\ResourceModel\Config
*/
protected $_catalogConfig;
/**
* @var array
*/
protected $_flatAttributeGroups = [];
/**
* @var \Magento\Catalog\Model\ResourceModel\ConfigFactory
*/
protected $_configFactory;
/**
* @var \Magento\Eav\Model\Entity\AttributeFactory
*/
protected $_attributeFactory;
/**
* @var \Magento\Store\Model\StoreManagerInterface
*/
protected $_storeManager;
/**
* @var bool
*/
protected $_addFilterableAttrs;
/**
* @var bool
*/
protected $_addChildData;
/**
* @var \Magento\Framework\Mview\View\Changelog
*/
protected $_changelog;
/**
* @param \Magento\Framework\App\Helper\Context $context
* @param \Magento\Framework\App\ResourceConnection $resource
* @param \Magento\Eav\Model\Config $eavConfig
* @param \Magento\Catalog\Model\Attribute\Config $attributeConfig
* @param \Magento\Catalog\Model\ResourceModel\ConfigFactory $configFactory
* @param \Magento\Eav\Model\Entity\AttributeFactory $attributeFactory
* @param \Magento\Store\Model\StoreManagerInterface $storeManager
* @param \Magento\Framework\Mview\View\Changelog $changelog
* @param bool $addFilterableAttrs
* @param bool $addChildData
* @param array $flatAttributeGroups
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
*/
public function __construct(
\Magento\Framework\App\Helper\Context $context,
\Magento\Framework\App\ResourceConnection $resource,
\Magento\Eav\Model\Config $eavConfig,
\Magento\Catalog\Model\Attribute\Config $attributeConfig,
\Magento\Catalog\Model\ResourceModel\ConfigFactory $configFactory,
\Magento\Eav\Model\Entity\AttributeFactory $attributeFactory,
\Magento\Store\Model\StoreManagerInterface $storeManager,
\Magento\Framework\Mview\View\Changelog $changelog,
$addFilterableAttrs = false,
$addChildData = false,
$flatAttributeGroups = []
) {
$this->_configFactory = $configFactory;
$this->_resource = $resource;
$this->_eavConfig = $eavConfig;
$this->_attributeConfig = $attributeConfig;
$this->_attributeFactory = $attributeFactory;
$this->_flatAttributeGroups = $flatAttributeGroups;
$this->_storeManager = $storeManager;
$this->_changelog = $changelog;
$this->_addFilterableAttrs = $addFilterableAttrs;
$this->_addChildData = $addChildData;
parent::__construct($context);
}
/**
* Retrieve catalog product flat columns array in DDL format
*
* @return array
*/
public function getFlatColumnsDdlDefinition()
{
$columns = [];
$columns['entity_id'] = [
'type' => \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER,
'length' => null,
'unsigned' => true,
'nullable' => false,
'default' => false,
'primary' => true,
'comment' => 'Entity Id',
];
if ($this->isAddChildData()) {
$columns['child_id'] = [
'type' => \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER,
'length' => null,
'unsigned' => true,
'nullable' => true,
'default' => null,
'primary' => true,
'comment' => 'Child Id',
];
$columns['is_child'] = [
'type' => \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT,
'length' => 1,
'unsigned' => true,
'nullable' => false,
'default' => '0',
'comment' => 'Checks If Entity Is Child',
];
}
$columns['attribute_set_id'] = [
'type' => \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT,
'length' => 5,
'unsigned' => true,
'nullable' => false,
'default' => '0',
'comment' => 'Attribute Set ID',
];
$columns['type_id'] = [
'type' => \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
'length' => 32,
'unsigned' => false,
'nullable' => false,
'default' => \Magento\Catalog\Model\Product\Type::DEFAULT_TYPE,
'comment' => 'Type Id',
];
return $columns;
}
/**
* Check whether filterable attributes should be added
*
* @return bool
*/
public function isAddFilterableAttributes()
{
return $this->_addFilterableAttrs;
}
/**
* Check whether child data should be added
*
* @return bool
*/
public function isAddChildData()
{
return $this->_addChildData;
}
/**
* Retrieve catalog product flat table columns array
*
* @return array
*/
public function getFlatColumns()
{
if ($this->_columns === null) {
$this->_columns = $this->getFlatColumnsDdlDefinition();
foreach ($this->getAttributes() as $attribute) {
/** @var $attribute \Magento\Eav\Model\Entity\Attribute\AbstractAttribute */
$columns = $attribute->setFlatAddFilterableAttributes(
$this->isAddFilterableAttributes()
)->setFlatAddChildData(
$this->isAddChildData()
)->getFlatColumns();
if ($columns !== null) {
// phpcs:ignore Magento2.Performance.ForeachArrayMerge
$this->_columns = array_merge($this->_columns, $columns);
}
}
}
return $this->_columns;
}
/**
* Retrieve entity type
*
* @return string
*/
public function getEntityType()
{
return \Magento\Catalog\Model\Product::ENTITY;
}
/**
* Retrieve Catalog Entity Type Id
*
* @return int
*/
public function getEntityTypeId()
{
if ($this->_entityTypeId === null) {
$this->_entityTypeId = $this->_configFactory->create()->getEntityTypeId();
}
return $this->_entityTypeId;
}
/**
* Retrieve attribute objects for flat
*
* @return array
*/
public function getAttributes()
{
if ($this->_attributes === null) {
$this->_attributes = [];
$attributeCodes = $this->getAttributeCodes();
$entity = $this->_eavConfig->getEntityType($this->getEntityType())->getEntity();
foreach ($attributeCodes as $attributeCode) {
$attribute = $this->_eavConfig->getAttribute(
$this->getEntityType(),
$attributeCode
)->setEntity(
$entity
);
try {
// check if exists source and backend model.
// To prevent exception when some module was disabled
$attribute->usesSource() && $attribute->getSource();
$attribute->getBackend();
$this->_attributes[$attributeCode] = $attribute;
} catch (\Exception $e) {
$this->_logger->critical($e);
}
}
}
return $this->_attributes;
}
/**
* Retrieve attribute codes using for flat
*
* @return array
*/
public function getAttributeCodes()
{
if ($this->_attributeCodes === null) {
$connection = $this->_resource->getConnection();
$this->_attributeCodes = [];
foreach ($this->_flatAttributeGroups as $attributeGroupName) {
$attributes = $this->_attributeConfig->getAttributeNames($attributeGroupName);
// phpcs:ignore Magento2.Performance.ForeachArrayMerge
$this->_systemAttributes = array_unique(array_merge($attributes, $this->_systemAttributes));
}
$bind = [
'backend_type' => \Magento\Eav\Model\Entity\Attribute\AbstractAttribute::TYPE_STATIC,
'entity_type_id' => $this->getEntityTypeId(),
];
$select = $connection->select()->from(
['main_table' => $this->getTable('eav_attribute')]
)->join(
['additional_table' => $this->getTable('catalog_eav_attribute')],
'additional_table.attribute_id = main_table.attribute_id'
)->where(
'main_table.entity_type_id = :entity_type_id'
);
$whereCondition = [
'main_table.backend_type = :backend_type',
$connection->quoteInto('additional_table.is_used_for_promo_rules = ?', 1),
$connection->quoteInto('additional_table.used_in_product_listing = ?', 1),
$connection->quoteInto('additional_table.used_for_sort_by = ?', 1),
$connection->quoteInto('main_table.attribute_code IN(?)', $this->_systemAttributes),
];
if ($this->isAddFilterableAttributes()) {
$whereCondition[] = $connection->quoteInto('additional_table.is_filterable > ?', 0);
}
$select->where(implode(' OR ', $whereCondition));
$attributesData = $connection->fetchAll($select, $bind);
$this->_eavConfig->importAttributesData($this->getEntityType(), $attributesData);
foreach ($attributesData as $data) {
$this->_attributeCodes[$data['attribute_id']] = $data['attribute_code'];
}
unset($attributesData);
}
return $this->_attributeCodes;
}
/**
* Retrieve catalog product flat table indexes array
*
* @return array
*/
public function getFlatIndexes()
{
if ($this->_indexes === null) {
$this->_indexes = [];
if ($this->isAddChildData()) {
$this->_indexes['PRIMARY'] = [
'type' => \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_PRIMARY,
'fields' => ['entity_id', 'child_id'],
];
$this->_indexes['IDX_CHILD'] = [
'type' => \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_INDEX,
'fields' => ['child_id'],
];
$this->_indexes['IDX_IS_CHILD'] = [
'type' => \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_INDEX,
'fields' => ['entity_id', 'is_child'],
];
} else {
$this->_indexes['PRIMARY'] = [
'type' => \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_PRIMARY,
'fields' => ['entity_id'],
];
}
$this->_indexes['IDX_TYPE_ID'] = [
'type' => \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_INDEX,
'fields' => ['type_id'],
];
$this->_indexes['IDX_ATTRIBUTE_SET'] = [
'type' => \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_INDEX,
'fields' => ['attribute_set_id'],
];
foreach ($this->getAttributes() as $attribute) {
/** @var $attribute \Magento\Eav\Model\Entity\Attribute */
$indexes = $attribute->setFlatAddFilterableAttributes(
$this->isAddFilterableAttributes()
)->setFlatAddChildData(
$this->isAddChildData()
)->getFlatIndexes();
if ($indexes !== null) {
// phpcs:ignore Magento2.Performance.ForeachArrayMerge
$this->_indexes = array_merge($this->_indexes, $indexes);
}
}
}
return $this->_indexes;
}
/**
* Get table structure for temporary eav tables
*
* @param array $attributes
* @return array
*/
public function getTablesStructure(array $attributes)
{
$eavAttributes = [];
$flatColumnsList = $this->getFlatColumns();
/** @var $attribute \Magento\Catalog\Model\ResourceModel\Eav\Attribute */
foreach ($attributes as $attribute) {
$eavTable = $attribute->getBackend()->getTable();
$attributeCode = $attribute->getAttributeCode();
if (isset($flatColumnsList[$attributeCode])) {
$eavAttributes[$eavTable][$attributeCode] = $attribute;
}
}
return $eavAttributes;
}
/**
* Returns table name
*
* @param string|array $name
* @return string
*/
public function getTable($name)
{
return $this->_resource->getTableName($name);
}
/**
* Retrieve Catalog Product Flat Table name
*
* @param int $storeId
* @return string
*/
public function getFlatTableName($storeId)
{
return sprintf('%s_%s', $this->getTable('catalog_product_flat'), $storeId);
}
/**
* Retrieve loaded attribute by code
*
* @param string $attributeCode
* @throws \Magento\Framework\Exception\LocalizedException
* @return \Magento\Eav\Model\Entity\Attribute
*/
public function getAttribute($attributeCode)
{
$attributes = $this->getAttributes();
if (!isset($attributes[$attributeCode])) {
$attribute = $this->_attributeFactory->create();
$attribute->loadByCode($this->getEntityTypeId(), $attributeCode);
if (!$attribute->getId()) {
throw new \Magento\Framework\Exception\LocalizedException(__('Invalid attribute %1', $attributeCode));
}
$entity = $this->_eavConfig->getEntityType($this->getEntityType())->getEntity();
$attribute->setEntity($entity);
return $attribute;
}
return $attributes[$attributeCode];
}
/**
* Delete all product flat tables for not existing stores
*
* @return void
*/
public function deleteAbandonedStoreFlatTables()
{
$connection = $this->_resource->getConnection();
$existentTables = $connection->getTables($connection->getTableName('catalog_product_flat_%'));
$this->_changelog->setViewId('catalog_product_flat');
foreach ($existentTables as $key => $tableName) {
if ($this->_changelog->getName() == $tableName) {
unset($existentTables[$key]);
}
}
$actualStoreTables = [];
foreach ($this->_storeManager->getStores() as $store) {
$actualStoreTables[] = $this->getFlatTableName($store->getId());
}
$tablesToDelete = array_diff($existentTables, $actualStoreTables);
foreach ($tablesToDelete as $table) {
$connection->dropTable($table);
}
}
/**
* @inheritDoc
*/
public function _resetState(): void
{
$this->_entityTypeId = null;
$this->_flatAttributeGroups = [];
}
}