You are here

public function EntityResource::createIndividual in JSON:API 8.2

Same name and namespace in other branches
  1. 8 src/Controller/EntityResource.php \Drupal\jsonapi\Controller\EntityResource::createIndividual()

Creates an individual entity.

Parameters

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

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

Return value

\Drupal\jsonapi\ResourceResponse The response.

Throws

\Symfony\Component\HttpKernel\Exception\ConflictHttpException Thrown when the entity already exists.

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

File

src/Controller/EntityResource.php, line 230

Class

EntityResource
Process all entity requests.

Namespace

Drupal\jsonapi\Controller

Code

public function createIndividual(ResourceType $resource_type, Request $request) {
  $parsed_entity = $this
    ->deserialize($resource_type, $request, JsonApiDocumentTopLevel::class);
  if ($parsed_entity instanceof FieldableEntityInterface) {

    // Only check 'edit' permissions for fields that were actually submitted
    // by the user. Field access makes no distinction between 'create' and
    // 'update', so the 'edit' operation is used here.
    $document = Json::decode($request
      ->getContent());
    foreach ([
      'attributes',
      'relationships',
    ] as $data_member_name) {
      if (isset($document['data'][$data_member_name])) {
        $valid_names = array_filter(array_map(function ($public_field_name) use ($resource_type) {
          return $resource_type
            ->getInternalName($public_field_name);
        }, array_keys($document['data'][$data_member_name])), function ($internal_field_name) use ($resource_type) {
          return $resource_type
            ->hasField($internal_field_name);
        });
        foreach ($valid_names as $field_name) {
          $field_access = $parsed_entity
            ->get($field_name)
            ->access('edit', NULL, TRUE);
          if (!$field_access
            ->isAllowed()) {
            $public_field_name = $resource_type
              ->getPublicName($field_name);
            throw new EntityAccessDeniedHttpException(NULL, $field_access, "/data/{$data_member_name}/{$public_field_name}", sprintf('The current user is not allowed to POST the selected field (%s).', $public_field_name));
          }
        }
      }
    }
  }
  static::validate($parsed_entity);

  // Return a 409 Conflict response in accordance with the JSON:API spec. See
  // http://jsonapi.org/format/#crud-creating-responses-409.
  if ($this
    ->entityExists($parsed_entity)) {
    throw new ConflictHttpException('Conflict: Entity already exists.');
  }
  $parsed_entity
    ->save();

  // Build response object.
  $resource_object = ResourceObject::createFromEntity($resource_type, $parsed_entity);
  $primary_data = new ResourceObjectData([
    $resource_object,
  ], 1);
  $response = $this
    ->buildWrappedResponse($primary_data, $request, $this
    ->getIncludes($request, $primary_data), 201);

  // According to JSON:API specification, when a new entity was created
  // we should send "Location" header to the frontend.
  if ($resource_type
    ->isLocatable()) {
    $url = $resource_object
      ->toUrl()
      ->setAbsolute()
      ->toString(TRUE);
    $response
      ->addCacheableDependency($url);
    $response->headers
      ->set('Location', $url
      ->getGeneratedUrl());
  }

  // Return response object with updated headers info.
  return $response;
}