Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions .github/workflows/CICD.yml
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ jobs:
uses: shivammathur/setup-php@f3e473d116dcccaddc5834248c87452386958240 # 2.37.2
with:
php-version: 8.4
extensions: opentelemetry

- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
Expand Down Expand Up @@ -119,6 +120,7 @@ jobs:
uses: shivammathur/setup-php@f3e473d116dcccaddc5834248c87452386958240 # 2.37.2
with:
php-version: 8.4
extensions: opentelemetry

- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
Expand Down Expand Up @@ -148,6 +150,7 @@ jobs:
with:
php-version: 8.4
coverage: none
extensions: opentelemetry

- name: Install Composer dependencies
uses: ramsey/composer-install@65e4f84970763564f46a70b8a54b90d033b3bdda # 4.0.0
Expand All @@ -174,6 +177,7 @@ jobs:
with:
php-version: 8.4
coverage: none
extensions: opentelemetry

- name: Install Composer dependencies
uses: ramsey/composer-install@65e4f84970763564f46a70b8a54b90d033b3bdda # 4.0.0
Expand Down Expand Up @@ -217,7 +221,7 @@ jobs:
uses: shivammathur/setup-php@f3e473d116dcccaddc5834248c87452386958240 # 2.37.2
with:
php-version: 8.4
extensions: bcmath, curl, dom, gd, imagick, json, libxml, mbstring, pcntl, pdo, pdo_sqlite, sqlite3, zip
extensions: bcmath, curl, dom, gd, imagick, json, libxml, mbstring, pcntl, pdo, pdo_sqlite, sqlite3, zip, opentelemetry
coverage: xdebug
tools: pecl, composer

Expand Down Expand Up @@ -479,7 +483,7 @@ jobs:
id-token: write
attestations: write
env:
extensions: bcmath, curl, dom, gd, imagick, json, libxml, mbstring, pcntl, pdo, pdo_sqlite, pdo_mysql, pdo_pgsql, pgsql, sqlite3, zip
extensions: bcmath, curl, dom, gd, imagick, json, libxml, mbstring, pcntl, pdo, pdo_sqlite, pdo_mysql, pdo_pgsql, pgsql, sqlite3, zip, opentelemetry

steps:
- name: Harden Runner
Expand Down Expand Up @@ -555,7 +559,7 @@ jobs:
contents: write
id-token: write
env:
extensions: bcmath, curl, dom, gd, imagick, json, libxml, mbstring, pcntl, pdo, pdo_sqlite, pdo_mysql, pdo_pgsql, pgsql, sqlite3, zip
extensions: bcmath, curl, dom, gd, imagick, json, libxml, mbstring, pcntl, pdo, pdo_sqlite, pdo_mysql, pdo_pgsql, pgsql, sqlite3, zip, opentelemetry

steps:
- name: Install Cosign
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/php_dist.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ jobs:
# Maps tcp port 5432 on service container to the host
- 5432:5432
env:
extensions: bcmath, curl, dom, gd, imagick, json, libxml, mbstring, pcntl, pdo, pdo_sqlite, pdo_mysql, pdo_pgsql, pgsql, sqlite3, zip
extensions: bcmath, curl, dom, gd, imagick, json, libxml, mbstring, pcntl, pdo, pdo_sqlite, pdo_mysql, pdo_pgsql, pgsql, sqlite3, zip, opentelemetry

steps:
- name: Harden Runner
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/php_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ jobs:
# Maps tcp port 5432 on service container to the host
- 5432:5432
env:
extensions: bcmath, curl, dom, gd, imagick, json, libxml, mbstring, pcntl, pdo, pdo_sqlite, pdo_mysql, pdo_pgsql, pgsql, sqlite3, zip
extensions: bcmath, curl, dom, gd, imagick, json, libxml, mbstring, pcntl, pdo, pdo_sqlite, pdo_mysql, pdo_pgsql, pgsql, sqlite3, zip, opentelemetry

steps:
- name: Harden Runner
Expand Down
174 changes: 92 additions & 82 deletions app/Actions/Photo/Create.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
use App\Models\Photo;
use App\Models\User;
use App\Services\Image\FileExtensionService;
use App\Services\Telemetry\TraceService;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Pipeline\Pipeline;
use LycheeVerify\Contract\VerifyInterface;
Expand All @@ -42,6 +43,8 @@ class Create
/** @var ImportParam the strategy parameters prepared and compiled by this class */
protected ImportParam $strategy_parameters;

private TraceService $trace;

public function __construct(
?ImportMode $import_mode,
int $intended_owner_id,
Expand All @@ -58,6 +61,7 @@ public function __construct(
preallocated_id: $preallocated_id,
upload_trust_level: $upload_trust_level,
);
$this->trace = app(TraceService::class);
}

