You are here

public function EntityResource::removeFromRelationshipData in JSON:API 8.2

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

src/Controller/EntityResource.php, line 732

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);

  /* @var \Drupal\Core\Field\EntityReferenceFieldItemListInterface $field_list */
  $field_list = $entity->{$related};
  $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);
}