Fixed error check
[squirrelmail.git] / class / template / template.class.php
index cd05765018bc43fa9ad84440b1181cebf1ed5589..db04cfa6306bac62d89c1a85e34e250c1d55e75d 100755 (executable)
@@ -42,37 +42,43 @@ class Template
    */
   var $template_dir = '';
 
+  /**
+   * The default template directory
+   *
+   * @var string
+   */
+  var $default_template_dir = 'templates/default/';
+
   /**
    * Template files provided by this template set
-   * 
+   *
    * @var array
    */
   var $templates_provided = array();
-  
+
   /**
    * Javascript files required by the template
-   * 
+   *
    * @var array
    */
   var $required_js_files = array();
-  
+
   /**
    * Javascript files provided by the template.  If a JS file is required, but
-   * not provided, the js file by the same name will be included from the 
+   * not provided, the js file by the same name will be included from the
    * default template directory.
-   * 
+   *
    * @var array
    */
   var $provided_js_files = array();
-  
+
   /**
    * Additional stylesheets provided by the template.  This allows template
-   * authors (namely me to begin with :p) to provide additional CSS sheets
-   * to templates while using the default template set stylesheet for other
-   * definitions.
+   * authors to provide additional CSS sheets to templates while using the 
+   * default template set stylesheet for other definitions.
    */