/**
Expand All @@ -81,59 +85,63 @@ public function __construct(
*/
public function add(NativeLocalFile $source_file, ?AbstractAlbum $album, ?int $file_last_modified_time = null): Photo
{
$this->checkQuota($source_file);

/** @var InitDTO $init_dto */
$init_dto = new InitDTO(
parameters: $this->strategy_parameters,
source_file: $source_file,
album: $album,
file_last_modified_time: $file_last_modified_time
);

$pre_pipes = [
Init\DetectAndStoreRaw::class,
Init\AssertSupportedMedia::class,
Init\FetchLastModifiedTime::class,
Init\MayLoadFileMetadata::class,
Init\FindDuplicate::class,
];

$init_dto = app(Pipeline::class)
->send($init_dto)
->through($pre_pipes)
->thenReturn();
return $this->trace->traceMethod('photo.create.add', function () use ($source_file,
$album,
$file_last_modified_time) {
$this->checkQuota($source_file);

/** @var InitDTO $init_dto */
$init_dto = new InitDTO(
parameters: $this->strategy_parameters,
source_file: $source_file,
album: $album,
file_last_modified_time: $file_last_modified_time
);

$pre_pipes = [
Init\DetectAndStoreRaw::class,
Init\AssertSupportedMedia::class,
Init\FetchLastModifiedTime::class,
Init\MayLoadFileMetadata::class,
Init\FindDuplicate::class,
];

$init_dto = app(Pipeline::class)
->send($init_dto)
->through($pre_pipes)
->thenReturn();

if ($init_dto->duplicate !== null) {
return $this->handleDuplicate($init_dto);
}
if ($init_dto->duplicate !== null) {
return $this->handleDuplicate($init_dto);
}

$post_pipes = [
Init\InitParentAlbum::class,
Init\LoadFileMetadata::class,
Init\FindLivePartner::class,
];
$post_pipes = [
Init\InitParentAlbum::class,
Init\LoadFileMetadata::class,
Init\FindLivePartner::class,
];

$init_dto = app(Pipeline::class)
->send($init_dto)
->through($post_pipes)
->thenReturn();
$init_dto = app(Pipeline::class)
->send($init_dto)
->through($post_pipes)
->thenReturn();

if ($init_dto->live_partner === null) {
return $this->handleStandalone($init_dto);
}
if ($init_dto->live_partner === null) {
return $this->handleStandalone($init_dto);
}

// livePartner !== null
$file_extension_service = app(FileExtensionService::class);
if ($file_extension_service->isSupportedVideo($source_file->getMimeType(), $source_file->getOriginalExtension())) {
return $this->handleVideoLivePartner($init_dto);
}
// livePartner !== null
$file_extension_service = app(FileExtensionService::class);
if ($file_extension_service->isSupportedVideo($source_file->getMimeType(), $source_file->getOriginalExtension())) {
return $this->handleVideoLivePartner($init_dto);
}

if ($file_extension_service->isSupportedImage($source_file->getPath(), $source_file->getMimeType(), $source_file->getOriginalExtension())) {
return $this->handlePhotoLivePartner($init_dto);
}
if ($file_extension_service->isSupportedImage($source_file->getPath(), $source_file->getMimeType(), $source_file->getOriginalExtension())) {
return $this->handlePhotoLivePartner($init_dto);
}

throw new LycheeLogicException('Pipe system for importing video failed');
throw new LycheeLogicException('Pipe system for importing video failed');
});
}

