vendor/pimcore/data-hub-simple-rest/src/Service/IndexService.php line 191

Open in your IDE?
  1. <?php
  2. /**
  3.  * Pimcore
  4.  *
  5.  * This source file is available under following license:
  6.  * - Pimcore Commercial License (PCL)
  7.  *
  8.  *  @copyright  Copyright (c) Pimcore GmbH (http://www.pimcore.org)
  9.  *  @license    http://www.pimcore.org/license     PCL
  10.  */
  11. namespace Pimcore\Bundle\DataHubSimpleRestBundle\Service;
  12. use Pimcore\Bundle\DataHubSimpleRestBundle\MappingAndDataExtractor\AbstractMappingAndDataExtractor;
  13. use Pimcore\Bundle\DataHubSimpleRestBundle\MappingAndDataExtractor\DataExtractorFactory;
  14. class IndexService extends AbstractService
  15. {
  16.     const LOCK_NAME_PREFIX 'datahub-simplerest-indexservice-';
  17.     /**
  18.      * @param string $configName
  19.      *
  20.      * @throws \Pimcore\Bundle\DataHubSimpleRestBundle\Exception\InvalidRequestException
  21.      */
  22.     protected function checkAndCreateIndexAlias(string $configName)
  23.     {
  24.         foreach ($this->getDataExtractorsForConfig($configName) as $type => $mappingAndDataExtractor) {
  25.             $this->indexHandler->checkAndCreateIndexAlias($mappingAndDataExtractor);
  26.         }
  27.     }
  28.     /**
  29.      * @param string|null $configName
  30.      *
  31.      * @throws \Pimcore\Bundle\DataHubSimpleRestBundle\Exception\InvalidRequestException
  32.      */
  33.     public function createOrUpdateMapping(string $configName null)
  34.     {
  35.         foreach ($this->getConfigsToProcess($configName) as $configName) {
  36.             $lockname self::LOCK_NAME_PREFIX $configName;
  37.             $lock $this->lockFactory->createLock($lockname);
  38.             if (!$lock->acquire()) {
  39.                 
  40.                 throw new \Exception("IndexService for config '$configName' already locked.");
  41.             }
  42.             try {
  43.                 $usedIndices = [];
  44.                 $this->checkAndCreateIndexAlias($configName);
  45.                 foreach ($this->getDataExtractorsForConfig($configName) as $type => $mappingAndDataExtractor) {
  46.                     $this->indexHandler->createOrUpdateMapping($mappingAndDataExtractor);
  47.                     $usedIndices[] = $mappingAndDataExtractor->getIndexName();
  48.                 }
  49.                 $this->indexHandler->cleanupUnusedEsIndices($this->indexNamePrefix '_' $configName$usedIndices);
  50.             } finally {
  51.                 $lock->release();
  52.             }
  53.         }
  54.     }
  55.     /**
  56.      * @param string $configName
  57.      *
  58.      * @return array
  59.      *
  60.      * @throws \Pimcore\Bundle\DataHubSimpleRestBundle\Exception\InvalidRequestException
  61.      */
  62.     public function getLabelKeysFromIndex(string $configName): array
  63.     {
  64.         $allAttributes = [];
  65.         foreach ($this->getDataExtractorsForConfig($configName) as $type => $mappingAndDataExtractor) {
  66.             $allAttributes array_merge(
  67.                 $allAttributes,
  68.                 $this->indexHandler->getLabelKeysFromIndex($mappingAndDataExtractor->getIndexName(), $mappingAndDataExtractor->getLabelBlackList())
  69.             );
  70.         }
  71.         return array_unique($allAttributes);
  72.     }
  73.     /**
  74.      * @param string $configName
  75.      */
  76.     public function cleanupIndicesForConfig(string $configName)
  77.     {
  78.         $this->indexHandler->cleanupUnusedEsIndices($this->indexNamePrefix '_' $configName, []);
  79.     }
  80.     /**
  81.      * @param int $elementId
  82.      * @param string $entityType
  83.      * @param string|null $configName
  84.      *
  85.      * @return bool
  86.      *
  87.      * @throws \Pimcore\Bundle\DataHubSimpleRestBundle\Exception\InvalidRequestException
  88.      */
  89.     public function doIndexData($elementIdstring $entityTypestring $configName null): bool
  90.     {
  91.         $originalConfigName $configName;
  92.         foreach ($this->getConfigsToProcess($configName) as $configName) {
  93.             $mappingAndDataExtractor $this->getDataExtractorForConfigAndEntityType($configName$entityType);
  94.             if ($mappingAndDataExtractor) {
  95.                 $data $mappingAndDataExtractor->extractData($elementId);
  96.                 $dataExtractorCollection $this->getDataExtractorCollectionForConfigAndType($configName$entityType);
  97.                 $possibleElementIndices = [];
  98.                 foreach ($dataExtractorCollection as $dataExtractor) {
  99.                     $possibleElementIndices[] = $dataExtractor->getIndexName();
  100.                 }
  101.                 //get existing item from index - theoretical max count is number of indices
  102.                 $indexElements $this->indexHandler->queryIndexById($possibleElementIndices$elementIdcount($possibleElementIndices));
  103.                 //add old parent element to queue - to update or delete it
  104.                 if ($indexElements['total_count'] > 0) {
  105.                     foreach ($indexElements['items'] as $indexElement) {
  106.                         $parentIndexElement $this->indexHandler->queryIndexById($possibleElementIndices$indexElement['system']['parentId']);
  107.                         if ($parentIndexElement) {
  108.                             $this->addItemToQueue($parentIndexElement['system']['id'], $parentIndexElement['system'][AbstractMappingAndDataExtractor::INTERNAL_ENTITY_TYPE], $originalConfigName == null null $configName);
  109.                         }
  110.                     }
  111.                 }
  112.                 if (empty($data)) {
  113.                     if ($indexElements['total_count'] > 0) {
  114.                         // if there is no child element, delete
  115.                         // if there is one, it might be a virtual parent folder that must not be deleted - except if there is more than one element with same ID in index (might be left over of virtual parents)
  116.                         if (!$this->indexHandler->hasChildElementInIndex($possibleElementIndices$elementId) || $indexElements['total_count'] > 1) {
  117.                             $this->indexHandler->deleteItem($mappingAndDataExtractor->getIndexName(), $elementId);
  118.                         }
  119.                     }
  120.                 } else {
  121.                     if ($entityType === DataExtractorFactory::DATA_EXTRACTOR_TYPE_ASSET || $entityType == DataExtractorFactory::DATA_EXTRACTOR_TYPE_ASSET_FOLDER) {
  122.                         //parents are in asset folder
  123.                         $folderMappingExtractor $this->getDataExtractorForConfigAndEntityType($configNameDataExtractorFactory::DATA_EXTRACTOR_TYPE_ASSET_FOLDER);
  124.                     } else {
  125.                         //parents are in object folder
  126.                         $folderMappingExtractor $this->getDataExtractorForConfigAndEntityType($configNameDataExtractorFactory::DATA_EXTRACTOR_TYPE_OBJECT_FOLDER);
  127.                     }
  128.                     //check if element is in folder index and if entity type is not folder -> delete from index to avoid duplicate entries
  129.                     foreach ($indexElements['items'] as $indexElement) {
  130.                         if (
  131.                             !in_array($entityType, [DataExtractorFactory::DATA_EXTRACTOR_TYPE_ASSET_FOLDERDataExtractorFactory::DATA_EXTRACTOR_TYPE_OBJECT_FOLDER]) &&
  132.                             $indexElement && in_array($indexElement['system'][AbstractMappingAndDataExtractor::INTERNAL_ENTITY_TYPE], [DataExtractorFactory::DATA_EXTRACTOR_TYPE_ASSET_FOLDERDataExtractorFactory::DATA_EXTRACTOR_TYPE_OBJECT_FOLDER])
  133.                         ) {
  134.                             $this->indexHandler->deleteItem($folderMappingExtractor->getIndexName(), $elementId);
  135.                         }
  136.                     }
  137.                     //add new element
  138.                     $this->indexHandler->indexItem($mappingAndDataExtractor->getIndexName(), $elementId$data);
  139.                     //check if parent element is in any index of config ... if not add a virutal folder to folder index
  140.                     $virtualParentArray $mappingAndDataExtractor->getVirtualParentArray($elementId);
  141.                     if ($virtualParentArray) {
  142.                         //check if new parent(s) are already in index - add or update them
  143.                         foreach ($virtualParentArray as $virtualParent) {
  144.                             if ($newParentIndexElement $this->indexHandler->queryIndexById($possibleElementIndices$virtualParent['id'])) {
  145.                                 $this->addItemToQueue($newParentIndexElement['system']['id'], $newParentIndexElement['system'][AbstractMappingAndDataExtractor::INTERNAL_ENTITY_TYPE], $originalConfigName == null null $configName);
  146.                                 break;
  147.                             } else {
  148.                                 $this->indexHandler->indexItem($folderMappingExtractor->getIndexName(), $virtualParent['id'], $virtualParent['data']);
  149.                             }
  150.                         }
  151.                     }
  152.                 }
  153.             }
  154.         }
  155.         return true;
  156.     }
  157.     /**
  158.      * @param int $elementId
  159.      * @param string $entityType
  160.      * @param string|null $configName
  161.      */
  162.     public function addItemToQueue($elementIdstring $entityTypestring $configName null)
  163.     {
  164.         $this->queueService->addItemToQueue($elementId$entityType$configName);
  165.     }
  166.     /**
  167.      * @param int $limit
  168.      *
  169.      * @return array
  170.      */
  171.     public function getAllQueueEntries($limit 100000): array
  172.     {
  173.         return $this->queueService->getAllQueueEntries($limit);
  174.     }
  175.     /**
  176.      * @param int $elementId
  177.      * @param string $entityType
  178.      * @param string $configName
  179.      *
  180.      * @return bool
  181.      *
  182.      * @throws \Pimcore\Bundle\DataHubSimpleRestBundle\Exception\InvalidRequestException
  183.      */
  184.     public function processQueueEntry($elementId$entityType$configName): bool
  185.     {
  186.         $success $this->doIndexData($elementId$entityType$configName);
  187.         if ($success) {
  188.             $this->queueService->markQueueEntryAsProcessed($elementId$entityType$configName);
  189.         }
  190.         return $success;
  191.     }
  192.     /**
  193.      * @param string|null $configName
  194.      *
  195.      * @throws \Pimcore\Bundle\DataHubSimpleRestBundle\Exception\InvalidRequestException
  196.      */
  197.     public function initIndex(string $configName null)
  198.     {
  199.         $originalConfigName $configName;
  200.         $this->invalidateIndexAll($configName);
  201.         foreach ($this->getConfigsToProcess($configName) as $configName) {
  202.             foreach ($this->getDataExtractorsForConfig($configName) as $type => $mappingAndDataExtractor) {
  203.                 //do not init folders as they are initialized implicitly with parents that are added
  204.                 //so we avoid empty folders in index
  205.                 if ($type !== DataExtractorFactory::DATA_EXTRACTOR_TYPE_OBJECT_FOLDER && $type !== DataExtractorFactory::DATA_EXTRACTOR_TYPE_ASSET_FOLDER) {
  206.                     $ids $mappingAndDataExtractor->calculateAllElementIds();
  207.                     foreach ($ids as $id) {
  208.                         $this->queueService->addItemToQueue($id$type$originalConfigName == null null $configName);
  209.                     }
  210.                 }
  211.             }
  212.         }
  213.     }
  214.     public function invalidateDuplicateIndexEntries(string $configName null)
  215.     {
  216.         $originalConfigName $configName;
  217.         foreach ($this->getConfigsToProcess($configName) as $configName) {
  218.             //for assets
  219.             $dataExtractorCollection $this->getDataExtractorCollectionForConfigAndType($configNameDataExtractorFactory::DATA_EXTRACTOR_TYPE_ASSET);
  220.             if ($dataExtractorCollection) {
  221.                 $indexNames = [];
  222.                 foreach ($dataExtractorCollection as $dataExtractor) {
  223.                     $indexNames[] = $dataExtractor->getIndexName();
  224.                 }
  225.                 $duplicateEntries $this->indexHandler->findDuplicateElements($indexNames);
  226.                 foreach ($duplicateEntries as $entry) {
  227.                     $this->queueService->addItemToQueue($entry['id'], $entry[AbstractMappingAndDataExtractor::INTERNAL_ENTITY_TYPE], $originalConfigName == null null $configName);
  228.                 }
  229.             }
  230.             //for objects
  231.             $dataExtractorCollection $this->getDataExtractorCollectionForConfigAndType($configNameDataExtractorFactory::DATA_EXTRACTOR_TYPE_OBJECT_FOLDER);
  232.             if ($dataExtractorCollection) {
  233.                 $indexNames = [];
  234.                 foreach ($dataExtractorCollection as $dataExtractor) {
  235.                     $indexNames[] = $dataExtractor->getIndexName();
  236.                 }
  237.                 $duplicateEntries $this->indexHandler->findDuplicateElements($indexNames);
  238.                 foreach ($duplicateEntries as $entry) {
  239.                     $this->queueService->addItemToQueue($entry['id'], $entry[AbstractMappingAndDataExtractor::INTERNAL_ENTITY_TYPE], $originalConfigName == null null $configName);
  240.                 }
  241.             }
  242.         }
  243.     }
  244.     /**
  245.      * @param string|null $configName
  246.      *
  247.      * @throws \Pimcore\Bundle\DataHubSimpleRestBundle\Exception\InvalidRequestException
  248.      */
  249.     public function invalidateIndexAll(string $configName null)
  250.     {
  251.         $originalConfigName $configName;
  252.         foreach ($this->getConfigsToProcess($configName) as $configName) {
  253.             foreach ($this->getDataExtractorsForConfig($configName) as $type => $mappingAndDataExtractor) {
  254.                 $allIds $this->indexHandler->getAllIdsFromIndex($mappingAndDataExtractor->getIndexName());
  255.                 foreach ($allIds as $id) {
  256.                     $this->addItemToQueue($id$type$originalConfigName == null null $configName);
  257.                 }
  258.             }
  259.         }
  260.     }
  261.     /**
  262.      * @param string $path
  263.      * @param string $entityType
  264.      * @param string|null $configName
  265.      *
  266.      * @throws \Pimcore\Bundle\DataHubSimpleRestBundle\Exception\InvalidRequestException
  267.      */
  268.     public function invalidateIndexByOriginalPath(string $pathstring $entityTypestring $configName null)
  269.     {
  270.         $originalConfigName $configName;
  271.         foreach ($this->getConfigsToProcess($configName) as $configName) {
  272.             foreach ($this->getDataExtractorCollectionForConfigAndType($configName$entityType) as $type => $mappingAndDataExtractor) {
  273.                 $allIds $this->indexHandler->getAllIdsFromIndexByOriginalPath($mappingAndDataExtractor->getIndexName(), $path);
  274.                 foreach ($allIds as $id) {
  275.                     $this->addItemToQueue($id$type$originalConfigName == null null $configName);
  276.                 }
  277.             }
  278.         }
  279.     }
  280. }