PageRenderTime 63ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/includes/template.php

https://code.google.com/p/enanocms/
PHP | 3430 lines | 2340 code | 452 blank | 638 comment | 391 complexity | 64bfb35a8d199d6f57077d3ffa51c932 MD5 | raw file
Possible License(s): GPL-2.0

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. /*
  3. * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
  4. * Copyright (C) 2006-2009 Dan Fuhry
  5. *
  6. * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
  7. * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
  10. * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
  11. */
  12. class template
  13. {
  14. var $tpl_strings, $tpl_bool, $vars_assign_history, $theme, $style, $no_headers, $additional_headers, $sidebar_extra, $sidebar_widgets, $toolbar_menu, $theme_list, $named_theme_list, $default_theme, $default_style, $plugin_blocks, $plugin_blocks_content, $namespace_string, $style_list, $theme_loaded;
  15. var $theme_initted = false;
  16. var $page_initted = false;
  17. var $elements = false;
  18. var $page_id = false;
  19. var $namespace = false;
  20. var $js_preload = array();
  21. var $js_append = '';
  22. /**
  23. * Page action conditions
  24. * @var array
  25. */
  26. var $conds = array();
  27. /**
  28. * The PageProcessor for the current page
  29. * @var object
  30. */
  31. var $page = false;
  32. /**
  33. * The list of themes that are critical for Enano operation. This doesn't include oxygen which
  34. * remains a user theme. By default this is admin and printable which have to be loaded on demand.
  35. * @var array
  36. */
  37. var $system_themes = array('admin', 'printable');
  38. /**
  39. * Set to true if the site is disabled and thus a message needs to be shown. This should ONLY be changed by common.php.
  40. * @var bool
  41. * @access private
  42. */
  43. var $site_disabled = false;
  44. /**
  45. * One of the absolute best parts of Enano :-P
  46. * @var string
  47. */
  48. var $fading_button = '';
  49. /**
  50. * Context stack. You can save and restore the var set.
  51. * @var array
  52. */
  53. var $context_stack = array('bool' => array(), 'str' => array(), 'history' => array());
  54. function __construct()
  55. {
  56. global $db, $session, $paths, $template, $plugins; // Common objects
  57. global $cache;
  58. $this->tpl_bool = Array();
  59. $this->tpl_strings = Array();
  60. $this->sidebar_extra = '';
  61. $this->toolbar_menu = '';
  62. $this->additional_headers = '';
  63. $this->plugin_blocks = Array();
  64. $this->plugin_blocks_content = array();
  65. $this->theme_loaded = false;
  66. $this->theme_list = Array();
  67. $this->named_theme_list = Array();
  68. $this->vars_assign_history = array(
  69. 'strings' => array(),
  70. 'bool' => array()
  71. );
  72. if ( defined('IN_ENANO_UPGRADE') )
  73. {
  74. return $this->construct_compat();
  75. }
  76. if ( !$this->theme_list = $cache->fetch('themes') )
  77. {
  78. $q = $db->sql_query('SELECT theme_id, theme_name, enabled, default_style, group_policy, group_list FROM ' . table_prefix . 'themes;');
  79. if ( !$q )
  80. $db->_die('template.php selecting theme list');
  81. $i = 0;
  82. while ( $row = $db->fetchrow() )
  83. {
  84. $this->theme_list[$i] = $row;
  85. $i++;
  86. }
  87. unset($theme);
  88. $this->theme_list = array_values($this->theme_list);
  89. $cache->store('themes', $this->theme_list, -1);
  90. }
  91. // Create associative array of themes
  92. foreach ( $this->theme_list as $i => &$theme )
  93. $this->named_theme_list[ $theme['theme_id'] ] =& $this->theme_list[$i];
  94. unset($theme);
  95. $this->default_theme = ( $_ = getConfig('theme_default') ) ? $_ : $this->theme_list[0]['theme_id'];
  96. $this->named_theme_list[ $this->default_theme ]['css'] = $this->get_theme_css_files($this->default_theme);
  97. // Come up with the default style. If the CSS file specified in default_style exists, we're good, just
  98. // use that. Otherwise, use the first stylesheet that comes to mind.
  99. $df_data =& $this->named_theme_list[ $this->default_theme ];
  100. $this->default_style = ( in_array($df_data['default_style'], $df_data['css']) ) ? $df_data['default_style'] : $df_data['css'][0];
  101. }
  102. /**
  103. * Save the current context and start a blank one.
  104. */
  105. function context_push()
  106. {
  107. array_push($this->context_stack['str'], $this->tpl_strings);
  108. array_push($this->context_stack['bool'], $this->tpl_bool);
  109. array_push($this->context_stack['history'], $this->vars_assign_history);
  110. }
  111. function context_pop()
  112. {
  113. $this->tpl_strings = array_pop($this->context_stack['str']);
  114. $this->tpl_bool = array_pop($this->context_stack['bool']);
  115. $this->vars_assign_history = array_pop($this->context_stack['history']);
  116. }
  117. /**
  118. * Gets the list of available CSS files (styles) for the specified theme.
  119. * @param string Theme ID
  120. * @return array
  121. */
  122. function get_theme_css_files($theme_id)
  123. {
  124. $css = array();
  125. $dir = ENANO_ROOT . "/themes/{$theme_id}/css";
  126. if ( $dh = @opendir($dir) )
  127. {
  128. while ( ( $file = @readdir($dh) ) !== false )
  129. {
  130. if ( preg_match('/\.css$/', $file) )
  131. $css[] = preg_replace('/\.css$/', '', $file);
  132. }
  133. closedir($dh);
  134. }
  135. // No CSS files? If so, nuke it.
  136. if ( count($css) < 1 )
  137. {
  138. unset($this->theme_list[$theme_id]);
  139. }
  140. return $css;
  141. }
  142. /**
  143. * Failsafe constructor for upgrades.
  144. */
  145. function construct_compat()
  146. {
  147. global $db, $session, $paths, $template, $plugins; // Common objects
  148. $this->tpl_bool = Array();
  149. $this->tpl_strings = Array();
  150. $this->sidebar_extra = '';
  151. $this->toolbar_menu = '';
  152. $this->additional_headers = '';
  153. $this->plugin_blocks = Array();
  154. $this->theme_loaded = false;
  155. $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;">
  156. <a style="background-image: none; padding-right: 0;" 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>
  157. </div>';
  158. $this->theme_list = Array();
  159. $this->named_theme_list = Array();
  160. $q = $db->sql_query('SELECT theme_id, theme_name, enabled, default_style FROM ' . table_prefix . 'themes;');
  161. if ( !$q )
  162. $db->_die('template.php selecting theme list');
  163. $i = 0;
  164. while ( $row = $db->fetchrow() )
  165. {
  166. $this->theme_list[$i] = $row;
  167. $i++;
  168. }
  169. // List out all CSS files for this theme
  170. foreach ( $this->theme_list as $i => &$theme )
  171. {
  172. $theme['css'] = array();
  173. $dir = ENANO_ROOT . "/themes/{$theme['theme_id']}/css";
  174. if ( $dh = @opendir($dir) )
  175. {
  176. while ( ( $file = @readdir($dh) ) !== false )
  177. {
  178. if ( preg_match('/\.css$/', $file) )
  179. $theme['css'][] = preg_replace('/\.css$/', '', $file);
  180. }
  181. closedir($dh);
  182. }
  183. // No CSS files? If so, nuke it.
  184. if ( count($theme['css']) < 1 )
  185. {
  186. unset($this->theme_list[$i]);
  187. }
  188. }
  189. $this->theme_list = array_values($this->theme_list);
  190. // Create associative array of themes
  191. foreach ( $this->theme_list as $i => &$theme )
  192. $this->named_theme_list[ $theme['theme_id'] ] =& $this->theme_list[$i];
  193. $this->default_theme = ( $_ = getConfig('theme_default') ) ? $_ : $this->theme_list[0]['theme_id'];
  194. // Come up with the default style. If the CSS file specified in default_style exists, we're good, just
  195. // use that. Otherwise, use the first stylesheet that comes to mind.
  196. $df_data =& $this->named_theme_list[ $this->default_theme ];
  197. $this->default_style = ( in_array($df_data['default_style'], $df_data['css']) ) ? $df_data['default_style'] : $df_data['css'][0];
  198. }
  199. /**
  200. * Systematically deletes themes from available list if they're blocked by theme security settings. Called when session->start() finishes.
  201. */
  202. function process_theme_acls()
  203. {
  204. global $db, $session, $paths, $template, $plugins; // Common objects
  205. global $lang;
  206. // generate the fading button - needs to be done after sessions are started
  207. $admintitle = ( $session->user_level >= USER_LEVEL_ADMIN && is_object(@$lang) ) ? ' title="' . $lang->get('sidebar_btn_enanopowered_admin_tip') . '"' : '';
  208. $this->fading_button = '<div style="background-image: url('.cdnPath.'/images/about-powered-enano-hover.png); background-repeat: no-repeat; width: 88px; height: 31px; margin: 0 auto 5px auto;">
  209. <a style="background-image: none; padding-right: 0;" href="http://enanocms.org/" onclick="window.open(this.href); return false;"' . $admintitle . '><img style="border-width: 0;" alt=" " src="'.cdnPath.'/images/about-powered-enano.png" onmouseover="domOpacity(this, 100, 0, 500);" onmouseout="domOpacity(this, 0, 100, 500);" /></a>
  210. </div>';
  211. // For each theme, check ACLs and delete from RAM if not authorized
  212. foreach ( $this->theme_list as $i => $theme )
  213. {
  214. if ( !@$theme['group_list'] )
  215. continue;
  216. if ( $theme['theme_id'] === getConfig('theme_default') )
  217. continue;
  218. switch ( $theme['group_policy'] )
  219. {
  220. case 'allow_all':
  221. // Unconditionally allowed
  222. continue;
  223. break;
  224. case 'whitelist':
  225. // If we're not on the list, off to the left please
  226. $list = enano_json_decode($theme['group_list']);
  227. $allowed = false;
  228. foreach ( $list as $acl )
  229. {
  230. if ( !preg_match('/^(u|g):([0-9]+)$/', $acl, $match) )
  231. // Invalid list entry, silently allow (maybe not a good idea but
  232. // really, these things are checked before they're inserted)
  233. continue 2;
  234. $mode = $match[1];
  235. $id = intval($match[2]);
  236. switch ( $mode )
  237. {
  238. case 'u':
  239. $allowed = ( $id == $session->user_id );
  240. if ( $allowed )
  241. break 2;
  242. break;
  243. case 'g':
  244. $allowed = ( isset($session->groups[$id]) );
  245. if ( $allowed )
  246. break 2;
  247. }
  248. }
  249. if ( !$allowed )
  250. {
  251. unset($this->theme_list[$i]);
  252. }
  253. break;
  254. case 'blacklist':
  255. // If we're ON the list, off to the left please
  256. $list = enano_json_decode($theme['group_list']);
  257. $allowed = true;
  258. foreach ( $list as $acl )
  259. {
  260. if ( !preg_match('/^(u|g):([0-9]+)$/', $acl, $match) )
  261. // Invalid list entry, silently allow (maybe not a good idea but
  262. // really, these things are checked before they're inserted)
  263. continue 2;
  264. $mode = $match[1];
  265. $id = intval($match[2]);
  266. switch ( $mode )
  267. {
  268. case 'u':
  269. $allowed = ( $id != $session->user_id );
  270. if ( !$allowed )
  271. break 2;
  272. break;
  273. case 'g':
  274. $allowed = ( !isset($session->groups[$id]) );
  275. if ( !$allowed )
  276. break 2;
  277. }
  278. }
  279. if ( !$allowed )
  280. {
  281. unset($this->theme_list[$i]);
  282. }
  283. break;
  284. }
  285. }
  286. $this->theme_list = array_values($this->theme_list);
  287. // Rebuild associative theme list
  288. $this->named_theme_list = array();
  289. foreach ( $this->theme_list as $i => &$theme )
  290. $this->named_theme_list[ $theme['theme_id'] ] =& $this->theme_list[$i];
  291. }
  292. /**
  293. * Register a new sidebar block.
  294. * @param string Block title
  295. * @param string Block HTML
  296. * @param bool If true, the class of the block will be the same as the one used for blocks that are a list of links instead of HTML content. This can do some wacky things like make all your <a>s block level.
  297. */
  298. function sidebar_widget($t, $h, $use_normal_section = false)
  299. {
  300. global $db, $session, $paths, $template, $plugins; // Common objects
  301. if ( !$this->theme_loaded )
  302. {
  303. $this->load_theme($session->theme, $session->style);
  304. }
  305. if(!$this->sidebar_widgets)
  306. $this->sidebar_widgets = '';
  307. $tplvars = $this->extract_vars('elements.tpl');
  308. if ( $use_normal_section )
  309. {
  310. $parser = $this->makeParserText($tplvars['sidebar_section']);
  311. }
  312. else
  313. {
  314. $parser = $this->makeParserText($tplvars['sidebar_section_raw']);
  315. }
  316. $parser->assign_vars(Array('TITLE' => '{TITLE}','CONTENT' => $h));
  317. $this->plugin_blocks[$t] = $parser->run();
  318. $this->plugin_blocks_content[$t] = $h;
  319. $this->sidebar_widgets .= $parser->run();
  320. }
  321. function add_header($html)
  322. {
  323. /* debug only **
  324. $bt = debug_backtrace();
  325. $bt = $bt[1];
  326. $this->additional_headers .= "\n <!-- {$bt['file']}:{$bt['line']} -->\n " . $html;
  327. */
  328. $this->additional_headers .= "\n " . $html;
  329. }
  330. function get_css($s = false)
  331. {
  332. global $db, $session, $paths, $template, $plugins; // Common objects
  333. $this->init_vars();
  334. $path = ( $s ) ? 'css/'.$s : 'css/'.$this->style.'.css';
  335. if ( !file_exists(ENANO_ROOT . '/themes/' . $this->theme . '/' . $path) )
  336. {
  337. echo "/* WARNING: Falling back to default file because file $path does not exist */\n";
  338. $path = 'css/' . $this->style_list[0] . '.css';
  339. }
  340. return $this->process_template($path);
  341. }
  342. function load_theme($name = false, $css = false)
  343. {
  344. global $db, $session, $paths, $template, $plugins; // Common objects
  345. $this->theme = ( $name ) ? $name : $session->theme;
  346. $this->style = ( $css ) ? $css : $session->style;
  347. if ( !$this->theme )
  348. {
  349. $this->theme = $this->theme_list[0]['theme_id'];
  350. $this->style = preg_replace('/\.css$/', '', $this->theme_list[0]['default_style']);
  351. }
  352. // Make sure we're allowed to use this theme.
  353. if ( (
  354. // If it was removed, it's probably blocked by an ACL, or it was uninstalled
  355. !isset($this->named_theme_list[$this->theme]) ||
  356. // Check if the theme is disabled
  357. ( isset($this->named_theme_list[$this->theme]) && isset($this->named_theme_list[$this->theme]['enabled']) && $this->named_theme_list[$this->theme]['enabled'] == 0 ) )
  358. // Above all, if it's a system theme, don't inhibit the loading process.
  359. && !in_array($this->theme, $this->system_themes)
  360. )
  361. {
  362. // No, something is preventing it - fall back to site default
  363. $this->theme = $this->default_theme;
  364. // Come up with the default style. If the CSS file specified in default_style exists, we're good, just
  365. // use that. Otherwise, use the first stylesheet that comes to mind.
  366. $df_data =& $this->named_theme_list[ $this->theme ];
  367. $this->style = ( in_array($df_data['default_style'], $df_data['css']) ) ? $df_data['default_style'] : $df_data['css'][0];
  368. }
  369. // The list of styles for the currently selected theme
  370. $this->style_list =& $this->named_theme_list[ $this->theme ]['css'];
  371. $this->theme_loaded = true;
  372. }
  373. /**
  374. * Change the theme we're supposed to display.
  375. * @param string Theme name
  376. * @param string Style name; optional
  377. */
  378. function set_theme($theme = false, $style = false)
  379. {
  380. $this->theme_initted = false;
  381. $this->load_theme($theme, $style);
  382. }
  383. /**
  384. * Change the page we're supposed to generate for
  385. * @param mixed Page ID *or* PageProcessor. If a PageProcessor, pulls permission info and such from that; if not, starts a PageProcessor. YOU SHOULD USE A PageProcessor WHENEVER POSSIBLE! It improves efficiency.
  386. * @param string Namespace; not required if including a PageProcessor.
  387. */
  388. function set_page($page_id_or_pp, $namespace = false)
  389. {
  390. global $paths;
  391. if ( is_object($page_id_or_pp) && get_class($page_id_or_pp) === 'PageProcessor' )
  392. {
  393. $this->page_initted = false;
  394. $page =& $page_id_or_pp;
  395. $this->page = $page;
  396. $this->page_id = $page->page_id;
  397. $this->namespace = $page->namespace;
  398. }
  399. else if ( is_string($page_id_or_pp) )
  400. {
  401. if ( !is_string($namespace) )
  402. return false;
  403. if ( $page_id_or_pp === $this->page_id && $namespace === $this->namespace )
  404. return true;
  405. $this->page_initted = false;
  406. $this->page = false;
  407. $this->page_id = sanitize_page_id($page_id_or_pp);
  408. $this->namespace = $namespace;
  409. }
  410. else
  411. {
  412. return false;
  413. }
  414. $this->assign_vars(array(
  415. 'PAGE_URLNAME' => $paths->get_pathskey($this->page_id, $this->namespace)
  416. ));
  417. return true;
  418. }
  419. /**
  420. * Queue a Javascript file to be loaded with the page instead of on demand.
  421. * @param mixed Javascript file string or array thereof, extensions are optional
  422. * @example
  423. <code>
  424. $template->preload_js(array('jquery', 'jquery-ui'));
  425. $template->preload_js('admin-menu.js');
  426. </code>
  427. * @return null
  428. */
  429. function preload_js($filemixed)
  430. {
  431. if ( is_string($filemixed) )
  432. $files = array($filemixed);
  433. else if ( is_array($filemixed) )
  434. $files = $filemixed;
  435. else
  436. // :-/
  437. return null;
  438. $this->js_preload = array_values(array_merge($this->js_preload, $files));
  439. }
  440. /**
  441. * Queue some HTML to be inserted after the Javascript runtime.
  442. * @param string HTML glob
  443. */
  444. function add_header_js($html)
  445. {
  446. $this->js_append .= "$html\n ";
  447. }
  448. /**
  449. * Global, only-called-once init. Goes to all themes.
  450. */
  451. function init_global_vars()
  452. {
  453. global $db, $session, $paths, $template, $plugins; // Common objects
  454. global $lang;
  455. global $email;
  456. $is_opera = (isset($_SERVER['HTTP_USER_AGENT']) && strstr($_SERVER['HTTP_USER_AGENT'], 'Opera')) ? true : false;
  457. $is_msie = (isset($_SERVER['HTTP_USER_AGENT']) && strstr($_SERVER['HTTP_USER_AGENT'], 'MSIE')) ? true : false;
  458. $this->assign_bool(array(
  459. 'auth_admin' => $session->user_level >= USER_LEVEL_ADMIN ? true : false,
  460. 'user_logged_in' => $session->user_logged_in,
  461. 'opera' => $is_opera,
  462. 'msie' => $is_msie,
  463. 'registration_disabled' => getConfig('account_activation', 'none') === 'disable'
  464. ));
  465. if ( $session->sid_super )
  466. {
  467. $ash = '&amp;auth=' . $session->sid_super;
  468. $asq = "?auth=" . $session->sid_super;
  469. $asa = "&auth=" . $session->sid_super;
  470. $as2 = htmlspecialchars(urlSeparator) . 'auth='.$session->sid_super;
  471. }
  472. else
  473. {
  474. $asq = '';
  475. $asa = '';
  476. $as2 = '';
  477. $ash = '';
  478. }
  479. // Append the Enano version to URLs to break the cache on upgrades
  480. $enano_version = enano_version();
  481. // Set up javascript includes
  482. // these depend heavily on whether we have a CDN to work with or not
  483. if ( getConfig('cdn_path') )
  484. {
  485. // we're on a CDN, point to static includes
  486. // CLI javascript compression script: includes/clientside/jscompress.php
  487. $js_head = '<script type="text/javascript" src="' . cdnPath . '/includes/clientside/static/enano-lib-basic.js?' . $enano_version . '"></script>';
  488. if ( !empty($this->js_preload) )
  489. {
  490. $loadlines = array();
  491. // make unique
  492. foreach ( $this->js_preload as &$script )
  493. {
  494. $script = preg_replace('/\.js$/', '', $script) . '.js';
  495. }
  496. unset($script);
  497. $this->js_preload = array_unique($this->js_preload);
  498. foreach ( $this->js_preload as $script )
  499. {
  500. $js_head .= "\n <script type=\"text/javascript\" src=\"" . cdnPath . "/includes/clientside/static/$script?$enano_version\"></script>";
  501. // special case for l10n: also load strings
  502. if ( $script == 'l10n.js' )
  503. {
  504. global $lang;
  505. $js_head .= "\n <script type=\"text/javascript\" src=\"" . makeUrlNS("Special", "LangExportJSON/$lang->lang_id", "$enano_version") . "\"></script>";
  506. }
  507. $loadlines[] = "loaded_components['$script'] = true;";
  508. }
  509. // tell the system that this stuff is already loaded
  510. $loadlines = implode("\n ", $loadlines);
  511. $js_head .= "\n <script type=\"text/javascript\">
  512. var loaded_components = loaded_components || {};
  513. $loadlines
  514. </script>";
  515. }
  516. $js_foot = <<<JSEOF
  517. <script type="text/javascript">
  518. // This initializes the Javascript runtime when the DOM is ready - not when the page is
  519. // done loading, because enano-lib-basic still has to load some 15 other script files
  520. // check for the init function - this is a KHTML fix
  521. // This doesn't seem to work properly in IE in 1.1.x - there are some problems with
  522. // tinyMCE and l10n.
  523. if ( typeof ( enano_init ) == 'function' && !IE )
  524. {
  525. enano_init();
  526. window.onload = function(e) { };
  527. }
  528. </script>
  529. $this->js_append
  530. JSEOF;
  531. }
  532. else
  533. {
  534. $cdnpath = cdnPath;
  535. $js_head = '';
  536. // point to jsres compressor
  537. $js_head .= <<<JSEOF
  538. <!-- Only load a basic set of functions for now. Let the rest of the API load when the page is finished. -->
  539. <script type="text/javascript" src="$cdnpath/includes/clientside/jsres.php?early&amp;$enano_version"></script>
  540. JSEOF;
  541. $js_foot = '';
  542. if ( !empty($this->js_preload) )
  543. {
  544. foreach ( $this->js_preload as &$script )
  545. {
  546. $script = preg_replace('/\.js$/', '', $script) . '.js';
  547. }
  548. $this->js_preload = array_unique($this->js_preload);
  549. if ( in_array('l10n.js', $this->js_preload) )
  550. {
  551. // special case for l10n: also load strings
  552. global $lang;
  553. $js_foot .= "\n <script type=\"text/javascript\" src=\"" . makeUrlNS("Special", "LangExportJSON/$lang->lang_id", $enano_version, true) . "\"></script>";
  554. }
  555. $scripts = implode(',', $this->js_preload);
  556. $js_foot .= "\n <script type=\"text/javascript\" src=\"" . cdnPath . "/includes/clientside/jsres.php?f=$scripts&amp;$enano_version\"></script>";
  557. }
  558. $js_foot .= <<<JSEOF
  559. <!-- jsres.php is a wrapper script that compresses and caches single JS files to minimize requests -->
  560. <script type="text/javascript" src="$cdnpath/includes/clientside/jsres.php?$enano_version"></script>
  561. <script type="text/javascript">//<![CDATA[
  562. // This initializes the Javascript runtime when the DOM is ready - not when the page is
  563. // done loading, because enano-lib-basic still has to load some 15 other script files
  564. // check for the init function - this is a KHTML fix
  565. // This doesn't seem to work properly in IE in 1.1.x - there are some problems with
  566. // tinyMCE and l10n.
  567. if ( typeof ( enano_init ) == 'function' && !IE )
  568. {
  569. enano_init();
  570. window.onload = function(e) { };
  571. }
  572. //]]></script>
  573. $this->js_append
  574. JSEOF;
  575. }
  576. $this->assign_bool(array(
  577. 'fixed_menus' => false,
  578. 'export' => false,
  579. 'right_sidebar' => true,
  580. 'enable_uploads' => ( getConfig('enable_uploads') == '1' && $session->get_permissions('upload_files') ) ? true : false,
  581. 'stupid_mode' => false,
  582. ));
  583. // Add the e-mail address client code to the header
  584. $this->add_header($email->jscode());
  585. // Assign our main variables
  586. $this->assign_vars(array(
  587. 'SITE_NAME' => htmlspecialchars(getConfig('site_name')),
  588. 'USERNAME' => $session->username,
  589. 'SITE_DESC' => htmlspecialchars(getConfig('site_desc')),
  590. 'SCRIPTPATH' => scriptPath,
  591. 'CONTENTPATH' => contentPath,
  592. 'CDNPATH' => cdnPath,
  593. 'ADMIN_SID_QUES' => $asq,
  594. 'ADMIN_SID_AMP' => $asa,
  595. 'ADMIN_SID_AMP_HTML' => $ash,
  596. 'ADMIN_SID_AUTO' => $as2,
  597. 'ADMIN_SID_RAW' => ( is_string($session->sid_super) ? $session->sid_super : '' ),
  598. 'CSRF_TOKEN' => $session->csrf_token,
  599. 'COPYRIGHT' => RenderMan::parse_internal_links(getConfig('copyright_notice')),
  600. 'REQUEST_URI' => ( defined('ENANO_CLI') ? '' : $_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'] ),
  601. 'SEARCH_ACTION' => makeUrlNS('Special', 'Search'),
  602. 'INPUT_TITLE' => ( urlSeparator == '&' ? '<input type="hidden" name="title" value="' . htmlspecialchars( $paths->get_pathskey($this->page_id, $this->namespace) ) . '" />' : ''),
  603. 'INPUT_AUTH' => ( $session->sid_super ? '<input type="hidden" name="auth" value="' . $session->sid_super . '" />' : ''),
  604. 'MAIN_PAGE' => get_main_page(),
  605. 'UNREAD_PMS' => $session->unread_pms,
  606. 'JS_HEADER' => $js_head,
  607. 'JS_FOOTER' => $js_foot,
  608. 'URL_ABOUT_ENANO' => makeUrlNS('Special', 'About_Enano', '', true),
  609. 'ENANO_VERSION' => enano_version()
  610. ), true);
  611. $tpl_strings = array();
  612. foreach ( $paths->nslist as $ns_id => $ns_prefix )
  613. {
  614. $tpl_strings[ 'NS_' . strtoupper($ns_id) ] = $ns_prefix;
  615. }
  616. $this->assign_vars($tpl_strings, true);
  617. }
  618. /**
  619. * Init theme vars, like sidebar, global JS, that kind of stuff.
  620. */
  621. function init_theme_vars()
  622. {
  623. global $db, $session, $paths, $template, $plugins; // Common objects
  624. global $lang;
  625. // allows conditional testing of the theme ID (a bit crude, came from my NSIS days)
  626. $this->assign_bool(array(
  627. "theme_is_{$this->theme}" => true
  628. ));
  629. $this->elements = $this->extract_vars('elements.tpl');
  630. // Generate the code for the Administration and Edit Sidebar buttons
  631. // Once again, the new template parsing system can be used here
  632. $parser = $this->makeParserText($this->elements['sidebar_button']);
  633. $parser->assign_vars(Array(
  634. 'HREF'=>makeUrlNS('Special', 'Administration'),
  635. 'FLAGS'=>'onclick="if ( !KILL_SWITCH ) { void(ajaxStartAdminLogin()); return false; }"',
  636. 'TEXT'=>$lang->get('sidebar_btn_administration'),
  637. ));
  638. $admin_link = $parser->run();
  639. // We're leaving this in for now, just blanked out, to avoid compatibility issues.
  640. $sidebar_link = '';
  641. $this->assign_vars(array(
  642. 'ADMIN_LINK' => $admin_link,
  643. 'SIDEBAR_LINK' => $sidebar_link,
  644. 'THEME_ID' => $this->theme,
  645. 'STYLE_ID' => $this->style
  646. ));
  647. // Add the site description sidebar block
  648. $this->sidebar_widget($lang->get('sidebar_title_about'), '<p>' . htmlspecialchars(getConfig('site_desc')) . '</p>');
  649. $this->theme_initted = true;
  650. }
  651. /**
  652. * Init page vars, like the toolbar, local JS, etc.
  653. */
  654. function init_page_vars()
  655. {
  656. global $db, $session, $paths, $template, $plugins; // Common objects
  657. global $lang;
  658. if ( !$this->page )
  659. {
  660. $this->page = new PageProcessor($this->page_id, $this->namespace);
  661. }
  662. $conds = $this->page->ns->get_conds();
  663. $this->assign_bool(array(
  664. 'in_admin' => ( ( $this->page_id == 'Administration' && $this->namespace == 'Special' ) || $this->namespace == 'Admin' ),
  665. 'auth_rename' => ( $conds['rename'] )
  666. ));
  667. // Get the "article" button text (depends on namespace)
  668. switch ( $this->namespace )
  669. {
  670. case "Article":
  671. default:
  672. $ns = $lang->get('onpage_lbl_page_article');
  673. break;
  674. case "Admin":
  675. $ns = $lang->get('onpage_lbl_page_admin');
  676. break;
  677. case "System":
  678. $ns = $lang->get('onpage_lbl_page_system');
  679. break;
  680. case "File":
  681. $ns = $lang->get('onpage_lbl_page_file');
  682. break;
  683. case "Help":
  684. $ns = $lang->get('onpage_lbl_page_help');
  685. break;
  686. case "User":
  687. $ns = $lang->get('onpage_lbl_page_user');
  688. break;
  689. case "Special":
  690. $ns = $lang->get('onpage_lbl_page_special');
  691. break;
  692. case "Template":
  693. $ns = $lang->get('onpage_lbl_page_template');
  694. break;
  695. case "Project":
  696. $ns = $lang->get('onpage_lbl_page_project');
  697. break;
  698. case "Category":
  699. $ns = $lang->get('onpage_lbl_page_category');
  700. break;
  701. case "API":
  702. $ns = $lang->get('onpage_lbl_page_external');
  703. break;
  704. }
  705. $this->namespace_string = $ns;
  706. unset($ns);
  707. // compatibility
  708. $local_namespace =& $this->namespace;
  709. $local_page_id =& $this->page_id;
  710. $code = $plugins->setHook('page_type_string_set');
  711. foreach ( $code as $cmd )
  712. {
  713. eval($cmd);
  714. }
  715. $ns =& $this->namespace_string;
  716. //
  717. // PAGE TOOLBAR (on-page controls/actions)
  718. //
  719. $local_page = $paths->get_pathskey($this->page_id, $this->namespace);
  720. $local_cdata = $this->page->ns->get_cdata();
  721. // Initialize the toolbar
  722. $tb = '';
  723. $this->toolbar_menu = '';
  724. // Create "xx page" button
  725. $btn_selected = ( isset($this->elements['toolbar_button_selected'])) ? $this->elements['toolbar_button_selected'] : $this->elements['toolbar_button'];
  726. $parser = $this->makeParserText($btn_selected);
  727. if ( $conds['article'] )
  728. {
  729. $parser->assign_vars(array(
  730. 'FLAGS' => 'onclick="if ( !KILL_SWITCH ) { void(ajaxReset()); return false; }" title="' . $lang->get('onpage_tip_article') . '" accesskey="a"',
  731. 'PARENTFLAGS' => 'id="mdgToolbar_article"',
  732. 'HREF' => makeUrl($local_page, null, true),
  733. 'TEXT' => $this->namespace_string
  734. ));
  735. $tb .= $parser->run();
  736. }
  737. $button = $this->makeParserText($this->elements['toolbar_button']);
  738. // Page toolbar
  739. // Comments button
  740. if ( $conds['comments'] )
  741. {
  742. $cdata = $this->page->ns->get_cdata();
  743. if ( isset($cdata['comments_approved']) )
  744. {
  745. $approval_counts = array(
  746. COMMENT_APPROVED => $cdata['comments_approved'],
  747. COMMENT_UNAPPROVED => $cdata['comments_unapproved'],
  748. COMMENT_SPAM => $cdata['comments_spam']
  749. );
  750. $num_comments = $session->check_acl_scope('mod_comments', $this->namespace) && $this->page->perms->get_permissions('mod_comments')
  751. ? array_sum($approval_counts)
  752. : $approval_counts[COMMENT_APPROVED];
  753. }
  754. else
  755. {
  756. $e = $db->sql_query('SELECT approved FROM '.table_prefix.'comments WHERE page_id=\''.$this->page_id.'\' AND namespace=\''.$this->namespace.'\';');
  757. if ( !$e )
  758. {
  759. $db->_die();
  760. }
  761. $num_comments = $db->numrows();
  762. $approval_counts = array(COMMENT_UNAPPROVED => 0, COMMENT_APPROVED => 0, COMMENT_SPAM => 0);
  763. while ( $r = $db->fetchrow() )
  764. {
  765. $approval_counts[$r['approved']]++;
  766. }
  767. }
  768. $db->free_result();
  769. // $n = ( $session->check_acl_scope('mod_comments', $this->namespace) && $perms->get_permissions('mod_comments') ) ? (string)$num_comments : (string)$na;
  770. if ( $session->check_acl_scope('mod_comments', $this->namespace) && $this->page->perms->get_permissions('mod_comments') && ( $approval_counts[COMMENT_UNAPPROVED] + $approval_counts[COMMENT_SPAM] ) > 0 )
  771. {
  772. $subst = array(
  773. 'num_comments' => $num_comments,
  774. 'num_app' => $approval_counts[COMMENT_APPROVED],
  775. 'num_unapp' => $approval_counts[COMMENT_UNAPPROVED],
  776. 'num_spam' => $approval_counts[COMMENT_SPAM]
  777. );
  778. $btn_text = $lang->get('onpage_btn_discussion_unapp', $subst);
  779. }
  780. else
  781. {
  782. $subst = array(
  783. 'num_comments' => $num_comments
  784. );
  785. $btn_text = $lang->get('onpage_btn_discussion', $subst);
  786. }
  787. $button->assign_vars(array(
  788. 'FLAGS' => 'onclick="if ( !KILL_SWITCH ) { void(ajaxComments()); return false; }" title="' . $lang->get('onpage_tip_comments') . '" accesskey="c"',
  789. 'PARENTFLAGS' => 'id="mdgToolbar_discussion"',
  790. 'HREF' => makeUrl($local_page, 'do=comments', true),
  791. 'TEXT' => $btn_text,
  792. ));
  793. $tb .= $button->run();
  794. }
  795. // Edit button
  796. if( $conds['edit'] )
  797. {
  798. $button->assign_vars(array(
  799. 'FLAGS' => 'onclick="if ( !KILL_SWITCH ) { void(ajaxEditor()); return false; }" title="' . $lang->get('onpage_tip_edit') . '" accesskey="e"',
  800. 'PARENTFLAGS' => 'id="mdgToolbar_edit"',
  801. 'HREF' => makeUrl($local_page, 'do=edit', true),
  802. 'TEXT' => $lang->get('onpage_btn_edit')
  803. ));
  804. $tb .= $button->run();
  805. // View source button
  806. }
  807. else if ( $conds['viewsource'] )
  808. {
  809. $button->assign_vars(array(
  810. 'FLAGS' => 'onclick="if ( !KILL_SWITCH ) { void(ajaxEditor()); return false; }" title="' . $lang->get('onpage_tip_viewsource') . '" accesskey="e"',
  811. 'PARENTFLAGS' => 'id="mdgToolbar_edit"',
  812. 'HREF' => makeUrl($local_page, 'do=viewsource', true),
  813. 'TEXT' => $lang->get('onpage_btn_viewsource')
  814. ));
  815. $tb .= $button->run();
  816. }
  817. // History button
  818. if ( $conds['history'] )
  819. {
  820. $button->assign_vars(array(
  821. 'FLAGS' => 'onclick="if ( !KILL_SWITCH ) { void(ajaxHistory()); return false; }" title="' . $lang->get('onpage_tip_history') . '" accesskey="h"',
  822. 'PARENTFLAGS' => 'id="mdgToolbar_history"',
  823. 'HREF' => makeUrl($local_page, 'do=history', true),
  824. 'TEXT' => $lang->get('onpage_btn_history')
  825. ));
  826. $tb .= $button->run();
  827. }
  828. $menubtn = $this->makeParserText($this->elements['toolbar_menu_button']);
  829. // Additional actions menu
  830. // Rename button
  831. if ( $conds['rename'] )
  832. {
  833. $menubtn->assign_vars(array(
  834. 'FLAGS' => 'onclick="if ( !KILL_SWITCH ) { void(ajaxRename()); return false; }" title="' . $lang->get('onpage_tip_rename') . '" accesskey="r"',
  835. 'HREF' => makeUrl($local_page, 'do=rename', true),
  836. 'TEXT' => $lang->get('onpage_btn_rename'),
  837. ));
  838. $this->toolbar_menu .= $menubtn->run();
  839. }
  840. // Vote-to-delete button
  841. if ( $conds['delvote'] )
  842. {
  843. $menubtn->assign_vars(array(
  844. 'FLAGS' => 'onclick="if ( !KILL_SWITCH ) { void(ajaxDelVote()); return false; }" title="' . $lang->get('onpage_tip_delvote') . '" accesskey="d"',
  845. 'HREF' => makeUrl($local_page, 'do=delvote', true),
  846. 'TEXT' => $lang->get('onpage_btn_votedelete'),
  847. ));
  848. $this->toolbar_menu .= $menubtn->run();
  849. }
  850. // Clear-votes button
  851. if ( $conds['resetvotes'] )
  852. {
  853. $menubtn->assign_vars(array(
  854. 'FLAGS' => 'onclick="if ( !KILL_SWITCH ) { void(ajaxResetDelVotes()); return false; }" title="' . $lang->get('onpage_tip_resetvotes') . '" accesskey="y"',
  855. 'HREF' => makeUrl($local_page, 'do=resetvotes', true),
  856. 'TEXT' => $lang->get('onpage_btn_votedelete_reset'),
  857. ));
  858. $this->toolbar_menu .= $menubtn->run();
  859. }
  860. // Printable page button
  861. if ( $conds['printable'] )
  862. {
  863. $menubtn->assign_vars(array(
  864. 'FLAGS' => 'title="' . $lang->get('onpage_tip_printable') . '"',
  865. 'HREF' => makeUrl($local_page, 'printable=yes', true),
  866. 'TEXT' => $lang->get('onpage_btn_printable'),
  867. ));
  868. $this->toolbar_menu .= $menubtn->run();
  869. }
  870. // Protect button
  871. if ( $conds['protect'] )
  872. {
  873. switch($this->page->ns->cdata['protected'])
  874. {
  875. case PROTECT_FULL: $protect_status = $lang->get('onpage_btn_protect_on'); break;
  876. case PROTECT_SEMI: $protect_status = $lang->get('onpage_btn_protect_semi'); break;
  877. case PROTECT_NONE: $protect_status = $lang->get('onpage_btn_protect_off'); break;
  878. }
  879. $label = $this->makeParserText($this->elements['toolbar_label']);
  880. $label->assign_vars(array('TEXT' => $lang->get('onpage_lbl_protect') . ' ' . "<b><span id=\"tb_ajax_protect_status\">$protect_status</span></b>"));
  881. $t0 = $label->run();
  882. $menubtn->assign_vars(array(
  883. 'FLAGS' => 'accesskey="p" onclick="ajaxProtect(' . $this->page->ns->cdata['protected'] . '); return false;" id="tb_ajax_protect_btn" title="' . $lang->get('onpage_tip_protect') . '"',
  884. 'HREF' => makeUrl($local_page, 'do=protect', true),
  885. 'TEXT' => $lang->get('onpage_btn_protect_change')
  886. ));
  887. $t1 = $menubtn->run();
  888. $this->toolbar_menu .= ' <table border="0" cellspacing="0" cellpadding="0">
  889. <tr>
  890. <td>'.$t0.'</td>
  891. <td>'.$t1.'</td>
  892. </tr>
  893. </table>';
  894. }
  895. // Wiki mode button
  896. if ( $conds['setwikimode'] )
  897. {
  898. // label at start
  899. $label = $this->makeParserText($this->elements['toolbar_label']);
  900. $label->assign_vars(array('TEXT' => $lang->get('onpage_lbl_wikimode')));
  901. $t0 = $label->run();
  902. // on button
  903. $ctmp = '';
  904. if ( $local_cdata['wiki_mode'] == 1 )
  905. {
  906. $ctmp = ' style="text-decoration: underline;"';
  907. }
  908. $menubtn->assign_vars(array(
  909. 'FLAGS' => $ctmp,
  910. 'HREF' => makeUrl($local_page, 'do=setwikimode&level=1', true),
  911. 'TEXT' => $lang->get('onpage_btn_wikimode_on')
  912. ));
  913. $t1 = $menubtn->run();
  914. // off button
  915. $ctmp = '';
  916. if ( $local_cdata['wiki_mode'] == 0 )
  917. {
  918. $ctmp=' style="text-decoration: underline;"';
  919. }
  920. $menubtn->assign_vars(array(
  921. 'FLAGS' => $ctmp,
  922. 'HREF' => makeUrl($local_page, 'do=setwikimode&level=0', true),
  923. 'TEXT' => $lang->get('onpage_btn_wikimode_off')
  924. ));
  925. $t2 = $menubtn->run();
  926. // global button
  927. $ctmp = '';
  928. if ( $local_cdata['wiki_mode'] == 2 )
  929. {
  930. $ctmp=' style="text-decoration: underline;"';
  931. }
  932. $menubtn->assign_vars(array(
  933. 'FLAGS' => $ctmp,
  934. 'HREF' => makeUrl($local_page, 'do=setwikimode&level=2', true),
  935. 'TEXT' => $lang->get('onpage_btn_wikimode_global')
  936. ));
  937. $t3 = $menubtn->run();
  938. // Tack it onto the list of buttons that are already there...
  939. $this->toolbar_menu .= ' <table border="0" cellspacing="0" cellpadding="0">
  940. <tr>
  941. <td>'.$t0.'</td>
  942. <td>'.$t1.'</td>
  943. <td>'.$t2.'</td>
  944. <td>'.$t3.'</td>
  945. </tr>
  946. </table>';
  947. }
  948. // Clear logs button
  949. if ( $conds['clearlogs'] )
  950. {
  951. $menubtn->assign_vars(array(
  952. 'FLAGS' => 'onclick="if ( !KILL_SWITCH ) { void(ajaxClearLogs()); return false; }" title="' . $lang->get('onpage_tip_flushlogs') . '" accesskey="l"',
  953. 'HREF' => makeUrl($local_page, 'do=flushlogs', true),
  954. 'TEXT' => $lang->get('onpage_btn_clearlogs'),
  955. ));
  956. $this->toolbar_menu .= $menubtn->run();
  957. }
  958. // Delete page button
  959. if ( $conds['delete'] )
  960. {
  961. $s = $lang->get('onpage_btn_deletepage');
  962. if ( $this->page->ns->cdata['delvotes'] == 1 )
  963. {
  964. $subst = array(
  965. 'num_votes' => $this->page->ns->cdata['delvotes'],
  966. 'plural' => ''
  967. );
  968. $s .= $lang->get('onpage_btn_deletepage_votes', $subst);
  969. }
  970. else if ( $this->page->ns->cdata['delvotes'] > 1 )
  971. {
  972. $subst = array(
  973. 'num_votes' => $this->page->ns->cdata['delvotes'],
  974. 'plural' => $lang->get('meta_plural')
  975. );
  976. $s .= $lang->get('onpage_btn_deletepage_votes', $subst);
  977. }
  978. $menubtn->assign_vars(array(
  979. 'FLAGS' => 'onclick="if ( !KILL_SWITCH ) { void(ajaxDeletePage()); return false; }" title="' . $lang->get('onpage_tip_deletepage') . '" accesskey="k"',
  980. 'HREF' => makeUrl($local_page, 'do=deletepage', true),
  981. 'TEXT' => $s,
  982. ));
  983. $this->toolbar_menu .= $menubtn->run();
  984. }
  985. // Password-protect button
  986. if ( $conds['password'] )
  987. {
  988. // label at start
  989. $label = $this->makeParserText($this->elements['toolbar_label']);
  990. $label->assign_vars(array('TEXT' => $lang->get('onpage_lbl_password')));
  991. $t0 = $label->run();
  992. $menubtn->assign_vars(array(
  993. 'FLAGS' => 'onclick="if ( !KILL_SWITCH ) { void(ajaxSetPassword()); return false; }" title="' . $lang->get('onpage_tip_password') . '"',
  994. 'HREF' => '#',
  995. 'TEXT' => $lang->get('onpage_btn_password_set'),
  996. ));
  997. $t = $menubtn->run();
  998. $this->toolbar_menu .= '<table border="0" cellspacing="0" cellpadding="0"><tr><td>'.$t0.'</td><td><input type="password" id="mdgPassSetField" size="10" /></td><td>'.$t.'</td></tr></table>';
  999. }
  1000. // Manage ACLs button
  1001. if ( $conds['acledit'] )
  1002. {
  1003. $menubtn->assign_vars(array(
  1004. 'FLAGS' => 'onclick="if ( !KILL_SWITCH ) { var s = ajaxOpenACLManager(); console.debug(s); return false; }" title="' . $lang->get('onpage_tip_aclmanager') . '" accesskey="m"',
  1005. 'HREF' => makeUrl($local_page, 'do=aclmanager', true),
  1006. 'TEXT' => $lang->get('onpage_btn_acl'),
  1007. ));
  1008. $this->toolbar_menu .= $menubtn->run();
  1009. }
  1010. // Administer page button
  1011. if ( $conds['adminpage'] )
  1012. {
  1013. $menubtn->assign_vars(array(
  1014. 'FLAGS' => 'onclick="if ( !KILL_SWITCH ) { void(ajaxAdminPage()); return false; }" title="' . $lang->get('onpage_tip_adminoptions') . '" accesskey="g"',
  1015. 'HREF' => makeUrlNS('Special', 'Administration', 'module='.$paths->nslist['Admin'].'PageManager', true),
  1016. 'TEXT' => $lang->get('onpage_btn_admin'),
  1017. ));
  1018. $this->toolbar_menu .= $menubtn->run();
  1019. }
  1020. if ( strlen($this->toolbar_menu) > 0 )
  1021. {
  1022. $button->assign_vars(array(
  1023. 'FLAGS' => 'id="mdgToolbar_moreoptions" onclick="if ( !KILL_SWITCH ) { return false; }" title="' . $lang->get('onpage_tip_moreoptions') . '"',
  1024. 'PARENTFLAGS' => '',
  1025. 'HREF' => makeUrl($local_page, 'do=moreoptions', true),
  1026. 'TEXT' => $lang->get('onpage_btn_moreoptions')
  1027. ));
  1028. $tb .= $button->run();
  1029. }
  1030. // Generate the code for the Log in, Log out, Change theme, Administration, and Edit Sidebar buttons
  1031. // Once again, the new template parsing system can be used here
  1032. $parser = $this->makeParserText($this->elements['sidebar_button']);
  1033. $parser->assign_vars(Array(
  1034. 'HREF'=>makeUrlNS('Special', "Logout/{$session->csrf_token}/{$local_page}"),
  1035. 'FLAGS'=>'onclick="if ( !KILL_SWITCH ) { mb_logout(); return false; }"',
  1036. 'TEXT'=>$lang->get('sidebar_btn_logout'),
  1037. ));
  1038. $logout_link = $parser->run();
  1039. $parser->assign_vars(Array(
  1040. 'HREF'=>makeUrlNS('Special', 'Login/' . $local_page),
  1041. 'FLAGS'=>'onclick="if ( !KILL_SWITCH ) { ajaxStartLogin(); return false; }"' . ( $local_page_id == 'Login' && $local_namespace == 'Special' ? ' class="currentpage"' : '' ),
  1042. 'TEXT'=>$lang->get('sidebar_btn_login'),
  1043. ));
  1044. $login_link = $parser->run();
  1045. $parser->assign_vars(Array(
  1046. 'HREF'=>makeUrlNS('Special', 'ChangeStyle/'.$local_page),
  1047. 'FLAGS'=>'onclick="if ( !KILL_SWITCH ) { ajaxChangeStyle(); return false; }"' . ( $local_page_id == 'ChangeStyle' && $local_namespace == 'Special' ? ' class="currentpage"' : '' ),
  1048. 'TEXT'=>$lang->get('sidebar_btn_changestyle'),
  1049. ));
  1050. $theme_link = $parser->run();
  1051. // Run hooks
  1052. $code = $plugins->setHook('tpl_compile_toolbar');
  1053. foreach ( $code as $cmd )
  1054. {
  1055. eval($cmd);
  1056. }
  1057. //
  1058. // ASSIGN VARIABLES
  1059. //
  1060. $this->assign_vars(array(
  1061. 'PAGE_NAME' => htmlspecialchars($this->page->ns->cdata['name']),
  1062. 'PAGE_URLNAME' => $paths->nslist[$this->namespace] . sanitize_page_id($this->page_id),
  1063. 'TOOLBAR' => $tb,
  1064. 'TOOLBAR_EXTRAS' => $this->toolbar_menu,
  1065. 'STYLE_LINK' => makeUrlNS('Special', 'CSS', null, true), //contentPath.$paths->nslist['Special'].'CSS' . $p,
  1066. 'LOGIN_LINK' => $login_link,
  1067. 'LOGOUT_LINK' => $logout_link,
  1068. 'THEME_LINK' => $theme_link
  1069. ), true);
  1070. $this->page_initted = true;
  1071. }
  1072. /**
  1073. * Generates and assigns the Javascript system variables
  1074. */
  1075. function generate_js_header()
  1076. {
  1077. global $db, $session, $paths, $template, $plugins; // Common objects
  1078. global $lang;
  1079. $SID = ($session->sid_super) ? $session->sid_super : '';
  1080. $local_page = $paths->get_pathskey($this->page_id, $this->namespace);
  1081. $local_fullpage = $paths->get_pathskey($this->page_id, $this->namespace) . substr($paths->fullpage, strlen($paths->page));
  1082. $urlname_clean = str_replace('\'', '\\\'', str_replace('\\', '\\\\', dirtify_page_id($local_fullpage)));
  1083. $urlname_clean = strtr( $urlname_clean, array( '<' => '&lt;', '>' => '&gt;' ) );
  1084. $urlname_jssafe = sanitize_page_id($local_fullpage);
  1085. $physical_urlname_jssafe = sanitize_page_id($paths->fullpage);
  1086. $protected = is_object($this->page) ? $this->page->ns->cdata['really_protected'] : false;
  1087. // Generate the dynamic javascript vars
  1088. // Sorry. I know. This block is a mess.
  1089. $js_dynamic = ' <script type="text/javascript">// <![CDATA[
  1090. // This section defines some basic and very important variables that are used later in the static Javascript library.
  1091. // SKIN DEVELOPERS: The template variable for this code block is {JS_DYNAMIC_VARS}. This MUST be inserted BEFORE the tag that links to the main Javascript lib.
  1092. var title = \''. $urlname_jssafe .'\';
  1093. var physical_title = \'' . $physical_urlname_jssafe . '\';
  1094. var on_main_page = ' . ( $local_page == get_main_page() ? 'true' : 'false' ) . ';
  1095. var main_page_members = \'' . addslashes(get_main_page(true)) . '\';
  1096. var page_exists = '. ( ( is_object($this->page) ? $this->page->ns->exists() : true ) ? 'true' : 'false' ) .';
  1097. var scriptPath = \'' . addslashes(scriptPath) . '\';
  1098. var contentPath = \'' . addslashes(contentPath) . '\';
  1099. var cdnPath = \'' . addslashes(cdnPath) . '\';
  1100. var ENANO_SID = \'' . $SID . '\';
  1101. var user_level = ' . $session->user_level . ';
  1102. var auth_level = ' . $session->auth_level . ';
  1103. var USER_LEVEL_GUEST = ' . USER_LEVEL_GUEST . ';
  1104. var USER_LEVEL_MEMBER = ' . USER_LEVEL_MEMBER . ';
  1105. var USER_LEVEL_CHPREF = ' . USER_LEVEL_CHPREF . ';
  1106. var USER_LEVEL_MOD = ' . USER_LEVEL_MOD . ';
  1107. var USER_LEVEL_ADMIN = ' . USER_LEVEL_ADMIN . ';
  1108. var disable_redirect = ' . ( isset($_GET['redirect']) && $_GET['redirect'] == 'no' ? 'true' : 'false' ) . ';
  1109. var pref_disable_js_fx = ' . ( @$session->user_extra['disable_js_fx'] == 1 ? 'true' : 'false' ) . ';
  1110. var csrf_token = "' . $session->csrf_token . '";
  1111. var prot = ' . ( ($protected) ? 'true' : 'false' ) .';
  1112. var ENANO_SPECIAL_CREATEPAGE = \''. makeUrl($paths->nslist['Special'].'CreatePage') .'\';
  1113. var ENANO_CREATEPAGE_PARAMS = \'_do=&pagename='. $this->page_id .'&namespace=' . $this->namespace . '\';
  1114. var ENANO_SPECIAL_CHANGESTYLE = \''. makeUrlNS('Special', 'ChangeStyle') .'\';
  1115. var namespace_list = [];
  1116. var msg_loading_component = \'' . addslashes($lang->get('ajax_msg_loading_component')) . '\';
  1117. var AES_BITS = '.AES_BITS.';
  1118. var AES_BLOCKSIZE = '.AES_BLOCKSIZE.';
  1119. var pagepass = \''. ( ( isset($_REQUEST['pagepass']) ) ? sha1($_REQUEST['pagepass']) : '' ) .'\';
  1120. var ENANO_LANG_ID = ' . $lang->lang_id . ';
  1121. var ENANO_PAGE_TYPE = "' . addslashes($this->namespace_string) . '";
  1122. var enano_version = "' . enano_version() . '";';
  1123. foreach ( $paths->nslist as $k => $c )
  1124. {
  1125. $js_dynamic .= "namespace_list['{$k}'] = '" . addslashes($c) . "';";
  1126. }
  1127. $js_dynamic .= "\n //]]>\n </script>";
  1128. $this->assign_vars(array(
  1129. 'JS_DYNAMIC_VARS' => $js_dynamic,
  1130. 'REPORT_URI' => makeUrl($local_fullpage, 'do=sql_report', true)
  1131. ), true);
  1132. }
  1133. /**
  1134. * Fetches, parses, and assigns the sidebar.
  1135. */
  1136. function assign_sidebar()
  1137. {
  1138. //
  1139. // COMPILE THE SIDEBAR
  1140. //
  1141. // This is done after the big assign_vars() so that sidebar code has access to the newly assigned variables
  1142. list($this->tpl_strings['SIDEBAR_LEFT'], $this->tpl_strings['SIDEBAR_RIGHT'], $min) = $this->fetch_sidebar();
  1143. $this->tpl_bool['sidebar_left'] = ( $this->tpl_strings['SIDEBAR_LEFT'] != $min) ? true : false;
  1144. $this->tpl_bool['sidebar_right'] = ( $this->tpl_strings['SIDEBAR_RIGHT'] != $min) ? true : false;
  1145. $this->tpl_bool['right_sidebar'] = $this->tpl_bool['sidebar_right']; // backward compatibility
  1146. }
  1147. /**
  1148. * Initializes all variables related to on-page content. This includes sidebars and what have you.
  1149. * @param object Optional PageProcessor object to use for passing metadata and permissions on. If omitted, uses information from $paths and $session.
  1150. * @param bool If true, re-inits even if already initted with this page_id and namespace
  1151. */
  1152. function init_vars($page = false, $force_init = false)
  1153. {
  1154. global $db, $session, $paths, $template, $plugins; // Common objects
  1155. global $lang;
  1156. $need_shared_init = ( !$this->theme_initted || !$this->page_initted );
  1157. if ( $need_shared_init )
  1158. {
  1159. if ( !$this->theme || !$this->style )
  1160. {
  1161. $this->load_theme();
  1162. }
  1163. $code = $plugins->setHook('compile_template', true);
  1164. foreach ( $code as $cmd )
  1165. {
  1166. eval($cmd);
  1167. }
  1168. }
  1169. if ( !$this->theme_loaded )
  1170. $this->load_theme();
  1171. require(ENANO_ROOT . "/themes/{$this->theme}/theme.cfg");
  1172. if ( !$this->page_id || !$this->namespace )
  1173. {
  1174. $this->page_id = $paths->page_id;
  1175. $this->namespace = $paths->namespace;
  1176. }
  1177. profiler_log('template: prepped for var set (loaded theme, ran compile_template hook)');
  1178. $this->init_global_vars();
  1179. profiler_log('template: global vars set');
  1180. if ( !$this->theme_initted )
  1181. $this->init_theme_vars();
  1182. profiler_log('template: theme vars set');
  1183. if ( !$this->page_initted && !empty($this->namespace) )
  1184. {
  1185. profiler_log('template: page vars set');
  1186. $this->init_page_vars();
  1187. }
  1188. else
  1189. {
  1190. profiler_message('template: skipped setting page vars');
  1191. }
  1192. // Perform shared init (combine javascript, etc.)
  1193. if ( $need_shared_init )
  1194. {
  1195. $this->generate_js_header();
  1196. $this->assign_sidebar();
  1197. profiler_log('template: assigned sidebar and JS');
  1198. }
  1199. // and finally one string value that needs to be symlinked...
  1200. if ( !isset($this->tpl_strings['ADDITIONAL_HEADERS']) )
  1201. {
  1202. $this->tpl_strings['ADDITIONAL_HEADERS'] =& $this->additional_headers;
  1203. }
  1204. // done!
  1205. $code = $plugins->setHook('template_var_init_end');
  1206. foreach ( $code as $cmd )
  1207. {
  1208. eval($cmd);
  1209. }
  1210. }
  1211. function header($simple = false)
  1212. {
  1213. global $db, $session, $paths, $template, $plugins; // Common objects
  1214. global $lang;
  1215. define('ENANO_HEADERS_SENT', true);
  1216. echo $this->getHeader($simple);
  1217. }
  1218. function footer($simple = false)
  1219. {
  1220. echo $this->getFooter($simple);
  1221. }
  1222. function getHeader($simple = false)
  1223. {
  1224. global $db, $session, $paths, $template, $plugins; // Common objects
  1225. global $lang;
  1226. if ( !$this->theme_loaded )
  1227. {
  1228. $this->load_theme($session->theme, $session->style);
  1229. }
  1230. if ( !$this->page_initted || !$this->theme_initted )
  1231. $this->init_vars();
  1232. // I feel awful doing this.
  1233. if ( preg_match('/^W3C_Validator/', @$_SERVER['HTTP_USER_AGENT']) )
  1234. {
  1235. header('Content-type: application/xhtml+xml');
  1236. }
  1237. $header = '';
  1238. if ( !$this->no_headers )
  1239. {
  1240. $header = ( $simple ) ?
  1241. $this->process_template('simple-header.tpl') :
  1242. $this->process_template('header.tpl');
  1243. }
  1244. if ( !$simple && $session->user_logged_in && $session->unread_pms > 0 )
  1245. {
  1246. $header .= $this->notify_unread_pms();
  1247. }
  1248. if ( !$simple && $session->sw_timed_out )
  1249. {
  1250. $login_link = makeUrlNS('Special', 'Login/' . $paths->fullpage, 'level=' . $session->user_level, true);
  1251. $header .= '<div class="usermessage">';
  1252. $header .= $lang->get('user_msg_elev_timed_out', array( 'login_link' => $login_link ));
  1253. $header .= '</div>';
  1254. }
  1255. if ( $this->site_disabled && $session->user_level >= USER_LEVEL_ADMIN && ( $paths->page != $paths->nslist['Special'] . 'Administration' ) )
  1256. {
  1257. $admin_link = makeUrlNS('Special', 'Administration', 'module=' . $paths->nslist['Admin'] . 'GeneralConfig', true);
  1258. $header .= '<div class="usermessage"><b>' . $lang->get('page_sitedisabled_admin_msg_title') . '</b><br />
  1259. ' . $lang->get('page_sitedisabled_admin_msg_body', array('admin_link' => $admin_link)) . '
  1260. </div>';
  1261. }
  1262. return $header;
  1263. }
  1264. function getFooter($simple = false)
  1265. {
  1266. global $db, $session, $paths, $template, $plugins; // Common objects
  1267. global $lang;
  1268. if ( !$this->no_headers )
  1269. {
  1270. global $_starttime;
  1271. if(isset($_GET['sqldbg']) && $session->get_permissions('mod_misc'))
  1272. {
  1273. echo '<h3>' . $lang->get('page_heading_sql_list') . '</h3><pre style="margin-left: 1em">';
  1274. echo htmlspecialchars($db->sql_backtrace());
  1275. echo '</pre>';
  1276. }
  1277. $t = ( $simple ) ? $this->process_template('simple-footer.tpl') : $this->process_template('footer.tpl');
  1278. $f = microtime_float();
  1279. $f = $f - $_starttime;
  1280. $f = sprintf("%.02f", $f);
  1281. $t_loc = $lang->get('page_msg_stats_gentime_short', array('time' => $f));
  1282. $t_loc_long = $lang->get('page_msg_stats_gentime_long', array('time' => $f));

Large files files are truncated, but you can click here to view the full file