vendor/shopware/elasticsearch/Product/CustomFieldUpdater.php line 43

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Shopware\Elasticsearch\Product;
  3. use Elasticsearch\Client;
  4. use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityWrittenContainerEvent;
  5. use Shopware\Core\Framework\Log\Package;
  6. use Shopware\Core\System\CustomField\CustomFieldDefinition;
  7. use Shopware\Core\System\CustomField\CustomFieldTypes;
  8. use Shopware\Elasticsearch\Framework\ElasticsearchHelper;
  9. use Shopware\Elasticsearch\Framework\ElasticsearchOutdatedIndexDetector;
  10. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  11. /**
  12.  * @deprecated tag:v6.5.0 - reason:becomes-internal - EventSubscribers will become internal in v6.5.0
  13.  */
  14. #[Package('core')]
  15. class CustomFieldUpdater implements EventSubscriberInterface
  16. {
  17.     private ElasticsearchOutdatedIndexDetector $indexDetector;
  18.     private Client $client;
  19.     private ElasticsearchHelper $elasticsearchHelper;
  20.     /**
  21.      * @internal
  22.      */
  23.     public function __construct(ElasticsearchOutdatedIndexDetector $indexDetectorClient $clientElasticsearchHelper $elasticsearchHelper)
  24.     {
  25.         $this->indexDetector $indexDetector;
  26.         $this->client $client;
  27.         $this->elasticsearchHelper $elasticsearchHelper;
  28.     }
  29.     public static function getSubscribedEvents(): array
  30.     {
  31.         return [
  32.             EntityWrittenContainerEvent::class => 'onNewCustomFieldCreated',
  33.         ];
  34.     }
  35.     public function onNewCustomFieldCreated(EntityWrittenContainerEvent $containerEvent): void
  36.     {
  37.         $event $containerEvent->getEventByEntityName(CustomFieldDefinition::ENTITY_NAME);
  38.         if ($event === null) {
  39.             return;
  40.         }
  41.         if (!$this->elasticsearchHelper->allowIndexing()) {
  42.             return;
  43.         }
  44.         $newCreatedFields = [];
  45.         foreach ($event->getWriteResults() as $writeResult) {
  46.             $existence $writeResult->getExistence();
  47.             if ($existence && $existence->exists()) {
  48.                 continue;
  49.             }
  50.             /** @var array<mixed> $esType */
  51.             $esType self::getTypeFromCustomFieldType($writeResult->getProperty('type'));
  52.             $newCreatedFields[(string) $writeResult->getProperty('name')] = $esType;
  53.         }
  54.         if (\count($newCreatedFields) === 0) {
  55.             return;
  56.         }
  57.         $this->createNewFieldsInIndices($newCreatedFields);
  58.     }
  59.     /**
  60.      * @deprecated tag:v6.5.0 - Return type will be changed to not nullable - reason:return-type-change
  61.      *
  62.      * @return array<mixed>|null
  63.      */
  64.     public static function getTypeFromCustomFieldType(string $type): ?array
  65.     {
  66.         switch ($type) {
  67.             case CustomFieldTypes::INT:
  68.                 return [
  69.                     'type' => 'long',
  70.                 ];
  71.             case CustomFieldTypes::FLOAT:
  72.                 return [
  73.                     'type' => 'double',
  74.                 ];
  75.             case CustomFieldTypes::BOOL:
  76.                 return [
  77.                     'type' => 'boolean',
  78.                 ];
  79.             case CustomFieldTypes::DATETIME:
  80.                 return [
  81.                     'type' => 'date',
  82.                     'format' => 'yyyy-MM-dd HH:mm:ss.000',
  83.                     'ignore_malformed' => true,
  84.                 ];
  85.             case CustomFieldTypes::PRICE:
  86.             case CustomFieldTypes::JSON:
  87.                 return [
  88.                     'type' => 'object',
  89.                     'dynamic' => true,
  90.                 ];
  91.             case CustomFieldTypes::HTML:
  92.             case CustomFieldTypes::TEXT:
  93.                 return [
  94.                     'type' => 'text',
  95.                 ];
  96.             case CustomFieldTypes::COLORPICKER:
  97.             case CustomFieldTypes::ENTITY:
  98.             case CustomFieldTypes::MEDIA:
  99.             case CustomFieldTypes::SELECT:
  100.             case CustomFieldTypes::SWITCH:
  101.             default:
  102.                 return [
  103.                     'type' => 'keyword',
  104.                 ];
  105.         }
  106.     }
  107.     /**
  108.      * @param array<string, array<mixed>> $newCreatedFields
  109.      */
  110.     private function createNewFieldsInIndices(array $newCreatedFields): void
  111.     {
  112.         $indices $this->indexDetector->getAllUsedIndices();
  113.         foreach ($indices as $indexName) {
  114.             $body = [
  115.                 'properties' => [
  116.                     'customFields' => [
  117.                         'properties' => $newCreatedFields,
  118.                     ],
  119.                 ],
  120.             ];
  121.             // For some reason, we need to include the includes to prevent merge conflicts.
  122.             // This error can happen for example after updating from version <6.4.
  123.             $current $this->client->indices()->get(['index' => $indexName]);
  124.             $includes $current[$indexName]['mappings']['_source']['includes'] ?? [];
  125.             if ($includes !== []) {
  126.                 $body['_source'] = [
  127.                     'includes' => $includes,
  128.                 ];
  129.             }
  130.             $this->client->indices()->putMapping([
  131.                 'index' => $indexName,
  132.                 'body' => $body,
  133.             ]);
  134.         }
  135.     }
  136. }