diff --git a/app/Actions/Album/ListAlbums.php b/app/Actions/Album/ListAlbums.php index 60a7c694b15..6ea745b8478 100644 --- a/app/Actions/Album/ListAlbums.php +++ b/app/Actions/Album/ListAlbums.php @@ -39,9 +39,9 @@ public function do(?int $lft, ?int $rgt, ?string $parent_id): array $query = (new SortingDecorator($unfiltered)) ->orderBy($sorting->column, $sorting->order); - /** @var NsCollection $albums */ + /** @var NsCollection $albums */ $albums = $query->get(); - /** @var NsCollection $tree */ + /** @var NsCollection $tree */ $tree = $albums->toTree(null); $flat_tree = $this->flatten($tree); @@ -66,8 +66,8 @@ public function do(?int $lft, ?int $rgt, ?string $parent_id): array /** * Flatten the tree and create bread crumb paths. * - * @param NsCollection|Collection $collection - * @param string $prefix + * @param NsCollection|Collection $collection + * @param string $prefix * * @return TAlbumSaved[] */ diff --git a/app/Actions/Album/PositionData.php b/app/Actions/Album/PositionData.php index 1c0c59db3f3..bf8f3c24a26 100644 --- a/app/Actions/Album/PositionData.php +++ b/app/Actions/Album/PositionData.php @@ -17,6 +17,7 @@ public function get(AbstractAlbum $album, bool $includeSubAlbums = false): Posit $album->all_photos() : $album->photos(); + // @phpstan-ignore-next-line $photoRelation ->with([ 'album' => function (BelongsTo $b) { diff --git a/app/Actions/Statistics/Spaces.php b/app/Actions/Statistics/Spaces.php index 90afd3d9b7a..82df2af7cab 100644 --- a/app/Actions/Statistics/Spaces.php +++ b/app/Actions/Statistics/Spaces.php @@ -63,7 +63,7 @@ public function getFullSpacePerUser(?int $owner_id = null): Collection * * @return Collection */ - public function getSpacePerSizeVariantType(?int $owner_id = null): Collection + public function getSpacePerSizeVariantTypePerUser(?int $owner_id = null): Collection { return DB::table('size_variants') ->when($owner_id !== null, fn ($query) => $query @@ -88,6 +88,53 @@ public function getSpacePerSizeVariantType(?int $owner_id = null): Collection ]); } + /** + * Return the amount of data stored on the server (optionally for an album). + * + * @param string $album_id + * + * @return Collection + */ + public function getSpacePerSizeVariantTypePerAlbum(string $album_id): Collection + { + $query = DB::table('albums') + ->where('albums.id', '=', $album_id) + ->joinSub( + query: DB::table('albums', 'descendants')->select('descendants.id', 'descendants._lft', 'descendants._rgt'), + as: 'descendants', + first: function (JoinClause $join) { + $join->on('albums._lft', '<=', 'descendants._lft') + ->on('albums._rgt', '>=', 'descendants._rgt'); + } + ) + ->joinSub( + query: DB::table('photos'), + as: 'photos', + first: 'photos.album_id', + operator: '=', + second: 'descendants.id', + ) + ->joinSub( + query: DB::table('size_variants')->select(['size_variants.id', 'size_variants.photo_id', 'size_variants.type', 'size_variants.filesize']), + as: 'size_variants', + first: 'size_variants.photo_id', + operator: '=', + second: 'photos.id', + ) + ->select( + 'size_variants.type', + DB::raw('SUM(size_variants.filesize) as size') + ) + ->groupBy('size_variants.type') + ->orderBy('size_variants.type', 'asc'); + + return $query->get() + ->map(fn ($item) => [ + 'type' => SizeVariantType::from($item->type), + 'size' => intval($item->size), + ]); + } + /** * Return size statistics per album. * @@ -99,7 +146,18 @@ public function getSpacePerSizeVariantType(?int $owner_id = null): Collection public function getSpacePerAlbum(?string $album_id = null, ?int $owner_id = null) { $query = DB::table('albums') - ->when($album_id !== null, fn ($query) => $query->where('albums.id', '=', $album_id)) + ->when($album_id !== null, + fn ($query) => $query + ->joinSub( + query: DB::table('albums', 'parent')->select('parent.id', 'parent._lft', 'parent._rgt'), + as: 'parent', + first: function (JoinClause $join) { + $join->on('albums._lft', '>=', 'parent._lft') + ->on('albums._rgt', '<=', 'parent._rgt'); + } + ) + ->where('parent.id', '=', $album_id) + ) ->when($owner_id !== null, fn ($query) => $query->joinSub( query: DB::table('base_albums')->select(['base_albums.id', 'base_albums.owner_id']), as: 'base_albums', @@ -211,7 +269,18 @@ public function getTotalSpacePerAlbum(?string $album_id = null, ?int $owner_id = public function getPhotoCountPerAlbum(?string $album_id = null, ?int $owner_id = null) { $query = DB::table('albums') - ->when($album_id !== null, fn ($query) => $query->where('albums.id', '=', $album_id)) + ->when($album_id !== null, + fn ($query) => $query + ->joinSub( + query: DB::table('albums', 'parent')->select('parent.id', 'parent._lft', 'parent._rgt'), + as: 'parent', + first: function (JoinClause $join) { + $join->on('albums._lft', '>=', 'parent._lft') + ->on('albums._rgt', '<=', 'parent._rgt'); + } + ) + ->where('parent.id', '=', $album_id) + ) ->joinSub( query: DB::table('base_albums')->select(['base_albums.id', 'base_albums.owner_id', 'base_albums.title', 'base_albums.is_nsfw']), as: 'base_albums', diff --git a/app/Contracts/Http/Requests/HasPhotoLayout.php b/app/Contracts/Http/Requests/HasPhotoLayout.php new file mode 100644 index 00000000000..6d1dc3e064e --- /dev/null +++ b/app/Contracts/Http/Requests/HasPhotoLayout.php @@ -0,0 +1,13 @@ +|Builder + * @return Relation>|Builder */ public function photos(): Relation|Builder; diff --git a/app/Eloquent/FixedQueryBuilderTrait.php b/app/Eloquent/FixedQueryBuilderTrait.php index cf037c8fdaf..54d3e0e1072 100644 --- a/app/Eloquent/FixedQueryBuilderTrait.php +++ b/app/Eloquent/FixedQueryBuilderTrait.php @@ -5,9 +5,9 @@ namespace App\Eloquent; use App\Exceptions\Internal\QueryBuilderException; +use Illuminate\Contracts\Database\Query\Expression; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Query\Builder as BaseBuilder; -use Illuminate\Database\Query\Expression; /** * Fixed Eloquent query builder. @@ -50,10 +50,10 @@ trait FixedQueryBuilderTrait /** * Add a basic where clause to the query. * - * @param \Closure|string|array|Expression $column - * @param mixed $operator - * @param mixed $value - * @param string $boolean + * @param \Closure|string|array|Expression $column + * @param mixed $operator + * @param mixed $value + * @param string $boolean * * @return $this * @@ -268,9 +268,9 @@ public function addSelect($column): static /** * Add an "or where" clause to the query. * - * @param \Closure|array|string|Expression $column - * @param mixed $operator - * @param mixed $value + * @param \Closure|string|array|Expression $column + * @param mixed $operator + * @param mixed $value * * @return $this * diff --git a/app/Http/Controllers/Admin/Maintenance/Model/Album.php b/app/Http/Controllers/Admin/Maintenance/Model/Album.php index ae3ede2006c..f5af93a005b 100644 --- a/app/Http/Controllers/Admin/Maintenance/Model/Album.php +++ b/app/Http/Controllers/Admin/Maintenance/Model/Album.php @@ -10,11 +10,11 @@ * This is necessary to fix the tree of the album model. * We do not want to have to deal with the relationships here. * - * @implements Node + * @implements Node */ class Album extends Model implements Node { - /** @phpstan-use NodeTrait */ + /** @phpstan-use NodeTrait */ use NodeTrait; public $timestamps = false; } \ No newline at end of file diff --git a/app/Http/Controllers/Gallery/AlbumController.php b/app/Http/Controllers/Gallery/AlbumController.php index 4c0462e5704..2e6cac71282 100644 --- a/app/Http/Controllers/Gallery/AlbumController.php +++ b/app/Http/Controllers/Gallery/AlbumController.php @@ -110,6 +110,7 @@ public function updateAlbum(UpdateAlbumRequest $request, SetHeader $setHeader): $album->copyright = $request->copyright(); $album->photo_sorting = $request->photoSortingCriterion(); $album->album_sorting = $request->albumSortingCriterion(); + $album->photo_layout = $request->photoLayout(); $album = $setHeader->do( album: $album, @@ -131,6 +132,7 @@ public function updateTagAlbum(UpdateTagAlbumRequest $request): EditableBaseAlbu $album->show_tags = $request->tags(); $album->copyright = $request->copyright(); $album->photo_sorting = $request->photoSortingCriterion(); + $album->photo_layout = $request->photoLayout(); $album->save(); return EditableBaseAlbumResource::fromModel($album); diff --git a/app/Http/Controllers/StatisticsController.php b/app/Http/Controllers/StatisticsController.php index cbd1ec9a014..4fdabca7ea9 100644 --- a/app/Http/Controllers/StatisticsController.php +++ b/app/Http/Controllers/StatisticsController.php @@ -5,6 +5,7 @@ use App\Actions\Statistics\Spaces; use App\Http\Requests\Statistics\SpacePerAlbumRequest; use App\Http\Requests\Statistics\SpacePerUserRequest; +use App\Http\Requests\Statistics\SpaceSizeVariantRequest; use App\Http\Resources\Statistics\Album; use App\Http\Resources\Statistics\Sizes; use App\Http\Resources\Statistics\UserSpace; @@ -29,16 +30,19 @@ public function getSpacePerUser(SpacePerUserRequest $request, Spaces $spaces): C } /** - * @param SpacePerUserRequest $request - * @param Spaces $spaces + * @param SpaceSizeVariantRequest $request + * @param Spaces $spaces * * @return Collection */ - public function getSpacePerSizeVariantType(SpacePerUserRequest $request, Spaces $spaces): Collection + public function getSpacePerSizeVariantType(SpaceSizeVariantRequest $request, Spaces $spaces): Collection { - $spaceData = $spaces->getSpacePerSizeVariantType( - owner_id: $request->ownerId() - ); + $albumId = $request->album()?->id; + $ownerId = $albumId === null ? $request->ownerId() : null; + + $spaceData = $albumId === null + ? $spaces->getSpacePerSizeVariantTypePerUser(owner_id: $ownerId) + : $spaces->getSpacePerSizeVariantTypePerAlbum(album_id: $albumId); return Sizes::collect($spaceData); } diff --git a/app/Http/Requests/Album/UpdateAlbumRequest.php b/app/Http/Requests/Album/UpdateAlbumRequest.php index 62357e19754..1a559356c2d 100644 --- a/app/Http/Requests/Album/UpdateAlbumRequest.php +++ b/app/Http/Requests/Album/UpdateAlbumRequest.php @@ -9,6 +9,7 @@ use App\Contracts\Http\Requests\HasDescription; use App\Contracts\Http\Requests\HasLicense; use App\Contracts\Http\Requests\HasPhoto; +use App\Contracts\Http\Requests\HasPhotoLayout; use App\Contracts\Http\Requests\HasPhotoSortingCriterion; use App\Contracts\Http\Requests\HasTitle; use App\Contracts\Http\Requests\RequestAttribute; @@ -20,6 +21,7 @@ use App\Enum\ColumnSortingPhotoType; use App\Enum\LicenseType; use App\Enum\OrderSortingType; +use App\Enum\PhotoLayoutType; use App\Http\Requests\BaseApiRequest; use App\Http\Requests\Traits\HasAlbumSortingCriterionTrait; use App\Http\Requests\Traits\HasAlbumTrait; @@ -28,6 +30,7 @@ use App\Http\Requests\Traits\HasCopyrightTrait; use App\Http\Requests\Traits\HasDescriptionTrait; use App\Http\Requests\Traits\HasLicenseTrait; +use App\Http\Requests\Traits\HasPhotoLayoutTrait; use App\Http\Requests\Traits\HasPhotoSortingCriterionTrait; use App\Http\Requests\Traits\HasPhotoTrait; use App\Http\Requests\Traits\HasTitleTrait; @@ -42,7 +45,7 @@ use Illuminate\Validation\Rules\Enum; use Illuminate\Validation\ValidationException; -class UpdateAlbumRequest extends BaseApiRequest implements HasAlbum, HasTitle, HasDescription, HasLicense, HasPhotoSortingCriterion, HasAlbumSortingCriterion, HasCopyright, HasPhoto, HasCompactBoolean +class UpdateAlbumRequest extends BaseApiRequest implements HasAlbum, HasTitle, HasDescription, HasLicense, HasPhotoSortingCriterion, HasAlbumSortingCriterion, HasCopyright, HasPhoto, HasCompactBoolean, HasPhotoLayout { use HasAlbumTrait; use HasLicenseTrait; @@ -54,6 +57,7 @@ class UpdateAlbumRequest extends BaseApiRequest implements HasAlbum, HasTitle, H use HasPhotoSortingCriterionTrait; use HasAlbumSortingCriterionTrait; use HasCopyrightTrait; + use HasPhotoLayoutTrait; public function authorize(): bool { @@ -84,6 +88,7 @@ public function rules(): array 'nullable', new Enum(OrderSortingType::class), ], RequestAttribute::ALBUM_ASPECT_RATIO_ATTRIBUTE => ['present', 'nullable', new Enum(AspectRatioType::class)], + RequestAttribute::ALBUM_PHOTO_LAYOUT => ['present', 'nullable', new Enum(PhotoLayoutType::class)], RequestAttribute::COPYRIGHT_ATTRIBUTE => ['present', 'nullable', new CopyrightRule()], RequestAttribute::IS_COMPACT_ATTRIBUTE => ['required', 'boolean'], RequestAttribute::HEADER_ID_ATTRIBUTE => ['present', new RandomIDRule(true)], @@ -123,6 +128,7 @@ protected function processValidatedValues(array $values, array $files): void new AlbumSortingCriterion($albumColumn->toColumnSortingType(), $albumOrder); $this->aspectRatio = AspectRatioType::tryFrom($values[RequestAttribute::ALBUM_ASPECT_RATIO_ATTRIBUTE]); + $this->photoLayout = PhotoLayoutType::tryFrom($values[RequestAttribute::ALBUM_PHOTO_LAYOUT]); $this->copyright = $values[RequestAttribute::COPYRIGHT_ATTRIBUTE]; $this->is_compact = static::toBoolean($values[RequestAttribute::IS_COMPACT_ATTRIBUTE]); diff --git a/app/Http/Requests/Album/UpdateTagAlbumRequest.php b/app/Http/Requests/Album/UpdateTagAlbumRequest.php index 6daa665b094..99a07ca451d 100644 --- a/app/Http/Requests/Album/UpdateTagAlbumRequest.php +++ b/app/Http/Requests/Album/UpdateTagAlbumRequest.php @@ -4,6 +4,7 @@ use App\Contracts\Http\Requests\HasCopyright; use App\Contracts\Http\Requests\HasDescription; +use App\Contracts\Http\Requests\HasPhotoLayout; use App\Contracts\Http\Requests\HasPhotoSortingCriterion; use App\Contracts\Http\Requests\HasTagAlbum; use App\Contracts\Http\Requests\HasTags; @@ -12,10 +13,12 @@ use App\DTO\PhotoSortingCriterion; use App\Enum\ColumnSortingPhotoType; use App\Enum\OrderSortingType; +use App\Enum\PhotoLayoutType; use App\Http\Requests\BaseApiRequest; use App\Http\Requests\Traits\Authorize\AuthorizeCanEditAlbumTrait; use App\Http\Requests\Traits\HasCopyrightTrait; use App\Http\Requests\Traits\HasDescriptionTrait; +use App\Http\Requests\Traits\HasPhotoLayoutTrait; use App\Http\Requests\Traits\HasPhotoSortingCriterionTrait; use App\Http\Requests\Traits\HasTagAlbumTrait; use App\Http\Requests\Traits\HasTagsTrait; @@ -28,7 +31,7 @@ use Illuminate\Validation\Rules\Enum; use Illuminate\Validation\ValidationException; -class UpdateTagAlbumRequest extends BaseApiRequest implements HasTagAlbum, HasTitle, HasDescription, HasPhotoSortingCriterion, HasCopyright, HasTags +class UpdateTagAlbumRequest extends BaseApiRequest implements HasTagAlbum, HasTitle, HasDescription, HasPhotoSortingCriterion, HasCopyright, HasTags, HasPhotoLayout { use HasTagAlbumTrait; use HasTitleTrait; @@ -36,6 +39,7 @@ class UpdateTagAlbumRequest extends BaseApiRequest implements HasTagAlbum, HasTi use HasPhotoSortingCriterionTrait; use HasCopyrightTrait; use HasTagsTrait; + use HasPhotoLayoutTrait; use AuthorizeCanEditAlbumTrait; /** @@ -55,6 +59,7 @@ public function rules(): array RequestAttribute::TAGS_ATTRIBUTE => 'required|array|min:1', RequestAttribute::TAGS_ATTRIBUTE . '.*' => 'required|string|min:1', RequestAttribute::COPYRIGHT_ATTRIBUTE => ['present', 'nullable', new CopyrightRule()], + RequestAttribute::ALBUM_PHOTO_LAYOUT => ['present', 'nullable', new Enum(PhotoLayoutType::class)], ]; } @@ -82,6 +87,7 @@ protected function processValidatedValues(array $values, array $files): void null : new PhotoSortingCriterion($photoColumn->toColumnSortingType(), $photoOrder); + $this->photoLayout = PhotoLayoutType::tryFrom($values[RequestAttribute::ALBUM_PHOTO_LAYOUT]); $this->copyright = $values[RequestAttribute::COPYRIGHT_ATTRIBUTE]; $this->tags = $values[RequestAttribute::TAGS_ATTRIBUTE]; } diff --git a/app/Http/Requests/Statistics/SpacePerAlbumRequest.php b/app/Http/Requests/Statistics/SpacePerAlbumRequest.php index 0b899ae08e0..b24802f9a79 100644 --- a/app/Http/Requests/Statistics/SpacePerAlbumRequest.php +++ b/app/Http/Requests/Statistics/SpacePerAlbumRequest.php @@ -2,14 +2,13 @@ namespace App\Http\Requests\Statistics; -use App\Contracts\Http\Requests\HasAlbum; +use App\Contracts\Http\Requests\HasAbstractAlbum; use App\Contracts\Http\Requests\HasOwnerId; use App\Contracts\Http\Requests\RequestAttribute; use App\Contracts\Models\AbstractAlbum; use App\Http\Requests\BaseApiRequest; -use App\Http\Requests\Traits\HasAlbumTrait; +use App\Http\Requests\Traits\HasAbstractAlbumTrait; use App\Http\Requests\Traits\HasOwnerIdTrait; -use App\Models\Album; use App\Models\Configs; use App\Policies\AlbumPolicy; use App\Policies\SettingsPolicy; @@ -17,9 +16,9 @@ use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Gate; -class SpacePerAlbumRequest extends BaseApiRequest implements HasAlbum, HasOwnerId +class SpacePerAlbumRequest extends BaseApiRequest implements HasAbstractAlbum, HasOwnerId { - use HasAlbumTrait; + use HasAbstractAlbumTrait; use HasOwnerIdTrait; /** @@ -31,7 +30,7 @@ public function authorize(): bool return Gate::check(SettingsPolicy::CAN_SEE_STATISTICS, [Configs::class]); } - return Gate::check(AlbumPolicy::CAN_ACCESS, [AbstractAlbum::class, $this->album]); + return Auth::check() && Gate::check(AlbumPolicy::CAN_ACCESS, [AbstractAlbum::class, $this->album]); } /** @@ -51,7 +50,7 @@ protected function processValidatedValues(array $values, array $files): void { /** @var string|null */ $albumID = $values[RequestAttribute::ALBUM_ID_ATTRIBUTE] ?? null; - $this->album = $albumID === null ? null : Album::query()->findOrFail($albumID); + $this->album = $this->albumFactory->findNullalbleAbstractAlbumOrFail($albumID); // Filter only to user if user is not admin if (Auth::check() && Auth::user()?->may_administrate !== true) { diff --git a/app/Http/Requests/Statistics/SpaceSizeVariantRequest.php b/app/Http/Requests/Statistics/SpaceSizeVariantRequest.php new file mode 100644 index 00000000000..30918f4d6fc --- /dev/null +++ b/app/Http/Requests/Statistics/SpaceSizeVariantRequest.php @@ -0,0 +1,60 @@ +album === null) { + return Gate::check(UserPolicy::CAN_EDIT, [User::class]); + } + + return Auth::check() && Gate::check(AlbumPolicy::CAN_ACCESS, [AbstractAlbum::class, $this->album]); + } + + /** + * {@inheritDoc} + */ + public function rules(): array + { + return [ + RequestAttribute::ALBUM_ID_ATTRIBUTE => ['sometimes', new RandomIDRule(true)], + ]; + } + + /** + * {@inheritDoc} + */ + protected function processValidatedValues(array $values, array $files): void + { + /** @var string|null */ + $albumID = $values[RequestAttribute::ALBUM_ID_ATTRIBUTE] ?? null; + $this->album = $this->albumFactory->findNullalbleAbstractAlbumOrFail($albumID); + + // Filter only to user if user is not admin + if (Auth::check() && Auth::user()?->may_administrate !== true) { + $this->owner_id = intval(Auth::id()); + } + } +} diff --git a/app/Http/Requests/Traits/HasPhotoLayoutTrait.php b/app/Http/Requests/Traits/HasPhotoLayoutTrait.php new file mode 100644 index 00000000000..131a78d9ce0 --- /dev/null +++ b/app/Http/Requests/Traits/HasPhotoLayoutTrait.php @@ -0,0 +1,18 @@ +photoLayout; + } +} diff --git a/app/Http/Resources/Editable/EditableBaseAlbumResource.php b/app/Http/Resources/Editable/EditableBaseAlbumResource.php index 753b928d13f..18c5a563914 100644 --- a/app/Http/Resources/Editable/EditableBaseAlbumResource.php +++ b/app/Http/Resources/Editable/EditableBaseAlbumResource.php @@ -6,6 +6,7 @@ use App\DTO\PhotoSortingCriterion; use App\Enum\AspectRatioType; use App\Enum\LicenseType; +use App\Enum\PhotoLayoutType; use App\Models\Album; use App\Models\TagAlbum; use Spatie\LaravelData\Data; @@ -22,6 +23,7 @@ class EditableBaseAlbumResource extends Data public ?PhotoSortingCriterion $photo_sorting; public ?AlbumSortingCriterion $album_sorting; public ?AspectRatioType $aspect_ratio; + public ?PhotoLayoutType $photo_layout; public ?string $header_id; public ?string $cover_id; /** @var string[] */ @@ -40,6 +42,7 @@ public function __construct(Album|TagAlbum $album) $this->album_sorting = null; $this->header_id = null; $this->cover_id = null; + $this->photo_layout = $album->photo_layout; if ($album instanceof Album) { $this->is_model_album = true; diff --git a/app/Http/Resources/GalleryConfigs/AlbumConfig.php b/app/Http/Resources/GalleryConfigs/AlbumConfig.php index 706940a2ed1..ceb7e6b0d22 100644 --- a/app/Http/Resources/GalleryConfigs/AlbumConfig.php +++ b/app/Http/Resources/GalleryConfigs/AlbumConfig.php @@ -5,6 +5,7 @@ use App\Contracts\Models\AbstractAlbum; use App\Enum\AspectRatioCSSType; use App\Enum\AspectRatioType; +use App\Enum\PhotoLayoutType; use App\Models\Album; use App\Models\Configs; use App\Models\Extensions\BaseAlbum; @@ -26,6 +27,7 @@ class AlbumConfig extends Data public bool $is_search_accessible; public bool $is_nsfw_warning_visible; public AspectRatioCSSType $album_thumb_css_aspect_ratio; + public PhotoLayoutType $photo_layout; public function __construct(AbstractAlbum $album) { @@ -49,6 +51,8 @@ public function __construct(AbstractAlbum $album) } else { $this->album_thumb_css_aspect_ratio = Configs::getValueAsEnum('default_album_thumb_aspect_ratio', AspectRatioType::class)->css(); } + + $this->photo_layout = (($album instanceof BaseAlbum) ? $album->photo_layout : null) ?? Configs::getValueAsEnum('layout', PhotoLayoutType::class); } public function setIsMapAccessible(): void diff --git a/app/Http/Resources/GalleryConfigs/PhotoLayoutConfig.php b/app/Http/Resources/GalleryConfigs/PhotoLayoutConfig.php index baa69156426..264171335b2 100644 --- a/app/Http/Resources/GalleryConfigs/PhotoLayoutConfig.php +++ b/app/Http/Resources/GalleryConfigs/PhotoLayoutConfig.php @@ -2,7 +2,6 @@ namespace App\Http\Resources\GalleryConfigs; -use App\Enum\PhotoLayoutType; use App\Models\Configs; use Spatie\LaravelData\Data; use Spatie\TypeScriptTransformer\Attributes\TypeScript; @@ -10,7 +9,6 @@ #[TypeScript()] class PhotoLayoutConfig extends Data { - public PhotoLayoutType $photos_layout; public int $photo_layout_justified_row_height; public int $photo_layout_masonry_column_width; public int $photo_layout_grid_column_width; @@ -24,6 +22,5 @@ public function __construct() $this->photo_layout_grid_column_width = Configs::getValueAsInt('photo_layout_grid_column_width'); $this->photo_layout_square_column_width = Configs::getValueAsInt('photo_layout_square_column_width'); $this->photo_layout_gap = Configs::getValueAsInt('photo_layout_gap'); - $this->photos_layout = Configs::getValueAsEnum('layout', PhotoLayoutType::class); } } diff --git a/app/Http/Resources/Models/ThumbAlbumResource.php b/app/Http/Resources/Models/ThumbAlbumResource.php index 9cffcd6c625..0c12a1da0a5 100644 --- a/app/Http/Resources/Models/ThumbAlbumResource.php +++ b/app/Http/Resources/Models/ThumbAlbumResource.php @@ -37,6 +37,7 @@ class ThumbAlbumResource extends Data private ?string $min_taken_at = null; private ?string $max_taken_at = null; public ?string $formatted_min_max = null; + public ?string $owner = null; public AlbumRightsResource $rights; @@ -60,6 +61,7 @@ public function __construct(AbstractAlbum $data) $this->created_at = $data->created_at->format($date_format); $policy = AlbumProtectionPolicy::ofBaseAlbum($data); $this->description = Str::limit($data->description, 100); + $this->owner = $data->owner->username; } if ($data instanceof Album) { diff --git a/app/Legacy/V1/Actions/Albums/Tree.php b/app/Legacy/V1/Actions/Albums/Tree.php index fb3cbb5c020..3478d911b74 100644 --- a/app/Legacy/V1/Actions/Albums/Tree.php +++ b/app/Legacy/V1/Actions/Albums/Tree.php @@ -62,9 +62,9 @@ public function get(): AlbumForestResource } $query->orderBy($this->sorting->column, $this->sorting->order); - /** @var NsCollection $albums */ + /** @var NsCollection $albums */ $albums = $query->get(); - /** @var ?NsCollection $sharedAlbums */ + /** @var ?NsCollection $sharedAlbums */ $sharedAlbums = null; $userID = Auth::id(); if ($userID !== null) { @@ -75,8 +75,8 @@ public function get(): AlbumForestResource // (sub)-tree and then `toTree` will return garbage as it does // not find connected paths within `$albums` or `$sharedAlbums`, // resp. - /** @var NsCollection $albums */ - /** @var ?NsCollection $sharedAlbums */ + /** @var NsCollection $albums */ + /** @var ?NsCollection $sharedAlbums */ list($albums, $sharedAlbums) = $albums->partition(fn (Album $album) => $album->owner_id === $userID); } diff --git a/app/Legacy/V1/Controllers/Administration/SettingsController.php b/app/Legacy/V1/Controllers/Administration/SettingsController.php index 02897c02fd2..df82fe38bfe 100644 --- a/app/Legacy/V1/Controllers/Administration/SettingsController.php +++ b/app/Legacy/V1/Controllers/Administration/SettingsController.php @@ -33,6 +33,7 @@ use App\SmartAlbums\BaseSmartAlbum; use Illuminate\Database\Eloquent\Collection; use Illuminate\Routing\Controller; +use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Storage; use Symfony\Component\HttpFoundation\Exception\BadRequestException; @@ -403,6 +404,9 @@ public function getAll(GetSetAllSettingsRequest $request): Collection return Configs::query() ->orderBy('cat') ->orderBy('id') + // Only display settings which are not part of SE + ->where('level', '=', 0) + ->whereNotIn('key', ['email']) ->get(); } @@ -419,7 +423,16 @@ public function getAll(GetSetAllSettingsRequest $request): Collection public function saveAll(GetSetAllSettingsRequest $request): void { $lastException = null; - foreach ($request->except(['_token', 'function', '/api/Settings::saveAll']) as $key => $value) { + // Select all the SE settings. + $except = DB::table('configs') + ->select('key') + ->where('level', '=', '1') + ->pluck('key') + // Concat bunch of things coming from the POST request. + ->concat(['_token', 'function', '/api/Settings::saveAll']) + // Convert to array. + ->all(); + foreach ($request->except($except) as $key => $value) { $value ??= ''; try { Configs::set($key, $value); diff --git a/app/Models/AccessPermission.php b/app/Models/AccessPermission.php index aa6cd0a22f0..c29578a82e8 100644 --- a/app/Models/AccessPermission.php +++ b/app/Models/AccessPermission.php @@ -104,7 +104,7 @@ public function newEloquentBuilder($query): AccessPermissionBuilder /** * Returns the relationship between an AccessPermission and its associated album. * - * @return BelongsTo + * @return BelongsTo */ public function album(): BelongsTo { @@ -114,7 +114,7 @@ public function album(): BelongsTo /** * Returns the relationship between an AccessPermission and its applied User. * - * @return BelongsTo + * @return BelongsTo */ public function user(): BelongsTo { diff --git a/app/Models/Album.php b/app/Models/Album.php index 40b6f36b9b0..a48e894d7a0 100644 --- a/app/Models/Album.php +++ b/app/Models/Album.php @@ -124,11 +124,11 @@ * * // * @mixin \Eloquent * - * @implements Node + * @implements Node */ class Album extends BaseAlbum implements Node { - /** @phpstan-use NodeTrait */ + /** @phpstan-use NodeTrait */ use NodeTrait; use ToArrayThrowsNotImplemented; /** @phpstan-use HasFactory<\Database\Factories\AlbumFactory> */ @@ -182,7 +182,7 @@ class Album extends BaseAlbum implements Node * * @return HasManyChildPhotos */ - public function photos(): HasManyChildPhotos + public function photos(): HasManyChildPhotos // @phpstan-ignore-line { return new HasManyChildPhotos($this); } @@ -216,14 +216,14 @@ public function children(): HasManyChildAlbums /** * Get query for descendants of the node. * - * @return DescendantsRelation + * @return DescendantsRelation * * @throws QueryBuilderException */ public function descendants(): DescendantsRelation { try { - /** @var DescendantsRelation */ + /** @var DescendantsRelation */ return new DescendantsRelation($this->newQuery(), $this); // @codeCoverageIgnoreStart } catch (\Throwable $e) { @@ -235,7 +235,7 @@ public function descendants(): DescendantsRelation /** * Return the relationship between an album and its cover. * - * @return HasOne + * @return HasOne */ public function cover(): HasOne { @@ -245,7 +245,7 @@ public function cover(): HasOne /** * Return the relationship between an album and its header. * - * @return HasOne + * @return HasOne */ public function header(): HasOne { diff --git a/app/Models/BaseAlbumImpl.php b/app/Models/BaseAlbumImpl.php index 5b9bbd5a0e4..e81954b43e7 100644 --- a/app/Models/BaseAlbumImpl.php +++ b/app/Models/BaseAlbumImpl.php @@ -8,6 +8,7 @@ use App\DTO\PhotoSortingCriterion; use App\Enum\ColumnSortingType; use App\Enum\OrderSortingType; +use App\Enum\PhotoLayoutType; use App\Models\Builders\BaseAlbumImplBuilder; use App\Models\Extensions\HasAttributesPatch; use App\Models\Extensions\HasBidirectionalRelationships; @@ -94,6 +95,7 @@ * @property Carbon $updated_at * @property string $title * @property string|null $description + * @property PhotoLayoutType|null $photo_layout * @property int $owner_id * @property User $owner * @property bool $is_nsfw @@ -178,6 +180,7 @@ class BaseAlbumImpl extends Model implements HasRandomID 'copyright' => null, // Special visibility attributes 'is_nsfw' => false, + 'photo_layout' => null, ]; /** @@ -190,6 +193,7 @@ class BaseAlbumImpl extends Model implements HasRandomID 'updated_at' => 'datetime', 'is_nsfw' => 'boolean', 'owner_id' => 'integer', + 'photo_layout' => PhotoLayoutType::class, ]; /** @@ -210,7 +214,7 @@ public function newEloquentBuilder($query): BaseAlbumImplBuilder /** * Returns the relationship between an album and its owner. * - * @return BelongsTo + * @return BelongsTo */ public function owner(): BelongsTo { @@ -221,7 +225,7 @@ public function owner(): BelongsTo * Returns the relationship between an album and all users with whom * this album is shared. * - * @return BelongsToMany + * @return BelongsToMany */ public function shared_with(): BelongsToMany { @@ -236,7 +240,7 @@ public function shared_with(): BelongsToMany /** * Returns the relationship between an album and its associated permissions. * - * @return hasMany + * @return hasMany */ public function access_permissions(): hasMany { diff --git a/app/Models/Builders/AlbumBuilder.php b/app/Models/Builders/AlbumBuilder.php index 9a9c09ff8ba..1e8fe6c469a 100644 --- a/app/Models/Builders/AlbumBuilder.php +++ b/app/Models/Builders/AlbumBuilder.php @@ -48,7 +48,7 @@ * @method $this whereNull(string|array $columns, string $boolean = 'and', bool $not = false) * @method $this orderByDesc($column) * - * @extends NSQueryBuilder + * @extends NSQueryBuilder */ class AlbumBuilder extends NSQueryBuilder { @@ -64,7 +64,7 @@ class AlbumBuilder extends NSQueryBuilder * * @param string[]|string $columns * - * @return Album[] + * @return array * * @throws InternalLycheeException */ diff --git a/app/Models/Builders/TagAlbumBuilder.php b/app/Models/Builders/TagAlbumBuilder.php index ec87520c434..6eb306727f0 100644 --- a/app/Models/Builders/TagAlbumBuilder.php +++ b/app/Models/Builders/TagAlbumBuilder.php @@ -28,7 +28,7 @@ class TagAlbumBuilder extends FixedQueryBuilder * * @param array|string $columns * - * @return TagAlbum[] + * @return array * * @throws QueryBuilderException */ diff --git a/app/Models/Extensions/BaseAlbum.php b/app/Models/Extensions/BaseAlbum.php index 4fbcdc36e46..fda81129de8 100644 --- a/app/Models/Extensions/BaseAlbum.php +++ b/app/Models/Extensions/BaseAlbum.php @@ -6,6 +6,7 @@ use App\Contracts\Models\AbstractAlbum; use App\Contracts\Models\HasRandomID; use App\DTO\PhotoSortingCriterion; +use App\Enum\PhotoLayoutType; use App\Models\AccessPermission; use App\Models\BaseAlbumImpl; use App\Models\User; @@ -30,6 +31,7 @@ * @property string|null $description * @property bool $is_nsfw * @property string|null $copyright + * @property PhotoLayoutType|null $photo_layout * @property int $owner_id * @property User $owner * @property Collection $access_permissions @@ -58,7 +60,7 @@ abstract class BaseAlbum extends Model implements AbstractAlbum, HasRandomID public $incrementing = false; /** - * @return BelongsTo + * @return BelongsTo */ public function base_class(): BelongsTo { @@ -79,7 +81,7 @@ public function owner(): BelongsTo * Returns the relationship between an album and all users with whom * this album is shared. * - * @return BelongsToMany + * @return BelongsToMany */ public function shared_with(): BelongsToMany { @@ -89,7 +91,7 @@ public function shared_with(): BelongsToMany /** * Returns the relationship between an album and its associated permissions. * - * @return HasMany + * @return HasMany */ public function access_permissions(): HasMany { @@ -117,7 +119,7 @@ public function public_permissions(): AccessPermission|null } /** - * @return Relation<\App\Models\Photo> + * @return Relation<\App\Models\Photo,AbstractAlbum&Model,Collection> */ abstract public function photos(): Relation; diff --git a/app/Models/Extensions/HasBidirectionalRelationships.php b/app/Models/Extensions/HasBidirectionalRelationships.php index b29cc02fa80..eefed37ce79 100644 --- a/app/Models/Extensions/HasBidirectionalRelationships.php +++ b/app/Models/Extensions/HasBidirectionalRelationships.php @@ -69,7 +69,7 @@ protected function getRelationshipFromMethod($method): mixed * @param string|null $localKey * @param string|null $foreignMethodName * - * @return HasManyBidirectionally + * @return HasManyBidirectionally */ public function hasManyBidirectionally(string $related, ?string $foreignKey = null, ?string $localKey = null, ?string $foreignMethodName = null): HasManyBidirectionally { diff --git a/app/Models/Extensions/Thumb.php b/app/Models/Extensions/Thumb.php index 3e388e4e141..109b557fdd2 100644 --- a/app/Models/Extensions/Thumb.php +++ b/app/Models/Extensions/Thumb.php @@ -36,11 +36,11 @@ protected function __construct(string $id, string $type, string $thumbUrl, ?stri * Restricts the given relation for size variants such that only the * necessary variants for a thumbnail are selected. * - * @param HasMany $relation + * @param HasMany $relation * - * @return HasMany + * @return HasMany */ - public static function sizeVariantsFilter(HasMany $relation): HasMany + public static function sizeVariantsFilter(HasMany $relation): HasMany // @phpstan-ignore-line { $svAlbumThumbs = [SizeVariantType::THUMB, SizeVariantType::THUMB2X]; if (Features::active('vuejs')) { @@ -56,8 +56,11 @@ 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 SortingCriterion $sorting the sorting criterion + * @template TDeclaringModel of \Illuminate\Database\Eloquent\Model + * @template TResult + * + * @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 * @@ -69,7 +72,7 @@ public static function createFromQueryable(Relation|Builder $photoQueryable, Sor try { /** @var Photo|null $cover */ $cover = $photoQueryable - ->withOnly(['size_variants' => (fn (HasMany $r) => self::sizeVariantsFilter($r))]) + ->withOnly(['size_variants' => (fn ($r) => self::sizeVariantsFilter($r))]) ->orderBy('photos.' . ColumnSortingPhotoType::IS_STARRED->value, OrderSortingType::DESC->value) ->orderBy('photos.' . $sorting->column->value, $sorting->order->value) ->select(['photos.id', 'photos.type']) @@ -88,7 +91,10 @@ public static function createFromQueryable(Relation|Builder $photoQueryable, Sor * 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 + * @template TDeclaringModel of \Illuminate\Database\Eloquent\Model + * @template TResult + * + * @param Relation|Builder $photoQueryable the relation to or query for {@link Photo} which is used to pick a thumb * * @return Thumb|null the created thumbnail; null if the relation is empty * @@ -100,7 +106,7 @@ public static function createFromRandomQueryable(Relation|Builder $photoQueryabl try { /** @var Photo|null $cover */ $cover = $photoQueryable - ->withOnly(['size_variants' => (fn (HasMany $r) => self::sizeVariantsFilter($r))]) + ->withOnly(['size_variants' => (fn ($r) => self::sizeVariantsFilter($r))]) ->inRandomOrder() ->select(['photos.id', 'photos.type']) ->first(); diff --git a/app/Models/JobHistory.php b/app/Models/JobHistory.php index af67207ad44..5abc1f85c66 100644 --- a/app/Models/JobHistory.php +++ b/app/Models/JobHistory.php @@ -74,7 +74,7 @@ public function newEloquentBuilder($query): JobHistoryBuilder /** * Returns the relationship between an Job and its owner. * - * @return BelongsTo + * @return BelongsTo */ public function owner(): BelongsTo { diff --git a/app/Models/OauthCredential.php b/app/Models/OauthCredential.php index a6e01245c0e..3022cfd123a 100644 --- a/app/Models/OauthCredential.php +++ b/app/Models/OauthCredential.php @@ -47,7 +47,7 @@ class OauthCredential extends Model /** * Return the relationship between a Photo and its Album. * - * @return BelongsTo + * @return BelongsTo */ public function user(): BelongsTo { diff --git a/app/Models/Photo.php b/app/Models/Photo.php index 3ba1a4b1941..5197c1991db 100644 --- a/app/Models/Photo.php +++ b/app/Models/Photo.php @@ -184,7 +184,7 @@ public function newEloquentBuilder($query): PhotoBuilder /** * Return the relationship between a Photo and its Album. * - * @return BelongsTo + * @return BelongsTo */ public function album(): BelongsTo { @@ -194,7 +194,7 @@ public function album(): BelongsTo /** * Return the relationship between a Photo and its Owner. * - * @return BelongsTo + * @return BelongsTo */ public function owner(): BelongsTo { diff --git a/app/Models/SizeVariant.php b/app/Models/SizeVariant.php index ede9699683c..70cd37034a3 100644 --- a/app/Models/SizeVariant.php +++ b/app/Models/SizeVariant.php @@ -140,7 +140,7 @@ public function newEloquentBuilder($query): SizeVariantBuilder * Returns the association to the photo which this size variant belongs * to. * - * @return BelongsTo + * @return BelongsTo */ public function photo(): BelongsTo { @@ -151,7 +151,7 @@ public function photo(): BelongsTo * Returns the association to the symbolics links which point to this * size variant. * - * @return HasManyBidirectionally + * @return HasManyBidirectionally */ public function sym_links(): HasManyBidirectionally { diff --git a/app/Models/SymLink.php b/app/Models/SymLink.php index fad2f66e2c1..0378148c436 100644 --- a/app/Models/SymLink.php +++ b/app/Models/SymLink.php @@ -90,7 +90,7 @@ public function newEloquentBuilder($query): SymLinkBuilder } /** - * @return BelongsTo + * @return BelongsTo */ public function size_variant(): BelongsTo { diff --git a/app/Models/TagAlbum.php b/app/Models/TagAlbum.php index 99e7b26d60f..7a9cea33721 100644 --- a/app/Models/TagAlbum.php +++ b/app/Models/TagAlbum.php @@ -95,7 +95,7 @@ class TagAlbum extends BaseAlbum 'thumb', ]; - public function photos(): HasManyPhotosByTag + public function photos(): HasManyPhotosByTag // @phpstan-ignore-line { return new HasManyPhotosByTag($this); } diff --git a/app/Models/User.php b/app/Models/User.php index 7b64c8857dd..5fa6b74a20d 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -128,7 +128,7 @@ public function newEloquentBuilder($query): UserBuilder /** * Return the albums owned by the user. * - * @return HasMany + * @return HasMany */ public function albums(): HasMany { @@ -139,7 +139,7 @@ public function albums(): HasMany /** * Return the photos owned by the user. * - * @return HasMany + * @return HasMany */ public function photos(): HasMany { @@ -149,7 +149,7 @@ public function photos(): HasMany /** * Return the albums shared to the user. * - * @return BelongsToMany + * @return BelongsToMany */ public function shared(): BelongsToMany { @@ -164,7 +164,7 @@ public function shared(): BelongsToMany /** * Return the Oauth credentials owned by the user. * - * @return HasMany + * @return HasMany */ public function oauthCredentials(): HasMany { @@ -208,7 +208,7 @@ public function getNameAttribute(): string */ public function delete(): bool { - /** @var HasMany[] $ownershipRelations */ + /** @var HasMany[] $ownershipRelations */ $ownershipRelations = [$this->photos(), $this->albums()]; $hasAny = false; diff --git a/app/Relations/BaseHasManyPhotos.php b/app/Relations/BaseHasManyPhotos.php index 94efedfb756..939f8f38d36 100644 --- a/app/Relations/BaseHasManyPhotos.php +++ b/app/Relations/BaseHasManyPhotos.php @@ -5,9 +5,11 @@ use App\DTO\SortingCriterion; use App\Eloquent\FixedQueryBuilder; use App\Exceptions\Internal\InvalidOrderDirectionException; +use App\Models\Album; use App\Models\Extensions\BaseAlbum; use App\Models\Extensions\SortingDecorator; use App\Models\Photo; +use App\Models\TagAlbum; use App\Policies\PhotoQueryPolicy; use Illuminate\Database\Eloquent\Collection; use Illuminate\Database\Eloquent\Relations\Relation; @@ -17,13 +19,18 @@ * direct parent of the queried photos, but include the photo due to some * indirect condition. * - * @extends Relation + * @template TDeclaringModel of TagAlbum|Album + * + * @extends Relation> */ abstract class BaseHasManyPhotos extends Relation { protected PhotoQueryPolicy $photoQueryPolicy; - public function __construct(BaseAlbum $owningAlbum) + /** + * @param TagAlbum|Album $owningAlbum + */ + public function __construct(TagAlbum|Album $owningAlbum) { // Sic! We must initialize attributes of this class before we call // the parent constructor. @@ -48,6 +55,7 @@ public function __construct(BaseAlbum $owningAlbum) // Moreover, it is impossible to pass `null`. // As a work-around we store the owning album in our own attribute // `$owningAlbum` and always use that instead of `$parent`. + /** @var Album|TagAlbum $owningAlbum */ parent::__construct( // Sic! We also must load the album eagerly. // This relation is not used by albums which own the queried @@ -56,6 +64,7 @@ public function __construct(BaseAlbum $owningAlbum) // Hence, the actually owning albums of the photos are not // necessarily loaded. Photo::query()->with(['album', 'size_variants', 'size_variants.sym_links']), + // @phpstan-ignore-next-line $owningAlbum ); } @@ -83,8 +92,6 @@ public function getParent(): BaseAlbum * because it was set in the constructor as `$owningAlbum`. * * @noinspection PhpIncompatibleReturnTypeInspection - * - * @phpstan-ignore-next-line */ return $this->parent; } @@ -96,14 +103,14 @@ public function getParent(): BaseAlbum * In this case, the default value is an empty collection of * {@link \App\Models\Photo}. * - * @param array $models a list of owning models, i.e. a list of albums - * @param string $relation the name of the relation on the owning models + * @param array $models a list of owning models, i.e. a list of albums + * @param string $relation the name of the relation on the owning models * - * @return array always returns $models + * @return array always returns $models */ public function initRelation(array $models, $relation): array { - /** @var BaseAlbum $model */ + /** @var TagAlbum|Album $model */ foreach ($models as $model) { $model->setRelation($relation, $this->related->newCollection()); } diff --git a/app/Relations/HasAlbumThumb.php b/app/Relations/HasAlbumThumb.php index 9689517fcef..a3e2f0731cf 100644 --- a/app/Relations/HasAlbumThumb.php +++ b/app/Relations/HasAlbumThumb.php @@ -22,7 +22,7 @@ /** * @mixin Builder * - * @extends Relation + * @extends Relation * * @disregard P1037 */ diff --git a/app/Relations/HasManyBidirectionally.php b/app/Relations/HasManyBidirectionally.php index 08a53890685..8be72f32267 100644 --- a/app/Relations/HasManyBidirectionally.php +++ b/app/Relations/HasManyBidirectionally.php @@ -10,9 +10,9 @@ /** * @template TRelatedModel of \Illuminate\Database\Eloquent\Model - * @template TParentModel of \Illuminate\Database\Eloquent\Model + * @template TDeclaringModel of \Illuminate\Database\Eloquent\Model * - * @extends HasMany + * @extends HasMany */ class HasManyBidirectionally extends HasMany implements BidirectionalRelation { @@ -20,7 +20,7 @@ class HasManyBidirectionally extends HasMany implements BidirectionalRelation /** * @param Builder $query - * @param TParentModel $parent + * @param TDeclaringModel $parent * @param string $foreignKey * @param string $localKey * @param string $foreignMethodName @@ -29,7 +29,6 @@ class HasManyBidirectionally extends HasMany implements BidirectionalRelation */ public function __construct(Builder $query, Model $parent, string $foreignKey, string $localKey, string $foreignMethodName) { - /** @phpstan-ignore-next-line */ parent::__construct($query, $parent, $foreignKey, $localKey); $this->foreignMethodName = $foreignMethodName; } @@ -42,11 +41,11 @@ public function __construct(Builder $query, Model $parent, string $foreignKey, s * but additionally sets the reverse association of the child object * back to its parent object. * - * @param TParentModel[] $models an array of parent models + * @param TDeclaringModel[] $models an array of parent models * @param Collection $results the unified collection of all child models of all parent models * @param string $relation the name of the relation from the parent to the child models * - * @return array + * @return array */ public function match(array $models, Collection $results, $relation): array { diff --git a/app/Relations/HasManyChildPhotos.php b/app/Relations/HasManyChildPhotos.php index d55436d3d13..2e5fa3e530c 100644 --- a/app/Relations/HasManyChildPhotos.php +++ b/app/Relations/HasManyChildPhotos.php @@ -60,8 +60,6 @@ public function getParent(): Album * because it was set in the constructor as `$owningAlbum`. * * @noinspection PhpIncompatibleReturnTypeInspection - * - * @phpstan-ignore-next-line */ return $this->parent; } diff --git a/app/Relations/HasManyPhotosByTag.php b/app/Relations/HasManyPhotosByTag.php index ce9154f1671..6fd7294971a 100644 --- a/app/Relations/HasManyPhotosByTag.php +++ b/app/Relations/HasManyPhotosByTag.php @@ -10,7 +10,11 @@ use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Collection; -/** @disregard */ +/** + * @disregard + * + * @extends BaseHasManyPhotos + */ class HasManyPhotosByTag extends BaseHasManyPhotos { public function __construct(TagAlbum $owningAlbum) @@ -31,7 +35,6 @@ public function __construct(TagAlbum $owningAlbum) public function addConstraints(): void { if (static::$constraints) { - /** @phpstan-ignore-next-line */ $this->addEagerConstraints([$this->parent]); } } diff --git a/app/Relations/HasManyPhotosRecursively.php b/app/Relations/HasManyPhotosRecursively.php index d276a9acd0d..f6ba804b2a3 100644 --- a/app/Relations/HasManyPhotosRecursively.php +++ b/app/Relations/HasManyPhotosRecursively.php @@ -12,7 +12,11 @@ use Illuminate\Database\Eloquent\Collection; use Illuminate\Support\Facades\Gate; -/** @disregard */ +/** + * @disregard + * + * @extends BaseHasManyPhotos + */ class HasManyPhotosRecursively extends BaseHasManyPhotos { protected AlbumQueryPolicy $albumQueryPolicy; @@ -34,8 +38,6 @@ public function getParent(): Album * because it was set in the constructor as `$owningAlbum`. * * @noinspection PhpIncompatibleReturnTypeInspection - * - * @phpstan-ignore-next-line */ return $this->parent; } diff --git a/app/Relations/HasManySizeVariants.php b/app/Relations/HasManySizeVariants.php index c40996b329f..7018e2e56a5 100644 --- a/app/Relations/HasManySizeVariants.php +++ b/app/Relations/HasManySizeVariants.php @@ -16,7 +16,7 @@ use Illuminate\Database\Eloquent\Relations\HasMany; /** - * @extends HasMany + * @extends HasMany */ class HasManySizeVariants extends HasMany { @@ -24,7 +24,7 @@ public function __construct(Photo $owningPhoto) { parent::__construct( SizeVariant::query(), - $owningPhoto, /** @phpstan-ignore-line */ + $owningPhoto, 'photo_id', 'id' ); diff --git a/composer.lock b/composer.lock index c6f5caf63a2..a66a56234ec 100644 --- a/composer.lock +++ b/composer.lock @@ -867,16 +867,16 @@ }, { "name": "aws/aws-crt-php", - "version": "v1.2.6", + "version": "v1.2.7", "source": { "type": "git", "url": "https://github.com/awslabs/aws-crt-php.git", - "reference": "a63485b65b6b3367039306496d49737cf1995408" + "reference": "d71d9906c7bb63a28295447ba12e74723bd3730e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/awslabs/aws-crt-php/zipball/a63485b65b6b3367039306496d49737cf1995408", - "reference": "a63485b65b6b3367039306496d49737cf1995408", + "url": "https://api.github.com/repos/awslabs/aws-crt-php/zipball/d71d9906c7bb63a28295447ba12e74723bd3730e", + "reference": "d71d9906c7bb63a28295447ba12e74723bd3730e", "shasum": "" }, "require": { @@ -915,22 +915,22 @@ ], "support": { "issues": "https://github.com/awslabs/aws-crt-php/issues", - "source": "https://github.com/awslabs/aws-crt-php/tree/v1.2.6" + "source": "https://github.com/awslabs/aws-crt-php/tree/v1.2.7" }, - "time": "2024-06-13T17:21:28+00:00" + "time": "2024-10-18T22:15:13+00:00" }, { "name": "aws/aws-sdk-php", - "version": "3.324.2", + "version": "3.324.9", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "fea3d0ac8f96009cb87cf8166caba6558f26a0ab" + "reference": "e6cb2597e6365c420f42d218a3a4e82a20df700d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/fea3d0ac8f96009cb87cf8166caba6558f26a0ab", - "reference": "fea3d0ac8f96009cb87cf8166caba6558f26a0ab", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/e6cb2597e6365c420f42d218a3a4e82a20df700d", + "reference": "e6cb2597e6365c420f42d218a3a4e82a20df700d", "shasum": "" }, "require": { @@ -1013,9 +1013,9 @@ "support": { "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80", "issues": "https://github.com/aws/aws-sdk-php/issues", - "source": "https://github.com/aws/aws-sdk-php/tree/3.324.2" + "source": "https://github.com/aws/aws-sdk-php/tree/3.324.9" }, - "time": "2024-10-14T18:06:11+00:00" + "time": "2024-10-23T18:06:30+00:00" }, { "name": "bepsvpt/secure-headers", @@ -2736,16 +2736,16 @@ }, { "name": "guzzlehttp/promises", - "version": "2.0.3", + "version": "2.0.4", "source": { "type": "git", "url": "https://github.com/guzzle/promises.git", - "reference": "6ea8dd08867a2a42619d65c3deb2c0fcbf81c8f8" + "reference": "f9c436286ab2892c7db7be8c8da4ef61ccf7b455" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/6ea8dd08867a2a42619d65c3deb2c0fcbf81c8f8", - "reference": "6ea8dd08867a2a42619d65c3deb2c0fcbf81c8f8", + "url": "https://api.github.com/repos/guzzle/promises/zipball/f9c436286ab2892c7db7be8c8da4ef61ccf7b455", + "reference": "f9c436286ab2892c7db7be8c8da4ef61ccf7b455", "shasum": "" }, "require": { @@ -2799,7 +2799,7 @@ ], "support": { "issues": "https://github.com/guzzle/promises/issues", - "source": "https://github.com/guzzle/promises/tree/2.0.3" + "source": "https://github.com/guzzle/promises/tree/2.0.4" }, "funding": [ { @@ -2815,7 +2815,7 @@ "type": "tidelift" } ], - "time": "2024-07-18T10:29:17+00:00" + "time": "2024-10-17T10:06:22+00:00" }, { "name": "guzzlehttp/psr7", @@ -3441,16 +3441,16 @@ }, { "name": "laravel/framework", - "version": "v11.27.2", + "version": "v11.29.0", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "a51d1f2b771c542324a3d9b76a98b1bbc75c0ee9" + "reference": "425054512c362835ba9c0307561973c8eeac7385" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/a51d1f2b771c542324a3d9b76a98b1bbc75c0ee9", - "reference": "a51d1f2b771c542324a3d9b76a98b1bbc75c0ee9", + "url": "https://api.github.com/repos/laravel/framework/zipball/425054512c362835ba9c0307561973c8eeac7385", + "reference": "425054512c362835ba9c0307561973c8eeac7385", "shasum": "" }, "require": { @@ -3646,20 +3646,20 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2024-10-09T04:17:35+00:00" + "time": "2024-10-22T14:13:31+00:00" }, { "name": "laravel/prompts", - "version": "v0.3.0", + "version": "v0.3.1", "source": { "type": "git", "url": "https://github.com/laravel/prompts.git", - "reference": "ea57a2261093986721d4a5f4f9524d76f21f9fa0" + "reference": "0f3848a445562dac376b27968f753c65e7e1036e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/prompts/zipball/ea57a2261093986721d4a5f4f9524d76f21f9fa0", - "reference": "ea57a2261093986721d4a5f4f9524d76f21f9fa0", + "url": "https://api.github.com/repos/laravel/prompts/zipball/0f3848a445562dac376b27968f753c65e7e1036e", + "reference": "0f3848a445562dac376b27968f753c65e7e1036e", "shasum": "" }, "require": { @@ -3703,9 +3703,9 @@ "description": "Add beautiful and user-friendly forms to your command-line applications.", "support": { "issues": "https://github.com/laravel/prompts/issues", - "source": "https://github.com/laravel/prompts/tree/v0.3.0" + "source": "https://github.com/laravel/prompts/tree/v0.3.1" }, - "time": "2024-09-30T14:27:51+00:00" + "time": "2024-10-09T19:42:26+00:00" }, { "name": "laravel/serializable-closure", @@ -4751,16 +4751,16 @@ }, { "name": "lychee-org/nestedset", - "version": "v9.0.0", + "version": "v9.0.1", "source": { "type": "git", "url": "https://github.com/LycheeOrg/laravel-nestedset.git", - "reference": "1a1f200ac78cc495b1f3cd5c568e1e5dc7bbd179" + "reference": "dcd86fa1dfcc7343a4b0ceddbda32ba55b2b440a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/LycheeOrg/laravel-nestedset/zipball/1a1f200ac78cc495b1f3cd5c568e1e5dc7bbd179", - "reference": "1a1f200ac78cc495b1f3cd5c568e1e5dc7bbd179", + "url": "https://api.github.com/repos/LycheeOrg/laravel-nestedset/zipball/dcd86fa1dfcc7343a4b0ceddbda32ba55b2b440a", + "reference": "dcd86fa1dfcc7343a4b0ceddbda32ba55b2b440a", "shasum": "" }, "require": { @@ -4771,8 +4771,8 @@ }, "require-dev": { "friendsofphp/php-cs-fixer": "^3.3", + "larastan/larastan": "^2.0", "lychee-org/phpstan-lychee": "^1.0.4", - "nunomaduro/larastan": "^2.0", "orchestra/testbench": "^9.0", "php-parallel-lint/php-parallel-lint": "^1.2", "phpunit/phpunit": "^10.5" @@ -4812,9 +4812,9 @@ "nsm" ], "support": { - "source": "https://github.com/LycheeOrg/laravel-nestedset/tree/v9.0.0" + "source": "https://github.com/LycheeOrg/laravel-nestedset/tree/v9.0.1" }, - "time": "2024-06-10T16:33:01+00:00" + "time": "2024-10-23T21:46:18+00:00" }, { "name": "lychee-org/php-exif", @@ -5464,32 +5464,31 @@ }, { "name": "nunomaduro/termwind", - "version": "v2.1.0", + "version": "v2.2.0", "source": { "type": "git", "url": "https://github.com/nunomaduro/termwind.git", - "reference": "e5f21eade88689536c0cdad4c3cd75f3ed26e01a" + "reference": "42c84e4e8090766bbd6445d06cd6e57650626ea3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nunomaduro/termwind/zipball/e5f21eade88689536c0cdad4c3cd75f3ed26e01a", - "reference": "e5f21eade88689536c0cdad4c3cd75f3ed26e01a", + "url": "https://api.github.com/repos/nunomaduro/termwind/zipball/42c84e4e8090766bbd6445d06cd6e57650626ea3", + "reference": "42c84e4e8090766bbd6445d06cd6e57650626ea3", "shasum": "" }, "require": { "ext-mbstring": "*", "php": "^8.2", - "symfony/console": "^7.0.4" + "symfony/console": "^7.1.5" }, "require-dev": { - "ergebnis/phpstan-rules": "^2.2.0", - "illuminate/console": "^11.1.1", - "laravel/pint": "^1.15.0", - "mockery/mockery": "^1.6.11", - "pestphp/pest": "^2.34.6", - "phpstan/phpstan": "^1.10.66", - "phpstan/phpstan-strict-rules": "^1.5.2", - "symfony/var-dumper": "^7.0.4", + "illuminate/console": "^11.28.0", + "laravel/pint": "^1.18.1", + "mockery/mockery": "^1.6.12", + "pestphp/pest": "^2.36.0", + "phpstan/phpstan": "^1.12.6", + "phpstan/phpstan-strict-rules": "^1.6.1", + "symfony/var-dumper": "^7.1.5", "thecodingmachine/phpstan-strict-rules": "^1.0.0" }, "type": "library", @@ -5532,7 +5531,7 @@ ], "support": { "issues": "https://github.com/nunomaduro/termwind/issues", - "source": "https://github.com/nunomaduro/termwind/tree/v2.1.0" + "source": "https://github.com/nunomaduro/termwind/tree/v2.2.0" }, "funding": [ { @@ -5548,7 +5547,7 @@ "type": "github" } ], - "time": "2024-09-05T15:25:50+00:00" + "time": "2024-10-15T16:15:16+00:00" }, { "name": "opcodesio/log-viewer", @@ -8155,16 +8154,16 @@ }, { "name": "spatie/laravel-data", - "version": "4.10.1", + "version": "4.11.1", "source": { "type": "git", "url": "https://github.com/spatie/laravel-data.git", - "reference": "d3113c6bc03a6f1c241074d6f5832e05daa7ca77" + "reference": "df5b58baebae34475ca35338b4e9a131c9e2a8e0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-data/zipball/d3113c6bc03a6f1c241074d6f5832e05daa7ca77", - "reference": "d3113c6bc03a6f1c241074d6f5832e05daa7ca77", + "url": "https://api.github.com/repos/spatie/laravel-data/zipball/df5b58baebae34475ca35338b4e9a131c9e2a8e0", + "reference": "df5b58baebae34475ca35338b4e9a131c9e2a8e0", "shasum": "" }, "require": { @@ -8190,7 +8189,7 @@ "phpstan/extension-installer": "^1.1", "phpunit/phpunit": "^10.0", "spatie/invade": "^1.0", - "spatie/laravel-typescript-transformer": "^2.3", + "spatie/laravel-typescript-transformer": "^2.5", "spatie/pest-plugin-snapshots": "^2.1", "spatie/test-time": "^1.2" }, @@ -8227,7 +8226,7 @@ ], "support": { "issues": "https://github.com/spatie/laravel-data/issues", - "source": "https://github.com/spatie/laravel-data/tree/4.10.1" + "source": "https://github.com/spatie/laravel-data/tree/4.11.1" }, "funding": [ { @@ -8235,7 +8234,7 @@ "type": "github" } ], - "time": "2024-10-07T08:36:46+00:00" + "time": "2024-10-23T07:14:53+00:00" }, { "name": "spatie/laravel-feed", @@ -11699,16 +11698,16 @@ "packages-dev": [ { "name": "barryvdh/laravel-debugbar", - "version": "v3.14.3", + "version": "v3.14.6", "source": { "type": "git", "url": "https://github.com/barryvdh/laravel-debugbar.git", - "reference": "c0bee7c08ae2429e4a9ed2bc75679b012db6e3bd" + "reference": "14e4517bd49130d6119228107eb21ae47ae120ab" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/c0bee7c08ae2429e4a9ed2bc75679b012db6e3bd", - "reference": "c0bee7c08ae2429e4a9ed2bc75679b012db6e3bd", + "url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/14e4517bd49130d6119228107eb21ae47ae120ab", + "reference": "14e4517bd49130d6119228107eb21ae47ae120ab", "shasum": "" }, "require": { @@ -11767,7 +11766,7 @@ ], "support": { "issues": "https://github.com/barryvdh/laravel-debugbar/issues", - "source": "https://github.com/barryvdh/laravel-debugbar/tree/v3.14.3" + "source": "https://github.com/barryvdh/laravel-debugbar/tree/v3.14.6" }, "funding": [ { @@ -11779,41 +11778,41 @@ "type": "github" } ], - "time": "2024-10-02T09:17:49+00:00" + "time": "2024-10-18T13:15:12+00:00" }, { "name": "barryvdh/laravel-ide-helper", - "version": "v3.1.0", + "version": "v3.2.0", "source": { "type": "git", "url": "https://github.com/barryvdh/laravel-ide-helper.git", - "reference": "591e7d665fbab8a3b682e451641706341573eb80" + "reference": "7956ccb4943f8532d008c17a1094b34bb6394d56" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/barryvdh/laravel-ide-helper/zipball/591e7d665fbab8a3b682e451641706341573eb80", - "reference": "591e7d665fbab8a3b682e451641706341573eb80", + "url": "https://api.github.com/repos/barryvdh/laravel-ide-helper/zipball/7956ccb4943f8532d008c17a1094b34bb6394d56", + "reference": "7956ccb4943f8532d008c17a1094b34bb6394d56", "shasum": "" }, "require": { - "barryvdh/reflection-docblock": "^2.1.1", + "barryvdh/reflection-docblock": "^2.1.2", "composer/class-map-generator": "^1.0", "ext-json": "*", - "illuminate/console": "^10 || ^11", - "illuminate/database": "^10.38 || ^11", - "illuminate/filesystem": "^10 || ^11", - "illuminate/support": "^10 || ^11", + "illuminate/console": "^11.15", + "illuminate/database": "^11.15", + "illuminate/filesystem": "^11.15", + "illuminate/support": "^11.15", "nikic/php-parser": "^4.18 || ^5", - "php": "^8.1", + "php": "^8.2", "phpdocumentor/type-resolver": "^1.1.0" }, "require-dev": { "ext-pdo_sqlite": "*", "friendsofphp/php-cs-fixer": "^3", - "illuminate/config": "^9 || ^10 || ^11", - "illuminate/view": "^9 || ^10 || ^11", + "illuminate/config": "^11.15", + "illuminate/view": "^11.15", "mockery/mockery": "^1.4", - "orchestra/testbench": "^8 || ^9", + "orchestra/testbench": "^9.2", "phpunit/phpunit": "^10.5", "spatie/phpunit-snapshot-assertions": "^4 || ^5", "vimeo/psalm": "^5.4" @@ -11824,7 +11823,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1-dev" + "dev-master": "3.2-dev" }, "laravel": { "providers": [ @@ -11861,7 +11860,7 @@ ], "support": { "issues": "https://github.com/barryvdh/laravel-ide-helper/issues", - "source": "https://github.com/barryvdh/laravel-ide-helper/tree/v3.1.0" + "source": "https://github.com/barryvdh/laravel-ide-helper/tree/v3.2.0" }, "funding": [ { @@ -11873,20 +11872,20 @@ "type": "github" } ], - "time": "2024-07-12T14:20:51+00:00" + "time": "2024-10-17T16:43:13+00:00" }, { "name": "barryvdh/reflection-docblock", - "version": "v2.1.1", + "version": "v2.1.3", "source": { "type": "git", "url": "https://github.com/barryvdh/ReflectionDocBlock.git", - "reference": "e6811e927f0ecc37cc4deaa6627033150343e597" + "reference": "c6fad15f7c878be21650c51e1f841bca7e49752e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/barryvdh/ReflectionDocBlock/zipball/e6811e927f0ecc37cc4deaa6627033150343e597", - "reference": "e6811e927f0ecc37cc4deaa6627033150343e597", + "url": "https://api.github.com/repos/barryvdh/ReflectionDocBlock/zipball/c6fad15f7c878be21650c51e1f841bca7e49752e", + "reference": "c6fad15f7c878be21650c51e1f841bca7e49752e", "shasum": "" }, "require": { @@ -11923,22 +11922,22 @@ } ], "support": { - "source": "https://github.com/barryvdh/ReflectionDocBlock/tree/v2.1.1" + "source": "https://github.com/barryvdh/ReflectionDocBlock/tree/v2.1.3" }, - "time": "2023-06-14T05:06:27+00:00" + "time": "2024-10-23T11:41:03+00:00" }, { "name": "brianium/paratest", - "version": "v7.4.7", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/paratestphp/paratest.git", - "reference": "70573947888f65dc45fc7a75f883589c7d6a1353" + "reference": "cf16fcbb9b8107a7df6b97e497fc91e819774d8b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/paratestphp/paratest/zipball/70573947888f65dc45fc7a75f883589c7d6a1353", - "reference": "70573947888f65dc45fc7a75f883589c7d6a1353", + "url": "https://api.github.com/repos/paratestphp/paratest/zipball/cf16fcbb9b8107a7df6b97e497fc91e819774d8b", + "reference": "cf16fcbb9b8107a7df6b97e497fc91e819774d8b", "shasum": "" }, "require": { @@ -11948,25 +11947,25 @@ "ext-simplexml": "*", "fidry/cpu-core-counter": "^1.2.0", "jean85/pretty-package-versions": "^2.0.6", - "php": "~8.2.0 || ~8.3.0", + "php": "~8.2.0 || ~8.3.0 || ~8.4.0", "phpunit/php-code-coverage": "^10.1.16", "phpunit/php-file-iterator": "^4.1.0", "phpunit/php-timer": "^6.0.0", - "phpunit/phpunit": "^10.5.33", + "phpunit/phpunit": "^10.5.36", "sebastian/environment": "^6.1.0", - "symfony/console": "^6.4.7 || ^7.1.4", - "symfony/process": "^6.4.7 || ^7.1.3" + "symfony/console": "^6.4.7 || ^7.1.5", + "symfony/process": "^6.4.7 || ^7.1.5" }, "require-dev": { "doctrine/coding-standard": "^12.0.0", "ext-pcov": "*", "ext-posix": "*", - "phpstan/phpstan": "^1.12.3", - "phpstan/phpstan-deprecation-rules": "^1.2.0", + "phpstan/phpstan": "^1.12.6", + "phpstan/phpstan-deprecation-rules": "^1.2.1", "phpstan/phpstan-phpunit": "^1.4.0", - "phpstan/phpstan-strict-rules": "^1.6.0", - "squizlabs/php_codesniffer": "^3.10.2", - "symfony/filesystem": "^6.4.3 || ^7.1.2" + "phpstan/phpstan-strict-rules": "^1.6.1", + "squizlabs/php_codesniffer": "^3.10.3", + "symfony/filesystem": "^6.4.3 || ^7.1.5" }, "bin": [ "bin/paratest", @@ -12006,7 +12005,7 @@ ], "support": { "issues": "https://github.com/paratestphp/paratest/issues", - "source": "https://github.com/paratestphp/paratest/tree/v7.4.7" + "source": "https://github.com/paratestphp/paratest/tree/v7.4.8" }, "funding": [ { @@ -12018,7 +12017,7 @@ "type": "paypal" } ], - "time": "2024-10-14T07:14:10+00:00" + "time": "2024-10-15T12:45:19+00:00" }, { "name": "clue/ndjson-react", @@ -12868,36 +12867,37 @@ }, { "name": "larastan/larastan", - "version": "v2.9.8", + "version": "v2.9.9", "source": { "type": "git", "url": "https://github.com/larastan/larastan.git", - "reference": "340badd89b0eb5bddbc503a4829c08cf9a2819d7" + "reference": "148faa138f0d8acb7d85f4a55693d3e13b6048d2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/larastan/larastan/zipball/340badd89b0eb5bddbc503a4829c08cf9a2819d7", - "reference": "340badd89b0eb5bddbc503a4829c08cf9a2819d7", + "url": "https://api.github.com/repos/larastan/larastan/zipball/148faa138f0d8acb7d85f4a55693d3e13b6048d2", + "reference": "148faa138f0d8acb7d85f4a55693d3e13b6048d2", "shasum": "" }, "require": { "ext-json": "*", - "illuminate/console": "^9.52.16 || ^10.28.0 || ^11.0", - "illuminate/container": "^9.52.16 || ^10.28.0 || ^11.0", - "illuminate/contracts": "^9.52.16 || ^10.28.0 || ^11.0", - "illuminate/database": "^9.52.16 || ^10.28.0 || ^11.0", - "illuminate/http": "^9.52.16 || ^10.28.0 || ^11.0", - "illuminate/pipeline": "^9.52.16 || ^10.28.0 || ^11.0", - "illuminate/support": "^9.52.16 || ^10.28.0 || ^11.0", + "illuminate/console": "^9.52.16 || ^10.28.0 || ^11.16", + "illuminate/container": "^9.52.16 || ^10.28.0 || ^11.16", + "illuminate/contracts": "^9.52.16 || ^10.28.0 || ^11.16", + "illuminate/database": "^9.52.16 || ^10.28.0 || ^11.16", + "illuminate/http": "^9.52.16 || ^10.28.0 || ^11.16", + "illuminate/pipeline": "^9.52.16 || ^10.28.0 || ^11.16", + "illuminate/support": "^9.52.16 || ^10.28.0 || ^11.16", "php": "^8.0.2", "phpmyadmin/sql-parser": "^5.9.0", - "phpstan/phpstan": "^1.11.2" + "phpstan/phpstan": "^1.12.5" }, "require-dev": { "doctrine/coding-standard": "^12.0", "nikic/php-parser": "^4.19.1", "orchestra/canvas": "^7.11.1 || ^8.11.0 || ^9.0.2", "orchestra/testbench": "^7.33.0 || ^8.13.0 || ^9.0.3", + "phpstan/phpstan-deprecation-rules": "^1.2", "phpunit/phpunit": "^9.6.13 || ^10.5.16" }, "suggest": { @@ -12946,7 +12946,7 @@ ], "support": { "issues": "https://github.com/larastan/larastan/issues", - "source": "https://github.com/larastan/larastan/tree/v2.9.8" + "source": "https://github.com/larastan/larastan/tree/v2.9.9" }, "funding": [ { @@ -12966,20 +12966,20 @@ "type": "patreon" } ], - "time": "2024-07-06T17:46:02+00:00" + "time": "2024-10-15T19:41:22+00:00" }, { "name": "lychee-org/phpstan-lychee", - "version": "v1.0.4", + "version": "v1.0.5", "source": { "type": "git", "url": "https://github.com/LycheeOrg/phpstan-lychee.git", - "reference": "4f04a10680fbe50884159b0ef8c06a670117f16d" + "reference": "fcdd430577c26178da59809db4e1dd0f0f12fc5e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/LycheeOrg/phpstan-lychee/zipball/4f04a10680fbe50884159b0ef8c06a670117f16d", - "reference": "4f04a10680fbe50884159b0ef8c06a670117f16d", + "url": "https://api.github.com/repos/LycheeOrg/phpstan-lychee/zipball/fcdd430577c26178da59809db4e1dd0f0f12fc5e", + "reference": "fcdd430577c26178da59809db4e1dd0f0f12fc5e", "shasum": "" }, "require": { @@ -13012,10 +13012,10 @@ ], "description": "Set of rules for all Lychee related php repo", "support": { - "source": "https://github.com/LycheeOrg/phpstan-lychee/tree/v1.0.4", + "source": "https://github.com/LycheeOrg/phpstan-lychee/tree/v1.0.5", "issues": "https://github.com/LycheeOrg/phpstan-lychee/issues" }, - "time": "2024-05-25T20:57:05+00:00" + "time": "2024-10-23T21:13:51+00:00" }, { "name": "maximebf/debugbar", @@ -13230,23 +13230,23 @@ }, { "name": "nunomaduro/collision", - "version": "v8.4.0", + "version": "v8.5.0", "source": { "type": "git", "url": "https://github.com/nunomaduro/collision.git", - "reference": "e7d1aa8ed753f63fa816932bbc89678238843b4a" + "reference": "f5c101b929c958e849a633283adff296ed5f38f5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nunomaduro/collision/zipball/e7d1aa8ed753f63fa816932bbc89678238843b4a", - "reference": "e7d1aa8ed753f63fa816932bbc89678238843b4a", + "url": "https://api.github.com/repos/nunomaduro/collision/zipball/f5c101b929c958e849a633283adff296ed5f38f5", + "reference": "f5c101b929c958e849a633283adff296ed5f38f5", "shasum": "" }, "require": { - "filp/whoops": "^2.15.4", - "nunomaduro/termwind": "^2.0.1", + "filp/whoops": "^2.16.0", + "nunomaduro/termwind": "^2.1.0", "php": "^8.2.0", - "symfony/console": "^7.1.3" + "symfony/console": "^7.1.5" }, "conflict": { "laravel/framework": "<11.0.0 || >=12.0.0", @@ -13254,14 +13254,14 @@ }, "require-dev": { "larastan/larastan": "^2.9.8", - "laravel/framework": "^11.19.0", - "laravel/pint": "^1.17.1", - "laravel/sail": "^1.31.0", - "laravel/sanctum": "^4.0.2", - "laravel/tinker": "^2.9.0", - "orchestra/testbench-core": "^9.2.3", - "pestphp/pest": "^2.35.0 || ^3.0.0", - "sebastian/environment": "^6.1.0 || ^7.0.0" + "laravel/framework": "^11.28.0", + "laravel/pint": "^1.18.1", + "laravel/sail": "^1.36.0", + "laravel/sanctum": "^4.0.3", + "laravel/tinker": "^2.10.0", + "orchestra/testbench-core": "^9.5.3", + "pestphp/pest": "^2.36.0 || ^3.4.0", + "sebastian/environment": "^6.1.0 || ^7.2.0" }, "type": "library", "extra": { @@ -13323,7 +13323,7 @@ "type": "patreon" } ], - "time": "2024-08-03T15:32:23+00:00" + "time": "2024-10-15T16:06:32+00:00" }, { "name": "phar-io/manifest", @@ -13593,16 +13593,16 @@ }, { "name": "phpstan/phpstan", - "version": "1.12.6", + "version": "1.12.7", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "dc4d2f145a88ea7141ae698effd64d9df46527ae" + "reference": "dc2b9976bd8b0f84ec9b0e50cc35378551de7af0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/dc4d2f145a88ea7141ae698effd64d9df46527ae", - "reference": "dc4d2f145a88ea7141ae698effd64d9df46527ae", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/dc2b9976bd8b0f84ec9b0e50cc35378551de7af0", + "reference": "dc2b9976bd8b0f84ec9b0e50cc35378551de7af0", "shasum": "" }, "require": { @@ -13647,7 +13647,7 @@ "type": "github" } ], - "time": "2024-10-06T15:03:59+00:00" + "time": "2024-10-18T11:12:07+00:00" }, { "name": "phpstan/phpstan-deprecation-rules", @@ -14068,16 +14068,16 @@ }, { "name": "phpunit/phpunit", - "version": "10.5.36", + "version": "10.5.37", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "aa0a8ce701ea7ee314b0dfaa8970dc94f3f8c870" + "reference": "c7cffa0efa2b70c22366523e6d804c9419eb2400" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/aa0a8ce701ea7ee314b0dfaa8970dc94f3f8c870", - "reference": "aa0a8ce701ea7ee314b0dfaa8970dc94f3f8c870", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/c7cffa0efa2b70c22366523e6d804c9419eb2400", + "reference": "c7cffa0efa2b70c22366523e6d804c9419eb2400", "shasum": "" }, "require": { @@ -14098,7 +14098,7 @@ "phpunit/php-timer": "^6.0.0", "sebastian/cli-parser": "^2.0.1", "sebastian/code-unit": "^2.0.0", - "sebastian/comparator": "^5.0.2", + "sebastian/comparator": "^5.0.3", "sebastian/diff": "^5.1.1", "sebastian/environment": "^6.1.0", "sebastian/exporter": "^5.1.2", @@ -14149,7 +14149,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.36" + "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.37" }, "funding": [ { @@ -14165,7 +14165,7 @@ "type": "tidelift" } ], - "time": "2024-10-08T15:36:51+00:00" + "time": "2024-10-19T13:03:41+00:00" }, { "name": "react/cache", @@ -14867,16 +14867,16 @@ }, { "name": "sebastian/comparator", - "version": "5.0.2", + "version": "5.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "2d3e04c3b4c1e84a5e7382221ad8883c8fbc4f53" + "reference": "a18251eb0b7a2dcd2f7aa3d6078b18545ef0558e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2d3e04c3b4c1e84a5e7382221ad8883c8fbc4f53", - "reference": "2d3e04c3b4c1e84a5e7382221ad8883c8fbc4f53", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/a18251eb0b7a2dcd2f7aa3d6078b18545ef0558e", + "reference": "a18251eb0b7a2dcd2f7aa3d6078b18545ef0558e", "shasum": "" }, "require": { @@ -14887,7 +14887,7 @@ "sebastian/exporter": "^5.0" }, "require-dev": { - "phpunit/phpunit": "^10.4" + "phpunit/phpunit": "^10.5" }, "type": "library", "extra": { @@ -14932,7 +14932,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", "security": "https://github.com/sebastianbergmann/comparator/security/policy", - "source": "https://github.com/sebastianbergmann/comparator/tree/5.0.2" + "source": "https://github.com/sebastianbergmann/comparator/tree/5.0.3" }, "funding": [ { @@ -14940,7 +14940,7 @@ "type": "github" } ], - "time": "2024-08-12T06:03:08+00:00" + "time": "2024-10-18T14:56:07+00:00" }, { "name": "sebastian/complexity", diff --git a/config/app.php b/config/app.php index b8fc30b3b99..62ff18af14f 100644 --- a/config/app.php +++ b/config/app.php @@ -15,7 +15,7 @@ if (!function_exists('renv')) { function renv(string $cst, ?string $default = null): string { - return rtrim(env($cst, $default) ?? '', '/'); + return rtrim((string) (env($cst, $default) ?? ''), '/'); } } @@ -76,7 +76,7 @@ function renv(string $cst, ?string $default = null): string 'url' => renv('APP_URL', 'http://localhost'), - 'dir_url' => env('APP_DIR', '') === '' ? '' : ('/' . trim(env('APP_DIR'), '/')), + 'dir_url' => env('APP_DIR', '') === '' ? '' : ('/' . trim((string) (env('APP_DIR') ?? ''), '/')), 'asset_url' => null, @@ -151,7 +151,7 @@ function renv(string $cst, ?string $default = null): string | Allows to define class names of diagnostics checks that will be skipped. | */ - 'skip_diagnostics_checks' => explode(',', env('SKIP_DIAGNOSTICS_CHECKS', '')), + 'skip_diagnostics_checks' => explode(',', (string) env('SKIP_DIAGNOSTICS_CHECKS', '')), /* |-------------------------------------------------------------------------- diff --git a/config/cache.php b/config/cache.php index da158160bca..2e68fee947a 100644 --- a/config/cache.php +++ b/config/cache.php @@ -102,5 +102,5 @@ | */ - 'prefix' => env('CACHE_PREFIX', Str::slug(env('APP_NAME', 'Lychee'), '_') . '_cache_'), + 'prefix' => env('CACHE_PREFIX', Str::slug((string) env('APP_NAME', 'Lychee'), '_') . '_cache_'), ]; diff --git a/config/database.php b/config/database.php index ada6f697b1f..da0afd5aa7b 100644 --- a/config/database.php +++ b/config/database.php @@ -183,7 +183,7 @@ 'options' => [ 'cluster' => env('REDIS_CLUSTER', 'redis'), - 'prefix' => env('REDIS_PREFIX', Str::slug(env('APP_NAME', 'Lychee'), '_') . '_database_'), + 'prefix' => env('REDIS_PREFIX', Str::slug((string) env('APP_NAME', 'Lychee'), '_') . '_database_'), ], 'default' => [ diff --git a/config/filesystems.php b/config/filesystems.php index 5839f3d373b..b79f3149d55 100644 --- a/config/filesystems.php +++ b/config/filesystems.php @@ -11,7 +11,7 @@ if (!function_exists('renv')) { function renv(string $cst, ?string $default = null): string { - return rtrim(env($cst, $default) ?? '', '/'); + return rtrim((string) (env($cst, $default) ?? ''), '/'); } } @@ -25,7 +25,7 @@ function renv(string $cst, ?string $default = null): string if (!function_exists('renv_cond')) { function renv_cond(string $cst): string { - return env($cst, '') === '' ? '' : ('/' . trim(env($cst), '/')); + return env($cst, '') === '' ? '' : ('/' . trim((string) env($cst), '/')); } } @@ -73,7 +73,7 @@ function renv_cond(string $cst): string // Lychee uses the disk "images" to store the media files 'images' => [ 'driver' => 'local', - 'root' => env('LYCHEE_UPLOADS', public_path(env('LYCHEE_UPLOADS_DIR', 'uploads/'))), + 'root' => env('LYCHEE_UPLOADS', public_path((string) env('LYCHEE_UPLOADS_DIR', 'uploads/'))), 'url' => env('LYCHEE_UPLOADS_URL', '') !== '' ? renv('LYCHEE_UPLOADS_URL') : (renv('APP_URL', '') . renv_cond('APP_DIR') . '/' . renv('LYCHEE_UPLOADS_DIR', 'uploads')), diff --git a/config/log-viewer.php b/config/log-viewer.php index 8ad54748e90..00118ba58f3 100644 --- a/config/log-viewer.php +++ b/config/log-viewer.php @@ -5,7 +5,7 @@ if (!function_exists('renv')) { function renv(string $cst, ?string $default = null): string { - return rtrim(env($cst, $default) ?? '', '/'); + return rtrim((string) (env($cst, $default) ?? ''), '/'); } } @@ -19,7 +19,7 @@ function renv(string $cst, ?string $default = null): string if (!function_exists('renv_cond')) { function renv_cond(string $cst): string { - return env($cst, '') === '' ? '' : ('/' . trim(env($cst), '/')); + return env($cst, '') === '' ? '' : ('/' . trim((string) env($cst), '/')); } } @@ -66,7 +66,7 @@ function renv_cond(string $cst): string | */ - 'back_to_system_url' => renv('APP_URL', 'http://localhost') . renv_cond('APP_DIR'), + 'back_to_system_url' => renv('APP_URL', 'http://localhost') . renv_cond('APP_DIR') . '/gallery', 'back_to_system_label' => null, // Displayed by default: "Back to {{ app.name }}" @@ -128,7 +128,7 @@ function renv_cond(string $cst): string 'hosts' => [ 'local' => [ - 'name' => ucfirst(env('APP_ENV', 'local')), + 'name' => ucfirst((string) env('APP_ENV', 'local')), ], // 'staging' => [ diff --git a/config/secure-headers.php b/config/secure-headers.php index 74ce5c58706..e537c5ca534 100644 --- a/config/secure-headers.php +++ b/config/secure-headers.php @@ -349,7 +349,7 @@ // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/connect-src 'connect-src' => array_merge( ['https://lycheeorg.github.io/update.json'], - explode(',', env('SECURITY_HEADER_CSP_CONNECT_SRC', '')) + explode(',', (string) env('SECURITY_HEADER_CSP_CONNECT_SRC', '')) ), // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/default-src @@ -488,7 +488,7 @@ 'allow' => array_merge( ['https://www.dropbox.com/static/api/1/dropins.js'], - explode(',', env('SECURITY_HEADER_SCRIPT_SRC_ALLOW', '')) + explode(',', (string) env('SECURITY_HEADER_SCRIPT_SRC_ALLOW', '')) ), 'schemes' => [ diff --git a/config/session.php b/config/session.php index 4a577c124f0..7aa69178ad4 100644 --- a/config/session.php +++ b/config/session.php @@ -128,7 +128,7 @@ 'cookie' => env( 'SESSION_COOKIE', - Str::slug(env('APP_NAME', 'Lychee'), '_') . '_session' + Str::slug((string) env('APP_NAME', 'Lychee'), '_') . '_session' ), /* diff --git a/database/migrations/2024_10_20_173904_add_photo_layout_per_album.php b/database/migrations/2024_10_20_173904_add_photo_layout_per_album.php new file mode 100644 index 00000000000..8de3f8b9d5a --- /dev/null +++ b/database/migrations/2024_10_20_173904_add_photo_layout_per_album.php @@ -0,0 +1,30 @@ +string(self::PHOTO_LAYOUT_COLUMN_NAME, 20)->nullable()->default(null)->after('copyright'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table(self::BASE_ALBUM, function (Blueprint $table) { + $table->dropColumn(self::PHOTO_LAYOUT_COLUMN_NAME); + }); + } +}; diff --git a/database/migrations/2024_10_23_222857_change_header.php b/database/migrations/2024_10_23_222857_change_header.php new file mode 100644 index 00000000000..932abcc15d0 --- /dev/null +++ b/database/migrations/2024_10_23_222857_change_header.php @@ -0,0 +1,22 @@ +where('value', '=', 'Lychee v5')->update(['value' => 'Lychee v6']); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + DB::table('configs')->where('value', '=', 'Lychee v6')->update(['value' => 'Lychee v5']); + } +}; diff --git a/database/migrations/2024_10_23_225332_warning_html_content.php b/database/migrations/2024_10_23_225332_warning_html_content.php new file mode 100644 index 00000000000..b658bd0fb90 --- /dev/null +++ b/database/migrations/2024_10_23_225332_warning_html_content.php @@ -0,0 +1,21 @@ +whereIn('key', ['nsfw_banner_override', 'footer_additional_text'])->update(['details' => ' Unsanitized html field.']); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + DB::table('configs')->whereIn('key', ['nsfw_banner_override', 'footer_additional_text'])->update(['details' => '']); + } +}; diff --git a/database/migrations/TemporaryModels/NestedSetForAlbums_AlbumModel.php b/database/migrations/TemporaryModels/NestedSetForAlbums_AlbumModel.php index b22a90cc798..2d1d6e87a53 100644 --- a/database/migrations/TemporaryModels/NestedSetForAlbums_AlbumModel.php +++ b/database/migrations/TemporaryModels/NestedSetForAlbums_AlbumModel.php @@ -18,11 +18,11 @@ * Unfortunately, we need the `fixTree()` algorithm and there is no * implementation which uses low-level DB queries. * - * @implements Node + * @implements Node */ class NestedSetForAlbums_AlbumModel extends Model implements Node { - /** @phpstan-use NodeTrait */ + /** @phpstan-use NodeTrait */ use NodeTrait; protected $table = 'albums'; diff --git a/database/migrations/TemporaryModels/RefactorAlbumModel_AlbumModel.php b/database/migrations/TemporaryModels/RefactorAlbumModel_AlbumModel.php index df1ff72b782..340333b7805 100644 --- a/database/migrations/TemporaryModels/RefactorAlbumModel_AlbumModel.php +++ b/database/migrations/TemporaryModels/RefactorAlbumModel_AlbumModel.php @@ -18,11 +18,11 @@ * Unfortunately, we need the `fixTree()` algorithm and there is no * implementation which uses low-level DB queries. * - * @implements Node + * @implements Node */ class RefactorAlbumModel_AlbumModel extends Model implements Node { - /** @phpstan-use NodeTrait */ + /** @phpstan-use NodeTrait */ use NodeTrait; protected $table = 'albums'; diff --git a/package-lock.json b/package-lock.json index 0181bed437d..f90e7b282cf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -70,27 +70,27 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.7.tgz", - "integrity": "sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.7.tgz", - "integrity": "sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.25.8", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.8.tgz", - "integrity": "sha512-HcttkxzdPucv3nNFmfOOMfFf64KgdJVqm1KaCm25dPGMLElo9nsLvXeJECQg8UzPuBGLyTSA0ZzqCtDSzKTEoQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.9.tgz", + "integrity": "sha512-aI3jjAAO1fh7vY/pBGsn1i9LDbRP43+asrRlkPuTXW5yHXtd1NgTEMudbBoDDxrf1daEEfPJqR+JBMakzrR4Dg==", "dependencies": { - "@babel/types": "^7.25.8" + "@babel/types": "^7.25.9" }, "bin": { "parser": "bin/babel-parser.js" @@ -100,13 +100,12 @@ } }, "node_modules/@babel/types": { - "version": "7.25.8", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.8.tgz", - "integrity": "sha512-JWtuCu8VQsMladxVz/P4HzHUGCAwpuqacmowgXFs5XjxIgKuNjnLokQzuVjlTvIzODaDmpjT3oxcC48vyk9EWg==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.9.tgz", + "integrity": "sha512-OwS2CM5KocvQ/k7dFJa8i5bNGJP0hXWfVCfDkqRFP1IreH1JDC7wG6eCYCi0+McbfT8OR/kNqsI0UU0xP9H6PQ==", "dependencies": { - "@babel/helper-string-parser": "^7.25.7", - "@babel/helper-validator-identifier": "^7.25.7", - "to-fast-properties": "^2.0.0" + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -925,9 +924,9 @@ } }, "node_modules/@primevue/core": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@primevue/core/-/core-4.1.0.tgz", - "integrity": "sha512-YulYm+PtoYSyLv/pNl3oyjvN+C9Ba/RSpW3bZAVkMRz9SWSA6lj2QaN+/9uxhokWZPL63zCHsHzIBV5YMvZshQ==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@primevue/core/-/core-4.1.1.tgz", + "integrity": "sha512-jUDrTh3g0FskTdD6rCCsoWfxKky0R7959p7vnaNYI6wMLreaTL3yC3nzYlEniIpb+F51Sm3KJ1eSJBN6DnSB8Q==", "dependencies": { "@primeuix/styled": "^0.2.0", "@primeuix/utils": "^0.2.0" @@ -940,21 +939,21 @@ } }, "node_modules/@primevue/icons": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@primevue/icons/-/icons-4.1.0.tgz", - "integrity": "sha512-npY8Jy3HX1+Qbv1jCRdAevOcOj355b0x1Wmepa7omhgQFIUVs2o18HGohYml4HJpmEAu6aKnUIhhodFMuglMeQ==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@primevue/icons/-/icons-4.1.1.tgz", + "integrity": "sha512-Ybeb+AHUsVybITuYNwS7goqWcXLLgCDSiCPoymyYwYkzn5qLakvJbQH1EX8lGOsrvqK0hG+s+n7Wm2MHJ8A72w==", "dependencies": { "@primeuix/utils": "^0.2.0", - "@primevue/core": "4.1.0" + "@primevue/core": "4.1.1" }, "engines": { "node": ">=12.11.0" } }, "node_modules/@primevue/themes": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@primevue/themes/-/themes-4.1.0.tgz", - "integrity": "sha512-EfAvNAI78rq8uPA+XFmHlACUXj2YpSM+PFjnFrTwHjqdSkmrBDweysNEI0p+/rj7l3rZBZLedEvbHcjP+9iumA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@primevue/themes/-/themes-4.1.1.tgz", + "integrity": "sha512-ec2gBN2vP0ydGtGAzC0nYCFqYN7CzvXxnlJqcvcPIo3rP/pcdj+FkzAe3y2DMG3OorYtqdzoyGtBefQrx3v5ag==", "dependencies": { "@primeuix/styled": "^0.2.0" }, @@ -1208,9 +1207,9 @@ "integrity": "sha512-q2ybP0u0NVj87oMnGZOGxY2iUN8ddr48zPOBHBdbOLpsMTA/keGj+93ou+OMCnJk0xewzlNIaVEkxM6VBD3E2w==" }, "node_modules/@types/leaflet": { - "version": "1.9.12", - "resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.9.12.tgz", - "integrity": "sha512-BK7XS+NyRI291HIo0HCfE18Lp8oA30H1gpi1tf0mF3TgiCEzanQjOqNZ4x126SXzzi2oNSZhZ5axJp1k0iM6jg==", + "version": "1.9.14", + "resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.9.14.tgz", + "integrity": "sha512-sx2q6MDJaajwhKeVgPSvqXd8rhNJSTA3tMidQGduZn9S6WBYxDkCpSpV5xXEmSg7Cgdk/5vJGhVF1kMYLzauBg==", "dev": true, "dependencies": { "@types/geojson": "*" @@ -1241,9 +1240,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.16.11", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.11.tgz", - "integrity": "sha512-y+cTCACu92FyA5fgQSAI8A1H429g7aSK2HsO7K4XYUWc4dY5IUz55JSDIYT6/VsOLfGy8vmvQYC2hfb0iF16Uw==", + "version": "20.16.15", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.15.tgz", + "integrity": "sha512-DV58qQz9dBMqVVn+qnKwGa51QzCD4YM/tQM16qLKxdf5tqz5W4QwtrMzjSTbabN1cFTSuyxVYBy+QWHjWW8X/g==", "dependencies": { "undici-types": "~6.19.2" } @@ -1685,9 +1684,9 @@ "peer": true }, "node_modules/acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.13.0.tgz", + "integrity": "sha512-8zSiw54Oxrdym50NlZ9sUusyO1Z1ZchgRLWRaK6c86XJFClyCgFKetdowBg5bKxyp/u+CDBJG4Mpp0m3HLZl9w==", "bin": { "acorn": "bin/acorn" }, @@ -1828,9 +1827,9 @@ } }, "node_modules/axios-cache-interceptor": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/axios-cache-interceptor/-/axios-cache-interceptor-1.6.0.tgz", - "integrity": "sha512-xuo4mZckPQmNV50bJpsMmGfpFV8SXsUWWUVKf1DXQy7t9p+6Pan9zrD3icAlCIdoYFw/ZJFKV6nUVqy8j0XCLQ==", + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/axios-cache-interceptor/-/axios-cache-interceptor-1.6.2.tgz", + "integrity": "sha512-YLbAODIHZZIcD4b3WYFVQOa5W2TY/WnJ6sBHqAg6Z+hx+RVj8/OcjQyRopO6awn7/kOkGL5X9TP16AucnlJ/lw==", "dependencies": { "cache-parser": "1.2.5", "fast-defer": "1.1.8", @@ -1882,9 +1881,9 @@ } }, "node_modules/browserslist": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.0.tgz", - "integrity": "sha512-Rmb62sR1Zpjql25eSanFGEhAxcFwfA1K0GuQcLoaJBAcENegrQut3hYdhXFF1obQfiDyqIW/cLM5HSJ/9k884A==", + "version": "4.24.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz", + "integrity": "sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==", "funding": [ { "type": "opencollective", @@ -1900,10 +1899,10 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001663", - "electron-to-chromium": "^1.5.28", + "caniuse-lite": "^1.0.30001669", + "electron-to-chromium": "^1.5.41", "node-releases": "^2.0.18", - "update-browserslist-db": "^1.1.0" + "update-browserslist-db": "^1.1.1" }, "bin": { "browserslist": "cli.js" @@ -1940,9 +1939,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001668", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001668.tgz", - "integrity": "sha512-nWLrdxqCdblixUO+27JtGJJE/txpJlyUy5YN1u53wLZkP0emYCo5zgS6QYft7VUYR42LGgi/S5hdLZTrnyIddw==", + "version": "1.0.30001669", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001669.tgz", + "integrity": "sha512-DlWzFDJqstqtIVx1zeSpIMLjunf5SmwOw0N2Ck/QSQdS8PLS4+9HrLaYei4w8BIAL7IB/UEDu889d8vhCTPA0w==", "funding": [ { "type": "opencollective", @@ -2182,9 +2181,9 @@ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" }, "node_modules/electron-to-chromium": { - "version": "1.5.38", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.38.tgz", - "integrity": "sha512-VbeVexmZ1IFh+5EfrYz1I0HTzHVIlJa112UEWhciPyeOcKJGeTv6N8WnG4wsQB81DGCaVEGhpSb6o6a8WYFXXg==" + "version": "1.5.43", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.43.tgz", + "integrity": "sha512-NxnmFBHDl5Sachd2P46O7UJiMaMHMLSofoIWVJq3mj8NJgG0umiSeljAVP9lGzjI0UDLJJ5jjoGjcrB8RSbjLQ==" }, "node_modules/emoji-regex": { "version": "9.2.2", @@ -3045,9 +3044,9 @@ "integrity": "sha512-hPvBmnRYPqWEtMfIFOlyjQv1q75UUtxt4U+YscKIQViGmEE2Xa4BuS1B1/cZdjy7MVcwtnr0WkEsr915LgRKOw==" }, "node_modules/picocolors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", - "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" }, "node_modules/picomatch": { "version": "2.3.1", @@ -3314,14 +3313,14 @@ "integrity": "sha512-jK3Et9UzwzTsd6tzl2RmwrVY/b8raJ3QZLzoDACj+oTJ0oX7L9Hy+XnVwgo4QVKlKpnP/Ur13SXV/pVh4LzaDw==" }, "node_modules/primevue": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/primevue/-/primevue-4.1.0.tgz", - "integrity": "sha512-iR/RysaTnZeIG3UVxdhazU7MA8nEODOpHk8WSINwYU0WMsA/ZghbchHOD5a/LYuLuZa3V03j7mX4LMKroeV+ag==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/primevue/-/primevue-4.1.1.tgz", + "integrity": "sha512-FeJkv7FhfePfUBoApW0qAhid6Znq18VgbGFZdmhUcxvOD49Y2Eo/k2Yn7ypPhRbRApWiaSRN0v/2G1I4AMj3xg==", "dependencies": { "@primeuix/styled": "^0.2.0", "@primeuix/utils": "^0.2.0", - "@primevue/core": "4.1.0", - "@primevue/icons": "4.1.0" + "@primevue/core": "4.1.1", + "@primevue/icons": "4.1.1" }, "engines": { "node": ">=12.11.0" @@ -3521,9 +3520,9 @@ "peer": true }, "node_modules/sass": { - "version": "1.79.5", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.79.5.tgz", - "integrity": "sha512-W1h5kp6bdhqFh2tk3DsI771MoEJjvrSY/2ihJRJS4pjIyfJCw0nTsxqhnrUzaLMOJjFchj8rOvraI/YUVjtx5g==", + "version": "1.80.3", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.80.3.tgz", + "integrity": "sha512-ptDWyVmDMVielpz/oWy3YP3nfs7LpJTHIJZboMVs8GEC9eUmtZTZhMHlTW98wY4aEorDfjN38+Wr/XjskFWcfA==", "devOptional": true, "dependencies": { "@parcel/watcher": "^2.4.1", @@ -3892,9 +3891,9 @@ } }, "node_modules/terser": { - "version": "5.34.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.34.1.tgz", - "integrity": "sha512-FsJZ7iZLd/BXkz+4xrRTGJ26o/6VTjQytUk8b8OxkwcD2I+79VPJlz7qss1+zE7h8GNIScFqXcDyJ/KqBYZFVA==", + "version": "5.36.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.36.0.tgz", + "integrity": "sha512-IYV9eNMuFAV4THUspIRXkLakHnV6XO7FEdtKjf/mDyrnqUg9LnlOn6/RwRvM9SZjR4GUq8Nk8zj67FzVARr74w==", "peer": true, "dependencies": { "@jridgewell/source-map": "^0.3.3", @@ -3973,14 +3972,6 @@ "resolved": "https://registry.npmjs.org/tinygesture/-/tinygesture-3.0.0.tgz", "integrity": "sha512-UawUggtPCHy+N65ULpR/i6VLH8AzB7jWVvTNoXRFTJNh+ub6lP/SJCxzV/Ua7sJbCt9U9I79wKkKk3wbjcLdbQ==" }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "engines": { - "node": ">=4" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -4077,9 +4068,9 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, "node_modules/vite": { - "version": "5.4.9", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.9.tgz", - "integrity": "sha512-20OVpJHh0PAM0oSOELa5GaZNWeDjcAvQjGXy2Uyr+Tp+/D2/Hdz6NLgpJLsarPTA2QJ6v8mX2P1ZfbsSKvdMkg==", + "version": "5.4.10", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.10.tgz", + "integrity": "sha512-1hvaPshuPUtxeQ0hsVH3Mud0ZanOLwVTneA1EgbAM5LhaZEqyPWGRQ7BtaMvUrTDeEaC8pxtj6a6jku3x4z6SQ==", "dependencies": { "esbuild": "^0.21.3", "postcss": "^8.4.43", diff --git a/phpstan.neon b/phpstan.neon index 4c3ccc686f3..9a92ba42b59 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -50,18 +50,18 @@ parameters: - '#Dynamic call to static method (Illuminate\\Database\\Query\\Builder|Illuminate\\Database\\Eloquent\\(Builder|Relations\\.*)|App\\Models\\Builders\\.*|App\\Eloquent\\FixedQueryBuilder|App\\Relations\\.*)(<.*>)?::exists\(\).#' - '#Dynamic call to static method App\\Models\\Builders\\.*::orderByDesc\(\).#' - '#Dynamic call to static method App\\Models\\Builders\\.*::selectRaw\(\).#' - - '#Call to an undefined method Illuminate\\Database\\Eloquent\\.*::with(Only)?\(\)#' + # - '#Call to an undefined method Illuminate\\Database\\Eloquent\\.*::with(Only)?\(\)#' # - '#Call to an undefined method App\\Relations\\HasManyPhotosRecursively::whereNotNull\(\)#' # - '#Call to an undefined method Illuminate\\Database\\Eloquent\\Builder|Illuminate\\Database\\Eloquent\\Relations\\Relation::whereNotNull\(\).#' - '#Call to protected method asDateTime\(\) of class Illuminate\\Database\\Eloquent\\Model.#' # Covariance - LSP princinple: https://en.wikipedia.org/wiki/Liskov_substitution_principle - - - message: '#Parameter \#1 \$column \(array\|Closure\|Illuminate\\Database\\Query\\Expression\|string\) of method .* should be contravariant with parameter \$column \(array\|\(Closure.*\)\|\(Closure.*\)\|Illuminate\\Contracts\\Database\\Query\\Expression\|string\) of method .*#' - paths: - - app/Eloquent/FixedQueryBuilderTrait.php - - '#Parameter \#1 \$models .* of method .*::initRelation\(\) should be contravariant with parameter \$models .* of method .*::initRelation\(\)#' - - '#Parameter \#(1|2) \$(models|albums|photos|results) .* of method .*::(match|addEagerConstraints)\(\) should be contravariant with parameter \$(models|albums|photos|results) .* of method .*::(match|addEagerConstraints)\(\)#' + # - + # message: '#Parameter \#1 \$column \(array\|Closure\|Illuminate\\Database\\Query\\Expression\|string\) of method .* should be contravariant with parameter \$column \(array\|\(Closure.*\)\|\(Closure.*\)\|Illuminate\\Contracts\\Database\\Query\\Expression\|string\) of method .*#' + # paths: + # - app/Eloquent/FixedQueryBuilderTrait.php + # - '#Parameter \#1 \$models .* of method .*::initRelation\(\) should be contravariant with parameter \$models .* of method .*::initRelation\(\)#' + # - '#Parameter \#(1|2) \$(models|albums|photos|results) .* of method .*::(match|addEagerConstraints)\(\) should be contravariant with parameter \$(models|albums|photos|results) .* of method .*::(match|addEagerConstraints)\(\)#' - '#Parameter .* of method .*::replicate\(\) should be contravariant with parameter .* of method .*::replicate\(\)#' - '#Parameter .* of method .*::save\(\) should be contravariant with parameter .* of method .*::save\(\)#' - '#Parameter .* of method .*::newEloquentBuilder\(\) should be contravariant with parameter .* of method Kalnoy\\Nestedset\\Node<.*>::newEloquentBuilder\(\)#' diff --git a/resources/js/components/drawers/AlbumStatistics.vue b/resources/js/components/drawers/AlbumStatistics.vue new file mode 100644 index 00000000000..fbf5cd3c27b --- /dev/null +++ b/resources/js/components/drawers/AlbumStatistics.vue @@ -0,0 +1,116 @@ + + diff --git a/resources/js/components/forms/album/AlbumCreateDialog.vue b/resources/js/components/forms/album/AlbumCreateDialog.vue index cde263c3fe8..21af97ddfd5 100644 --- a/resources/js/components/forms/album/AlbumCreateDialog.vue +++ b/resources/js/components/forms/album/AlbumCreateDialog.vue @@ -13,7 +13,7 @@ - @@ -25,10 +25,11 @@ import AlbumService from "@/services/album-service"; import Dialog from "primevue/dialog"; import InputText from "@/components/forms/basic/InputText.vue"; -import { ref, watch } from "vue"; +import { computed, ref, watch } from "vue"; import { useRouter } from "vue-router"; import FloatLabel from "primevue/floatlabel"; import Button from "primevue/button"; +import { useToast } from "primevue/usetoast"; const props = defineProps<{ parentId: string | null; @@ -37,24 +38,31 @@ const props = defineProps<{ const visible = defineModel("visible", { default: false }); const parentId = ref(props.parentId); +const toast = useToast(); const router = useRouter(); const title = ref(undefined as undefined | string); +const isValid = computed(() => title.value !== undefined && title.value.length > 0 && title.value.length <= 100); + function create() { - if (!title.value) { + if (!isValid.value) { return; } AlbumService.createAlbum({ - title: title.value, + title: title.value as string, parent_id: parentId.value, - }).then((response) => { - title.value = undefined; - visible.value = false; - AlbumService.clearCache(parentId.value); - router.push(`/gallery/${response.data}`); - }); + }) + .then((response) => { + title.value = undefined; + visible.value = false; + AlbumService.clearCache(parentId.value); + router.push(`/gallery/${response.data}`); + }) + .catch((error) => { + toast.add({ severity: "error", summary: "Oups", detail: error.message }); + }); } watch( diff --git a/resources/js/components/forms/album/AlbumCreateTagDialog.vue b/resources/js/components/forms/album/AlbumCreateTagDialog.vue index 71461eadce3..d030506ba36 100644 --- a/resources/js/components/forms/album/AlbumCreateTagDialog.vue +++ b/resources/js/components/forms/album/AlbumCreateTagDialog.vue @@ -24,7 +24,7 @@ - @@ -36,34 +36,42 @@ import AlbumService from "@/services/album-service"; import Dialog from "primevue/dialog"; import FloatLabel from "primevue/floatlabel"; -import { ref, watch } from "vue"; +import { computed, ref, watch } from "vue"; import { useRouter } from "vue-router"; import InputText from "@/components/forms/basic/InputText.vue"; import Button from "primevue/button"; import AutoComplete from "primevue/autocomplete"; +import { useToast } from "primevue/usetoast"; const props = defineProps<{ visible: boolean; }>(); +const toast = useToast(); const router = useRouter(); const visible = ref(props.visible); const title = ref(undefined as undefined | string); const tags = ref([] as string[]); +const isValid = computed(() => title.value !== undefined && title.value.length > 0 && title.value.length <= 100); + function create() { - if (!title.value || tags.value.length === 0) { + if (!isValid.value) { return; } AlbumService.createTag({ - title: title.value, + title: title.value as string, tags: tags.value, - }).then((response) => { - AlbumService.clearAlbums(); - router.push(`/gallery/${response.data}`); - }); + }) + .then((response) => { + AlbumService.clearAlbums(); + router.push(`/gallery/${response.data}`); + }) + .catch((error) => { + toast.add({ severity: "error", summary: "Oups", detail: error.message }); + }); } watch( diff --git a/resources/js/components/forms/album/AlbumProperties.vue b/resources/js/components/forms/album/AlbumProperties.vue index 640633ac71a..bc946c90b03 100644 --- a/resources/js/components/forms/album/AlbumProperties.vue +++ b/resources/js/components/forms/album/AlbumProperties.vue @@ -182,6 +182,30 @@ +
+ + + + +
| undefined); const albumSortingColumn = ref(undefined as SelectOption | undefined); const albumSortingOrder = ref(undefined as SelectOption | undefined); +const photoLayout = ref(undefined as SelectOption | undefined); const license = ref(undefined as SelectOption | undefined); const copyright = ref(undefined as undefined | string); const tags = ref([] as string[]); @@ -294,6 +320,7 @@ function load(editable: App.Http.Resources.Editable.EditableBaseAlbumResource, p photoSortingOrder.value = SelectBuilders.buildSortingOrder(editable.photo_sorting?.order); albumSortingColumn.value = SelectBuilders.buildAlbumSorting(editable.album_sorting?.column); albumSortingOrder.value = SelectBuilders.buildSortingOrder(editable.album_sorting?.order); + photoLayout.value = SelectBuilders.buildPhotoLayout(editable.photo_layout); license.value = SelectBuilders.buildLicense(editable.license); aspectRatio.value = SelectBuilders.buildAspectRatio(editable.aspect_ratio); header_id.value = buildHeaderId(editable.header_id, photos); @@ -324,6 +351,7 @@ function saveAlbum() { copyright: copyright.value ?? null, header_id: header_id.value?.id === "compact" ? null : (header_id.value?.id ?? null), is_compact: header_id.value?.id === "compact", + photo_layout: photoLayout.value?.value ?? null, }; AlbumService.updateAlbum(data) .then(() => { @@ -349,6 +377,7 @@ function saveTagAlbum() { photo_sorting_column: photoSortingColumn.value?.value ?? null, photo_sorting_order: photoSortingOrder.value?.value ?? null, copyright: copyright.value ?? null, + photo_layout: photoLayout.value?.value ?? null, }; AlbumService.updateTag(data) .then(() => { diff --git a/resources/js/components/forms/album/AlbumShare.vue b/resources/js/components/forms/album/AlbumShare.vue index 87cd6664c1d..9692db199c6 100644 --- a/resources/js/components/forms/album/AlbumShare.vue +++ b/resources/js/components/forms/album/AlbumShare.vue @@ -1,7 +1,7 @@