Skip to content

Commit

Permalink
[stacked 12] Use pipes photo partners (LycheeOrg#2376)
Browse files Browse the repository at this point in the history
  • Loading branch information
ildyria committed Apr 11, 2024
1 parent 9838839 commit 3ffe070
Show file tree
Hide file tree
Showing 5 changed files with 152 additions and 4 deletions.
80 changes: 76 additions & 4 deletions app/Actions/Photo/Create.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use App\Actions\Photo\Pipes\Duplicate;
use App\Actions\Photo\Pipes\Init;
use App\Actions\Photo\Pipes\PhotoPartner;
use App\Actions\Photo\Pipes\Shared;
use App\Actions\Photo\Pipes\Standalone;
use App\Actions\Photo\Pipes\VideoPartner;
Expand All @@ -14,8 +15,10 @@
use App\DTO\ImportParam;
use App\DTO\PhotoCreate\DuplicateDTO;
use App\DTO\PhotoCreate\InitDTO;
use App\DTO\PhotoCreate\PhotoPartnerDTO;
use App\DTO\PhotoCreate\StandaloneDTO;
use App\DTO\PhotoCreate\VideoPartnerDTO;
use App\Exceptions\Internal\LycheeLogicException;
use App\Exceptions\PhotoResyncedException;
use App\Exceptions\PhotoSkippedException;
use App\Image\Files\NativeLocalFile;
Expand Down Expand Up @@ -93,9 +96,11 @@ public function add(NativeLocalFile $sourceFile, ?AbstractAlbum $album, ?int $fi
return $this->handleVideoLivePartner($initDTO);
}

$oldCodePath = new LegacyPhotoCreate($this->strategyParameters->importMode, $this->strategyParameters->intendedOwnerId);
if ($sourceFile->isSupportedImage()) {
return $this->handlePhotoLivePartner($initDTO);
}

return $oldCodePath->add($sourceFile, $album, $fileLastModifiedTime);
throw new LycheeLogicException('Pipe system for importing video failed');
}

/**
Expand Down Expand Up @@ -177,7 +182,7 @@ private function handleVideoLivePartner(InitDTO $initDTO): Photo
/**
* Execute the pipes on the DTO.
*
* @template T of VideoPartnerDTO|StandaloneDTO
* @template T of VideoPartnerDTO|StandaloneDTO|PhotoPartnerDTO
*
* @param array $pipes
* @param T $dto
Expand All @@ -186,7 +191,7 @@ private function handleVideoLivePartner(InitDTO $initDTO): Photo
*
* @throws LycheeException
*/
private function executePipeOnDTO(array $pipes, VideoPartnerDTO|StandaloneDTO $dto): VideoPartnerDTO|StandaloneDTO
private function executePipeOnDTO(array $pipes, VideoPartnerDTO|StandaloneDTO|PhotoPartnerDTO $dto): VideoPartnerDTO|StandaloneDTO|PhotoPartnerDTO
{
try {
return app(Pipeline::class)
Expand All @@ -204,4 +209,71 @@ private function executePipeOnDTO(array $pipes, VideoPartnerDTO|StandaloneDTO $d
throw $e;
}
}

/**
* Adds a photo as partner to an existing video.
*
* Note the asymmetry to {@link handleVideoLivePartner}.
*
* A photo is always added as if it had no partner, even if the video had
* been added first.
* Then the already existing video is added to the freshly added photo.
* Hence, this strategy works mostly like the stand-alone strategy and also
* requires the photo file to be a native, local file in order to be able to
* extract EXIF data.
*/
private function handlePhotoLivePartner(InitDTO $initDTO): Photo
{
// Save old video.
$oldVideo = $initDTO->livePartner;

// Import Photo as stand alone.
$standAloneDto = StandaloneDTO::ofInit($initDTO);
$standAlonePipes = [
Standalone\FixTimeStamps::class,
Standalone\InitNamingStrategy::class,
Shared\HydrateMetadata::class,
Shared\SetStarred::class,
Shared\SetParentAndOwnership::class,
Standalone\SetOriginalChecksum::class,
Standalone\FetchSourceImage::class,
Standalone\ExtractGoogleMotionPictures::class,
Standalone\PlacePhoto::class,
Standalone\PlaceGoogleMotionVideo::class,
Standalone\SetChecksum::class,
Shared\Save::class,
Standalone\CreateOriginalSizeVariant::class,
Standalone\CreateSizeVariants::class,
];
$standAloneDto = $this->executePipeOnDTO($standAlonePipes, $standAloneDto);

// Use file from video as input for Video Partner and import
$videoPartnerDTO = new VideoPartnerDTO(
videoFile: $oldVideo->size_variants->getOriginal()->getFile(),
shallDeleteImported: true,
shallImportViaSymlink: false,
photo: $standAloneDto->getPhoto()
);
$videoPartnerPipes = [
VideoPartner\GetVideoPath::class,
VideoPartner\PlaceVideo::class,
VideoPartner\UpdateLivePartner::class,
Shared\Save::class,
];
$videoPartnerDTO = $this->executePipeOnDTO($videoPartnerPipes, $videoPartnerDTO);

$finalizeDTO = new PhotoPartnerDTO(
photo: $videoPartnerDTO->photo,
oldVideo: $oldVideo
);

// Finalize
$finalize = [
PhotoPartner\SetOldChecksum::class,
PhotoPartner\DeleteOldVideoPartner::class,
Shared\Save::class,
];

return $this->executePipeOnDTO($finalize, $finalizeDTO)->getPhoto();
}
}
16 changes: 16 additions & 0 deletions app/Actions/Photo/Pipes/PhotoPartner/DeleteOldVideoPartner.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

