>|null */ private static ?array $memo = null; private static bool $loaded = false; /** پاک کردن memo درخواست — برای دکمهٔ همگام‌سازی / بروزرسانی */ public function flushCache(): void { self::$memo = null; self::$loaded = false; } /** * دوباره از سوپرادمین می‌خواند (بدون کش پایدار). * * @return array{ok: bool, count: int, items: array, source: string, meta?: array} */ public function refreshFromSuperAdmin(): array { $this->flushCache(); $client = app(SuperAdminProgramSettingsClient::class); $map = $this->catalogMap(); if ($map === null) { return [ 'ok' => false, 'count' => 0, 'items' => [], 'source' => 'unavailable', 'meta' => $client->lastFetchMeta(), ]; } $items = []; foreach ($map as $key => $row) { if (! is_array($row)) { continue; } $value = $row['value'] ?? null; if ($value === null || $value === '') { continue; } $items[(string) $key] = (string) $value; } return [ 'ok' => true, 'count' => count($items), 'items' => $items, 'source' => 'superadmin', 'meta' => $client->lastFetchMeta(), ]; } /** * همهٔ کلیدهای سوپرادمین (حتی value خالی). null = سوپرادمین در دسترس نبود. * * @return array>|null */ public function catalogMap(): ?array { return $this->load(); } /** * فقط کلیدهایی که سوپرادمین مقدار غیرخالی دارد — برای ConfigService. * * @return array>|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>|null */ private function load(): ?array { if (self::$loaded) { return self::$memo; } self::$loaded = true; $items = app(SuperAdminProgramSettingsClient::class)->fetchItems(); if ($items === null) { self::$memo = null; return null; } $map = self::ownedItemsMap($items); self::$memo = $map; return $map; } /** * فقط کلیدهای دسترسی سوپرادمین — بقیهٔ پاسخ remote دور ریخته می‌شود. * * @param array> $items * @return array> */ public static function ownedItemsMap(array $items): array { $map = []; foreach ($items as $row) { if (! is_array($row)) { continue; } $key = trim((string) ($row['key'] ?? '')); if ($key === '' || ! self::isSuperAdminOwned($key)) { continue; } $map[$key] = $row; } return $map; } /** * @return array> */ public function items(): array { $map = $this->map(); if ($map === null || $map === []) { return []; } return array_values($map); } /** * @return array|null */ public function row(string $key): ?array { $map = $this->map(); if ($map === null) { return null; } $key = trim($key); if ($key === '' || ! self::isSuperAdminOwned($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); } /** * کلیدهای صفحهٔ «ساعت کاری» هم مالکشان پنل خانگی است — اگر از overlay خوانده شوند * مقدار ذخیره‌شده در پنل هیچ‌وقت روی قیمت کاربر اعمال نمی‌شود. */ public static function isLocalOwned(string $key): bool { return in_array($key, self::LOCAL_OWNED_KEYS, true) || in_array($key, ConfigService::TRADING_HOURS_CLIENT_KEYS, true); } public static function isSuperAdminOwned(string $key): bool { return in_array(trim($key), self::SUPERADMIN_OWNED_KEYS, true); } public static function isClientFeatureKey(string $key): bool { return in_array(trim($key), self::CLIENT_FEATURE_KEYS, true); } }