function EntityResource::createIndividual

Same name in other branches
  1. 9 core/modules/jsonapi/src/Controller/EntityResource.php \Drupal\jsonapi\Controller\EntityResource::createIndividual()
  2. 10 core/modules/jsonapi/src/Controller/EntityResource.php \Drupal\jsonapi\Controller\EntityResource::createIndividual()
  3. 11.x core/modules/jsonapi/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

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

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());
        $field_mapping = array_map(function (ResourceTypeField $field) {
            return $field->getPublicName();
        }, $resource_type->getFields());
        // 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 ($resource_type->getEntityTypeId() === 'user') {
            $field_mapping = array_diff($field_mapping, [
                $resource_type->getPublicName('display_name'),
            ]);
        }
        foreach ([
            'attributes',
            'relationships',
        ] as $data_member_name) {
            if (isset($document['data'][$data_member_name])) {
                foreach (array_intersect_key(array_flip($field_mapping), $document['data'][$data_member_name]) as $internal_field_name) {
                    $field_access = $parsed_entity->get($internal_field_name)
                        ->access('edit', NULL, TRUE);
                    if (!$field_access->isAllowed()) {
                        $public_field_name = $field_mapping[$internal_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;
}

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