From 5a4c154bc5f78906c343dff6bc131a9f7d36dc2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Viguier?= Date: Mon, 26 Dec 2022 16:45:05 +0100 Subject: [PATCH] =?UTF-8?q?Use=20Enum=20to=20enforce=20stricter=20types=20?= =?UTF-8?q?(=E2=9A=A0=20php=208.1)=20(#1618)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * use Enum * fix tests & phpstan * support Severity Type * more lax values for ASC DESC * Change FULL for ORIGINAL + DonwloadVariantType enum --- .github/workflows/CICD.yml | 11 +- .github/workflows/php-cs-fixer.yml | 2 +- README.md | 6 +- app/Actions/Album/PositionData.php | 4 +- app/Actions/Albums/PositionData.php | 4 +- app/Actions/Albums/Top.php | 4 +- app/Actions/Albums/Tree.php | 4 +- .../Pipes/Checks/PHPVersionCheck.php | 10 +- app/Actions/InstallUpdate/CheckUpdate.php | 17 +- app/Actions/Photo/Archive.php | 99 +--- .../Strategies/AddStandaloneStrategy.php | 6 +- .../Photo/Strategies/RotateStrategy.php | 5 +- app/Assets/BaseSizeVariantNamingStrategy.php | 10 +- ...tGroupedWithRandomSuffixNamingStrategy.php | 26 +- app/Console/Commands/ExifLens.php | 4 +- app/Console/Commands/GenerateThumbs.php | 20 +- app/Console/Commands/Ghostbuster.php | 3 +- app/Console/Commands/ShowLogs.php | 2 +- app/Console/Commands/Takedate.php | 4 +- app/Console/Commands/VideoData.php | 4 +- .../Http/Requests/HasSizeVariant.php | 6 +- .../AbstractSizeVariantNamingStrategy.php | 5 +- app/Contracts/Models/SizeVariantFactory.php | 21 +- app/DTO/AlbumSortingCriterion.php | 29 +- app/DTO/ArrayableDTO.php | 14 +- app/DTO/BaseSortingCriterion.php | 38 -- app/DTO/DiagnosticInfo.php | 13 +- app/DTO/ImportEventReport.php | 10 +- app/DTO/PhotoSortingCriterion.php | 31 +- app/DTO/SortingCriterion.php | 23 + app/Enum/ColumnSortingAlbumType.php | 30 ++ app/Enum/ColumnSortingPhotoType.php | 31 ++ app/Enum/ColumnSortingType.php | 26 + app/Enum/DownloadVariantType.php | 40 ++ app/Enum/OrderSortingType.php | 13 + app/Enum/SeverityType.php | 22 + app/Enum/SizeVariantType.php | 37 ++ app/Enum/UpdateStatus.php | 18 + app/Exceptions/Handler.php | 25 +- app/Http/Middleware/ContentType.php | 2 +- .../Requests/Album/SetAlbumSortingRequest.php | 16 +- .../Requests/Photo/ArchivePhotosRequest.php | 23 +- .../Settings/SetSortingSettingsRequest.php | 47 +- .../Requests/Traits/HasSizeVariantTrait.php | 8 +- app/Image/SizeVariantDefaultFactory.php | 81 ++-- app/Locale/ChineseSimplified.php | 1 + app/Locale/ChineseTraditional.php | 1 + app/Locale/Czech.php | 1 + app/Locale/Dutch.php | 1 + app/Locale/English.php | 1 + app/Locale/French.php | 1 + app/Locale/German.php | 1 + app/Locale/Greek.php | 1 + app/Locale/Italian.php | 1 + app/Locale/NorwegianBokmal.php | 1 + app/Locale/Polish.php | 1 + app/Locale/Portuguese.php | 1 + app/Locale/Russian.php | 1 + app/Locale/Slovak.php | 1 + app/Locale/Spanish.php | 1 + app/Locale/Swedish.php | 1 + app/Locale/Vietnamese.php | 1 + app/ModelFunctions/LogFunctions.php | 7 +- app/Models/BaseAlbumImpl.php | 10 +- app/Models/Configs.php | 26 +- app/Models/Extensions/SizeVariants.php | 78 ++- app/Models/Extensions/SortingDecorator.php | 68 +-- app/Models/Extensions/Thumb.php | 19 +- app/Models/Logs.php | 82 ++-- app/Models/SizeVariant.php | 46 +- app/Relations/BaseHasManyPhotos.php | 6 +- app/Relations/HasAlbumThumb.php | 6 +- app/Relations/HasManyChildAlbums.php | 4 +- app/Relations/HasManyChildPhotos.php | 10 +- app/Relations/HasManyPhotosByTag.php | 6 +- app/Relations/HasManyPhotosRecursively.php | 7 +- app/Rules/AlbumSortingRule.php | 31 -- app/Rules/OrderRule.php | 44 -- app/Rules/PhotoSortingRule.php | 31 -- app/Rules/SizeVariantRule.php | 44 -- app/SmartAlbums/BaseSmartAlbum.php | 3 +- bootstrap/PanicAttack.php | 7 - composer.json | 4 +- composer.lock | 449 ++++++++++-------- public/Lychee-front | 2 +- public/dist/frontend.js | 7 +- resources/views/logs/list.blade.php | 2 +- tests/Feature/CommandGenerateThumbsTest.php | 4 +- tests/Feature/CommandVideoDataTest.php | 4 +- tests/Feature/Lib/PhotosUnitTest.php | 3 +- tests/Feature/PhotosDownloadTest.php | 22 +- tests/Feature/SettingsTest.php | 33 +- 92 files changed, 959 insertions(+), 977 deletions(-) delete mode 100644 app/DTO/BaseSortingCriterion.php create mode 100644 app/DTO/SortingCriterion.php create mode 100644 app/Enum/ColumnSortingAlbumType.php create mode 100644 app/Enum/ColumnSortingPhotoType.php create mode 100644 app/Enum/ColumnSortingType.php create mode 100644 app/Enum/DownloadVariantType.php create mode 100644 app/Enum/OrderSortingType.php create mode 100644 app/Enum/SeverityType.php create mode 100644 app/Enum/SizeVariantType.php create mode 100644 app/Enum/UpdateStatus.php delete mode 100644 app/Rules/AlbumSortingRule.php delete mode 100644 app/Rules/OrderRule.php delete mode 100644 app/Rules/PhotoSortingRule.php delete mode 100644 app/Rules/SizeVariantRule.php diff --git a/.github/workflows/CICD.yml b/.github/workflows/CICD.yml index 675f125ff99..27d5ecbd2a3 100644 --- a/.github/workflows/CICD.yml +++ b/.github/workflows/CICD.yml @@ -38,7 +38,7 @@ jobs: - name: Set up PHP uses: shivammathur/setup-php@v2 with: - php-version: 8.0 + php-version: 8.1 - name: Checkout code uses: actions/checkout@v3 @@ -70,7 +70,7 @@ jobs: run: PHP_CS_FIXER_IGNORE_ENV=1 vendor/bin/php-cs-fixer fix --config=.php-cs-fixer.php --verbose --diff --dry-run phpstan: - name: 2️⃣ PHP 8.0 - PHPStan + name: 2️⃣ PHP 8.1 - PHPStan runs-on: ubuntu-latest needs: - php_syntax_errors @@ -81,9 +81,8 @@ jobs: - name: Setup PHP uses: shivammathur/setup-php@v2 with: - php-version: 8.0 + php-version: 8.1 coverage: none - tools: phpstan - name: Install Composer dependencies uses: ramsey/composer-install@v2 @@ -99,7 +98,6 @@ jobs: strategy: matrix: php-version: - - 8.0 - 8.1 - 8.2 sql-versions: @@ -181,7 +179,6 @@ jobs: strategy: matrix: php-version: - - 8.0 - 8.1 - 8.2 sql-versions: @@ -275,7 +272,7 @@ jobs: - name: Setup PHP uses: shivammathur/setup-php@v2 with: - php-version: 8.0 + php-version: 8.1 extensions: ${{ env.extensions }} coverage: none diff --git a/.github/workflows/php-cs-fixer.yml b/.github/workflows/php-cs-fixer.yml index 3eb6fcebc0e..26a4d1ae572 100644 --- a/.github/workflows/php-cs-fixer.yml +++ b/.github/workflows/php-cs-fixer.yml @@ -30,7 +30,7 @@ jobs: coverage: none - name: Install PHP-CS-Fixer run: | - curl -L https://github.com/FriendsOfPHP/PHP-CS-Fixer/releases/download/v3.11.0/php-cs-fixer.phar -o .github/build/php-cs-fixer + curl -L https://github.com/FriendsOfPHP/PHP-CS-Fixer/releases/download/v3.13.0/php-cs-fixer.phar -o .github/build/php-cs-fixer chmod a+x .github/build/php-cs-fixer - name: Prepare Git User run: | diff --git a/README.md b/README.md index 85f4f0d9dcb..f58bd4e35c9 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@

@LycheeOrg

[![GitHub Release][release-shield]](https://github.com/LycheeOrg/Lychee/releases) -[![PHP 8.0 & 8.1][php-shield]](https://lycheeorg.github.io/docs/#server-requirements) +[![PHP 8.1 & 8.2][php-shield]](https://lycheeorg.github.io/docs/#server-requirements) [![MIT License][license-shield]](https://github.com/LycheeOrg/Lychee/blob/master/LICENSE) [![Downloads][download-shield]](https://github.com/LycheeOrg/Lychee/releases)
@@ -32,7 +32,7 @@ Lychee is a free photo-management tool, which runs on your server or web-space. ## Installation -To run Lychee, everything you need is a web-server with PHP 8.0 or later and a MySQL-Database. Follow the instructions to install Lychee on your server. This version of Lychee is built on the Laravel framework. To install: +To run Lychee, everything you need is a web-server with PHP 8.1 or later and a database (MySQL/MariaDB, PostgreSQL or SQLite). Follow the instructions to install Lychee on your server. This version of Lychee is built on the Laravel framework. To install: 1. Clone this repo to your server and set the web root to `lychee/public` 2. Run `composer install --no-dev` to install dependencies @@ -96,7 +96,7 @@ We would like to thank Jetbrains for supporting us with their [Open Source Devel [build-status-shield]: https://img.shields.io/github/actions/workflow/status/LycheeOrg/Lychee/CICD.yml?branch=master [codecov-shield]: https://codecov.io/gh/LycheeOrg/Lychee/branch/master/graph/badge.svg [release-shield]: https://img.shields.io/github/release/LycheeOrg/Lychee.svg -[php-shield]: https://img.shields.io/badge/PHP-8.0%20|%208.1-blue +[php-shield]: https://img.shields.io/badge/PHP-8.1%20|%208.2-blue [license-shield]: https://img.shields.io/github/license/LycheeOrg/Lychee.svg [cii-shield]: https://img.shields.io/cii/summary/2855.svg [sonar-shield]: https://sonarcloud.io/api/project_badges/measure?project=LycheeOrg_Lychee-Laravel&metric=alert_status diff --git a/app/Actions/Album/PositionData.php b/app/Actions/Album/PositionData.php index 0498a9d5a4f..8d5601137c9 100644 --- a/app/Actions/Album/PositionData.php +++ b/app/Actions/Album/PositionData.php @@ -4,8 +4,8 @@ use App\Contracts\Models\AbstractAlbum; use App\DTO\PositionData as PositionDataDTO; +use App\Enum\SizeVariantType; use App\Models\Album; -use App\Models\SizeVariant; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\HasMany; @@ -33,7 +33,7 @@ public function get(AbstractAlbum $album, bool $includeSubAlbums = false): Posit // this really helps, if you want to show thousands // of photos on a map, as there are up to 7 size // variants per photo - $r->whereBetween('type', [SizeVariant::SMALL2X, SizeVariant::THUMB]); + $r->whereBetween('type', [SizeVariantType::SMALL2X, SizeVariantType::THUMB]); }, 'size_variants.sym_links', ]) diff --git a/app/Actions/Albums/PositionData.php b/app/Actions/Albums/PositionData.php index 7ce5b93efa6..23021e3411e 100644 --- a/app/Actions/Albums/PositionData.php +++ b/app/Actions/Albums/PositionData.php @@ -4,9 +4,9 @@ use App\Contracts\Exceptions\InternalLycheeException; use App\DTO\PositionData as PositionDataDTO; +use App\Enum\SizeVariantType; use App\Models\Configs; use App\Models\Photo; -use App\Models\SizeVariant; use App\Policies\PhotoQueryPolicy; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\HasMany; @@ -48,7 +48,7 @@ public function do(): PositionDataDTO // this really helps, if you want to show thousands // of photos on a map, as there are up to 7 size // variants per photo - $r->whereBetween('type', [SizeVariant::SMALL2X, SizeVariant::THUMB]); + $r->whereBetween('type', [SizeVariantType::SMALL2X, SizeVariantType::THUMB]); }, 'size_variants.sym_links', ]) diff --git a/app/Actions/Albums/Top.php b/app/Actions/Albums/Top.php index 75d25bf9f54..2f4312c75c5 100644 --- a/app/Actions/Albums/Top.php +++ b/app/Actions/Albums/Top.php @@ -5,6 +5,8 @@ use App\Contracts\Exceptions\InternalLycheeException; use App\DTO\AlbumSortingCriterion; use App\DTO\TopAlbums; +use App\Enum\ColumnSortingType; +use App\Enum\OrderSortingType; use App\Exceptions\ConfigurationKeyMissingException; use App\Exceptions\Internal\InvalidOrderDirectionException; use App\Factories\AlbumFactory; @@ -86,7 +88,7 @@ public function get(): TopAlbums if ($userID !== null) { // For authenticated users we group albums by ownership. $albums = (new SortingDecorator($query)) - ->orderBy('owner_id') + ->orderBy(ColumnSortingType::OWNER_ID, OrderSortingType::ASC) ->orderBy($this->sorting->column, $this->sorting->order) ->get(); diff --git a/app/Actions/Albums/Tree.php b/app/Actions/Albums/Tree.php index 4eebc3cd343..3aeb9c93dd0 100644 --- a/app/Actions/Albums/Tree.php +++ b/app/Actions/Albums/Tree.php @@ -5,6 +5,8 @@ use App\Contracts\Exceptions\InternalLycheeException; use App\DTO\AlbumSortingCriterion; use App\DTO\AlbumTree; +use App\Enum\ColumnSortingType; +use App\Enum\OrderSortingType; use App\Exceptions\ConfigurationKeyMissingException; use App\Exceptions\Internal\InvalidOrderDirectionException; use App\Models\Album; @@ -55,7 +57,7 @@ public function get(): AlbumTree ); if (Auth::check()) { // For authenticated users we group albums by ownership. - $query->orderBy('owner_id'); + $query->orderBy(ColumnSortingType::OWNER_ID, OrderSortingType::ASC); } $query->orderBy($this->sorting->column, $this->sorting->order); diff --git a/app/Actions/Diagnostics/Pipes/Checks/PHPVersionCheck.php b/app/Actions/Diagnostics/Pipes/Checks/PHPVersionCheck.php index 7ac2697f380..7fa1b9e8d7c 100644 --- a/app/Actions/Diagnostics/Pipes/Checks/PHPVersionCheck.php +++ b/app/Actions/Diagnostics/Pipes/Checks/PHPVersionCheck.php @@ -26,14 +26,10 @@ private function checkPhpVersion(array &$data): void // 26 Nov 2020 => 8.0 = RELEASED => 7.4 = WARNING // 6 Dec 2020 => 7.3 = DEPRECATED = ERROR // 25 Nov 2021 => 8.1 = Released => 8.0 = WARNING & 7.4 = ERROR - $php_error = 7.4; - $php_warning = 8; - $php_latest = 8.1; - // ! 08 Dec 2022 => 8.0 = DEPRECATED = ERROR - // $php_error = 8.1; - // $php_warning = 8.1; - // $php_latest = 8.2; + $php_error = 8.0; + $php_warning = 8.1; + $php_latest = 8.2; if (floatval(phpversion()) <= $php_error) { $data[] = 'Error: Upgrade to PHP ' . $php_warning . ' or higher'; diff --git a/app/Actions/InstallUpdate/CheckUpdate.php b/app/Actions/InstallUpdate/CheckUpdate.php index 7d12c6e0c6f..ece0d85e6f0 100644 --- a/app/Actions/InstallUpdate/CheckUpdate.php +++ b/app/Actions/InstallUpdate/CheckUpdate.php @@ -4,6 +4,7 @@ use App\Actions\Diagnostics\Pipes\Checks\MigrationCheck; use App\Actions\Diagnostics\Pipes\Checks\UpdatableCheck; +use App\Enum\UpdateStatus; use App\Metadata\Versions\FileVersion; use App\Metadata\Versions\GitHubVersion; use App\Metadata\Versions\InstalledVersion; @@ -33,16 +34,16 @@ public function __construct( * - `2` - Not up-to-date. * - `3` - Require migration. * - * @return int the update state between 0..3 + * @return UpdateStatus the update state between 0..3 */ - public function getCode(): int + public function getCode(): UpdateStatus { if ($this->installedVersion->isRelease()) { // @codeCoverageIgnoreStart return match (false) { - MigrationCheck::isUpToDate() => 3, - $this->fileVersion->isUpToDate() => 2, - default => 1 + MigrationCheck::isUpToDate() => UpdateStatus::REQUIRE_MIGRATION, + $this->fileVersion->isUpToDate() => UpdateStatus::NOT_UP_TO_DATE, + default => UpdateStatus::UP_TO_DATE }; // @codeCoverageIgnoreEnd } @@ -51,13 +52,13 @@ public function getCode(): int UpdatableCheck::assertUpdatability(); // @codeCoverageIgnoreStart if (!$this->gitHubFunctions->isUpToDate()) { - return 2; + return UpdateStatus::NOT_UP_TO_DATE; } else { - return 1; + return UpdateStatus::UP_TO_DATE; } // @codeCoverageIgnoreEnd } catch (\Exception $e) { - return 0; + return UpdateStatus::NOT_MASTER; } } } diff --git a/app/Actions/Photo/Archive.php b/app/Actions/Photo/Archive.php index 5f381717df6..f5f7ef4a6e4 100644 --- a/app/Actions/Photo/Archive.php +++ b/app/Actions/Photo/Archive.php @@ -5,13 +5,14 @@ use App\Actions\Photo\Extensions\ArchiveFileInfo; use App\Contracts\Exceptions\LycheeException; use App\Contracts\Models\AbstractSizeVariantNamingStrategy; +use App\Enum\DownloadVariantType; +use App\Enum\SizeVariantType; use App\Exceptions\ConfigurationKeyMissingException; use App\Exceptions\Internal\FrameworkException; use App\Exceptions\Internal\InvalidSizeVariantException; use App\Image\Files\FlysystemFile; use App\Models\Configs; use App\Models\Photo; -use App\Models\SizeVariant; use Illuminate\Database\Eloquent\Collection; use Safe\Exceptions\InfoException; use function Safe\fclose; @@ -27,36 +28,6 @@ class Archive { - public const LIVEPHOTOVIDEO = 'LIVEPHOTOVIDEO'; - public const FULL = 'FULL'; - public const MEDIUM2X = 'MEDIUM2X'; - public const MEDIUM = 'MEDIUM'; - public const SMALL2X = 'SMALL2X'; - public const SMALL = 'SMALL'; - public const THUMB2X = 'THUMB2X'; - public const THUMB = 'THUMB'; - - public const VARIANTS = [ - self::LIVEPHOTOVIDEO, - self::FULL, - self::MEDIUM2X, - self::MEDIUM, - self::SMALL2X, - self::SMALL, - self::THUMB2X, - self::THUMB, - ]; - - public const VARIANT2VARIANT = [ - self::FULL => SizeVariant::ORIGINAL, - self::MEDIUM2X => SizeVariant::MEDIUM2X, - self::MEDIUM => SizeVariant::MEDIUM, - self::SMALL2X => SizeVariant::SMALL2X, - self::SMALL => SizeVariant::SMALL, - self::THUMB2X => SizeVariant::THUMB2X, - self::THUMB => SizeVariant::THUMB, - ]; - public const BAD_CHARS = [ "\x00", "\x01", "\x02", "\x03", "\x04", "\x05", "\x06", "\x07", "\x08", "\x09", "\x0a", "\x0b", "\x0c", "\x0d", "\x0e", "\x0f", @@ -74,29 +45,19 @@ class Archive * a single element) or a ZIP file (if the array of photo IDs contains * more than one element). * - * @param Collection $photos the photos which shall be included - * in the response - * @param string $variant the desired variant of the photo; - * valid values are - * {@link Archive::LIVEPHOTOVIDEO}, - * {@link Archive::FULL}, - * {@link Archive::MEDIUM2X}, - * {@link Archive::MEDIUM}, - * {@link Archive::SMALL2X}, - * {@link Archive::SMALL}, - * {@link Archive::THUMB2X}, - * {@link Archive::THUMB} + * @param Collection $photos the photos which shall be included in the response + * @param DownloadVariantType $downloadVariant the desired variant of the photo * * @return StreamedResponse * * @throws LycheeException */ - public function do(Collection $photos, string $variant): StreamedResponse + public function do(Collection $photos, DownloadVariantType $downloadVariant): StreamedResponse { if ($photos->count() === 1) { - $response = $this->file($photos->first(), $variant); + $response = $this->file($photos->first(), $downloadVariant); } else { - $response = $this->zip($photos, $variant); + $response = $this->zip($photos, $downloadVariant); } return $response; @@ -117,16 +78,16 @@ public function do(Collection $photos, string $variant): StreamedResponse * However, the client would not get a "nice" file name, but the * random file name of the size variant. * - * @param Photo $photo the photo - * @param string $variant the requested size variant + * @param Photo $photo the photo + * @param DownloadVariantType $downloadVariant the requested size variant * * @return StreamedResponse * * @throws LycheeException */ - protected function file(Photo $photo, string $variant): StreamedResponse + protected function file(Photo $photo, DownloadVariantType $downloadVariant): StreamedResponse { - $archiveFileInfo = $this->extractFileInfo($photo, $variant); + $archiveFileInfo = $this->extractFileInfo($photo, $downloadVariant); $responseGenerator = function () use ($archiveFileInfo) { $outputStream = fopen('php://output', 'wb'); @@ -155,7 +116,7 @@ protected function file(Photo $photo, string $variant): StreamedResponse // hexadecimal string. $response->headers->set('ETag', md5( $archiveFileInfo->getFile()->getBasename() . - $variant . + $downloadVariant->value . $photo->updated_at->toAtomString() . $archiveFileInfo->getFile()->getFilesize()) ); @@ -168,19 +129,19 @@ protected function file(Photo $photo, string $variant): StreamedResponse } /** - * @param Collection $photos - * @param string $variant + * @param Collection $photos + * @param DownloadVariantType $downloadVariant * * @return StreamedResponse * * @throws FrameworkException * @throws ConfigurationKeyMissingException */ - protected function zip(Collection $photos, string $variant): StreamedResponse + protected function zip(Collection $photos, DownloadVariantType $downloadVariant): StreamedResponse { $this->deflateLevel = Configs::getValueAsInt('zip_deflate_level'); - $responseGenerator = function () use ($variant, $photos) { + $responseGenerator = function () use ($downloadVariant, $photos) { $options = new \ZipStream\Option\Archive(); $options->setEnableZip64(Configs::getValueAsBool('zip64')); $options->setZeroHeader(true); @@ -247,7 +208,7 @@ protected function zip(Collection $photos, string $variant): StreamedResponse // Partition the set /** @var Photo $photo */ foreach ($photos as $photo) { - $archiveFileInfo = $this->extractFileInfo($photo, $variant); + $archiveFileInfo = $this->extractFileInfo($photo, $downloadVariant); $archiveFileInfos[] = $archiveFileInfo; $filename = $archiveFileInfo->getFilename(); if (array_key_exists($filename, $ambiguousFilenames)) { @@ -315,33 +276,23 @@ protected function zip(Collection $photos, string $variant): StreamedResponse /** * Creates a {@link ArchiveFileInfo} for the indicated photo and variant. * - * @param Photo $photo the photo whose archive information - * shall be returned - * @param string $variant the desired variant of the photo; valid values - * are - * {@link Archive::LIVEPHOTOVIDEO}, - * {@link Archive::FULL}, - * {@link Archive::MEDIUM2X}, - * {@link Archive::MEDIUM}, - * {@link Archive::SMALL2X}, - * {@link Archive::SMALL}, - * {@link Archive::THUMB2X}, - * {@link Archive::THUMB} + * @param Photo $photo the photo whose archive information shall be returned + * @param DownloadVariantType $downloadVariant the desired variant of the photo * * @return ArchiveFileInfo the created archive info * * @throws InvalidSizeVariantException */ - protected function extractFileInfo(Photo $photo, string $variant): ArchiveFileInfo + protected function extractFileInfo(Photo $photo, DownloadVariantType $downloadVariant): ArchiveFileInfo { $validFilename = str_replace(self::BAD_CHARS, '', $photo->title); $baseFilename = $validFilename !== '' ? $validFilename : 'Untitled'; - if ($variant === self::LIVEPHOTOVIDEO) { + if ($downloadVariant === DownloadVariantType::LIVEPHOTOVIDEO) { $sourceFile = new FlysystemFile(AbstractSizeVariantNamingStrategy::getImageDisk(), $photo->live_photo_short_path); $baseFilenameAddon = ''; - } elseif (array_key_exists($variant, self::VARIANT2VARIANT)) { - $sv = $photo->size_variants->getSizeVariant(self::VARIANT2VARIANT[$variant]); + } else { + $sv = $photo->size_variants->getSizeVariant($downloadVariant->getSizeVariantType()); $baseFilenameAddon = ''; if ($sv !== null) { $sourceFile = $sv->getFile(); @@ -349,14 +300,12 @@ protected function extractFileInfo(Photo $photo, string $variant): ArchiveFileIn // particular suffix but remain as is. // All other size variants (i.e. the generated, smaller ones) // get size information as suffix. - if ($sv->type !== SizeVariant::ORIGINAL) { + if ($sv->type !== SizeVariantType::ORIGINAL) { $baseFilenameAddon = '-' . $sv->width . 'x' . $sv->height; } } else { throw new InvalidSizeVariantException('Size variant missing'); } - } else { - throw new InvalidSizeVariantException('Invalid type of size variant ' . $variant); } return new ArchiveFileInfo($baseFilename, $baseFilenameAddon, $sourceFile); diff --git a/app/Actions/Photo/Strategies/AddStandaloneStrategy.php b/app/Actions/Photo/Strategies/AddStandaloneStrategy.php index ded8463d15a..6b77247ed28 100644 --- a/app/Actions/Photo/Strategies/AddStandaloneStrategy.php +++ b/app/Actions/Photo/Strategies/AddStandaloneStrategy.php @@ -9,6 +9,7 @@ use App\Contracts\Models\AbstractSizeVariantNamingStrategy; use App\Contracts\Models\SizeVariantFactory; use App\DTO\ImageDimension; +use App\Enum\SizeVariantType; use App\Exceptions\ConfigurationException; use App\Exceptions\Handler; use App\Exceptions\Internal\FrameworkException; @@ -21,7 +22,6 @@ use App\Image\Handlers\VideoHandler; use App\Image\StreamStat; use App\Models\Photo; -use App\Models\SizeVariant; use Illuminate\Contracts\Container\BindingResolutionException; class AddStandaloneStrategy extends AbstractAddStrategy @@ -135,7 +135,7 @@ public function do(): Photo // If import strategy request to delete the source file. // `$this->sourceFile` will be deleted after this step. // But `$this->sourceImage` remains in memory. - $targetFile = $this->namingStrategy->createFile(SizeVariant::ORIGINAL); + $targetFile = $this->namingStrategy->createFile(SizeVariantType::ORIGINAL); $streamStat = $this->putSourceIntoFinalDestination($targetFile); // If we have a temporary video file from a Google Motion Picture, @@ -169,7 +169,7 @@ public function do(): Photo $this->sourceImage->getDimensions() : new ImageDimension($this->parameters->exifInfo->width, $this->parameters->exifInfo->height); $this->photo->size_variants->create( - SizeVariant::ORIGINAL, + SizeVariantType::ORIGINAL, $targetFile->getRelativePath(), $imageDim, $streamStat->bytes diff --git a/app/Actions/Photo/Strategies/RotateStrategy.php b/app/Actions/Photo/Strategies/RotateStrategy.php index 5dff9ebeeff..7b0dcb0259d 100644 --- a/app/Actions/Photo/Strategies/RotateStrategy.php +++ b/app/Actions/Photo/Strategies/RotateStrategy.php @@ -6,6 +6,7 @@ use App\Contracts\Models\AbstractSizeVariantNamingStrategy; use App\Contracts\Models\SizeVariantFactory; use App\DTO\ImageDimension; +use App\Enum\SizeVariantType; use App\Exceptions\Handler; use App\Exceptions\Internal\FrameworkException; use App\Exceptions\Internal\IllegalOrderOfOperationException; @@ -101,7 +102,7 @@ public function do(): Photo // Create new target file for rotated original size variant, // and stream it into the final place - $targetFile = $this->namingStrategy->createFile(SizeVariant::ORIGINAL); + $targetFile = $this->namingStrategy->createFile(SizeVariantType::ORIGINAL); $streamStat = $image->save($targetFile, true); // The checksum has been changed due to rotation. @@ -111,7 +112,7 @@ public function do(): Photo // Re-create original size variant of photo $newOriginalSizeVariant = $this->photo->size_variants->create( - SizeVariant::ORIGINAL, + SizeVariantType::ORIGINAL, $targetFile->getRelativePath(), $image->getDimensions(), $streamStat->bytes diff --git a/app/Assets/BaseSizeVariantNamingStrategy.php b/app/Assets/BaseSizeVariantNamingStrategy.php index 5754c73a2da..a22ec3d5122 100644 --- a/app/Assets/BaseSizeVariantNamingStrategy.php +++ b/app/Assets/BaseSizeVariantNamingStrategy.php @@ -3,9 +3,9 @@ namespace App\Assets; use App\Contracts\Models\AbstractSizeVariantNamingStrategy; +use App\Enum\SizeVariantType; use App\Exceptions\Internal\IllegalOrderOfOperationException; use App\Exceptions\Internal\MissingValueException; -use App\Models\SizeVariant; abstract class BaseSizeVariantNamingStrategy extends AbstractSizeVariantNamingStrategy { @@ -23,11 +23,11 @@ abstract class BaseSizeVariantNamingStrategy extends AbstractSizeVariantNamingSt * @throws MissingValueException * @throws IllegalOrderOfOperationException */ - protected function generateExtension(int $sizeVariant): string + protected function generateExtension(SizeVariantType $sizeVariant): string { - if ($sizeVariant === SizeVariant::THUMB || - $sizeVariant === SizeVariant::THUMB2X || - ($sizeVariant !== SizeVariant::ORIGINAL && !$this->photo->isPhoto()) + if ($sizeVariant === SizeVariantType::THUMB || + $sizeVariant === SizeVariantType::THUMB2X || + ($sizeVariant !== SizeVariantType::ORIGINAL && !$this->photo->isPhoto()) ) { return self::THUMB_EXTENSION; } diff --git a/app/Assets/SizeVariantGroupedWithRandomSuffixNamingStrategy.php b/app/Assets/SizeVariantGroupedWithRandomSuffixNamingStrategy.php index 4853c7cbf6a..4e3132caa85 100644 --- a/app/Assets/SizeVariantGroupedWithRandomSuffixNamingStrategy.php +++ b/app/Assets/SizeVariantGroupedWithRandomSuffixNamingStrategy.php @@ -2,12 +2,11 @@ namespace App\Assets; +use App\Enum\SizeVariantType; use App\Exceptions\InsufficientEntropyException; -use App\Exceptions\Internal\InvalidSizeVariantException; use App\Exceptions\Internal\LycheeAssertionError; use App\Image\Files\FlysystemFile; use App\Models\Photo; -use App\Models\SizeVariant; use Safe\Exceptions\PcreException; /** @@ -20,19 +19,6 @@ */ class SizeVariantGroupedWithRandomSuffixNamingStrategy extends BaseSizeVariantNamingStrategy { - /** - * Maps a size variant to the path prefix (directory) where the file for that size variant is stored. - */ - public const VARIANT_2_PATH_PREFIX = [ - SizeVariant::THUMB => 'thumb', - SizeVariant::THUMB2X => 'thumb2x', - SizeVariant::SMALL => 'small', - SizeVariant::SMALL2X => 'small2x', - SizeVariant::MEDIUM => 'medium', - SizeVariant::MEDIUM2X => 'medium2x', - SizeVariant::ORIGINAL => 'original', - ]; - /** * The length of the random file name without file extension. * @@ -106,7 +92,7 @@ public function setPhoto(?Photo $photo): void // at the beginning. if (\Safe\preg_match( '#^\.?[/\\\\]?' . - self::VARIANT_2_PATH_PREFIX[SizeVariant::ORIGINAL] . '[/\\\\]' . + SizeVariantType::ORIGINAL->name() . '[/\\\\]' . '([0-9a-f]{2})[/\\\\]' . '([0-9a-f]{2})[/\\\\]' . '([0-9a-f]{' . (self::NAME_LENGTH - 4) . '})\.#i', @@ -131,14 +117,10 @@ public function setPhoto(?Photo $photo): void /** * {@inheritDoc} */ - public function createFile(int $sizeVariant): FlysystemFile + public function createFile(SizeVariantType $sizeVariant): FlysystemFile { - if (SizeVariant::ORIGINAL > $sizeVariant || $sizeVariant > SizeVariant::THUMB) { - throw new InvalidSizeVariantException('invalid $sizeVariant = ' . $sizeVariant); - } - $relativePath = - self::VARIANT_2_PATH_PREFIX[$sizeVariant] . DIRECTORY_SEPARATOR . + $sizeVariant->name() . DIRECTORY_SEPARATOR . $this->cachedRndMiddlePath . $this->generateExtension($sizeVariant); diff --git a/app/Console/Commands/ExifLens.php b/app/Console/Commands/ExifLens.php index 94833070903..815e81a68a2 100644 --- a/app/Console/Commands/ExifLens.php +++ b/app/Console/Commands/ExifLens.php @@ -3,12 +3,12 @@ namespace App\Console\Commands; use App\Contracts\Exceptions\ExternalLycheeException; +use App\Enum\SizeVariantType; use App\Exceptions\ModelDBException; use App\Exceptions\UnexpectedException; use App\Image\Files\BaseMediaFile; use App\Metadata\Extractor; use App\Models\Photo; -use App\Models\SizeVariant; use Illuminate\Console\Command; use Illuminate\Database\Eloquent\Relations\HasMany; use Safe\Exceptions\InfoException; @@ -52,7 +52,7 @@ public function handle(): int // we use lens because this is the one which is most likely to be empty. $photos = Photo::with(['size_variants' => function (HasMany $r) { - $r->where('type', '=', SizeVariant::ORIGINAL); + $r->where('type', '=', SizeVariantType::ORIGINAL); }]) ->where('lens', '=', '') ->whereNotIn('type', BaseMediaFile::SUPPORTED_VIDEO_MIME_TYPES) diff --git a/app/Console/Commands/GenerateThumbs.php b/app/Console/Commands/GenerateThumbs.php index dff7e17dd21..9561c93b80b 100644 --- a/app/Console/Commands/GenerateThumbs.php +++ b/app/Console/Commands/GenerateThumbs.php @@ -5,9 +5,9 @@ use App\Contracts\Exceptions\ExternalLycheeException; use App\Contracts\Exceptions\LycheeException; use App\Contracts\Models\SizeVariantFactory; +use App\Enum\SizeVariantType; use App\Exceptions\UnexpectedException; use App\Models\Photo; -use App\Models\SizeVariant; use Illuminate\Console\Command; use Illuminate\Database\Eloquent\Builder; use Safe\Exceptions\InfoException; @@ -17,17 +17,15 @@ class GenerateThumbs extends Command { /** - * @var array - * - * @phpstan-var array> + * @var array */ public const SIZE_VARIANTS = [ - 'thumb' => SizeVariant::THUMB, - 'thumb2x' => SizeVariant::THUMB2X, - 'small' => SizeVariant::SMALL, - 'small2x' => SizeVariant::SMALL2X, - 'medium' => SizeVariant::MEDIUM, - 'medium2x' => SizeVariant::MEDIUM2X, + 'thumb' => SizeVariantType::THUMB, + 'thumb2x' => SizeVariantType::THUMB2X, + 'small' => SizeVariantType::SMALL, + 'small2x' => SizeVariantType::SMALL2X, + 'medium' => SizeVariantType::MEDIUM, + 'medium2x' => SizeVariantType::MEDIUM2X, ]; /** @@ -56,7 +54,7 @@ public function handle(): int try { $sizeVariantName = strval($this->argument('type')); if (!array_key_exists($sizeVariantName, self::SIZE_VARIANTS)) { - $this->error(sprintf('Type %s is not one of %s', $sizeVariantName, implode(', ', array_flip(self::SIZE_VARIANTS)))); + $this->error(sprintf('Type %s is not one of %s', $sizeVariantName, implode(', ', array_keys(self::SIZE_VARIANTS)))); return 1; } diff --git a/app/Console/Commands/Ghostbuster.php b/app/Console/Commands/Ghostbuster.php index bb178ba2d0b..bdaf1c5fa8e 100644 --- a/app/Console/Commands/Ghostbuster.php +++ b/app/Console/Commands/Ghostbuster.php @@ -4,6 +4,7 @@ use App\Console\Commands\Utilities\Colorize; use App\Contracts\Models\AbstractSizeVariantNamingStrategy; +use App\Enum\SizeVariantType; use App\Exceptions\UnexpectedException; use App\Models\Photo; use App\Models\SizeVariant; @@ -168,7 +169,7 @@ public function handle(): int if ($dryrun) { $this->line(str_pad($sizeVariant->short_path, 50) . $this->col->red(' does not exist and photo would be removed') . '.'); } else { - if ($sizeVariant->type === SizeVariant::ORIGINAL) { + if ($sizeVariant->type === SizeVariantType::ORIGINAL) { $sizeVariant->photo->delete(); } else { $sizeVariant->delete(); diff --git a/app/Console/Commands/ShowLogs.php b/app/Console/Commands/ShowLogs.php index a933e4ae1ee..06c2112a3cc 100644 --- a/app/Console/Commands/ShowLogs.php +++ b/app/Console/Commands/ShowLogs.php @@ -96,7 +96,7 @@ private function action_show(int $n, string $order): void foreach ($logs->reverse() as $log) { $this->line($this->col->magenta($log->created_at) . ' -- ' - . $this->color_type(str_pad($log->type, 7)) + . $this->color_type(str_pad($log->type->value, 7)) . ' -- ' . $this->col->blue($log->function) . ' -- ' diff --git a/app/Console/Commands/Takedate.php b/app/Console/Commands/Takedate.php index aaaad084883..49000a86a77 100644 --- a/app/Console/Commands/Takedate.php +++ b/app/Console/Commands/Takedate.php @@ -4,10 +4,10 @@ use App\Contracts\Exceptions\ExternalLycheeException; use App\Contracts\Exceptions\InternalLycheeException; +use App\Enum\SizeVariantType; use App\Exceptions\UnexpectedException; use App\Metadata\Extractor; use App\Models\Photo; -use App\Models\SizeVariant; use Illuminate\Console\Command; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Support\Carbon; @@ -106,7 +106,7 @@ public function handle(): int // For faster iteration we eagerly load the original size variant, // but only the original size variant $photoQuery = Photo::with(['size_variants' => function (HasMany $r) { - $r->where('type', '=', SizeVariant::ORIGINAL); + $r->where('type', '=', SizeVariantType::ORIGINAL); }]); if (!$force) { diff --git a/app/Console/Commands/VideoData.php b/app/Console/Commands/VideoData.php index e4ff1260752..7496864c89d 100644 --- a/app/Console/Commands/VideoData.php +++ b/app/Console/Commands/VideoData.php @@ -5,11 +5,11 @@ use App\Contracts\Exceptions\ExternalLycheeException; use App\Contracts\Exceptions\LycheeException; use App\Contracts\Models\SizeVariantFactory; +use App\Enum\SizeVariantType; use App\Exceptions\UnexpectedException; use App\Image\Files\BaseMediaFile; use App\Metadata\Extractor; use App\Models\Photo; -use App\Models\SizeVariant; use Illuminate\Console\Command; use Illuminate\Database\Eloquent\Builder; use Safe\Exceptions\InfoException; @@ -62,7 +62,7 @@ public function handle(): int ->with(['size_variants']) ->whereIn('type', BaseMediaFile::SUPPORTED_VIDEO_MIME_TYPES) ->whereDoesntHave('size_variants', function (Builder $query) { - $query->where('type', '=', SizeVariant::THUMB); + $query->where('type', '=', SizeVariantType::THUMB); }) ->take($count) ->get(); diff --git a/app/Contracts/Http/Requests/HasSizeVariant.php b/app/Contracts/Http/Requests/HasSizeVariant.php index 6cc495f0084..8bd4fc26f89 100644 --- a/app/Contracts/Http/Requests/HasSizeVariant.php +++ b/app/Contracts/Http/Requests/HasSizeVariant.php @@ -2,10 +2,12 @@ namespace App\Contracts\Http\Requests; +use App\Enum\DownloadVariantType; + interface HasSizeVariant { /** - * @return string + * @return DownloadVariantType */ - public function sizeVariant(): string; + public function sizeVariant(): DownloadVariantType; } \ No newline at end of file diff --git a/app/Contracts/Models/AbstractSizeVariantNamingStrategy.php b/app/Contracts/Models/AbstractSizeVariantNamingStrategy.php index 5cf1d46dfcc..60f9b80d8cd 100644 --- a/app/Contracts/Models/AbstractSizeVariantNamingStrategy.php +++ b/app/Contracts/Models/AbstractSizeVariantNamingStrategy.php @@ -3,6 +3,7 @@ namespace App\Contracts\Models; use App\Contracts\Exceptions\LycheeException; +use App\Enum\SizeVariantType; use App\Image\Files\FlysystemFile; use App\Models\Photo; use Illuminate\Contracts\Filesystem\Filesystem; @@ -67,11 +68,11 @@ public function setPhoto(?Photo $photo): void /** * Creates a file for the designated size variant. * - * @param int $sizeVariant the size variant + * @param SizeVariantType $sizeVariant the size variant * * @return FlysystemFile the file * * @throws LycheeException */ - abstract public function createFile(int $sizeVariant): FlysystemFile; + abstract public function createFile(SizeVariantType $sizeVariant): FlysystemFile; } diff --git a/app/Contracts/Models/SizeVariantFactory.php b/app/Contracts/Models/SizeVariantFactory.php index 5ef17b63253..4c915f163f3 100644 --- a/app/Contracts/Models/SizeVariantFactory.php +++ b/app/Contracts/Models/SizeVariantFactory.php @@ -4,6 +4,7 @@ use App\Contracts\Exceptions\LycheeException; use App\Contracts\Image\ImageHandlerInterface; +use App\Enum\SizeVariantType; use App\Models\Photo; use App\Models\SizeVariant; use Illuminate\Support\Collection; @@ -48,22 +49,20 @@ public function init(Photo $photo, ?ImageHandlerInterface $referenceImage = null * {@link SizeVariantFactory::createSizeVariant()}. * Refer there for further information. * - * @param int $sizeVariant the desired size variant; admissible values - * are: - * {@link SizeVariant::THUMB}, - * {@link SizeVariant::THUMB2X}, - * {@link SizeVariant::SMALL}, - * {@link SizeVariant::SMALL2X}, - * {@link SizeVariant::MEDIUM} and - * {@link SizeVariant::MEDIUM2X} + * @param SizeVariantType $sizeVariant the desired size variant; admissible values + * are: + * {@link SizeVariantType::THUMB}, + * {@link SizeVariantType::THUMB2X}, + * {@link SizeVariantType::SMALL}, + * {@link SizeVariantType::SMALL2X}, + * {@link SizeVariantType::MEDIUM} and + * {@link SizeVariantType::MEDIUM2X} * * @return SizeVariant|null the freshly created and persisted size variant * * @throws LycheeException - * - * @phpstan-param int<0,6> $sizeVariant */ - public function createSizeVariantCond(int $sizeVariant): ?SizeVariant; + public function createSizeVariantCond(SizeVariantType $sizeVariant): ?SizeVariant; /** * Creates a selected set of size variants. diff --git a/app/DTO/AlbumSortingCriterion.php b/app/DTO/AlbumSortingCriterion.php index 8af7d64cebf..faccb7ca852 100644 --- a/app/DTO/AlbumSortingCriterion.php +++ b/app/DTO/AlbumSortingCriterion.php @@ -2,33 +2,26 @@ namespace App\DTO; +use App\Enum\ColumnSortingAlbumType; +use App\Enum\ColumnSortingType; +use App\Enum\OrderSortingType; use App\Models\Configs; -class AlbumSortingCriterion extends BaseSortingCriterion +class AlbumSortingCriterion extends SortingCriterion { - public const COLUMN_MIN_TAKEN_AT = 'min_taken_at'; - public const COLUMN_MAX_TAKEN_AT = 'max_taken_at'; - - public const COLUMNS = [ - BaseSortingCriterion::COLUMN_CREATED_AT, - BaseSortingCriterion::COLUMN_TITLE, - BaseSortingCriterion::COLUMN_DESCRIPTION, - BaseSortingCriterion::COLUMN_IS_PUBLIC, - self::COLUMN_MIN_TAKEN_AT, - self::COLUMN_MAX_TAKEN_AT, - ]; - /** * @return self - * - * @noinspection PhpDocMissingThrowsInspection */ public static function createDefault(): self { - /* @noinspection PhpUnhandledExceptionInspection */ + $columnSorting = Configs::getValueAsEnum('sorting_albums_col', ColumnSortingAlbumType::class); + $columnSorting = $columnSorting?->toColumnSortingType(); + + $orderSorting = Configs::getValueAsEnum('sorting_albums_order', OrderSortingType::class); + return new self( - Configs::getValueAsString('sorting_albums_col'), - Configs::getValueAsString('sorting_albums_order') + $columnSorting ?? ColumnSortingType::CREATED_AT, + $orderSorting ?? OrderSortingType::ASC ); } } diff --git a/app/DTO/ArrayableDTO.php b/app/DTO/ArrayableDTO.php index 58589b9f7db..2d9fb51324a 100644 --- a/app/DTO/ArrayableDTO.php +++ b/app/DTO/ArrayableDTO.php @@ -23,15 +23,17 @@ public function toArray(): array $cls = new \ReflectionClass($this); $props = $cls->getProperties(\ReflectionProperty::IS_PUBLIC); foreach ($props as $prop) { - $value = $prop->getValue($this); - if (is_object($value)) { - if ($value instanceof Arrayable) { - $value = $value->toArray(); + $propertyValue = $prop->getValue($this); + if (is_object($propertyValue)) { + if ($propertyValue instanceof Arrayable) { + $propertyValue = $propertyValue->toArray(); + } elseif ($propertyValue instanceof \BackedEnum) { + $propertyValue = $propertyValue->value; } else { - throw new LycheeLogicException(sprintf('Unable to convert %s into an array', get_class($value))); + throw new LycheeLogicException(sprintf('Unable to convert %s into an array', get_class($propertyValue))); } } - $result[$prop->getName()] = $value; + $result[$prop->getName()] = $propertyValue; } return $result; diff --git a/app/DTO/BaseSortingCriterion.php b/app/DTO/BaseSortingCriterion.php deleted file mode 100644 index a069215c763..00000000000 --- a/app/DTO/BaseSortingCriterion.php +++ /dev/null @@ -1,38 +0,0 @@ -column = $column; - $this->order = $order; - } -} diff --git a/app/DTO/DiagnosticInfo.php b/app/DTO/DiagnosticInfo.php index 07564bf6505..76618636a10 100644 --- a/app/DTO/DiagnosticInfo.php +++ b/app/DTO/DiagnosticInfo.php @@ -2,20 +2,21 @@ namespace App\DTO; +use App\Enum\UpdateStatus; + class DiagnosticInfo extends ArrayableDTO { /** - * @param string[] $errors list of error messages - * @param string[] $infos list of informational messages - * @param string[] $configs list of configuration settings - * @param int $update the update status, see - * {@link \App\Actions\InstallUpdate\CheckUpdate::getCode()} + * @param string[] $errors list of error messages + * @param string[] $infos list of informational messages + * @param string[] $configs list of configuration settings + * @param UpdateStatus $update the update status */ public function __construct( public array $errors, public array $infos, public array $configs, - public int $update + public UpdateStatus $update ) { } } \ No newline at end of file diff --git a/app/DTO/ImportEventReport.php b/app/DTO/ImportEventReport.php index 774630cd974..95f1771c3bf 100644 --- a/app/DTO/ImportEventReport.php +++ b/app/DTO/ImportEventReport.php @@ -2,8 +2,8 @@ namespace App\DTO; +use App\Enum\SeverityType; use App\Exceptions\Handler as ExceptionHandler; -use App\Models\Logs; class ImportEventReport extends BaseImportReport { @@ -11,11 +11,11 @@ class ImportEventReport extends BaseImportReport protected string $subtype; protected ?string $path; - protected int $severity; + protected SeverityType $severity; protected string $message; protected ?\Throwable $throwable; - protected function __construct(string $subtype, int $severity, ?string $path, string $message, ?\Throwable $throwable = null) + protected function __construct(string $subtype, SeverityType $severity, ?string $path, string $message, ?\Throwable $throwable = null) { parent::__construct(self::REPORT_TYPE); $this->subtype = $subtype; @@ -27,7 +27,7 @@ protected function __construct(string $subtype, int $severity, ?string $path, st public static function createWarning(string $subtype, ?string $path, string $message): self { - return new self($subtype, Logs::SEVERITY_WARNING, $path, $message); + return new self($subtype, SeverityType::WARNING, $path, $message); } public static function createFromException(\Throwable $e, ?string $path): self @@ -47,7 +47,7 @@ public function toArray(): array { return array_merge(parent::toArray(), [ 'subtype' => $this->subtype, - 'severity' => Logs::SEVERITY_2_STRING[$this->severity], + 'severity' => $this->severity->value, 'path' => $this->path, 'message' => $this->message, ]); diff --git a/app/DTO/PhotoSortingCriterion.php b/app/DTO/PhotoSortingCriterion.php index 13daf8fc553..0d80853eb7e 100644 --- a/app/DTO/PhotoSortingCriterion.php +++ b/app/DTO/PhotoSortingCriterion.php @@ -2,35 +2,26 @@ namespace App\DTO; +use App\Enum\ColumnSortingPhotoType; +use App\Enum\ColumnSortingType; +use App\Enum\OrderSortingType; use App\Models\Configs; -class PhotoSortingCriterion extends BaseSortingCriterion +class PhotoSortingCriterion extends SortingCriterion { - public const COLUMN_TAKEN_AT = 'taken_at'; - public const COLUMN_IS_STARRED = 'is_starred'; - public const COLUMN_TYPE = 'type'; - - public const COLUMNS = [ - BaseSortingCriterion::COLUMN_CREATED_AT, - BaseSortingCriterion::COLUMN_TITLE, - BaseSortingCriterion::COLUMN_DESCRIPTION, - BaseSortingCriterion::COLUMN_IS_PUBLIC, - self::COLUMN_TAKEN_AT, - self::COLUMN_IS_STARRED, - self::COLUMN_TYPE, - ]; - /** * @return self - * - * @noinspection PhpDocMissingThrowsInspection */ public static function createDefault(): self { - /* @noinspection PhpUnhandledExceptionInspection */ + $columnSorting = Configs::getValueAsEnum('sorting_photos_col', ColumnSortingPhotoType::class); + $columnSorting = $columnSorting?->toColumnSortingType(); + + $orderSorting = Configs::getValueAsEnum('sorting_photos_order', OrderSortingType::class); + return new self( - Configs::getValueAsString('sorting_photos_col'), - Configs::getValueAsString('sorting_photos_order') + $columnSorting ?? ColumnSortingType::CREATED_AT, + $orderSorting ?? OrderSortingType::ASC ); } } diff --git a/app/DTO/SortingCriterion.php b/app/DTO/SortingCriterion.php new file mode 100644 index 00000000000..fe2b9b3a33c --- /dev/null +++ b/app/DTO/SortingCriterion.php @@ -0,0 +1,23 @@ +value); + } +} diff --git a/app/Enum/ColumnSortingPhotoType.php b/app/Enum/ColumnSortingPhotoType.php new file mode 100644 index 00000000000..471c5c2fe1b --- /dev/null +++ b/app/Enum/ColumnSortingPhotoType.php @@ -0,0 +1,31 @@ +value); + } +} diff --git a/app/Enum/ColumnSortingType.php b/app/Enum/ColumnSortingType.php new file mode 100644 index 00000000000..c4a7d0a7293 --- /dev/null +++ b/app/Enum/ColumnSortingType.php @@ -0,0 +1,26 @@ + SizeVariantType::THUMB, + self::THUMB2X => SizeVariantType::THUMB2X, + self::SMALL => SizeVariantType::SMALL, + self::SMALL2X => SizeVariantType::SMALL2X, + self::MEDIUM => SizeVariantType::MEDIUM, + self::MEDIUM2X => SizeVariantType::MEDIUM2X, + self::ORIGINAL => SizeVariantType::ORIGINAL, + self::LIVEPHOTOVIDEO => null + }; + } +} \ No newline at end of file diff --git a/app/Enum/OrderSortingType.php b/app/Enum/OrderSortingType.php new file mode 100644 index 00000000000..fdc5bd81f0f --- /dev/null +++ b/app/Enum/OrderSortingType.php @@ -0,0 +1,13 @@ + 'thumb', + self::THUMB2X => 'thumb2x', + self::SMALL => 'small', + self::SMALL2X => 'small2x', + self::MEDIUM => 'medium', + self::MEDIUM2X => 'medium2x', + self::ORIGINAL => 'original', + }; + } +} \ No newline at end of file diff --git a/app/Enum/UpdateStatus.php b/app/Enum/UpdateStatus.php new file mode 100644 index 00000000000..41b9ab9b882 --- /dev/null +++ b/app/Enum/UpdateStatus.php @@ -0,0 +1,18 @@ + - * - * @phpstan-var array> + * @var array */ public const EXCEPTION2SEVERITY = [ - PhotoResyncedException::class => Logs::SEVERITY_WARNING, - PhotoSkippedException::class => Logs::SEVERITY_WARNING, - ImportCancelledException::class => Logs::SEVERITY_NOTICE, - ConfigurationException::class => Logs::SEVERITY_NOTICE, - LocationDecodingFailed::class => Logs::SEVERITY_WARNING, + PhotoResyncedException::class => SeverityType::WARNING, + PhotoSkippedException::class => SeverityType::WARNING, + ImportCancelledException::class => SeverityType::NOTICE, + ConfigurationException::class => SeverityType::NOTICE, + LocationDecodingFailed::class => SeverityType::WARNING, ]; /** @@ -400,15 +399,13 @@ public function report(\Throwable $e): void /** * @param \Throwable $e * - * @return int - * - * @phpstan-return int<0,7> + * @return SeverityType */ - public static function getLogSeverity(\Throwable $e): int + public static function getLogSeverity(\Throwable $e): SeverityType { return array_key_exists(get_class($e), self::EXCEPTION2SEVERITY) ? self::EXCEPTION2SEVERITY[get_class($e)] : - Logs::SEVERITY_ERROR; + SeverityType::ERROR; } /** diff --git a/app/Http/Middleware/ContentType.php b/app/Http/Middleware/ContentType.php index 8bc394c4244..caeef4c7978 100644 --- a/app/Http/Middleware/ContentType.php +++ b/app/Http/Middleware/ContentType.php @@ -39,7 +39,7 @@ public function handle(Request $request, \Closure $next, string $contentType): m throw new UnexpectedContentType(self::JSON); } } elseif ($contentType === self::MULTIPART) { - if ($request->getContentType() !== 'form') { + if ($request->getContentTypeFormat() !== 'form') { throw new UnexpectedContentType(self::MULTIPART); } } else { diff --git a/app/Http/Requests/Album/SetAlbumSortingRequest.php b/app/Http/Requests/Album/SetAlbumSortingRequest.php index c1d13a39fe6..678c3ff2c9a 100644 --- a/app/Http/Requests/Album/SetAlbumSortingRequest.php +++ b/app/Http/Requests/Album/SetAlbumSortingRequest.php @@ -6,13 +6,14 @@ use App\Contracts\Http\Requests\HasSortingCriterion; use App\Contracts\Http\Requests\RequestAttribute; use App\DTO\PhotoSortingCriterion; +use App\Enum\ColumnSortingPhotoType; +use App\Enum\OrderSortingType; use App\Http\Requests\BaseApiRequest; use App\Http\Requests\Traits\Authorize\AuthorizeCanEditAlbumTrait; use App\Http\Requests\Traits\HasBaseAlbumTrait; use App\Http\Requests\Traits\HasSortingCriterionTrait; -use App\Rules\OrderRule; -use App\Rules\PhotoSortingRule; use App\Rules\RandomIDRule; +use Illuminate\Validation\Rules\Enum; class SetAlbumSortingRequest extends BaseApiRequest implements HasBaseAlbum, HasSortingCriterion { @@ -27,10 +28,10 @@ public function rules(): array { return [ RequestAttribute::ALBUM_ID_ATTRIBUTE => ['required', new RandomIDRule(false)], - RequestAttribute::SORTING_COLUMN_ATTRIBUTE => ['present', new PhotoSortingRule()], + RequestAttribute::SORTING_COLUMN_ATTRIBUTE => ['present', 'nullable', new Enum(ColumnSortingPhotoType::class)], RequestAttribute::SORTING_ORDER_ATTRIBUTE => [ 'required_with:' . RequestAttribute::SORTING_COLUMN_ATTRIBUTE, - new OrderRule(true), + 'nullable', new Enum(OrderSortingType::class), ], ]; } @@ -41,9 +42,12 @@ public function rules(): array protected function processValidatedValues(array $values, array $files): void { $this->album = $this->albumFactory->findBaseAlbumOrFail($values[RequestAttribute::ALBUM_ID_ATTRIBUTE]); - $column = $values[RequestAttribute::SORTING_COLUMN_ATTRIBUTE]; + + $column = ColumnSortingPhotoType::tryFrom($values[RequestAttribute::SORTING_COLUMN_ATTRIBUTE]); + $order = OrderSortingType::tryFrom($values[RequestAttribute::SORTING_ORDER_ATTRIBUTE]); + $this->sortingCriterion = $column === null ? null : - new PhotoSortingCriterion($column, $values[RequestAttribute::SORTING_ORDER_ATTRIBUTE]); + new PhotoSortingCriterion($column->toColumnSortingType(), $order); } } diff --git a/app/Http/Requests/Photo/ArchivePhotosRequest.php b/app/Http/Requests/Photo/ArchivePhotosRequest.php index 6dc7db9bea7..1b8f2f725bb 100644 --- a/app/Http/Requests/Photo/ArchivePhotosRequest.php +++ b/app/Http/Requests/Photo/ArchivePhotosRequest.php @@ -2,19 +2,19 @@ namespace App\Http\Requests\Photo; -use App\Actions\Photo\Archive; use App\Contracts\Http\Requests\HasPhotos; use App\Contracts\Http\Requests\HasSizeVariant; use App\Contracts\Http\Requests\RequestAttribute; +use App\Enum\DownloadVariantType; use App\Http\Requests\BaseApiRequest; use App\Http\Requests\Traits\HasPhotosTrait; use App\Http\Requests\Traits\HasSizeVariantTrait; use App\Models\Photo; use App\Policies\PhotoPolicy; use App\Rules\RandomIDListRule; -use App\Rules\SizeVariantRule; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Support\Facades\Gate; +use Illuminate\Validation\Rules\Enum; class ArchivePhotosRequest extends BaseApiRequest implements HasPhotos, HasSizeVariant { @@ -43,7 +43,7 @@ public function rules(): array { return [ RequestAttribute::PHOTO_IDS_ATTRIBUTE => ['required', new RandomIDListRule()], - RequestAttribute::SIZE_VARIANT_ATTRIBUTE => ['required', new SizeVariantRule()], + RequestAttribute::SIZE_VARIANT_ATTRIBUTE => ['required', new Enum(DownloadVariantType::class)], ]; } @@ -52,26 +52,17 @@ public function rules(): array */ protected function processValidatedValues(array $values, array $files): void { - $this->sizeVariant = $values[RequestAttribute::SIZE_VARIANT_ATTRIBUTE]; + $this->sizeVariant = DownloadVariantType::from($values[RequestAttribute::SIZE_VARIANT_ATTRIBUTE]); $photoQuery = Photo::with(['album']); // The condition is required, because Lychee also supports to archive // the "live video" as a size variant which is not a proper size variant - if (array_key_exists($this->sizeVariant, Archive::VARIANT2VARIANT)) { + $variant = $this->sizeVariant->getSizeVariantType(); + if ($variant !== null) { // NOT LIVE PHOTO // If a proper size variant is requested, eagerly load the size // variants but only the requested type due to efficiency reasons $photoQuery = $photoQuery->with([ - 'size_variants' => function (HasMany $r) { - // The ridiculous mapping `VARIANT2VARIANT` is only - // necessary, because the size variant with the largest - // dimensions is called `FULL` by the front-end in the - // context of archiving, but `ORIGINAL` everywhere else. - // This should be made consistent. - // Although, `ORIGINAL` is used more prominently, `FULL` - // is probably the better wording. - // TODO: Fix this and make it consistent. - $r->where('type', '=', Archive::VARIANT2VARIANT[$this->sizeVariant]); - }, + 'size_variants' => fn (HasMany $r) => $r->where('type', '=', $variant), ]); } // `findOrFail` returns the union `Photo|Collection` diff --git a/app/Http/Requests/Settings/SetSortingSettingsRequest.php b/app/Http/Requests/Settings/SetSortingSettingsRequest.php index ca71e639324..88e38529bf2 100644 --- a/app/Http/Requests/Settings/SetSortingSettingsRequest.php +++ b/app/Http/Requests/Settings/SetSortingSettingsRequest.php @@ -2,13 +2,14 @@ namespace App\Http\Requests\Settings; +use App\Enum\ColumnSortingAlbumType; +use App\Enum\ColumnSortingPhotoType; +use App\Enum\OrderSortingType; use App\Http\Requests\BaseApiRequest; use App\Models\Configs; use App\Policies\SettingsPolicy; -use App\Rules\AlbumSortingRule; -use App\Rules\OrderRule; -use App\Rules\PhotoSortingRule; use Illuminate\Support\Facades\Gate; +use Illuminate\Validation\Rules\Enum; class SetSortingSettingsRequest extends BaseApiRequest { @@ -17,10 +18,10 @@ class SetSortingSettingsRequest extends BaseApiRequest public const ALBUM_SORTING_COLUMN_ATTRIBUTE = 'sorting_albums_column'; public const ALBUM_SORTING_ORDER_ATTRIBUTE = 'sorting_albums_order'; - protected string $photoSortingColumn; - protected string $photoSortingOrder; - protected string $albumSortingColumn; - protected string $albumSortingOrder; + protected ColumnSortingPhotoType $photoSortingColumn; + protected OrderSortingType $photoSortingOrder; + protected ColumnSortingAlbumType $albumSortingColumn; + protected OrderSortingType $albumSortingOrder; /** * {@inheritDoc} @@ -36,10 +37,10 @@ public function authorize(): bool public function rules(): array { return [ - self::PHOTO_SORTING_COLUMN_ATTRIBUTE => ['required', new PhotoSortingRule()], - self::PHOTO_SORTING_ORDER_ATTRIBUTE => ['required', new OrderRule(false)], - self::ALBUM_SORTING_COLUMN_ATTRIBUTE => ['required', new AlbumSortingRule()], - self::ALBUM_SORTING_ORDER_ATTRIBUTE => ['required', new OrderRule(false)], + self::PHOTO_SORTING_COLUMN_ATTRIBUTE => ['required', new Enum(ColumnSortingPhotoType::class)], + self::PHOTO_SORTING_ORDER_ATTRIBUTE => ['required', new Enum(OrderSortingType::class)], + self::ALBUM_SORTING_COLUMN_ATTRIBUTE => ['required', new Enum(ColumnSortingAlbumType::class)], + self::ALBUM_SORTING_ORDER_ATTRIBUTE => ['required', new Enum(OrderSortingType::class)], ]; } @@ -48,40 +49,40 @@ public function rules(): array */ protected function processValidatedValues(array $values, array $files): void { - $this->photoSortingColumn = $values[self::PHOTO_SORTING_COLUMN_ATTRIBUTE]; - $this->photoSortingOrder = $values[self::PHOTO_SORTING_ORDER_ATTRIBUTE]; - $this->albumSortingColumn = $values[self::ALBUM_SORTING_COLUMN_ATTRIBUTE]; - $this->albumSortingOrder = $values[self::ALBUM_SORTING_ORDER_ATTRIBUTE]; + $this->photoSortingColumn = ColumnSortingPhotoType::from($values[self::PHOTO_SORTING_COLUMN_ATTRIBUTE]); + $this->photoSortingOrder = OrderSortingType::from($values[self::PHOTO_SORTING_ORDER_ATTRIBUTE]); + $this->albumSortingColumn = ColumnSortingAlbumType::from($values[self::ALBUM_SORTING_COLUMN_ATTRIBUTE]); + $this->albumSortingOrder = OrderSortingType::from($values[self::ALBUM_SORTING_ORDER_ATTRIBUTE]); } /** - * @return string + * @return ColumnSortingPhotoType */ - public function photoSortingColumn(): string + public function photoSortingColumn(): ColumnSortingPhotoType { return $this->photoSortingColumn; } /** - * @return string + * @return OrderSortingType */ - public function photoSortingOrder(): string + public function photoSortingOrder(): OrderSortingType { return $this->photoSortingOrder; } /** - * @return string + * @return ColumnSortingAlbumType */ - public function albumSortingColumn(): string + public function albumSortingColumn(): ColumnSortingAlbumType { return $this->albumSortingColumn; } /** - * @return string + * @return OrderSortingType */ - public function albumSortingOrder(): string + public function albumSortingOrder(): OrderSortingType { return $this->albumSortingOrder; } diff --git a/app/Http/Requests/Traits/HasSizeVariantTrait.php b/app/Http/Requests/Traits/HasSizeVariantTrait.php index ef8356b3640..f7c5deb8a12 100644 --- a/app/Http/Requests/Traits/HasSizeVariantTrait.php +++ b/app/Http/Requests/Traits/HasSizeVariantTrait.php @@ -2,14 +2,16 @@ namespace App\Http\Requests\Traits; +use App\Enum\DownloadVariantType; + trait HasSizeVariantTrait { - protected string $sizeVariant; + protected DownloadVariantType $sizeVariant; /** - * @return string + * @return DownloadVariantType */ - public function sizeVariant(): string + public function sizeVariant(): DownloadVariantType { return $this->sizeVariant; } diff --git a/app/Image/SizeVariantDefaultFactory.php b/app/Image/SizeVariantDefaultFactory.php index 86c3f1f8121..eef5aae1ab8 100644 --- a/app/Image/SizeVariantDefaultFactory.php +++ b/app/Image/SizeVariantDefaultFactory.php @@ -7,6 +7,7 @@ use App\Contracts\Models\AbstractSizeVariantNamingStrategy; use App\Contracts\Models\SizeVariantFactory; use App\DTO\ImageDimension; +use App\Enum\SizeVariantType; use App\Exceptions\ConfigurationException; use App\Exceptions\ExternalComponentMissingException; use App\Exceptions\ImageProcessingException; @@ -102,12 +103,12 @@ protected function loadReferenceImage(): void public function createSizeVariants(): Collection { $allVariants = [ - SizeVariant::THUMB, - SizeVariant::THUMB2X, - SizeVariant::SMALL, - SizeVariant::SMALL2X, - SizeVariant::MEDIUM, - SizeVariant::MEDIUM2X, + SizeVariantType::THUMB, + SizeVariantType::THUMB2X, + SizeVariantType::SMALL, + SizeVariantType::SMALL2X, + SizeVariantType::MEDIUM, + SizeVariantType::MEDIUM2X, ]; $collection = new Collection(); @@ -124,16 +125,16 @@ public function createSizeVariants(): Collection /** * {@inheritDoc} */ - public function createSizeVariantCond(int $sizeVariant): ?SizeVariant + public function createSizeVariantCond(SizeVariantType $sizeVariant): ?SizeVariant { - if ($sizeVariant === SizeVariant::ORIGINAL) { + if ($sizeVariant === SizeVariantType::ORIGINAL) { throw new InvalidSizeVariantException('createSizeVariantCond() must not be used to create original size'); } if (!$this->isEnabledByConfiguration($sizeVariant)) { return null; } // Don't generate medium size variants for videos, because the current web front-end has no use for it. Let's save some storage space. - if ($this->photo->isVideo() && ($sizeVariant === SizeVariant::MEDIUM || $sizeVariant === SizeVariant::MEDIUM2X)) { + if ($this->photo->isVideo() && ($sizeVariant === SizeVariantType::MEDIUM || $sizeVariant === SizeVariantType::MEDIUM2X)) { return null; } // Don't re-create existing size variant @@ -145,8 +146,8 @@ public function createSizeVariantCond(int $sizeVariant): ?SizeVariant $realDim = $this->referenceImage->getDimensions(); $isLargeEnough = match ($sizeVariant) { - SizeVariant::THUMB => true, - SizeVariant::THUMB2X => $realDim->width >= $maxDim->width && $realDim->height >= $maxDim->height, + SizeVariantType::THUMB => true, + SizeVariantType::THUMB2X => $realDim->width >= $maxDim->width && $realDim->height >= $maxDim->height, default => ($realDim->width >= $maxDim->width && $maxDim->width !== 0) || ($realDim->height >= $maxDim->height && $maxDim->height !== 0) }; @@ -161,27 +162,25 @@ public function createSizeVariantCond(int $sizeVariant): ?SizeVariant * The method does not check whether the size variant already exist * and will overwrite an existing one of the same type. * - * @param int $sizeVariant the desired size variant; admissible - * values are: - * {@link SizeVariant::THUMB}, - * {@link SizeVariant::THUMB2X}, - * {@link SizeVariant::SMALL}, - * {@link SizeVariant::SMALL2X}, - * {@link SizeVariant::MEDIUM} and - * {@link SizeVariant::MEDIUM2X} - * @param ImageDimension $maxDim the designated dimensions of the - * size variant + * @param SizeVariantType $sizeVariant the desired size variant; admissible + * values are: + * {@link SizeVariantType::THUMB}, + * {@link SizeVariantType::THUMB2X}, + * {@link SizeVariantType::SMALL}, + * {@link SizeVariantType::SMALL2X}, + * {@link SizeVariantType::MEDIUM} and + * {@link SizeVariantType::MEDIUM2X} + * @param ImageDimension $maxDim the designated dimensions of the + * size variant * * @return SizeVariant the generated size variant * * @throws LycheeException - * - * @phpstan-param int<0,6> $sizeVariant */ - private function createSizeVariantInternal(int $sizeVariant, ImageDimension $maxDim): SizeVariant + private function createSizeVariantInternal(SizeVariantType $sizeVariant, ImageDimension $maxDim): SizeVariant { $svImage = match ($sizeVariant) { - SizeVariant::THUMB, SizeVariant::THUMB2X => $this->referenceImage->cloneAndCrop($maxDim), + SizeVariantType::THUMB, SizeVariantType::THUMB2X => $this->referenceImage->cloneAndCrop($maxDim), default => $this->referenceImage->cloneAndScale($maxDim) }; @@ -199,41 +198,41 @@ private function createSizeVariantInternal(int $sizeVariant, ImageDimension $max /** * Determines the maximum dimensions of the designated size variant. * - * @param int $sizeVariant the size variant + * @param SizeVariantType $sizeVariant the size variant * * @return ImageDimension * * @throws InvalidSizeVariantException */ - protected function getMaxDimensions(int $sizeVariant): ImageDimension + protected function getMaxDimensions(SizeVariantType $sizeVariant): ImageDimension { switch ($sizeVariant) { - case SizeVariant::MEDIUM2X: + case SizeVariantType::MEDIUM2X: $maxWidth = 2 * Configs::getValueAsInt('medium_max_width'); $maxHeight = 2 * Configs::getValueAsInt('medium_max_height'); break; - case SizeVariant::MEDIUM: + case SizeVariantType::MEDIUM: $maxWidth = Configs::getValueAsInt('medium_max_width'); $maxHeight = Configs::getValueAsInt('medium_max_height'); break; - case SizeVariant::SMALL2X: + case SizeVariantType::SMALL2X: $maxWidth = 2 * Configs::getValueAsInt('small_max_width'); $maxHeight = 2 * Configs::getValueAsInt('small_max_height'); break; - case SizeVariant::SMALL: + case SizeVariantType::SMALL: $maxWidth = Configs::getValueAsInt('small_max_width'); $maxHeight = Configs::getValueAsInt('small_max_height'); break; - case SizeVariant::THUMB2X: + case SizeVariantType::THUMB2X: $maxWidth = self::THUMBNAIL2X_DIM; $maxHeight = self::THUMBNAIL2X_DIM; break; - case SizeVariant::THUMB: + case SizeVariantType::THUMB: $maxWidth = self::THUMBNAIL_DIM; $maxHeight = self::THUMBNAIL_DIM; break; default: - throw new InvalidSizeVariantException('unknown size variant: ' . $sizeVariant); + throw new InvalidSizeVariantException('unknown size variant: ' . $sizeVariant->value); } return new ImageDimension($maxWidth, $maxHeight); @@ -255,14 +254,14 @@ protected function getMaxDimensions(int $sizeVariant): ImageDimension * still returns false, if both the allowed maximum width and height * equal zero. * - * @param int $sizeVariant the indicated size variant + * @param SizeVariantType $sizeVariant the indicated size variant * * @return bool true, if the size variant is enabled and the allowed width * or height is unequal to zero * * @throws InvalidSizeVariantException */ - protected function isEnabledByConfiguration(int $sizeVariant): bool + protected function isEnabledByConfiguration(SizeVariantType $sizeVariant): bool { $maxDim = $this->getMaxDimensions($sizeVariant); if ($maxDim->width === 0 && $maxDim->height === 0) { @@ -270,11 +269,11 @@ protected function isEnabledByConfiguration(int $sizeVariant): bool } return match ($sizeVariant) { - SizeVariant::MEDIUM2X => Configs::getValueAsBool('medium_2x'), - SizeVariant::SMALL2X => Configs::getValueAsBool('small_2x'), - SizeVariant::THUMB2X => Configs::getValueAsBool('thumb_2x'), - SizeVariant::SMALL, SizeVariant::MEDIUM, SizeVariant::THUMB => true, - default => throw new InvalidSizeVariantException('unknown size variant: ' . $sizeVariant), + SizeVariantType::MEDIUM2X => Configs::getValueAsBool('medium_2x'), + SizeVariantType::SMALL2X => Configs::getValueAsBool('small_2x'), + SizeVariantType::THUMB2X => Configs::getValueAsBool('thumb_2x'), + SizeVariantType::SMALL, SizeVariantType::MEDIUM, SizeVariantType::THUMB => true, + default => throw new InvalidSizeVariantException('unknown size variant: ' . $sizeVariant->value), }; } } diff --git a/app/Locale/ChineseSimplified.php b/app/Locale/ChineseSimplified.php index a49b38391e2..5ac9b4e5969 100644 --- a/app/Locale/ChineseSimplified.php +++ b/app/Locale/ChineseSimplified.php @@ -467,6 +467,7 @@ public function get_locale(): array 'URL_COPY_TO_CLIPBOARD' => '复制到剪贴板', 'URL_COPIED_TO_CLIPBOARD' => 'URL 已经复制到剪贴板!', 'PHOTO_DIRECT_LINKS_TO_IMAGES' => '图像文件的直链:', + 'PHOTO_ORIGINAL' => 'Original', 'PHOTO_MEDIUM' => '中等尺寸', 'PHOTO_MEDIUM_HIDPI' => '中等尺寸 HiDPI', 'PHOTO_SMALL' => '缩略图', diff --git a/app/Locale/ChineseTraditional.php b/app/Locale/ChineseTraditional.php index 31939fa0094..69dcc80bf9e 100644 --- a/app/Locale/ChineseTraditional.php +++ b/app/Locale/ChineseTraditional.php @@ -467,6 +467,7 @@ public function get_locale(): array 'URL_COPY_TO_CLIPBOARD' => '複製到剪貼板', 'URL_COPIED_TO_CLIPBOARD' => '複製到剪貼板的URL!', 'PHOTO_DIRECT_LINKS_TO_IMAGES' => '指向圖像文件的直接鏈接:', + 'PHOTO_ORIGINAL' => 'Original', 'PHOTO_MEDIUM' => '中等', 'PHOTO_MEDIUM_HIDPI' => '中等解析度', 'PHOTO_SMALL' => '低', diff --git a/app/Locale/Czech.php b/app/Locale/Czech.php index 00ba61a5678..f34f87edcf1 100644 --- a/app/Locale/Czech.php +++ b/app/Locale/Czech.php @@ -467,6 +467,7 @@ public function get_locale(): array 'URL_COPY_TO_CLIPBOARD' => 'Kopírovat do schránky', 'URL_COPIED_TO_CLIPBOARD' => 'URL zkopírována do schránky!', 'PHOTO_DIRECT_LINKS_TO_IMAGES' => 'Přímý odkaz k souborům:', + 'PHOTO_ORIGINAL' => 'Original', 'PHOTO_MEDIUM' => 'Střední', 'PHOTO_MEDIUM_HIDPI' => 'Střední HiDPI', 'PHOTO_SMALL' => 'Náhled', diff --git a/app/Locale/Dutch.php b/app/Locale/Dutch.php index 3eaae540f25..ce3d8f33281 100644 --- a/app/Locale/Dutch.php +++ b/app/Locale/Dutch.php @@ -467,6 +467,7 @@ public function get_locale(): array 'URL_COPY_TO_CLIPBOARD' => 'Copy to clipboard', 'URL_COPIED_TO_CLIPBOARD' => 'Copied URL to clipboard!', 'PHOTO_DIRECT_LINKS_TO_IMAGES' => 'Direct links to image files:', + 'PHOTO_ORIGINAL' => 'Original', 'PHOTO_MEDIUM' => 'Medium', 'PHOTO_MEDIUM_HIDPI' => 'Medium HiDPI', 'PHOTO_SMALL' => 'Thumb', diff --git a/app/Locale/English.php b/app/Locale/English.php index c2ad0259597..0c0b9e45051 100644 --- a/app/Locale/English.php +++ b/app/Locale/English.php @@ -467,6 +467,7 @@ public function get_locale(): array 'URL_COPY_TO_CLIPBOARD' => 'Copy to clipboard', 'URL_COPIED_TO_CLIPBOARD' => 'Copied URL to clipboard!', 'PHOTO_DIRECT_LINKS_TO_IMAGES' => 'Direct links to image files:', + 'PHOTO_ORIGINAL' => 'Original', 'PHOTO_MEDIUM' => 'Medium', 'PHOTO_MEDIUM_HIDPI' => 'Medium HiDPI', 'PHOTO_SMALL' => 'Thumb', diff --git a/app/Locale/French.php b/app/Locale/French.php index 41dfe8b7845..224c8a53e65 100644 --- a/app/Locale/French.php +++ b/app/Locale/French.php @@ -467,6 +467,7 @@ public function get_locale(): array 'URL_COPY_TO_CLIPBOARD' => 'Copier dans le presse-papier', 'URL_COPIED_TO_CLIPBOARD' => 'l’URL a été copiée dans le presse-papier !', 'PHOTO_DIRECT_LINKS_TO_IMAGES' => 'Liens directs pour les fichier de l’image :', + 'PHOTO_ORIGINAL' => 'Taille originale', 'PHOTO_MEDIUM' => 'Moyenne taille', 'PHOTO_MEDIUM_HIDPI' => 'Moyenne taille HiDPI', 'PHOTO_SMALL' => 'Petite taille', diff --git a/app/Locale/German.php b/app/Locale/German.php index 67c61496348..d6d6abdb3ba 100644 --- a/app/Locale/German.php +++ b/app/Locale/German.php @@ -467,6 +467,7 @@ public function get_locale(): array 'URL_COPY_TO_CLIPBOARD' => 'In die Zwischenablage kopiert', 'URL_COPIED_TO_CLIPBOARD' => 'URL in die Zwischenablage kopiert!', 'PHOTO_DIRECT_LINKS_TO_IMAGES' => 'Direkte Links zu den Bilddateien:', + 'PHOTO_ORIGINAL' => 'Original', 'PHOTO_MEDIUM' => 'Mittlere Größe', 'PHOTO_MEDIUM_HIDPI' => 'Mittlere Größe HiDPI', 'PHOTO_SMALL' => 'Miniaturansicht', diff --git a/app/Locale/Greek.php b/app/Locale/Greek.php index 86e84491040..5ba0fa67147 100644 --- a/app/Locale/Greek.php +++ b/app/Locale/Greek.php @@ -467,6 +467,7 @@ public function get_locale(): array 'URL_COPY_TO_CLIPBOARD' => 'Αντιγραφή στο πρόχειρο', 'URL_COPIED_TO_CLIPBOARD' => 'Η διεύθυνση URL αντιγράφηκε στο πρόχειρο!', 'PHOTO_DIRECT_LINKS_TO_IMAGES' => 'Απευθείας σύνδεσμοι στα αρχεία εικόνων:', + 'PHOTO_ORIGINAL' => 'Original', 'PHOTO_MEDIUM' => 'Μέτρια', 'PHOTO_MEDIUM_HIDPI' => 'Μέτρια HiDPI', 'PHOTO_SMALL' => 'Μικρογραφία', diff --git a/app/Locale/Italian.php b/app/Locale/Italian.php index a991a7b5d2d..048ff671fb6 100644 --- a/app/Locale/Italian.php +++ b/app/Locale/Italian.php @@ -467,6 +467,7 @@ public function get_locale(): array 'URL_COPY_TO_CLIPBOARD' => 'Copy to clipboard', 'URL_COPIED_TO_CLIPBOARD' => 'Copied URL to clipboard!', 'PHOTO_DIRECT_LINKS_TO_IMAGES' => 'Direct links to image files:', + 'PHOTO_ORIGINAL' => 'Original', 'PHOTO_MEDIUM' => 'Medium', 'PHOTO_MEDIUM_HIDPI' => 'Medium HiDPI', 'PHOTO_SMALL' => 'Thumb', diff --git a/app/Locale/NorwegianBokmal.php b/app/Locale/NorwegianBokmal.php index a0d4824831e..ded5e459e49 100644 --- a/app/Locale/NorwegianBokmal.php +++ b/app/Locale/NorwegianBokmal.php @@ -467,6 +467,7 @@ public function get_locale(): array 'URL_COPY_TO_CLIPBOARD' => 'Kopier til utklippstavlen', 'URL_COPIED_TO_CLIPBOARD' => 'Kopierte lenke til utklippstavlen!', 'PHOTO_DIRECT_LINKS_TO_IMAGES' => 'Direkte lenke til bildefiler:', + 'PHOTO_ORIGINAL' => 'Original', 'PHOTO_MEDIUM' => 'Medium', 'PHOTO_MEDIUM_HIDPI' => 'Medium HiDPI', 'PHOTO_SMALL' => 'Miniatyr', diff --git a/app/Locale/Polish.php b/app/Locale/Polish.php index 9afa2c69c59..f95ff27418f 100644 --- a/app/Locale/Polish.php +++ b/app/Locale/Polish.php @@ -467,6 +467,7 @@ public function get_locale(): array 'URL_COPY_TO_CLIPBOARD' => 'Kopiuj do schowka', 'URL_COPIED_TO_CLIPBOARD' => 'Skopiowano URL do schowka!', 'PHOTO_DIRECT_LINKS_TO_IMAGES' => 'Direct links to image files:', + 'PHOTO_ORIGINAL' => 'Original', 'PHOTO_MEDIUM' => ' Średnie', 'PHOTO_MEDIUM_HIDPI' => 'Medium HiDPI', 'PHOTO_SMALL' => 'Miniaturka', diff --git a/app/Locale/Portuguese.php b/app/Locale/Portuguese.php index e88a0b28c3d..a9bb620681b 100644 --- a/app/Locale/Portuguese.php +++ b/app/Locale/Portuguese.php @@ -467,6 +467,7 @@ public function get_locale(): array 'URL_COPY_TO_CLIPBOARD' => 'Copiar para o clipboard', 'URL_COPIED_TO_CLIPBOARD' => 'URL copiado para o clipboard!', 'PHOTO_DIRECT_LINKS_TO_IMAGES' => 'Links diretos para os ficheiros de imagem:', + 'PHOTO_ORIGINAL' => 'Original', 'PHOTO_MEDIUM' => 'Média', 'PHOTO_MEDIUM_HIDPI' => 'Média HiDPI', 'PHOTO_SMALL' => 'Pequena', diff --git a/app/Locale/Russian.php b/app/Locale/Russian.php index 8834ab990ec..2f6d4bf0c5f 100644 --- a/app/Locale/Russian.php +++ b/app/Locale/Russian.php @@ -467,6 +467,7 @@ public function get_locale(): array 'URL_COPY_TO_CLIPBOARD' => 'Copy to clipboard', 'URL_COPIED_TO_CLIPBOARD' => 'Copied URL to clipboard!', 'PHOTO_DIRECT_LINKS_TO_IMAGES' => 'Direct links to image files:', + 'PHOTO_ORIGINAL' => 'Original', 'PHOTO_MEDIUM' => 'Medium', 'PHOTO_MEDIUM_HIDPI' => 'Medium HiDPI', 'PHOTO_SMALL' => 'Thumb', diff --git a/app/Locale/Slovak.php b/app/Locale/Slovak.php index 1d15f4ebc91..f6f7c43392f 100644 --- a/app/Locale/Slovak.php +++ b/app/Locale/Slovak.php @@ -467,6 +467,7 @@ public function get_locale(): array 'URL_COPY_TO_CLIPBOARD' => 'Skopírovať do schránky', 'URL_COPIED_TO_CLIPBOARD' => 'URL skopírované do schránky!', 'PHOTO_DIRECT_LINKS_TO_IMAGES' => 'Priame linky k súborom obrázkov:', + 'PHOTO_ORIGINAL' => 'Original', 'PHOTO_MEDIUM' => 'Medium', 'PHOTO_MEDIUM_HIDPI' => 'Medium HiDPI', 'PHOTO_SMALL' => 'Náhľad', diff --git a/app/Locale/Spanish.php b/app/Locale/Spanish.php index 1e806fe4275..6061231f05d 100644 --- a/app/Locale/Spanish.php +++ b/app/Locale/Spanish.php @@ -467,6 +467,7 @@ public function get_locale(): array 'URL_COPY_TO_CLIPBOARD' => 'Copiar al portapapeles', 'URL_COPIED_TO_CLIPBOARD' => '¡URL copiada al portapapeles!', 'PHOTO_DIRECT_LINKS_TO_IMAGES' => 'Enlaces directos a archivos de imagen:', + 'PHOTO_ORIGINAL' => 'Original', 'PHOTO_MEDIUM' => 'Mediana', 'PHOTO_MEDIUM_HIDPI' => 'Mediana HiDPI', 'PHOTO_SMALL' => 'Miniatura', diff --git a/app/Locale/Swedish.php b/app/Locale/Swedish.php index 55788d443ae..a5594528d7e 100644 --- a/app/Locale/Swedish.php +++ b/app/Locale/Swedish.php @@ -467,6 +467,7 @@ public function get_locale(): array 'URL_COPY_TO_CLIPBOARD' => 'Copy to clipboard', 'URL_COPIED_TO_CLIPBOARD' => 'Copied URL to clipboard!', 'PHOTO_DIRECT_LINKS_TO_IMAGES' => 'Direct links to image files:', + 'PHOTO_ORIGINAL' => 'Original', 'PHOTO_MEDIUM' => 'Medium', 'PHOTO_MEDIUM_HIDPI' => 'Medium HiDPI', 'PHOTO_SMALL' => 'Thumb', diff --git a/app/Locale/Vietnamese.php b/app/Locale/Vietnamese.php index 8d9ff4d8545..6da93505c74 100644 --- a/app/Locale/Vietnamese.php +++ b/app/Locale/Vietnamese.php @@ -467,6 +467,7 @@ public function get_locale(): array 'URL_COPY_TO_CLIPBOARD' => 'Sao chép vào bộ nhớ tạm thời', 'URL_COPIED_TO_CLIPBOARD' => 'Đã sao chép vào bộ nhớ tạm thời!', 'PHOTO_DIRECT_LINKS_TO_IMAGES' => 'Đường link trực tiếp đến tập tin hình ảnh:', + 'PHOTO_ORIGINAL' => 'Original', 'PHOTO_MEDIUM' => 'Vừa', 'PHOTO_MEDIUM_HIDPI' => 'Độ phân giải cho hình vừa HiDPI', 'PHOTO_SMALL' => 'Nhỏ', diff --git a/app/ModelFunctions/LogFunctions.php b/app/ModelFunctions/LogFunctions.php index 792478a5f87..e056f0b9fc0 100644 --- a/app/ModelFunctions/LogFunctions.php +++ b/app/ModelFunctions/LogFunctions.php @@ -2,6 +2,7 @@ namespace App\ModelFunctions; +use App\Enum\SeverityType; use App\Models\Logs; use Psr\Log\AbstractLogger; @@ -51,8 +52,12 @@ public function log($level, \Stringable|string $message, array $context = []): v $text = 'argument is not stringable!'; } + // Just make sure that the level is valid. + // if not report as critical + $log_level = SeverityType::tryFrom($level) ?? SeverityType::CRITICAL; + $log = Logs::create([ - 'type' => $level, + 'type' => $log_level, 'function' => $fun, 'line' => $line, 'text' => $text, diff --git a/app/Models/BaseAlbumImpl.php b/app/Models/BaseAlbumImpl.php index 81544ab3c22..3e9e4d5e8f6 100644 --- a/app/Models/BaseAlbumImpl.php +++ b/app/Models/BaseAlbumImpl.php @@ -6,6 +6,8 @@ use App\Contracts\Models\HasRandomID; use App\DTO\AlbumProtectionPolicy; use App\DTO\PhotoSortingCriterion; +use App\Enum\ColumnSortingType; +use App\Enum\OrderSortingType; use App\Models\Extensions\HasAttributesPatch; use App\Models\Extensions\HasBidirectionalRelationships; use App\Models\Extensions\HasRandomIDAndLegacyTimeBasedID; @@ -267,13 +269,15 @@ protected function getSortingAttribute(): ?PhotoSortingCriterion return ($sortingColumn === null || $sortingOrder === null) ? null : - new PhotoSortingCriterion($sortingColumn, $sortingOrder); + new PhotoSortingCriterion( + ColumnSortingType::from($sortingColumn), + OrderSortingType::from($sortingOrder)); } protected function setSortingAttribute(?PhotoSortingCriterion $sorting): void { - $this->attributes['sorting_col'] = $sorting?->column; - $this->attributes['sorting_order'] = $sorting?->order; + $this->attributes['sorting_col'] = $sorting?->column->value; + $this->attributes['sorting_order'] = $sorting?->order->value; } protected function setPolicyAttribute(AlbumProtectionPolicy $protectionPolicy): void diff --git a/app/Models/Configs.php b/app/Models/Configs.php index b4d0a8d0b4a..c4472a4c32e 100644 --- a/app/Models/Configs.php +++ b/app/Models/Configs.php @@ -7,11 +7,13 @@ use App\Exceptions\Internal\LycheeAssertionError; use App\Exceptions\Internal\QueryBuilderException; use App\Exceptions\ModelDBException; +use App\Exceptions\UnexpectedException; use App\Facades\Helpers; use App\Models\Extensions\ConfigsHas; use App\Models\Extensions\FixedQueryBuilder; use App\Models\Extensions\ThrowsConsistentExceptions; use App\Models\Extensions\UseFixedQueryBuilder; +use BackedEnum; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\ModelNotFoundException; @@ -209,6 +211,23 @@ public static function getValueAsBool(string $key): bool return self::getValue($key) === '1'; } + /** + * @template T of BackedEnum + * + * @param string $key + * @param class-string $type + * + * @return T|null + */ + public static function getValueAsEnum(string $key, string $type): \BackedEnum|null + { + if (!function_exists('enum_exists') || !enum_exists($type) || !method_exists($type, 'tryFrom')) { + throw new UnexpectedException(); + } + + return $type::tryFrom(self::getValue($key)); + } + /** * Update Lychee configuration * Note that we must invalidate the cache now. @@ -221,7 +240,7 @@ public static function getValueAsBool(string $key): bool * @throws InvalidConfigOption * @throws QueryBuilderException */ - public static function set(string $key, string|int|bool $value): void + public static function set(string $key, string|int|bool|\BackedEnum $value): void { try { /** @var Configs $config */ @@ -229,6 +248,11 @@ public static function set(string $key, string|int|bool $value): void ->where('key', '=', $key) ->firstOrFail(); + // For BackEnm we take the value. In theory this is no longer necessary because we enforce at the column type. + if ($value instanceof \BackedEnum) { + $value = $value->value; + } + $strValue = match (gettype($value)) { 'boolean' => $value === true ? '1' : '0', 'integer', 'string' => strval($value), diff --git a/app/Models/Extensions/SizeVariants.php b/app/Models/Extensions/SizeVariants.php index 4786df2a7f2..6a096c1e6b8 100644 --- a/app/Models/Extensions/SizeVariants.php +++ b/app/Models/Extensions/SizeVariants.php @@ -5,6 +5,7 @@ use App\Actions\SizeVariant\Delete; use App\DTO\AbstractDTO; use App\DTO\ImageDimension; +use App\Enum\SizeVariantType; use App\Exceptions\Internal\IllegalOrderOfOperationException; use App\Exceptions\Internal\InvalidSizeVariantException; use App\Exceptions\Internal\LycheeAssertionError; @@ -69,25 +70,25 @@ public function add(SizeVariant $sizeVariant): void } $sizeVariant->setRelation('photo', $this->photo); switch ($sizeVariant->type) { - case SizeVariant::ORIGINAL: + case SizeVariantType::ORIGINAL: $ref = &$this->original; break; - case SizeVariant::MEDIUM2X: + case SizeVariantType::MEDIUM2X: $ref = &$this->medium2x; break; - case SizeVariant::MEDIUM: + case SizeVariantType::MEDIUM: $ref = &$this->medium; break; - case SizeVariant::SMALL2X: + case SizeVariantType::SMALL2X: $ref = &$this->small2x; break; - case SizeVariant::SMALL: + case SizeVariantType::SMALL: $ref = &$this->small; break; - case SizeVariant::THUMB2X: + case SizeVariantType::THUMB2X: $ref = &$this->thumb2x; break; - case SizeVariant::THUMB: + case SizeVariantType::THUMB: $ref = &$this->thumb; break; default: @@ -108,44 +109,35 @@ public function add(SizeVariant $sizeVariant): void public function toArray(): array { return [ - 'original' => $this->original?->toArray(), - 'medium2x' => $this->medium2x?->toArray(), - 'medium' => $this->medium?->toArray(), - 'small2x' => $this->small2x?->toArray(), - 'small' => $this->small?->toArray(), - 'thumb2x' => $this->thumb2x?->toArray(), - 'thumb' => $this->thumb?->toArray(), + SizeVariantType::ORIGINAL->name() => $this->original?->toArray(), + SizeVariantType::MEDIUM2X->name() => $this->medium2x?->toArray(), + SizeVariantType::MEDIUM->name() => $this->medium?->toArray(), + SizeVariantType::SMALL2X->name() => $this->small2x?->toArray(), + SizeVariantType::SMALL->name() => $this->small?->toArray(), + SizeVariantType::THUMB2X->name() => $this->thumb2x?->toArray(), + SizeVariantType::THUMB->name() => $this->thumb?->toArray(), ]; } /** * Returns the requested size variant of the photo. * - * @param int $sizeVariantType the type of the size variant; allowed - * values are: - * {@link SizeVariant::ORIGINAL}, - * {@link SizeVariant::MEDIUM2X}, - * {@link SizeVariant::MEDIUM2}, - * {@link SizeVariant::SMALL2X}, - * {@link SizeVariant::SMALL}, - * {@link SizeVariant::THUMB2X}, and - * {@link SizeVariant::THUMB} + * @param SizeVariantType $sizeVariantType the type of the size variant * * @return SizeVariant|null The size variant * * @throws InvalidSizeVariantException */ - public function getSizeVariant(int $sizeVariantType): ?SizeVariant + public function getSizeVariant(SizeVariantType $sizeVariantType): ?SizeVariant { return match ($sizeVariantType) { - SizeVariant::ORIGINAL => $this->original, - SizeVariant::MEDIUM2X => $this->medium2x, - SizeVariant::MEDIUM => $this->medium, - SizeVariant::SMALL2X => $this->small2x, - SizeVariant::SMALL => $this->small, - SizeVariant::THUMB2X => $this->thumb2x, - SizeVariant::THUMB => $this->thumb, - default => throw new InvalidSizeVariantException('size variant ' . $sizeVariantType . 'invalid'), + SizeVariantType::ORIGINAL => $this->original, + SizeVariantType::MEDIUM2X => $this->medium2x, + SizeVariantType::MEDIUM => $this->medium, + SizeVariantType::SMALL2X => $this->small2x, + SizeVariantType::SMALL => $this->small, + SizeVariantType::THUMB2X => $this->thumb2x, + SizeVariantType::THUMB => $this->thumb }; } @@ -173,28 +165,18 @@ public function getThumb(): ?SizeVariant * Creates a new instance of {@link \App\Models\SizeVariant} for the * associated photo and persists it to DB. * - * @param int $sizeVariantType the type of the desired size variant; - * allowed values are: - * {@link SizeVariant::ORIGINAL}, - * {@link SizeVariant::MEDIUM2X}, - * {@link SizeVariant::MEDIUM2}, - * {@link SizeVariant::SMALL2X}, - * {@link SizeVariant::SMALL}, - * {@link SizeVariant::THUMB2X}, and - * {@link SizeVariant::THUMB} - * @param string $shortPath the short path of the media file this - * size variant shall point to - * @param ImageDimension $dim the width of the size variant - * @param int $filesize the filesize of the size variant + * @param SizeVariantType $sizeVariantType the type of the desired size variant; + * @param string $shortPath the short path of the media file this + * size variant shall point to + * @param ImageDimension $dim the width of the size variant + * @param int $filesize the filesize of the size variant * * @return SizeVariant The newly created and persisted size variant * * @throws IllegalOrderOfOperationException * @throws ModelDBException - * - * @phpstan-param int<0,6> $sizeVariantType */ - public function create(int $sizeVariantType, string $shortPath, ImageDimension $dim, int $filesize): SizeVariant + public function create(SizeVariantType $sizeVariantType, string $shortPath, ImageDimension $dim, int $filesize): SizeVariant { if (!$this->photo->exists) { throw new IllegalOrderOfOperationException('Cannot create a size variant for a photo whose id is not yet persisted to DB'); diff --git a/app/Models/Extensions/SortingDecorator.php b/app/Models/Extensions/SortingDecorator.php index 378e72bdc93..5f61e767e00 100644 --- a/app/Models/Extensions/SortingDecorator.php +++ b/app/Models/Extensions/SortingDecorator.php @@ -2,8 +2,8 @@ namespace App\Models\Extensions; -use App\DTO\AlbumSortingCriterion; -use App\DTO\BaseSortingCriterion; +use App\Enum\ColumnSortingType; +use App\Enum\OrderSortingType; use App\Exceptions\Internal\InvalidOrderDirectionException; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Collection; @@ -11,8 +11,8 @@ class SortingDecorator { public const POSTPONE_COLUMNS = [ - BaseSortingCriterion::COLUMN_TITLE, - BaseSortingCriterion::COLUMN_DESCRIPTION, + ColumnSortingType::TITLE, + ColumnSortingType::DESCRIPTION, ]; protected Builder $baseBuilder; @@ -48,7 +48,7 @@ public function __construct(Builder $baseBuilder) * The mixed case with some pre-sorting on the SQL layer and final sorting * on the software layer is more complicated. * - * @var array{column: string, direction:string}[] + * @var array */ protected array $orderBy = []; @@ -73,32 +73,39 @@ public function __construct(Builder $baseBuilder) protected int $pivotIdx = -1; /** - * @param string $column the column acc. to which the result shall be - * sorted; must either be - * {@link SortingCriterion::COLUMN_CREATED_AT}, - * {@link SortingCriterion::COLUMN_TITLE}, - * {@link SortingCriterion::COLUMN_DESCRIPTION}, - * {@link SortingCriterion::COLUMN_IS_PUBLIC}, - * {@link PhotoSortingCriterion::COLUMN_TAKEN_AT}, - * {@link PhotoSortingCriterion::COLUMN_IS_STARRED}, - * {@link PhotoSortingCriterion::COLUMN_TYPE}, - * {@link AlbumSortingCriterion::COLUMN_MIN_TAKEN_AT}, or - * {@link AlbumSortingCriterion::COLUMN_MAX_TAKEN_AT}. - * @param string $direction the order direction must be either - * {@link SortingCriterion::ASC} or - * {@link SortingCriterion::DESC} + * @param ColumnSortingType $column the column acc. to which the result shall be sorted + * @param OrderSortingType $direction the order direction * * @throws InvalidOrderDirectionException */ - public function orderBy(string $column, string $direction = BaseSortingCriterion::ASC): SortingDecorator + public function orderBy(ColumnSortingType $column, OrderSortingType $direction): SortingDecorator { - $direction = strtolower($direction); - if (!in_array($direction, ['asc', 'desc'], true)) { - throw new InvalidOrderDirectionException(); + $this->orderBy[] = [ + 'column' => $column->value, + 'direction' => $direction->value, + ]; + + if (in_array($column, self::POSTPONE_COLUMNS, true)) { + $this->pivotIdx = sizeof($this->orderBy) - 1; } + + return $this; + } + + /** + * Some sorting are done at the photo level, however because we enforce more strictly the type on column + * we are now prefixing the column by `photos.`. + * + * @param ColumnSortingType $column the column acc. to which the result shall be sorted + * @param OrderSortingType $direction the order direction + * + * @throws InvalidOrderDirectionException + */ + public function orderPhotosBy(ColumnSortingType $column, OrderSortingType $direction): SortingDecorator + { $this->orderBy[] = [ - 'column' => $column, - 'direction' => $direction, + 'column' => 'photos.' . $column->value, + 'direction' => $direction->value, ]; if (in_array($column, self::POSTPONE_COLUMNS, true)) { @@ -143,11 +150,16 @@ public function get(array $columns = ['*']): Collection // Sort with PHP for the remaining criteria in reverse order. for ($i = $this->pivotIdx; $i >= 0; $i--) { $column = $this->orderBy[$i]['column']; - $options = in_array($column, self::POSTPONE_COLUMNS, true) ? SORT_NATURAL | SORT_FLAG_CASE : SORT_REGULAR; + + // This conversion is necessary + $columnSortingName = str_replace('photos.', '', $column); + $columnSortingType = ColumnSortingType::tryFrom($columnSortingName) ?? ColumnSortingType::CREATED_AT; + + $options = in_array($columnSortingType, self::POSTPONE_COLUMNS, true) ? SORT_NATURAL | SORT_FLAG_CASE : SORT_REGULAR; $result = $result->sortBy( - $column, + $columnSortingName, $options, - $this->orderBy[$i]['direction'] === 'desc' + $this->orderBy[$i]['direction'] === OrderSortingType::DESC->value )->values(); } diff --git a/app/Models/Extensions/Thumb.php b/app/Models/Extensions/Thumb.php index 2c42e527c27..130fe55cdc2 100644 --- a/app/Models/Extensions/Thumb.php +++ b/app/Models/Extensions/Thumb.php @@ -3,11 +3,12 @@ namespace App\Models\Extensions; use App\DTO\AbstractDTO; -use App\DTO\BaseSortingCriterion; -use App\DTO\PhotoSortingCriterion; +use App\DTO\SortingCriterion; +use App\Enum\ColumnSortingPhotoType; +use App\Enum\OrderSortingType; +use App\Enum\SizeVariantType; use App\Exceptions\InvalidPropertyException; use App\Models\Photo; -use App\Models\SizeVariant; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\Relation; @@ -37,7 +38,7 @@ protected function __construct(string $id, string $type, string $thumbUrl, ?stri */ public static function sizeVariantsFilter(HasMany $relation): HasMany { - return $relation->whereIn('type', [SizeVariant::THUMB, SizeVariant::THUMB2X]); + return $relation->whereIn('type', [SizeVariantType::THUMB, SizeVariantType::THUMB2X]); } /** @@ -46,22 +47,22 @@ public static function sizeVariantsFilter(HasMany $relation): HasMany * Note, this method assumes that the relation is already restricted * such that it only returns photos which the current user may see. * - * @param Relation|Builder $photoQueryable the relation to or query for {@link Photo} which is used to pick a thumb - * @param BaseSortingCriterion $sorting the sorting criterion + * @param Relation|Builder $photoQueryable the relation to or query for {@link Photo} which is used to pick a thumb + * @param SortingCriterion $sorting the sorting criterion * * @return Thumb|null the created thumbnail; null if the relation is empty * * @throws InvalidPropertyException thrown, if $sortingOrder neither * equals `desc` nor `asc` */ - public static function createFromQueryable(Relation|Builder $photoQueryable, BaseSortingCriterion $sorting): ?Thumb + public static function createFromQueryable(Relation|Builder $photoQueryable, SortingCriterion $sorting): ?Thumb { try { /** @var Photo|null $cover */ $cover = $photoQueryable ->withOnly(['size_variants' => (fn (HasMany $r) => self::sizeVariantsFilter($r))]) - ->orderBy('photos.' . PhotoSortingCriterion::COLUMN_IS_STARRED, BaseSortingCriterion::DESC) - ->orderBy('photos.' . $sorting->column, $sorting->order) + ->orderBy('photos.' . ColumnSortingPhotoType::IS_STARRED->value, OrderSortingType::DESC->value) + ->orderBy('photos.' . $sorting->column->value, $sorting->order->value) ->select(['photos.id', 'photos.type']) ->first(); diff --git a/app/Models/Logs.php b/app/Models/Logs.php index 50b91c47b2a..86bf7d8d505 100644 --- a/app/Models/Logs.php +++ b/app/Models/Logs.php @@ -2,6 +2,7 @@ namespace App\Models; +use App\Enum\SeverityType; use App\Models\Extensions\ThrowsConsistentExceptions; use App\Models\Extensions\UseFixedQueryBuilder; use App\Models\Extensions\UTCBasedTimes; @@ -11,13 +12,13 @@ /** * App\Logs. * - * @property int $id - * @property string $type - * @property string $function - * @property int $line - * @property string $text - * @property Carbon|null $created_at - * @property Carbon|null $updated_at + * @property int $id + * @property SeverityType $type + * @property string $function + * @property int $line + * @property string $text + * @property Carbon|null $created_at + * @property Carbon|null $updated_at */ class Logs extends Model { @@ -26,26 +27,6 @@ class Logs extends Model /** @phpstan-use UseFixedQueryBuilder */ use UseFixedQueryBuilder; - public const SEVERITY_EMERGENCY = 0; - public const SEVERITY_ALERT = 1; - public const SEVERITY_CRITICAL = 2; - public const SEVERITY_ERROR = 3; - public const SEVERITY_WARNING = 4; - public const SEVERITY_NOTICE = 5; - public const SEVERITY_INFO = 6; - public const SEVERITY_DEBUG = 7; - - public const SEVERITY_2_STRING = [ - self::SEVERITY_EMERGENCY => 'emergency', - self::SEVERITY_ALERT => 'alert', - self::SEVERITY_CRITICAL => 'critical', - self::SEVERITY_ERROR => 'error', - self::SEVERITY_WARNING => 'warning', - self::SEVERITY_NOTICE => 'notice', - self::SEVERITY_INFO => 'info', - self::SEVERITY_DEBUG => 'debug', - ]; - public const MAX_METHOD_LENGTH = 100; /** @@ -58,6 +39,13 @@ class Logs extends Model 'text', ]; + /** + * @var array + */ + protected $casts = [ + 'type' => SeverityType::class, + ]; + /** * Logs a notification. * @@ -69,7 +57,7 @@ class Logs extends Model */ public static function notice(string $method, int $line, string $msg): void { - self::log(self::SEVERITY_NOTICE, $method, $line, $msg); + self::log(SeverityType::NOTICE, $method, $line, $msg); } /** @@ -83,7 +71,7 @@ public static function notice(string $method, int $line, string $msg): void */ public static function warning(string $method, int $line, string $msg): void { - self::log(self::SEVERITY_WARNING, $method, $line, $msg); + self::log(SeverityType::WARNING, $method, $line, $msg); } /** @@ -97,37 +85,35 @@ public static function warning(string $method, int $line, string $msg): void */ public static function error(string $method, int $line, string $msg): void { - self::log(self::SEVERITY_ERROR, $method, $line, $msg); + self::log(SeverityType::ERROR, $method, $line, $msg); } /** * Writes a log entry. * - * @param int $severity the severity of the incident, must be one out - * of {@link Logs::SEVERITY_EMERGENCY}, - * {@link Logs::SEVERITY_ALERT}, - * {@link Logs::SEVERITY_CRITICAL}, - * {@link Logs::SEVERITY_ERROR}, - * {@link Logs::SEVERITY_WARNING}, - * {@link Logs::SEVERITY_NOTICE}, - * {@link Logs::SEVERITY_INFO} or - * {@link Logs::SEVERITY_DEBUG} - * @param string $method the name of the method which triggers the log - * (use the magic constant `__METHOD__`, neither - * `__FUNCTION__` nor `__FILE__`) - * @param int $line the line which triggers the log - * @param string $msg the message to log - * - * @phpstan-param int<0,7> $severity + * @param SeverityType $severity the severity of the incident, must be one out + * of {@link SeverityType::EMERGENCY}, + * {@link SeverityType::ALERT}, + * {@link SeverityType::CRITICAL}, + * {@link SeverityType::ERROR}, + * {@link SeverityType::WARNING}, + * {@link SeverityType::NOTICE}, + * {@link SeverityType::INFO} or + * {@link SeverityType::DEBUG} + * @param string $method the name of the method which triggers the log + * (use the magic constant `__METHOD__`, neither + * `__FUNCTION__` nor `__FILE__`) + * @param int $line the line which triggers the log + * @param string $msg the message to log */ - public static function log(int $severity, string $method, int $line, string $msg): void + public static function log(SeverityType $severity, string $method, int $line, string $msg): void { try { if (strlen($method) > self::MAX_METHOD_LENGTH) { $method = '...' . substr($method, 3, self::MAX_METHOD_LENGTH - 3); } $log = new self([ - 'type' => self::SEVERITY_2_STRING[$severity], + 'type' => $severity, 'function' => $method, 'line' => $line, 'text' => $msg, diff --git a/app/Models/SizeVariant.php b/app/Models/SizeVariant.php index 2cda4d4bf93..ab8797b6a8d 100644 --- a/app/Models/SizeVariant.php +++ b/app/Models/SizeVariant.php @@ -5,8 +5,8 @@ use App\Actions\SizeVariant\Delete; use App\Casts\MustNotSetCast; use App\Contracts\Models\AbstractSizeVariantNamingStrategy; +use App\Enum\SizeVariantType; use App\Exceptions\ConfigurationException; -use App\Exceptions\Internal\InvalidSizeVariantException; use App\Exceptions\MediaFileOperationException; use App\Exceptions\ModelDBException; use App\Image\Files\FlysystemFile; @@ -43,7 +43,7 @@ * @property int $id * @property string $photo_id * @property Photo $photo - * @property int $type + * @property SizeVariantType $type * @property string $short_path * @property string $url * @property string $full_path @@ -51,8 +51,6 @@ * @property int $height * @property int $filesize * @property Collection $sym_links - * - * @phpstan-property int<0,6> $type */ class SizeVariant extends Model { @@ -63,14 +61,6 @@ class SizeVariant extends Model /** @phpstan-use UseFixedQueryBuilder */ use UseFixedQueryBuilder; - public const ORIGINAL = 0; - public const MEDIUM2X = 1; - public const MEDIUM = 2; - public const SMALL2X = 3; - public const SMALL = 4; - public const THUMB2X = 5; - public const THUMB = 6; - /** * This model has no own timestamps as it is inseparably bound to its * parent {@link \App\Models\Photo} and uses the same timestamps. @@ -84,7 +74,7 @@ class SizeVariant extends Model */ protected $casts = [ 'id' => 'integer', - 'type' => 'integer', + 'type' => SizeVariantType::class, 'full_path' => MustNotSetCast::class . ':short_path', 'url' => MustNotSetCast::class . ':short_path', 'width' => 'integer', @@ -209,36 +199,6 @@ public function getFile(): FlysystemFile return new FlysystemFile(AbstractSizeVariantNamingStrategy::getImageDisk(), $this->short_path); } - /** - * Mutator of the attribute {@link SizeVariant::$type}. - * - * @param int $sizeVariantType the type of size variant; allowed values are - * {@link SizeVariant::ORIGINAL}, - * {@link SizeVariant::MEDIUM2X}, - * {@link SizeVariant::MEDIUM}, - * {@link SizeVariant::SMALL2X}, - * {@link SizeVariant::SMALL}, - * {@link SizeVariant::THUMB2X}, and - * {@link SizeVariant::THUMB} - * - * @throws InvalidSizeVariantException thrown if `$sizeVariantType` is - * out-of-bounds - * - * @phpstan-param int<0,6> $sizeVariantType - */ - public function setTypeAttribute(int $sizeVariantType): void - { - // This method is also invoked if the model is hydrated from the DB. - // Hence, we cannot ensure by static code analyzing that the - // restriction `int<0,6>` always holds. - // We must check at runtime, too. - // @phpstan-ignore-next-line - if (self::ORIGINAL > $sizeVariantType || $sizeVariantType > self::THUMB) { - throw new InvalidSizeVariantException('passed size variant ' . $sizeVariantType . ' out-of-range'); - } - $this->attributes['type'] = $sizeVariantType; - } - /** * {@inheritDoc} * diff --git a/app/Relations/BaseHasManyPhotos.php b/app/Relations/BaseHasManyPhotos.php index c744f18182a..342696a2b57 100644 --- a/app/Relations/BaseHasManyPhotos.php +++ b/app/Relations/BaseHasManyPhotos.php @@ -2,7 +2,7 @@ namespace App\Relations; -use App\DTO\BaseSortingCriterion; +use App\DTO\SortingCriterion; use App\Exceptions\Internal\InvalidOrderDirectionException; use App\Models\Extensions\BaseAlbum; use App\Models\Extensions\FixedQueryBuilder; @@ -125,11 +125,11 @@ public function getResults(): Collection { /** @var BaseAlbum */ $parent = $this->parent; - /** @var BaseSortingCriterion $sorting */ + /** @var SortingCriterion $sorting */ $sorting = $parent->getEffectiveSorting(); return (new SortingDecorator($this->getRelationQuery())) - ->orderBy('photos.' . $sorting->column, $sorting->order) + ->orderPhotosBy($sorting->column, $sorting->order) ->get(); } } diff --git a/app/Relations/HasAlbumThumb.php b/app/Relations/HasAlbumThumb.php index 040abb18c9f..fbaf7ec5879 100644 --- a/app/Relations/HasAlbumThumb.php +++ b/app/Relations/HasAlbumThumb.php @@ -3,6 +3,8 @@ namespace App\Relations; use App\DTO\PhotoSortingCriterion; +use App\Enum\ColumnSortingPhotoType; +use App\Enum\OrderSortingType; use App\Models\Album; use App\Models\Extensions\FixedQueryBuilder; use App\Models\Extensions\Thumb; @@ -177,8 +179,8 @@ public function addEagerConstraints(array $models): void ->join('albums', 'albums.id', '=', 'photos.album_id') ->whereColumn('albums._lft', '>=', 'covered_albums._lft') ->whereColumn('albums._rgt', '<=', 'covered_albums._rgt') - ->orderBy('photos.is_starred', 'desc') - ->orderBy('photos.' . $this->sorting->column, $this->sorting->order) + ->orderBy('photos.' . ColumnSortingPhotoType::IS_STARRED->value, OrderSortingType::DESC->value) + ->orderBy('photos.' . $this->sorting->column->value, $this->sorting->order->value) ->limit(1); if (Auth::user()?->may_administrate !== true) { $bestPhotoIDSelect->where(function (Builder $query2) { diff --git a/app/Relations/HasManyChildAlbums.php b/app/Relations/HasManyChildAlbums.php index 36d3e9e47c6..3d8929c7bd4 100644 --- a/app/Relations/HasManyChildAlbums.php +++ b/app/Relations/HasManyChildAlbums.php @@ -4,7 +4,7 @@ use App\Contracts\Exceptions\InternalLycheeException; use App\DTO\AlbumSortingCriterion; -use App\DTO\BaseSortingCriterion; +use App\Enum\OrderSortingType; use App\Exceptions\Internal\InvalidOrderDirectionException; use App\Models\Album; use App\Models\Extensions\AlbumBuilder; @@ -106,7 +106,7 @@ public function match(array $models, Collection $results, $relation): array /** @var Collection $childrenOfModel */ $childrenOfModel = $this->getRelationValue($dictionary, $key, 'many'); $childrenOfModel = $childrenOfModel - ->sortBy($this->sorting->column, SORT_NATURAL | SORT_FLAG_CASE, $this->sorting->order === BaseSortingCriterion::DESC) + ->sortBy($this->sorting->column->value, SORT_NATURAL | SORT_FLAG_CASE, $this->sorting->order === OrderSortingType::DESC) ->values(); $model->setRelation($relation, $childrenOfModel); // This is the newly added code which sets this method apart diff --git a/app/Relations/HasManyChildPhotos.php b/app/Relations/HasManyChildPhotos.php index a3bfb45095f..cd926cf7989 100644 --- a/app/Relations/HasManyChildPhotos.php +++ b/app/Relations/HasManyChildPhotos.php @@ -3,7 +3,7 @@ namespace App\Relations; use App\Contracts\Exceptions\InternalLycheeException; -use App\DTO\BaseSortingCriterion; +use App\Enum\OrderSortingType; use App\Exceptions\Internal\InvalidOrderDirectionException; use App\Models\Album; use App\Models\Extensions\FixedQueryBuilder; @@ -93,8 +93,8 @@ public function getResults() $albumSorting = $this->getParent()->getEffectiveSorting(); return (new SortingDecorator($this->query)) - ->orderBy( - 'photos.' . $albumSorting->column, + ->orderPhotosBy( + $albumSorting->column, $albumSorting->order ) ->get(); @@ -128,9 +128,9 @@ public function match(array $models, Collection $results, $relation): array $sorting = $model->getEffectiveSorting(); $childrenOfModel = $childrenOfModel ->sortBy( - $sorting->column, + $sorting->column->value, in_array($sorting->column, SortingDecorator::POSTPONE_COLUMNS, true) ? SORT_NATURAL | SORT_FLAG_CASE : SORT_REGULAR, - $sorting->order === BaseSortingCriterion::DESC + $sorting->order === OrderSortingType::DESC ) ->values(); $model->setRelation($relation, $childrenOfModel); diff --git a/app/Relations/HasManyPhotosByTag.php b/app/Relations/HasManyPhotosByTag.php index e4f451f949c..d4d88c4b4aa 100644 --- a/app/Relations/HasManyPhotosByTag.php +++ b/app/Relations/HasManyPhotosByTag.php @@ -3,7 +3,7 @@ namespace App\Relations; use App\Contracts\Exceptions\InternalLycheeException; -use App\DTO\BaseSortingCriterion; +use App\Enum\OrderSortingType; use App\Exceptions\Internal\NotImplementedException; use App\Models\Extensions\SortingDecorator; use App\Models\TagAlbum; @@ -91,9 +91,9 @@ public function match(array $albums, Collection $photos, $relation): array $sorting = $album->getEffectiveSorting(); $photos = $photos->sortBy( - $sorting->column, + $sorting->column->value, in_array($sorting->column, SortingDecorator::POSTPONE_COLUMNS, true) ? SORT_NATURAL | SORT_FLAG_CASE : SORT_REGULAR, - $sorting->order === BaseSortingCriterion::DESC + $sorting->order === OrderSortingType::DESC )->values(); $album->setRelation($relation, $photos); diff --git a/app/Relations/HasManyPhotosRecursively.php b/app/Relations/HasManyPhotosRecursively.php index d68be681f3f..d98c8631486 100644 --- a/app/Relations/HasManyPhotosRecursively.php +++ b/app/Relations/HasManyPhotosRecursively.php @@ -3,11 +3,10 @@ namespace App\Relations; use App\Contracts\Exceptions\InternalLycheeException; -use App\DTO\BaseSortingCriterion; +use App\Enum\OrderSortingType; use App\Exceptions\Internal\NotImplementedException; use App\Models\Album; use App\Models\Extensions\SortingDecorator; -use App\Models\Photo; use App\Policies\AlbumPolicy; use App\Policies\AlbumQueryPolicy; use Illuminate\Database\Eloquent\Collection; @@ -117,9 +116,9 @@ public function match(array $albums, Collection $photos, $relation): array } else { $sorting = $album->getEffectiveSorting(); $photos = $photos->sortBy( - $sorting->column, + $sorting->column->value, in_array($sorting->column, SortingDecorator::POSTPONE_COLUMNS, true) ? SORT_NATURAL | SORT_FLAG_CASE : SORT_REGULAR, - $sorting->order === BaseSortingCriterion::DESC + $sorting->order === OrderSortingType::DESC )->values(); $album->setRelation($relation, $photos); } diff --git a/app/Rules/AlbumSortingRule.php b/app/Rules/AlbumSortingRule.php deleted file mode 100644 index 991457b076a..00000000000 --- a/app/Rules/AlbumSortingRule.php +++ /dev/null @@ -1,31 +0,0 @@ -isNullable = $isNullable; - } - - /** - * {@inheritDoc} - */ - public function passes($attribute, $value): bool - { - return - ($this->isNullable && $value === null) || - $value === BaseSortingCriterion::ASC || - $value === BaseSortingCriterion::DESC; - } - - /** - * {@inheritDoc} - */ - public function message(): string - { - return ':attribute must be either ' . - ($this->isNullable ? 'null, ' : '') . - BaseSortingCriterion::ASC . - ' or ' . - BaseSortingCriterion::DESC; - } -} diff --git a/app/Rules/PhotoSortingRule.php b/app/Rules/PhotoSortingRule.php deleted file mode 100644 index a817dda5589..00000000000 --- a/app/Rules/PhotoSortingRule.php +++ /dev/null @@ -1,31 +0,0 @@ -photos === null) { $sorting = PhotoSortingCriterion::createDefault(); - $this->photos = (new SortingDecorator($this->photos())) - ->orderBy('photos.' . $sorting->column, $sorting->order) + ->orderPhotosBy($sorting->column, $sorting->order) ->get(); } diff --git a/bootstrap/PanicAttack.php b/bootstrap/PanicAttack.php index ce6e6ce0972..de273e8feac 100644 --- a/bootstrap/PanicAttack.php +++ b/bootstrap/PanicAttack.php @@ -133,12 +133,5 @@ public function handle(string $error_message) $this->$fun(); } } - // var_dump($error_message); - // if nothing has been caught so far - // $this->title = 'Error !'; - // $this->code = 500; - // $this->message = 'Oups, something went wrong !'; - // $this->message = $last_error['message']; - // $this->displaySimpleError(); } } diff --git a/composer.json b/composer.json index fb849d67942..c76b34b31c8 100644 --- a/composer.json +++ b/composer.json @@ -33,7 +33,7 @@ "license": "MIT", "type": "project", "require": { - "php": "^8.0.2", + "php": "^8.1", "ext-bcmath": "*", "ext-ctype": "*", "ext-exif": "*", @@ -117,7 +117,7 @@ }, "config": { "platform": { - "php": "8.0.2" + "php": "8.1" }, "preferred-install": "dist", "sort-packages": true, diff --git a/composer.lock b/composer.lock index 38aa7969b1a..b71c0a84b10 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "0c414a81b0bdf7389edf5293515ddbf5", + "content-hash": "37a26b01edd840015153b3ba14d34221", "packages": [ { "name": "bepsvpt/secure-headers", @@ -530,30 +530,29 @@ }, { "name": "doctrine/event-manager", - "version": "1.2.0", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/doctrine/event-manager.git", - "reference": "95aa4cb529f1e96576f3fda9f5705ada4056a520" + "reference": "750671534e0241a7c50ea5b43f67e23eb5c96f32" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/event-manager/zipball/95aa4cb529f1e96576f3fda9f5705ada4056a520", - "reference": "95aa4cb529f1e96576f3fda9f5705ada4056a520", + "url": "https://api.github.com/repos/doctrine/event-manager/zipball/750671534e0241a7c50ea5b43f67e23eb5c96f32", + "reference": "750671534e0241a7c50ea5b43f67e23eb5c96f32", "shasum": "" }, "require": { - "doctrine/deprecations": "^0.5.3 || ^1", - "php": "^7.1 || ^8.0" + "php": "^8.1" }, "conflict": { "doctrine/common": "<2.9" }, "require-dev": { - "doctrine/coding-standard": "^9 || ^10", - "phpstan/phpstan": "~1.4.10 || ^1.8.8", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "vimeo/psalm": "^4.24" + "doctrine/coding-standard": "^10", + "phpstan/phpstan": "^1.8.8", + "phpunit/phpunit": "^9.5", + "vimeo/psalm": "^4.28" }, "type": "library", "autoload": { @@ -602,7 +601,7 @@ ], "support": { "issues": "https://github.com/doctrine/event-manager/issues", - "source": "https://github.com/doctrine/event-manager/tree/1.2.0" + "source": "https://github.com/doctrine/event-manager/tree/2.0.0" }, "funding": [ { @@ -618,7 +617,7 @@ "type": "tidelift" } ], - "time": "2022-10-12T20:51:15+00:00" + "time": "2022-10-12T20:59:15+00:00" }, { "name": "doctrine/inflector", @@ -4699,25 +4698,25 @@ }, { "name": "symfony/cache", - "version": "v6.0.16", + "version": "v6.2.0", "source": { "type": "git", "url": "https://github.com/symfony/cache.git", - "reference": "40cd2323c219e30292c0e2520572b54310e534c6" + "reference": "64cb231dfb25677097d18503d1ad4d016b19f19c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/40cd2323c219e30292c0e2520572b54310e534c6", - "reference": "40cd2323c219e30292c0e2520572b54310e534c6", + "url": "https://api.github.com/repos/symfony/cache/zipball/64cb231dfb25677097d18503d1ad4d016b19f19c", + "reference": "64cb231dfb25677097d18503d1ad4d016b19f19c", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "psr/cache": "^2.0|^3.0", "psr/log": "^1.1|^2|^3", "symfony/cache-contracts": "^1.1.7|^2|^3", "symfony/service-contracts": "^1.1|^2|^3", - "symfony/var-exporter": "^5.4|^6.0" + "symfony/var-exporter": "^6.2" }, "conflict": { "doctrine/dbal": "<2.13.1", @@ -4747,6 +4746,9 @@ "psr-4": { "Symfony\\Component\\Cache\\": "" }, + "classmap": [ + "Traits/ValueWrapper.php" + ], "exclude-from-classmap": [ "/Tests/" ] @@ -4772,7 +4774,7 @@ "psr6" ], "support": { - "source": "https://github.com/symfony/cache/tree/v6.0.16" + "source": "https://github.com/symfony/cache/tree/v6.2.0" }, "funding": [ { @@ -4788,24 +4790,24 @@ "type": "tidelift" } ], - "time": "2022-11-07T17:51:53+00:00" + "time": "2022-11-24T11:58:37+00:00" }, { "name": "symfony/cache-contracts", - "version": "v3.0.2", + "version": "v3.2.0", "source": { "type": "git", "url": "https://github.com/symfony/cache-contracts.git", - "reference": "1c0a181c9ee221afe4fa55b2d13fc63c5ae14348" + "reference": "e8d1a5fc43534063204b74c080ebe36307d12271" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache-contracts/zipball/1c0a181c9ee221afe4fa55b2d13fc63c5ae14348", - "reference": "1c0a181c9ee221afe4fa55b2d13fc63c5ae14348", + "url": "https://api.github.com/repos/symfony/cache-contracts/zipball/e8d1a5fc43534063204b74c080ebe36307d12271", + "reference": "e8d1a5fc43534063204b74c080ebe36307d12271", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "psr/cache": "^3.0" }, "suggest": { @@ -4814,7 +4816,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "3.0-dev" + "dev-main": "3.3-dev" }, "thanks": { "name": "symfony/contracts", @@ -4851,7 +4853,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/cache-contracts/tree/v3.0.2" + "source": "https://github.com/symfony/cache-contracts/tree/v3.2.0" }, "funding": [ { @@ -4867,24 +4869,25 @@ "type": "tidelift" } ], - "time": "2022-01-02T09:55:41+00:00" + "time": "2022-11-25T10:21:52+00:00" }, { "name": "symfony/console", - "version": "v6.0.16", + "version": "v6.2.1", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "be294423f337dda97c810733138c0caec1bb0575" + "reference": "58f6cef5dc5f641b7bbdbf8b32b44cc926c35f3f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/be294423f337dda97c810733138c0caec1bb0575", - "reference": "be294423f337dda97c810733138c0caec1bb0575", + "url": "https://api.github.com/repos/symfony/console/zipball/58f6cef5dc5f641b7bbdbf8b32b44cc926c35f3f", + "reference": "58f6cef5dc5f641b7bbdbf8b32b44cc926c35f3f", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.1|^3", "symfony/polyfill-mbstring": "~1.0", "symfony/service-contracts": "^1.1|^2|^3", "symfony/string": "^5.4|^6.0" @@ -4946,7 +4949,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.0.16" + "source": "https://github.com/symfony/console/tree/v6.2.1" }, "funding": [ { @@ -4962,24 +4965,24 @@ "type": "tidelift" } ], - "time": "2022-11-25T18:58:46+00:00" + "time": "2022-12-01T13:44:20+00:00" }, { "name": "symfony/css-selector", - "version": "v6.0.11", + "version": "v6.2.0", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "ab2746acddc4f03a7234c8441822ac5d5c63efe9" + "reference": "91c342ffc99283c43653ed8eb47bc2a94db7f398" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/ab2746acddc4f03a7234c8441822ac5d5c63efe9", - "reference": "ab2746acddc4f03a7234c8441822ac5d5c63efe9", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/91c342ffc99283c43653ed8eb47bc2a94db7f398", + "reference": "91c342ffc99283c43653ed8eb47bc2a94db7f398", "shasum": "" }, "require": { - "php": ">=8.0.2" + "php": ">=8.1" }, "type": "library", "autoload": { @@ -5011,7 +5014,7 @@ "description": "Converts CSS selectors to XPath expressions", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/css-selector/tree/v6.0.11" + "source": "https://github.com/symfony/css-selector/tree/v6.2.0" }, "funding": [ { @@ -5027,29 +5030,29 @@ "type": "tidelift" } ], - "time": "2022-06-27T17:10:44+00:00" + "time": "2022-08-26T05:51:22+00:00" }, { "name": "symfony/deprecation-contracts", - "version": "v3.0.2", + "version": "v3.2.0", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "26954b3d62a6c5fd0ea8a2a00c0353a14978d05c" + "reference": "1ee04c65529dea5d8744774d474e7cbd2f1206d3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/26954b3d62a6c5fd0ea8a2a00c0353a14978d05c", - "reference": "26954b3d62a6c5fd0ea8a2a00c0353a14978d05c", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/1ee04c65529dea5d8744774d474e7cbd2f1206d3", + "reference": "1ee04c65529dea5d8744774d474e7cbd2f1206d3", "shasum": "" }, "require": { - "php": ">=8.0.2" + "php": ">=8.1" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.0-dev" + "dev-main": "3.3-dev" }, "thanks": { "name": "symfony/contracts", @@ -5078,7 +5081,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.0.2" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.2.0" }, "funding": [ { @@ -5094,24 +5097,24 @@ "type": "tidelift" } ], - "time": "2022-01-02T09:55:41+00:00" + "time": "2022-11-25T10:21:52+00:00" }, { "name": "symfony/error-handler", - "version": "v6.0.15", + "version": "v6.2.1", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "f000c166cb3ee32c4c822831a79260a135cd59b5" + "reference": "b4e41f62c1124378863ff2705158a60da3e4c6b9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/f000c166cb3ee32c4c822831a79260a135cd59b5", - "reference": "f000c166cb3ee32c4c822831a79260a135cd59b5", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/b4e41f62c1124378863ff2705158a60da3e4c6b9", + "reference": "b4e41f62c1124378863ff2705158a60da3e4c6b9", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "psr/log": "^1|^2|^3", "symfony/var-dumper": "^5.4|^6.0" }, @@ -5149,7 +5152,7 @@ "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v6.0.15" + "source": "https://github.com/symfony/error-handler/tree/v6.2.1" }, "funding": [ { @@ -5165,24 +5168,24 @@ "type": "tidelift" } ], - "time": "2022-10-28T16:22:58+00:00" + "time": "2022-12-01T21:07:46+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v6.0.9", + "version": "v6.2.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "5c85b58422865d42c6eb46f7693339056db098a8" + "reference": "9efb1618fabee89515fe031314e8ed5625f85a53" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/5c85b58422865d42c6eb46f7693339056db098a8", - "reference": "5c85b58422865d42c6eb46f7693339056db098a8", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/9efb1618fabee89515fe031314e8ed5625f85a53", + "reference": "9efb1618fabee89515fe031314e8ed5625f85a53", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "symfony/event-dispatcher-contracts": "^2|^3" }, "conflict": { @@ -5232,7 +5235,7 @@ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v6.0.9" + "source": "https://github.com/symfony/event-dispatcher/tree/v6.2.0" }, "funding": [ { @@ -5248,24 +5251,24 @@ "type": "tidelift" } ], - "time": "2022-05-05T16:45:52+00:00" + "time": "2022-11-02T09:08:04+00:00" }, { "name": "symfony/event-dispatcher-contracts", - "version": "v3.0.2", + "version": "v3.2.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "7bc61cc2db649b4637d331240c5346dcc7708051" + "reference": "0782b0b52a737a05b4383d0df35a474303cabdae" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/7bc61cc2db649b4637d331240c5346dcc7708051", - "reference": "7bc61cc2db649b4637d331240c5346dcc7708051", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/0782b0b52a737a05b4383d0df35a474303cabdae", + "reference": "0782b0b52a737a05b4383d0df35a474303cabdae", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "psr/event-dispatcher": "^1" }, "suggest": { @@ -5274,7 +5277,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "3.0-dev" + "dev-main": "3.3-dev" }, "thanks": { "name": "symfony/contracts", @@ -5311,7 +5314,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.0.2" + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.2.0" }, "funding": [ { @@ -5327,24 +5330,27 @@ "type": "tidelift" } ], - "time": "2022-01-02T09:55:41+00:00" + "time": "2022-11-25T10:21:52+00:00" }, { "name": "symfony/finder", - "version": "v6.0.11", + "version": "v6.2.0", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "09cb683ba5720385ea6966e5e06be2a34f2568b1" + "reference": "eb2355f69519e4ef33f1835bca4c935f5d42e570" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/09cb683ba5720385ea6966e5e06be2a34f2568b1", - "reference": "09cb683ba5720385ea6966e5e06be2a34f2568b1", + "url": "https://api.github.com/repos/symfony/finder/zipball/eb2355f69519e4ef33f1835bca4c935f5d42e570", + "reference": "eb2355f69519e4ef33f1835bca4c935f5d42e570", "shasum": "" }, "require": { - "php": ">=8.0.2" + "php": ">=8.1" + }, + "require-dev": { + "symfony/filesystem": "^6.0" }, "type": "library", "autoload": { @@ -5372,7 +5378,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v6.0.11" + "source": "https://github.com/symfony/finder/tree/v6.2.0" }, "funding": [ { @@ -5388,27 +5394,30 @@ "type": "tidelift" } ], - "time": "2022-07-29T07:39:48+00:00" + "time": "2022-10-09T08:55:40+00:00" }, { "name": "symfony/http-foundation", - "version": "v6.0.16", + "version": "v6.2.1", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "86eec2c66d00a2dd03d84352cd10b12df73101ec" + "reference": "d0bbd5a7e81b38f32504399b9199f265505b7bac" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/86eec2c66d00a2dd03d84352cd10b12df73101ec", - "reference": "86eec2c66d00a2dd03d84352cd10b12df73101ec", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/d0bbd5a7e81b38f32504399b9199f265505b7bac", + "reference": "d0bbd5a7e81b38f32504399b9199f265505b7bac", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "symfony/deprecation-contracts": "^2.1|^3", "symfony/polyfill-mbstring": "~1.1" }, + "conflict": { + "symfony/cache": "<6.2" + }, "require-dev": { "predis/predis": "~1.0", "symfony/cache": "^5.4|^6.0", @@ -5447,7 +5456,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v6.0.16" + "source": "https://github.com/symfony/http-foundation/tree/v6.2.1" }, "funding": [ { @@ -5463,26 +5472,27 @@ "type": "tidelift" } ], - "time": "2022-11-07T08:07:05+00:00" + "time": "2022-12-04T18:26:13+00:00" }, { "name": "symfony/http-kernel", - "version": "v6.0.16", + "version": "v6.2.1", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "8ba1344821807ad51f230f0d01e0fa8f366e4abb" + "reference": "bcbd2ea12fee651a4c8bff4f6f00cce2ac1f8404" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/8ba1344821807ad51f230f0d01e0fa8f366e4abb", - "reference": "8ba1344821807ad51f230f0d01e0fa8f366e4abb", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/bcbd2ea12fee651a4c8bff4f6f00cce2ac1f8404", + "reference": "bcbd2ea12fee651a4c8bff4f6f00cce2ac1f8404", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "psr/log": "^1|^2|^3", - "symfony/error-handler": "^5.4|^6.0", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/error-handler": "^6.1", "symfony/event-dispatcher": "^5.4|^6.0", "symfony/http-foundation": "^5.4|^6.0", "symfony/polyfill-ctype": "^1.8" @@ -5490,9 +5500,9 @@ "conflict": { "symfony/browser-kit": "<5.4", "symfony/cache": "<5.4", - "symfony/config": "<5.4", + "symfony/config": "<6.1", "symfony/console": "<5.4", - "symfony/dependency-injection": "<5.4", + "symfony/dependency-injection": "<6.2", "symfony/doctrine-bridge": "<5.4", "symfony/form": "<5.4", "symfony/http-client": "<5.4", @@ -5509,10 +5519,10 @@ "require-dev": { "psr/cache": "^1.0|^2.0|^3.0", "symfony/browser-kit": "^5.4|^6.0", - "symfony/config": "^5.4|^6.0", + "symfony/config": "^6.1", "symfony/console": "^5.4|^6.0", "symfony/css-selector": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", + "symfony/dependency-injection": "^6.2", "symfony/dom-crawler": "^5.4|^6.0", "symfony/expression-language": "^5.4|^6.0", "symfony/finder": "^5.4|^6.0", @@ -5522,6 +5532,7 @@ "symfony/stopwatch": "^5.4|^6.0", "symfony/translation": "^5.4|^6.0", "symfony/translation-contracts": "^1.1|^2|^3", + "symfony/uid": "^5.4|^6.0", "twig/twig": "^2.13|^3.0.4" }, "suggest": { @@ -5556,7 +5567,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v6.0.16" + "source": "https://github.com/symfony/http-kernel/tree/v6.2.1" }, "funding": [ { @@ -5572,37 +5583,42 @@ "type": "tidelift" } ], - "time": "2022-11-28T18:15:44+00:00" + "time": "2022-12-06T17:28:26+00:00" }, { "name": "symfony/mailer", - "version": "v6.0.16", + "version": "v6.2.1", "source": { "type": "git", "url": "https://github.com/symfony/mailer.git", - "reference": "aa47b34ab09fa03106d9e156632e4c6176b962da" + "reference": "a18c3dd41cfcf011e3866802e39b9ae9e541deaf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mailer/zipball/aa47b34ab09fa03106d9e156632e4c6176b962da", - "reference": "aa47b34ab09fa03106d9e156632e4c6176b962da", + "url": "https://api.github.com/repos/symfony/mailer/zipball/a18c3dd41cfcf011e3866802e39b9ae9e541deaf", + "reference": "a18c3dd41cfcf011e3866802e39b9ae9e541deaf", "shasum": "" }, "require": { "egulias/email-validator": "^2.1.10|^3", - "php": ">=8.0.2", + "php": ">=8.1", "psr/event-dispatcher": "^1", "psr/log": "^1|^2|^3", "symfony/event-dispatcher": "^5.4|^6.0", - "symfony/mime": "^5.4|^6.0", + "symfony/mime": "^6.2", "symfony/service-contracts": "^1.1|^2|^3" }, "conflict": { - "symfony/http-kernel": "<5.4" + "symfony/http-kernel": "<5.4", + "symfony/messenger": "<6.2", + "symfony/mime": "<6.2", + "symfony/twig-bridge": "<6.2.1" }, "require-dev": { + "symfony/console": "^5.4|^6.0", "symfony/http-client-contracts": "^1.1|^2|^3", - "symfony/messenger": "^5.4|^6.0" + "symfony/messenger": "^6.2", + "symfony/twig-bridge": "^6.2" }, "type": "library", "autoload": { @@ -5630,7 +5646,7 @@ "description": "Helps sending emails", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/mailer/tree/v6.0.16" + "source": "https://github.com/symfony/mailer/tree/v6.2.1" }, "funding": [ { @@ -5646,24 +5662,24 @@ "type": "tidelift" } ], - "time": "2022-11-04T07:39:59+00:00" + "time": "2022-12-06T16:54:23+00:00" }, { "name": "symfony/mime", - "version": "v6.0.16", + "version": "v6.2.0", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "ad9878bede5707cdf5ff7f5c86d82a921bbbfe1c" + "reference": "1e8005a7cbd79fb824ad81308ef2a76592a08bc0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/ad9878bede5707cdf5ff7f5c86d82a921bbbfe1c", - "reference": "ad9878bede5707cdf5ff7f5c86d82a921bbbfe1c", + "url": "https://api.github.com/repos/symfony/mime/zipball/1e8005a7cbd79fb824ad81308ef2a76592a08bc0", + "reference": "1e8005a7cbd79fb824ad81308ef2a76592a08bc0", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "symfony/polyfill-intl-idn": "^1.10", "symfony/polyfill-mbstring": "^1.0" }, @@ -5672,15 +5688,16 @@ "phpdocumentor/reflection-docblock": "<3.2.2", "phpdocumentor/type-resolver": "<1.4.0", "symfony/mailer": "<5.4", - "symfony/serializer": "<5.4.14|>=6.0,<6.0.14|>=6.1,<6.1.6" + "symfony/serializer": "<6.2" }, "require-dev": { "egulias/email-validator": "^2.1.10|^3.1", + "league/html-to-markdown": "^5.0", "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", "symfony/dependency-injection": "^5.4|^6.0", "symfony/property-access": "^5.4|^6.0", "symfony/property-info": "^5.4|^6.0", - "symfony/serializer": "^5.4.14|~6.0.14|^6.1.6" + "symfony/serializer": "^6.2" }, "type": "library", "autoload": { @@ -5712,7 +5729,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v6.0.16" + "source": "https://github.com/symfony/mime/tree/v6.2.0" }, "funding": [ { @@ -5728,7 +5745,7 @@ "type": "tidelift" } ], - "time": "2022-11-28T12:25:56+00:00" + "time": "2022-11-28T12:28:19+00:00" }, { "name": "symfony/polyfill-ctype", @@ -6469,20 +6486,20 @@ }, { "name": "symfony/process", - "version": "v6.0.11", + "version": "v6.2.0", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "44270a08ccb664143dede554ff1c00aaa2247a43" + "reference": "ba6e55359f8f755fe996c58a81e00eaa67a35877" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/44270a08ccb664143dede554ff1c00aaa2247a43", - "reference": "44270a08ccb664143dede554ff1c00aaa2247a43", + "url": "https://api.github.com/repos/symfony/process/zipball/ba6e55359f8f755fe996c58a81e00eaa67a35877", + "reference": "ba6e55359f8f755fe996c58a81e00eaa67a35877", "shasum": "" }, "require": { - "php": ">=8.0.2" + "php": ">=8.1" }, "type": "library", "autoload": { @@ -6510,7 +6527,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v6.0.11" + "source": "https://github.com/symfony/process/tree/v6.2.0" }, "funding": [ { @@ -6526,35 +6543,35 @@ "type": "tidelift" } ], - "time": "2022-06-27T17:10:44+00:00" + "time": "2022-11-02T09:08:04+00:00" }, { "name": "symfony/routing", - "version": "v6.0.15", + "version": "v6.2.0", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "3b7384fad32c6d0e1919b5bd18a69fbcfc383508" + "reference": "857ac6f4df371470fbdefa2f5967a2618dbf1852" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/3b7384fad32c6d0e1919b5bd18a69fbcfc383508", - "reference": "3b7384fad32c6d0e1919b5bd18a69fbcfc383508", + "url": "https://api.github.com/repos/symfony/routing/zipball/857ac6f4df371470fbdefa2f5967a2618dbf1852", + "reference": "857ac6f4df371470fbdefa2f5967a2618dbf1852", "shasum": "" }, "require": { - "php": ">=8.0.2" + "php": ">=8.1" }, "conflict": { "doctrine/annotations": "<1.12", - "symfony/config": "<5.4", + "symfony/config": "<6.2", "symfony/dependency-injection": "<5.4", "symfony/yaml": "<5.4" }, "require-dev": { "doctrine/annotations": "^1.12", "psr/log": "^1|^2|^3", - "symfony/config": "^5.4|^6.0", + "symfony/config": "^6.2", "symfony/dependency-injection": "^5.4|^6.0", "symfony/expression-language": "^5.4|^6.0", "symfony/http-foundation": "^5.4|^6.0", @@ -6598,7 +6615,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v6.0.15" + "source": "https://github.com/symfony/routing/tree/v6.2.0" }, "funding": [ { @@ -6614,24 +6631,24 @@ "type": "tidelift" } ], - "time": "2022-10-18T13:11:57+00:00" + "time": "2022-11-09T13:28:29+00:00" }, { "name": "symfony/service-contracts", - "version": "v3.0.2", + "version": "v3.1.1", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "d78d39c1599bd1188b8e26bb341da52c3c6d8a66" + "reference": "925e713fe8fcacf6bc05e936edd8dd5441a21239" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/d78d39c1599bd1188b8e26bb341da52c3c6d8a66", - "reference": "d78d39c1599bd1188b8e26bb341da52c3c6d8a66", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/925e713fe8fcacf6bc05e936edd8dd5441a21239", + "reference": "925e713fe8fcacf6bc05e936edd8dd5441a21239", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "psr/container": "^2.0" }, "conflict": { @@ -6643,7 +6660,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "3.0-dev" + "dev-main": "3.1-dev" }, "thanks": { "name": "symfony/contracts", @@ -6653,7 +6670,10 @@ "autoload": { "psr-4": { "Symfony\\Contracts\\Service\\": "" - } + }, + "exclude-from-classmap": [ + "/Test/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -6680,7 +6700,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.0.2" + "source": "https://github.com/symfony/service-contracts/tree/v3.1.1" }, "funding": [ { @@ -6696,24 +6716,24 @@ "type": "tidelift" } ], - "time": "2022-05-30T19:17:58+00:00" + "time": "2022-05-30T19:18:58+00:00" }, { "name": "symfony/string", - "version": "v6.0.15", + "version": "v6.2.0", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "51ac0fa0ccf132a00519b87c97e8f775fa14e771" + "reference": "145702685e0d12f81d755c71127bfff7582fdd36" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/51ac0fa0ccf132a00519b87c97e8f775fa14e771", - "reference": "51ac0fa0ccf132a00519b87c97e8f775fa14e771", + "url": "https://api.github.com/repos/symfony/string/zipball/145702685e0d12f81d755c71127bfff7582fdd36", + "reference": "145702685e0d12f81d755c71127bfff7582fdd36", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-intl-grapheme": "~1.0", "symfony/polyfill-intl-normalizer": "~1.0", @@ -6725,6 +6745,7 @@ "require-dev": { "symfony/error-handler": "^5.4|^6.0", "symfony/http-client": "^5.4|^6.0", + "symfony/intl": "^6.2", "symfony/translation-contracts": "^2.0|^3.0", "symfony/var-exporter": "^5.4|^6.0" }, @@ -6765,7 +6786,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v6.0.15" + "source": "https://github.com/symfony/string/tree/v6.2.0" }, "funding": [ { @@ -6781,24 +6802,24 @@ "type": "tidelift" } ], - "time": "2022-10-10T09:34:08+00:00" + "time": "2022-11-30T17:13:47+00:00" }, { "name": "symfony/translation", - "version": "v6.0.14", + "version": "v6.2.0", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "6f99eb179aee4652c0a7cd7c11f2a870d904330c" + "reference": "c08de62caead8357244efcb809d0b1a2584f2198" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/6f99eb179aee4652c0a7cd7c11f2a870d904330c", - "reference": "6f99eb179aee4652c0a7cd7c11f2a870d904330c", + "url": "https://api.github.com/repos/symfony/translation/zipball/c08de62caead8357244efcb809d0b1a2584f2198", + "reference": "c08de62caead8357244efcb809d0b1a2584f2198", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "symfony/polyfill-mbstring": "~1.0", "symfony/translation-contracts": "^2.3|^3.0" }, @@ -6814,6 +6835,7 @@ "symfony/translation-implementation": "2.3|3.0" }, "require-dev": { + "nikic/php-parser": "^4.13", "psr/log": "^1|^2|^3", "symfony/config": "^5.4|^6.0", "symfony/console": "^5.4|^6.0", @@ -6823,10 +6845,12 @@ "symfony/http-kernel": "^5.4|^6.0", "symfony/intl": "^5.4|^6.0", "symfony/polyfill-intl-icu": "^1.21", + "symfony/routing": "^5.4|^6.0", "symfony/service-contracts": "^1.1.2|^2|^3", "symfony/yaml": "^5.4|^6.0" }, "suggest": { + "nikic/php-parser": "To use PhpAstExtractor", "psr/log-implementation": "To use logging capability in translator", "symfony/config": "", "symfony/yaml": "" @@ -6860,7 +6884,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v6.0.14" + "source": "https://github.com/symfony/translation/tree/v6.2.0" }, "funding": [ { @@ -6876,24 +6900,24 @@ "type": "tidelift" } ], - "time": "2022-10-07T08:02:12+00:00" + "time": "2022-11-02T09:08:04+00:00" }, { "name": "symfony/translation-contracts", - "version": "v3.0.2", + "version": "v3.2.0", "source": { "type": "git", "url": "https://github.com/symfony/translation-contracts.git", - "reference": "acbfbb274e730e5a0236f619b6168d9dedb3e282" + "reference": "68cce71402305a015f8c1589bfada1280dc64fe7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/acbfbb274e730e5a0236f619b6168d9dedb3e282", - "reference": "acbfbb274e730e5a0236f619b6168d9dedb3e282", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/68cce71402305a015f8c1589bfada1280dc64fe7", + "reference": "68cce71402305a015f8c1589bfada1280dc64fe7", "shasum": "" }, "require": { - "php": ">=8.0.2" + "php": ">=8.1" }, "suggest": { "symfony/translation-implementation": "" @@ -6901,7 +6925,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "3.0-dev" + "dev-main": "3.3-dev" }, "thanks": { "name": "symfony/contracts", @@ -6911,7 +6935,10 @@ "autoload": { "psr-4": { "Symfony\\Contracts\\Translation\\": "" - } + }, + "exclude-from-classmap": [ + "/Test/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -6938,7 +6965,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/translation-contracts/tree/v3.0.2" + "source": "https://github.com/symfony/translation-contracts/tree/v3.2.0" }, "funding": [ { @@ -6954,24 +6981,24 @@ "type": "tidelift" } ], - "time": "2022-06-27T17:10:44+00:00" + "time": "2022-11-25T10:21:52+00:00" }, { "name": "symfony/uid", - "version": "v6.0.13", + "version": "v6.2.0", "source": { "type": "git", "url": "https://github.com/symfony/uid.git", - "reference": "db426b27173f5e2d8b960dd10fa8ce19ea9ca5f3" + "reference": "4f9f537e57261519808a7ce1d941490736522bbc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/uid/zipball/db426b27173f5e2d8b960dd10fa8ce19ea9ca5f3", - "reference": "db426b27173f5e2d8b960dd10fa8ce19ea9ca5f3", + "url": "https://api.github.com/repos/symfony/uid/zipball/4f9f537e57261519808a7ce1d941490736522bbc", + "reference": "4f9f537e57261519808a7ce1d941490736522bbc", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "symfony/polyfill-uuid": "^1.15" }, "require-dev": { @@ -7012,7 +7039,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/uid/tree/v6.0.13" + "source": "https://github.com/symfony/uid/tree/v6.2.0" }, "funding": [ { @@ -7028,24 +7055,24 @@ "type": "tidelift" } ], - "time": "2022-09-09T09:33:56+00:00" + "time": "2022-10-09T08:55:40+00:00" }, { "name": "symfony/var-dumper", - "version": "v6.0.14", + "version": "v6.2.1", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "72af925ddd41ca0372d166d004bc38a00c4608cc" + "reference": "1e7544c8698627b908657e5276854d52ab70087a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/72af925ddd41ca0372d166d004bc38a00c4608cc", - "reference": "72af925ddd41ca0372d166d004bc38a00c4608cc", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/1e7544c8698627b908657e5276854d52ab70087a", + "reference": "1e7544c8698627b908657e5276854d52ab70087a", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "symfony/polyfill-mbstring": "~1.0" }, "conflict": { @@ -7100,7 +7127,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v6.0.14" + "source": "https://github.com/symfony/var-dumper/tree/v6.2.1" }, "funding": [ { @@ -7116,24 +7143,24 @@ "type": "tidelift" } ], - "time": "2022-10-07T08:02:12+00:00" + "time": "2022-12-03T22:32:58+00:00" }, { "name": "symfony/var-exporter", - "version": "v6.0.10", + "version": "v6.2.1", "source": { "type": "git", "url": "https://github.com/symfony/var-exporter.git", - "reference": "e3df004a8d0fb572c420a6915cd23db9254c8366" + "reference": "8a3f442d48567a5447e984ce9e86875ed768304a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-exporter/zipball/e3df004a8d0fb572c420a6915cd23db9254c8366", - "reference": "e3df004a8d0fb572c420a6915cd23db9254c8366", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/8a3f442d48567a5447e984ce9e86875ed768304a", + "reference": "8a3f442d48567a5447e984ce9e86875ed768304a", "shasum": "" }, "require": { - "php": ">=8.0.2" + "php": ">=8.1" }, "require-dev": { "symfony/var-dumper": "^5.4|^6.0" @@ -7169,10 +7196,12 @@ "export", "hydrate", "instantiate", + "lazy loading", + "proxy", "serialize" ], "support": { - "source": "https://github.com/symfony/var-exporter/tree/v6.0.10" + "source": "https://github.com/symfony/var-exporter/tree/v6.2.1" }, "funding": [ { @@ -7188,7 +7217,7 @@ "type": "tidelift" } ], - "time": "2022-05-27T12:57:11+00:00" + "time": "2022-12-03T22:32:58+00:00" }, { "name": "thecodingmachine/safe", @@ -11074,20 +11103,20 @@ }, { "name": "symfony/filesystem", - "version": "v6.0.13", + "version": "v6.2.0", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "3adca49133bd055ebe6011ed1e012be3c908af79" + "reference": "50b2523c874605cf3d4acf7a9e2b30b6a440a016" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/3adca49133bd055ebe6011ed1e012be3c908af79", - "reference": "3adca49133bd055ebe6011ed1e012be3c908af79", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/50b2523c874605cf3d4acf7a9e2b30b6a440a016", + "reference": "50b2523c874605cf3d4acf7a9e2b30b6a440a016", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-mbstring": "~1.8" }, @@ -11117,7 +11146,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v6.0.13" + "source": "https://github.com/symfony/filesystem/tree/v6.2.0" }, "funding": [ { @@ -11133,24 +11162,24 @@ "type": "tidelift" } ], - "time": "2022-09-21T20:25:27+00:00" + "time": "2022-11-20T13:01:27+00:00" }, { "name": "symfony/options-resolver", - "version": "v6.0.3", + "version": "v6.2.0", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "51f7006670febe4cbcbae177cbffe93ff833250d" + "reference": "d28f02acde71ff75e957082cd36e973df395f626" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/51f7006670febe4cbcbae177cbffe93ff833250d", - "reference": "51f7006670febe4cbcbae177cbffe93ff833250d", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/d28f02acde71ff75e957082cd36e973df395f626", + "reference": "d28f02acde71ff75e957082cd36e973df395f626", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "symfony/deprecation-contracts": "^2.1|^3" }, "type": "library", @@ -11184,7 +11213,7 @@ "options" ], "support": { - "source": "https://github.com/symfony/options-resolver/tree/v6.0.3" + "source": "https://github.com/symfony/options-resolver/tree/v6.2.0" }, "funding": [ { @@ -11200,24 +11229,24 @@ "type": "tidelift" } ], - "time": "2022-01-02T09:55:41+00:00" + "time": "2022-11-02T09:08:04+00:00" }, { "name": "symfony/stopwatch", - "version": "v6.0.13", + "version": "v6.2.0", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", - "reference": "7554fde6848af5ef1178f8ccbdbdb8ae1092c70a" + "reference": "266636bb8f3fbdccc302491df7b3a1b9a8c238a7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/7554fde6848af5ef1178f8ccbdbdb8ae1092c70a", - "reference": "7554fde6848af5ef1178f8ccbdbdb8ae1092c70a", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/266636bb8f3fbdccc302491df7b3a1b9a8c238a7", + "reference": "266636bb8f3fbdccc302491df7b3a1b9a8c238a7", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "symfony/service-contracts": "^1|^2|^3" }, "type": "library", @@ -11246,7 +11275,7 @@ "description": "Provides a way to profile code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/stopwatch/tree/v6.0.13" + "source": "https://github.com/symfony/stopwatch/tree/v6.2.0" }, "funding": [ { @@ -11262,7 +11291,7 @@ "type": "tidelift" } ], - "time": "2022-09-28T15:52:47+00:00" + "time": "2022-09-28T16:00:52+00:00" }, { "name": "symplify/phpstan-rules", @@ -11444,7 +11473,7 @@ "prefer-stable": true, "prefer-lowest": false, "platform": { - "php": "^8.0.2", + "php": "^8.1", "ext-bcmath": "*", "ext-ctype": "*", "ext-exif": "*", @@ -11463,7 +11492,7 @@ "ext-zip": "*" }, "platform-overrides": { - "php": "8.0.2" + "php": "8.1" }, "plugin-api-version": "2.2.0" } diff --git a/public/Lychee-front b/public/Lychee-front index 37e6c3ac319..5a7a50c19a5 160000 --- a/public/Lychee-front +++ b/public/Lychee-front @@ -1 +1 @@ -Subproject commit 37e6c3ac31991d426ef7658c640d395575ed3262 +Subproject commit 5a7a50c19a503c32496a9dbcd41cf666cfd9aeec diff --git a/public/dist/frontend.js b/public/dist/frontend.js index b409bbcf10f..b621e736b3f 100644 --- a/public/dist/frontend.js +++ b/public/dist/frontend.js @@ -4069,7 +4069,7 @@ contextMenu.photoMulti = function (photoIDs, e) { }, { title: build.iconic("trash") + lychee.locale["DELETE_ALL"], fn: function fn() { return _photo3.delete(photoIDs); } }, { title: build.iconic("cloud-download") + lychee.locale["DOWNLOAD_ALL"], fn: function fn() { - return _photo3.getArchive(photoIDs, "FULL"); + return _photo3.getArchive(photoIDs, "ORIGINAL"); } }]; basicContext.show(items, e.originalEvent, contextMenu.close); @@ -7876,6 +7876,7 @@ lychee.locale = { URL_COPY_TO_CLIPBOARD: "Copy to clipboard", URL_COPIED_TO_CLIPBOARD: "Copied URL to clipboard!", PHOTO_DIRECT_LINKS_TO_IMAGES: "Direct links to image files:", + PHOTO_ORIGINAL: "Original", PHOTO_MEDIUM: "Medium", PHOTO_MEDIUM_HIDPI: "Medium HiDPI", PHOTO_SMALL: "Thumb", @@ -9915,7 +9916,7 @@ _photo3.setLicense = function (photoID) { /** * @param {string[]} photoIDs * @param {?string} [kind=null] - the type of size variant; one out of - * `"FULL"`, `"MEDIUM2X"`, `"MEDIUM"`, + * `"ORIGINAL"`, `"MEDIUM2X"`, `"MEDIUM"`, * `"SMALL2X"`, `"SMALL"`, `"THUMB2X"` or * `"THUMB"`, * @returns {void} @@ -9934,7 +9935,7 @@ _photo3.getArchive = function (photoIDs) { var myPhoto = _photo3.json && _photo3.json.id === photoIDs[0] ? _photo3.json : album.getByID(photoIDs[0]); var kind2VariantAndLocalizedLabel = { - FULL: ["original", lychee.locale["PHOTO_FULL"]], + ORIGINAL: ["original", lychee.locale["PHOTO_ORIGINAL"]], MEDIUM2X: ["medium2x", lychee.locale["PHOTO_MEDIUM_HIDPI"]], MEDIUM: ["medium", lychee.locale["PHOTO_MEDIUM"]], SMALL2X: ["small2x", lychee.locale["PHOTO_SMALL_HIDPI"]], diff --git a/resources/views/logs/list.blade.php b/resources/views/logs/list.blade.php index deb4f2a2884..e528fd895e0 100644 --- a/resources/views/logs/list.blade.php +++ b/resources/views/logs/list.blade.php @@ -7,7 +7,7 @@
 @forelse($logs as $log)
-    {{ $log->created_at }} -- {{ str_pad($log->type, 7) }} -- {{ $log->function }} -- {{ $log->line }} -- {{ $log->text }}
+    {{ $log->created_at }} -- {{ str_pad($log->type->value, 7) }} -- {{ $log->function }} -- {{ $log->line }} -- {{ $log->text }}
 @empty
 	Everything looks fine, Lychee has not reported any problems!
 @endforelse
diff --git a/tests/Feature/CommandGenerateThumbsTest.php b/tests/Feature/CommandGenerateThumbsTest.php
index 8edfa205eb2..6ec71c05208 100644
--- a/tests/Feature/CommandGenerateThumbsTest.php
+++ b/tests/Feature/CommandGenerateThumbsTest.php
@@ -12,7 +12,7 @@
 
 namespace Tests\Feature;
 
-use App\Models\SizeVariant;
+use App\Enum\SizeVariantType;
 use Illuminate\Support\Facades\DB;
 use function Safe\unlink;
 use Tests\AbstractTestCase;
@@ -54,7 +54,7 @@ public function testThumbRecreation(): void
 		unlink(public_path($photo1->size_variants->small->url));
 		DB::table('size_variants')
 			->where('photo_id', '=', $photo1->id)
-			->where('type', '=', SizeVariant::SMALL)
+			->where('type', '=', SizeVariantType::SMALL)
 			->delete();
 
 		// Re-create it
diff --git a/tests/Feature/CommandVideoDataTest.php b/tests/Feature/CommandVideoDataTest.php
index c3ddec3d642..a6ae8ebd6db 100644
--- a/tests/Feature/CommandVideoDataTest.php
+++ b/tests/Feature/CommandVideoDataTest.php
@@ -12,7 +12,7 @@
 
 namespace Tests\Feature;
 
-use App\Models\SizeVariant;
+use App\Enum\SizeVariantType;
 use Illuminate\Support\Facades\DB;
 use Tests\AbstractTestCase;
 use Tests\Feature\Base\BasePhotoTest;
@@ -34,7 +34,7 @@ public function testThumbRecreation(): void
 		\Safe\unlink(public_path($photo1->size_variants->thumb->url));
 		DB::table('size_variants')
 			->where('photo_id', '=', $photo1->id)
-			->where('type', '=', SizeVariant::THUMB)
+			->where('type', '=', SizeVariantType::THUMB)
 			->delete();
 
 		// Re-create it
diff --git a/tests/Feature/Lib/PhotosUnitTest.php b/tests/Feature/Lib/PhotosUnitTest.php
index 97603c76ad3..26a193e104a 100644
--- a/tests/Feature/Lib/PhotosUnitTest.php
+++ b/tests/Feature/Lib/PhotosUnitTest.php
@@ -12,7 +12,6 @@
 
 namespace Tests\Feature\Lib;
 
-use App\Actions\Photo\Archive;
 use Illuminate\Http\UploadedFile;
 use Illuminate\Testing\TestResponse;
 use Symfony\Component\HttpFoundation\StreamedResponse;
@@ -371,7 +370,7 @@ public function duplicate(
 	 */
 	public function download(
 		array $ids,
-		string $kind = Archive::FULL,
+		string $kind,
 		int $expectedStatusCode = 200
 	): TestResponse {
 		$response = $this->testCase->getWithParameters(
diff --git a/tests/Feature/PhotosDownloadTest.php b/tests/Feature/PhotosDownloadTest.php
index 34f787f116d..51bab624ae3 100644
--- a/tests/Feature/PhotosDownloadTest.php
+++ b/tests/Feature/PhotosDownloadTest.php
@@ -13,6 +13,7 @@
 namespace Tests\Feature;
 
 use App\Actions\Photo\Archive;
+use App\Enum\DownloadVariantType;
 use App\Image\Files\InMemoryBuffer;
 use App\Image\Files\TemporaryLocalFile;
 use App\Image\Handlers\ImagickHandler;
@@ -68,7 +69,8 @@ public function testSinglePhotoDownload(): void
 		$photoUploadResponse = $this->photos_tests->upload(
 			AbstractTestCase::createUploadedFile(AbstractTestCase::SAMPLE_FILE_NIGHT_IMAGE)
 		);
-		$photoArchiveResponse = $this->photos_tests->download([$photoUploadResponse->offsetGet('id')]);
+		$photoArchiveResponse = $this->photos_tests->download(
+			[$photoUploadResponse->offsetGet('id')], DownloadVariantType::ORIGINAL->value);
 
 		// Stream the response in a temporary file
 		$memoryBlob = new InMemoryBuffer();
@@ -99,7 +101,8 @@ public function testMultiplePhotoDownload(): void
 			AbstractTestCase::createUploadedFile(AbstractTestCase::SAMPLE_FILE_MONGOLIA_IMAGE)
 		)->offsetGet('id');
 
-		$photoArchiveResponse = $this->photos_tests->download([$photoID1, $photoID2]);
+		$photoArchiveResponse = $this->photos_tests->download(
+			[$photoID1, $photoID2], DownloadVariantType::ORIGINAL->value);
 
 		$zipArchive = AssertableZipArchive::createFromResponse($photoArchiveResponse);
 		$zipArchive->assertContainsFilesExactly([
@@ -123,7 +126,7 @@ public function testGoogleMotionPhotoDownload(): void
 		);
 		$photoArchiveResponse = $this->photos_tests->download(
 			[$photoUploadResponse->offsetGet('id')],
-			Archive::LIVEPHOTOVIDEO
+			DownloadVariantType::LIVEPHOTOVIDEO->value
 		);
 
 		// Stream the response in a temporary file
@@ -158,7 +161,8 @@ public function testAmbiguousPhotoDownload(): void
 			[$photoID2a], null
 		)->offsetGet('id');
 
-		$photoArchiveResponse = $this->photos_tests->download([$photoID1, $photoID2a, $photoID2b]);
+		$photoArchiveResponse = $this->photos_tests->download([$photoID1, $photoID2a, $photoID2b],
+			DownloadVariantType::ORIGINAL->value);
 
 		$zipArchive = AssertableZipArchive::createFromResponse($photoArchiveResponse);
 		$zipArchive->assertContainsFilesExactly([
@@ -174,7 +178,7 @@ public function testPhotoDownloadWithMultiByteFilename(): void
 			AbstractTestCase::createUploadedFile(AbstractTestCase::SAMPLE_FILE_SUNSET_IMAGE)
 		)->offsetGet('id');
 
-		$download = $this->photos_tests->download([$id]);
+		$download = $this->photos_tests->download([$id], DownloadVariantType::ORIGINAL->value);
 		$download->assertHeader('Content-Type', AbstractTestCase::MIME_TYPE_IMG_JPEG);
 		$download->assertHeader('Content-Length', filesize(base_path(AbstractTestCase::SAMPLE_FILE_SUNSET_IMAGE)));
 		$download->assertHeader('Content-Disposition', HeaderUtils::makeDisposition(
@@ -201,7 +205,7 @@ public function testMultiplePhotoDownloadWithMultiByteFilename(): void
 			AbstractTestCase::createUploadedFile(AbstractTestCase::SAMPLE_FILE_MONGOLIA_IMAGE)
 		)->offsetGet('id');
 
-		$photoArchiveResponse = $this->photos_tests->download([$photoID1, $photoID2]);
+		$photoArchiveResponse = $this->photos_tests->download([$photoID1, $photoID2], DownloadVariantType::ORIGINAL->value);
 
 		$zipArchive = AssertableZipArchive::createFromResponse($photoArchiveResponse);
 		$zipArchive->assertContainsFilesExactly([
@@ -251,7 +255,7 @@ public function testDownloadOfInvisibleUnsortedPhotoByNonOwner(): void
 		Auth::logout();
 		Session::flush();
 		Auth::loginUsingId($userID2);
-		$this->photos_tests->download([$photoID], Archive::FULL, 403);
+		$this->photos_tests->download([$photoID], DownloadVariantType::ORIGINAL->value, 403);
 	}
 
 	public function testDownloadOfPhotoInSharedDownloadableAlbum(): void
@@ -274,7 +278,7 @@ public function testDownloadOfPhotoInSharedDownloadableAlbum(): void
 			Auth::logout();
 			Session::flush();
 			Auth::loginUsingId($userID2);
-			$this->photos_tests->download([$photoID]);
+			$this->photos_tests->download([$photoID], DownloadVariantType::ORIGINAL->value);
 		} finally {
 			Configs::set(self::CONFIG_DOWNLOADABLE, $areAlbumsDownloadable);
 		}
@@ -300,7 +304,7 @@ public function testDownloadOfPhotoInSharedNonDownloadableAlbum(): void
 			Auth::logout();
 			Session::flush();
 			Auth::loginUsingId($userID2);
-			$this->photos_tests->download([$photoID], Archive::FULL, 403);
+			$this->photos_tests->download([$photoID], DownloadVariantType::ORIGINAL->value, 403);
 		} finally {
 			Configs::set(self::CONFIG_DOWNLOADABLE, $areAlbumsDownloadable);
 		}
diff --git a/tests/Feature/SettingsTest.php b/tests/Feature/SettingsTest.php
index 2f0a5caa01f..4c9a497710e 100644
--- a/tests/Feature/SettingsTest.php
+++ b/tests/Feature/SettingsTest.php
@@ -12,7 +12,8 @@
 
 namespace Tests\Feature;
 
-use App\DTO\BaseSortingCriterion;
+use App\Enum\ColumnSortingType;
+use App\Enum\OrderSortingType;
 use App\Http\Requests\Settings\SetSortingSettingsRequest;
 use App\Models\Configs;
 use Illuminate\Support\Facades\Auth;
@@ -65,42 +66,42 @@ private function sendKV(
 	public function testSetSorting(): void
 	{
 		$this->send('/Settings::setSorting', [
-			SetSortingSettingsRequest::ALBUM_SORTING_COLUMN_ATTRIBUTE => BaseSortingCriterion::COLUMN_CREATED_AT,
-			SetSortingSettingsRequest::PHOTO_SORTING_COLUMN_ATTRIBUTE => BaseSortingCriterion::COLUMN_CREATED_AT,
-			SetSortingSettingsRequest::ALBUM_SORTING_ORDER_ATTRIBUTE => BaseSortingCriterion::ASC,
-			SetSortingSettingsRequest::PHOTO_SORTING_ORDER_ATTRIBUTE => BaseSortingCriterion::ASC,
+			SetSortingSettingsRequest::ALBUM_SORTING_COLUMN_ATTRIBUTE => ColumnSortingType::CREATED_AT,
+			SetSortingSettingsRequest::PHOTO_SORTING_COLUMN_ATTRIBUTE => ColumnSortingType::CREATED_AT,
+			SetSortingSettingsRequest::ALBUM_SORTING_ORDER_ATTRIBUTE => OrderSortingType::ASC,
+			SetSortingSettingsRequest::PHOTO_SORTING_ORDER_ATTRIBUTE => OrderSortingType::ASC,
 		]);
 
 		$this->send('/Settings::setSorting', [
 			SetSortingSettingsRequest::ALBUM_SORTING_COLUMN_ATTRIBUTE => '123',
-			SetSortingSettingsRequest::PHOTO_SORTING_COLUMN_ATTRIBUTE => BaseSortingCriterion::COLUMN_CREATED_AT,
-			SetSortingSettingsRequest::ALBUM_SORTING_ORDER_ATTRIBUTE => BaseSortingCriterion::ASC,
-			SetSortingSettingsRequest::PHOTO_SORTING_ORDER_ATTRIBUTE => BaseSortingCriterion::ASC,
+			SetSortingSettingsRequest::PHOTO_SORTING_COLUMN_ATTRIBUTE => ColumnSortingType::CREATED_AT,
+			SetSortingSettingsRequest::ALBUM_SORTING_ORDER_ATTRIBUTE => OrderSortingType::ASC,
+			SetSortingSettingsRequest::PHOTO_SORTING_ORDER_ATTRIBUTE => OrderSortingType::ASC,
 		],
 			422,
-			'sorting albums column must be null or one out of'
+			'The selected sorting albums column is invalid'
 		);
 
 		$this->send('/Settings::setSorting', [
-			SetSortingSettingsRequest::ALBUM_SORTING_COLUMN_ATTRIBUTE => BaseSortingCriterion::COLUMN_CREATED_AT,
+			SetSortingSettingsRequest::ALBUM_SORTING_COLUMN_ATTRIBUTE => ColumnSortingType::CREATED_AT,
 			SetSortingSettingsRequest::PHOTO_SORTING_COLUMN_ATTRIBUTE => '123',
-			SetSortingSettingsRequest::ALBUM_SORTING_ORDER_ATTRIBUTE => BaseSortingCriterion::ASC,
-			SetSortingSettingsRequest::PHOTO_SORTING_ORDER_ATTRIBUTE => BaseSortingCriterion::ASC,
+			SetSortingSettingsRequest::ALBUM_SORTING_ORDER_ATTRIBUTE => OrderSortingType::ASC,
+			SetSortingSettingsRequest::PHOTO_SORTING_ORDER_ATTRIBUTE => OrderSortingType::ASC,
 		],
 			422,
-			'sorting photos column must be null or one out of'
+			'The selected sorting photos column is invalid'
 		);
 
 		$this->send(
 			'/Settings::setSorting',
 			[
-				SetSortingSettingsRequest::ALBUM_SORTING_COLUMN_ATTRIBUTE => BaseSortingCriterion::COLUMN_CREATED_AT,
-				SetSortingSettingsRequest::PHOTO_SORTING_COLUMN_ATTRIBUTE => BaseSortingCriterion::COLUMN_CREATED_AT,
+				SetSortingSettingsRequest::ALBUM_SORTING_COLUMN_ATTRIBUTE => ColumnSortingType::CREATED_AT,
+				SetSortingSettingsRequest::PHOTO_SORTING_COLUMN_ATTRIBUTE => ColumnSortingType::CREATED_AT,
 				SetSortingSettingsRequest::ALBUM_SORTING_ORDER_ATTRIBUTE => '123',
 				SetSortingSettingsRequest::PHOTO_SORTING_ORDER_ATTRIBUTE => '123',
 			],
 			422,
-			'order must be either'
+			'The selected sorting photos order is invalid'
 		);
 	}