Find this useful? Enter your email to receive occasional updates for securing PHP code.
Signing you up...
Thank you for signing up!
PHP Decode
<?php /** * Copyright Magento, Inc. All rights reserved. * See COPYING.txt for license ..
Decoded Output download
<?php
/**
* Copyright Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\Catalog\Model\ResourceModel\Product\Indexer\Eav;
use Magento\Catalog\Model\Product\Attribute\Source\Status as ProductStatus;
use Magento\Catalog\Api\Data\ProductInterface;
use Magento\Catalog\Api\Data\ProductAttributeInterface;
use Magento\Catalog\Model\ResourceModel\Helper;
use Magento\Eav\Api\AttributeRepositoryInterface;
use Magento\Eav\Model\Config;
use Magento\Framework\Api\SearchCriteriaBuilder;
use Magento\Framework\DB\Select;
use Magento\Framework\DB\Sql\UnionExpression;
use Magento\Framework\EntityManager\MetadataPool;
use Magento\Framework\Event\ManagerInterface;
use Magento\Framework\Indexer\Table\StrategyInterface;
use Magento\Framework\Model\ResourceModel\Db\Context;
/**
* Catalog Product Eav Select and Multiply Select Attributes Indexer resource model
*
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
class Source extends AbstractEav
{
public const TRANSIT_PREFIX = 'transit_';
/**
* Catalog resource helper
*
* @var \Magento\Catalog\Model\ResourceModel\Helper
*/
protected $_resourceHelper;
/**
* @var \Magento\Eav\Api\AttributeRepositoryInterface
*/
private $attributeRepository;
/**
* @var \Magento\Framework\Api\SearchCriteriaBuilder
*/
private $criteriaBuilder;
/**
* Construct
*
* @param Context $context
* @param StrategyInterface $tableStrategy
* @param Config $eavConfig
* @param ManagerInterface $eventManager
* @param Helper $resourceHelper
* @param null|string $connectionName
* @param AttributeRepositoryInterface|null $attributeRepository
* @param SearchCriteriaBuilder|null $criteriaBuilder
* @param MetadataPool|null $metadataPool
*/
public function __construct(
\Magento\Framework\Model\ResourceModel\Db\Context $context,
\Magento\Framework\Indexer\Table\StrategyInterface $tableStrategy,
\Magento\Eav\Model\Config $eavConfig,
\Magento\Framework\Event\ManagerInterface $eventManager,
\Magento\Catalog\Model\ResourceModel\Helper $resourceHelper,
?string $connectionName = null,
\Magento\Eav\Api\AttributeRepositoryInterface $attributeRepository = null,
\Magento\Framework\Api\SearchCriteriaBuilder $criteriaBuilder = null,
?\Magento\Framework\EntityManager\MetadataPool $metadataPool = null
) {
parent::__construct(
$context,
$tableStrategy,
$eavConfig,
$eventManager,
$connectionName,
$metadataPool
);
$this->_resourceHelper = $resourceHelper;
$this->attributeRepository = $attributeRepository
?: \Magento\Framework\App\ObjectManager::getInstance()
->get(\Magento\Eav\Api\AttributeRepositoryInterface::class);
$this->criteriaBuilder = $criteriaBuilder
?: \Magento\Framework\App\ObjectManager::getInstance()
->get(\Magento\Framework\Api\SearchCriteriaBuilder::class);
}
/**
* @inheritDoc
*/
public function reindexEntities($processIds)
{
$this->clearTemporaryIndexTable();
$this->_prepareIndex($processIds);
$this->_prepareRelationIndex($processIds);
return $this;
}
/**
* Initialize connection and define main index table
*
* @return void
*/
protected function _construct()
{
$this->_init('catalog_product_index_eav', 'entity_id');
}
/**
* Retrieve indexable eav attribute ids
*
* @param bool $multiSelect
* @return array
*/
protected function _getIndexableAttributes($multiSelect)
{
$select = $this->getConnection()->select()->from(
['ca' => $this->getTable('catalog_eav_attribute')],
'attribute_id'
)->join(
['ea' => $this->getTable('eav_attribute')],
'ca.attribute_id = ea.attribute_id',
[]
)->where(
$this->_getIndexableAttributesCondition()
);
if ($multiSelect == true) {
$select->where('ea.backend_type = ?', 'text')->where('ea.frontend_input = ?', 'multiselect');
} else {
$select->where('ea.backend_type = ?', 'int')->where('ea.frontend_input IN( ? )', ['select', 'boolean']);
}
return $this->getConnection()->fetchCol($select);
}
/**
* Prepare data index for indexable attributes
*
* @param array $entityIds the entity ids limitation
* @param int $attributeId the attribute id limitation
* @return $this
*/
protected function _prepareIndex($entityIds = null, $attributeId = null)
{
$this->_prepareSelectIndex($entityIds, $attributeId);
$this->_prepareMultiselectIndex($entityIds, $attributeId);
return $this;
}
/**
* Prepare data index for indexable select attributes
*
* @param array $entityIds the entity ids limitation
* @param int $attributeId the attribute id limitation
* @return $this
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
* @throws \Exception
*/
protected function _prepareSelectIndex($entityIds = null, $attributeId = null)
{
$connection = $this->getConnection();
$idxTable = $this->getIdxTable();
// prepare select attributes
$attrIds = $attributeId === null ? $this->_getIndexableAttributes(false) : [$attributeId];
if (!$attrIds) {
return $this;
}
$productIdField = $this->getMetadataPool()->getMetadata(ProductInterface::class)->getLinkField();
$attrIdsFlat = implode(',', array_map('intval', $attrIds));
$ifNullSql = $connection->getIfNullSql('pis.value', 'COALESCE(ds.value, dd.value)');
/**@var $select Select */
$select = $connection->select()->distinct(true)->from(
['s' => $this->getTable('store')],
[]
)->joinLeft(
['dd' => $this->getTable('catalog_product_entity_int')],
'dd.store_id = 0',
[]
)->joinLeft(
['ds' => $this->getTable('catalog_product_entity_int')],
"ds.store_id = s.store_id AND ds.attribute_id = dd.attribute_id AND " .
"ds.{$productIdField} = dd.{$productIdField}",
[]
)->joinLeft(
['d2d' => $this->getTable('catalog_product_entity_int')],
sprintf(
"d2d.store_id = 0 AND d2d.{$productIdField} = dd.{$productIdField} AND d2d.attribute_id = %s",
$this->_eavConfig->getAttribute(\Magento\Catalog\Model\Product::ENTITY, 'status')->getId()
),
[]
)->joinLeft(
['d2s' => $this->getTable('catalog_product_entity_int')],
"d2s.store_id = s.store_id AND d2s.attribute_id = d2d.attribute_id AND " .
"d2s.{$productIdField} = d2d.{$productIdField}",
[]
)->joinLeft(
['cpe' => $this->getTable('catalog_product_entity')],
"cpe.{$productIdField} = dd.{$productIdField}",
[]
)->joinLeft(
['pis' => $this->getTable('catalog_product_entity_int')],
"pis.{$productIdField} = cpe.{$productIdField} " .
"AND pis.attribute_id = dd.attribute_id AND pis.store_id = s.store_id",
[]
)->where(
's.store_id != 0'
)->where(
'(ds.value IS NOT NULL OR dd.value IS NOT NULL)'
)->where(
(new \Zend_Db_Expr('COALESCE(d2s.value, d2d.value)')) . ' = ' . ProductStatus::STATUS_ENABLED
)->where(
"dd.attribute_id IN({$attrIdsFlat})"
)->where(
'NOT(pis.value IS NULL AND pis.value_id IS NOT NULL)'
)->where(
$ifNullSql . ' IS NOT NULL'
)->columns(
[
'cpe.entity_id',
'dd.attribute_id',
's.store_id',
'value' => new \Zend_Db_Expr('COALESCE(ds.value, dd.value)'),
'cpe.entity_id AS source_id',
]
);
$visibilityCondition = $connection->quoteInto(
'>?',
\Magento\Catalog\Model\Product\Visibility::VISIBILITY_NOT_VISIBLE
);
$this->_addAttributeToSelect(
$select,
'visibility',
"cpe.{$productIdField}",
's.store_id',
$visibilityCondition
);
if ($entityIds !== null) {
$ids = implode(',', array_map('intval', $entityIds));
$selectWithoutDefaultStore = $connection->select()->from(
['wd' => $this->getTable('catalog_product_entity_int')],
[
'cpe.entity_id',
'attribute_id',
'store_id',
'value',
'cpe.entity_id',
]
)->joinLeft(
['cpe' => $this->getTable('catalog_product_entity')],
"cpe.{$productIdField} = wd.{$productIdField}",
[]
)->joinLeft(
['d2d' => $this->getTable('catalog_product_entity_int')],
sprintf(
"d2d.store_id = 0 AND d2d.{$productIdField} = wd.{$productIdField} AND d2d.attribute_id = %s",
$this->_eavConfig->getAttribute(\Magento\Catalog\Model\Product::ENTITY, 'status')->getId()
),
[]
)->joinLeft(
['d2s' => $this->getTable('catalog_product_entity_int')],
"d2s.store_id != 0 AND d2s.attribute_id = d2d.attribute_id AND " .
"d2s.{$productIdField} = d2d.{$productIdField}",
[]
)
->where((new \Zend_Db_Expr('COALESCE(d2s.value, d2d.value)')) . ' = ' . ProductStatus::STATUS_ENABLED)
->where("wd.attribute_id IN({$attrIdsFlat})")
->where('wd.value IS NOT NULL')
->where('wd.store_id != 0')
->where("cpe.entity_id IN({$ids})");
$select->where("cpe.entity_id IN({$ids})");
$this->_addAttributeToSelect(
$selectWithoutDefaultStore,
'visibility',
"cpe.{$productIdField}",
'wd.store_id',
$visibilityCondition
);
$selects = new UnionExpression(
[$select, $selectWithoutDefaultStore],
Select::SQL_UNION,
'( %s )'
);
$select = $connection->select();
$select->from(['u' => $selects]);
}
/**
* Add additional external limitation
*/
$this->_eventManager->dispatch(
'prepare_catalog_product_index_select',
[
'select' => $select,
'entity_field' => new \Zend_Db_Expr('cpe.entity_id'),
'website_field' => new \Zend_Db_Expr('s.website_id'),
'store_field' => new \Zend_Db_Expr('s.store_id'),
]
);
$query = $select->insertFromSelect($idxTable);
$connection->query($query);
return $this;
}
/**
* Prepare data index for indexable multiply select attributes
*
* @param array $entityIds the entity ids limitation
* @param int $attributeId the attribute id limitation
* @return $this
* @throws \Exception
*/
protected function _prepareMultiselectIndex($entityIds = null, $attributeId = null)
{
$connection = $this->getConnection();
// prepare multiselect attributes
$attrIds = $attributeId === null ? $this->_getIndexableAttributes(true) : [$attributeId];
if (!$attrIds) {
return $this;
}
$productIdField = $this->getMetadataPool()->getMetadata(ProductInterface::class)->getLinkField();
// load attribute options
$options = [];
$select = $connection->select()->from(
$this->getTable('eav_attribute_option'),
['attribute_id', 'option_id']
)->where('attribute_id IN(?)', $attrIds);
$query = $select->query();
while ($row = $query->fetch()) {
$options[$row['attribute_id']][$row['option_id']] = true;
}
// Retrieve any custom source model options
$sourceModelOptions = $this->getMultiSelectAttributeWithSourceModels($attrIds);
$options = array_replace_recursive($options, $sourceModelOptions);
// prepare get multiselect values query
$productValueExpression = $connection->getCheckSql('pvs.value_id > 0', 'pvs.value', 'pvd.value');
$select = $connection->select()->from(
['pvd' => $this->getTable('catalog_product_entity_text')],
[]
)->join(
['cs' => $this->getTable('store')],
'',
[]
)->joinLeft(
['pvs' => $this->getTable('catalog_product_entity_text')],
"pvs.{$productIdField} = pvd.{$productIdField} AND pvs.attribute_id = pvd.attribute_id"
. ' AND pvs.store_id=cs.store_id',
[]
)->joinLeft(
['cpe' => $this->getTable('catalog_product_entity')],
"cpe.{$productIdField} = pvd.{$productIdField}",
[]
)->where(
'pvd.store_id=?',
$connection->getIfNullSql('pvs.store_id', \Magento\Store\Model\Store::DEFAULT_STORE_ID)
)->where(
'cs.store_id!=?',
\Magento\Store\Model\Store::DEFAULT_STORE_ID
)->where(
'pvd.attribute_id IN(?)',
$attrIds
)->where(
'cpe.entity_id IS NOT NULL'
)->columns(
[
'entity_id' => 'cpe.entity_id',
'attribute_id' => 'attribute_id',
'store_id' => 'cs.store_id',
'value' => $productValueExpression,
'source_id' => 'cpe.entity_id',
]
);
$statusCond = $connection->quoteInto('=?', ProductStatus::STATUS_ENABLED);
$this->_addAttributeToSelect($select, 'status', "pvd.{$productIdField}", 'cs.store_id', $statusCond);
if ($entityIds !== null) {
$select->where('cpe.entity_id IN(?)', $entityIds, \Zend_Db::INT_TYPE);
}
/**
* Add additional external limitation
*/
$this->_eventManager->dispatch(
'prepare_catalog_product_index_select',
[
'select' => $select,
'entity_field' => new \Zend_Db_Expr('cpe.entity_id'),
'website_field' => new \Zend_Db_Expr('cs.website_id'),
'store_field' => new \Zend_Db_Expr('cs.store_id'),
]
);
$this->_addAttributeToSelect(
$select,
'visibility',
"cpe.{$productIdField}",
'cs.store_id',
$connection->quoteInto('>?', \Magento\Catalog\Model\Product\Visibility::VISIBILITY_NOT_VISIBLE)
);
$this->saveDataFromSelect($select, $options);
return $this;
}
/**
* Get options for multiselect attributes using custom source models
* Based on @maderlock's fix from:
* https://github.com/magento/magento2/issues/417#issuecomment-265146285
*
* @param array $attrIds
*
* @return array
*/
private function getMultiSelectAttributeWithSourceModels($attrIds)
{
// Add options from custom source models
$this->criteriaBuilder
->addFilter('attribute_id', $attrIds, 'in')
->addFilter('source_model', true, 'notnull');
$criteria = $this->criteriaBuilder->create();
$attributes = $this->attributeRepository->getList(
ProductAttributeInterface::ENTITY_TYPE_CODE,
$criteria
)->getItems();
$options = [];
foreach ($attributes as $attribute) {
$sourceModelOptions = $attribute->getOptions();
// Add options to list used below
foreach ($sourceModelOptions as $option) {
$options[$attribute->getAttributeId()][$option->getValue()] = true;
}
}
return $options;
}
/**
* Save a data to temporary source index table
*
* @param array $data
* @return $this
*/
protected function _saveIndexData(array $data)
{
if (!$data) {
return $this;
}
$connection = $this->getConnection();
$connection->insertArray(
$this->getIdxTable(),
['entity_id', 'attribute_id', 'store_id', 'value', 'source_id'],
$data
);
return $this;
}
/**
* Retrieve temporary source index table name
*
* @param string|null $table
* @return string
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function getIdxTable($table = null)
{
return $this->tableStrategy->getTableName('catalog_product_index_eav');
}
/**
* Save data from select
*
* @param Select $select
* @param array $options
* @return void
*/
private function saveDataFromSelect(Select $select, array $options)
{
$i = 0;
$data = [];
$query = $select->query();
while ($row = $query->fetch()) {
$values = isset($row['value']) ? explode(',', $row['value']) : [];
foreach ($values as $valueId) {
if (isset($options[$row['attribute_id']][$valueId])) {
$data[] = [$row['entity_id'], $row['attribute_id'], $row['store_id'], $valueId, $row['source_id']];
$i++;
if ($i % 10000 == 0) {
$this->_saveIndexData($data);
$data = [];
}
}
}
}
$this->_saveIndexData($data);
}
/**
* Prepare data index for product relations
*
* @param array $parentIds the parent entity ids limitation
* @return $this
*/
protected function _prepareRelationIndex($parentIds = null)
{
$connection = $this->getConnection();
$idxTable = $this->getIdxTable();
if (!$this->tableStrategy->getUseIdxTable()) {
$additionalIdxTable = $connection->getTableName(self::TRANSIT_PREFIX . $this->getIdxTable());
$connection->createTemporaryTableLike($additionalIdxTable, $idxTable);
$query = $connection->insertFromSelect(
$this->_prepareRelationIndexSelect($parentIds),
$additionalIdxTable,
[]
);
$connection->query($query);
$select = $connection->select()->from($additionalIdxTable);
$query = $connection->insertFromSelect(
$select,
$idxTable,
[],
\Magento\Framework\DB\Adapter\AdapterInterface::INSERT_IGNORE
);
$connection->query($query);
$connection->dropTemporaryTable($additionalIdxTable);
} else {
$query = $connection->insertFromSelect(
$this->_prepareRelationIndexSelect($parentIds),
$idxTable,
[],
\Magento\Framework\DB\Adapter\AdapterInterface::INSERT_IGNORE
);
$connection->query($query);
}
return $this;
}
}
?>
Did this file decode correctly?
Original Code
<?php
/**
* Copyright Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\Catalog\Model\ResourceModel\Product\Indexer\Eav;
use Magento\Catalog\Model\Product\Attribute\Source\Status as ProductStatus;
use Magento\Catalog\Api\Data\ProductInterface;
use Magento\Catalog\Api\Data\ProductAttributeInterface;
use Magento\Catalog\Model\ResourceModel\Helper;
use Magento\Eav\Api\AttributeRepositoryInterface;
use Magento\Eav\Model\Config;
use Magento\Framework\Api\SearchCriteriaBuilder;
use Magento\Framework\DB\Select;
use Magento\Framework\DB\Sql\UnionExpression;
use Magento\Framework\EntityManager\MetadataPool;
use Magento\Framework\Event\ManagerInterface;
use Magento\Framework\Indexer\Table\StrategyInterface;
use Magento\Framework\Model\ResourceModel\Db\Context;
/**
* Catalog Product Eav Select and Multiply Select Attributes Indexer resource model
*
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
class Source extends AbstractEav
{
public const TRANSIT_PREFIX = 'transit_';
/**
* Catalog resource helper
*
* @var \Magento\Catalog\Model\ResourceModel\Helper
*/
protected $_resourceHelper;
/**
* @var \Magento\Eav\Api\AttributeRepositoryInterface
*/
private $attributeRepository;
/**
* @var \Magento\Framework\Api\SearchCriteriaBuilder
*/
private $criteriaBuilder;
/**
* Construct
*
* @param Context $context
* @param StrategyInterface $tableStrategy
* @param Config $eavConfig
* @param ManagerInterface $eventManager
* @param Helper $resourceHelper
* @param null|string $connectionName
* @param AttributeRepositoryInterface|null $attributeRepository
* @param SearchCriteriaBuilder|null $criteriaBuilder
* @param MetadataPool|null $metadataPool
*/
public function __construct(
\Magento\Framework\Model\ResourceModel\Db\Context $context,
\Magento\Framework\Indexer\Table\StrategyInterface $tableStrategy,
\Magento\Eav\Model\Config $eavConfig,
\Magento\Framework\Event\ManagerInterface $eventManager,
\Magento\Catalog\Model\ResourceModel\Helper $resourceHelper,
?string $connectionName = null,
\Magento\Eav\Api\AttributeRepositoryInterface $attributeRepository = null,
\Magento\Framework\Api\SearchCriteriaBuilder $criteriaBuilder = null,
?\Magento\Framework\EntityManager\MetadataPool $metadataPool = null
) {
parent::__construct(
$context,
$tableStrategy,
$eavConfig,
$eventManager,
$connectionName,
$metadataPool
);
$this->_resourceHelper = $resourceHelper;
$this->attributeRepository = $attributeRepository
?: \Magento\Framework\App\ObjectManager::getInstance()
->get(\Magento\Eav\Api\AttributeRepositoryInterface::class);
$this->criteriaBuilder = $criteriaBuilder
?: \Magento\Framework\App\ObjectManager::getInstance()
->get(\Magento\Framework\Api\SearchCriteriaBuilder::class);
}
/**
* @inheritDoc
*/
public function reindexEntities($processIds)
{
$this->clearTemporaryIndexTable();
$this->_prepareIndex($processIds);
$this->_prepareRelationIndex($processIds);
return $this;
}
/**
* Initialize connection and define main index table
*
* @return void
*/
protected function _construct()
{
$this->_init('catalog_product_index_eav', 'entity_id');
}
/**
* Retrieve indexable eav attribute ids
*
* @param bool $multiSelect
* @return array
*/
protected function _getIndexableAttributes($multiSelect)
{
$select = $this->getConnection()->select()->from(
['ca' => $this->getTable('catalog_eav_attribute')],
'attribute_id'
)->join(
['ea' => $this->getTable('eav_attribute')],
'ca.attribute_id = ea.attribute_id',
[]
)->where(
$this->_getIndexableAttributesCondition()
);
if ($multiSelect == true) {
$select->where('ea.backend_type = ?', 'text')->where('ea.frontend_input = ?', 'multiselect');
} else {
$select->where('ea.backend_type = ?', 'int')->where('ea.frontend_input IN( ? )', ['select', 'boolean']);
}
return $this->getConnection()->fetchCol($select);
}
/**
* Prepare data index for indexable attributes
*
* @param array $entityIds the entity ids limitation
* @param int $attributeId the attribute id limitation
* @return $this
*/
protected function _prepareIndex($entityIds = null, $attributeId = null)
{
$this->_prepareSelectIndex($entityIds, $attributeId);
$this->_prepareMultiselectIndex($entityIds, $attributeId);
return $this;
}
/**
* Prepare data index for indexable select attributes
*
* @param array $entityIds the entity ids limitation
* @param int $attributeId the attribute id limitation
* @return $this
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
* @throws \Exception
*/
protected function _prepareSelectIndex($entityIds = null, $attributeId = null)
{
$connection = $this->getConnection();
$idxTable = $this->getIdxTable();
// prepare select attributes
$attrIds = $attributeId === null ? $this->_getIndexableAttributes(false) : [$attributeId];
if (!$attrIds) {
return $this;
}
$productIdField = $this->getMetadataPool()->getMetadata(ProductInterface::class)->getLinkField();
$attrIdsFlat = implode(',', array_map('intval', $attrIds));
$ifNullSql = $connection->getIfNullSql('pis.value', 'COALESCE(ds.value, dd.value)');
/**@var $select Select */
$select = $connection->select()->distinct(true)->from(
['s' => $this->getTable('store')],
[]
)->joinLeft(
['dd' => $this->getTable('catalog_product_entity_int')],
'dd.store_id = 0',
[]
)->joinLeft(
['ds' => $this->getTable('catalog_product_entity_int')],
"ds.store_id = s.store_id AND ds.attribute_id = dd.attribute_id AND " .
"ds.{$productIdField} = dd.{$productIdField}",
[]
)->joinLeft(
['d2d' => $this->getTable('catalog_product_entity_int')],
sprintf(
"d2d.store_id = 0 AND d2d.{$productIdField} = dd.{$productIdField} AND d2d.attribute_id = %s",
$this->_eavConfig->getAttribute(\Magento\Catalog\Model\Product::ENTITY, 'status')->getId()
),
[]
)->joinLeft(
['d2s' => $this->getTable('catalog_product_entity_int')],
"d2s.store_id = s.store_id AND d2s.attribute_id = d2d.attribute_id AND " .
"d2s.{$productIdField} = d2d.{$productIdField}",
[]
)->joinLeft(
['cpe' => $this->getTable('catalog_product_entity')],
"cpe.{$productIdField} = dd.{$productIdField}",
[]
)->joinLeft(
['pis' => $this->getTable('catalog_product_entity_int')],
"pis.{$productIdField} = cpe.{$productIdField} " .
"AND pis.attribute_id = dd.attribute_id AND pis.store_id = s.store_id",
[]
)->where(
's.store_id != 0'
)->where(
'(ds.value IS NOT NULL OR dd.value IS NOT NULL)'
)->where(
(new \Zend_Db_Expr('COALESCE(d2s.value, d2d.value)')) . ' = ' . ProductStatus::STATUS_ENABLED
)->where(
"dd.attribute_id IN({$attrIdsFlat})"
)->where(
'NOT(pis.value IS NULL AND pis.value_id IS NOT NULL)'
)->where(
$ifNullSql . ' IS NOT NULL'
)->columns(
[
'cpe.entity_id',
'dd.attribute_id',
's.store_id',
'value' => new \Zend_Db_Expr('COALESCE(ds.value, dd.value)'),
'cpe.entity_id AS source_id',
]
);
$visibilityCondition = $connection->quoteInto(
'>?',
\Magento\Catalog\Model\Product\Visibility::VISIBILITY_NOT_VISIBLE
);
$this->_addAttributeToSelect(
$select,
'visibility',
"cpe.{$productIdField}",
's.store_id',
$visibilityCondition
);
if ($entityIds !== null) {
$ids = implode(',', array_map('intval', $entityIds));
$selectWithoutDefaultStore = $connection->select()->from(
['wd' => $this->getTable('catalog_product_entity_int')],
[
'cpe.entity_id',
'attribute_id',
'store_id',
'value',
'cpe.entity_id',
]
)->joinLeft(
['cpe' => $this->getTable('catalog_product_entity')],
"cpe.{$productIdField} = wd.{$productIdField}",
[]
)->joinLeft(
['d2d' => $this->getTable('catalog_product_entity_int')],
sprintf(
"d2d.store_id = 0 AND d2d.{$productIdField} = wd.{$productIdField} AND d2d.attribute_id = %s",
$this->_eavConfig->getAttribute(\Magento\Catalog\Model\Product::ENTITY, 'status')->getId()
),
[]
)->joinLeft(
['d2s' => $this->getTable('catalog_product_entity_int')],
"d2s.store_id != 0 AND d2s.attribute_id = d2d.attribute_id AND " .
"d2s.{$productIdField} = d2d.{$productIdField}",
[]
)
->where((new \Zend_Db_Expr('COALESCE(d2s.value, d2d.value)')) . ' = ' . ProductStatus::STATUS_ENABLED)
->where("wd.attribute_id IN({$attrIdsFlat})")
->where('wd.value IS NOT NULL')
->where('wd.store_id != 0')
->where("cpe.entity_id IN({$ids})");
$select->where("cpe.entity_id IN({$ids})");
$this->_addAttributeToSelect(
$selectWithoutDefaultStore,
'visibility',
"cpe.{$productIdField}",
'wd.store_id',
$visibilityCondition
);
$selects = new UnionExpression(
[$select, $selectWithoutDefaultStore],
Select::SQL_UNION,
'( %s )'
);
$select = $connection->select();
$select->from(['u' => $selects]);
}
/**
* Add additional external limitation
*/
$this->_eventManager->dispatch(
'prepare_catalog_product_index_select',
[
'select' => $select,
'entity_field' => new \Zend_Db_Expr('cpe.entity_id'),
'website_field' => new \Zend_Db_Expr('s.website_id'),
'store_field' => new \Zend_Db_Expr('s.store_id'),
]
);
$query = $select->insertFromSelect($idxTable);
$connection->query($query);
return $this;
}
/**
* Prepare data index for indexable multiply select attributes
*
* @param array $entityIds the entity ids limitation
* @param int $attributeId the attribute id limitation
* @return $this
* @throws \Exception
*/
protected function _prepareMultiselectIndex($entityIds = null, $attributeId = null)
{
$connection = $this->getConnection();
// prepare multiselect attributes
$attrIds = $attributeId === null ? $this->_getIndexableAttributes(true) : [$attributeId];
if (!$attrIds) {
return $this;
}
$productIdField = $this->getMetadataPool()->getMetadata(ProductInterface::class)->getLinkField();
// load attribute options
$options = [];
$select = $connection->select()->from(
$this->getTable('eav_attribute_option'),
['attribute_id', 'option_id']
)->where('attribute_id IN(?)', $attrIds);
$query = $select->query();
while ($row = $query->fetch()) {
$options[$row['attribute_id']][$row['option_id']] = true;
}
// Retrieve any custom source model options
$sourceModelOptions = $this->getMultiSelectAttributeWithSourceModels($attrIds);
$options = array_replace_recursive($options, $sourceModelOptions);
// prepare get multiselect values query
$productValueExpression = $connection->getCheckSql('pvs.value_id > 0', 'pvs.value', 'pvd.value');
$select = $connection->select()->from(
['pvd' => $this->getTable('catalog_product_entity_text')],
[]
)->join(
['cs' => $this->getTable('store')],
'',
[]
)->joinLeft(
['pvs' => $this->getTable('catalog_product_entity_text')],
"pvs.{$productIdField} = pvd.{$productIdField} AND pvs.attribute_id = pvd.attribute_id"
. ' AND pvs.store_id=cs.store_id',
[]
)->joinLeft(
['cpe' => $this->getTable('catalog_product_entity')],
"cpe.{$productIdField} = pvd.{$productIdField}",
[]
)->where(
'pvd.store_id=?',
$connection->getIfNullSql('pvs.store_id', \Magento\Store\Model\Store::DEFAULT_STORE_ID)
)->where(
'cs.store_id!=?',
\Magento\Store\Model\Store::DEFAULT_STORE_ID
)->where(
'pvd.attribute_id IN(?)',
$attrIds
)->where(
'cpe.entity_id IS NOT NULL'
)->columns(
[
'entity_id' => 'cpe.entity_id',
'attribute_id' => 'attribute_id',
'store_id' => 'cs.store_id',
'value' => $productValueExpression,
'source_id' => 'cpe.entity_id',
]
);
$statusCond = $connection->quoteInto('=?', ProductStatus::STATUS_ENABLED);
$this->_addAttributeToSelect($select, 'status', "pvd.{$productIdField}", 'cs.store_id', $statusCond);
if ($entityIds !== null) {
$select->where('cpe.entity_id IN(?)', $entityIds, \Zend_Db::INT_TYPE);
}
/**
* Add additional external limitation
*/
$this->_eventManager->dispatch(
'prepare_catalog_product_index_select',
[
'select' => $select,
'entity_field' => new \Zend_Db_Expr('cpe.entity_id'),
'website_field' => new \Zend_Db_Expr('cs.website_id'),
'store_field' => new \Zend_Db_Expr('cs.store_id'),
]
);
$this->_addAttributeToSelect(
$select,
'visibility',
"cpe.{$productIdField}",
'cs.store_id',
$connection->quoteInto('>?', \Magento\Catalog\Model\Product\Visibility::VISIBILITY_NOT_VISIBLE)
);
$this->saveDataFromSelect($select, $options);
return $this;
}
/**
* Get options for multiselect attributes using custom source models
* Based on @maderlock's fix from:
* https://github.com/magento/magento2/issues/417#issuecomment-265146285
*
* @param array $attrIds
*
* @return array
*/
private function getMultiSelectAttributeWithSourceModels($attrIds)
{
// Add options from custom source models
$this->criteriaBuilder
->addFilter('attribute_id', $attrIds, 'in')
->addFilter('source_model', true, 'notnull');
$criteria = $this->criteriaBuilder->create();
$attributes = $this->attributeRepository->getList(
ProductAttributeInterface::ENTITY_TYPE_CODE,
$criteria
)->getItems();
$options = [];
foreach ($attributes as $attribute) {
$sourceModelOptions = $attribute->getOptions();
// Add options to list used below
foreach ($sourceModelOptions as $option) {
$options[$attribute->getAttributeId()][$option->getValue()] = true;
}
}
return $options;
}
/**
* Save a data to temporary source index table
*
* @param array $data
* @return $this
*/
protected function _saveIndexData(array $data)
{
if (!$data) {
return $this;
}
$connection = $this->getConnection();
$connection->insertArray(
$this->getIdxTable(),
['entity_id', 'attribute_id', 'store_id', 'value', 'source_id'],
$data
);
return $this;
}
/**
* Retrieve temporary source index table name
*
* @param string|null $table
* @return string
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function getIdxTable($table = null)
{
return $this->tableStrategy->getTableName('catalog_product_index_eav');
}
/**
* Save data from select
*
* @param Select $select
* @param array $options
* @return void
*/
private function saveDataFromSelect(Select $select, array $options)
{
$i = 0;
$data = [];
$query = $select->query();
while ($row = $query->fetch()) {
$values = isset($row['value']) ? explode(',', $row['value']) : [];
foreach ($values as $valueId) {
if (isset($options[$row['attribute_id']][$valueId])) {
$data[] = [$row['entity_id'], $row['attribute_id'], $row['store_id'], $valueId, $row['source_id']];
$i++;
if ($i % 10000 == 0) {
$this->_saveIndexData($data);
$data = [];
}
}
}
}
$this->_saveIndexData($data);
}
/**
* Prepare data index for product relations
*
* @param array $parentIds the parent entity ids limitation
* @return $this
*/
protected function _prepareRelationIndex($parentIds = null)
{
$connection = $this->getConnection();
$idxTable = $this->getIdxTable();
if (!$this->tableStrategy->getUseIdxTable()) {
$additionalIdxTable = $connection->getTableName(self::TRANSIT_PREFIX . $this->getIdxTable());
$connection->createTemporaryTableLike($additionalIdxTable, $idxTable);
$query = $connection->insertFromSelect(
$this->_prepareRelationIndexSelect($parentIds),
$additionalIdxTable,
[]
);
$connection->query($query);
$select = $connection->select()->from($additionalIdxTable);
$query = $connection->insertFromSelect(
$select,
$idxTable,
[],
\Magento\Framework\DB\Adapter\AdapterInterface::INSERT_IGNORE
);
$connection->query($query);
$connection->dropTemporaryTable($additionalIdxTable);
} else {
$query = $connection->insertFromSelect(
$this->_prepareRelationIndexSelect($parentIds),
$idxTable,
[],
\Magento\Framework\DB\Adapter\AdapterInterface::INSERT_IGNORE
);
$connection->query($query);
}
return $this;
}
}
Function Calls
None |
Stats
MD5 | e3b572569993d9d9cd93bc5645b8ede8 |
Eval Count | 0 |
Decode Time | 86 ms |