diff --git a/src/Controller/MediaSourceController.php b/src/Controller/MediaSourceController.php
index 29ff9412..a7e5221a 100644
--- a/src/Controller/MediaSourceController.php
+++ b/src/Controller/MediaSourceController.php
@@ -231,23 +231,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, FileSystemInterface::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 dc6d4c5a..de346115 100644
--- a/src/MediaSource/MediaSourceService.php
+++ b/src/MediaSource/MediaSourceService.php
@@ -318,4 +318,68 @@ 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");
+ }
+ }
+
}