![]() 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/Category/Flat/Action/ |
<?php /** * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\Catalog\Model\Indexer\Category\Flat\Action; /** * Class for full reindex flat categories */ class Full extends \Magento\Catalog\Model\Indexer\Category\Flat\AbstractAction { /** * Suffix for table to show it is old */ const OLD_TABLE_SUFFIX = '_old'; /** * Whether table changes are allowed * * @var bool */ protected $allowTableChanges = true; /** * Add suffix to table name to show it is old * * @param string $tableName * @return string */ protected function addOldTableSuffix($tableName) { return $tableName . self::OLD_TABLE_SUFFIX; } /** * Populate category flat tables with data * * @param \Magento\Store\Model\Store[] $stores * @return Full */ protected function populateFlatTables(array $stores) { $rootId = \Magento\Catalog\Model\Category::TREE_ROOT_ID; $categories = []; $categoriesIds = []; /* @var $store \Magento\Store\Model\Store */ foreach ($stores as $store) { if (!isset($categories[$store->getRootCategoryId()])) { $select = $this->connection->select()->from( $this->connection->getTableName($this->getTableName('catalog_category_entity')) )->where( 'path = ?', (string)$rootId )->orWhere( 'path = ?', "{$rootId}/{$store->getRootCategoryId()}" )->orWhere( 'path LIKE ?', "{$rootId}/{$store->getRootCategoryId()}/%" ); $categories[$store->getRootCategoryId()] = $this->connection->fetchAll($select); $categoriesIds[$store->getRootCategoryId()] = []; foreach ($categories[$store->getRootCategoryId()] as $category) { $categoriesIds[$store->getRootCategoryId()][] = $category['entity_id']; } } /** @TODO Do something with chunks */ $categoriesIdsChunks = array_chunk($categoriesIds[$store->getRootCategoryId()], 500); foreach ($categoriesIdsChunks as $categoriesIdsChunk) { $attributesData = $this->getAttributeValues($categoriesIdsChunk, $store->getId()); $linkField = $this->categoryMetadata->getLinkField(); $data = []; foreach ($categories[$store->getRootCategoryId()] as $category) { if (!isset($attributesData[$category[$linkField]])) { continue; } $category['store_id'] = $store->getId(); $data[] = $this->prepareValuesToInsert( // phpcs:ignore Magento2.Performance.ForeachArrayMerge array_merge($category, $attributesData[$category[$linkField]]) ); } $this->connection->insertMultiple( $this->addTemporaryTableSuffix($this->getMainStoreTable($store->getId())), $data ); } } return $this; } /** * Create table and add attributes as fields for specified store. * * This routine assumes that DDL operations are allowed * * @param int $store * @return Full */ protected function createTable($store) { $temporaryTable = $this->addTemporaryTableSuffix($this->getMainStoreTable($store)); $table = $this->getFlatTableStructure($temporaryTable); $this->connection->dropTable($temporaryTable); $this->connection->createTable($table); return $this; } /** * Create category flat tables and add attributes as fields. * * Tables are created only if DDL operations are allowed * * @param \Magento\Store\Model\Store[] $stores if empty, create tables for all stores of the application * @return Full */ protected function createTables(array $stores = []) { if ($this->connection->getTransactionLevel() > 0) { return $this; } if (empty($stores)) { $stores = $this->storeManager->getStores(); } /* @var $store \Magento\Store\Model\Store */ foreach ($stores as $store) { $this->createTable($store->getId()); } return $this; } /** * Switch table (temporary becomes active, old active will be dropped) * * @param \Magento\Store\Model\Store[] $stores * @return Full */ protected function switchTables(array $stores = []) { /** @var $store \Magento\Store\Model\Store */ foreach ($stores as $store) { $activeTableName = $this->getMainStoreTable($store->getId()); $temporaryTableName = $this->addTemporaryTableSuffix($this->getMainStoreTable($store->getId())); $oldTableName = $this->addOldTableSuffix($this->getMainStoreTable($store->getId())); //switch tables $tablesToRename = []; if ($this->connection->isTableExists($activeTableName)) { $tablesToRename[] = ['oldName' => $activeTableName, 'newName' => $oldTableName]; } $tablesToRename[] = ['oldName' => $temporaryTableName, 'newName' => $activeTableName]; foreach ($tablesToRename as $tableToRename) { $this->connection->renameTable($tableToRename['oldName'], $tableToRename['newName']); } //delete inactive table $tableToDelete = $oldTableName; if ($this->connection->isTableExists($tableToDelete)) { $this->connection->dropTable($tableToDelete); } } return $this; } /** * Retrieve all actual Catalog Product Flat Table names * * @return string[] */ private function getActualStoreTablesForCategoryFlat(): array { $actualStoreTables = []; foreach ($this->storeManager->getStores() as $store) { $actualStoreTables[] = sprintf( '%s_store_%s', $this->connection->getTableName($this->getTableName('catalog_category_flat')), $store->getId() ); } return $actualStoreTables; } /** * Delete all category flat tables for not existing stores * * @return void */ private function deleteAbandonedStoreCategoryFlatTables(): void { $existentTables = $this->connection->getTables( $this->connection->getTableName($this->getTableName('catalog_category_flat_store_%')) ); $actualStoreTables = $this->getActualStoreTablesForCategoryFlat(); $tablesToDelete = array_diff($existentTables, $actualStoreTables); foreach ($tablesToDelete as $table) { $this->connection->dropTable($table); } } /** * Transactional rebuild flat data from eav * * @return Full */ public function reindexAll() { $this->createTables(); if ($this->allowTableChanges) { $this->allowTableChanges = false; } $stores = $this->storeManager->getStores(); $this->populateFlatTables($stores); $this->switchTables($stores); $this->deleteAbandonedStoreCategoryFlatTables(); $this->allowTableChanges = true; return $this; } }