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

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