/vendor/magento/module-catalog-search/Model/Indexer/Fulltext/Action/Full.php
PHP | 450 lines | 205 code | 50 blank | 195 comment | 14 complexity | 7ff457a68b00631b0b484f0de9d4af8e MD5 | raw file
- <?php
- /**
- * Copyright © 2016 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
- namespace Magento\CatalogSearch\Model\Indexer\Fulltext\Action;
- use Magento\CatalogSearch\Model\Indexer\Fulltext;
- use Magento\Framework\App\ResourceConnection;
- /**
- * @SuppressWarnings(PHPMD.TooManyFields)
- * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
- */
- class Full
- {
- /**
- * Scope identifier
- */
- const SCOPE_FIELD_NAME = 'scope';
- /**
- * Searchable attributes cache
- *
- * @var \Magento\Eav\Model\Entity\Attribute[]
- */
- protected $searchableAttributes;
- /**
- * Index values separator
- *
- * @var string
- */
- protected $separator = ' | ';
- /**
- * Array of \DateTime objects per store
- *
- * @var \DateTime[]
- */
- protected $dates = [];
- /**
- * Product Type Instances cache
- *
- * @var array
- */
- protected $productTypes = [];
- /**
- * Product Emulators cache
- *
- * @var array
- */
- protected $productEmulators = [];
- /**
- * @var \Magento\Catalog\Model\ResourceModel\Product\Attribute\CollectionFactory
- */
- protected $productAttributeCollectionFactory;
- /**
- * Catalog product status
- *
- * @var \Magento\Catalog\Model\Product\Attribute\Source\Status
- */
- protected $catalogProductStatus;
- /**
- * Eav config
- *
- * @var \Magento\Eav\Model\Config
- */
- protected $eavConfig;
- /**
- * Catalog product type
- *
- * @var \Magento\Catalog\Model\Product\Type
- */
- protected $catalogProductType;
- /**
- * Core event manager proxy
- *
- * @var \Magento\Framework\Event\ManagerInterface
- */
- protected $eventManager;
- /**
- * Core store config
- *
- * @var \Magento\Framework\App\Config\ScopeConfigInterface
- */
- protected $scopeConfig;
- /**
- * Store manager
- *
- * @var \Magento\Store\Model\StoreManagerInterface
- */
- protected $storeManager;
- /**
- * @var \Magento\CatalogSearch\Model\ResourceModel\Engine
- */
- protected $engine;
- /**
- * @var \Magento\Framework\Indexer\SaveHandler\IndexerInterface
- */
- protected $indexHandler;
- /**
- * @var \Magento\Framework\Stdlib\DateTime
- */
- protected $dateTime;
- /**
- * @var \Magento\Framework\Locale\ResolverInterface
- */
- protected $localeResolver;
- /**
- * @var \Magento\Framework\Stdlib\DateTime\TimezoneInterface
- */
- protected $localeDate;
- /**
- * @var Resource
- */
- protected $resource;
- /**
- * @var \Magento\CatalogSearch\Model\ResourceModel\Fulltext
- */
- protected $fulltextResource;
- /**
- * @var \Magento\Framework\Search\Request\Config
- */
- protected $searchRequestConfig;
- /**
- * @var \Magento\Framework\Search\Request\DimensionFactory
- */
- private $dimensionFactory;
- /**
- * @var \Magento\Framework\DB\Adapter\AdapterInterface
- */
- protected $connection;
- /**
- * @var \Magento\CatalogSearch\Model\Indexer\Fulltext\Action\IndexIteratorFactory
- */
- private $iteratorFactory;
- /**
- * @param ResourceConnection $resource
- * @param \Magento\Catalog\Model\Product\Type $catalogProductType
- * @param \Magento\Eav\Model\Config $eavConfig
- * @param \Magento\Framework\Search\Request\Config $searchRequestConfig
- * @param \Magento\Catalog\Model\Product\Attribute\Source\Status $catalogProductStatus
- * @param \Magento\Catalog\Model\ResourceModel\Product\Attribute\CollectionFactory $prodAttributeCollectionFactory
- * @param \Magento\CatalogSearch\Model\ResourceModel\EngineProvider $engineProvider
- * @param \Magento\CatalogSearch\Model\Indexer\IndexerHandlerFactory $indexHandlerFactory
- * @param \Magento\Framework\Event\ManagerInterface $eventManager
- * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
- * @param \Magento\Store\Model\StoreManagerInterface $storeManager
- * @param \Magento\Framework\Stdlib\DateTime $dateTime
- * @param \Magento\Framework\Locale\ResolverInterface $localeResolver
- * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate
- * @param \Magento\CatalogSearch\Model\ResourceModel\Fulltext $fulltextResource
- * @param \Magento\Framework\Search\Request\DimensionFactory $dimensionFactory
- * @param \Magento\Framework\Indexer\ConfigInterface $indexerConfig
- * @param \Magento\CatalogSearch\Model\Indexer\Fulltext\Action\IndexIteratorFactory $indexIteratorFactory
- * @SuppressWarnings(PHPMD.ExcessiveParameterList)
- */
- public function __construct(
- ResourceConnection $resource,
- \Magento\Catalog\Model\Product\Type $catalogProductType,
- \Magento\Eav\Model\Config $eavConfig,
- \Magento\Framework\Search\Request\Config $searchRequestConfig,
- \Magento\Catalog\Model\Product\Attribute\Source\Status $catalogProductStatus,
- \Magento\Catalog\Model\ResourceModel\Product\Attribute\CollectionFactory $prodAttributeCollectionFactory,
- \Magento\CatalogSearch\Model\ResourceModel\EngineProvider $engineProvider,
- \Magento\CatalogSearch\Model\Indexer\IndexerHandlerFactory $indexHandlerFactory,
- \Magento\Framework\Event\ManagerInterface $eventManager,
- \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
- \Magento\Store\Model\StoreManagerInterface $storeManager,
- \Magento\Framework\Stdlib\DateTime $dateTime,
- \Magento\Framework\Locale\ResolverInterface $localeResolver,
- \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate,
- \Magento\CatalogSearch\Model\ResourceModel\Fulltext $fulltextResource,
- \Magento\Framework\Search\Request\DimensionFactory $dimensionFactory,
- \Magento\Framework\Indexer\ConfigInterface $indexerConfig,
- \Magento\CatalogSearch\Model\Indexer\Fulltext\Action\IndexIteratorFactory $indexIteratorFactory
- ) {
- $this->resource = $resource;
- $this->connection = $resource->getConnection();
- $this->catalogProductType = $catalogProductType;
- $this->eavConfig = $eavConfig;
- $this->searchRequestConfig = $searchRequestConfig;
- $this->catalogProductStatus = $catalogProductStatus;
- $this->productAttributeCollectionFactory = $prodAttributeCollectionFactory;
- $this->eventManager = $eventManager;
- $this->scopeConfig = $scopeConfig;
- $this->storeManager = $storeManager;
- $this->engine = $engineProvider->get();
- $configData = $indexerConfig->getIndexer(Fulltext::INDEXER_ID);
- $this->indexHandler = $indexHandlerFactory->create(['data' => $configData]);
- $this->dateTime = $dateTime;
- $this->localeResolver = $localeResolver;
- $this->localeDate = $localeDate;
- $this->fulltextResource = $fulltextResource;
- $this->dimensionFactory = $dimensionFactory;
- $this->iteratorFactory = $indexIteratorFactory;
- }
- /**
- * Rebuild whole fulltext index for all stores
- *
- * @return void
- */
- public function reindexAll()
- {
- $storeIds = array_keys($this->storeManager->getStores());
- foreach ($storeIds as $storeId) {
- $this->cleanIndex($storeId);
- $this->rebuildStoreIndex($storeId);
- }
- $this->searchRequestConfig->reset();
- }
- /**
- * Return validated table name
- *
- * @param string|string[] $table
- * @return string
- */
- protected function getTable($table)
- {
- return $this->resource->getTableName($table);
- }
- /**
- * Get parents IDs of product IDs to be re-indexed
- *
- * @param int[] $entityIds
- * @return int[]
- */
- protected function getProductIdsFromParents(array $entityIds)
- {
- return $this->connection
- ->select()
- ->from($this->getTable('catalog_product_relation'), 'parent_id')
- ->distinct(true)
- ->where('child_id IN (?)', $entityIds)
- ->where('parent_id NOT IN (?)', $entityIds)
- ->query()
- ->fetchAll(\Zend_Db::FETCH_COLUMN);
- }
- /**
- * Regenerate search index for specific store
- *
- * @param int $storeId Store View Id
- * @param int|array $productIds Product Entity Id
- * @return \Generator
- *
- * @SuppressWarnings(PHPMD.CyclomaticComplexity)
- * @SuppressWarnings(PHPMD.NPathComplexity)
- */
- public function rebuildStoreIndex($storeId, $productIds = null)
- {
- if ($productIds !== null) {
- $productIds = array_unique(array_merge($productIds, $this->getProductIdsFromParents($productIds)));
- }
- // prepare searchable attributes
- $staticFields = [];
- foreach ($this->getSearchableAttributes('static') as $attribute) {
- $staticFields[] = $attribute->getAttributeCode();
- }
- $dynamicFields = [
- 'int' => array_keys($this->getSearchableAttributes('int')),
- 'varchar' => array_keys($this->getSearchableAttributes('varchar')),
- 'text' => array_keys($this->getSearchableAttributes('text')),
- 'decimal' => array_keys($this->getSearchableAttributes('decimal')),
- 'datetime' => array_keys($this->getSearchableAttributes('datetime')),
- ];
- // status and visibility filter
- $visibility = $this->getSearchableAttribute('visibility');
- $status = $this->getSearchableAttribute('status');
- $statusIds = $this->catalogProductStatus->getVisibleStatusIds();
- $allowedVisibility = $this->engine->getAllowedVisibility();
- return $this->iteratorFactory->create([
- 'storeId' => $storeId,
- 'productIds' => $productIds,
- 'staticFields' => $staticFields,
- 'dynamicFields' => $dynamicFields,
- 'visibility' => $visibility,
- 'allowedVisibility' => $allowedVisibility,
- 'status' => $status,
- 'statusIds' => $statusIds
- ]);
- }
- /**
- * Clean search index data for store
- *
- * @param int $storeId
- * @return void
- */
- protected function cleanIndex($storeId)
- {
- $dimension = $this->dimensionFactory->create(['name' => self::SCOPE_FIELD_NAME, 'value' => $storeId]);
- $this->indexHandler->cleanIndex([$dimension]);
- }
- /**
- * Retrieve EAV Config Singleton
- *
- * @return \Magento\Eav\Model\Config
- */
- protected function getEavConfig()
- {
- return $this->eavConfig;
- }
- /**
- * Retrieve searchable attributes
- *
- * @param string $backendType
- * @return \Magento\Eav\Model\Entity\Attribute[]
- */
- protected function getSearchableAttributes($backendType = null)
- {
- if (null === $this->searchableAttributes) {
- $this->searchableAttributes = [];
- $productAttributes = $this->productAttributeCollectionFactory->create();
- $productAttributes->addToIndexFilter(true);
- /** @var \Magento\Eav\Model\Entity\Attribute[] $attributes */
- $attributes = $productAttributes->getItems();
- $this->eventManager->dispatch(
- 'catelogsearch_searchable_attributes_load_after',
- ['engine' => $this->engine, 'attributes' => $attributes]
- );
- $entity = $this->getEavConfig()->getEntityType(\Magento\Catalog\Model\Product::ENTITY)->getEntity();
- foreach ($attributes as $attribute) {
- $attribute->setEntity($entity);
- }
- $this->searchableAttributes = $attributes;
- }
- if ($backendType !== null) {
- $attributes = [];
- foreach ($this->searchableAttributes as $attributeId => $attribute) {
- if ($attribute->getBackendType() == $backendType) {
- $attributes[$attributeId] = $attribute;
- }
- }
- return $attributes;
- }
- return $this->searchableAttributes;
- }
- /**
- * Retrieve searchable attribute by Id or code
- *
- * @param int|string $attribute
- * @return \Magento\Eav\Model\Entity\Attribute
- */
- protected function getSearchableAttribute($attribute)
- {
- $attributes = $this->getSearchableAttributes();
- if (is_numeric($attribute)) {
- if (isset($attributes[$attribute])) {
- return $attributes[$attribute];
- }
- } elseif (is_string($attribute)) {
- foreach ($attributes as $attributeModel) {
- if ($attributeModel->getAttributeCode() == $attribute) {
- return $attributeModel;
- }
- }
- }
- return $this->getEavConfig()->getAttribute(\Magento\Catalog\Model\Product::ENTITY, $attribute);
- }
- /**
- * Returns expression for field unification
- *
- * @param string $field
- * @param string $backendType
- * @return \Zend_Db_Expr
- */
- protected function unifyField($field, $backendType = 'varchar')
- {
- if ($backendType == 'datetime') {
- $expr = $this->connection->getDateFormatSql($field, '%Y-%m-%d %H:%i:%s');
- } else {
- $expr = $field;
- }
- return $expr;
- }
- /**
- * Retrieve Product Type Instance
- *
- * @param string $typeId
- * @return \Magento\Catalog\Model\Product\Type\AbstractType
- */
- protected function getProductTypeInstance($typeId)
- {
- if (!isset($this->productTypes[$typeId])) {
- $productEmulator = $this->getProductEmulator($typeId);
- $this->productTypes[$typeId] = $this->catalogProductType->factory($productEmulator);
- }
- return $this->productTypes[$typeId];
- }
- /**
- * Retrieve Product Emulator (Magento Object)
- *
- * @param string $typeId
- * @return \Magento\Framework\DataObject
- */
- protected function getProductEmulator($typeId)
- {
- if (!isset($this->productEmulators[$typeId])) {
- $productEmulator = new \Magento\Framework\DataObject();
- $productEmulator->setTypeId($typeId);
- $this->productEmulators[$typeId] = $productEmulator;
- }
- return $this->productEmulators[$typeId];
- }
- }