From a1958113ebb22c3277f37c94e0cf713913555f35 Mon Sep 17 00:00:00 2001 From: dannylamb Date: Wed, 9 Dec 2020 16:19:44 +0000 Subject: [PATCH 1/2] Refactoring multi-file media to create files like we do for other derivatives --- src/Controller/MediaSourceController.php | 48 ++++++++++++------ src/MediaSource/MediaSourceService.php | 63 ++++++++++++++++++++++++ 2 files changed, 96 insertions(+), 15 deletions(-) diff --git a/src/Controller/MediaSourceController.php b/src/Controller/MediaSourceController.php index c32b8079..9706e450 100644 --- a/src/Controller/MediaSourceController.php +++ b/src/Controller/MediaSourceController.php @@ -230,23 +230,41 @@ class MediaSourceController extends ControllerBase { public function attachToMedia( Media $media, string $destination_field, - Request $request) { + Request $request + ) { $content_location = $request->headers->get('Content-Location', ""); - $contents = $request->getContent(); - if ($contents) { - $file = file_save_data($contents, $content_location, FILE_EXISTS_REPLACE); - if ($media->hasField($destination_field)) { - $media->{$destination_field}->setValue([ - 'target_id' => $file->id(), - ]); - $media->save(); - } - else { - $this->getLogger('islandora')->warning("Field $destination_field is not defined in Media Type {$media->bundle()}"); - } + if (empty($content_location)) { + throw new BadRequestHttpException("Missing Content-Location header"); + } + + $content_type = $request->headers->get('Content-Type', ""); + if (empty($content_type)) { + throw new BadRequestHttpException("Missing Content-Type header"); + } + + // Since we create both a Media and its File, + // start a transaction. + $transaction = $this->database->startTransaction(); + + try { + $this->service->putToMedia( + $media, + $destination_field, + $request->getContent(TRUE), + $content_type, + $content_location + ); + // Should only see this with a GET request for testing. + return new Response("

Complete

"); + } + catch (HttpException $e) { + $transaction->rollBack(); + throw $e; + } + catch (\Exception $e) { + $transaction->rollBack(); + throw new HttpException(500, $e->getMessage()); } - // Should only see this with a GET request for testing. - return new Response("

Complete

"); } /** diff --git a/src/MediaSource/MediaSourceService.php b/src/MediaSource/MediaSourceService.php index 8e3491fe..d9388dbd 100644 --- a/src/MediaSource/MediaSourceService.php +++ b/src/MediaSource/MediaSourceService.php @@ -330,4 +330,67 @@ class MediaSourceService { } + /** + * Creates a new File using the provided resource, adding it to a Media. + * + * @param \Drupal\media\MediaInterface $media + * The Media that will receive the new file. + * @param string $destination_field + * The field on the media where the file will go. + * @param resource $resource + * New file contents as a resource. + * @param string $mimetype + * New mimetype of contents. + * @param string $content_location + * Drupal/PHP stream wrapper for where to upload the binary. + * + * @throws \Symfony\Component\HttpKernel\Exception\BadRequestHttpException + * @throws \Symfony\Component\HttpKernel\Exception\HttpException + */ + public function putToMedia( + MediaInterface $media, + $destination_field, + $resource, + $mimetype, + $content_location + ) { + if ($media->hasField($destination_field)) { + // Construct the File. + $file = $this->entityTypeManager->getStorage('file')->create([ + 'uid' => $this->account->id(), + 'uri' => $content_location, + 'filename' => $this->fileSystem->basename($content_location), + 'filemime' => $mimetype, + 'status' => FILE_STATUS_PERMANENT, + ]); + + // Validate file extension. + $bundle = $media->bundle(); + $destination_field_config= $this->entityTypeManager->getStorage('field_config')->load("media.$bundle.$destination_field"); + $valid_extensions = $destination_field_config->getSetting('file_extensions'); + $errors = file_validate_extensions($file, $valid_extensions); + + if (!empty($errors)) { + throw new BadRequestHttpException("Invalid file extension. Valid types are $valid_extensions"); + } + + $directory = $this->fileSystem->dirname($content_location); + if (!file_prepare_directory($directory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS)) { + throw new HttpException(500, "The destination directory does not exist, could not be created, or is not writable"); + } + + // Copy over the file content. + $this->updateFile($file, $resource, $mimetype); + $file->save(); + + // Update the media + $media->{$destination_field}->setValue([ + 'target_id' => $file->id(), + ]); + $media->save(); + } + else { + throw new BadRequestHttpException("Media does not have destination field $destination_field"); + } + } } From 9ff811a3b17f078e57f013a39aa48b427fa5fddf Mon Sep 17 00:00:00 2001 From: dannylamb Date: Thu, 10 Dec 2020 15:20:09 +0000 Subject: [PATCH 2/2] Coding standards --- src/Controller/MediaSourceController.php | 2 +- src/MediaSource/MediaSourceService.php | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Controller/MediaSourceController.php b/src/Controller/MediaSourceController.php index 9706e450..bab43fcf 100644 --- a/src/Controller/MediaSourceController.php +++ b/src/Controller/MediaSourceController.php @@ -249,7 +249,7 @@ class MediaSourceController extends ControllerBase { try { $this->service->putToMedia( $media, - $destination_field, + $destination_field, $request->getContent(TRUE), $content_type, $content_location diff --git a/src/MediaSource/MediaSourceService.php b/src/MediaSource/MediaSourceService.php index d9388dbd..4909124b 100644 --- a/src/MediaSource/MediaSourceService.php +++ b/src/MediaSource/MediaSourceService.php @@ -366,7 +366,7 @@ class MediaSourceService { // Validate file extension. $bundle = $media->bundle(); - $destination_field_config= $this->entityTypeManager->getStorage('field_config')->load("media.$bundle.$destination_field"); + $destination_field_config = $this->entityTypeManager->getStorage('field_config')->load("media.$bundle.$destination_field"); $valid_extensions = $destination_field_config->getSetting('file_extensions'); $errors = file_validate_extensions($file, $valid_extensions); @@ -383,7 +383,7 @@ class MediaSourceService { $this->updateFile($file, $resource, $mimetype); $file->save(); - // Update the media + // Update the media. $media->{$destination_field}->setValue([ 'target_id' => $file->id(), ]); @@ -393,4 +393,5 @@ class MediaSourceService { throw new BadRequestHttpException("Media does not have destination field $destination_field"); } } + }