| Current Path : /home/rtorresani/www/vendor/magento/module-catalog/Model/Indexer/Category/Flat/Action/ |
| Current File : //home/rtorresani/www/vendor/magento/module-catalog/Model/Indexer/Category/Flat/Action/Rows.php |
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\Catalog\Model\Indexer\Category\Flat\Action;
use Magento\Catalog\Api\CategoryRepositoryInterface;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Store\Model\Store;
class Rows extends \Magento\Catalog\Model\Indexer\Category\Flat\AbstractAction
{
/**
* @var CategoryRepositoryInterface
*/
protected $categoryRepository;
/**
* @param \Magento\Framework\App\ResourceConnection $resource
* @param \Magento\Store\Model\StoreManagerInterface $storeManager
* @param \Magento\Catalog\Model\ResourceModel\Helper $resourceHelper
* @param CategoryRepositoryInterface $categoryRepository
*/
public function __construct(
\Magento\Framework\App\ResourceConnection $resource,
\Magento\Store\Model\StoreManagerInterface $storeManager,
\Magento\Catalog\Model\ResourceModel\Helper $resourceHelper,
CategoryRepositoryInterface $categoryRepository
) {
$this->categoryRepository = $categoryRepository;
parent::__construct($resource, $storeManager, $resourceHelper);
}
/**
* Return index table name
*
* @param Store $store
* @param bool $useTempTable
* @return string
*/
protected function getTableNameByStore(Store $store, $useTempTable)
{
$tableName = $this->getMainStoreTable($store->getId());
return $useTempTable ? $this->addTemporaryTableSuffix($tableName) : $tableName;
}
/**
* Refresh entities index
*
* @param int[] $entityIds
* @param bool $useTempTable
* @return Rows
*/
public function reindex(array $entityIds = [], $useTempTable = false)
{
$stores = $this->storeManager->getStores();
foreach ($stores as $store) {
$this->reindexStore($store, $entityIds, $useTempTable);
}
return $this;
}
/**
* Delete non stores categories
*
* @param Store $store
* @param bool $useTempTable
* @return void
*/
protected function deleteNonStoreCategories(Store $store, $useTempTable)
{
$rootId = \Magento\Catalog\Model\Category::TREE_ROOT_ID;
$rootIdExpr = $this->connection->quote((string)$rootId);
$rootCatIdExpr = $this->connection->quote("{$rootId}/{$store->getRootCategoryId()}");
$catIdExpr = $this->connection->quote("{$rootId}/{$store->getRootCategoryId()}/%");
/** @var \Magento\Framework\DB\Select $select */
$select = $this->connection->select()->from(
['cf' => $this->getTableNameByStore($store, $useTempTable)]
)->where(
"cf.path = {$rootIdExpr} OR cf.path = {$rootCatIdExpr} OR cf.path like {$catIdExpr}"
)->where(
'cf.entity_id NOT IN (?)',
new \Zend_Db_Expr(
$this->connection->select()->from(
['ce' => $this->getTableName('catalog_category_entity')],
['entity_id']
)
)
);
$sql = $select->deleteFromSelect('cf');
$this->connection->query($sql);
}
/**
* Filter category ids by store
*
* @param int[] $ids
* @param Store $store
* @return int[]
*/
protected function filterIdsByStore(array $ids, $store)
{
$rootId = \Magento\Catalog\Model\Category::TREE_ROOT_ID;
$rootIdExpr = $this->connection->quote((string)$rootId);
$rootCatIdExpr = $this->connection->quote("{$rootId}/{$store->getRootCategoryId()}");
$catIdExpr = $this->connection->quote("{$rootId}/{$store->getRootCategoryId()}/%");
$select = $this->connection->select()->from(
$this->getTableName('catalog_category_entity'),
['entity_id']
)->where(
"path = {$rootIdExpr} OR path = {$rootCatIdExpr} OR path like {$catIdExpr}"
)->where(
"entity_id IN (?)",
$ids,
\Zend_Db::INT_TYPE
);
$resultIds = [];
foreach ($this->connection->fetchAll($select) as $category) {
$resultIds[] = $category['entity_id'];
}
return $resultIds;
}
/**
* Reindex data for store
*
* @param Store $store
* @param int[] $entityIds
* @param bool $useTempTable
*/
private function reindexStore(Store $store, array $entityIds, $useTempTable)
{
$tableName = $this->getTableNameByStore($store, $useTempTable);
if (!$this->connection->isTableExists($tableName)) {
return;
}
$categoriesIdsChunks = array_chunk($entityIds, 500);
foreach ($categoriesIdsChunks as $categoriesIdsChunk) {
$categoriesIdsChunk = $this->filterIdsByStore($categoriesIdsChunk, $store);
$attributesData = $this->getAttributeValues($categoriesIdsChunk, $store->getId());
$indexData = $this->buildIndexData($store, $categoriesIdsChunk, $attributesData);
$this->updateIndexData($tableName, $indexData);
}
$this->deleteNonStoreCategories($store, $useTempTable);
}
/**
* Build data for insert into index
*
* @param Store $store
* @param int[] $categoriesIdsChunk
* @param array[] $attributesData
* @return array
*/
private function buildIndexData(Store $store, $categoriesIdsChunk, $attributesData)
{
$linkField = $this->categoryMetadata->getLinkField();
$data = [];
foreach ($categoriesIdsChunk as $categoryId) {
try {
$category = $this->categoryRepository->get($categoryId);
} catch (NoSuchEntityException $e) {
continue;
}
$categoryData = $category->getData();
$linkId = $categoryData[$linkField];
$categoryAttributesData = [];
if (isset($attributesData[$linkId]) && is_array($attributesData[$linkId])) {
$categoryAttributesData = $attributesData[$linkId];
}
$categoryIndexData = $this->buildCategoryIndexData(
$store,
$categoryData,
$categoryAttributesData
);
$data[] = $categoryIndexData;
}
return $data;
}
/**
* Prepare Category data
*
* @param Store $store
* @param array $categoryData
* @param array $categoryAttributesData
* @return array
* @throws NoSuchEntityException
*/
private function buildCategoryIndexData(Store $store, array $categoryData, array $categoryAttributesData)
{
$data = $this->prepareValuesToInsert(
array_merge(
$categoryData,
$categoryAttributesData,
['store_id' => $store->getId()]
)
);
return $data;
}
/**
* Insert or update index data
*
* @param string $tableName
* @param array $data
* @return void
*/
private function updateIndexData($tableName, $data)
{
foreach ($data as $row) {
$updateFields = [];
foreach (array_keys($row) as $key) {
$updateFields[$key] = $key;
}
$this->connection->insertOnDuplicate($tableName, $row, $updateFields);
}
}
}