X-Git-Url: https://vcs.fsf.org/?p=squirrelmail.git;a=blobdiff_plain;f=class%2Ftemplate%2FTemplate.class.php;h=3e8361db9750cf94f76bb62c7b24ae6163a7937a;hp=1e91362102f6a933420b67e6713cd0c8208f3c53;hb=c0d968010e710870fdfee2f22d7cc9fad370c7a9;hpb=dfbd28954a0a041b31682bbfbd8b6ffc065efd36 diff --git a/class/template/Template.class.php b/class/template/Template.class.php index 1e913621..3e8361db 100644 --- a/class/template/Template.class.php +++ b/class/template/Template.class.php @@ -1,17 +1,14 @@ * @package squirrelmail * */ @@ -48,10 +50,11 @@ class Template * @var string * */ - var $template_id = ''; + var $template_set_id = ''; /** - * The template directory to use + * The template set base directory (relative path from + * the main SquirrelMail directory (SM_PATH)) * * @var string * @@ -67,62 +70,78 @@ class Template var $template_engine = ''; /** - * The default template ID + * The content type for this template set + */ + var $content_type = ''; + + /** + * The fall-back template ID * * @var string * */ - var $default_template_id = ''; + var $fallback_template_set_id = ''; /** - * The default template directory + * The fall-back template directory (relative + * path from the main SquirrelMail directory (SM_PATH)) * * @var string * */ - var $default_template_dir = ''; + var $fallback_template_dir = ''; /** - * The default template engine (please use constants defined in constants.php) + * The fall-back template engine (please use + * constants defined in constants.php) * * @var string * */ - var $default_template_engine = ''; + var $fallback_template_engine = ''; /** - * Javascript files required by the template + * Template file cache. Structured as an array, whose keys + * are all the template file names (with path information relative + * to the template set's base directory, e.g., "css/style.css") + * found in all parent template sets including the ultimate fall-back + * template set. Array values are sub-arrays with the + * following key-value pairs: * - * @var array + * PATH -- file path, relative to SM_PATH + * SET_ID -- the ID of the template set that this file belongs to + * ENGINE -- the engine needed to render this template file * */ - var $required_js_files = array(); + var $template_file_cache = array(); /** - * Alternate stylesheets provided by the template. This is defined in the - * template config file so that we can provide pretty names in the display - * preferences - * - * @var array - **/ - var $alternate_stylesehets = array(); - + * Extra template engine class objects for rendering templates + * that require a different engine than the one for the current + * template set. Keys should be the name of the template engine, + * values are the corresponding class objects. + * + * @var array + * + */ + var $other_template_engine_objects = array(); + /** * Constructor * * Please do not call directly. Use Template::construct_template(). * - * @param string $template_id the template ID + * @param string $template_set_id the template ID * */ - function Template($template_id) { -//FIXME: find a way to test that this is ONLY ever called + function Template($template_set_id) { +//FIXME: find a way to test that this is ONLY ever called // from the construct_template() method (I doubt it // is worth the trouble to parse the current stack trace) // if (???) // trigger_error('Please do not use default Template() constructor. Instead, use Template::construct_template().', E_USER_ERROR); - $this->set_up_template($template_id); + $this->set_up_template($template_set_id); } @@ -133,143 +152,350 @@ class Template * to get a Template object from the normal/default constructor, * and is necessary in order to control the return value. * - * @param string $template_id the template ID + * @param string $template_set_id the template ID * * @return object The correct Template object for the given template set * + * @static + * */ - function construct_template($template_id) { + function construct_template($template_set_id) { - $template = new Template($template_id); + $template = new Template($template_set_id); + $template->override_plugins(); return $template->get_template_engine_subclass(); } /** - * Set up internal attributes + * Set up internal attributes * - * This method does most of the work for setting up + * This method does most of the work for setting up * newly constructed objects. * - * @param string $template_id the template ID + * @param string $template_set_id the template ID * */ - function set_up_template($template_id) { + function set_up_template($template_set_id) { // FIXME: do we want to place any restrictions on the ID like // making sure no slashes included? // get template ID // - $this->template_id = $template_id; + $this->template_set_id = $template_set_id; - // FIXME: do we want to place any restrictions on the ID like - // making sure no slashes included? - // get default template ID + $this->fallback_template_set_id = Template::get_fallback_template_set(); + + + // set up template directories + // + $this->template_dir + = Template::calculate_template_file_directory($this->template_set_id); + $this->fallback_template_dir + = Template::calculate_template_file_directory($this->fallback_template_set_id); + + + // determine content type, defaulting to text/html + // + $this->content_type = Template::get_template_config($this->template_set_id, + 'content_type', + 'text/html'); + + + // determine template engine + // FIXME: assuming PHP template engine may not necessarily be a good thing + // + $this->template_engine = Template::get_template_config($this->template_set_id, + 'template_engine', + SQ_PHP_TEMPLATE); + + + // get template file cache + // + $this->template_file_cache = Template::cache_template_file_hierarchy($template_set_id); + + } + + /** + * Determine what the ultimate fallback template set is. + * + * NOTE that if the fallback setting cannot be found in the + * main SquirrelMail configuration settings that the value + * of $default is returned. + * + * @param string $default The template set ID to use if + * the fallback setting cannot be + * found in SM config (optional; + * defaults to "default"). + * + * @return string The ID of the fallback template set. + * + * @static + * + */ + function get_fallback_template_set($default='default') { + +// FIXME: do we want to place any restrictions on the ID such as +// making sure no slashes included? + + // values are in main SM config file + // + global $templateset_fallback, $aTemplateSet; + $aTemplateSet = (!isset($aTemplateSet) || !is_array($aTemplateSet) + ? array() : $aTemplateSet); + $templateset_fallback = (!isset($templateset_fallback) + ? $default : $templateset_fallback); + + // iterate through all template sets, is this a valid skin ID? + // + $found_it = FALSE; + foreach ($aTemplateSet as $aTemplate) { + if ($aTemplate['ID'] === $templateset_fallback) { + $found_it = TRUE; + break; + } + } + + if ($found_it) + return $templateset_fallback; + + // FIXME: note that it is possible for $default to + // point to an invalid (nonexistent) template set + // and that error will not be caught here + // + return $default; + + } + + /** + * Determine what the default template set is. + * + * NOTE that if the default setting cannot be found in the + * main SquirrelMail configuration settings that the value + * of $default is returned. + * + * @param string $default The template set ID to use if + * the default setting cannot be + * found in SM config (optional; + * defaults to "default"). + * + * @return string The ID of the default template set. + * + * @static + * + */ + function get_default_template_set($default='default') { + +// FIXME: do we want to place any restrictions on the ID such as +// making sure no slashes included? + + // values are in main SM config file // global $templateset_default, $aTemplateSet; - $aTemplateSet = (!isset($aTemplateSet) || !is_array($aTemplateSet) + $aTemplateSet = (!isset($aTemplateSet) || !is_array($aTemplateSet) ? array() : $aTemplateSet); - $templateset_default = (!isset($templateset_default) ? 0 : $templateset_default); - $this->default_template_id = (!empty($aTemplateSet[$templateset_default]['ID']) - ? $aTemplateSet[$templateset_default]['ID'] - : 'default'); + $templateset_default = (!isset($templateset_default) + ? $default : $templateset_default); + + // iterate through all template sets, is this a valid skin ID? + // + $found_it = FALSE; + foreach ($aTemplateSet as $aTemplate) { + if ($aTemplate['ID'] === $templateset_default) { + $found_it = TRUE; + break; + } + } + if ($found_it) + return $templateset_default; - // set up template directories + // FIXME: note that it is possible for $default to + // point to an invalid (nonexistent) template set + // and that error will not be caught here // - $this->template_dir - = Template::calculate_template_file_directory($this->template_id); - $this->default_template_dir - = Template::calculate_template_file_directory($this->default_template_id); + return $default; + } - // pull in the template config file and load javascript and - // css files needed for this template set + /** + * Determine what the RPC template set is. + * + * NOTE that if the default setting cannot be found in the + * main SquirrelMail configuration settings that the value + * of $default is returned. + * + * @param string $default The template set ID to use if + * the default setting cannot be + * found in SM config (optional; + * defaults to "default_rpc"). + * + * @return string The ID of the RPC template set. + * + * @static + * + */ + function get_rpc_template_set($default='default_rpc') { + +// FIXME: do we want to place any restrictions on the ID such as +// making sure no slashes included? + + // values are in main SM config file // - $template_config_file = SM_PATH . $this->get_template_file_directory() - . 'config.php'; - if (!file_exists($template_config_file)) { + global $rpc_templateset; + $rpc_templateset = (!isset($rpc_templateset) + ? $default : $rpc_templateset); - trigger_error('No template configuration file was found where expected: ("' - . $template_config_file . '")', E_USER_ERROR); + // FIXME: note that it is possible for this to + // point to an invalid (nonexistent) template set + // and that error will not be caught here + // + return $rpc_templateset; - } else { + } - require($template_config_file); - $this->required_js_files = is_array($required_js_files) - ? $required_js_files : array(); - $this->alternate_stylesheets = is_array($alternate_stylesheets) ? - $alternate_stylesheets : - array(); + /** + * Allow template set to override plugin configuration by either + * adding or removing plugins. + * + * NOTE: due to when this code executes, plugins activated here + * do not have access to the config_override and loading_prefs + * hooks; instead, such plugins can use the + * "template_plugins_override_after" hook defined below. + * + */ + function override_plugins() { - } + global $disable_plugins, $plugins, $squirrelmail_plugin_hooks, $null; + if ($disable_plugins) return; + + $add_plugins = Template::get_template_config($this->template_set_id, + 'add_plugins', array()); + $remove_plugins = Template::get_template_config($this->template_set_id, + 'remove_plugins', array()); +//FIXME (?) we assume $add_plugins and $remove_plugins are arrays -- we could +// error check here, or just assume that template authors or admins +// won't screw up their config files - // determine template engine + + // disable all plugins? (can still add some by using $add_plugins) // - if (empty($template_engine)) { - trigger_error('No template engine ($template_engine) was specified in template configuration file: ("' - . $template_config_file . '")', E_USER_ERROR); - } else { - $this->template_engine = $template_engine; + if (in_array('*', $remove_plugins)) { + $plugins = array(); + $squirrelmail_plugin_hooks = array(); + $remove_plugins = array(); } + + foreach ($add_plugins as $plugin_name) { + // add plugin to global plugin array + // + $plugins[] = $plugin_name; + + + // enable plugin -- emulate code from use_plugin() function + // in SquirrelMail core, but also need to call the + // "squirrelmail_plugin_init_" function, which + // in static configuration is not called (this inconsistency + // could be a source of anomalous-seeming bugs in poorly + // coded plugins) + // + if (file_exists(SM_PATH . "plugins/$plugin_name/setup.php")) { + include_once(SM_PATH . "plugins/$plugin_name/setup.php"); + + $function = "squirrelmail_plugin_init_$plugin_name"; + if (function_exists($function)) + $function(); + } + } + + foreach ($remove_plugins as $plugin_name) { + // remove plugin from both global plugin & plugin hook arrays + // + $plugin_key = array_search($plugin_name, $plugins); + if (!is_null($plugin_key) && $plugin_key !== FALSE) { + unset($plugins[$plugin_key]); + if (is_array($squirrelmail_plugin_hooks)) + foreach (array_keys($squirrelmail_plugin_hooks) as $hookName) { + unset($squirrelmail_plugin_hooks[$hookName][$plugin_name]); + } + } + } + + do_hook('template_plugins_override_after', $null); + } /** * Instantiate and return correct subclass for this template * set's templating engine. * + * @param string $template_set_id The template set whose engine + * is to be used as an override + * (if not given, this template + * set's engine is used) (optional). + * * @return object The Template subclass object for the template engine. * */ - function get_template_engine_subclass() { + function get_template_engine_subclass($template_set_id='') { + + if (empty($template_set_id)) $template_set_id = $this->template_set_id; + // FIXME: assuming PHP template engine may not necessarily be a good thing + $engine = Template::get_template_config($template_set_id, + 'template_engine', SQ_PHP_TEMPLATE); - $engine_class_file = SM_PATH . 'class/template/' - . $this->template_engine . 'Template.class.php'; + + $engine_class_file = SM_PATH . 'class/template/' + . $engine . 'Template.class.php'; if (!file_exists($engine_class_file)) { - trigger_error('Unknown template engine (' . $this->template_engine + trigger_error('Unknown template engine (' . $engine . ') was specified in template configuration file', E_USER_ERROR); } - $engine_class = $this->template_engine . 'Template'; - require($engine_class_file); - return new $engine_class($this->template_id); + $engine_class = $engine . 'Template'; + require_once($engine_class_file); + return new $engine_class($template_set_id); } /** - * Determine the relative template directory path for + * Determine the relative template directory path for * the given template ID. * - * @param string $template_id The template ID from which to build - * the directory path + * @param string $template_set_id The template ID from which to build + * the directory path * * @return string The relative template path (based off of SM_PATH) * + * @static + * */ - function calculate_template_file_directory($template_id) { + function calculate_template_file_directory($template_set_id) { - return 'templates/' . $template_id . '/'; + return 'templates/' . $template_set_id . '/'; } /** - * Determine the relative images directory path for + * Determine the relative images directory path for * the given template ID. * - * @param string $template_id The template ID from which to build - * the directory path + * @param string $template_set_id The template ID from which to build + * the directory path * * @return string The relative images path (based off of SM_PATH) * + * @static + * */ - function calculate_template_images_directory($template_id) { + function calculate_template_images_directory($template_set_id) { - return 'templates/' . $template_id . '/images/'; + return 'templates/' . $template_set_id . '/images/'; } @@ -286,149 +512,666 @@ class Template } + /** + * Return the template ID for the fallback template set. + * + * @return string The ID of the fallback template set. + * + */ + function get_fallback_template_set_id() { + + return $this->fallback_template_set_id; + + } /** - * Return the relative template directory path for the DEFAULT template set. + * Return the relative template directory path for the + * fallback template set. * - * @return string The relative path to the default template directory based - * from the main SquirrelMail directory (SM_PATH). + * @return string The relative path to the fallback template + * directory based from the main SquirrelMail + * directory (SM_PATH). * */ - function get_default_template_file_directory() { + function get_fallback_template_file_directory() { - return $this->default_template_dir; + return $this->fallback_template_dir; } + /** + * Return the content-type for this template set. + * + * @return string The content-type. + * + */ + function get_content_type() { + + return $this->content_type; + + } /** - * Find the right template file. + * Get template set config setting + * + * Given a template set ID and setting name, returns the + * setting's value. Note that settings are cached in + * session, so "live" changes to template configuration + * won't be reflected until the user logs out and back + * in again. + * + * @param string $template_set_id The template set for which + * to look up the setting. + * @param string $setting The name of the setting to + * retrieve. + * @param mixed $default When the requested setting + * is not found, the contents + * of this value are returned + * instead (optional; default + * is NULL). + * NOTE that unlike sqGetGlobalVar(), + * this function will also return + * the default value if the + * requested setting is found + * but is empty. + * @param boolean $live_config When TRUE, the target template + * set's configuration file is + * reloaded every time this + * method is called. Default + * behavior is to only load the + * configuration file if it had + * never been loaded before, but + * not again after that (optional; + * default FALSE). Use with care! + * Should mostly be used for + * debugging. + * + * @return mixed The desired setting's value or if not found, + * the contents of $default are returned. + * + * @static * - * Templates are expected to be found in the template set directory, - * for example: - * SM_PATH/templates/