public function EntityResource::addToRelationshipData in Drupal 8
Same name and namespace in other branches
- 9 core/modules/jsonapi/src/Controller/EntityResource.php \Drupal\jsonapi\Controller\EntityResource::addToRelationshipData()
Adds a relationship to a to-many relationship.
Parameters
\Drupal\jsonapi\ResourceType\ResourceType $resource_type: The base JSON:API resource type for the request to be served.
\Drupal\Core\Entity\FieldableEntityInterface $entity: The requested entity.
string $related: The related field name.
\Symfony\Component\HttpFoundation\Request $request: The request object.
Return value
\Drupal\jsonapi\ResourceResponse The response.
Throws
\Drupal\jsonapi\Exception\EntityAccessDeniedHttpException Thrown when the current user is not allowed to PATCH the selected field(s).
\Symfony\Component\HttpKernel\Exception\ConflictHttpException Thrown when POSTing to a "to-one" relationship.
\Drupal\Core\Entity\EntityStorageException Thrown when the underlying entity cannot be saved.
\Drupal\jsonapi\Exception\UnprocessableHttpEntityException Thrown when the updated entity does not pass validation.
File
- core/
modules/ jsonapi/ src/ Controller/ EntityResource.php, line 599
Class
- EntityResource
- Process all entity requests.
Namespace
Drupal\jsonapi\ControllerCode
public function addToRelationshipData(ResourceType $resource_type, FieldableEntityInterface $entity, $related, Request $request) {
$resource_identifiers = $this
->deserialize($resource_type, $request, ResourceIdentifier::class, $related);
$internal_relationship_field_name = $resource_type
->getInternalName($related);
// According to the specification, you are only allowed to POST to a
// relationship if it is a to-many relationship.
/* @var \Drupal\Core\Field\EntityReferenceFieldItemListInterface $field_list */
$field_list = $entity->{$internal_relationship_field_name};
/* @var \Drupal\field\Entity\FieldConfig $field_definition */
$field_definition = $field_list
->getFieldDefinition();
$is_multiple = $field_definition
->getFieldStorageDefinition()
->isMultiple();
if (!$is_multiple) {
throw new ConflictHttpException(sprintf('You can only POST to to-many relationships. %s is a to-one relationship.', $related));
}
$original_resource_identifiers = ResourceIdentifier::toResourceIdentifiersWithArityRequired($field_list);
$new_resource_identifiers = array_udiff(ResourceIdentifier::deduplicate(array_merge($original_resource_identifiers, $resource_identifiers)), $original_resource_identifiers, [
ResourceIdentifier::class,
'compare',
]);
// There are no relationships that need to be added so we can exit early.
if (empty($new_resource_identifiers)) {
$status = static::relationshipResponseRequiresBody($resource_identifiers, $original_resource_identifiers) ? 200 : 204;
return $this
->getRelationship($resource_type, $entity, $related, $request, $status);
}
$main_property_name = $field_definition
->getItemDefinition()
->getMainPropertyName();
foreach ($new_resource_identifiers as $new_resource_identifier) {
$new_field_value = [
$main_property_name => $this
->getEntityFromResourceIdentifier($new_resource_identifier)
->id(),
];
// Remove `arity` from the received extra properties, otherwise this
// will fail field validation.
$new_field_value += array_diff_key($new_resource_identifier
->getMeta(), array_flip([
ResourceIdentifier::ARITY_KEY,
]));
$field_list
->appendItem($new_field_value);
}
$this
->validate($entity);
$entity
->save();
$final_resource_identifiers = ResourceIdentifier::toResourceIdentifiersWithArityRequired($field_list);
$status = static::relationshipResponseRequiresBody($resource_identifiers, $final_resource_identifiers) ? 200 : 204;
return $this
->getRelationship($resource_type, $entity, $related, $request, $status);
}