Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stacked 13: Statistics per album #2577

Merged
merged 9 commits into from
Oct 26, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions app/Actions/Album/ListAlbums.php
Original file line number Diff line number Diff line change
@@ -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<int,string,Album> $albums */
/** @var NsCollection<Album> $albums */
$albums = $query->get();
/** @var NsCollection<int,string,Album> $tree */
/** @var NsCollection<Album> $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<int,string,Album>|Collection<int,Album> $collection
* @param string $prefix
* @param NsCollection<Album>|Collection<int,Album> $collection
* @param string $prefix
*
* @return TAlbumSaved[]
*/
1 change: 1 addition & 0 deletions app/Actions/Album/PositionData.php
Original file line number Diff line number Diff line change
@@ -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) {
75 changes: 72 additions & 3 deletions app/Actions/Statistics/Spaces.php
Original file line number Diff line number Diff line change
@@ -63,7 +63,7 @@ public function getFullSpacePerUser(?int $owner_id = null): Collection
*
* @return Collection<int,array{type:SizeVariantType,size:int}>
*/
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<int,array{type:SizeVariantType,size:int}>
*/
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',
13 changes: 13 additions & 0 deletions app/Contracts/Http/Requests/HasPhotoLayout.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

namespace App\Contracts\Http\Requests;

use App\Enum\PhotoLayoutType;

interface HasPhotoLayout
{
/**
* @return PhotoLayoutType|null
*/
public function photoLayout(): ?PhotoLayoutType;
}
1 change: 1 addition & 0 deletions app/Contracts/Http/Requests/RequestAttribute.php
Original file line number Diff line number Diff line change
@@ -46,6 +46,7 @@ class RequestAttribute
public const PHOTO_SORTING_ORDER_ATTRIBUTE = 'photo_sorting_order';
public const ALBUM_SORTING_COLUMN_ATTRIBUTE = 'album_sorting_column';
public const ALBUM_SORTING_ORDER_ATTRIBUTE = 'album_sorting_order';
public const ALBUM_PHOTO_LAYOUT = 'photo_layout';

public const PERMISSION_ID = 'perm_id';
public const IS_COMPACT_ATTRIBUTE = 'is_compact';
3 changes: 2 additions & 1 deletion app/Contracts/Models/AbstractAlbum.php
Original file line number Diff line number Diff line change
@@ -7,6 +7,7 @@
use App\Models\Photo;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\Relation;

/**
@@ -31,7 +32,7 @@
interface AbstractAlbum
{
/**
* @return Relation<Photo>|Builder<Photo>
* @return Relation<Photo,AbstractAlbum&Model,Collection<int,Photo>>|Builder<Photo>
*/
public function photos(): Relation|Builder;

16 changes: 8 additions & 8 deletions app/Eloquent/FixedQueryBuilderTrait.php
Original file line number Diff line number Diff line change
@@ -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<string>|Expression $column
* @param mixed $operator
* @param mixed $value
* @param string $boolean
* @param \Closure|string|array<int|string,mixed>|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>|string|Expression $column
* @param mixed $operator
* @param mixed $value
* @param \Closure|string|array<int|string,mixed>|Expression $column
* @param mixed $operator
* @param mixed $value
*
* @return $this
*
4 changes: 2 additions & 2 deletions app/Http/Controllers/Admin/Maintenance/Model/Album.php
Original file line number Diff line number Diff line change
@@ -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<string,Album>
* @implements Node<Album>
*/
class Album extends Model implements Node
{
/** @phpstan-use NodeTrait<string,Album> */
/** @phpstan-use NodeTrait<Album> */
use NodeTrait;
public $timestamps = false;
}
2 changes: 2 additions & 0 deletions app/Http/Controllers/Gallery/AlbumController.php
Original file line number Diff line number Diff line change
@@ -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);
16 changes: 10 additions & 6 deletions app/Http/Controllers/StatisticsController.php
Original file line number Diff line number Diff line change
@@ -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<int,Sizes>
*/
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);
}
8 changes: 7 additions & 1 deletion app/Http/Requests/Album/UpdateAlbumRequest.php
Original file line number Diff line number Diff line change
@@ -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]);
8 changes: 7 additions & 1 deletion app/Http/Requests/Album/UpdateTagAlbumRequest.php
Original file line number Diff line number Diff line change
@@ -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,14 +31,15 @@
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;
use HasDescriptionTrait;
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];
}
Loading