|null */ private static ?array $resolvedData = null; /** * Bind data to the view. */ public function compose(View $view): void { if (self::$resolvedData === null) { self::$resolvedData = $this->resolveData(); } $view->with(self::$resolvedData); } /** * Build the global view data (called once per request). * * @return array */ private function resolveData(): array { // Cached site settings (shared across all requests) $siteArray = $this->rememberWithCacheFallback('site_settings_array', self::CACHE_TTL, function () { return Settings::query() ->pluck('value', 'name') ->map(fn ($value) => Settings::convertValue($value)) ->all(); }); $viewData = [ 'serverroot' => url('/'), 'site' => $siteArray, ]; // Cached useful links for sidebar $viewData['usefulLinks'] = $this->rememberWithCacheFallback('content_useful_links', self::CACHE_TTL, function () { return Content::active() ->ofType(Content::TYPE_USEFUL) ->ordered() ->get(); }); if (Auth::check()) { $userId = Auth::id(); // User data with category exclusions (short cache per user) $userdata = $this->rememberWithCacheFallback('composer_user_'.$userId, self::CACHE_TTL, function () use ($userId) { $user = User::find($userId); $user->categoryexclusions = User::getCachedCategoryExclusionById($userId); return $user; }); // Update last login every 3 hours (outside of cache to avoid stale checks) if (now()->subHours(3) > $userdata->lastlogin) { event(new UserLoggedIn($userdata)); } // Cached menu categories per user (depends on their exclusions) $parentcatlist = $this->rememberWithCacheFallback('menu_user_'.$userId, self::CACHE_TTL, function () use ($userdata) { return Category::getForMenu($userdata->categoryexclusions); }); $viewData = array_merge($viewData, [ 'userdata' => $userdata, 'loggedin' => true, 'isadmin' => $userdata->hasRole('Admin'), 'ismod' => $userdata->hasRole('Moderator'), 'parentcatlist' => $parentcatlist, 'header_menu_cat' => request()->input('t', ''), ]); } else { $viewData = array_merge($viewData, [ 'isadmin' => false, 'ismod' => false, 'loggedin' => false, ]); } return $viewData; } /** * @param callable(): mixed $callback */ private function rememberWithCacheFallback(string $key, int|\DateInterval $ttl, callable $callback): mixed { try { return Cache::remember($key, $ttl, $callback); } catch (\Throwable $e) { if (config('app.debug')) { Log::debug('GlobalDataComposer cache bypassed: '.$e->getMessage()); } return $callback(); } } }