Feat: Adding Store Details Page
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Core\Store\Services;
|
||||
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\Event;
|
||||
use Lunar\Models\Language;
|
||||
use Modules\Core\Store\Events\StoreDetailsUpdated;
|
||||
use Modules\Core\Store\Models\StoreDetails;
|
||||
|
||||
/**
|
||||
* The only entrypoint that creates/updates the StoreDetails singleton — same
|
||||
* shape as Modules\Core\Localization\Services\TranslationService: every
|
||||
* write goes through here so it can dispatch StoreDetailsUpdated, which
|
||||
* Modules\Core\Store\Listeners\FlushStoreDetailsCache reacts to. Never call
|
||||
* StoreDetails::query()->update(...) or $storeDetails->save() directly — a
|
||||
* write bypassing this service leaves current()'s forever-cache stale.
|
||||
*/
|
||||
class StoreDetailsService
|
||||
{
|
||||
public const CACHE_KEY = 'store-details';
|
||||
|
||||
/**
|
||||
* Forever-cached — read on every storefront request that shows store
|
||||
* details (e.g. the checkout confirmation page's bank transfer
|
||||
* instructions), so this should never re-query the database on a normal
|
||||
* request. Only ever invalidated by update() below, via
|
||||
* FlushStoreDetailsCache reacting to StoreDetailsUpdated.
|
||||
*/
|
||||
public function current(): StoreDetails
|
||||
{
|
||||
return Cache::rememberForever(
|
||||
self::CACHE_KEY,
|
||||
fn () => $this->firstOrCreate(),
|
||||
);
|
||||
}
|
||||
|
||||
public function update(array $attributes): StoreDetails
|
||||
{
|
||||
$storeDetails = $this->firstOrCreate();
|
||||
|
||||
$storeDetails->update($attributes);
|
||||
|
||||
Event::dispatch(new StoreDetailsUpdated($storeDetails));
|
||||
|
||||
return $storeDetails;
|
||||
}
|
||||
|
||||
/**
|
||||
* A freshly-created row must never leave a translatable column
|
||||
* genuinely NULL — Lunar's own TranslatedText component (Modules\Core\
|
||||
* Store\Filament\Pages\ManageStoreDetails's `name`/`address`/
|
||||
* `bank_transfer_instructions` fields) silently drops every keystroke
|
||||
* on re-render when the field it's editing starts out NULL rather than
|
||||
* an empty per-locale array. Real-world precedent (PaymentMethod's own
|
||||
* translatable `name` column) never hits this, because every
|
||||
* PaymentMethod row is created THROUGH the same Filament form that
|
||||
* immediately fills `name` — this singleton is instead created blank
|
||||
* and opened for editing in the same visit, which is exactly the gap
|
||||
* that surfaces the bug. Caught and fixed after the fact, verified via
|
||||
* tinker: seeding a real (non-null) array made typing into the field
|
||||
* persist correctly, confirming NULL was the trigger.
|
||||
*/
|
||||
private function firstOrCreate(): StoreDetails
|
||||
{
|
||||
return StoreDetails::query()->firstOrCreate([], [
|
||||
'name' => $this->emptyPerLocale(),
|
||||
'address' => $this->emptyPerLocale(),
|
||||
'bank_transfer_instructions' => $this->emptyPerLocale(),
|
||||
]);
|
||||
}
|
||||
|
||||
private function emptyPerLocale(): array
|
||||
{
|
||||
return Language::query()->pluck('code')->mapWithKeys(fn (string $code) => [$code => ''])->all();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user