class FieldItemNormalizer in Drupal 9
Same name in this branch
- 9 core/modules/jsonapi/src/Normalizer/FieldItemNormalizer.php \Drupal\jsonapi\Normalizer\FieldItemNormalizer
- 9 core/modules/hal/src/Normalizer/FieldItemNormalizer.php \Drupal\hal\Normalizer\FieldItemNormalizer
- 9 core/modules/serialization/src/Normalizer/FieldItemNormalizer.php \Drupal\serialization\Normalizer\FieldItemNormalizer
Same name and namespace in other branches
- 8 core/modules/jsonapi/src/Normalizer/FieldItemNormalizer.php \Drupal\jsonapi\Normalizer\FieldItemNormalizer
Converts the Drupal field item object to a JSON:API array structure.
@internal JSON:API maintains no PHP API since its API is the HTTP API. This class may change at any time and this will break any dependencies on it.
Hierarchy
- class \Drupal\serialization\Normalizer\NormalizerBase implements \Symfony\Component\Serializer\SerializerAwareInterface, CacheableNormalizerInterface uses \Symfony\Component\Serializer\SerializerAwareTrait
- class \Drupal\jsonapi\Normalizer\NormalizerBase
- class \Drupal\jsonapi\Normalizer\FieldItemNormalizer implements \Symfony\Component\Serializer\Normalizer\DenormalizerInterface uses SerializedColumnNormalizerTrait
- class \Drupal\jsonapi\Normalizer\NormalizerBase
Expanded class hierarchy of FieldItemNormalizer
See also
https://www.drupal.org/project/drupal/issues/3032787
1 file declares its use of FieldItemNormalizer
- FieldItemNormalizerTest.php in core/
modules/ jsonapi/ tests/ src/ Kernel/ Normalizer/ FieldItemNormalizerTest.php
1 string reference to 'FieldItemNormalizer'
- jsonapi.services.yml in core/
modules/ jsonapi/ jsonapi.services.yml - core/modules/jsonapi/jsonapi.services.yml
1 service uses FieldItemNormalizer
File
- core/
modules/ jsonapi/ src/ Normalizer/ FieldItemNormalizer.php, line 26
Namespace
Drupal\jsonapi\NormalizerView source
class FieldItemNormalizer extends NormalizerBase implements DenormalizerInterface {
use SerializedColumnNormalizerTrait;
/**
* The interface or class that this Normalizer supports.
*
* @var string
*/
protected $supportedInterfaceOrClass = FieldItemInterface::class;
/**
* The entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* FieldItemNormalizer constructor.
*
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager.
*/
public function __construct(EntityTypeManagerInterface $entity_type_manager) {
$this->entityTypeManager = $entity_type_manager;
}
/**
* {@inheritdoc}
*
* This normalizer leaves JSON:API normalizer land and enters the land of
* Drupal core's serialization system. That system was never designed with
* cacheability in mind, and hence bubbles cacheability out of band. This must
* catch it, and pass it to the value object that JSON:API uses.
*/
public function normalize($field_item, $format = NULL, array $context = []) {
assert($field_item instanceof FieldItemInterface);
/** @var \Drupal\Core\TypedData\TypedDataInterface $property */
$values = [];
$context[CacheableNormalizerInterface::SERIALIZATION_CONTEXT_CACHEABILITY] = new CacheableMetadata();
if (!empty($field_item
->getProperties(TRUE))) {
// We normalize each individual value, so each can do their own casting,
// if needed.
$field_properties = TypedDataInternalPropertiesHelper::getNonInternalProperties($field_item);
foreach ($field_properties as $property_name => $property) {
$values[$property_name] = $this->serializer
->normalize($property, $format, $context);
}
// Flatten if there is only a single property to normalize.
$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;
}
/**
* {@inheritdoc}
*/
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;
}
};
// Because e.g. the 'bundle' entity key field requires field values to not
// be expanded to an array of all properties, we special-case single-value
// properties.
if (!is_array($data)) {
// The NULL normalization means there is no value, hence we can return
// early. Note that this is not just an optimization but a necessity for
// field types without main properties (such as the "map" field type).
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;
}
/**
* Gets a field item instance for use with SerializedColumnNormalizerTrait.
*
* @param \Drupal\jsonapi\ResourceType\ResourceType $resource_type
* The JSON:API resource type of the entity being denormalized.
* @param \Drupal\Core\Field\TypedData\FieldItemDataDefinitionInterface $item_definition
* The field item definition of the instance to get.
*
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
*/
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;
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
CacheableNormalizerInterface:: |
constant | Name of key for bubbling cacheability metadata via serialization context. | ||
FieldItemNormalizer:: |
protected | property | The entity type manager. | |
FieldItemNormalizer:: |
protected | property |
The interface or class that this Normalizer supports. Overrides NormalizerBase:: |
|
FieldItemNormalizer:: |
public | function | ||
FieldItemNormalizer:: |
protected | function | Gets a field item instance for use with SerializedColumnNormalizerTrait. | |
FieldItemNormalizer:: |
public | function | This normalizer leaves JSON:API normalizer land and enters the land of Drupal core's serialization system. That system was never designed with cacheability in mind, and hence bubbles cacheability out of band. This must catch it, and pass it to… | |
FieldItemNormalizer:: |
public | function | FieldItemNormalizer constructor. | |
NormalizerBase:: |
protected | property |
List of formats which supports (de-)normalization. Overrides NormalizerBase:: |
|
NormalizerBase:: |
protected | function | Adds cacheability if applicable. | |
NormalizerBase:: |
protected | function |
Checks if the provided format is supported by this normalizer. Overrides NormalizerBase:: |
|
NormalizerBase:: |
protected static | function | Rasterizes a value recursively. | |
NormalizerBase:: |
public | function | Implements \Symfony\Component\Serializer\Normalizer\DenormalizerInterface::supportsDenormalization() | 1 |
NormalizerBase:: |
public | function | 1 | |
SerializedColumnNormalizerTrait:: |
protected | function | Checks if there is a serialized string for a column. | |
SerializedColumnNormalizerTrait:: |
protected | function | Checks if the data contains string value for serialize column. | |
SerializedColumnNormalizerTrait:: |
protected | function | Gets the names of all properties the plugin treats as serialized data. | |
SerializedColumnNormalizerTrait:: |
protected | function | Gets the names of all serialized properties. |