Files
usher-manage-stack/app/Models/SystemSetting.php
2025-11-20 23:21:05 +08:00

224 lines
5.3 KiB
PHP

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Cache;
class SystemSetting extends Model
{
use HasFactory;
protected $fillable = [
'key',
'value',
'type',
'group',
'description',
];
/**
* Cache key prefix for settings
*/
const CACHE_PREFIX = 'system_setting_';
/**
* Cache duration in seconds (1 hour)
*/
const CACHE_DURATION = 3600;
/**
* Boot the model
*/
protected static function booted()
{
// Clear cache when setting is updated or deleted
static::saved(function ($setting) {
Cache::forget(self::CACHE_PREFIX . $setting->key);
Cache::forget('all_system_settings');
});
static::deleted(function ($setting) {
Cache::forget(self::CACHE_PREFIX . $setting->key);
Cache::forget('all_system_settings');
});
}
/**
* Get a setting value by key with caching
*
* @param string $key
* @param mixed $default
* @return mixed
*/
public static function get(string $key, $default = null)
{
return Cache::remember(
self::CACHE_PREFIX . $key,
self::CACHE_DURATION,
function () use ($key, $default) {
$setting = self::where('key', $key)->first();
if (!$setting) {
return $default;
}
return $setting->getCastedValue();
}
);
}
/**
* Set a setting value (creates if not exists)
*
* @param string $key
* @param mixed $value
* @param string $type
* @param string|null $group
* @param string|null $description
* @return SystemSetting
*/
public static function set(string $key, $value, string $type = 'string', ?string $group = null, ?string $description = null): SystemSetting
{
$setting = self::updateOrCreate(
['key' => $key],
[
'value' => self::encodeValue($value, $type),
'type' => $type,
'group' => $group,
'description' => $description,
]
);
return $setting;
}
/**
* Check if a setting exists
*
* @param string $key
* @return bool
*/
public static function has(string $key): bool
{
return Cache::remember(
self::CACHE_PREFIX . $key . '_exists',
self::CACHE_DURATION,
fn() => self::where('key', $key)->exists()
);
}
/**
* Delete a setting by key
*
* @param string $key
* @return bool
*/
public static function forget(string $key): bool
{
return self::where('key', $key)->delete() > 0;
}
/**
* Get all settings grouped by group
*
* @return \Illuminate\Support\Collection
*/
public static function getAllGrouped()
{
return Cache::remember(
'all_system_settings',
self::CACHE_DURATION,
function () {
return self::all()->groupBy('group')->map(function ($groupSettings) {
return $groupSettings->mapWithKeys(function ($setting) {
return [$setting->key => $setting->getCastedValue()];
});
});
}
);
}
/**
* Get the casted value based on type
*
* @return mixed
*/
public function getCastedValue()
{
if ($this->value === null) {
return null;
}
return match ($this->type) {
'boolean' => filter_var($this->value, FILTER_VALIDATE_BOOLEAN),
'integer' => (int) $this->value,
'json', 'array' => json_decode($this->value, true),
default => $this->value,
};
}
/**
* Encode value for storage based on type
*
* @param mixed $value
* @param string $type
* @return string|null
*/
protected static function encodeValue($value, string $type): ?string
{
if ($value === null) {
return null;
}
return match ($type) {
'boolean' => $value ? '1' : '0',
'integer' => (string) $value,
'json', 'array' => json_encode($value),
default => (string) $value,
};
}
/**
* Toggle a boolean setting
*
* @param string $key
* @return bool New value after toggle
*/
public static function toggle(string $key): bool
{
$currentValue = self::get($key, false);
$newValue = !$currentValue;
self::set($key, $newValue, 'boolean');
return $newValue;
}
/**
* Increment an integer setting
*
* @param string $key
* @param int $amount
* @return int
*/
public static function incrementSetting(string $key, int $amount = 1): int
{
$currentValue = self::get($key, 0);
$newValue = $currentValue + $amount;
self::set($key, $newValue, 'integer');
return $newValue;
}
/**
* Clear all settings cache
*
* @return void
*/
public static function clearCache(): void
{
Cache::flush();
}
}