namespace App\Actions\Photo\Pipes\PhotoPartner;

use App\Contracts\PhotoCreate\PhotoPartnerPipe;
use App\DTO\PhotoCreate\PhotoPartnerDTO;

class DeleteOldVideoPartner implements PhotoPartnerPipe
{
public function handle(PhotoPartnerDTO $state, \Closure $next): PhotoPartnerDTO
{
$state->oldVideo->delete();

return $next($state);
}
}
17 changes: 17 additions & 0 deletions app/Actions/Photo/Pipes/PhotoPartner/SetOldChecksum.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

namespace App\Actions\Photo\Pipes\PhotoPartner;

use App\Contracts\PhotoCreate\PhotoPartnerPipe;
use App\DTO\PhotoCreate\PhotoPartnerDTO;

class SetOldChecksum implements PhotoPartnerPipe
{
public function handle(PhotoPartnerDTO $state, \Closure $next): PhotoPartnerDTO
{
// As the video is uploaded already, we must copy over the checksum
$state->photo->live_photo_checksum = $state->oldVideo->checksum;

return $next($state);
}
}
19 changes: 19 additions & 0 deletions app/Contracts/PhotoCreate/PhotoPartnerPipe.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

namespace App\Contracts\PhotoCreate;

use App\DTO\PhotoCreate\PhotoPartnerDTO;

/**
* Basic definition of a Photo Partner pipe.
*/
interface PhotoPartnerPipe
{
/**
* @param PhotoPartnerDTO $state
* @param \Closure(PhotoPartnerDTO $state): PhotoPartnerDTO $next
*
* @return PhotoPartnerDTO
*/
public function handle(PhotoPartnerDTO $state, \Closure $next): PhotoPartnerDTO;
}
24 changes: 24 additions & 0 deletions app/DTO/PhotoCreate/PhotoPartnerDTO.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

namespace App\DTO\PhotoCreate;

use App\Contracts\Image\StreamStats;
use App\Contracts\PhotoCreate\PhotoDTO;
use App\Models\Photo;

class PhotoPartnerDTO implements PhotoDTO
{
public StreamStats|null $streamStat;
public string $videoPath;

public function __construct(
public readonly Photo $photo,
public readonly Photo $oldVideo,
) {
}

public function getPhoto(): Photo
{
return $this->photo;
}
}

0 comments on commit 3ffe070

Please sign in to comment.