optimizations

This commit is contained in:
2026-03-28 19:15:39 +01:00
parent 0b25d9570a
commit cab4fbd83e
509 changed files with 1016804 additions and 1605 deletions

View File

@@ -0,0 +1,162 @@
<?php
declare(strict_types=1);
namespace App\Services\NovaCards;
use App\Jobs\UpdateNovaCardStatsJob;
use App\Models\NovaCard;
use App\Models\NovaCardCollection;
use App\Models\NovaCardCollectionItem;
use App\Models\User;
use Illuminate\Support\Str;
class NovaCardCollectionService
{
public function createCollection(User $user, array $attributes): NovaCardCollection
{
$name = trim((string) ($attributes['name'] ?? 'Saved Cards'));
$slug = $this->uniqueSlug($user, Str::slug($attributes['slug'] ?? $name) ?: 'saved-cards');
return NovaCardCollection::query()->create([
'user_id' => $user->id,
'slug' => $slug,
'name' => $name,
'description' => $attributes['description'] ?? null,
'visibility' => $attributes['visibility'] ?? NovaCardCollection::VISIBILITY_PRIVATE,
'official' => false,
]);
}
public function createManagedCollection(array $attributes): NovaCardCollection
{
$owner = User::query()->findOrFail((int) $attributes['user_id']);
$name = trim((string) ($attributes['name'] ?? 'Untitled Collection'));
$slug = $this->uniqueSlug($owner, Str::slug($attributes['slug'] ?? $name) ?: 'nova-collection');
return NovaCardCollection::query()->create([
'user_id' => $owner->id,
'slug' => $slug,
'name' => $name,
'description' => $attributes['description'] ?? null,
'visibility' => $attributes['visibility'] ?? NovaCardCollection::VISIBILITY_PUBLIC,
'official' => (bool) ($attributes['official'] ?? false),
'featured' => (bool) ($attributes['featured'] ?? false),
]);
}
public function listCollections(User $user): array
{
return NovaCardCollection::query()
->withCount('items')
->where('user_id', $user->id)
->orderByDesc('updated_at')
->get()
->map(fn (NovaCardCollection $collection): array => [
'id' => (int) $collection->id,
'slug' => (string) $collection->slug,
'name' => (string) $collection->name,
'description' => $collection->description,
'visibility' => (string) $collection->visibility,
'featured' => (bool) $collection->featured,
'cards_count' => (int) $collection->cards_count,
'items_count' => (int) $collection->items_count,
])
->values()
->all();
}
public function saveCard(User $user, NovaCard $card, ?int $collectionId = null, ?string $note = null): NovaCardCollection
{
$collection = $collectionId
? NovaCardCollection::query()->where('user_id', $user->id)->findOrFail($collectionId)
: $this->defaultCollection($user);
$this->addCardToCollection($collection, $card, $note);
return $collection->refresh();
}
public function addCardToCollection(NovaCardCollection $collection, NovaCard $card, ?string $note = null, ?int $sortOrder = null): NovaCardCollectionItem
{
$sortOrder ??= (int) NovaCardCollectionItem::query()->where('collection_id', $collection->id)->max('sort_order') + 1;
$item = NovaCardCollectionItem::query()->updateOrCreate([
'collection_id' => $collection->id,
'card_id' => $card->id,
], [
'note' => $note,
'sort_order' => $sortOrder,
]);
$this->refreshCounts($collection, $card);
return $item;
}
public function unsaveCard(User $user, NovaCard $card, ?int $collectionId = null): void
{
$query = NovaCardCollectionItem::query()
->where('card_id', $card->id)
->whereHas('collection', fn ($builder) => $builder->where('user_id', $user->id));
if ($collectionId !== null) {
$query->where('collection_id', $collectionId);
}
$collectionIds = $query->pluck('collection_id')->unique()->all();
$query->delete();
foreach ($collectionIds as $id) {
$collection = NovaCardCollection::query()->find($id);
if ($collection) {
$this->refreshCounts($collection, $card);
}
}
}
public function removeCardFromCollection(NovaCardCollection $collection, NovaCard $card): void
{
NovaCardCollectionItem::query()
->where('collection_id', $collection->id)
->where('card_id', $card->id)
->delete();
$this->refreshCounts($collection, $card);
}
public function defaultCollection(User $user): NovaCardCollection
{
return NovaCardCollection::query()->firstOrCreate([
'user_id' => $user->id,
'slug' => 'saved-cards',
], [
'name' => 'Saved Cards',
'description' => 'Private library of Nova Cards saved for remixing, referencing, and future collections.',
'visibility' => NovaCardCollection::VISIBILITY_PRIVATE,
'official' => false,
]);
}
private function refreshCounts(NovaCardCollection $collection, NovaCard $card): void
{
$collection->forceFill([
'cards_count' => NovaCardCollectionItem::query()->where('collection_id', $collection->id)->count(),
])->save();
UpdateNovaCardStatsJob::dispatch($card->id);
}
private function uniqueSlug(User $user, string $base): string
{
$slug = $base;
$suffix = 2;
while (NovaCardCollection::query()->where('user_id', $user->id)->where('slug', $slug)->exists()) {
$slug = $base . '-' . $suffix;
$suffix++;
}
return $slug;
}
}