Files
boursecu_server/app/Services/SuperAdminProgramSettingsOverlay.php
T

225 lines
6.6 KiB
PHP
Raw Normal View History

<?php
namespace App\Services;
2026-08-22 18:06:35 +03:30
use Illuminate\Support\Facades\Cache;
/**
* تنظیمات پیشرفته سوپرادمین برای ConfigService و get_settings.
2026-08-22 18:06:35 +03:30
* در هر درخواست یک بار fetch می‌شود؛ آخرین پاسخ سالم برای قطعی لحظه‌ای کش می‌ماند.
*/
class SuperAdminProgramSettingsOverlay
{
2026-08-22 18:06:35 +03:30
/**
* آخرین پاسخ سالم سوپرادمین.
*
* کلیدهای can_edit=0 مالکشان سوپرادمین است و کپی‌شان در جدول settings لوکال
* ممکن است ماندهٔ deploy باشد. بدون این کش، یک timeout لحظه‌ای باعث می‌شود
* ConfigService به آن کپی سقوط کند — مثلاً price_provider از zaarbox به montzar
* می‌پرید و مظنهٔ قدیمی montzar_live_price به‌جای قیمت زنده نمایش داده می‌شد.
*/
private const LAST_GOOD_CACHE_KEY = 'superadmin:program_settings:last_good';
private const LAST_GOOD_CACHE_MINUTES = 1440;
2026-08-23 22:34:18 +03:30
/**
* کلیدهایی که فقط سوپرادمین ویرایش می‌کند (پنل خانگی 403).
* این لیست فیلتر overlay نیست — برای load از blacklist زیر استفاده می‌شود
* تا مثلاً price_provider از سوپرادمین/کش last-good حذف نشود.
2026-08-23 22:34:18 +03:30
*/
public const SUPERADMIN_OWNED_KEYS = [
'customer_direct_sms',
'customer_special_pricing',
'enable_automation',
2026-08-23 22:34:18 +03:30
'enable_conditional_order',
'enable_customer_level_profit',
'enable_product_funds',
'group_sms',
'has_page_earn_money',
'has_page_gift_card',
'has_page_notification',
'has_page_price_trigger',
'jibit_enabled',
'permision__enabled',
'show_to_users_chat',
];
/** کلیدهایی که هنوز صفحهٔ اختصاصی ادمین خانگی مالک‌شان است — از overlay دور انداخته می‌شوند */
public const LOCAL_OWNED_KEYS = [
'tracking_systems',
];
/** لاگ/قیمت لحظه‌ای همکار — can_edit=1 در DB؛ کد مستقیم UpdateConfig می‌زند، نه سوپرادمین */
public const RUNTIME_KEYS = [
'montzar_last_product_log',
'montzar_order_response',
'montzar_live_price',
'montzar_mazaneh',
'montzar_diff',
'montzar_truly_buy_mazaneh',
'montzar_truly_sell_mazaneh',
'montzar_token',
'montzar_closed',
'up_price',
'down_price',
'price_extreme_date',
'do_send_liman',
];
/** @var array<string, array<string, mixed>>|null */
private static ?array $memo = null;
private static bool $loaded = false;
/**
* همهٔ کلیدهای سوپرادمین (حتی value خالی). null = سوپرادمین در دسترس نبود.
*
* @return array<string, array<string, mixed>>|null
*/
public function catalogMap(): ?array
{
return $this->load();
}
/**
* فقط کلیدهایی که سوپرادمین مقدار غیرخالی دارد — برای ConfigService.
*
* @return array<string, array<string, mixed>>|null
*/
public function map(): ?array
{
$full = $this->load();
if ($full === null) {
return null;
}
$withValue = [];
foreach ($full as $key => $row) {
$value = is_array($row) ? ($row['value'] ?? null) : null;
if ($value === null || $value === '') {
continue;
}
$withValue[$key] = $row;
}
return $withValue;
}
/**
* @return array<string, array<string, mixed>>|null
*/
private function load(): ?array
{
if (self::$loaded) {
return self::$memo;
}
self::$loaded = true;
$items = app(SuperAdminProgramSettingsClient::class)->fetchItems();
2026-08-22 18:06:35 +03:30
if ($items !== null) {
$this->rememberLastGood($items);
} else {
$items = $this->lastGoodItems();
}
if ($items === null) {
self::$memo = null;
return null;
}
$map = [];
foreach ($items as $row) {
if (! is_array($row)) {
continue;
}
$key = trim((string) ($row['key'] ?? ''));
// blacklist: فقط کلیدهای لوکال/runtime را دور بریز — نه whitelist قابلیت‌ها
// (whitelist قبلی price_provider را حذف می‌کرد و با قطعی SA به montzar لوکال می‌پرید)
if ($key === '' || self::isLocalOwned($key) || self::isRuntime($key)) {
continue;
}
$map[$key] = $row;
}
self::$memo = $map;
return $map;
}
2026-08-22 18:06:35 +03:30
/** @param array<int, array<string, mixed>> $items */
private function rememberLastGood(array $items): void
{
try {
Cache::put(
self::LAST_GOOD_CACHE_KEY,
$items,
now()->addMinutes(self::LAST_GOOD_CACHE_MINUTES)
);
} catch (\Throwable $e) {
// کش در دسترس نیست — همان رفتار قبلی
}
}
/**
* @return array<int, array<string, mixed>>|null
*/
private function lastGoodItems(): ?array
{
try {
$cached = Cache::get(self::LAST_GOOD_CACHE_KEY);
} catch (\Throwable $e) {
return null;
}
return is_array($cached) && $cached !== [] ? $cached : null;
}
/**
* @return array<int, array<string, mixed>>
*/
public function items(): array
{
$map = $this->map();
if ($map === null || $map === []) {
return [];
}
return array_values($map);
}
/**
* @return array<string, mixed>|null
*/
public function row(string $key): ?array
{
$map = $this->map();
if ($map === null) {
return null;
}
$key = trim($key);
if ($key === '' || ! array_key_exists($key, $map)) {
return null;
}
return $map[$key];
}
public static function isRuntime(string $key): bool
{
return in_array($key, self::RUNTIME_KEYS, true);
}
public static function isLocalOwned(string $key): bool
{
return in_array($key, self::LOCAL_OWNED_KEYS, true);
}
2026-08-23 22:34:18 +03:30
public static function isSuperAdminOwned(string $key): bool
{
return in_array(trim($key), self::SUPERADMIN_OWNED_KEYS, true);
}
}