-  var $additional_css_sheets = array(); 
-  
+  var $additional_css_sheets = array();
+
     /**
      * Constructor
      *
@@ -80,7 +86,7 @@ class Template
      */
     function Template($sTplDir) {
         $this->template_dir = $sTplDir;
-       
+
         // Pull in the tempalte config file
         if (!file_exists($this->template_dir . 'template.php')) {
              trigger_error('No template.php could be found in the requested template directory ("'.$this->template_dir.'")', E_USER_ERROR);
@@ -133,11 +139,20 @@ class Template
    *
    * @param array|string $tpl_var the template variable name(s)
    * @param mixed $value the value to append
+   * @param boolean $merge when $value is given as an array, 
+   *                       this indicates whether or not that 
+   *                       array itself should be appended as 
+   *                       a new template variable value or if 
+   *                       that array's values should be merged 
+   *                       into the existing array of template 
+   *                       variable values
    */
   function append($tpl_var, $value = NULL, $merge = FALSE)
   {
     if (is_array($tpl_var))
     {
+      //FIXME: $tpl_var is supposed to be a list of template var names,
+      //       so we should be looking at the values NOT the keys!
       foreach ($tpl_var as $_key => $_val)
       {
         if ($_key != '')
@@ -145,6 +160,18 @@ class Template
           if(isset($this->values[$_key]) && !is_array($this->values[$_key]))
             settype($this->values[$_key],'array');
 
+          //FIXME: we should be iterating the $value array here not the values of the
+          //       list of template variable names!  I think this is totally broken 
+          // This might just be a matter of needing to clarify the method's API;
+          // values may have been meant to be passed in $tpl_var in the case that
+          // $tpl_var is an array.  Ugly and non-intuitive.
+          // PROPOSAL: API should be as such:  
+          //   if (is_string($tpl_var)) then $values are added/merged as already done
+          //   if (is_array($tpl_var)) then $values is required to be an array whose
+          //                                keys must match up with $tpl_var keys and
+          //                                whose values are then what is added to
+          //                                each template variable value (array or 
+          //                                strings, doesn't matter)
           if($merge && is_array($_val))
           {
             foreach($_val as $_mkey => $_mval)
@@ -178,6 +205,13 @@ class Template
    *
    * @param string $tpl_var the template variable name
    * @param mixed $value the referenced value to append
+   * @param boolean $merge when $value is given as an array, 
+   *                       this indicates whether or not that 
+   *                       array itself should be appended as 
+   *                       a new template variable value or if 
+   *                       that array's values should be merged 
+   *                       into the existing array of template 
+   *                       variable values
    */
   function append_by_ref($tpl_var, &$value, $merge = FALSE)
   {
@@ -196,54 +230,194 @@ class Template
     }
   }
 
-  /**
-   * Display the template
-   *
-   * @param string $file The template file to use
-   */
-  function display($file)
-  {
-    // Pull in our config file
-    $t = &$this->values; // place values array directly in scope
-    
-    $template = in_array($file, $this->templates_provided) ? $this->template_dir . $file : SM_PATH .'templates/default/'. $file;
-    if (!file_exists($template)) {
-        trigger_error('The template "'.htmlspecialchars($file).'" could not be displayed!', E_USER_ERROR);
-    } else {
-        ob_start();
-        include($template);
-        ob_end_flush();
+
+    /**
+     *
+     * Return the relative template directory path for this template set.
+     *
+     * @return string The relative path to the template directory based
+     *                from the main SquirrelMail directory (SM_PATH).
+     *
+     */
+    function get_template_file_directory() {
+
+//FIXME: temporarily parse off SM_PATH from the template dir class attribute until we can change the entire template subsystem such that the template dir is derived internally in this class from the template ID/name/attributes
+return substr($this->template_dir, strlen(SM_PATH));
+        return $this->template_dir;
+
     }
-  }
 
-  /**
-   * Return the results of applying a template.
-   *
-   * @param string $file The template file to use
-   * @return string A string of the results
-   */
-  function fetch($file)
-  {
-    ob_start();
-    $t = &$this->values; // place values array directly in scope
-
-    $template = in_array($file, $this->templates_provided) ? $this->template_dir . $file : SM_PATH .'templates/default/'. $file;
-    if (!file_exists($template)) {
-        trigger_error('The template "'.htmlspecialchars($file).'" could not be fetched!', E_USER_ERROR);
-    } else {
-        ob_start();
-        include($template);
-        $contents = ob_get_contents();
-        ob_end_flush();
-        return $contents;
+
+    /**
+     *
+     * Return the relative template directory path for the DEFAULT template set.
+     *
+     * @return string The relative path to the default template directory based
+     *                from the main SquirrelMail directory (SM_PATH).
+     *
+     */
+    function get_default_template_file_directory() {
+
+        return $this->default_template_dir;
+
     }
 
-  }
+
+    /**
+     *
+     * Find the right template file.
+     *
+     * Templates are expected to be found in the template set directory,
+     * for example:
+     *     SM_PATH/templates/<template name>/
+     * or, in the case of plugin templates, in a plugin directory in the 
+     * template set directory, for example:
+     *     SM_PATH/templates/<template name>/plugins/<plugin name>/
+     * *OR* in a template directory in the plugin as a fallback, for example:
+     *     SM_PATH/plugins/<plugin name>/templates/<template name>/
+     * If the correct file is not found for the current template set, a 
+     * default template is loaded, which is expected to be found in the 
+     * default template directory, for example:
+     *     SM_PATH/templates/default/
+     * or for plugins, in a plugin directory in the default template set,
+     * for example:
+     *     SM_PATH/templates/default/plugins/<plugin name>/
+     * *OR* in a default template directory in the plugin as a fallback,
+     * for example:
+     *     SM_PATH/plugins/<plugin name>/templates/default/
+     *
+     * Plugin authors must note that the $filename MUST be prefaced
+     * with "plugins/<plugin name>/" in order to correctly resolve the 
+     * template file.
+     *
+     * @param string $filename The name of the template file,
+     *                         possibly prefaced with 
+     *                         "plugins/<plugin name>/"
+     *                         indicating that it is a plugin
+     *                         template.
+     *
+     * @return string The full path to the template file; if 
+     *                not found, an empty string.  The caller
+     *                is responsible for throwing erros or 
+     *                other actions if template file is not found.
+     *
+     */
+    function get_template_file_path($filename) {
+
+        // is the template found in the normal template directory?
+        //
+        $filepath = SM_PATH . $this->get_template_file_directory() . $filename;
+        if (!file_exists($filepath)) {
+
+            // no, so now we have to get the default template...
+            // however, in the case of a plugin template, let's
+            // give one more try to find the right template as
+            // provided by the plugin
+            //
+            if (strpos($filename, 'plugins/') === 0) {
+
+                $plugin_name = substr($filename, 8, strpos($filename, '/', 8) - 8);
+                $filepath = SM_PATH . 'plugins/' . $plugin_name . '/'
+                          . $this->get_template_file_directory() 
+                          . substr($filename, strlen($plugin_name) + 9);
+
+                // no go, we have to get the default template, 
+                // first try the default SM template
+                //
+                if (!file_exists($filepath)) {
+
+                    $filepath = SM_PATH 
+                              . $this->get_default_template_file_directory() 
+                              . $filename;
+
+                    // still no luck?  get default template from the plugin
+                    //
+                    if (!file_exists($filepath)) {
+
+                        $filepath = SM_PATH . 'plugins/' . $plugin_name . '/'
+                                  . $this->get_default_template_file_directory() 
+                                  . substr($filename, strlen($plugin_name) + 9);
+
+                        // no dice whatsoever, return empty string
+                        //
+                        if (!file_exists($filepath)) {
+                            $filepath = '';
+                        }
+
+                    }
+
+                }
+
+
+            // get default template for non-plugin templates
+            //
+            } else {
+
+                $filepath = SM_PATH . $this->get_default_template_file_directory() 
+                          . $filename;
+
+                // no dice whatsoever, return empty string
+                //
+                if (!file_exists($filepath)) {
+                    $filepath = '';
+                }
+
+            }
+
+        }
+
+        return $filepath;
+
+    }
+
+
+    /**
+     * Display the template
+     *
+     * @param string $file The template file to use
+     */
+    function display($file)
+    {
+        // Pull in our config file
+        $t = &$this->values; // place values array directly in scope
+
+        // Get right template file
+        $template = $this->get_template_file_path($file);
+        if (empty($template)) {
+            trigger_error('The template "'.htmlspecialchars($file).'" could not be displayed!', E_USER_ERROR);
+        } else {
+            ob_start();
+            include($template);
+            ob_end_flush();
+        }
+    }
+
+    /**
+     * Return the results of applying a template.
+     *
+     * @param string $file The template file to use
+     * @return string A string of the results
+     */
+    function fetch($file) {
+        $t = &$this->values; // place values array directly in scope
+
+        // Get right template file
+        $template = $this->get_template_file_path($file);
+        if (empty($template)) {
+            trigger_error('The template "'.htmlspecialchars($file).'" could not be fetched!', E_USER_ERROR);
+        } else {
+            ob_start();
+            include($template);
+            $contents = ob_get_contents();
+            ob_end_clean();
+            return $contents;
+        }
+    }
 
   /**
-   * Return paths to the required javascript files.  Used when generating page 
+   * Return paths to the required javascript files.  Used when generating page
    * header.
-   * 
+   *
    * @return array $paths
    */
   function getJavascriptIncludes () {
@@ -253,14 +427,14 @@ class Template
             $paths[] = './'.$this->template_dir.'js/'.basename($file);
         else $paths[] = SM_PATH .'templates/default/js/'.basename($file);
     }
-    
+
     return $paths;
   }
 
   /**
    * Return any additional stylsheets provided by the template.  Used when
    * generating page headers.
-   * 
+   *
    * @return array $paths
    */
   function getAdditionalStyleSheets () {
@@ -275,5 +449,3 @@ class Template
     return $paths;
   }
 }
-
-?>