From fdee82cfde271e0a59396fc90c02f95cb1e7f597 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Viguier?= Date: Thu, 11 Apr 2024 13:29:39 +0200 Subject: [PATCH] [stacked 5] Add initial steps as Pipes (#2368) --- app/Actions/Photo/Create.php | 30 ++++++++++ .../Photo/Pipes/Init/AssertSupportedMedia.php | 27 +++++++++ .../Pipes/Init/FetchLastModifiedTime.php | 25 +++++++++ .../Photo/Pipes/Init/FindDuplicate.php | 31 +++++++++++ .../Photo/Pipes/Init/FindLivePartner.php | 48 ++++++++++++++++ .../Photo/Pipes/Init/InitParentAlbum.php | 40 ++++++++++++++ .../Photo/Pipes/Init/LoadFileMetadata.php | 35 ++++++++++++ app/Contracts/PhotoCreate/InitPipe.php | 21 +++++++ app/DTO/PhotoCreate/InitDTO.php | 55 +++++++++++++++++++ 9 files changed, 312 insertions(+) create mode 100644 app/Actions/Photo/Pipes/Init/AssertSupportedMedia.php create mode 100644 app/Actions/Photo/Pipes/Init/FetchLastModifiedTime.php create mode 100644 app/Actions/Photo/Pipes/Init/FindDuplicate.php create mode 100644 app/Actions/Photo/Pipes/Init/FindLivePartner.php create mode 100644 app/Actions/Photo/Pipes/Init/InitParentAlbum.php create mode 100644 app/Actions/Photo/Pipes/Init/LoadFileMetadata.php create mode 100644 app/Contracts/PhotoCreate/InitPipe.php create mode 100644 app/DTO/PhotoCreate/InitDTO.php diff --git a/app/Actions/Photo/Create.php b/app/Actions/Photo/Create.php index 7e8a95b0896..c5fe582ef02 100644 --- a/app/Actions/Photo/Create.php +++ b/app/Actions/Photo/Create.php @@ -2,14 +2,18 @@ namespace App\Actions\Photo; +use App\Actions\Photo\Pipes\Init; +use App\Assets\Features; use App\Contracts\Exceptions\LycheeException; use App\Contracts\Models\AbstractAlbum; use App\DTO\ImportMode; use App\DTO\ImportParam; +use App\DTO\PhotoCreate\InitDTO; use App\Image\Files\NativeLocalFile; use App\Legacy\Actions\Photo\Create as LegacyPhotoCreate; use App\Models\Photo; use Illuminate\Database\Eloquent\ModelNotFoundException; +use Illuminate\Pipeline\Pipeline; class Create { @@ -41,6 +45,32 @@ public function __construct(?ImportMode $importMode, int $intendedOwnerId) */ public function add(NativeLocalFile $sourceFile, ?AbstractAlbum $album, ?int $fileLastModifiedTime = null): Photo { + if (Features::inactive('create-photo-via-pipes')) { + $oldCodePath = new LegacyPhotoCreate($this->strategyParameters->importMode, $this->strategyParameters->intendedOwnerId); + + return $oldCodePath->add($sourceFile, $album, $fileLastModifiedTime); + } + + $initDTO = new InitDTO( + parameters: $this->strategyParameters, + sourceFile: $sourceFile, + album: $album, + fileLastModifiedTime: $fileLastModifiedTime + ); + + /** @var InitDTO $initDTO */ + $initDTO = app(Pipeline::class) + ->send($initDTO) + ->through([ + Init\AssertSupportedMedia::class, + Init\FetchLastModifiedTime::class, + Init\InitParentAlbum::class, + Init\LoadFileMetadata::class, + Init\FindDuplicate::class, + Init\FindLivePartner::class, + ]) + ->thenReturn(); + $oldCodePath = new LegacyPhotoCreate($this->strategyParameters->importMode, $this->strategyParameters->intendedOwnerId); return $oldCodePath->add($sourceFile, $album, $fileLastModifiedTime); diff --git a/app/Actions/Photo/Pipes/Init/AssertSupportedMedia.php b/app/Actions/Photo/Pipes/Init/AssertSupportedMedia.php new file mode 100644 index 00000000000..c600ccea2f4 --- /dev/null +++ b/app/Actions/Photo/Pipes/Init/AssertSupportedMedia.php @@ -0,0 +1,27 @@ +sourceFile->assertIsSupportedMediaOrAcceptedRaw(); + + return $next($state); + } +} \ No newline at end of file diff --git a/app/Actions/Photo/Pipes/Init/FetchLastModifiedTime.php b/app/Actions/Photo/Pipes/Init/FetchLastModifiedTime.php new file mode 100644 index 00000000000..85b3c9d5d09 --- /dev/null +++ b/app/Actions/Photo/Pipes/Init/FetchLastModifiedTime.php @@ -0,0 +1,25 @@ +fileLastModifiedTime === null) { + $state->fileLastModifiedTime ??= $state->sourceFile->lastModified(); + } + + return $next($state); + } +} + diff --git a/app/Actions/Photo/Pipes/Init/FindDuplicate.php b/app/Actions/Photo/Pipes/Init/FindDuplicate.php new file mode 100644 index 00000000000..b09ebafc12b --- /dev/null +++ b/app/Actions/Photo/Pipes/Init/FindDuplicate.php @@ -0,0 +1,31 @@ +sourceFile)->checksum; + + $state->duplicate = Photo::query() + ->where('checksum', '=', $checksum) + ->orWhere('original_checksum', '=', $checksum) + ->orWhere('live_photo_checksum', '=', $checksum) + ->first(); + + return $next($state); + } +} + diff --git a/app/Actions/Photo/Pipes/Init/FindLivePartner.php b/app/Actions/Photo/Pipes/Init/FindLivePartner.php new file mode 100644 index 00000000000..b65bf89a56f --- /dev/null +++ b/app/Actions/Photo/Pipes/Init/FindLivePartner.php @@ -0,0 +1,48 @@ +exifInfo->livePhotoContentID !== null) { + $state->livePartner = Photo::query() + ->where('live_photo_content_id', '=', $state->exifInfo->livePhotoContentID) + ->where('album_id', '=', $state->album?->id) + ->whereNull('live_photo_short_path')->first(); + } + + // if a potential partner has been found, ensure that it is of a + // different kind then the uploaded media. + if ( + $state->livePartner !== null && !( + BaseMediaFile::isSupportedImageMimeType($state->exifInfo->type) && $state->livePartner->isVideo() || + BaseMediaFile::isSupportedVideoMimeType($state->exifInfo->type) && $state->livePartner->isPhoto() + ) + ) { + $state->livePartner = null; + } + + return $next($state); + } catch (IllegalOrderOfOperationException $e) { + throw LycheeAssertionError::createFromUnexpectedException($e); + } + } +} + diff --git a/app/Actions/Photo/Pipes/Init/InitParentAlbum.php b/app/Actions/Photo/Pipes/Init/InitParentAlbum.php new file mode 100644 index 00000000000..310fd5cdca7 --- /dev/null +++ b/app/Actions/Photo/Pipes/Init/InitParentAlbum.php @@ -0,0 +1,40 @@ +album === null || $state->album instanceof Album) { + return $next($state); + } + + if ($state->album instanceof BaseSmartAlbum) { + if ($state->album instanceof StarredAlbum) { + $state->is_starred = true; + } + + $state->album = null; + + return $next($state); + } + + throw new InvalidPropertyException('The given parent album does not support uploading'); + } +} \ No newline at end of file diff --git a/app/Actions/Photo/Pipes/Init/LoadFileMetadata.php b/app/Actions/Photo/Pipes/Init/LoadFileMetadata.php new file mode 100644 index 00000000000..a6893651719 --- /dev/null +++ b/app/Actions/Photo/Pipes/Init/LoadFileMetadata.php @@ -0,0 +1,35 @@ +exifInfo = Extractor::createFromFile($state->sourceFile, $state->fileLastModifiedTime); + + // Use basename of file if IPTC title missing + if ( + $state->exifInfo->title === null || + $state->exifInfo->title === '' + ) { + $state->exifInfo->title = substr($state->sourceFile->getOriginalBasename(), 0, 98); + } + + return $next($state); + } +} + diff --git a/app/Contracts/PhotoCreate/InitPipe.php b/app/Contracts/PhotoCreate/InitPipe.php new file mode 100644 index 00000000000..a3826e8675c --- /dev/null +++ b/app/Contracts/PhotoCreate/InitPipe.php @@ -0,0 +1,21 @@ +sourceFile = $sourceFile; + $this->importMode = $parameters->importMode; + $this->intendedOwnerId = $parameters->intendedOwnerId; + $this->is_starred = $parameters->is_starred; + $this->exifInfo = $parameters->exifInfo; + $this->album = $album; + $this->fileLastModifiedTime = $fileLastModifiedTime; + } +}