function EntityResource::removeFromRelationshipData

Same name in other branches
  1. 8.9.x core/modules/jsonapi/src/Controller/EntityResource.php \Drupal\jsonapi\Controller\EntityResource::removeFromRelationshipData()
  2. 10 core/modules/jsonapi/src/Controller/EntityResource.php \Drupal\jsonapi\Controller\EntityResource::removeFromRelationshipData()
  3. 11.x core/modules/jsonapi/src/Controller/EntityResource.php \Drupal\jsonapi\Controller\EntityResource::removeFromRelationshipData()

Deletes the relationship of an entity.

Parameters

\Drupal\jsonapi\ResourceType\ResourceType $resource_type: The base JSON:API resource type for the request to be served.

\Drupal\Core\Entity\EntityInterface $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

\Symfony\Component\HttpKernel\Exception\BadRequestHttpException Thrown when not body was provided for the DELETE operation.

\Symfony\Component\HttpKernel\Exception\ConflictHttpException Thrown when deleting a "to-one" relationship.

\Drupal\Core\Entity\EntityStorageException Thrown when the underlying entity cannot be saved.

File

core/modules/jsonapi/src/Controller/EntityResource.php, line 769

Class

EntityResource
Process all entity requests.

Namespace

Drupal\jsonapi\Controller

Code

public function removeFromRelationshipData(ResourceType $resource_type, EntityInterface $entity, $related, Request $request) {
    $resource_identifiers = $this->deserialize($resource_type, $request, ResourceIdentifier::class, $related);
    $internal_relationship_field_name = $resource_type->getInternalName($related);
    
    /** @var \Drupal\Core\Field\EntityReferenceFieldItemListInterface $field_list */
    $field_list = $entity->{$internal_relationship_field_name};
    $is_multiple = $field_list->getFieldDefinition()
        ->getFieldStorageDefinition()
        ->isMultiple();
    if (!$is_multiple) {
        throw new ConflictHttpException(sprintf('You can only DELETE from to-many relationships. %s is a to-one relationship.', $related));
    }
    // Compute the list of current values and remove the ones in the payload.
    $original_resource_identifiers = ResourceIdentifier::toResourceIdentifiersWithArityRequired($field_list);
    $removed_resource_identifiers = array_uintersect($resource_identifiers, $original_resource_identifiers, [
        ResourceIdentifier::class,
        'compare',
    ]);
    $deltas_to_be_removed = [];
    foreach ($removed_resource_identifiers as $removed_resource_identifier) {
        foreach ($original_resource_identifiers as $delta => $existing_resource_identifier) {
            // Identify the field item deltas which should be removed.
            if (ResourceIdentifier::isDuplicate($removed_resource_identifier, $existing_resource_identifier)) {
                $deltas_to_be_removed[] = $delta;
            }
        }
    }
    // Field item deltas are reset when an item is removed. This removes
    // items in descending order so that the deltas yet to be removed will
    // continue to exist.
    rsort($deltas_to_be_removed);
    foreach ($deltas_to_be_removed as $delta) {
        $field_list->removeItem($delta);
    }
    // Save the entity and return the response object.
    static::validate($entity);
    $entity->save();
    return $this->getRelationship($resource_type, $entity, $related, $request, 204);
}

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.