You are here

public function EntityReferenceFieldNormalizer::denormalize in JSON:API 8

Overrides FieldNormalizer::denormalize

File

src/Normalizer/EntityReferenceFieldNormalizer.php, line 153

Class

EntityReferenceFieldNormalizer
Normalizer class specific for entity reference field objects.

Namespace

Drupal\jsonapi\Normalizer

Code

public function denormalize($data, $class, $format = NULL, array $context = []) {

  // If we get to here is through a write method on a relationship operation.

  /** @var \Drupal\jsonapi\ResourceType\ResourceType $resource_type */
  $resource_type = $context['resource_type'];
  $entity_type_id = $resource_type
    ->getEntityTypeId();
  $field_definitions = $this->fieldManager
    ->getFieldDefinitions($entity_type_id, $resource_type
    ->getBundle());
  if (empty($context['related']) || empty($field_definitions[$context['related']])) {
    throw new BadRequestHttpException('Invalid or missing related field.');
  }

  /* @var \Drupal\field\Entity\FieldConfig $field_definition */
  $field_definition = $field_definitions[$context['related']];

  // This is typically 'target_id'.
  $item_definition = $field_definition
    ->getItemDefinition();
  $property_key = $item_definition
    ->getMainPropertyName();
  $target_resource_types = $resource_type
    ->getRelatableResourceTypesByField($context['related']);
  $target_resource_type_names = array_map(function (ResourceType $resource_type) {
    return $resource_type
      ->getTypeName();
  }, $target_resource_types);
  $is_multiple = $field_definition
    ->getFieldStorageDefinition()
    ->isMultiple();
  $data = $this
    ->massageRelationshipInput($data, $is_multiple);
  $values = array_map(function ($value) use ($property_key, $target_resource_type_names) {

    // Make sure that the provided type is compatible with the targeted
    // resource.
    if (!in_array($value['type'], $target_resource_type_names)) {
      throw new BadRequestHttpException(sprintf('The provided type (%s) does not mach the destination resource types (%s).', $value['type'], implode(', ', $target_resource_type_names)));
    }

    // Load the entity by UUID.
    list($entity_type_id, ) = explode('--', $value['type']);
    $entity = $this->entityRepository
      ->loadEntityByUuid($entity_type_id, $value['id']);
    $value['id'] = $entity ? $entity
      ->id() : NULL;
    $properties = [
      $property_key => $value['id'],
    ];

    // Also take into account additional properties provided by the field
    // type.
    if (!empty($value['meta'])) {
      foreach ($value['meta'] as $meta_key => $meta_value) {
        $properties[$meta_key] = $meta_value;
      }
    }
    return $properties;
  }, $data['data']);
  return $this->pluginManager
    ->createFieldItemList($context['target_entity'], $context['related'], $values);
}