| 
									
										
										
										
											2025-01-04 12:22:53 +00:00
										 |  |  | <?php | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-15 08:13:39 +00:00
										 |  |  | class Feedback { | 
					
						
							|  |  |  |     // Feedback types
 | 
					
						
							| 
									
										
										
										
											2025-01-04 12:22:53 +00:00
										 |  |  |     const TYPE_SUCCESS = 'success'; | 
					
						
							|  |  |  |     const TYPE_ERROR = 'danger'; | 
					
						
							|  |  |  |     const TYPE_INFO = 'info'; | 
					
						
							|  |  |  |     const TYPE_WARNING = 'warning'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-15 08:13:39 +00:00
										 |  |  |     // Default feedback message configurations
 | 
					
						
							| 
									
										
										
										
											2025-01-06 09:13:28 +00:00
										 |  |  |     const NOTICE = [ | 
					
						
							|  |  |  |         'DEFAULT' => [ | 
					
						
							|  |  |  |             'type' => self::TYPE_INFO, | 
					
						
							|  |  |  |             'dismissible' => true | 
					
						
							|  |  |  |         ] | 
					
						
							|  |  |  |     ]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const ERROR = [ | 
					
						
							|  |  |  |         'DEFAULT' => [ | 
					
						
							|  |  |  |             'type' => self::TYPE_ERROR, | 
					
						
							|  |  |  |             'dismissible' => false | 
					
						
							|  |  |  |         ] | 
					
						
							|  |  |  |     ]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const LOGIN = [ | 
					
						
							|  |  |  |         'LOGIN_SUCCESS' => [ | 
					
						
							|  |  |  |             'type' => self::TYPE_SUCCESS, | 
					
						
							|  |  |  |             'dismissible' => true | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |         'LOGIN_FAILED' => [ | 
					
						
							|  |  |  |             'type' => self::TYPE_ERROR, | 
					
						
							|  |  |  |             'dismissible' => false | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |         'LOGOUT_SUCCESS' => [ | 
					
						
							|  |  |  |             'type' => self::TYPE_SUCCESS, | 
					
						
							|  |  |  |             'dismissible' => true | 
					
						
							|  |  |  |         ], | 
					
						
							| 
									
										
										
										
											2025-04-13 16:06:48 +00:00
										 |  |  |         'SESSION_TIMEOUT' => [ | 
					
						
							|  |  |  |             'type' => self::TYPE_ERROR, | 
					
						
							|  |  |  |             'dismissible' => true | 
					
						
							|  |  |  |         ], | 
					
						
							| 
									
										
										
										
											2025-01-06 09:13:28 +00:00
										 |  |  |         'IP_BLACKLISTED' => [ | 
					
						
							|  |  |  |             'type' => self::TYPE_ERROR, | 
					
						
							|  |  |  |             'dismissible' => false | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |         'IP_NOT_WHITELISTED' => [ | 
					
						
							|  |  |  |             'type' => self::TYPE_ERROR, | 
					
						
							|  |  |  |             'dismissible' => false | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |         'TOO_MANY_ATTEMPTS' => [ | 
					
						
							|  |  |  |             'type' => self::TYPE_ERROR, | 
					
						
							|  |  |  |             'dismissible' => false | 
					
						
							|  |  |  |         ] | 
					
						
							|  |  |  |     ]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-05-22 11:20:36 +00:00
										 |  |  |     const REGISTER = [ | 
					
						
							|  |  |  |         'SUCCESS' => [ | 
					
						
							|  |  |  |             'type' => self::TYPE_SUCCESS, | 
					
						
							|  |  |  |             'dismissible' => true | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |         'FAILED' => [ | 
					
						
							|  |  |  |             'type' => self::TYPE_ERROR, | 
					
						
							|  |  |  |             'dismissible' => true | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |         'DISABLED' => [ | 
					
						
							|  |  |  |             'type' => self::TYPE_ERROR, | 
					
						
							|  |  |  |             'dismissible' => false | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |     ]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-04 12:22:53 +00:00
										 |  |  |     const SECURITY = [ | 
					
						
							|  |  |  |         'WHITELIST_ADD_SUCCESS' => [ | 
					
						
							|  |  |  |             'type' => self::TYPE_SUCCESS, | 
					
						
							|  |  |  |             'dismissible' => true | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |         'WHITELIST_ADD_ERROR' => [ | 
					
						
							|  |  |  |             'type' => self::TYPE_ERROR, | 
					
						
							|  |  |  |             'dismissible' => true | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |         'WHITELIST_REMOVE_SUCCESS' => [ | 
					
						
							|  |  |  |             'type' => self::TYPE_SUCCESS, | 
					
						
							|  |  |  |             'dismissible' => true | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |         'WHITELIST_REMOVE_ERROR' => [ | 
					
						
							|  |  |  |             'type' => self::TYPE_ERROR, | 
					
						
							|  |  |  |             'dismissible' => true | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |         'BLACKLIST_ADD_SUCCESS' => [ | 
					
						
							|  |  |  |             'type' => self::TYPE_SUCCESS, | 
					
						
							|  |  |  |             'dismissible' => true | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |         'BLACKLIST_ADD_ERROR' => [ | 
					
						
							|  |  |  |             'type' => self::TYPE_ERROR, | 
					
						
							|  |  |  |             'dismissible' => true | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |         'BLACKLIST_REMOVE_SUCCESS' => [ | 
					
						
							|  |  |  |             'type' => self::TYPE_SUCCESS, | 
					
						
							|  |  |  |             'dismissible' => true | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |         'BLACKLIST_REMOVE_ERROR' => [ | 
					
						
							|  |  |  |             'type' => self::TYPE_ERROR, | 
					
						
							|  |  |  |             'dismissible' => true | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |         'RATE_LIMIT_INFO' => [ | 
					
						
							|  |  |  |             'type' => self::TYPE_INFO, | 
					
						
							|  |  |  |             'dismissible' => false | 
					
						
							|  |  |  |         ], | 
					
						
							| 
									
										
										
										
											2025-01-06 09:13:28 +00:00
										 |  |  |         'PERMISSION_DENIED' => [ | 
					
						
							| 
									
										
										
										
											2025-01-04 12:22:53 +00:00
										 |  |  |             'type' => self::TYPE_ERROR, | 
					
						
							|  |  |  |             'dismissible' => false | 
					
						
							|  |  |  |         ], | 
					
						
							| 
									
										
										
										
											2025-01-06 09:13:28 +00:00
										 |  |  |         'IP_REQUIRED' => [ | 
					
						
							| 
									
										
										
										
											2025-01-04 12:22:53 +00:00
										 |  |  |             'type' => self::TYPE_ERROR, | 
					
						
							|  |  |  |             'dismissible' => false | 
					
						
							|  |  |  |         ] | 
					
						
							|  |  |  |     ]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-05-22 11:20:36 +00:00
										 |  |  |     const THEME = [ | 
					
						
							|  |  |  |         'THEME_CHANGE_SUCCESS' => [ | 
					
						
							| 
									
										
										
										
											2025-02-11 15:25:55 +00:00
										 |  |  |             'type' => self::TYPE_SUCCESS, | 
					
						
							|  |  |  |             'dismissible' => true | 
					
						
							|  |  |  |         ], | 
					
						
							| 
									
										
										
										
											2025-05-22 11:20:36 +00:00
										 |  |  |         'THEME_CHANGE_FAILED' => [ | 
					
						
							| 
									
										
										
										
											2025-02-11 15:25:55 +00:00
										 |  |  |             'type' => self::TYPE_ERROR, | 
					
						
							|  |  |  |             'dismissible' => true | 
					
						
							| 
									
										
										
										
											2025-05-22 11:20:36 +00:00
										 |  |  |         ] | 
					
						
							| 
									
										
										
										
											2025-02-11 15:25:55 +00:00
										 |  |  |     ]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const SYSTEM = [ | 
					
						
							|  |  |  |         'DB_ERROR' => [ | 
					
						
							|  |  |  |             'type' => self::TYPE_ERROR, | 
					
						
							|  |  |  |             'dismissible' => false | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |         'DB_CONNECT_ERROR' => [ | 
					
						
							|  |  |  |             'type' => self::TYPE_ERROR, | 
					
						
							|  |  |  |             'dismissible' => false | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |         'DB_UNKNOWN_TYPE' => [ | 
					
						
							|  |  |  |             'type' => self::TYPE_ERROR, | 
					
						
							|  |  |  |             'dismissible' => false | 
					
						
							|  |  |  |         ], | 
					
						
							| 
									
										
										
										
											2025-09-24 18:29:31 +00:00
										 |  |  |         'MIGRATIONS_PENDING' => [ | 
					
						
							|  |  |  |             'type' => self::TYPE_WARNING, | 
					
						
							|  |  |  |             'dismissible' => true | 
					
						
							|  |  |  |         ], | 
					
						
							| 
									
										
										
										
											2025-02-11 15:25:55 +00:00
										 |  |  |     ]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-06 09:13:28 +00:00
										 |  |  |     private static $strings = null; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							| 
									
										
										
										
											2025-02-15 08:13:39 +00:00
										 |  |  |      * Get feedback message strings | 
					
						
							| 
									
										
										
										
											2025-01-06 09:13:28 +00:00
										 |  |  |      */ | 
					
						
							|  |  |  |     private static function getStrings() { | 
					
						
							|  |  |  |         if (self::$strings === null) { | 
					
						
							| 
									
										
										
										
											2025-02-15 08:13:39 +00:00
										 |  |  |             self::$strings = require __DIR__ . '/../includes/strings.php'; | 
					
						
							| 
									
										
										
										
											2025-01-06 09:13:28 +00:00
										 |  |  |         } | 
					
						
							|  |  |  |         return self::$strings; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-04 12:22:53 +00:00
										 |  |  |     /** | 
					
						
							| 
									
										
										
										
											2025-02-15 08:13:39 +00:00
										 |  |  |      * Get feedback message configuration by key | 
					
						
							| 
									
										
										
										
											2025-01-04 12:22:53 +00:00
										 |  |  |      */ | 
					
						
							|  |  |  |     public static function get($category, $key) { | 
					
						
							| 
									
										
										
										
											2025-01-06 09:13:28 +00:00
										 |  |  |         $config = constant("self::$category")[$key] ?? null; | 
					
						
							|  |  |  |         if (!$config) return null; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $strings = self::getStrings(); | 
					
						
							|  |  |  |         $message = $strings[$category][$key] ?? ''; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return array_merge($config, ['message' => $message]); | 
					
						
							| 
									
										
										
										
											2025-01-04 12:22:53 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							| 
									
										
										
										
											2025-02-15 08:13:39 +00:00
										 |  |  |      * Render feedback message HTML | 
					
						
							| 
									
										
										
										
											2025-01-04 12:22:53 +00:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2025-02-15 08:13:39 +00:00
										 |  |  |     // Usage: echo Feedback::render('LOGIN', 'LOGIN_SUCCESS', 'custom message [or null]', true [for dismissible; or null], true [for small; or omit]);
 | 
					
						
							| 
									
										
										
										
											2025-01-15 16:22:49 +00:00
										 |  |  |     public static function render($category, $key, $customMessage = null, $dismissible = null, $small = false, $sanitize = true) { | 
					
						
							| 
									
										
										
										
											2025-01-04 12:22:53 +00:00
										 |  |  |         $config = self::get($category, $key); | 
					
						
							|  |  |  |         if (!$config) return ''; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $message = $customMessage ?? $config['message']; | 
					
						
							| 
									
										
										
										
											2025-01-07 11:02:57 +00:00
										 |  |  |         $isDismissible = $dismissible ?? $config['dismissible'] ?? false; | 
					
						
							| 
									
										
										
										
											2025-01-06 09:13:28 +00:00
										 |  |  |         $dismissClass = $isDismissible ? ' alert-dismissible fade show' : ''; | 
					
						
							| 
									
										
										
										
											2025-01-06 09:43:20 +00:00
										 |  |  |         $dismissButton = $isDismissible ? '<button type="button" class="btn-close' . ($small ? ' btn-close-sm' : '') . '" data-bs-dismiss="alert" aria-label="Close"></button>' : ''; | 
					
						
							|  |  |  |         $smallClass = $small ? ' alert-sm' : ''; | 
					
						
							| 
									
										
										
										
											2025-01-04 12:22:53 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |         return sprintf( | 
					
						
							| 
									
										
										
										
											2025-01-06 09:43:20 +00:00
										 |  |  |             '<div class="alert alert-%s%s%s" role="alert">%s%s</div>', | 
					
						
							| 
									
										
										
										
											2025-01-04 12:22:53 +00:00
										 |  |  |             $config['type'], | 
					
						
							| 
									
										
										
										
											2025-01-06 09:13:28 +00:00
										 |  |  |             $dismissClass, | 
					
						
							| 
									
										
										
										
											2025-01-06 09:43:20 +00:00
										 |  |  |             $smallClass, | 
					
						
							| 
									
										
										
										
											2025-01-15 16:22:49 +00:00
										 |  |  |             $sanitize ? htmlspecialchars($message) : $message, | 
					
						
							| 
									
										
										
										
											2025-01-04 12:22:53 +00:00
										 |  |  |             $dismissButton | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-23 10:37:10 +00:00
										 |  |  |     /** | 
					
						
							| 
									
										
										
										
											2025-02-15 08:13:39 +00:00
										 |  |  |      * Get feedback message data for JavaScript | 
					
						
							| 
									
										
										
										
											2025-01-23 10:37:10 +00:00
										 |  |  |      */ | 
					
						
							|  |  |  |     public static function getMessageData($category, $key, $customMessage = null, $dismissible = null, $small = false) { | 
					
						
							|  |  |  |         $config = self::get($category, $key); | 
					
						
							|  |  |  |         if (!$config) return null; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return [ | 
					
						
							|  |  |  |             'type' => $config['type'], | 
					
						
							|  |  |  |             'message' => $customMessage ?? $config['message'], | 
					
						
							|  |  |  |             'dismissible' => $dismissible ?? $config['dismissible'] ?? false, | 
					
						
							|  |  |  |             'small' => $small | 
					
						
							|  |  |  |         ]; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-04 12:22:53 +00:00
										 |  |  |     /** | 
					
						
							| 
									
										
										
										
											2025-02-15 08:13:39 +00:00
										 |  |  |      * Store feedback message in session for display after redirect | 
					
						
							| 
									
										
										
										
											2025-01-04 12:22:53 +00:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2025-02-15 08:13:39 +00:00
										 |  |  |     // Usage: Feedback::flash('LOGIN', 'LOGIN_SUCCESS', 'custom message [or null]', true [for dismissible; or null], true [for small; or omit]);
 | 
					
						
							| 
									
										
										
										
											2025-01-07 11:02:57 +00:00
										 |  |  |     public static function flash($category, $key, $customMessage = null, $dismissible = null, $small = false) { | 
					
						
							| 
									
										
										
										
											2025-01-04 12:22:53 +00:00
										 |  |  |         if (!isset($_SESSION['flash_messages'])) { | 
					
						
							|  |  |  |             $_SESSION['flash_messages'] = []; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2025-01-07 11:02:57 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-15 08:13:39 +00:00
										 |  |  |         // Get the feedback message configuration
 | 
					
						
							| 
									
										
										
										
											2025-01-07 11:02:57 +00:00
										 |  |  |         $config = self::get($category, $key); | 
					
						
							|  |  |  |         $isDismissible = $dismissible ?? $config['dismissible'] ?? false; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-04 12:22:53 +00:00
										 |  |  |         $_SESSION['flash_messages'][] = [ | 
					
						
							|  |  |  |             'category' => $category, | 
					
						
							|  |  |  |             'key' => $key, | 
					
						
							| 
									
										
										
										
											2025-01-06 09:13:28 +00:00
										 |  |  |             'custom_message' => $customMessage, | 
					
						
							| 
									
										
										
										
											2025-01-07 11:02:57 +00:00
										 |  |  |             'dismissible' => $isDismissible, | 
					
						
							| 
									
										
										
										
											2025-01-06 09:43:20 +00:00
										 |  |  |             'small' => $small | 
					
						
							| 
									
										
										
										
											2025-01-04 12:22:53 +00:00
										 |  |  |         ]; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							| 
									
										
										
										
											2025-02-15 08:13:39 +00:00
										 |  |  |      * Get and clear all flash feedback messages | 
					
						
							| 
									
										
										
										
											2025-01-04 12:22:53 +00:00
										 |  |  |      */ | 
					
						
							|  |  |  |     public static function getFlash() { | 
					
						
							| 
									
										
										
										
											2025-02-15 08:13:39 +00:00
										 |  |  |         $system_messages = $_SESSION['flash_messages'] ?? []; | 
					
						
							| 
									
										
										
										
											2025-01-04 12:22:53 +00:00
										 |  |  |         unset($_SESSION['flash_messages']); | 
					
						
							| 
									
										
										
										
											2025-02-15 08:13:39 +00:00
										 |  |  |         return $system_messages; | 
					
						
							| 
									
										
										
										
											2025-01-04 12:22:53 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | } |