Skip to content

Commit 14350e1

Browse files
committed
feature: refactoring the tag system
1 parent 3269840 commit 14350e1

33 files changed

Lines changed: 569 additions & 68 deletions

app/Actions/Album/CreateTagAlbum.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
use App\Exceptions\ModelDBException;
1212
use App\Exceptions\UnauthenticatedException;
13+
use App\Models\Tag;
1314
use App\Models\TagAlbum;
1415
use Illuminate\Support\Facades\Auth;
1516

@@ -33,7 +34,7 @@ public function create(string $title, array $show_tags): TagAlbum
3334

3435
$album = new TagAlbum();
3536
$album->title = $title;
36-
$album->show_tags = $show_tags;
37+
$album->show_tags = Tag::from($show_tags)->all();
3738
$album->owner_id = $user_id;
3839
$album->save();
3940
$this->setStatistics($album);

app/Actions/Album/PositionData.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ public function get(AbstractAlbum $album, bool $include_sub_albums = false): Pos
3535
$r->whereBetween('type', [SizeVariantType::SMALL2X, SizeVariantType::THUMB]);
3636
},
3737
'palette',
38+
'tags',
3839
])
3940
->whereNotNull('latitude')
4041
->whereNotNull('longitude');

app/Actions/Albums/PositionData.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ public function do(): PositionDataResource
4949
$r->whereBetween('type', [SizeVariantType::SMALL2X, SizeVariantType::THUMB]);
5050
},
5151
'palette',
52+
'tags',
5253
])
5354
->whereNotNull('latitude')
5455
->whereNotNull('longitude'),

