vendor/shopware/core/Framework/DataAbstractionLayer/FieldSerializer/CustomFieldsSerializer.php line 102

  1. <?php declare(strict_types=1);
  2. namespace Shopware\Core\Framework\DataAbstractionLayer\FieldSerializer;
  3. use Shopware\Core\Framework\DataAbstractionLayer\DefinitionInstanceRegistry;
  4. use Shopware\Core\Framework\DataAbstractionLayer\Exception\InvalidSerializerFieldException;
  5. use Shopware\Core\Framework\DataAbstractionLayer\Field\CustomFields;
  6. use Shopware\Core\Framework\DataAbstractionLayer\Field\Field;
  7. use Shopware\Core\Framework\DataAbstractionLayer\Field\JsonField;
  8. use Shopware\Core\Framework\DataAbstractionLayer\Write\Command\JsonUpdateCommand;
  9. use Shopware\Core\Framework\DataAbstractionLayer\Write\DataStack\KeyValuePair;
  10. use Shopware\Core\Framework\DataAbstractionLayer\Write\EntityExistence;
  11. use Shopware\Core\Framework\DataAbstractionLayer\Write\WriteParameterBag;
  12. use Shopware\Core\Framework\Log\Package;
  13. use Shopware\Core\Framework\Util\Json;
  14. use Shopware\Core\Framework\Uuid\Uuid;
  15. use Shopware\Core\System\CustomField\CustomFieldService;
  16. use Symfony\Component\Validator\Validator\ValidatorInterface;
  17. /**
  18.  * @internal
  19.  */
  20. #[Package('core')]
  21. class CustomFieldsSerializer extends JsonFieldSerializer
  22. {
  23.     public function __construct(
  24.         DefinitionInstanceRegistry $definitionRegistry,
  25.         ValidatorInterface $validator,
  26.         private readonly CustomFieldService $attributeService
  27.     ) {
  28.         parent::__construct($validator$definitionRegistry);
  29.     }
  30.     public function encode(Field $fieldEntityExistence $existenceKeyValuePair $dataWriteParameterBag $parameters): \Generator
  31.     {
  32.         if (!$field instanceof CustomFields) {
  33.             throw new InvalidSerializerFieldException(CustomFields::class, $field);
  34.         }
  35.         $this->validateIfNeeded($field$existence$data$parameters);
  36.         $attributes $data->getValue();
  37.         if ($attributes === null) {
  38.             yield $field->getStorageName() => null;
  39.             return;
  40.         }
  41.         if (empty($attributes)) {
  42.             yield $field->getStorageName() => '{}';
  43.             return;
  44.         }
  45.         // set fields dynamically
  46.         /** @var array<string, mixed> $attributes */
  47.         $field->setPropertyMapping($this->getFields(array_keys($attributes)));
  48.         $encoded $this->validateMapping($field$attributes$parameters);
  49.         if (empty($encoded)) {
  50.             return;
  51.         }
  52.         if ($existence->exists()) {
  53.             $this->extractJsonUpdate([$field->getStorageName() => $encoded], $existence$parameters);
  54.             return;
  55.         }
  56.         yield $field->getStorageName() => Json::encode($encoded);
  57.     }
  58.     /**
  59.      * @return array<string, mixed>|object|null
  60.      */
  61.     public function decode(Field $fieldmixed $value): array|object|null
  62.     {
  63.         if (!$field instanceof CustomFields) {
  64.             throw new InvalidSerializerFieldException(CustomFields::class, $field);
  65.         }
  66.         if ($value) {
  67.             // set fields dynamically
  68.             /** @var array<string> $attributes */
  69.             $attributes array_keys(json_decode((string) $valuetrue512\JSON_THROW_ON_ERROR));
  70.             $field->setPropertyMapping($this->getFields($attributes));
  71.         }
  72.         return parent::decode($field$value);
  73.     }
  74.     /**
  75.      * @param array<string> $attributeNames
  76.      *
  77.      * @return array<Field>
  78.      */
  79.     private function getFields(array $attributeNames): array
  80.     {
  81.         $fields = [];
  82.         foreach ($attributeNames as $attributeName) {
  83.             $fields[] = $this->attributeService->getCustomField($attributeName)
  84.                 ?? new JsonField($attributeName$attributeName);
  85.         }
  86.         return $fields;
  87.     }
  88.     /**
  89.      * @param array<string, array<string, mixed>> $data
  90.      */
  91.     private function extractJsonUpdate(array $dataEntityExistence $existenceWriteParameterBag $parameters): void
  92.     {
  93.         foreach ($data as $storageName => $attributes) {
  94.             $entityName $existence->getEntityName();
  95.             if (!$entityName) {
  96.                 continue;
  97.             }
  98.             $definition $this->definitionRegistry->getByEntityName($entityName);
  99.             $pks Uuid::fromHexToBytesList($existence->getPrimaryKey());
  100.             $jsonUpdateCommand = new JsonUpdateCommand(
  101.                 $definition,
  102.                 $storageName,
  103.                 $attributes,
  104.                 $pks,
  105.                 $existence,
  106.                 $parameters->getPath()
  107.             );
  108.             $parameters->getCommandQueue()->add($jsonUpdateCommand->getDefinition(), $jsonUpdateCommand);
  109.         }
  110.     }
  111. }