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

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