"0xffffff", "docBg1" => "0xffffff", "docBg2" => "0xffffff", "xText" => "0x33485c", "yText" => "0x33485c", "title" => "0x333333", "misc" => "0x999999", "altBorder" => "0xffffff", "altBg" => "0xffffff", "altText" => "0x666666", "graphBorder" => "0xcccccc", "graphBg1" => "0xf6f6f6", "graphBg2" => "0xf6f6f6", "graphLines" => "0xcccccc", "graphText" => "0x333333", "graphTextShadow" => "0xf9f9f9", "barBorder" => "0xeeeeee", "barBorderHilite" => "0x333333", "legendBorder" => "0xffffff", "legendBg1" => "0xffffff", "legendBg2" => "0xffffff", "legendText" => "0x444444", "legendColorKeyBorder" => "0x777777", "scrollBar" => "0xcccccc", "scrollBarBorder" => "0xeeeeee", "scrollBarTrack" => "0xeeeeee", "scrollBarTrackBorder" => "0xcccccc", ); /** * Colors used in pie charts * * @var array */ protected $pieChartColors = array( "docBorder" => "0xffffff", "docBg1" => "0xffffff", "docBg2" => "0xffffff", "title" => "0x333333", "subtitle" => "0x666666", "misc" => "0x999999", "altBorder" => "0xffffff", "altBg" => "0xffffff", "altText" => "0x666666", "graphText" => "0x33485c", "graphTextShadow" => "0xf9f9f9", "pieBorder" => "0xffffff", "pieBorderHilite" => "0x333333", "legendBorder" => "0xffffff", "legendBg1" => "0xffffff", "legendBg2" => "0xffffff", "legendText" => "0x444444", "legendColorKeyBorder" => "0x777777", "scrollBar" => "0xdfdfdf", "scrollBarBorder" => "0xfafafa", "scrollBarTrack" => "0xeeeeee", "scrollBarTrackBorder" => "0xcccccc", ); /** * Cache built of all css files locations * * @var array */ private $_cssCache = array(); /** * Cache built of all image files locations * * @var array */ private $_imageCache = array(); /** * Cache built of all javascript files locations * * @var array */ private $_jsCache = array(); /** * Cache built of all template files locations * * @var array */ private $_templateCache = array(); /** * Size of the caches after the are initialized in the constructor * * @var array */ private $_initialCacheSize = array( 'cssCache' => 0, 'imageCache' => 0, 'jsCache' => 0, 'templateCache' => 0, ); /** * Controls whether or not to clear the cache on destroy; defaults to false */ private $_clearCacheOnDestroy = false; private $imageExtensions = array( 'gif', 'png', 'jpg', 'tif', 'bmp', ); /** * Constructor * * Sets the theme properties from the defaults passed to it, and loads the file path cache from an external cache * * @param $defaults string defaults for the current theme */ public function __construct( $defaults ) { $this->cached_results= array(); if (isset($defaults['parentTheme'])) { $themedef = array(); include("themes/{$defaults['parentTheme']}/themedef.php"); foreach ($themedef as $key => $value) { if (property_exists(__CLASS__, $key)) { // For all arrays ( except colors and fonts ) you can just specify the items // to change instead of all of the values if (is_array($this->$key) && !in_array($key, array('colors', 'fonts'))) { $this->$key = array_merge($this->$key, $value); } else { $this->$key = $value; } } } } foreach ($defaults as $key => $value) { if (property_exists(__CLASS__, $key)) { // For all arrays ( except colors and fonts ) you can just specify the items // to change instead of all of the values if (is_array($this->$key) && !in_array($key, array('colors', 'fonts'))) { $this->$key = array_merge($this->$key, $value); } else { $this->$key = $value; } } } if (!inDeveloperMode()) { // load stored theme cache from sugar cache if it's there if ($GLOBALS['external_cache_enabled'] && $GLOBALS['external_cache_type'] != 'base-in-memory') { $this->_jsCache = sugar_cache_retrieve('theme_' . $this->dirName . '_jsCache'); $this->_cssCache = sugar_cache_retrieve('theme_' . $this->dirName . '_cssCache'); $this->_imageCache = sugar_cache_retrieve('theme_' . $this->dirName . '_imageCache'); $this->_templateCache = sugar_cache_retrieve('theme_' . $this->dirName . '_templateCache'); } // otherwise, see if we serialized them to a file elseif (sugar_is_file($GLOBALS['sugar_config']['cache_dir'] . $this->getFilePath() . '/pathCache.php')) { $caches = unserialize(file_get_contents($GLOBALS['sugar_config']['cache_dir'] . $this->getFilePath() . '/pathCache.php')); if (isset($caches['jsCache'])) { $this->_jsCache = $caches['jsCache']; } if (isset($caches['cssCache'])) { $this->_cssCache = $caches['cssCache']; } if (isset($caches['imageCache'])) { $this->_imageCache = $caches['imageCache']; } if (isset($caches['templateCache'])) { $this->_templateCache = $caches['templateCache']; } } } $this->_initialCacheSize = array( 'jsCache' => count($this->_jsCache), 'cssCache' => count($this->_cssCache), 'imageCache' => count($this->_imageCache), 'templateCache' => count($this->_templateCache), ); } /** * Destructor * Here we'll write out the internal file path caches to an external cache of some sort. */ public function __destruct() { // Bug 28309 - Set the current directory to one which we expect it to be (i.e. the root directory of the install set_include_path(realpath(dirname(__FILE__) . '/../..') . PATH_SEPARATOR . get_include_path()); chdir(realpath(dirname(__FILE__) . '/../..')); // Bug 30807/30808 - Re-setup the external cache since the object isn't there when calling this method. $GLOBALS['external_cache_checked'] = false; check_cache(); // clear out the cache on destroy if we are asked to if ($this->_clearCacheOnDestroy) { if (is_file($GLOBALS['sugar_config']['cache_dir'] . $this->getFilePath() . '/pathCache.php')) unlink($GLOBALS['sugar_config']['cache_dir'] . $this->getFilePath() . '/pathCache.php'); if ($GLOBALS['external_cache_enabled'] && $GLOBALS['external_cache_type'] != 'base-in-memory') { sugar_cache_clear('theme_' . $this->dirName . '_jsCache'); sugar_cache_clear('theme_' . $this->dirName . '_cssCache'); sugar_cache_clear('theme_' . $this->dirName . '_imageCache'); sugar_cache_clear('theme_' . $this->dirName . '_templateCache'); } } elseif (!inDeveloperMode()) { // push our cache into the sugar cache if ($GLOBALS['external_cache_enabled'] && $GLOBALS['external_cache_type'] != 'base-in-memory') { // only update the caches if they have been changed in this request if (count($this->_jsCache) != $this->_initialCacheSize['jsCache']) sugar_cache_put('theme_' . $this->dirName . '_jsCache', $this->_jsCache); if (count($this->_cssCache) != $this->_initialCacheSize['cssCache']) sugar_cache_put('theme_' . $this->dirName . '_cssCache', $this->_cssCache); if (count($this->_imageCache) != $this->_initialCacheSize['imageCache']) sugar_cache_put('theme_' . $this->dirName . '_imageCache', $this->_imageCache); if (count($this->_templateCache) != $this->_initialCacheSize['templateCache']) sugar_cache_put('theme_' . $this->dirName . '_templateCache', $this->_templateCache); } // fallback in case there is no useful external caching available // only update the caches if they have been changed in this request elseif (count($this->_jsCache) != $this->_initialCacheSize['jsCache'] || count($this->_cssCache) != $this->_initialCacheSize['cssCache'] || count($this->_imageCache) != $this->_initialCacheSize['imageCache'] || count($this->_templateCache) != $this->_initialCacheSize['templateCache'] ) { sugar_file_put_contents( create_cache_directory($this->getFilePath() . '/pathCache.php'), serialize( array( 'jsCache' => $this->_jsCache, 'cssCache' => $this->_cssCache, 'imageCache' => $this->_imageCache, 'templateCache' => $this->_templateCache, ) ) ); } } // clear out the cache if we are in developerMode // ( so it will be freshly rebuilt for the next load ) elseif ($GLOBALS['external_cache_enabled']) { sugar_cache_clear('theme_' . $this->dirName . '_jsCache'); sugar_cache_clear('theme_' . $this->dirName . '_cssCache'); sugar_cache_clear('theme_' . $this->dirName . '_imageCache'); sugar_cache_clear('theme_' . $this->dirName . '_templateCache'); } } /** * Specifies what is returned when the object is cast to a string, in this case it will be the * theme directory name. * * @return string theme directory name */ public function __toString() { return $this->dirName; } /** * Generic public accessor method for all the properties of the theme ( which are kept protected ) * * @return string */ public function __get( $key ) { if (isset($this->$key)) return $this->$key; } public function __isset($key) { return isset($this->$key); } /** * Clears out the caches used for this themes */ public function clearCache() { $this->_clearCacheOnDestroy = true; } /** * Return array of all valid fields that can be specified in the themedef.php file * * @return array */ public static function getThemeDefFields() { return array( 'name', 'description', 'dirName', 'parentTheme', 'version', 'colors', 'fonts', 'barChartColors', 'pieChartColors', ); } /** * Returns the file path of the current theme * * @return string */ public function getFilePath() { return 'themes/' . $this->dirName; } /** * Returns the image path of the current theme * * @return string */ public function getImagePath() { return $this->getFilePath() . '/images'; } /** * Returns the css path of the current theme * * @return string */ public function getCSSPath() { return $this->getFilePath() . '/css'; } /** * Returns the javascript path of the current theme * * @return string */ public function getJSPath() { return $this->getFilePath() . '/js'; } /** * Returns the tpl path of the current theme * * @return string */ public function getTemplatePath() { return $this->getFilePath() . '/tpls'; } /** * Returns the file path of the theme defaults * * @return string */ public final function getDefaultFilePath() { return 'themes/default'; } /** * Returns the image path of the theme defaults * * @return string */ public final function getDefaultImagePath() { return $this->getDefaultFilePath() . '/images'; } /** * Returns the css path of the theme defaults * * @return string */ public final function getDefaultCSSPath() { return $this->getDefaultFilePath() . '/css'; } /** * Returns the template path of the theme defaults * * @return string */ public final function getDefaultTemplatePath() { return $this->getDefaultFilePath() . '/tpls'; } /** * Returns the javascript path of the theme defaults * * @return string */ public final function getDefaultJSPath() { return $this->getDefaultFilePath() . '/js'; } /** * Returns CSS for the current theme. * * @param $color string optional, specifies the css color file to use if the theme supports it; defaults to cookie value or theme default * @param $font string optional, specifies the css font file to use if the theme supports it; defaults to cookie value or theme default * @return string HTML code */ public function getCSS( $color = null, $font = null ) { // include style.css file $html = ''; $html .= ''; $html .= ''; // for BC during upgrade if (!empty($this->colors)) { if (isset($_SESSION['authenticated_user_theme_color']) && in_array($_SESSION['authenticated_user_theme_color'], $this->colors)) $color = $_SESSION['authenticated_user_theme_color']; else $color = $this->colors[0]; $html .= ''; } if (!empty($this->fonts)) { if (isset($_SESSION['authenticated_user_theme_font']) && in_array($_SESSION['authenticated_user_theme_font'], $this->fonts)) $font = $_SESSION['authenticated_user_theme_font']; else $font = $this->fonts[0]; $html .= ''; } return $html; } /** * Returns javascript for the current theme * * @return string HTML code */ public function getJS() { $styleJS = $this->getJSURL('style.js'); return << EOHTML; } /** * Returns the path for the tpl file in the current theme. If not found in the current theme, will revert * to looking in the base theme. * * @param string $templateName tpl file name * @return string path of tpl file to include */ public function getTemplate( $templateName ) { if (isset($this->_templateCache[$templateName])) { return $this->_templateCache[$templateName]; } $templatePath = ''; if (sugar_is_file('custom/' . $this->getTemplatePath() . '/' . $templateName)) $templatePath = 'custom/' . $this->getTemplatePath() . '/' . $templateName; elseif (sugar_is_file($this->getTemplatePath() . '/' . $templateName)) $templatePath = $this->getTemplatePath() . '/' . $templateName; elseif (isset($this->parentTheme) && SugarThemeRegistry::get($this->parentTheme) instanceOf SugarTheme && ($filename = SugarThemeRegistry::get($this->parentTheme)->getTemplate($templateName)) != '') $templatePath = $filename; elseif (sugar_is_file('custom/' . $this->getDefaultTemplatePath() . '/' . $templateName)) $templatePath = 'custom/' . $this->getDefaultTemplatePath() . '/' . $templateName; elseif (sugar_is_file($this->getDefaultTemplatePath() . '/' . $templateName)) $templatePath = $this->getDefaultTemplatePath() . '/' . $templateName; else { $GLOBALS['log']->warn("Template $templateName not found"); return false; } $this->_imageCache[$templateName] = $templatePath; return $templatePath; } /** * Returns an image tag for the given image. * * @param string $image image name * @param string $other_attributes optional, other attributes to add to the image tag, not cached * @param string $width optional, defaults to the actual image's width * @param string $height optional, defaults to the actual image's height * @return string HTML image tag */ public function getImage( $imageName, $other_attributes = '', $width = null, $height = null, $ext = '.gif' ) { $cached_results = $this->cached_results; // static $cached_results = array(); $imageName .= $ext; if (!empty($cached_results[$imageName])) { return $cached_results[$imageName] . "$other_attributes />"; } $imageURL = $this->getImageURL($imageName, false); if (empty($imageURL)) { return false; } $size = getimagesize($imageURL); if (is_null($width)) { $width = $size[0]; } if (is_null($height)) { $height = $size[1]; } // Cache everything but the other attributes.... $cached_results[$imageName] = "cached_results[$imageName] = ""; } /** * Returns the URL for an image in the current theme. If not found in the current theme, will revert * to looking in the base theme. * * @param string $imageName image file name * @param bool $addJSPath call getJSPath() with the results to add some unique image tracking support * @return string path to image */ public function getImageURL( $imageName, $addJSPath = true ) { if (isset($this->_imageCache[$imageName])) { if ($addJSPath) { return getJSPath($this->_imageCache[$imageName]); } else { return $this->_imageCache[$imageName]; } } $imagePath = ''; if (($filename = $this->_getImageFileName('custom/' . $this->getImagePath() . '/' . $imageName)) != '') { $imagePath = $filename; } elseif (($filename = $this->_getImageFileName($this->getImagePath() . '/' . $imageName)) != '') { $imagePath = $filename; } elseif (isset($this->parentTheme) && SugarThemeRegistry::get($this->parentTheme) instanceOf SugarTheme && ($filename = SugarThemeRegistry::get($this->parentTheme)->getImageURL($imageName, false)) != '') { $imagePath = $filename; } elseif (($filename = $this->_getImageFileName('custom/' . $this->getDefaultImagePath() . '/' . $imageName)) != '') { $imagePath = $filename; } elseif (($filename = $this->_getImageFileName($this->getDefaultImagePath() . '/' . $imageName)) != '') { $imagePath = $filename; } else { $GLOBALS['log']->warn("Image $imageName not found"); return false; } $this->_imageCache[$imageName] = $imagePath; if ($addJSPath) { return getJSPath($imagePath); } return $imagePath; } /** * Checks for an image using all of the accepted image extensions * * @param string $imageName image file name * @return string path to image */ protected function _getImageFileName( $imageName ) { // return now if the extension matches that of which we are looking for if (sugar_is_file($imageName)) return $imageName; $pathParts = pathinfo($imageName); foreach ($this->imageExtensions as $extension) if (isset($pathParts['extension'])) if (( $extension != $pathParts['extension'] ) && sugar_is_file($pathParts['dirname'] . '/' . $pathParts['filename'] . '.' . $extension)) return $pathParts['dirname'] . '/' . $pathParts['filename'] . '.' . $extension; return ''; } /** * Returns the URL for the css file in the current theme. If not found in the current theme, will revert * to looking in the base theme. * * @param string $cssFileName css file name * @param bool $addJSPath call getJSPath() with the results to add some unique image tracking support * @return string path of css file to include */ public function getCSSURL( $cssFileName, $addJSPath = true ) { if (isset($this->_cssCache[$cssFileName])) { if ($addJSPath) return getJSPath($this->_cssCache[$cssFileName]); else return $this->_cssCache[$cssFileName]; } $cssFileContents = ''; if (isset($this->parentTheme) && SugarThemeRegistry::get($this->parentTheme) instanceOf SugarTheme && ($filename = SugarThemeRegistry::get($this->parentTheme)->getCSSURL($cssFileName, false)) != '') $cssFileContents .= file_get_contents($filename); else { if (sugar_is_file($this->getDefaultCSSPath() . '/' . $cssFileName)) $cssFileContents .= file_get_contents($this->getDefaultCSSPath() . '/' . $cssFileName); if (sugar_is_file('custom/' . $this->getDefaultCSSPath() . '/' . $cssFileName)) $cssFileContents .= file_get_contents('custom/' . $this->getDefaultCSSPath() . '/' . $cssFileName); } if (sugar_is_file($this->getCSSPath() . '/' . $cssFileName)) $cssFileContents .= file_get_contents($this->getCSSPath() . '/' . $cssFileName); if (sugar_is_file('custom/' . $this->getCSSPath() . '/' . $cssFileName)) $cssFileContents .= file_get_contents('custom/' . $this->getCSSPath() . '/' . $cssFileName); if (empty($cssFileContents)) { $GLOBALS['log']->warn("CSS File $cssFileName not found"); return false; } // fix any image references that may be defined in css files $cssFileContents = str_ireplace("entryPoint=getImage&", "entryPoint=getImage&themeName={$this->dirName}&", $cssFileContents); // create the cached file location $cssFilePath = create_cache_directory($this->getCSSPath() . "/$cssFileName"); // if this is the style.css file, prepend the base.css and calendar-win2k-cold-1.css // files before the theme styles if ($cssFileName == 'style.css' && !isset($this->parentTheme)) { $cssFileContents = file_get_contents('jscalendar/calendar-win2k-cold-1.css') . $cssFileContents; if (inDeveloperMode()) $cssFileContents = file_get_contents('include/javascript/yui/build/base/base.css') . $cssFileContents; else $cssFileContents = file_get_contents('include/javascript/yui/build/base/base-min.css') . $cssFileContents; } // minify the css if (!inDeveloperMode() && !sugar_is_file($cssFilePath)) { $cssFileContents = cssmin::minify($cssFileContents); } // now write the css to cache sugar_file_put_contents($cssFilePath, $cssFileContents); $this->_cssCache[$cssFileName] = $cssFilePath; if ($addJSPath) return getJSPath($cssFilePath); return $cssFilePath; } /** * Returns the URL for an image in the current theme. If not found in the current theme, will revert * to looking in the base theme. * * @param string $jsFileName js file name * @param bool $addJSPath call getJSPath() with the results to add some unique image tracking support * @return string path to js file */ public function getJSURL( $jsFileName, $addJSPath = true ) { if (isset($this->_jsCache[$jsFileName])) { if ($addJSPath) return getJSPath($this->_jsCache[$jsFileName]); else return $this->_jsCache[$jsFileName]; } $jsFileContents = ''; if (isset($this->parentTheme) && SugarThemeRegistry::get($this->parentTheme) instanceOf SugarTheme && ($filename = SugarThemeRegistry::get($this->parentTheme)->getJSURL($jsFileName, false)) != '') $jsFileContents .= file_get_contents($filename); else { if (sugar_is_file($this->getDefaultJSPath() . '/' . $jsFileName)) $jsFileContents .= file_get_contents($this->getDefaultJSPath() . '/' . $jsFileName); if (sugar_is_file('custom/' . $this->getDefaultJSPath() . '/' . $jsFileName)) $jsFileContents .= file_get_contents('custom/' . $this->getDefaultJSPath() . '/' . $jsFileName); } if (sugar_is_file($this->getJSPath() . '/' . $jsFileName)) $jsFileContents .= file_get_contents($this->getJSPath() . '/' . $jsFileName); if (sugar_is_file('custom/' . $this->getJSPath() . '/' . $jsFileName)) $jsFileContents .= file_get_contents('custom/' . $this->getJSPath() . '/' . $jsFileName); if (empty($jsFileContents)) { $GLOBALS['log']->warn("Javascript File $jsFileName not found"); return false; } // create the cached file location $jsFilePath = create_cache_directory($this->getJSPath() . "/$jsFileName"); // minify the js if (!inDeveloperMode() && !sugar_is_file(str_replace('.js', '-min.js', $jsFilePath))) { $jsFileContents = JSMin::minify($jsFileContents); $jsFilePath = str_replace('.js', '-min.js', $jsFilePath); } // now write the js to cache sugar_file_put_contents($jsFilePath, $jsFileContents); $this->_jsCache[$jsFileName] = $jsFilePath; if ($addJSPath) return getJSPath($jsFilePath); return $jsFilePath; } /** * Returns an array of all of the images available for the current theme * * @return array */ public function getAllImages() { // first, lets get all the paths of where to look $pathsToSearch = array($this->getImagePath()); $theme = $this; while (isset($theme->parentTheme) && SugarThemeRegistry::get($theme->parentTheme) instanceOf SugarTheme) { $theme = SugarThemeRegistry::get($theme->parentTheme); $pathsToSearch[] = $theme->getImagePath(); } $pathsToSearch[] = $this->getDefaultImagePath(); // now build the array $imageArray = array(); foreach ($pathsToSearch as $path) { if (!sugar_is_dir($path)) $path = "custom/$path"; if (sugar_is_dir($path) && $dir = opendir($path)) { while (($file = readdir($dir)) !== false) { if ($file == ".." || $file == "." || $file == ".svn" || $file == "CVS" || $file == "Attic" ) continue; if (!isset($imageArray[$file])) $imageArray[$file] = $this->getImageURL($file, false); } closedir($dir); } } ksort($imageArray); return $imageArray; } } /** * Registry for all the current classes in the system */ class SugarThemeRegistry { /** * Array of all themes and thier object * * @var array */ private static $_themes = array(); /** * Name of the current theme; corresponds to an index key in SugarThemeRegistry::$_themes * * @var string */ private static $_currentTheme; /** * Disable the constructor since this will be a singleton */ private function __construct() { } /** * Adds a new theme to the registry * * @param $themedef array */ public static function add( array $themedef ) { // make sure the we know the sugar version if (!isset($GLOBALS['sugar_version'])) { include('sugar_version.php'); $GLOBALS['sugar_version'] = $sugar_version; } // Assume theme is designed for 5.5.x if not specified otherwise if (!isset($themedef['version'])) $themedef['version']['regex_matches'] = array('5\.5\.*'); // Check to see if theme is valid for this version of Sugar; return false if not $version_ok = false; if (isset($themedef['version']['exact_matches'])) { $matches_empty = false; foreach ($themedef['version']['exact_matches'] as $match) { if ($match == $GLOBALS['sugar_version']) { $version_ok = true; } } } if (!$version_ok && isset($themedef['version']['regex_matches'])) { $matches_empty = false; foreach ($themedef['version']['regex_matches'] as $match) { if (preg_match("/$match/", $GLOBALS['sugar_version'])) { $version_ok = true; } } } if (!$version_ok) return false; $theme = new SugarTheme($themedef); self::$_themes[$theme->dirName] = $theme; } /** * Removes a new theme from the registry * * @param $themeName string */ public static function remove( $themeName ) { if (self::exists($themeName)) unset(self::$_themes[$themeName]); } /** * Returns a theme object in the registry specified by the given $themeName * * @param $themeName string */ public static function get( $themeName ) { if (isset(self::$_themes[$themeName])) return self::$_themes[$themeName]; } /** * Returns the current theme object * */ public static function current() { if (!isset(self::$_currentTheme)) self::buildRegistry(); return self::$_themes[self::$_currentTheme]; } /** * Returns true if a theme object specified by the given $themeName exists in the registry * * @param $themeName string * @return bool */ public static function exists( $themeName ) { return (self::get($themeName) !== null); } /** * Sets the given $themeName to be the current theme * * @param $themeName string */ public static function set( $themeName ) { if (!self::exists($themeName)) return false; self::$_currentTheme = $themeName; // set some of the expected globals $GLOBALS['barChartColors'] = self::current()->barChartColors; $GLOBALS['pieChartColors'] = self::current()->pieChartColors; } /** * Builds the theme registry */ public static function buildRegistry() { self::$_themes = array(); $dirs = array("themes/", "custom/themes/"); // check for a default themedef file $themedefDefault = array(); if (sugar_is_file("custom/themes/default/themedef.php")) { $themedef = array(); require("custom/themes/default/themedef.php"); $themedefDefault = $themedef; } foreach ($dirs as $dirPath) { if (sugar_is_dir('./' . $dirPath) && $dir = opendir('./' . $dirPath)) { while (($file = readdir($dir)) !== false) { if ($file == ".." || $file == "." || $file == ".svn" || $file == "CVS" || $file == "Attic" || $file == "default" || !sugar_is_dir("./$dirPath" . $file) || !sugar_is_file("./{$dirPath}{$file}/themedef.php") ) continue; $themedef = array(); require("./{$dirPath}{$file}/themedef.php"); $themedef = array_merge($themedef, $themedefDefault); $themedef['dirName'] = $file; // check for theme already existing in the registry // if so, then it will override the current one if (self::exists($themedef['dirName'])) { $existingTheme = self::get($themedef['dirName']); foreach (SugarTheme::getThemeDefFields() as $field) if (!isset($themedef[$field])) $themedef[$field] = $existingTheme->$field; self::remove($themedef['dirName']); } if (isset($themedef['name'])) { self::add($themedef); } } closedir($dir); } } // default to setting the default theme as the current theme if (!self::set($GLOBALS['sugar_config']['default_theme'])) { if (count(self::availableThemes()) == 0) sugar_die('No valid themes are found on this instance'); else self::set(array_pop(array_keys(self::availableThemes()))); } } /** * Returns an array of available themes. Designed to be absorbed into get_select_options_with_id() * * @return array */ public static function availableThemes() { $themelist = array(); $disabledThemes = array(); if (isset($GLOBALS['sugar_config']['disabled_themes'])) $disabledThemes = explode(',', $GLOBALS['sugar_config']['disabled_themes']); foreach (self::$_themes as $themename => $themeobject) { if (in_array($themename, $disabledThemes)) continue; $themelist[$themeobject->dirName] = $themeobject->name; } asort($themelist, SORT_STRING); return $themelist; } /** * Returns an array of un-available themes. Designed used with the theme selector in the admin panel * * @return array */ public static function unAvailableThemes() { $themelist = array(); $disabledThemes = array(); if (isset($GLOBALS['sugar_config']['disabled_themes'])) $disabledThemes = explode(',', $GLOBALS['sugar_config']['disabled_themes']); foreach (self::$_themes as $themename => $themeobject) { if (in_array($themename, $disabledThemes)) $themelist[$themeobject->dirName] = $themeobject->name; } return $themelist; } /** * Returns an array of all themes found in the current installation * * @return array */ public static function allThemes() { $themelist = array(); foreach (self::$_themes as $themename => $themeobject) $themelist[$themeobject->dirName] = $themeobject->name; return $themelist; } /** * Clears out the cached path locations for all themes */ public static function clearAllCaches() { foreach (self::$_themes as $themeobject) { $themeobject->clearCache(); } } }