src/Core/Framework/DataAbstractionLayer/FieldSerializer/CustomFieldsSerializer.php line 93

  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\DataStack\KeyValuePair;
  9. use Shopware\Core\Framework\DataAbstractionLayer\Write\EntityExistence;
  10. use Shopware\Core\Framework\DataAbstractionLayer\Write\WriteCommandExtractor;
  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\System\CustomField\CustomFieldService;
  15. use Symfony\Component\Validator\Validator\ValidatorInterface;
  16. /**
  17.  * @internal
  18.  */
  19. #[Package('core')]
  20. class CustomFieldsSerializer extends JsonFieldSerializer
  21. {
  22.     /**
  23.      * @internal
  24.      */
  25.     public function __construct(
  26.         DefinitionInstanceRegistry $compositeHandler,
  27.         ValidatorInterface $validator,
  28.         private readonly CustomFieldService $attributeService,
  29.         private readonly WriteCommandExtractor $writeExtractor
  30.     ) {
  31.         parent::__construct($validator$compositeHandler);
  32.     }
  33.     public function encode(Field $fieldEntityExistence $existenceKeyValuePair $dataWriteParameterBag $parameters): \Generator
  34.     {
  35.         if (!$field instanceof CustomFields) {
  36.             throw new InvalidSerializerFieldException(CustomFields::class, $field);
  37.         }
  38.         $this->validateIfNeeded($field$existence$data$parameters);
  39.         $attributes $data->getValue();
  40.         if ($attributes === null) {
  41.             yield $field->getStorageName() => null;
  42.             return;
  43.         }
  44.         if (empty($attributes)) {
  45.             yield $field->getStorageName() => '{}';
  46.             return;
  47.         }
  48.         // set fields dynamically
  49.         $field->setPropertyMapping($this->getFields(array_keys($attributes)));
  50.         $encoded $this->validateMapping($field$attributes$parameters);
  51.         if (empty($encoded)) {
  52.             return;
  53.         }
  54.         if ($existence->exists()) {
  55.             $this->writeExtractor->extractJsonUpdate([$field->getStorageName() => $encoded], $existence$parameters);
  56.             return;
  57.         }
  58.         yield $field->getStorageName() => Json::encode($encoded);
  59.     }
  60.     public function decode(Field $fieldmixed $value): array|object|null
  61.     {
  62.         if (!$field instanceof CustomFields) {
  63.             throw new InvalidSerializerFieldException(CustomFields::class, $field);
  64.         }
  65.         if ($value) {
  66.             // set fields dynamically
  67.             $field->setPropertyMapping($this->getFields(array_keys(json_decode((string) $valuetrue512\JSON_THROW_ON_ERROR))));
  68.         }
  69.         return parent::decode($field$value);
  70.     }
  71.     private function getFields(array $attributeNames): array
  72.     {
  73.         $fields = [];
  74.         foreach ($attributeNames as $attributeName) {
  75.             $fields[] = $this->attributeService->getCustomField($attributeName)
  76.                 ?? new JsonField($attributeName$attributeName);
  77.         }
  78.         return $fields;
  79.     }
  80. }