getThemeName(); } public function hasStylesheet() { $cssFilename = sprintf('%s/%s/theme.css', $this->getThemePublicPath(), $this->getThemeName()); return file_exists($cssFilename); } public static function gravatarUrl($emailAddress, $size = 48, $default = 'identicon') { $hash = md5(strtolower(trim($emailAddress))); return sprintf('https://www.gravatar.com/avatar/%s?s=%d&d=%s', $hash, $size, $default); } public function info() { $themeName = $this->getThemeName(); $jsonFile = sprintf('%s/%s/theme.json', $this->getThemePrivatePath(), $this->sanitiseThemeName($themeName)); if (file_exists($jsonFile)) { return json_decode(file_get_contents($jsonFile), true); } return array(); } public function render($viewPath, array $viewData = array()) { return view($this->viewName($viewPath), $viewData); } public function viewName($viewPath) { $themeName = $this->getThemeName(); // First see if the current theme has the specified file $requestedViewFilename = $this->getRealFilePath($themeName, $viewPath); if (!file_exists($requestedViewFilename)) { // If it doesn't, revert to the base theme // TODO allow themes to specify another theme as the parent, and traverse up the theme tree to find the // relevant file - this allows for sub-themes $themeName = ThemeHelper::DEFAULT_THEME; } return sprintf('themes.%s.%s', $themeName, $viewPath); } private function getRealFilePath($themeName, $viewPath) { return sprintf( '%s/%s/%s.blade.php', $this->getThemePrivatePath(), $themeName, str_replace('.', DIRECTORY_SEPARATOR, $viewPath) ); } private function getThemePrivatePath() { return sprintf('%s/resources/views/themes', dirname(dirname(__DIR__))); } private function getThemePublicPath() { return sprintf('%s/public/themes', dirname(dirname(__DIR__))); } private function getThemeName() { return $this->sanitiseThemeName(UserConfig::get('theme')); } private function sanitiseThemeName($themeName) { // Ensure nasty people can't try and trick us into traversing the directory tree return preg_replace('/[\\\.\/]/', '', strtolower($themeName)); } }