You are here

public function EntityResource::patchIndividual in Drupal 9

Same name and namespace in other branches
  1. 8 core/modules/jsonapi/src/Controller/EntityResource.php \Drupal\jsonapi\Controller\EntityResource::patchIndividual()
  2. 10 core/modules/jsonapi/src/Controller/EntityResource.php \Drupal\jsonapi\Controller\EntityResource::patchIndividual()

Patches an individual entity.

Parameters

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

\Drupal\Core\Entity\EntityInterface $entity: The loaded entity.

\Symfony\Component\HttpFoundation\Request $request: The request object.

Return value

\Drupal\jsonapi\ResourceResponse The response.

Throws

\Symfony\Component\HttpKernel\Exception\BadRequestHttpException Thrown when the selected entity does not match the id in th payload.

\Drupal\jsonapi\Exception\UnprocessableHttpEntityException Thrown when the patched entity does not pass validation.

File

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

Class

EntityResource
Process all entity requests.

Namespace

Drupal\jsonapi\Controller

Code

public function patchIndividual(ResourceType $resource_type, EntityInterface $entity, Request $request) {
  if ($entity instanceof RevisionableInterface && !($entity
    ->isLatestRevision() && $entity
    ->isDefaultRevision())) {
    throw new BadRequestHttpException('Updating a resource object that has a working copy is not yet supported. See https://www.drupal.org/project/drupal/issues/2795279.');
  }
  $parsed_entity = $this
    ->deserialize($resource_type, $request, JsonApiDocumentTopLevel::class);
  $body = Json::decode($request
    ->getContent());
  $data = $body['data'];
  if ($data['id'] != $entity
    ->uuid()) {
    throw new BadRequestHttpException(sprintf('The selected entity (%s) does not match the ID in the payload (%s).', $entity
      ->uuid(), $data['id']));
  }
  $data += [
    'attributes' => [],
    'relationships' => [],
  ];
  $field_names = array_map([
    $resource_type,
    'getInternalName',
  ], array_merge(array_keys($data['attributes']), array_keys($data['relationships'])));

  // User resource objects contain a read-only attribute that is not a real
  // field on the user entity type.
  // @see \Drupal\jsonapi\JsonApiResource\ResourceObject::extractContentEntityFields()
  // @todo: eliminate this special casing in https://www.drupal.org/project/drupal/issues/3079254.
  if ($entity
    ->getEntityTypeId() === 'user') {
    $field_names = array_diff($field_names, [
      $resource_type
        ->getPublicName('display_name'),
    ]);
  }
  array_reduce($field_names, function (EntityInterface $destination, $field_name) use ($resource_type, $parsed_entity) {
    $this
      ->updateEntityField($resource_type, $parsed_entity, $destination, $field_name);
    return $destination;
  }, $entity);
  static::validate($entity, $field_names);

  // Set revision data details for revisionable entities.
  if ($entity
    ->getEntityType()
    ->isRevisionable()) {
    if ($bundle_entity_type = $entity
      ->getEntityType()
      ->getBundleEntityType()) {
      $bundle_entity = $this->entityTypeManager
        ->getStorage($bundle_entity_type)
        ->load($entity
        ->bundle());
      if ($bundle_entity instanceof RevisionableEntityBundleInterface) {
        $entity
          ->setNewRevision($bundle_entity
          ->shouldCreateNewRevision());
      }
    }
    if ($entity instanceof RevisionLogInterface && $entity
      ->isNewRevision()) {
      $entity
        ->setRevisionUserId($this->user
        ->id());
      $entity
        ->setRevisionCreationTime($this->time
        ->getRequestTime());
    }
  }
  $entity
    ->save();
  $primary_data = new ResourceObjectData([
    ResourceObject::createFromEntity($resource_type, $entity),
  ], 1);
  return $this
    ->buildWrappedResponse($primary_data, $request, $this
    ->getIncludes($request, $primary_data));
}