123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256 |
- <?php
- /**
- * Copyright © Magento, Inc. All rights reserved.
- * See COPYING.txt for license details.
- */
- namespace Magento\Framework\Indexer\SaveHandler;
- use Magento\Framework\App\ResourceConnection;
- use Magento\Framework\DB\Adapter\AdapterInterface;
- use Magento\Framework\Search\Request\Dimension;
- use Magento\Framework\Search\Request\IndexScopeResolverInterface;
- use Magento\Framework\Indexer\IndexStructureInterface;
- use Magento\Framework\Indexer\ScopeResolver\FlatScopeResolver;
- use Magento\Framework\Indexer\ScopeResolver\IndexScopeResolver;
- /**
- * Save handler for indexer.
- */
- class IndexerHandler implements IndexerInterface
- {
- /**
- * @var string[]
- */
- protected $dataTypes = ['searchable', 'filterable'];
- /**
- * @var IndexStructureInterface
- */
- protected $indexStructure;
- /**
- * @var array
- */
- protected $data;
- /**
- * @var array
- */
- protected $fields;
- /**
- * @var Resource|Resource
- */
- protected $resource;
- /**
- * @var Batch
- */
- protected $batch;
- /**
- * @var int
- */
- protected $batchSize;
- /**
- * @var IndexScopeResolverInterface[]
- */
- protected $scopeResolvers;
- /**
- * @param IndexStructureInterface $indexStructure
- * @var AdapterInterface
- */
- protected $connection;
- /**
- * @param IndexStructureInterface $indexStructure
- * @param ResourceConnection $resource
- * @param Batch $batch
- * @param \Magento\Framework\Indexer\ScopeResolver\IndexScopeResolver $indexScopeResolver
- * @param \Magento\Framework\Indexer\ScopeResolver\FlatScopeResolver $flatScopeResolver
- * @param array $data
- * @param int $batchSize
- */
- public function __construct(
- IndexStructureInterface $indexStructure,
- ResourceConnection $resource,
- Batch $batch,
- IndexScopeResolver $indexScopeResolver,
- FlatScopeResolver $flatScopeResolver,
- array $data,
- $batchSize = 100
- ) {
- $this->indexStructure = $indexStructure;
- $this->resource = $resource;
- $this->connection = $resource->getConnection();
- $this->batch = $batch;
- $this->scopeResolvers[$this->dataTypes[0]] = $indexScopeResolver;
- $this->scopeResolvers[$this->dataTypes[1]] = $flatScopeResolver;
- $this->data = $data;
- $this->batchSize = $batchSize;
- $this->fields = [];
- $this->prepareFields();
- }
- /**
- * @inheritdoc
- */
- public function saveIndex($dimensions, \Traversable $documents)
- {
- foreach ($this->batch->getItems($documents, $this->batchSize) as $batchDocuments) {
- $this->insertDocumentsForSearchable($batchDocuments, $dimensions);
- $this->insertDocumentsForFilterable($batchDocuments, $dimensions);
- }
- }
- /**
- * @inheritdoc
- */
- public function deleteIndex($dimensions, \Traversable $documents)
- {
- foreach ($this->dataTypes as $dataType) {
- foreach ($this->batch->getItems($documents, $this->batchSize) as $batchDocuments) {
- $documentsId = array_column($batchDocuments, 'id');
- $this->connection->delete($this->getTableName($dataType, $dimensions), ['id' => $documentsId]);
- }
- }
- }
- /**
- * @inheritdoc
- */
- public function cleanIndex($dimensions)
- {
- $this->indexStructure->delete($this->getIndexName(), $dimensions);
- $this->indexStructure->create($this->getIndexName(), $this->fields, $dimensions);
- }
- /**
- * @inheritdoc
- */
- public function isAvailable($dimensions = [])
- {
- return true;
- }
- /**
- * Returns table name.
- *
- * @param string $dataType
- * @param Dimension[] $dimensions
- * @return string
- */
- protected function getTableName($dataType, $dimensions)
- {
- return $this->scopeResolvers[$dataType]->resolve($this->getIndexName(), $dimensions);
- }
- /**
- * Returns index name
- *
- * @return string
- */
- protected function getIndexName()
- {
- return $this->data['indexer_id'];
- }
- /**
- * Save searchable documents to storage.
- *
- * @param array $documents
- * @param Dimension[] $dimensions
- * @return void
- */
- private function insertDocumentsForSearchable(array $documents, array $dimensions)
- {
- $this->connection->insertOnDuplicate(
- $this->getTableName($this->dataTypes[0], $dimensions),
- $this->prepareSearchableFields($documents),
- ['data_index']
- );
- }
- /**
- * Save filterable documents to storage.
- *
- * @param array $documents
- * @param Dimension[] $dimensions
- * @return void
- */
- protected function insertDocumentsForFilterable(array $documents, array $dimensions)
- {
- $onDuplicate = [];
- foreach ($this->fields as $field) {
- if ($field['type'] === $this->dataTypes[1]) {
- $onDuplicate[] = $field['name'];
- }
- }
- $this->connection->insertOnDuplicate(
- $this->getTableName($this->dataTypes[1], $dimensions),
- $this->prepareFilterableFields($documents),
- $onDuplicate
- );
- }
- /**
- * Prepare filterable fields.
- *
- * @param array $documents
- * @return array
- */
- protected function prepareFilterableFields(array $documents)
- {
- $insertDocuments = [];
- foreach ($documents as $entityId => $document) {
- $documentFlat = ['entity_id' => $entityId];
- foreach ($this->fields as $field) {
- if ($field['type'] == $this->dataTypes[1]) {
- $documentFlat[$field['name']] = $document[$field['name']];
- }
- }
- $insertDocuments[] = $documentFlat;
- }
- return $insertDocuments;
- }
- /**
- * Prepare searchable fields.
- *
- * @param array $documents
- * @return array
- */
- private function prepareSearchableFields(array $documents)
- {
- $insertDocuments = [];
- foreach ($documents as $entityId => $document) {
- foreach ($this->fields as $field) {
- if ($field['type'] === $this->dataTypes[0]) {
- $insertDocuments[] = [
- 'entity_id' => $entityId,
- 'attribute_id' => $field['name'],
- 'data_index' => $document[$field['name']],
- ];
- }
- }
- }
- return $insertDocuments;
- }
- /**
- * Prepare fields.
- *
- * @return void
- */
- private function prepareFields()
- {
- foreach ($this->data['fieldsets'] as $fieldset) {
- $this->fields = array_merge($this->fields, array_values($fieldset['fields']));
- }
- }
- }
|