View source
<?php
namespace Drupal\jsonapi\Normalizer;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Field\FieldItemInterface;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\TypedData\FieldItemDataDefinitionInterface;
use Drupal\Core\TypedData\TypedDataInternalPropertiesHelper;
use Drupal\jsonapi\Normalizer\Value\CacheableNormalization;
use Drupal\jsonapi\ResourceType\ResourceType;
use Drupal\serialization\Normalizer\CacheableNormalizerInterface;
use Drupal\serialization\Normalizer\SerializedColumnNormalizerTrait;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
class FieldItemNormalizer extends NormalizerBase implements DenormalizerInterface {
use SerializedColumnNormalizerTrait;
protected $supportedInterfaceOrClass = FieldItemInterface::class;
protected $entityTypeManager;
public function __construct(EntityTypeManagerInterface $entity_type_manager) {
$this->entityTypeManager = $entity_type_manager;
}
public function normalize($field_item, $format = NULL, array $context = []) {
assert($field_item instanceof FieldItemInterface);
$values = [];
$context[CacheableNormalizerInterface::SERIALIZATION_CONTEXT_CACHEABILITY] = new CacheableMetadata();
if (!empty($field_item
->getProperties(TRUE))) {
$field_properties = TypedDataInternalPropertiesHelper::getNonInternalProperties($field_item);
foreach ($field_properties as $property_name => $property) {
$values[$property_name] = $this->serializer
->normalize($property, $format, $context);
}
$flatten = count($field_properties) === 1 && $field_item::mainPropertyName() !== NULL;
$values = static::rasterizeValueRecursive($flatten ? reset($values) : $values);
}
else {
$values = $field_item
->getValue();
}
$normalization = new CacheableNormalization($context[CacheableNormalizerInterface::SERIALIZATION_CONTEXT_CACHEABILITY], $values);
unset($context[CacheableNormalizerInterface::SERIALIZATION_CONTEXT_CACHEABILITY]);
return $normalization;
}
public function denormalize($data, $class, $format = NULL, array $context = []) {
$item_definition = $context['field_definition']
->getItemDefinition();
assert($item_definition instanceof FieldItemDataDefinitionInterface);
$field_item = $this
->getFieldItemInstance($context['resource_type'], $item_definition);
$this
->checkForSerializedStrings($data, $class, $field_item);
$property_definitions = $item_definition
->getPropertyDefinitions();
$serialized_property_names = $this
->getCustomSerializedPropertyNames($field_item);
$denormalize_property = function ($property_name, $property_value, $property_value_class, $format, $context) use ($serialized_property_names) {
if ($this->serializer
->supportsDenormalization($property_value, $property_value_class, $format, $context)) {
return $this->serializer
->denormalize($property_value, $property_value_class, $format, $context);
}
else {
if (in_array($property_name, $serialized_property_names, TRUE)) {
$property_value = serialize($property_value);
}
return $property_value;
}
};
if (!is_array($data)) {
if ($data === NULL) {
return $data;
}
$property_value = $data;
$property_name = $item_definition
->getMainPropertyName();
$property_value_class = $property_definitions[$property_name]
->getClass();
return $denormalize_property($property_name, $property_value, $property_value_class, $format, $context);
}
$data_internal = [];
if (!empty($property_definitions)) {
foreach ($data as $property_name => $property_value) {
$property_value_class = $property_definitions[$property_name]
->getClass();
$data_internal[$property_name] = $denormalize_property($property_name, $property_value, $property_value_class, $format, $context);
}
}
else {
$data_internal = $data;
}
return $data_internal;
}
protected function getFieldItemInstance(ResourceType $resource_type, FieldItemDataDefinitionInterface $item_definition) {
if ($bundle_key = $this->entityTypeManager
->getDefinition($resource_type
->getEntityTypeId())
->getKey('bundle')) {
$create_values = [
$bundle_key => $resource_type
->getBundle(),
];
}
else {
$create_values = [];
}
$entity = $this->entityTypeManager
->getStorage($resource_type
->getEntityTypeId())
->create($create_values);
$field = $entity
->get($item_definition
->getFieldDefinition()
->getName());
assert($field instanceof FieldItemListInterface);
$field_item = $field
->appendItem();
assert($field_item instanceof FieldItemInterface);
return $field_item;
}
}