210 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			PHP
		
	
			
		
		
	
	
			210 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			PHP
		
	
| <?php
 | |
| 
 | |
| /**
 | |
|  * Theme Helper
 | |
|  *
 | |
|  * Handles theme management and template/asset loading for the application.
 | |
|  * Supports multiple themes with fallback to default theme when needed.
 | |
|  * The default theme uses app/templates and public_html/static as fallbacks/
 | |
|  */
 | |
| 
 | |
| namespace App\Helpers;
 | |
| 
 | |
| use Exception;
 | |
| 
 | |
| class Theme
 | |
| {
 | |
|     /**
 | |
|      * @var array Theme configuration
 | |
|      */
 | |
|     private static $config;
 | |
| 
 | |
|     /**
 | |
|      * @var string Current theme name
 | |
|      */
 | |
|     private static $currentTheme;
 | |
| 
 | |
|     /**
 | |
|      * Initialize the theme system
 | |
|      */
 | |
|     public static function init()
 | |
|     {
 | |
|         self::$config = require __DIR__ . '/../config/theme.php';
 | |
|         self::$currentTheme = self::getCurrentThemeName();
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Get the current theme name
 | |
|      *
 | |
|      * @return string
 | |
|      */
 | |
|     public static function getCurrentThemeName()
 | |
|     {
 | |
|         // Check if already determined
 | |
|         if (self::$currentTheme !== null) {
 | |
|             return self::$currentTheme;
 | |
|         }
 | |
| 
 | |
|         // Get from session if available
 | |
|         if (Session::isValidSession() && ($theme = Session::get('user_theme'))) {
 | |
|             if (self::themeExists($theme)) {
 | |
|                 self::$currentTheme = $theme;
 | |
|                 return $theme;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         // Default to 'default' theme which uses app/templates
 | |
|         self::$currentTheme = 'default';
 | |
|         return 'default';
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Set the current theme for the session
 | |
|      *
 | |
|      * @param string $themeName
 | |
|      * @return bool
 | |
|      */
 | |
|     public static function setCurrentTheme(string $themeName): bool
 | |
|     {
 | |
|         if (!self::themeExists($themeName)) {
 | |
|             return false;
 | |
|         }
 | |
| 
 | |
|         if (Session::isValidSession()) {
 | |
|             Session::set('user_theme', $themeName);
 | |
|         }
 | |
| 
 | |
|         self::$currentTheme = $themeName;
 | |
|         return true;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Check if a theme exists
 | |
|      *
 | |
|      * @param string $themeName
 | |
|      * @return bool
 | |
|      */
 | |
|     public static function themeExists(string $themeName): bool
 | |
|     {
 | |
|         $themePath = self::getThemePath($themeName);
 | |
|         return is_dir($themePath) && file_exists("$themePath/config.php");
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Get the path to a theme
 | |
|      *
 | |
|      * @param string|null $themeName
 | |
|      * @return string
 | |
|      */
 | |
|     public static function getThemePath(?string $themeName = null): string
 | |
|     {
 | |
|         $themeName = $themeName ?? self::getCurrentThemeName();
 | |
|         $config = self::getConfig();
 | |
|         return rtrim($config['paths']['themes'], '/') . "/$themeName";
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Get the URL for a theme asset
 | |
|      *
 | |
|      * @param string $path
 | |
|      * @param bool $includeVersion
 | |
|      * @return string
 | |
|      */
 | |
|     public static function asset($path, $includeVersion = false)
 | |
|     {
 | |
|         $themeName = self::getCurrentThemeName();
 | |
|         $config = self::getConfig();
 | |
|         $baseUrl = rtrim($GLOBALS['app_root'] ?? '', '/');
 | |
| 
 | |
|         // For non-default themes, use theme assets
 | |
|         if ($themeName !== 'default') {
 | |
|             $assetPath = "/themes/{$themeName}/assets/" . ltrim($path, '/');
 | |
| 
 | |
|             // Add version query string for cache busting
 | |
|             if ($includeVersion) {
 | |
|                 $version = self::getThemeVersion($themeName);
 | |
|                 $assetPath .= (strpos($assetPath, '?') !== false ? '&' : '?') . 'v=' . $version;
 | |
|             }
 | |
|         } else {
 | |
|             // For default theme, use public_html directly
 | |
|             $assetPath = '/' . ltrim($path, '/');
 | |
|         }
 | |
| 
 | |
|         return $baseUrl . $assetPath;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Include a theme template
 | |
|      *
 | |
|      * @param string $template
 | |
|      * @param array $data
 | |
|      * @return void
 | |
|      */
 | |
|     public static function include($template, $data = [])
 | |
|     {
 | |
|         $themeName = self::getCurrentThemeName();
 | |
|         $config = self::getConfig();
 | |
| 
 | |
|         // For non-default themes, look in the theme directory
 | |
|         if ($themeName !== 'default') {
 | |
|             $themePath = $config['paths']['themes'] . '/' . $themeName . '/views/' . $template . '.php';
 | |
|             if (file_exists($themePath)) {
 | |
|                 extract($data);
 | |
|                 include $themePath;
 | |
|                 return;
 | |
|             }
 | |
| 
 | |
|             // Fallback to default theme if template not found in custom theme
 | |
|             $legacyPath = $config['paths']['templates'] . '/' . $template . '.php';
 | |
|             if (file_exists($legacyPath)) {
 | |
|                 extract($data);
 | |
|                 include $legacyPath;
 | |
|                 return;
 | |
|             }
 | |
|         } else {
 | |
|             // Default theme uses app/templates
 | |
|             $legacyPath = $config['paths']['templates'] . '/' . $template . '.php';
 | |
|             if (file_exists($legacyPath)) {
 | |
|                 extract($data);
 | |
|                 include $legacyPath;
 | |
|                 return;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         // Log error if template not found
 | |
|         error_log("Template not found: {$template} in theme: {$themeName}");
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Get all available themes
 | |
|      *
 | |
|      * @return array
 | |
|      */
 | |
|     public static function getAvailableThemes(): array
 | |
|     {
 | |
|         $themes = [];
 | |
|         $themesDir = self::$config['path'] ?? (__DIR__ . '/../../themes');
 | |
| 
 | |
|         if (!is_dir($themesDir)) {
 | |
|             return [];
 | |
|         }
 | |
| 
 | |
|         foreach (scandir($themesDir) as $item) {
 | |
|             if ($item === '.' || $item === '..' || !is_dir("$themesDir/$item")) {
 | |
|                 continue;
 | |
|             }
 | |
| 
 | |
|             $configFile = "$themesDir/$item/config.php";
 | |
|             if (file_exists($configFile)) {
 | |
|                 $config = include $configFile;
 | |
|                 $themes[$item] = $config['name'] ?? ucfirst($item);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         return $themes;
 | |
|     }
 | |
| }
 | |
| 
 | |
| // Initialize the theme system
 | |
| Theme::init();
 |