app/Actions/Photo/Pipes/Shared/HydrateMetadata.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ public function handle(DuplicateDTO|StandaloneDTO $state, \Closure $next): Dupli
3838
$state->photo->description = $state->exif_info->description;
3939
}
4040
if (count($state->photo->tags) === 0) {
41-
$state->photo->tags = $state->exif_info->tags;
41+
// TODO FIX ME.
42+
// $state->photo->tags = $state->exif_info->tags;
4243
}
4344
if ($state->photo->type === null) {
4445
$state->photo->type = $state->exif_info->type;

app/Actions/Search/PhotoSearch.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ public function query(array $terms): Collection
5757
public function sqlQuery(array $terms, ?Album $album = null): Builder
5858
{
5959
$query = $this->photoQueryPolicy->applySearchabilityFilter(
60-
query: Photo::query()->with(['albums', 'statistics', 'size_variants', 'palette']),
60+
query: Photo::query()->with(['albums', 'statistics', 'size_variants', 'palette', 'tags']),
6161
origin: $album,
6262
include_nsfw: !Configs::getValueAsBool('hide_nsfw_in_search')
6363
);
@@ -67,7 +67,7 @@ public function sqlQuery(array $terms, ?Album $album = null): Builder
6767
fn (FixedQueryBuilder $query) => $query
6868
->where('title', 'like', '%' . $term . '%')
6969
->orWhere('description', 'like', '%' . $term . '%')
70-
->orWhere('tags', 'like', '%' . $term . '%')
70+
// ->orWhere('tags', 'like', '%' . $term . '%')
7171
->orWhere('location', 'like', '%' . $term . '%')
7272
->orWhere('model', 'like', '%' . $term . '%')
7373
->orWhere('taken_at', 'like', '%' . $term . '%')
Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,48 +8,53 @@
88

99
namespace App\Casts;
1010

11+
use App\Models\Tag;
1112
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
1213
use Illuminate\Database\Eloquent\Model;
1314

1415
/**
15-
* @implements CastsAttributes<array,(string|null)[]>
16+
* @implements CastsAttributes<array,(Tag|null)[]>
1617
*/
17-
class ArrayCast implements CastsAttributes
18+
class TagArrayCast implements CastsAttributes
1819
{
1920
/**
2021
* @param Model $model the associated model class
2122
* @param string $key the name of the SQL column holding the stringified array
2223
* @param mixed $value the stringified array
2324
* @param array<string,mixed> $attributes all SQL attributes of the entity
2425
*
25-
* @return array<int,string> the array
26+
* @return array<int,Tag> the array
2627
*/
2728
public function get(Model $model, string $key, mixed $value, array $attributes): array
2829
{
29-
return ($value === null || $value === '') ? [] : explode(',', strval($value));
30+
if ($value === null || $value === '') {
31+
return [];
32+
}
33+
34+
// Split the string by ' OR ' and return an array of Tag objects
35+
return Tag::whereIn('id', explode(' OR ', strval($value)))->get()->all();
3036
}
3137

3238
/**
33-
* @param Model $model the associated model class
34-
* @param string $key the name of the SQL column holding the stringified array
35-
* @param (string|null)[]|null $value the array
36-
* @param array<string,mixed> $attributes
39+
* @param Model $model the associated model class
40+
* @param string $key the name of the SQL column holding the stringified array
41+
* @param (Tag|null)[]|null $value the array
42+
* @param array<string,mixed> $attributes
3743
*
3844
* @return array<string,mixed> An associative map of SQL columns and their values
3945
*/
4046
public function set(Model $model, string $key, mixed $value, array $attributes): array
4147
{
4248
// Normalize the input value
43-
// The array must not contain empty tags and tags which contain a comma
4449
// TODO: Either use a separate table to store the tags or another encoding (e.g. JSON) which also allows commas in tags
4550

4651
$arr = !is_array($value) ? [] : array_values(array_filter(
4752
$value,
48-
fn ($elem) => ($elem !== null && $elem !== '' && !str_contains($elem, ',')),
53+
fn ($elem) => ($elem !== null && $elem !== '' && $elem instanceof Tag && $elem->name !== ''),
4954
));
5055

5156
return [
52-
$key => count($arr) === 0 ? null : implode(',', $arr),
57+
$key => count($arr) === 0 ? null : implode(' OR ', array_map(fn ($t) => $t->id, $arr)),
5358
];
5459
}
5560
}

app/Factories/AlbumFactory.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,8 @@ public function findBaseAlbumOrFail(string $album_id, bool $with_relations = tru
9696
$tag_album_query = TagAlbum::query();
9797

9898
if ($with_relations) {
99-
$album_query->with(['access_permissions', 'photos', 'children', 'children.owner', 'photos.size_variants', 'photos.statistics', 'photos.palette']);
100-
$tag_album_query->with(['photos', 'photos.size_variants', 'photos.statistics', 'photos.palette']);
99+
$album_query->with(['access_permissions', 'photos', 'children', 'children.owner', 'photos.size_variants', 'photos.statistics', 'photos.palette', 'photos.tags']);
100+
$tag_album_query->with(['photos', 'photos.size_variants', 'photos.statistics', 'photos.palette', 'photos.tags']);
101101
}
102102

103103
$ret = $album_query->find($album_id) ?? $tag_album_query->find($album_id);

app/Http/Controllers/Gallery/AlbumController.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
use App\Http\Resources\Models\Utils\AlbumProtectionPolicy;
5858
use App\Models\Album;
5959
use App\Models\Extensions\BaseAlbum;
60+
use App\Models\Tag;
6061
use App\Models\TagAlbum;
6162
use App\SmartAlbums\BaseSmartAlbum;
6263
use Illuminate\Routing\Controller;
@@ -165,7 +166,7 @@ public function updateTagAlbum(UpdateTagAlbumRequest $request): EditableBaseAlbu
165166
}
166167
$album->title = $request->title();
167168
$album->description = $request->description();
168-
$album->show_tags = $request->tags();
169+
$album->show_tags = Tag::from($request->tags())->all();
169170
$album->copyright = $request->copyright();
170171
$album->photo_sorting = $request->photoSortingCriterion();
171172
$album->photo_layout = $request->photoLayout();

app/Http/Controllers/Gallery/FrameController.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,12 +86,12 @@ private function loadPhoto(AbstractAlbum|null $album, int $retries = 5): ?Photo
8686
// default query
8787
if ($album === null) {
8888
$query = $this->photo_query_policy->applySearchabilityFilter(
89-
query: Photo::query()->with(['albums', 'size_variants', 'palette']),
89+
query: Photo::query()->with(['albums', 'size_variants', 'palette', 'tags']),
9090
origin: null,
9191
include_nsfw: !Configs::getValueAsBool('hide_nsfw_in_frame')
9292
);
9393
} else {
94-
$query = $album->photos()->with(['albums', 'size_variants', 'palette']);
94+
$query = $album->photos()->with(['albums', 'size_variants', 'palette', 'tags']);
9595
}
9696

9797
/** @var ?Photo $photo */

app/Http/Controllers/Gallery/PhotoController.php

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,11 @@
3535
use App\Jobs\ProcessImageJob;
3636
use App\Models\Configs;
3737
use App\Models\Photo;
38+
use App\Models\Tag;
3839
use Illuminate\Routing\Controller;
3940
use Illuminate\Support\Facades\App;
4041
use Illuminate\Support\Facades\Auth;
42+
use Illuminate\Support\Facades\DB;
4143
use Illuminate\Support\Facades\Storage;
4244

4345
/**
@@ -122,7 +124,10 @@ public function update(EditPhotoRequest $request): PhotoResource
122124
$photo->title = $request->title();
123125
$photo->description = $request->description();
124126
$photo->created_at = $request->uploadDate();
125-
$photo->tags = $request->tags();
127+
128+
$existing_tags = Tag::from($request->tags());
129+
$photo->tags()->sync($existing_tags->pluck('id'));
130+
$photo->load('tags');
126131
$photo->license = $request->license()->value;
127132

128133
// if the request takenAt is null, then we set the initial value back.
@@ -205,15 +210,21 @@ public function rename(RenamePhotoRequest $request): void
205210
public function tags(SetPhotosTagsRequest $request): void
206211
{
207212
$tags = $request->tags();
213+
$photos = $request->photos();
208214

209-
/** @var Photo $photo */
210-
foreach ($request->photos() as $photo) {
211-
if ($request->shall_override) {
212-
$photo->tags = $tags;
213-
} else {
214-
$photo->tags = array_unique(array_merge($photo->tags, $tags));
215-
}
216-
$photo->save();
215+
// Fetch existing tags
216+
$existing_tags = Tag::from($tags);
217+
218+
if ($request->shall_override) {
219+
// Delete existing associations for those photos ids if we override the tags
220+
DB::table('photos_tags')
221+
->whereIn('photo_id', $photos->pluck('id'))
222+
->delete();
217223
}
224+
225+
// Associate the existing tags with the photos
226+
$existing_tags->each(function (Tag $tag) use ($photos): void {
227+
$tag->photos()->syncWithoutDetaching($photos->pluck('id'));
228+
});
218229
}
219230
}

0 commit comments

Comments
 (0)