You are here

public function ResourceIdentifierNormalizer::denormalize in Drupal 9

Same name and namespace in other branches
  1. 8 core/modules/jsonapi/src/Normalizer/ResourceIdentifierNormalizer.php \Drupal\jsonapi\Normalizer\ResourceIdentifierNormalizer::denormalize()

File

core/modules/jsonapi/src/Normalizer/ResourceIdentifierNormalizer.php, line 66

Class

ResourceIdentifierNormalizer
Normalizes a Relationship according to the JSON:API specification.

Namespace

Drupal\jsonapi\Normalizer

Code

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

  // If we get here, it's via a relationship POST/PATCH.

  /** @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($resource_type
    ->getPublicName($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);
  $resource_identifiers = 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 match the destination resource types (%s).', $value['type'], implode(', ', $target_resource_type_names)));
    }
    return new ResourceIdentifier($value['type'], $value['id'], isset($value['meta']) ? $value['meta'] : []);
  }, $data['data']);
  if (!ResourceIdentifier::areResourceIdentifiersUnique($resource_identifiers)) {
    throw new BadRequestHttpException('Duplicate relationships are not permitted. Use `meta.arity` to distinguish resource identifiers with matching `type` and `id` values.');
  }
  return $resource_identifiers;
}