includes/template.php
changeset 533 698a8f04957c
parent 526 b2fb50d572c7
child 534 6be4b47aa247
child 536 218a627eb53e
equal deleted inserted replaced
532:03429d7b1537 533:698a8f04957c
    10  *
    10  *
    11  * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
    11  * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
    12  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
    12  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
    13  */
    13  */
    14  
    14  
    15 class template {
    15 class template
       
    16 {
    16   var $tpl_strings, $tpl_bool, $theme, $style, $no_headers, $additional_headers, $sidebar_extra, $sidebar_widgets, $toolbar_menu, $theme_list, $named_theme_list, $default_theme, $default_style, $plugin_blocks, $namespace_string, $style_list, $theme_loaded;
    17   var $tpl_strings, $tpl_bool, $theme, $style, $no_headers, $additional_headers, $sidebar_extra, $sidebar_widgets, $toolbar_menu, $theme_list, $named_theme_list, $default_theme, $default_style, $plugin_blocks, $namespace_string, $style_list, $theme_loaded;
    17   
    18   
    18   /**
    19   /**
    19    * The list of themes that are critical for Enano operation. This doesn't include oxygen which
    20    * The list of themes that are critical for Enano operation. This doesn't include oxygen which
    20    * remains a user theme. By default this is admin and printable which have to be loaded on demand.
    21    * remains a user theme. By default this is admin and printable which have to be loaded on demand.
  1201    * @return string
  1202    * @return string
  1202    */
  1203    */
  1203   
  1204   
  1204   function compile_tpl_code($text)
  1205   function compile_tpl_code($text)
  1205   {
  1206   {
  1206     global $db, $session, $paths, $template, $plugins; // Common objects
  1207     return template_compiler_core($text);  
  1207     // A random seed used to salt tags
       
  1208     $seed = md5 ( microtime() . mt_rand() );
       
  1209     
       
  1210     // Strip out PHP sections
       
  1211     preg_match_all('/<\?php(.+?)\?>/is', $text, $php_matches);
       
  1212     
       
  1213     foreach ( $php_matches[0] as $i => $match )
       
  1214     {
       
  1215       // Substitute the PHP section with a random tag
       
  1216       $tag = "{PHP:$i:$seed}";
       
  1217       $text = str_replace_once($match, $tag, $text);
       
  1218     }
       
  1219     
       
  1220     // Escape slashes and single quotes in template code
       
  1221     $text = str_replace('\\', '\\\\', $text);
       
  1222     $text = str_replace('\'', '\\\'', $text);
       
  1223     
       
  1224     // Initialize the PHP compiled code
       
  1225     $text = 'ob_start(); echo \''.$text.'\'; $tpl_code = ob_get_contents(); ob_end_clean(); return $tpl_code;';
       
  1226     
       
  1227     ##
       
  1228     ## Main rules
       
  1229     ##
       
  1230     
       
  1231     //
       
  1232     // Conditionals
       
  1233     //
       
  1234     
       
  1235     $keywords = array('BEGIN', 'BEGINNOT', 'IFSET', 'IFPLUGIN');
       
  1236     $code = $plugins->setHook('template_compile_logic_keyword');
       
  1237     foreach ( $code as $cmd )
       
  1238     {
       
  1239       eval($cmd);
       
  1240     }
       
  1241     
       
  1242     $keywords = implode('|', $keywords);
       
  1243     
       
  1244     // Matches
       
  1245     //          1     2                 3                 4   56                       7     8
       
  1246     $regexp = '/(<!-- ('. $keywords .') ([A-z0-9_-]+) -->)(.*)((<!-- BEGINELSE \\3 -->)(.*))?(<!-- END \\3 -->)/isU';
       
  1247     
       
  1248     /*
       
  1249     The way this works is: match all blocks using the standard form with a different keyword in the block each time,
       
  1250     and replace them with appropriate PHP logic. Plugin-extensible now. :-)
       
  1251     
       
  1252     The while-loop is to bypass what is apparently a PCRE bug. It's hackish but it works. Properly written plugins should only need
       
  1253     to compile templates (using this method) once for each time the template file is changed.
       
  1254     */
       
  1255     while ( preg_match($regexp, $text) )
       
  1256     {
       
  1257       preg_match_all($regexp, $text, $matches);
       
  1258       for ( $i = 0; $i < count($matches[0]); $i++ )
       
  1259       {
       
  1260         $start_tag =& $matches[1][$i];
       
  1261         $type =& $matches[2][$i];
       
  1262         $test =& $matches[3][$i];
       
  1263         $particle_true  =& $matches[4][$i];
       
  1264         $else_tag =& $matches[6][$i];
       
  1265         $particle_else =& $matches[7][$i];
       
  1266         $end_tag =& $matches[8][$i];
       
  1267         
       
  1268         switch($type)
       
  1269         {
       
  1270           case 'BEGIN':
       
  1271             $cond = "isset(\$this->tpl_bool['$test']) && \$this->tpl_bool['$test']";
       
  1272             break;
       
  1273           case 'BEGINNOT':
       
  1274             $cond = "!isset(\$this->tpl_bool['$test']) || ( isset(\$this->tpl_bool['$test']) && !\$this->tpl_bool['$test'] )";
       
  1275             break;
       
  1276           case 'IFPLUGIN':
       
  1277             $cond = "getConfig('plugin_$test') == '1'";
       
  1278             break;
       
  1279           case 'IFSET':
       
  1280             $cond = "isset(\$this->tpl_strings['$test'])";
       
  1281             break;
       
  1282           default:
       
  1283             $code = $plugins->setHook('template_compile_logic_cond');
       
  1284             foreach ( $code as $cmd )
       
  1285             {
       
  1286               eval($cmd);
       
  1287             }
       
  1288             break;
       
  1289         }
       
  1290         
       
  1291         if ( !isset($cond) || ( isset($cond) && !is_string($cond) ) )
       
  1292           continue;
       
  1293         
       
  1294         $tag_complete = <<<TPLCODE
       
  1295 ';
       
  1296         /* START OF CONDITION: $type ($test) */
       
  1297         if ( $cond )
       
  1298         {
       
  1299           echo '$particle_true';
       
  1300         /* ELSE OF CONDITION: $type ($test) */
       
  1301         }
       
  1302         else
       
  1303         {
       
  1304           echo '$particle_else';
       
  1305         /* END OF CONDITION: $type ($test) */
       
  1306         }
       
  1307         echo '
       
  1308 TPLCODE;
       
  1309         
       
  1310         $text = str_replace_once($matches[0][$i], $tag_complete, $text);
       
  1311         
       
  1312       }
       
  1313     }
       
  1314     
       
  1315     // For debugging ;-)
       
  1316     // die("<pre>&lt;?php\n" . htmlspecialchars($text."\n\n".print_r($matches,true)) . "\n\n?&gt;</pre>");
       
  1317     
       
  1318     //
       
  1319     // Data substitution/variables
       
  1320     //
       
  1321     
       
  1322     // System messages
       
  1323     $text = preg_replace('/<!-- SYSMSG ([A-z0-9\._-]+?) -->/is', '\' . $template->tplWikiFormat($paths->sysMsg(\'\\1\')) . \'', $text);
       
  1324     
       
  1325     // Template variables
       
  1326     $text = preg_replace('/\{([A-z0-9_-]+?)\}/is', '\' . $this->tpl_strings[\'\\1\'] . \'', $text);
       
  1327     
       
  1328     // Reinsert PHP
       
  1329     
       
  1330     foreach ( $php_matches[1] as $i => $match )
       
  1331     {
       
  1332       // Substitute the random tag with the "real" PHP code
       
  1333       $tag = "{PHP:$i:$seed}";
       
  1334       $text = str_replace_once($tag, "'; $match echo '", $text);
       
  1335     }
       
  1336     
       
  1337     // echo('<pre>' . htmlspecialchars($text) . '</pre>');
       
  1338     
       
  1339     return $text;  
       
  1340     
       
  1341   }
  1208   }
  1342   
  1209   
  1343   /**
  1210   /**
  1344    * Compiles the contents of a given template file, possibly using a cached copy, and returns the compiled code.
  1211    * Compiles the contents of a given template file, possibly using a cached copy, and returns the compiled code.
  1345    * @param string Filename of template (header.tpl)
  1212    * @param string Filename of template (header.tpl)
  2012   }
  1879   }
  2013   
  1880   
  2014 } // class template
  1881 } // class template
  2015 
  1882 
  2016 /**
  1883 /**
       
  1884  * The core of the template compilation engine. Independent from the Enano API for failsafe operation.
       
  1885  * @param string text to process
       
  1886  * @return string Compiled PHP code
       
  1887  * @access private
       
  1888  */
       
  1889 
       
  1890 function template_compiler_core($text)
       
  1891 {
       
  1892   global $db, $session, $paths, $template, $plugins; // Common objects
       
  1893   // A random seed used to salt tags
       
  1894   $seed = md5 ( microtime() . mt_rand() );
       
  1895   
       
  1896   // Strip out PHP sections
       
  1897   preg_match_all('/<\?php(.+?)\?>/is', $text, $php_matches);
       
  1898   
       
  1899   foreach ( $php_matches[0] as $i => $match )
       
  1900   {
       
  1901     // Substitute the PHP section with a random tag
       
  1902     $tag = "{PHP:$i:$seed}";
       
  1903     $text = str_replace_once($match, $tag, $text);
       
  1904   }
       
  1905   
       
  1906   // Escape slashes and single quotes in template code
       
  1907   $text = str_replace('\\', '\\\\', $text);
       
  1908   $text = str_replace('\'', '\\\'', $text);
       
  1909   
       
  1910   // Initialize the PHP compiled code
       
  1911   $text = 'ob_start(); echo \''.$text.'\'; $tpl_code = ob_get_contents(); ob_end_clean(); return $tpl_code;';
       
  1912   
       
  1913   ##
       
  1914   ## Main rules
       
  1915   ##
       
  1916   
       
  1917   //
       
  1918   // Conditionals
       
  1919   //
       
  1920   
       
  1921   $keywords = array('BEGIN', 'BEGINNOT', 'IFSET', 'IFPLUGIN');
       
  1922   
       
  1923   // only do this if the plugins API is loaded
       
  1924   if ( is_object(@$plugins) )
       
  1925   {
       
  1926     $code = $plugins->setHook('template_compile_logic_keyword');
       
  1927     foreach ( $code as $cmd )
       
  1928     {
       
  1929       eval($cmd);
       
  1930     }
       
  1931   }
       
  1932   
       
  1933   $keywords = implode('|', $keywords);
       
  1934   
       
  1935   // Matches
       
  1936   //          1     2                 3                 4   56                       7     8
       
  1937   $regexp = '/(<!-- ('. $keywords .') ([A-z0-9_-]+) -->)(.*)((<!-- BEGINELSE \\3 -->)(.*))?(<!-- END \\3 -->)/isU';
       
  1938   
       
  1939   /*
       
  1940   The way this works is: match all blocks using the standard form with a different keyword in the block each time,
       
  1941   and replace them with appropriate PHP logic. Plugin-extensible now. :-)
       
  1942   
       
  1943   The while-loop is to bypass what is apparently a PCRE bug. It's hackish but it works. Properly written plugins should only need
       
  1944   to compile templates (using this method) once for each time the template file is changed.
       
  1945   */
       
  1946   
       
  1947   profiler_log("[template] compiler matchout start");
       
  1948   preg_match_all($regexp, $text, $matches);
       
  1949   profiler_log("[template] compiler core loop start");
       
  1950   for ( $i = 0; $i < count($matches[0]); $i++ )
       
  1951   {
       
  1952     $start_tag =& $matches[1][$i];
       
  1953     $type =& $matches[2][$i];
       
  1954     $test =& $matches[3][$i];
       
  1955     $particle_true  =& $matches[4][$i];
       
  1956     $else_tag =& $matches[6][$i];
       
  1957     $particle_else =& $matches[7][$i];
       
  1958     $end_tag =& $matches[8][$i];
       
  1959     
       
  1960     switch($type)
       
  1961     {
       
  1962       case 'BEGIN':
       
  1963         $cond = "isset(\$this->tpl_bool['$test']) && \$this->tpl_bool['$test']";
       
  1964         break;
       
  1965       case 'BEGINNOT':
       
  1966         $cond = "!isset(\$this->tpl_bool['$test']) || ( isset(\$this->tpl_bool['$test']) && !\$this->tpl_bool['$test'] )";
       
  1967         break;
       
  1968       case 'IFPLUGIN':
       
  1969         $cond = "getConfig('plugin_$test') == '1'";
       
  1970         break;
       
  1971       case 'IFSET':
       
  1972         $cond = "isset(\$this->tpl_strings['$test'])";
       
  1973         break;
       
  1974       default:
       
  1975         // only do this if the plugins API is loaded
       
  1976         if ( is_object(@$plugins) )
       
  1977         {
       
  1978           $code = $plugins->setHook('template_compile_logic_cond');
       
  1979           foreach ( $code as $cmd )
       
  1980           {
       
  1981             eval($cmd);
       
  1982           }
       
  1983         }
       
  1984         break;
       
  1985     }
       
  1986     
       
  1987     if ( !isset($cond) || ( isset($cond) && !is_string($cond) ) )
       
  1988       continue;
       
  1989     
       
  1990     $tag_complete = <<<TPLCODE
       
  1991 ';
       
  1992     /* START OF CONDITION: $type ($test) */
       
  1993     if ( $cond )
       
  1994     {
       
  1995       echo '$particle_true';
       
  1996     /* ELSE OF CONDITION: $type ($test) */
       
  1997     }
       
  1998     else
       
  1999     {
       
  2000       echo '$particle_else';
       
  2001     /* END OF CONDITION: $type ($test) */
       
  2002     }
       
  2003     echo '
       
  2004 TPLCODE;
       
  2005     
       
  2006     $text = str_replace_once($matches[0][$i], $tag_complete, $text);
       
  2007   }
       
  2008   
       
  2009   profiler_log("[template] compiler core loop end");
       
  2010   
       
  2011   // For debugging ;-)
       
  2012   // die("<pre>&lt;?php\n" . htmlspecialchars($text."\n\n".print_r($matches,true)) . "\n\n?&gt;</pre>");
       
  2013   
       
  2014   //
       
  2015   // Data substitution/variables
       
  2016   //
       
  2017   
       
  2018   // System messages
       
  2019   $text = preg_replace('/<!-- SYSMSG ([A-z0-9\._-]+?) -->/is', '\' . $template->tplWikiFormat($paths->sysMsg(\'\\1\')) . \'', $text);
       
  2020   
       
  2021   // Template variables
       
  2022   $text = preg_replace('/\{([A-z0-9_-]+?)\}/is', '\' . $this->tpl_strings[\'\\1\'] . \'', $text);
       
  2023   
       
  2024   // Reinsert PHP
       
  2025   
       
  2026   foreach ( $php_matches[1] as $i => $match )
       
  2027   {
       
  2028     // Substitute the random tag with the "real" PHP code
       
  2029     $tag = "{PHP:$i:$seed}";
       
  2030     $text = str_replace_once($tag, "'; $match echo '", $text);
       
  2031   }
       
  2032   
       
  2033   // echo('<pre>' . htmlspecialchars($text) . '</pre>');
       
  2034   
       
  2035   profiler_log("[template] compiler subst end");
       
  2036   
       
  2037   return $text;
       
  2038 }
       
  2039 
       
  2040 /**
  2017  * Handles parsing of an individual template file. Instances should only be created through $template->makeParser(). To use:
  2041  * Handles parsing of an individual template file. Instances should only be created through $template->makeParser(). To use:
  2018  *   - Call $template->makeParser(template file name) - file name should be something.tpl, css/whatever.css, etc.
  2042  *   - Call $template->makeParser(template file name) - file name should be something.tpl, css/whatever.css, etc.
  2019  *   - Make an array of strings you want the template to access. $array['STRING'] would be referenced in the template like {STRING}
  2043  *   - Make an array of strings you want the template to access. $array['STRING'] would be referenced in the template like {STRING}
  2020  *   - Make an array of boolean values. These can be used for conditionals in the template (<!-- IF something --> whatever <!-- ENDIF something -->)
  2044  *   - Make an array of boolean values. These can be used for conditionals in the template (<!-- IF something --> whatever <!-- ENDIF something -->)
  2021  *   - Call assign_vars() to pass the strings to the template parser. Same thing with assign_bool().
  2045  *   - Call assign_vars() to pass the strings to the template parser. Same thing with assign_bool().
  2022  *   - Call run() to parse the template and get your fully compiled HTML.
  2046  *   - Call run() to parse the template and get your fully compiled HTML.
  2023  * @access private
  2047  * @access private
  2024  */
  2048  */
  2025 
  2049 
  2026 class templateIndividual extends template {
  2050 class templateIndividual extends template
       
  2051 {
  2027   var $tpl_strings, $tpl_bool, $tpl_code;
  2052   var $tpl_strings, $tpl_bool, $tpl_code;
  2028   var $compiled = false;
  2053   var $compiled = false;
  2029   /**
  2054   /**
  2030    * Constructor.
  2055    * Constructor.
  2031    */
  2056    */
  2082  * "critical error" messages. ** REQUIRES ** the Oxygen theme.
  2107  * "critical error" messages. ** REQUIRES ** the Oxygen theme.
  2083  */
  2108  */
  2084 
  2109 
  2085 class template_nodb
  2110 class template_nodb
  2086 {
  2111 {
  2087   var $fading_button, $tpl_strings, $tpl_bool, $theme, $style, $no_headers, $additional_headers, $sidebar_extra, $sidebar_widgets, $toolbar_menu, $theme_list;
  2112   var $fading_button, $tpl_strings, $tpl_bool, $theme, $style, $no_headers, $additional_headers, $sidebar_extra, $sidebar_widgets, $toolbar_menu, $theme_list, $named_theme_list;
  2088   function __construct() {
  2113   function __construct()
  2089     
  2114   {
  2090     $this->tpl_bool    = Array();
  2115     $this->tpl_bool    = Array();
  2091     $this->tpl_strings = Array();
  2116     $this->tpl_strings = Array();
  2092     $this->sidebar_extra = '';
  2117     $this->sidebar_extra = '';
  2093     $this->sidebar_widgets = '';
  2118     $this->sidebar_widgets = '';
  2094     $this->toolbar_menu = '';
  2119     $this->toolbar_menu = '';
  2096     
  2121     
  2097     $this->fading_button = '<div style="background-image: url('.scriptPath.'/images/about-powered-enano-hover.png); background-repeat: no-repeat; width: 88px; height: 31px; margin: 0 auto 5px auto;">
  2122     $this->fading_button = '<div style="background-image: url('.scriptPath.'/images/about-powered-enano-hover.png); background-repeat: no-repeat; width: 88px; height: 31px; margin: 0 auto 5px auto;">
  2098                               <a href="http://enanocms.org/" onclick="window.open(this.href); return false;"><img style="border-width: 0;" alt=" " src="'.scriptPath.'/images/about-powered-enano.png" onmouseover="domOpacity(this, 100, 0, 500);" onmouseout="domOpacity(this, 0, 100, 500);" /></a>
  2123                               <a href="http://enanocms.org/" onclick="window.open(this.href); return false;"><img style="border-width: 0;" alt=" " src="'.scriptPath.'/images/about-powered-enano.png" onmouseover="domOpacity(this, 100, 0, 500);" onmouseout="domOpacity(this, 0, 100, 500);" /></a>
  2099                             </div>';
  2124                             </div>';
  2100     
  2125     
  2101     $this->theme_list = Array(Array(
  2126     // get list of themes
  2102       'theme_id'=>'oxygen',
  2127     $this->theme_list = array();
  2103       'theme_name'=>'Oxygen',
  2128     $this->named_theme_list = array();
  2104       'theme_order'=>1,
  2129     $order = 0;
  2105       'enabled'=>1,
  2130     
  2106       ));
  2131     if ( $dir = @opendir( ENANO_ROOT . '/themes' ) )
       
  2132     {
       
  2133       while ( $dh = @readdir($dir) )
       
  2134       {
       
  2135         if ( $dh == '.' || $dh == '..' || !is_dir( ENANO_ROOT . "/themes/$dh" ) )
       
  2136           continue;
       
  2137         $theme_dir = ENANO_ROOT . "/themes/$dh";
       
  2138         if ( !file_exists("$theme_dir/theme.cfg") )
       
  2139           continue;
       
  2140         $data = array(
       
  2141             'theme_id' => $dh,
       
  2142             'theme_name' => ucwords($dh),
       
  2143             'enabled' => 1,
       
  2144             'theme_order' => ++$order,
       
  2145             'default_style' => $this->get_default_style($dh)
       
  2146           );
       
  2147         $this->named_theme_list[$dh] = $data;
       
  2148         $this->theme_list[] =& $this->named_theme_list[$dh];
       
  2149       }
       
  2150       @closedir($dir);
       
  2151     }
  2107   }
  2152   }
  2108   function template() {
  2153   function template() {
  2109     $this->__construct();
  2154     $this->__construct();
       
  2155   }
       
  2156   function get_default_style($theme_id)
       
  2157   {
       
  2158     if ( !is_dir( ENANO_ROOT . "/themes/$theme_id/css" ) )
       
  2159       return false;
       
  2160     $ds = false;
       
  2161     if ( $dh = @opendir( ENANO_ROOT . "/themes/$theme_id/css" ) )
       
  2162     {
       
  2163       while ( $dir = @readdir($dh) )
       
  2164       {
       
  2165         if ( !preg_match('/\.css$/', $dir) )
       
  2166           continue;
       
  2167         if ( $dir == '_printable.css' )
       
  2168           continue;
       
  2169         $ds = preg_replace('/\.css$/', '', $dir);
       
  2170         break;
       
  2171       }
       
  2172       closedir($dh);
       
  2173     }
       
  2174     else
       
  2175     {
       
  2176       return false;
       
  2177     }
       
  2178     return $ds;
  2110   }
  2179   }
  2111   function get_css($s = false) {
  2180   function get_css($s = false) {
  2112     if($s)
  2181     if($s)
  2113       return $this->process_template('css/'.$s);
  2182       return $this->process_template('css/'.$s);
  2114     else
  2183     else
  2115       return $this->process_template('css/'.$this->style.'.css');
  2184       return $this->process_template('css/'.$this->style.'.css');
  2116   }
  2185   }
  2117   function load_theme($name, $css, $auto_init = true) {
  2186   function load_theme($name, $css, $auto_init = true)
       
  2187   {
       
  2188     if ( !isset($this->named_theme_list[$name]) )
       
  2189       $name = $this->theme_list[0]['theme_id'];
       
  2190     
       
  2191     if ( !file_exists(ENANO_ROOT . "/themes/$name/css/$css.css") )
       
  2192       $css = $this->named_theme_list[$name]['default_style'];
       
  2193     
  2118     $this->theme = $name;
  2194     $this->theme = $name;
  2119     $this->style = $css;
  2195     $this->style = $css;
  2120     
  2196     
  2121     $this->tpl_strings['SCRIPTPATH'] = scriptPath;
  2197     $this->tpl_strings['SCRIPTPATH'] = scriptPath;
  2122     if ( $auto_init )
  2198     if ( $auto_init )
  2167     {
  2243     {
  2168       $js_dynamic .= '<script type="text/javascript" src="install.php?mode=langjs"></script>';
  2244       $js_dynamic .= '<script type="text/javascript" src="install.php?mode=langjs"></script>';
  2169     }
  2245     }
  2170     $js_dynamic .= '<script type="text/javascript">var title="'. $title .'"; var scriptPath="'.scriptPath.'"; var ENANO_SID=""; var AES_BITS='.AES_BITS.'; var AES_BLOCKSIZE=' . AES_BLOCKSIZE . '; var pagepass=\'\'; var ENANO_LANG_ID = 1;</script>';
  2246     $js_dynamic .= '<script type="text/javascript">var title="'. $title .'"; var scriptPath="'.scriptPath.'"; var ENANO_SID=""; var AES_BITS='.AES_BITS.'; var AES_BLOCKSIZE=' . AES_BLOCKSIZE . '; var pagepass=\'\'; var ENANO_LANG_ID = 1;</script>';
  2171     
  2247     
       
  2248     global $site_name, $site_desc;
       
  2249     $site_default_name = ( !empty($site_name) ) ? $site_name : 'Critical error';
       
  2250     $site_default_desc = ( !empty($site_desc) ) ? $site_desc : 'This site is experiencing a problem and cannot load.';
       
  2251     
       
  2252     $site_name_final = ( defined('IN_ENANO_INSTALL') && is_object($lang) ) ? $lang->get('meta_site_name') : $site_default_name;
       
  2253     $site_desc_final = ( defined('IN_ENANO_INSTALL') && is_object($lang) ) ? $lang->get('meta_site_desc') : $site_default_desc;
       
  2254     
  2172     // The rewritten template engine will process all required vars during the load_template stage instead of (cough) re-processing everything each time around.
  2255     // The rewritten template engine will process all required vars during the load_template stage instead of (cough) re-processing everything each time around.
  2173     $tpl_strings = Array(
  2256     $tpl_strings = Array(
  2174       'PAGE_NAME'=>$this_page,
  2257       'PAGE_NAME'=>$this_page,
  2175       'PAGE_URLNAME'=>'Null',
  2258       'PAGE_URLNAME'=>'Null',
  2176       'SITE_NAME'=> ( defined('IN_ENANO_INSTALL') && is_object($lang) ) ? $lang->get('meta_site_name') : 'Critical error',
  2259       'SITE_NAME' => $site_name_final,
  2177       'USERNAME'=>'admin',
  2260       'USERNAME'=>'admin',
  2178       'SITE_DESC'=>( defined('IN_ENANO_INSTALL') && is_object($lang) ) ? $lang->get('meta_site_desc') : 'This site is experiencing a problem and cannot load.',
  2261       'SITE_DESC' => $site_desc_final,
  2179       'TOOLBAR'=>$tb,
  2262       'TOOLBAR'=>$tb,
  2180       'SCRIPTPATH'=>scriptPath,
  2263       'SCRIPTPATH'=>scriptPath,
  2181       'CONTENTPATH'=>contentPath,
  2264       'CONTENTPATH'=>contentPath,
  2182       'ADMIN_SID_QUES'=>$asq,
  2265       'ADMIN_SID_QUES'=>$asq,
  2183       'ADMIN_SID_AMP'=>$asa,
  2266       'ADMIN_SID_AMP'=>$asa,
  2198       'REPORT_URI' => '',
  2281       'REPORT_URI' => '',
  2199       'URL_ABOUT_ENANO' => 'http://enanocms.org/'
  2282       'URL_ABOUT_ENANO' => 'http://enanocms.org/'
  2200       );
  2283       );
  2201     $this->tpl_strings = array_merge($tpl_strings, $this->tpl_strings);
  2284     $this->tpl_strings = array_merge($tpl_strings, $this->tpl_strings);
  2202     
  2285     
  2203     $sidebar = ( gettype($sideinfo) == 'string' ) ? $sideinfo : '';
  2286     $sidebar = ( is_array(@$sideinfo) ) ? $sideinfo : '';
  2204     if($sidebar != '')
  2287     if ( $sidebar != '' )
  2205     {
  2288     {
  2206       if(isset($tplvars['sidebar_top']))
  2289       if ( isset($tplvars['sidebar_top']) )
  2207       {
  2290       {
  2208         $text = $this->makeParserText($tplvars['sidebar_top']);
  2291         $text = $this->makeParserText($tplvars['sidebar_top']);
  2209         $top = $text->run();
  2292         $top = $text->run();
  2210       } else {
  2293       }
       
  2294       else
       
  2295       {
  2211         $top = '';
  2296         $top = '';
  2212       }
  2297       }
       
  2298       
  2213       $p = $this->makeParserText($tplvars['sidebar_section']);
  2299       $p = $this->makeParserText($tplvars['sidebar_section']);
  2214       $p->assign_vars(Array(
  2300       $b = $this->makeParserText($tplvars['sidebar_button']);
  2215           'TITLE'=>$lang->get('meta_sidebar_heading'),
  2301       $sidebar_text = '';
  2216           'CONTENT'=>$sidebar,
  2302       
       
  2303       foreach ( $sidebar as $title => $links )
       
  2304       {
       
  2305         $p->assign_vars(array(
       
  2306           'TITLE' => $title
  2217         ));
  2307         ));
  2218       $sidebar = $p->run();
  2308         // build content
  2219       if(isset($tplvars['sidebar_bottom']))
  2309         $content = '';
       
  2310         foreach ( $links as $link_text => $url )
       
  2311         {
       
  2312           $b->assign_vars(array(
       
  2313             'HREF' => htmlspecialchars($url),
       
  2314             'FLAGS' => '',
       
  2315             'TEXT' => $link_text
       
  2316           ));
       
  2317           $content .= $b->run();
       
  2318         }
       
  2319         $p->assign_vars(array(
       
  2320           'CONTENT' => $content
       
  2321         ));
       
  2322         $sidebar_text .= $p->run();
       
  2323       }
       
  2324       
       
  2325       if ( isset($tplvars['sidebar_bottom']) )
  2220       {
  2326       {
  2221         $text = $this->makeParserText($tplvars['sidebar_bottom']);
  2327         $text = $this->makeParserText($tplvars['sidebar_bottom']);
  2222         $bottom = $text->run();
  2328         $bottom = $text->run();
  2223       } else {
  2329       }
       
  2330       else
       
  2331       {
  2224         $bottom = '';
  2332         $bottom = '';
  2225       }
  2333       }
  2226       $sidebar = $top . $sidebar . $bottom;
  2334       $sidebar = $top . $sidebar_text . $bottom;
  2227     }
  2335     }
  2228     $this->tpl_strings['SIDEBAR_LEFT'] = $sidebar;
  2336     $this->tpl_strings['SIDEBAR_LEFT'] = $sidebar;
  2229     
  2337     
  2230     $this->tpl_bool['sidebar_left']  = ( $this->tpl_strings['SIDEBAR_LEFT']  != '') ? true : false;
  2338     $this->tpl_bool['sidebar_left']  = ( $this->tpl_strings['SIDEBAR_LEFT']  != '') ? true : false;
  2231     $this->tpl_bool['sidebar_right'] = ( $this->tpl_strings['SIDEBAR_RIGHT'] != '') ? true : false;
  2339     $this->tpl_bool['sidebar_right'] = ( $this->tpl_strings['SIDEBAR_RIGHT'] != '') ? true : false;
  2294       $t = str_replace('[[NumQueries]]', ( is_object($db) ? (string)$db->num_queries : '0' ), $t);
  2402       $t = str_replace('[[NumQueries]]', ( is_object($db) ? (string)$db->num_queries : '0' ), $t);
  2295       $t = str_replace('[[GenTime]]', (string)$f, $t);
  2403       $t = str_replace('[[GenTime]]', (string)$f, $t);
  2296       $t = str_replace('[[NumQueriesLoc]]', $q_loc, $t);
  2404       $t = str_replace('[[NumQueriesLoc]]', $q_loc, $t);
  2297       $t = str_replace('[[GenTimeLoc]]', $t_loc, $t);
  2405       $t = str_replace('[[GenTimeLoc]]', $t_loc, $t);
  2298       
  2406       
       
  2407       if ( defined('ENANO_DEBUG') )
       
  2408         $t = str_replace('</body>', '<div id="profile" style="margin: 10px;">' . profiler_make_html() . '</div></body>', $t);
       
  2409       
  2299       echo $t;
  2410       echo $t;
  2300     }
  2411     }
  2301     else return '';
  2412     else return '';
  2302   }
  2413   }
  2303   function getHeader()
  2414   function getHeader()
  2323       return $t;
  2434       return $t;
  2324     }
  2435     }
  2325     else return '';
  2436     else return '';
  2326   }
  2437   }
  2327   
  2438   
  2328   function process_template($file) {
  2439   function process_template($file)
  2329     
  2440   {
  2330     eval($this->compile_template($file));
  2441     profiler_log("[template_nodb] STARTED eval of file $file");
  2331     return $tpl_code;
  2442     $compiled = $this->compile_template($file);
       
  2443     profiler_log("[template_nodb] COMPILED file $file");
       
  2444     $result = eval($compiled);
       
  2445     profiler_log("[template_nodb] FINISHED eval of file $file");
       
  2446     return $result;
  2332   }
  2447   }
  2333   
  2448   
  2334   function extract_vars($file) {
  2449   function extract_vars($file) {
  2335     global $db, $session, $paths, $template, $plugins; // Common objects
  2450     global $db, $session, $paths, $template, $plugins; // Common objects
  2336     if(!is_file(ENANO_ROOT . '/themes/'.$this->theme.'/'.$file)) die('Cannot find '.$file.' file for style "'.$this->theme.'", exiting');
  2451     if(!is_file(ENANO_ROOT . '/themes/'.$this->theme.'/'.$file)) die('Cannot find '.$file.' file for style "'.$this->theme.'", exiting');
  2341     {
  2456     {
  2342       $tplvars[$matches[1][$i]] = $matches[2][$i];
  2457       $tplvars[$matches[1][$i]] = $matches[2][$i];
  2343     }
  2458     }
  2344     return $tplvars;
  2459     return $tplvars;
  2345   }
  2460   }
  2346   function compile_template($text) {
  2461   function compile_template($text)
  2347     global $sideinfo;
  2462   {
  2348     $text = file_get_contents(ENANO_ROOT . '/themes/'.$this->theme.'/'.$text);
  2463     $text = file_get_contents(ENANO_ROOT . '/themes/'.$this->theme.'/'.$text);
  2349     $text = str_replace('<script type="text/javascript" src="{SCRIPTPATH}/ajax.php?title={PAGE_URLNAME}&amp;_mode=jsres"></script>', '', $text); // Remove the AJAX code - we don't need it, and it requires a database connection
  2464     return $this->compile_template_text_post(template_compiler_core($text));
  2350     $text = '$tpl_code = \''.str_replace('\'', '\\\'', $text).'\'; return $tpl_code;';
  2465   }
  2351     $text = preg_replace('#<!-- BEGIN (.*?) -->#is', '\'; if($this->tpl_bool[\'\\1\']) { $tpl_code .= \'', $text);
  2466   
  2352     $text = preg_replace('#<!-- IFPLUGIN (.*?) -->#is', '\'; if(getConfig(\'plugin_\\1\')==\'1\') { $tpl_code .= \'', $text);
  2467   function compile_template_text($text)
  2353     if(defined('IN_ENANO_INSTALL')) $text = str_replace('<!-- SYSMSG Sidebar -->', '<div class="slider"><div class="heading"><a class="head">Installation progress</a></div><div class="slideblock">'.$sideinfo.'</div></div>', $text);
  2468   {
  2354     else $text = str_replace('<!-- SYSMSG Sidebar -->', '<div class="slider"><div class="heading"><a class="head">System error</a></div><div class="slideblock"><a href="#" onclick="return false;">Enano critical error page</a></div></div>', $text);
  2469     return $this->compile_template_text_post(template_compiler_core($text));
  2355     $text = preg_replace('#<!-- SYSMSG (.*?) -->#is', '', $text);
  2470   }
  2356     $text = preg_replace('#<!-- BEGINNOT (.*?) -->#is', '\'; if(!$this->tpl_bool[\'\\1\']) { $tpl_code .= \'', $text);
  2471   
  2357     $text = preg_replace('#<!-- BEGINELSE (.*?) -->#is', '\'; } else { $tpl_code .= \'', $text);
  2472   /**
  2358     $text = preg_replace('#<!-- END (.*?) -->#is', '\'; } $tpl_code .= \'', $text);
  2473    * Post-processor for template code. Basically what this does is it localizes {lang:foo} blocks.
  2359     $text = preg_replace('#{([A-z0-9]*)}#is', '\'.$this->tpl_strings[\'\\1\'].\'', $text);
  2474    * @param string Mostly-processed TPL code
  2360     return $text; //('<pre>'.htmlspecialchars($text).'</pre>');
  2475    * @return string
  2361   }
  2476    */
  2362   
  2477   
  2363   function compile_template_text($text) {
  2478   function compile_template_text_post($text)
  2364     global $sideinfo;
  2479   {
  2365     $text = str_replace('<script type="text/javascript" src="{SCRIPTPATH}/ajax.php?title={PAGE_URLNAME}&amp;_mode=jsres"></script>', '', $text); // Remove the AJAX code - we don't need it, and it requires a database connection
  2480     global $lang;
  2366     $text = '$tpl_code = \''.str_replace('\'', '\\\'', $text).'\'; return $tpl_code;';
  2481     preg_match_all('/\{lang:([a-z0-9]+_[a-z0-9_]+)\}/', $text, $matches);
  2367     $text = preg_replace('#<!-- BEGIN (.*?) -->#is', '\'; if($this->tpl_bool[\'\\1\']) { $tpl_code .= \'', $text);
  2482     foreach ( $matches[1] as $i => $string_id )
  2368     $text = preg_replace('#<!-- IFPLUGIN (.*?) -->#is', '\'; if(getConfig(\'plugin_\\1\')==\'1\') { $tpl_code .= \'', $text);
  2483     {
  2369     if(defined('IN_ENANO_INSTALL')) $text = str_replace('<!-- SYSMSG Sidebar -->', '<div class="slider"><div class="heading"><a class="head">Installation progress</a></div><div class="slideblock">'.$sideinfo.'</div></div>', $text);
  2484       if ( is_object(@$lang) )
  2370     else $text = str_replace('<!-- SYSMSG Sidebar -->', '<div class="slider"><div class="heading"><a class="head">System error</a></div><div class="slideblock"><a href="#" onclick="return false;>Enano critical error page</a></div></div>', $text);
  2485       {
  2371     $text = preg_replace('#<!-- SYSMSG (.*?) -->#is', '', $text);
  2486         $string = $lang->get($string_id);
  2372     $text = preg_replace('#<!-- BEGINNOT (.*?) -->#is', '\'; if(!$this->tpl_bool[\'\\1\']) { $tpl_code .= \'', $text);
  2487       }
  2373     $text = preg_replace('#<!-- BEGINELSE (.*?) -->#is', '\'; } else { $tpl_code .= \'', $text);
  2488       else
  2374     $text = preg_replace('#<!-- END (.*?) -->#is', '\'; } $tpl_code .= \'', $text);
  2489       {
  2375     $text = preg_replace('#{([A-z0-9]*)}#is', '\'.$this->tpl_strings[\'\\1\'].\'', $text);
  2490         $string = '[language not loaded]';
  2376     return $text; //('<pre>'.htmlspecialchars($text).'</pre>');
  2491       }
       
  2492       $string = str_replace('\\', '\\\\', $string);
       
  2493       $string = str_replace('\'', '\\\'', $string);
       
  2494       $text = str_replace_once($matches[0][$i], $string, $text);
       
  2495     }
       
  2496     return $text;
  2377   }
  2497   }
  2378   
  2498   
  2379   /**
  2499   /**
  2380    * Allows individual parsing of template files. Similar to phpBB but follows the spirit of object-oriented programming ;)
  2500    * Allows individual parsing of template files. Similar to phpBB but follows the spirit of object-oriented programming ;)
  2381    * Returns on object of class templateIndividual. Usage instructions can be found in the inline docs for that class.
  2501    * Returns on object of class templateIndividual. Usage instructions can be found in the inline docs for that class.
  2400    
  2520    
  2401   function makeParserText($code)
  2521   function makeParserText($code)
  2402   {
  2522   {
  2403     $parser = new templateIndividualSafe($code, $this);
  2523     $parser = new templateIndividualSafe($code, $this);
  2404     return $parser;
  2524     return $parser;
       
  2525   }
       
  2526   
       
  2527   /**
       
  2528    * Assigns an array of string values to the template. Strings can be accessed from the template by inserting {KEY_NAME} in the template file.
       
  2529    * @param $vars array
       
  2530    */
       
  2531   function assign_vars($vars)
       
  2532   {
       
  2533     if(is_array($this->tpl_strings))
       
  2534       $this->tpl_strings = array_merge($this->tpl_strings, $vars);
       
  2535     else
       
  2536       $this->tpl_strings = $vars;
  2405   }
  2537   }
  2406    
  2538    
  2407 } // class template_nodb
  2539 } // class template_nodb
  2408 
  2540 
  2409 /**
  2541 /**
  2410  * Identical to templateIndividual, except extends template_nodb instead of template
  2542  * Identical to templateIndividual, except extends template_nodb instead of template
  2411  * @see class template
  2543  * @see class template
  2412  */
  2544  */
  2413  
  2545  
  2414 class templateIndividualSafe extends template_nodb {
  2546 class templateIndividualSafe extends template_nodb
       
  2547 {
  2415   var $tpl_strings, $tpl_bool, $tpl_code;
  2548   var $tpl_strings, $tpl_bool, $tpl_code;
  2416   var $compiled = false;
  2549   var $compiled = false;
  2417   /**
  2550   /**
  2418    * Constructor.
  2551    * Constructor.
  2419    */
  2552    */