/**
Expand Down Expand Up @@ -176,41 +184,43 @@ private function handleDuplicate(InitDTO $init_dto): Photo

private function handleStandalone(InitDTO $init_dto): Photo
{
$dto = StandaloneDTO::ofInit($init_dto);

$pipes = [
Standalone\FixTimeStamps::class,
Standalone\InitNamingStrategy::class,
Standalone\ApplyUserProvidedMetadata::class,
Shared\HydrateMetadata::class,
Shared\SetHighlighted::class,
Shared\SetOwnership::class,
Standalone\SetOriginalChecksum::class,
Standalone\FetchSourceImage::class,
Standalone\ExtractGoogleMotionPictures::class,
Standalone\PlacePhoto::class,
Standalone\PlaceGoogleMotionVideo::class,
Standalone\SetChecksum::class,
Standalone\AutoRenamer::class,
Shared\SetUploadValidated::class,
Shared\Save::class,
Shared\SetParent::class,
Shared\SaveStatistics::class,
Standalone\CreateOriginalSizeVariant::class,
Standalone\CreateRawSizeVariant::class,
Standalone\CreateSizeVariants::class,
Standalone\ApplyWatermark::class,
Standalone\EncodePlaceholder::class,
Standalone\ReplaceOriginalWithBackup::class,
Shared\UploadSizeVariantsToS3::class,
Shared\GeodecodeLocation::class,
Shared\ExtractColourPalette::class,
Shared\NotifyAlbums::class,
Standalone\AutoScanFacesOnUpload::class,
Standalone\AutoScanNsfwOnUpload::class,
];

return $this->executePipeOnDTO($pipes, $dto)->getPhoto();
return $this->trace->traceMethod('photo.handle_standalone', function () use ($init_dto) {
$dto = StandaloneDTO::ofInit($init_dto);

$pipes = [
Standalone\FixTimeStamps::class,
Standalone\InitNamingStrategy::class,
Standalone\ApplyUserProvidedMetadata::class,
Shared\HydrateMetadata::class,
Shared\SetHighlighted::class,
Shared\SetOwnership::class,
Standalone\SetOriginalChecksum::class,
Standalone\FetchSourceImage::class,
Standalone\ExtractGoogleMotionPictures::class,
Standalone\PlacePhoto::class,
Standalone\PlaceGoogleMotionVideo::class,
Standalone\SetChecksum::class,
Standalone\AutoRenamer::class,
Shared\SetUploadValidated::class,
Shared\Save::class,
Shared\SetParent::class,
Shared\SaveStatistics::class,
Standalone\CreateOriginalSizeVariant::class,
Standalone\CreateRawSizeVariant::class,
Standalone\CreateSizeVariants::class,
Standalone\ApplyWatermark::class,
Standalone\EncodePlaceholder::class,
Standalone\ReplaceOriginalWithBackup::class,
Shared\UploadSizeVariantsToS3::class,
Shared\GeodecodeLocation::class,
Shared\ExtractColourPalette::class,
Shared\NotifyAlbums::class,
Standalone\AutoScanFacesOnUpload::class,
Standalone\AutoScanNsfwOnUpload::class,
];

return $this->executePipeOnDTO($pipes, $dto)->getPhoto();
});
}

private function handleVideoLivePartner(InitDTO $init_dto): Photo
Expand Down Expand Up @@ -378,4 +388,4 @@ private function checkQuota(NativeLocalFile $source_file): void
throw new QuotaExceededException();
}
}
}
}
33 changes: 33 additions & 0 deletions app/Actions/Photo/Pipes/Init/AbstractInitPipe.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

/**
* SPDX-License-Identifier: MIT
* Copyright (c) 2017-2018 Tobias Reich
* Copyright (c) 2018-2026 LycheeOrg.
*/

namespace App\Actions\Photo\Pipes\Init;

use App\Contracts\PhotoCreate\InitPipe;
use App\DTO\PhotoCreate\InitDTO;
use App\Services\Telemetry\TraceService;

abstract class AbstractInitPipe implements InitPipe
{
/**
* @param InitDTO $state
* @param \Closure(InitDTO $state): InitDTO $next
*
* @return InitDTO
*/
public function handle(InitDTO $state, \Closure $next): InitDTO
{
$trace = app(TraceService::class);

return $trace->traceMethod($this->getSpanName(), fn () => $this->execute($state, $next));
}

abstract protected function getSpanName(): string;

abstract protected function execute(InitDTO $state, \Closure $next): InitDTO;
}
12 changes: 8 additions & 4 deletions app/Actions/Photo/Pipes/Init/AssertSupportedMedia.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

namespace App\Actions\Photo\Pipes\Init;

use App\Contracts\PhotoCreate\InitPipe;
use App\DTO\PhotoCreate\InitDTO;
use App\Exceptions\MediaFileOperationException;
use App\Exceptions\MediaFileUnsupportedException;
Expand All @@ -17,7 +16,7 @@
/**
* Assert whether we support said file.
*/
class AssertSupportedMedia implements InitPipe
class AssertSupportedMedia extends AbstractInitPipe
{
public function __construct(
private FileExtensionService $file_extension_service,
Expand All @@ -30,7 +29,7 @@ public function __construct(
* @throws MediaFileUnsupportedException
* @throws MediaFileOperationException
*/
public function handle(InitDTO $state, \Closure $next): InitDTO
protected function execute(InitDTO $state, \Closure $next): InitDTO
{
$this->file_extension_service->assertIsSupportedMediaOrAcceptedRaw(
$state->source_file->getPath(),
Expand All @@ -40,4 +39,9 @@ public function handle(InitDTO $state, \Closure $next): InitDTO

return $next($state);
}
}

protected function getSpanName(): string
{
return 'photo.assert_supported_media';
}
}
Loading
Loading