configService->all(); $enabled = filter_var($settings['maintenance_mode_enabled'] ?? false, FILTER_VALIDATE_BOOLEAN); $isCurrentlyDown = $this->isDown(); if ($enabled) { $this->activateMaintenance($settings); // Only notify if it was NOT already down if (! $isCurrentlyDown) { Notification::send( User::permission('view notification center')->get(), new SystemManagementNotification('Maintenance Active', 'System is entering Maintenance Mode.', 'warning') ); } } else { $this->deactivateMaintenance(); // Only notify if it WAS previously down if ($isCurrentlyDown) { Notification::send( User::permission('view notification center')->get(), new SystemManagementNotification('System Online', 'System is now LIVE and online.', 'success') ); } } return true; } catch (Exception $e) { Log::error('Maintenance Mode Sync Error: '.$e->getMessage()); return false; } } /** * Activate Laravel's native maintenance mode with dynamic parameters. */ protected function activateMaintenance(array $settings) { $options = []; // 1. Secret Bypass URL if (! empty($settings['maintenance_mode_secret'])) { $options['--secret'] = $settings['maintenance_mode_secret']; } // 2. Refresh (Browser refresh interval) $options['--refresh'] = 60; // Default 60 seconds // 3. Retry After Header if (! empty($settings['maintenance_mode_retry'])) { $options['--retry'] = (int) $settings['maintenance_mode_retry']; } // 4. Allowed IPs if (! empty($settings['maintenance_mode_allowed_ips'])) { // Convert textarea lines/commas to array $ips = preg_split('/[\s,]+/', $settings['maintenance_mode_allowed_ips'], -1, PREG_SPLIT_NO_EMPTY); if (! empty($ips)) { $options['--allow'] = $ips; } } // 5. Status Code (Always 503 for maintenance) $options['--status'] = 503; Log::info('System: Activating Maintenance Mode', $options); // Note: Laravel 11+ down command handles these options Artisan::call('down', $options); } /** * Deactivate maintenance mode. */ protected function deactivateMaintenance() { if (app()->isDownForMaintenance()) { Log::info('System: Deactivating Maintenance Mode'); Artisan::call('up'); } } /** * Check if the system is currently in maintenance mode. */ public function isDown(): bool { return app()->isDownForMaintenance(); } /** * Automatically release maintenance mode if the end time has passed. */ public function autoCheckAndRelease(): void { $settings = $this->configService->all(); $enabled = filter_var($settings['maintenance_mode_enabled'] ?? false, FILTER_VALIDATE_BOOLEAN); $endAt = $settings['maintenance_mode_end_at'] ?? null; if (! $enabled || empty($endAt)) { return; } try { $endTime = new \DateTime($endAt); $now = new \DateTime; if ($now >= $endTime) { Log::info('System: Maintenance window expired. Automatically deactivating maintenance mode.', [ 'expired_at' => $endAt, 'current_time' => $now->format('Y-m-d H:i:s'), ]); // Update configuration in DB $this->configService->update([ 'maintenance_mode_enabled' => false, 'maintenance_mode_end_at' => null, // Optional: Clear the end time ]); // Physical release (artisan up) $this->syncState(); } } catch (Exception $e) { Log::error('System: Automatic Maintenance Release failed: '.$e->getMessage()); } } /** * Broadcast a real-time warning to all active users via WebSockets. */ public function broadcastWarning(int $minutes) { $message = __('SYSTEM ALERT: The system will enter maintenance mode in :min minutes. Please save your work immediately.', ['min' => $minutes]); // 1. Broadcast event for real-time UI notification (WebSockets) event(new SystemNotification( message: $message, type: 'warning', title: __('Maintenance Warning') )); // 2. Persistent notification in the database Notification::send( User::all(), // Notify everyone new SystemManagementNotification('Scheduled Maintenance', $message, 'warning', 'Developer') ); Log::info("System: Broadcasted maintenance warning (Starting in {$minutes}m)."); return true; } }