class FileUpload
Same name in other branches
- 8.9.x core/modules/jsonapi/src/Controller/FileUpload.php \Drupal\jsonapi\Controller\FileUpload
- 10 core/modules/jsonapi/src/Controller/FileUpload.php \Drupal\jsonapi\Controller\FileUpload
- 11.x core/modules/jsonapi/src/Controller/FileUpload.php \Drupal\jsonapi\Controller\FileUpload
Handles file upload requests.
@internal JSON:API maintains no PHP API. The API is the HTTP API. This class may change at any time and could break any dependencies on it.
Hierarchy
- class \Drupal\jsonapi\Controller\FileUpload uses \Drupal\jsonapi\Entity\EntityValidationTrait
Expanded class hierarchy of FileUpload
See also
https://www.drupal.org/project/drupal/issues/3032787
2 string references to 'FileUpload'
- jsonapi.services.yml in core/
modules/ jsonapi/ jsonapi.services.yml - core/modules/jsonapi/jsonapi.services.yml
- ManagedFile::processManagedFile in core/
modules/ file/ src/ Element/ ManagedFile.php - Render API callback: Expands the managed_file element type.
1 service uses FileUpload
- jsonapi.file_upload in core/
modules/ jsonapi/ jsonapi.services.yml - Drupal\jsonapi\Controller\FileUpload
File
-
core/
modules/ jsonapi/ src/ Controller/ FileUpload.php, line 40
Namespace
Drupal\jsonapi\ControllerView source
class FileUpload {
use EntityValidationTrait;
/**
* The current user making the request.
*
* @var \Drupal\Core\Session\AccountInterface
*/
protected $currentUser;
/**
* The field manager.
*
* @var \Drupal\Core\Entity\EntityFieldManagerInterface
*/
protected $fieldManager;
/**
* The file uploader.
*
* @var \Drupal\jsonapi\Controller\TemporaryJsonapiFileFieldUploader
*/
protected $fileUploader;
/**
* An HTTP kernel for making subrequests.
*
* @var \Symfony\Component\HttpKernel\HttpKernelInterface
*/
protected $httpKernel;
/**
* Creates a new FileUpload instance.
*
* @param \Drupal\Core\Session\AccountInterface $current_user
* The current user.
* @param \Drupal\Core\Entity\EntityFieldManagerInterface $field_manager
* The entity field manager.
* @param \Drupal\jsonapi\Controller\TemporaryJsonapiFileFieldUploader $file_uploader
* The file uploader.
* @param \Symfony\Component\HttpKernel\HttpKernelInterface $http_kernel
* An HTTP kernel for making subrequests.
*/
public function __construct(AccountInterface $current_user, EntityFieldManagerInterface $field_manager, TemporaryJsonapiFileFieldUploader $file_uploader, HttpKernelInterface $http_kernel) {
$this->currentUser = $current_user;
$this->fieldManager = $field_manager;
$this->fileUploader = $file_uploader;
$this->httpKernel = $http_kernel;
}
/**
* Handles JSON:API file upload requests.
*
* @param \Symfony\Component\HttpFoundation\Request $request
* The HTTP request object.
* @param \Drupal\jsonapi\ResourceType\ResourceType $resource_type
* The JSON:API resource type for the current request.
* @param string $file_field_name
* The file field for which the file is to be uploaded.
* @param \Drupal\Core\Entity\FieldableEntityInterface $entity
* The entity for which the file is to be uploaded.
*
* @return \Drupal\jsonapi\ResourceResponse
* The response object.
*
* @throws \Symfony\Component\HttpKernel\Exception\UnprocessableEntityHttpException
* Thrown when there are validation errors.
* @throws \Drupal\Core\Entity\EntityStorageException
* Thrown if the upload's target resource could not be saved.
* @throws \Exception
* Thrown if an exception occurs during a subrequest to fetch the newly
* created file entity.
*/
public function handleFileUploadForExistingResource(Request $request, ResourceType $resource_type, $file_field_name, FieldableEntityInterface $entity) {
$file_field_name = $resource_type->getInternalName($file_field_name);
$field_definition = $this->validateAndLoadFieldDefinition($resource_type->getEntityTypeId(), $resource_type->getBundle(), $file_field_name);
static::ensureFileUploadAccess($this->currentUser, $field_definition, $entity);
$filename = $this->fileUploader
->validateAndParseContentDispositionHeader($request);
$file = $this->fileUploader
->handleFileUploadForField($field_definition, $filename, $this->currentUser);
if ($file instanceof EntityConstraintViolationListInterface) {
$violations = $file;
$message = "Unprocessable Entity: file validation failed.\n";
$message .= implode("\n", array_map(function (ConstraintViolationInterface $violation) {
return PlainTextOutput::renderFromHtml($violation->getMessage());
}, (array) $violations->getIterator()));
throw new UnprocessableEntityHttpException($message);
}
if ($resource_type->getFieldByInternalName($file_field_name)
->hasOne()) {
$entity->{$file_field_name} = $file;
}
else {
$entity->get($file_field_name)
->appendItem($file);
}
static::validate($entity, [
$file_field_name,
]);
$entity->save();
$route_parameters = [
'entity' => $entity->uuid(),
];
$route_name = sprintf('jsonapi.%s.%s.related', $resource_type->getTypeName(), $resource_type->getPublicName($file_field_name));
$related_url = Url::fromRoute($route_name, $route_parameters)->toString(TRUE);
$request = Request::create($related_url->getGeneratedUrl(), 'GET', [], $request->cookies
->all(), [], $request->server
->all());
return $this->httpKernel
->handle($request, HttpKernelInterface::SUB_REQUEST);
}
/**
* Handles JSON:API file upload requests.
*
* @param \Symfony\Component\HttpFoundation\Request $request
* The HTTP request object.
* @param \Drupal\jsonapi\ResourceType\ResourceType $resource_type
* The JSON:API resource type for the current request.
* @param string $file_field_name
* The file field for which the file is to be uploaded.
*
* @return \Drupal\jsonapi\ResourceResponse
* The response object.
*
* @throws \Symfony\Component\HttpKernel\Exception\UnprocessableEntityHttpException
* Thrown when there are validation errors.
*/
public function handleFileUploadForNewResource(Request $request, ResourceType $resource_type, $file_field_name) {
$file_field_name = $resource_type->getInternalName($file_field_name);
$field_definition = $this->validateAndLoadFieldDefinition($resource_type->getEntityTypeId(), $resource_type->getBundle(), $file_field_name);
static::ensureFileUploadAccess($this->currentUser, $field_definition);
$filename = $this->fileUploader
->validateAndParseContentDispositionHeader($request);
$file = $this->fileUploader
->handleFileUploadForField($field_definition, $filename, $this->currentUser);
if ($file instanceof EntityConstraintViolationListInterface) {
$violations = $file;
$message = "Unprocessable Entity: file validation failed.\n";
$message .= implode("\n", array_map(function (ConstraintViolationInterface $violation) {
return PlainTextOutput::renderFromHtml($violation->getMessage());
}, iterator_to_array($violations)));
throw new UnprocessableEntityHttpException($message);
}
// @todo Remove line below in favor of commented line in https://www.drupal.org/project/drupal/issues/2878463.
$self_link = new Link(new CacheableMetadata(), Url::fromRoute('jsonapi.file--file.individual', [
'entity' => $file->uuid(),
]), 'self');
/* $self_link = new Link(new CacheableMetadata(), $this->entity->toUrl('jsonapi'), ['self']); */
$links = new LinkCollection([
'self' => $self_link,
]);
$relatable_resource_types = $resource_type->getRelatableResourceTypesByField($resource_type->getPublicName($file_field_name));
$file_resource_type = reset($relatable_resource_types);
$resource_object = ResourceObject::createFromEntity($file_resource_type, $file);
return new ResourceResponse(new JsonApiDocumentTopLevel(new ResourceObjectData([
$resource_object,
], 1), new NullIncludedData(), $links), 201, []);
}
/**
* Ensures that the given account is allowed to upload a file.
*
* @param \Drupal\Core\Session\AccountInterface $account
* The account for which access should be checked.
* @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
* The field for which the file is to be uploaded.
* @param \Drupal\Core\Entity\FieldableEntityInterface|null $entity
* The entity, if one exists, for which the file is to be uploaded.
*/
protected static function ensureFileUploadAccess(AccountInterface $account, FieldDefinitionInterface $field_definition, FieldableEntityInterface $entity = NULL) {
$access_result = $entity ? TemporaryJsonapiFileFieldUploader::checkFileUploadAccess($account, $field_definition, $entity) : TemporaryJsonapiFileFieldUploader::checkFileUploadAccess($account, $field_definition);
if (!$access_result->isAllowed()) {
$reason = 'The current user is not permitted to upload a file for this field.';
if ($access_result instanceof AccessResultReasonInterface) {
$reason .= ' ' . $access_result->getReason();
}
throw new AccessDeniedHttpException($reason);
}
}
/**
* Validates and loads a field definition instance.
*
* @param string $entity_type_id
* The entity type ID the field is attached to.
* @param string $bundle
* The bundle the field is attached to.
* @param string $field_name
* The field name.
*
* @return \Drupal\Core\Field\FieldDefinitionInterface
* The field definition.
*
* @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
* Thrown when the field does not exist.
* @throws \Symfony\Component\HttpFoundation\File\Exception\AccessDeniedException
* Thrown when the target type of the field is not a file, or the current
* user does not have 'edit' access for the field.
*/
protected function validateAndLoadFieldDefinition($entity_type_id, $bundle, $field_name) {
$field_definitions = $this->fieldManager
->getFieldDefinitions($entity_type_id, $bundle);
if (!isset($field_definitions[$field_name])) {
throw new NotFoundHttpException(sprintf('Field "%s" does not exist.', $field_name));
}
/** @var \Drupal\Core\Field\FieldDefinitionInterface $field_definition */
$field_definition = $field_definitions[$field_name];
if ($field_definition->getSetting('target_type') !== 'file') {
throw new AccessDeniedException(sprintf('"%s" is not a file field', $field_name));
}
return $field_definition;
}
}
Members
Title Sort descending | Modifiers | Object type | Summary |
---|---|---|---|
EntityValidationTrait::validate | protected static | function | Verifies that an entity does not violate any validation constraints. |
FileUpload::$currentUser | protected | property | The current user making the request. |
FileUpload::$fieldManager | protected | property | The field manager. |
FileUpload::$fileUploader | protected | property | The file uploader. |
FileUpload::$httpKernel | protected | property | An HTTP kernel for making subrequests. |
FileUpload::ensureFileUploadAccess | protected static | function | Ensures that the given account is allowed to upload a file. |
FileUpload::handleFileUploadForExistingResource | public | function | Handles JSON:API file upload requests. |
FileUpload::handleFileUploadForNewResource | public | function | Handles JSON:API file upload requests. |
FileUpload::validateAndLoadFieldDefinition | protected | function | Validates and loads a field definition instance. |
FileUpload::__construct | public | function | Creates a new FileUpload instance. |
Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.