public static function create($name = null, $template_engine = null, $theme_dir = null)
{
static $bound = array();
$hash = md5(serialize(array($name, $template_engine, $theme_dir)));
if (isset($bound[$hash])) {
return $bound[$hash];
}
// If the name is not supplied, load the active theme
if (empty($name)) {
$themedata = self::get_active();
if (empty($themedata)) {
die(_t('Theme not installed.'));
}
} else {
$themedata = self::get_by_name($name);
}
// If a theme wasn't found by name, create a blank object
if (!$themedata) {
$themedata = array();
$themedata['name'] = $name;
$themedata['version'] = 0;
}
// If a specific template engine was supplied, use it
if (!empty($template_engine)) {
$themedata['template_engine'] = $template_engine;
}
// If a theme directory was supplied, use the directory that was supplied
if (!empty($theme_dir)) {
$themedata['theme_dir'] = $theme_dir;
}
// Set the default theme file
$themefile = 'theme.php';
if (isset($themedata['info']->class['file']) && (string) $themedata['info']->class['file'] != '') {
$themefile = (string) $themedata->xml->class['file'];
}
// Convert themedata to QueryRecord for legacy purposes
// @todo: Potentially break themes by sending an array to the constructor instead of this QueryRecord
$themedata = new QueryRecord($themedata);
// Set the default fallback theme class, which a parent can override
$fallback_classname = '\\Habari\\Theme';
// Deal with parent themes
if (isset($themedata->parent)) {
// @todo If the parent theme doesn't exist, provide a useful error
$parent_data = self::get_by_name($themedata->parent);
$parent_themefile = 'theme.php';
if (isset($parent_data['info']->class['file']) && (string) $parent_data['info']->class['file'] != '') {
$parent_themefile = (string) $parent_data['info']->class['file'];
}
include_once $parent_data['theme_dir'] . $parent_themefile;
$themedata->parent_theme_dir = Utils::single_array($parent_data['theme_dir']);
$themedata->theme_dir = array_merge(Utils::single_array($themedata->theme_dir), $themedata->parent_theme_dir);
// Does the parent have a class? If so, set the fallback class name
if (isset($themedata->class)) {
$fallback_classname = $themedata->class;
} else {
$fallback_classname = self::class_from_filename($parent_data['theme_dir'] . $parent_themefile);
}
}
$primary_theme_dir = $themedata->theme_dir;
$primary_theme_dir = is_array($primary_theme_dir) ? reset($primary_theme_dir) : $primary_theme_dir;
// Include the theme class file
if (file_exists($primary_theme_dir . $themefile)) {
include_once $primary_theme_dir . $themefile;
}
if (isset($themedata->class)) {
$classname = $themedata->class;
} else {
$classname = self::class_from_filename($primary_theme_dir . $themefile);
}
// the final fallback, for the admin "theme"
if ($classname == '') {
$classname = $fallback_classname;
}
$created_theme = new $classname($themedata);
$created_theme->upgrade();
Plugins::act_id('init_theme', $created_theme->plugin_id(), $created_theme);
Plugins::act('init_theme_any', $created_theme);
$bound[$hash] = $created_theme;
return $created_theme;
}